示例图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue UI Framework with External Dark Mode</title>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-plus/theme-chalk/dark/css-vars.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div id="app">
<header class="app-header">
<h1>
<i class="fab fa-vuejs"></i> Vue UI Framework
<span class="subtitle">FastAdmin外部深色模式控制示例</span>
</h1>
<div class="controls">
<!-- Vue控制的深色模式切换按钮 -->
<el-button @click="toggleDarkMode" type="primary" class="toggle-btn">
<i :class="darkMode ? 'fas fa-sun' : 'fas fa-moon'"></i>
{{ darkMode ? '切换到浅色模式' : '切换到深色模式' }}
</el-button>
<!-- 状态指示器 -->
<div class="mode-indicator">
<span class="tag" :class="darkMode ? 'dark-tag' : 'light-tag'">
<i :class="darkMode ? 'fas fa-moon' : 'fas fa-sun'"></i>
{{ darkMode ? '深色模式' : '浅色模式' }}
</span>
</div>
</div>
</header>
<main class="content-container">
<div class="demo-section">
<h2><i class="fas fa-user-circle"></i> 客户信息面板</h2>
<div class="card">
<div class="demo-collapse">
<el-collapse v-model="activeNames" accordion>
<el-collapse-item title="基本信息" name="1">
<div class="info-item">
<span class="label">姓名:</span>
<span class="value">小和</span>
</div>
<div class="info-item">
<span class="label">电话:</span>
<span class="value">199-8329-7340</span>
</div>
<div class="info-item">
<span class="label">邮箱:</span>
<span class="value">xiaohe@he4966.cn</span>
</div>
<div class="info-item">
<span class="label">地址:</span>
<span class="value">无锡滨湖区楝泽路9-3</span>
</div>
</el-collapse-item>
<el-collapse-item title="账户信息" name="2">
<div class="info-item">
<span class="label">QQ</span>
<span class="value">496631085</span>
</div>
<div class="info-item">
<span class="label">账户状态:</span>
<el-tag type="success">活跃</el-tag>
</div>
<div class="info-item">
<span class="label">创建日期:</span>
<span class="value">2008-06-06</span>
</div>
<div class="info-item">
<span class="label">最后登录:</span>
<span class="value">2023-10-28 14:30:22</span>
</div>
</el-collapse-item>
<el-collapse-item title="订单历史" name="3">
<el-table :data="orders" style="width: 100%">
<el-table-column prop="id" label="订单号" width="180"></el-table-column>
<el-table-column prop="date" label="日期" width="180"></el-table-column>
<el-table-column prop="product" label="产品"></el-table-column>
<el-table-column prop="amount" label="金额" align="right">
<template #default="scope">
¥{{ scope.row.amount.toFixed(2) }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态">
<template #default="scope">
<el-tag :type="scope.row.status === '已完成' ? 'success' : 'warning'">
{{ scope.row.status }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-collapse-item>
</el-collapse>
</div>
</div>
</div>
<div class="stats-section">
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon">
<i class="fas fa-users"></i>
</div>
<div class="stat-content">
<div class="stat-value">1,254</div>
<div class="stat-label">总客户数</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="fas fa-shopping-cart"></i>
</div>
<div class="stat-content">
<div class="stat-value">328</div>
<div class="stat-label">今日订单</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="fas fa-chart-line"></i>
</div>
<div class="stat-content">
<div class="stat-value">¥86,540</div>
<div class="stat-label">今日销售额</div>
</div>
</div>
<div class="stat-card">
<div class="stat-icon">
<i class="fas fa-comments"></i>
</div>
<div class="stat-content">
<div class="stat-value">42</div>
<div class="stat-label">新消息</div>
</div>
</div>
</div>
</div>
</main>
<footer class="app-footer">
<p>© 2023 Vue UI 管理系统 | 外部深色模式控制演示</p>
<p>当前模式: <strong>{{ darkMode ? '深色模式' : '浅色模式' }}</strong></p>
</footer>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/element-plus"></script>
<script>
const app = Vue.createApp({
data() {
return {
activeNames: ['1'],
darkMode: false,
orders: [
{ id: 'ORD-202310-001', date: '2023-10-25', product: '高端智能手机', amount: 5999.00, status: '已完成' },
{ id: 'ORD-202310-002', date: '2023-10-26', product: '无线蓝牙耳机', amount: 899.00, status: '已完成' },
{ id: 'ORD-202310-003', date: '2023-10-27', product: '智能手表', amount: 1299.00, status: '处理中' },
{ id: 'ORD-202310-004', date: '2023-10-28', product: '平板电脑', amount: 3299.00, status: '已发货' },
{ id: 'ORD-202310-005', date: '2023-10-28', product: '笔记本电脑', amount: 7899.00, status: '待付款' }
]
}
},
methods: {
toggleDarkMode() {
this.darkMode = !this.darkMode;
this.updateDarkMode();
this.updateExternalButton();
},
updateDarkMode() {
if (this.darkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
},
updateExternalButton() {
const button = document.querySelector('.theme-toggle');
if (button) {
button.setAttribute('data-mode', this.darkMode ? 'light' : 'dark');
button.title = this.darkMode ? '切换浅色模式' : '切换深色模式';
button.innerHTML = this.darkMode
? '<i class="fas fa-sun"></i> 外部切换浅色模式'
: '<i class="fas fa-moon"></i> 外部切换深色模式';
}
}
},
mounted() {
// 初始化模式
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
this.darkMode = true;
}
this.updateDarkMode();
this.updateExternalButton();
// 监听外部按钮点击事件
const externalButton = top.document.querySelector('.theme-toggle');
if (externalButton) {
console.log('外部按钮点击事件已监听到 he4966');
externalButton.addEventListener('click', () => {
this.darkMode = externalButton.getAttribute('data-mode') === 'dark';
this.updateDarkMode();
this.updateExternalButton();
});
}
}
});
app.use(ElementPlus);
app.mount('#app');
</script>
<style>
:root {
--primary-color: #409EFF;
--success-color: #67C23A;
--warning-color: #E6A23C;
--danger-color: #F56C6C;
--info-color: #909399;
--bg-color: #f5f7fa;
--text-color: #303133;
--border-color: #dcdfe6;
--card-bg: #ffffff;
--header-bg: #ffffff;
--footer-bg: #f2f6fc;
--transition: all 0.3s ease;
}
.dark {
--primary-color: #66b1ff;
--success-color: #85ce61;
--warning-color: #ebb563;
--danger-color: #f78989;
--info-color: #a6a9ad;
--bg-color: #121212;
--text-color: #e0e0e0;
--border-color: #434343;
--card-bg: #1e1e1e;
--header-bg: #1a1a1a;
--footer-bg: #1a1a1a;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
transition: var(--transition);
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
line-height: 1.6;
padding: 20px;
transition: var(--transition);
}
.external-controls {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
}
.theme-toggle {
background: var(--primary-color);
color: white;
border: none;
padding: 10px 15px;
border-radius: 4px;
cursor: pointer;
font-weight: 500;
display: flex;
align-items: center;
gap: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.theme-toggle:hover {
opacity: 0.9;
transform: translateY(-2px);
}
#app {
max-width: 1200px;
margin: 60px auto 20px;
display: flex;
flex-direction: column;
gap: 24px;
}
.app-header {
background: var(--header-bg);
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.app-header h1 {
font-size: 24px;
display: flex;
align-items: center;
gap: 12px;
color: var(--primary-color);
}
.app-header .subtitle {
font-size: 16px;
color: var(--info-color);
font-weight: normal;
}
.controls {
display: flex;
align-items: center;
gap: 16px;
}
.toggle-btn {
display: flex;
align-items: center;
gap: 8px;
}
.mode-indicator .tag {
padding: 6px 12px;
border-radius: 20px;
font-size: 14px;
font-weight: 500;
}
.light-tag {
background: #ecf5ff;
color: var(--primary-color);
}
.dark-tag {
background: rgba(102, 177, 255, 0.1);
color: var(--primary-color);
}
.content-container {
display: flex;
flex-direction: column;
gap: 24px;
}
.demo-section, .stats-section {
background: var(--card-bg);
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.demo-section h2 {
padding: 16px 20px;
background: rgba(64, 158, 255, 0.1);
color: var(--primary-color);
font-size: 18px;
display: flex;
align-items: center;
gap: 10px;
}
.card {
padding: 20px;
}
.info-item {
display: flex;
padding: 10px 0;
border-bottom: 1px solid var(--border-color);
}
.info-item:last-child {
border-bottom: none;
}
.label {
font-weight: 600;
width: 120px;
color: var(--info-color);
}
.value {
flex: 1;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 20px;
padding: 20px;
}
.stat-card {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
display: flex;
align-items: center;
gap: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.stat-icon {
width: 60px;
height: 60px;
background: rgba(64, 158, 255, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
color: var(--primary-color);
}
.stat-value {
font-size: 24px;
font-weight: 700;
margin-bottom: 4px;
}
.stat-label {
color: var(--info-color);
font-size: 14px;
}
.app-footer {
text-align: center;
padding: 20px;
color: var(--info-color);
font-size: 14px;
background: var(--footer-bg);
border-radius: 8px;
margin-top: 20px;
}
@media (max-width: 768px) {
.app-header {
flex-direction: column;
align-items: flex-start;
}
.controls {
width: 100%;
justify-content: space-between;
}
}
</style>
</body>
</html>
精简优化后的逻辑代码(推荐):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fastadmin 嵌入element-plus 的黑暗主题 demo</title>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<link rel="stylesheet" href="https://unpkg.com/element-plus/theme-chalk/dark/css-vars.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
<div id="app">
<div class="demo-collapse">
<el-collapse v-model="activeNames" @change="handleChange">
<el-collapse-item title="客户信息" name="1">
<div>
面板组内容1
</div>
</el-collapse-item>
<el-collapse-item title="Feedback" name="2">
<div>
面板组标题1
</div>
<div>
视觉反馈:通过更新或重新排列来反映当前状态
页面的元素。
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/element-plus"></script>
<script>
const app = Vue.createApp({
data() {
return {
darkMode: false,
}
},
methods: {
// toggleDarkMode() {
// this.darkMode = !this.darkMode;
// this.updateDarkMode();
// this.updateExternalButton();
// },
updateDarkMode() {
// 更新页面主题颜色模
alert(this.darkMode);
if (this.darkMode) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
},
updateExternalButton() {
// const button = top.document.querySelector('.theme-toggle');
// if (button) {
// button.setAttribute('data-mode', this.darkMode ? 'light' : 'dark');
// button.title = this.darkMode ? '切换浅色模式' : '切换深色模式';
// button.innerHTML = this.darkMode
// ? '<i class="fas fa-sun"></i> 外部切换浅色模式'
// : '<i class="fas fa-moon"></i> 外部切换深色模式';
// }
}
},
mounted() {
// 初始化模式
// 监听外部按钮点击事件
const externalButton = top.document.querySelector('.theme-toggle');
if (externalButton) {
console.log('外部按钮点击事件已监听到 QQ496631085');
// alert('外部按钮点击事件已监听到 QQ496631085'+externalButton.getAttribute('data-mode'));
if (externalButton.getAttribute('data-mode') === 'light') {
this.darkMode = true;
} else {
this.darkMode = false;
}
this.updateDarkMode();
externalButton.addEventListener('click', () => {
this.darkMode = !this.darkMode;
this.updateDarkMode();
this.updateExternalButton();
});
}
}
});
app.use(ElementPlus);
app.mount('#app');
</script>
</body>
</html>