前端初始化

This commit is contained in:
“hsc”
2026-08-21 15:27:51 +08:00
commit ef029340f2
14411 changed files with 2275932 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
<template>
<router-view />
</template>
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

+38
View File
@@ -0,0 +1,38 @@
<script setup>
import { ref } from 'vue'
defineProps({
msg: String
})
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<p>
Welcome:
<a href="https://hx.dcloud.net.cn/" target="_blank">HBuilderX</a>
</p>
<p>
<a href="https://vitejs.dev/guide/features.html" target="_blank">
Vite Documentation
</a>
|
<a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
</p>
<button type="button" @click="count++">count is: {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test hot module replacement.
</p>
</template>
<style scoped>
a {
color: #42b983;
}
</style>
+87
View File
@@ -0,0 +1,87 @@
<template>
<div class="app-header">
<div class="header-left">
<el-icon class="collapse-btn" @click="appStore.toggleSidebar">
<Fold v-if="!appStore.sidebarCollapsed" />
<Expand v-else />
</el-icon>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item v-for="item in breadcrumbs" :key="item.path">
{{ item.meta?.title }}
</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="header-right">
<el-dropdown>
<span class="user-info">
<el-icon><User /></el-icon>
<span>管理员</span>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item divided>退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { Fold, Expand, User } from '@element-plus/icons-vue'
import { useAppStore } from '@/store/app'
const route = useRoute()
const appStore = useAppStore()
const breadcrumbs = computed(() => {
return route.matched.filter(item => item.meta?.title)
})
</script>
<style scoped>
.app-header {
height: 56px;
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
z-index: 10;
}
.header-left {
display: flex;
align-items: center;
gap: 16px;
}
.collapse-btn {
font-size: 20px;
cursor: pointer;
color: #606266;
}
.collapse-btn:hover {
color: #409EFF;
}
.header-right {
display: flex;
align-items: center;
}
.user-info {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
font-size: 14px;
color: #606266;
}
</style>
+29
View File
@@ -0,0 +1,29 @@
<template>
<div class="app-layout">
<Sidebar />
<div class="layout-right">
<Header />
<MainContent />
</div>
</div>
</template>
<script setup>
import Sidebar from './Sidebar.vue'
import Header from './Header.vue'
import MainContent from './MainContent.vue'
</script>
<style scoped>
.app-layout {
display: flex;
height: 100vh;
}
.layout-right {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
</style>
+30
View File
@@ -0,0 +1,30 @@
<template>
<div class="main-content">
<el-scrollbar>
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</el-scrollbar>
</div>
</template>
<style scoped>
.main-content {
flex: 1;
padding: 20px;
background: #f0f2f5;
overflow: auto;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
+115
View File
@@ -0,0 +1,115 @@
<template>
<div class="sidebar" :class="{ 'is-collapsed': appStore.sidebarCollapsed }">
<div class="logo-container">
<img src="@/assets/logo.png" class="logo" />
<span v-show="!appStore.sidebarCollapsed" class="title">设备管理系统</span>
</div>
<el-scrollbar>
<el-menu
:default-active="activeMenu"
:collapse="appStore.sidebarCollapsed"
:unique-opened="true"
router
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
>
<template v-for="route in menuRoutes" :key="route.path">
<!-- 单个菜单项 -->
<el-menu-item
v-if="!route.children || route.children.length === 0"
:index="route.path"
>
<el-icon><component :is="route.meta?.icon" /></el-icon>
<template #title>{{ route.meta?.title }}</template>
</el-menu-item>
<!-- 带子菜单 -->
<el-sub-menu v-else :index="route.path">
<template #title>
<el-icon><component :is="route.meta?.icon" /></el-icon>
<span>{{ route.meta?.title }}</span>
</template>
<el-menu-item
v-for="child in route.children"
:key="child.path"
:index="resolvePath(route.path, child.path)"
>
<el-icon><component :is="child.meta?.icon" /></el-icon>
<template #title>{{ child.meta?.title }}</template>
</el-menu-item>
</el-sub-menu>
</template>
</el-menu>
</el-scrollbar>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useAppStore } from '@/store/app'
const route = useRoute()
const router = useRouter()
const appStore = useAppStore()
const activeMenu = computed(() => route.path)
const menuRoutes = computed(() => {
return router.options.routes
.filter(r => r.component && r.path !== '/:pathMatch(.*)*')
.map(r => ({
...r,
children: (r.children || []).filter(c => !c.path.includes(':'))
}))
})
function resolvePath(basePath, childPath) {
return childPath.startsWith('/') ? childPath : `${basePath}/${childPath}`
}
</script>
<style scoped>
.sidebar {
width: 210px;
height: 100vh;
background-color: #304156;
transition: width 0.3s;
display: flex;
flex-direction: column;
flex-shrink: 0;
}
.sidebar.is-collapsed {
width: 64px;
}
.logo-container {
height: 56px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 10px;
overflow: hidden;
}
.logo {
width: 32px;
height: 32px;
flex-shrink: 0;
}
.title {
color: #fff;
font-size: 16px;
font-weight: 600;
margin-left: 10px;
white-space: nowrap;
}
.el-menu {
border-right: none;
flex: 1;
}
</style>
+19
View File
@@ -0,0 +1,19 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import router from './router'
import App from './App.vue'
const app = createApp(App)
// 注册所有 Element Plus 图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
+331
View File
@@ -0,0 +1,331 @@
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/layout/Layout.vue'
const routes = [
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/Index.vue'),
meta: { title: '工作台', icon: 'Odometer' }
}
]
},
// 资产模块
{
path: '/asset',
component: Layout,
redirect: '/asset/ledger',
meta: { title: '资产', icon: 'Box' },
children: [
{
path: 'ledger',
name: 'EquipmentLedger',
component: () => import('@/views/asset/ledger/Index.vue'),
meta: { title: '设备台账', icon: 'List' }
},
{
path: 'ledger/equipment',
name: 'EquipmentInfo',
component: () => import('@/views/asset/ledger/EquipmentInfo.vue'),
meta: { title: '设备信息', icon: 'Document' }
},
{
path: 'ledger/category',
name: 'CategoryView',
component: () => import('@/views/asset/ledger/CategoryView.vue'),
meta: { title: '分类管理视图', icon: 'FolderOpened' }
},
{
path: 'ledger/lifecycle',
name: 'LifecycleView',
component: () => import('@/views/asset/ledger/LifecycleView.vue'),
meta: { title: '全生命周期视图', icon: 'Clock' }
},
{
path: 'ledger/compliance',
name: 'ComplianceView',
component: () => import('@/views/asset/ledger/ComplianceView.vue'),
meta: { title: '合规管理视图', icon: 'Stamp' }
},
{
path: 'ledger/statistics',
name: 'AssetStatistics',
component: () => import('@/views/asset/ledger/Statistics.vue'),
meta: { title: '分类统计', icon: 'DataAnalysis' }
},
{
path: 'qrcode',
name: 'QRCode',
component: () => import('@/views/asset/qrcode/Index.vue'),
meta: { title: '二维码管理', icon: 'Iphone' }
}
]
},
// 检测模块
{
path: '/inspection',
component: Layout,
redirect: '/inspection/dashboard',
meta: { title: '检测', icon: 'Monitor' },
children: [
{
path: 'dashboard',
name: 'DeviceDashboard',
component: () => import('@/views/inspection/dashboard/Index.vue'),
meta: { title: '设备看板', icon: 'DataBoard' }
},
{
path: 'dashboard/temperature',
name: 'TemperatureBox',
component: () => import('@/views/inspection/dashboard/TemperatureBox.vue'),
meta: { title: '温度箱看板', icon: 'Sunny' }
},
{
path: 'dashboard/charge',
name: 'ChargeCabinet',
component: () => import('@/views/inspection/dashboard/ChargeCabinet.vue'),
meta: { title: '充放电柜看板', icon: 'Battery' }
},
{
path: 'dashboard/auxiliary',
name: 'AuxiliaryDevice',
component: () => import('@/views/inspection/dashboard/AuxiliaryDevice.vue'),
meta: { title: '辅助设备看板', icon: 'SetUp' }
},
{
path: 'dashboard/detail/:id',
name: 'DeviceDetail',
component: () => import('@/views/inspection/dashboard/DeviceDetail.vue'),
meta: { title: '设备详情', icon: 'View' }
},
{
path: 'report',
name: 'StatisticsReport',
component: () => import('@/views/inspection/report/Index.vue'),
meta: { title: '统计报表', icon: 'DataLine' }
},
{
path: 'bigscreen',
name: 'BigScreen',
component: () => import('@/views/inspection/bigscreen/Index.vue'),
meta: { title: '数据大屏', icon: 'FullScreen' }
},
{
path: 'efficiency',
name: 'EfficiencyAnalysis',
component: () => import('@/views/inspection/efficiency/Index.vue'),
meta: { title: '设备效率分析', icon: 'TrendCharts' }
},
{
path: 'patrol',
name: 'PatrolManage',
component: () => import('@/views/inspection/patrol/Index.vue'),
meta: { title: '巡检管理', icon: 'Guide' }
},
{
path: 'patrol/template',
name: 'PatrolTemplate',
component: () => import('@/views/inspection/patrol/Template.vue'),
meta: { title: '巡检模板配置', icon: 'Setting' }
},
{
path: 'patrol/task',
name: 'PatrolTask',
component: () => import('@/views/inspection/patrol/Task.vue'),
meta: { title: '巡检任务执行', icon: 'Checked' }
},
{
path: 'patrol/record',
name: 'PatrolRecord',
component: () => import('@/views/inspection/patrol/Record.vue'),
meta: { title: '巡检记录查询', icon: 'Document' }
},
{
path: 'patrol/auto',
name: 'AutoPatrol',
component: () => import('@/views/inspection/patrol/AutoPatrol.vue'),
meta: { title: '自动巡检', icon: 'MagicStick' }
},
{
path: 'alert-rule',
name: 'AlertRule',
component: () => import('@/views/inspection/alert-rule/Index.vue'),
meta: { title: '告警规则', icon: 'Bell' }
},
{
path: 'alert-message',
name: 'AlertMessage',
component: () => import('@/views/inspection/alert-message/Index.vue'),
meta: { title: '消息告警', icon: 'ChatDotRound' }
}
]
},
// 配置管理 (IOT)
{
path: '/config',
component: Layout,
redirect: '/config/product',
meta: { title: '配置管理', icon: 'Setting' },
children: [
{
path: 'product',
name: 'ProductManage',
component: () => import('@/views/config/product/Index.vue'),
meta: { title: '产品管理', icon: 'Goods' }
},
{
path: 'product/category',
name: 'ProductCategory',
component: () => import('@/views/config/product/Category.vue'),
meta: { title: '产品分类', icon: 'Menu' }
},
{
path: 'device',
name: 'DeviceManage',
component: () => import('@/views/config/device/Index.vue'),
meta: { title: '设备管理', icon: 'Cpu' }
},
{
path: 'gateway',
name: 'GatewayManage',
component: () => import('@/views/config/gateway/Index.vue'),
meta: { title: '网关管理', icon: 'Connection' }
},
{
path: 'protocol/certificate',
name: 'CertificateManage',
component: () => import('@/views/config/protocol/Certificate.vue'),
meta: { title: '证书管理', icon: 'Key' }
},
{
path: 'protocol/message',
name: 'ProtocolManage',
component: () => import('@/views/config/protocol/Message.vue'),
meta: { title: '协议管理', icon: 'Document' }
},
{
path: 'protocol/network',
name: 'NetworkComponent',
component: () => import('@/views/config/protocol/Network.vue'),
meta: { title: '网络组件与协议注册', icon: 'Share' }
},
{
path: 'protocol/template',
name: 'ProtocolTemplate',
component: () => import('@/views/config/protocol/Template.vue'),
meta: { title: '协议模板库', icon: 'Files' }
},
{
path: 'protocol/device-gateway',
name: 'DeviceGateway',
component: () => import('@/views/config/protocol/DeviceGateway.vue'),
meta: { title: '设备网关', icon: 'Switch' }
},
{
path: 'collection/point',
name: 'CollectionPoint',
component: () => import('@/views/config/collection/Point.vue'),
meta: { title: '采集点位配置', icon: 'Location' }
},
{
path: 'collection/strategy',
name: 'CollectionStrategy',
component: () => import('@/views/config/collection/Strategy.vue'),
meta: { title: '采集策略管理', icon: 'Timer' }
},
{
path: 'collection/cleaning',
name: 'DataCleaning',
component: () => import('@/views/config/collection/Cleaning.vue'),
meta: { title: '数据清洗与转换', icon: 'Filter' }
},
{
path: 'collection/storage',
name: 'TimeSeriesStorage',
component: () => import('@/views/config/collection/Storage.vue'),
meta: { title: '时序数据存储', icon: 'Coin' }
}
]
},
// 系统管理
{
path: '/system',
component: Layout,
redirect: '/system/role',
meta: { title: '系统管理', icon: 'Tools' },
children: [
{
path: 'role',
name: 'RoleManage',
component: () => import('@/views/system/role/Index.vue'),
meta: { title: '角色权限管理', icon: 'Lock' }
},
{
path: 'audit',
name: 'AuditLog',
component: () => import('@/views/system/audit/Index.vue'),
meta: { title: '操作审计日志', icon: 'Notebook' }
},
{
path: 'organization',
name: 'Organization',
component: () => import('@/views/system/organization/Index.vue'),
meta: { title: '组织架构管理', icon: 'OfficeBuilding' }
},
{
path: 'user',
name: 'UserManage',
component: () => import('@/views/system/user/Index.vue'),
meta: { title: '用户管理', icon: 'User' }
},
{
path: 'dict',
name: 'DictManage',
component: () => import('@/views/system/dict/Index.vue'),
meta: { title: '数据字典管理', icon: 'Collection' }
},
{
path: 'params',
name: 'SystemParams',
component: () => import('@/views/system/params/Index.vue'),
meta: { title: '系统参数配置', icon: 'Setting' }
},
{
path: 'storage',
name: 'FileStorage',
component: () => import('@/views/system/storage/Index.vue'),
meta: { title: '文件存储管理', icon: 'Folder' }
},
{
path: 'log/access',
name: 'AccessLog',
component: () => import('@/views/system/log/AccessLog.vue'),
meta: { title: '访问日志', icon: 'View' }
},
{
path: 'log/system',
name: 'SystemLog',
component: () => import('@/views/system/log/SystemLog.vue'),
meta: { title: '系统日志', icon: 'Monitor' }
}
]
},
// 404
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/error/NotFound.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
+12
View File
@@ -0,0 +1,12 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useAppStore = defineStore('app', () => {
const sidebarCollapsed = ref(false)
function toggleSidebar() {
sidebarCollapsed.value = !sidebarCollapsed.value
}
return { sidebarCollapsed, toggleSidebar }
})
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>分类管理视图</span>
</template>
<el-empty description="分类管理视图 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现分类管理视图功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>合规管理视图</span>
</template>
<el-empty description="合规管理视图 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现合规管理视图功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备信息</span>
</template>
<el-empty description="设备信息 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备信息功能
</script>
+164
View File
@@ -0,0 +1,164 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<div class="card-header">
<span>设备台账</span>
<div>
<el-button type="primary" @click="dialogVisible = true">
<el-icon><Plus /></el-icon> 新增设备
</el-button>
<el-button type="success">
<el-icon><Upload /></el-icon> 批量导入
</el-button>
<el-button>
<el-icon><Download /></el-icon> 导出
</el-button>
</div>
</div>
</template>
<!-- 搜索栏 -->
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item label="设备编号">
<el-input v-model="searchForm.code" placeholder="请输入设备编号" clearable />
</el-form-item>
<el-form-item label="设备名称">
<el-input v-model="searchForm.name" placeholder="请输入设备名称" clearable />
</el-form-item>
<el-form-item label="所属部门">
<el-select v-model="searchForm.department" placeholder="请选择" clearable>
<el-option label="研发部" value="rd" />
<el-option label="生产部" value="prod" />
<el-option label="质检部" value="qa" />
</el-select>
</el-form-item>
<el-form-item label="设备状态">
<el-select v-model="searchForm.status" placeholder="请选择" clearable>
<el-option label="在用" value="active" />
<el-option label="闲置" value="idle" />
<el-option label="维修中" value="repairing" />
<el-option label="报废" value="scrapped" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="tableData" border stripe style="width: 100%">
<el-table-column prop="code" label="设备编号" width="120" />
<el-table-column prop="name" label="设备名称" min-width="150" />
<el-table-column prop="model" label="型号规格" width="150" />
<el-table-column prop="department" label="所属部门" width="120" />
<el-table-column prop="location" label="存放位置" width="150" />
<el-table-column prop="purchaseDate" label="购置日期" width="120" />
<el-table-column prop="status" label="状态" width="100">
<template #default="{ row }">
<el-tag :type="statusType(row.status)">{{ row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="200" fixed="right">
<template #default>
<el-button link type="primary" size="small">查看</el-button>
<el-button link type="primary" size="small">编辑</el-button>
<el-button link type="danger" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
/>
</div>
</el-card>
<!-- 新增设备对话框 -->
<el-dialog v-model="dialogVisible" title="新增设备" width="600px">
<el-form :model="form" label-width="100px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="设备编号"><el-input v-model="form.code" /></el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称"><el-input v-model="form.name" /></el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="型号规格"><el-input v-model="form.model" /></el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所属部门">
<el-select v-model="form.department" style="width:100%">
<el-option label="研发部" value="rd" />
<el-option label="生产部" value="prod" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="存放位置"><el-input v-model="form.location" /></el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="购置日期"><el-date-picker v-model="form.purchaseDate" type="date" style="width:100%" /></el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供应商"><el-input v-model="form.supplier" /></el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="保修期"><el-input v-model="form.warranty" /></el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="dialogVisible = false">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
const searchForm = ref({ code: '', name: '', department: '', status: '' })
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(100)
const dialogVisible = ref(false)
const form = ref({})
const tableData = ref([
{ code: 'EQ-001', name: '高低温试验箱', model: 'GDS-100', department: '研发部', location: 'A栋3楼实验室', purchaseDate: '2024-01-15', status: '在用' },
{ code: 'EQ-002', name: '充放电测试柜', model: 'CDC-200', department: '生产部', location: 'B栋1楼车间', purchaseDate: '2024-03-20', status: '在用' },
{ code: 'EQ-003', name: '振动试验台', model: 'ZD-500', department: '质检部', location: 'A栋2楼实验室', purchaseDate: '2023-08-10', status: '维修中' },
{ code: 'EQ-004', name: '温湿度传感器', model: 'TH-10', department: '研发部', location: 'A栋3楼实验室', purchaseDate: '2024-06-01', status: '在用' },
{ code: 'EQ-005', name: '数据采集仪', model: 'DAQ-300', department: '生产部', location: 'B栋2楼', purchaseDate: '2023-11-25', status: '闲置' }
])
function statusType(status) {
const map = { '在用': 'success', '闲置': 'info', '维修中': 'warning', '报废': 'danger' }
return map[status] || 'info'
}
function handleSearch() { /* TODO: 对接API */ }
function resetSearch() { searchForm.value = { code: '', name: '', department: '', status: '' } }
</script>
<style scoped>
.card-header { display: flex; justify-content: space-between; align-items: center; }
.search-form { margin-bottom: 16px; }
.pagination { margin-top: 16px; display: flex; justify-content: flex-end; }
</style>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>全生命周期视图</span>
</template>
<el-empty description="全生命周期视图 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现全生命周期视图功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>分类统计</span>
</template>
<el-empty description="分类统计 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现分类统计功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>二维码管理</span>
</template>
<el-empty description="二维码管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现二维码管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>数据清洗与转换</span>
</template>
<el-empty description="数据清洗与转换 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现数据清洗与转换功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>采集点位配置</span>
</template>
<el-empty description="采集点位配置 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现采集点位配置功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>时序数据存储</span>
</template>
<el-empty description="时序数据存储 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现时序数据存储功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>采集策略管理</span>
</template>
<el-empty description="采集策略管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现采集策略管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备管理</span>
</template>
<el-empty description="设备管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>网关管理</span>
</template>
<el-empty description="网关管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现网关管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>产品分类</span>
</template>
<el-empty description="产品分类 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现产品分类功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>产品管理</span>
</template>
<el-empty description="产品管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现产品管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>证书管理</span>
</template>
<el-empty description="证书管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现证书管理功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备网关</span>
</template>
<el-empty description="设备网关 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备网关功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>协议管理</span>
</template>
<el-empty description="协议管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现协议管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>网络组件与协议注册</span>
</template>
<el-empty description="网络组件与协议注册 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现网络组件与协议注册功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>协议模板库</span>
</template>
<el-empty description="协议模板库 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现协议模板库功能
</script>
+89
View File
@@ -0,0 +1,89 @@
<template>
<div class="dashboard">
<el-row :gutter="20">
<el-col :span="6" v-for="item in statsCards" :key="item.title">
<el-card shadow="hover" class="stat-card">
<div class="stat-content">
<div class="stat-info">
<div class="stat-title">{{ item.title }}</div>
<div class="stat-value">{{ item.value }}</div>
</div>
<el-icon class="stat-icon" :style="{ color: item.color }">
<component :is="item.icon" />
</el-icon>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="16">
<el-card>
<template #header>设备状态分布</template>
<div ref="chartRef" style="height: 350px"></div>
</el-card>
</el-col>
<el-col :span="8">
<el-card>
<template #header>快捷操作</template>
<div class="quick-actions">
<el-button type="primary" @click="$router.push('/asset/ledger')">设备台账</el-button>
<el-button type="success" @click="$router.push('/inspection/dashboard')">设备看板</el-button>
<el-button type="warning" @click="$router.push('/inspection/patrol')">巡检管理</el-button>
<el-button type="danger" @click="$router.push('/inspection/alert-message')">告警信息</el-button>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
const statsCards = ref([
{ title: '设备总数', value: '1,286', icon: 'Box', color: '#409EFF' },
{ title: '在用设备', value: '1,052', icon: 'CircleCheck', color: '#67C23A' },
{ title: '待维修', value: '23', icon: 'Tools', color: '#E6A23C' },
{ title: '今日告警', value: '7', icon: 'Bell', color: '#F56C6C' }
])
const chartRef = ref(null)
onMounted(() => {
const chart = echarts.init(chartRef.value)
chart.setOption({
tooltip: { trigger: 'item' },
legend: { bottom: 0 },
series: [{
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
itemStyle: { borderRadius: 10, borderColor: '#fff', borderWidth: 2 },
label: { show: true, formatter: '{b}: {c} ({d}%)' },
data: [
{ value: 1052, name: '在用' },
{ value: 86, name: '闲置' },
{ value: 23, name: '维修中' },
{ value: 45, name: '待报废' },
{ value: 80, name: '其他' }
]
}]
})
window.addEventListener('resize', () => chart.resize())
})
</script>
<style scoped>
.stat-card .stat-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.stat-title { font-size: 14px; color: #909399; }
.stat-value { font-size: 28px; font-weight: bold; color: #303133; margin-top: 8px; }
.stat-icon { font-size: 48px; opacity: 0.8; }
.quick-actions { display: flex; flex-direction: column; gap: 12px; }
.quick-actions .el-button { width: 100%; }
</style>
+9
View File
@@ -0,0 +1,9 @@
<template>
<div class="not-found">
<el-result icon="404" title="404" sub-title="抱歉您访问的页面不存在">
<template #extra>
<el-button type="primary" @click="$router.push('/')">返回首页</el-button>
</template>
</el-result>
</div>
</template>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>消息告警</span>
</template>
<el-empty description="消息告警 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现消息告警功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>告警规则</span>
</template>
<el-empty description="告警规则 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现告警规则功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>数据大屏</span>
</template>
<el-empty description="数据大屏 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现数据大屏功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>辅助设备看板</span>
</template>
<el-empty description="辅助设备看板 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现辅助设备看板功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>充放电柜看板</span>
</template>
<el-empty description="充放电柜看板 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现充放电柜看板功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备详情</span>
</template>
<el-empty description="设备详情 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备详情功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备看板</span>
</template>
<el-empty description="设备看板 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备看板功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>温度箱看板</span>
</template>
<el-empty description="温度箱看板 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现温度箱看板功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>设备效率分析</span>
</template>
<el-empty description="设备效率分析 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现设备效率分析功能
</script>
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>自动巡检</span>
</template>
<el-empty description="自动巡检 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现自动巡检功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>巡检管理</span>
</template>
<el-empty description="巡检管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现巡检管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>巡检记录查询</span>
</template>
<el-empty description="巡检记录查询 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现巡检记录查询功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>巡检任务执行</span>
</template>
<el-empty description="巡检任务执行 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现巡检任务执行功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>巡检模板配置</span>
</template>
<el-empty description="巡检模板配置 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现巡检模板配置功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>统计报表</span>
</template>
<el-empty description="统计报表 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现统计报表功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>操作审计日志</span>
</template>
<el-empty description="操作审计日志 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现操作审计日志功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>数据字典管理</span>
</template>
<el-empty description="数据字典管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现数据字典管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>访问日志</span>
</template>
<el-empty description="访问日志 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现访问日志功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>系统日志</span>
</template>
<el-empty description="系统日志 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现系统日志功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>组织架构管理</span>
</template>
<el-empty description="组织架构管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现组织架构管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>系统参数配置</span>
</template>
<el-empty description="系统参数配置 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现系统参数配置功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>角色权限管理</span>
</template>
<el-empty description="角色权限管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现角色权限管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>文件存储管理</span>
</template>
<el-empty description="文件存储管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现文件存储管理功能
</script>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div class="page-container">
<el-card>
<template #header>
<span>用户管理</span>
</template>
<el-empty description="用户管理 - 功能开发中" />
</el-card>
</div>
</template>
<script setup>
// TODO: 实现用户管理功能
</script>