From e365192a36d6d9432fbd00ea9d577a38f8679707 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期五, 13 三月 2026 11:21:33 +0800
Subject: [PATCH] 2026.3.13
---
src/views/analysis/huanxincode/HuanxinCodeManage.vue | 707 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 706 insertions(+), 1 deletions(-)
diff --git a/src/views/analysis/huanxincode/HuanxinCodeManage.vue b/src/views/analysis/huanxincode/HuanxinCodeManage.vue
index 0389851..9a75b38 100644
--- a/src/views/analysis/huanxincode/HuanxinCodeManage.vue
+++ b/src/views/analysis/huanxincode/HuanxinCodeManage.vue
@@ -1 +1,706 @@
-<template>鐜俊鐮佺鐞�</template>
+<template>
+ <div class="huanxin-code-manage">
+ <!-- 椤堕儴瀹忚鐪嬫澘鍖� -->
+ <el-row :gutter="20" class="dashboard">
+ <el-col :span="8">
+ <el-card shadow="hover" class="dashboard-card green-card" @click="filterByCode('green')">
+ <div class="card-content">
+ <div class="card-title">缁跨爜搴楅摵鏁�</div>
+ <div class="card-value">{{ statistics.greenCount }}</div>
+ <div class="card-percentage">{{ statistics.greenPercentage }}%</div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="8">
+ <el-card shadow="hover" class="dashboard-card yellow-card" @click="filterByCode('yellow')">
+ <div class="card-content">
+ <div class="card-title">榛勭爜搴楅摵鏁�</div>
+ <div class="card-value">{{ statistics.yellowCount }}</div>
+ <div class="card-percentage">{{ statistics.yellowPercentage }}%</div>
+ </div>
+ </el-card>
+ </el-col>
+ <el-col :span="8">
+ <el-card shadow="hover" class="dashboard-card red-card" @click="filterByCode('red')">
+ <div class="card-content">
+ <div class="card-title">绾㈢爜搴楅摵鏁�</div>
+ <div class="card-value">{{ statistics.redCount }}</div>
+ <div class="card-percentage">{{ statistics.redPercentage }}%</div>
+ </div>
+ </el-card>
+ </el-col>
+ </el-row>
+
+ <!-- 璇勫垎妯″瀷閰嶇疆鎸夐挳 -->
+ <!-- <div class="model-config" v-if="isAdmin">
+ <el-button type="primary" @click="openModelConfig">
+ <el-icon><Setting /></el-icon>
+ <span>璇勫垎妯″瀷閰嶇疆</span>
+ </el-button>
+ </div> -->
+
+ <!-- 涓儴瑙嗗浘鍒囨崲鍖� -->
+ <el-tabs v-model="activeView" class="view-tabs">
+ <!-- 鍒楄〃瑙嗗浘 -->
+ <el-tab-pane label="鍒楄〃瑙嗗浘" name="list">
+ <el-table :data="filteredShopList" style="width: 100%">
+ <el-table-column prop="shopName" label="搴楅摵鍚嶇О" />
+ <el-table-column prop="district" label="鎵�鍦ㄥ尯鍘�" width="120" />
+ <el-table-column prop="town" label="鎵�鍦ㄨ闀�" width="150" />
+ <el-table-column label="鐜俊鐮�" width="100">
+ <template #default="scope">
+ <el-tag :type="getCodeType(scope.row.code)">{{ getCodeText(scope.row.code) }}</el-tag>
+ </template>
+ </el-table-column>
+ <el-table-column prop="score" label="褰撳墠璇勫垎" width="120" sortable />
+ <el-table-column label="璇勫垎鍙樺寲瓒嬪娍" width="150">
+ <template #default="scope">
+ <div class="trend">
+ <el-icon :class="['trend-icon', scope.row.trend > 0 ? 'up' : 'down']">
+ <ArrowUp v-if="scope.row.trend > 0" />
+ <ArrowDown v-else />
+ </el-icon>
+ <span :class="scope.row.trend > 0 ? 'up' : 'down'">
+ {{ scope.row.trend > 0 ? '+' : '' }}{{ scope.row.trend }}鍒�
+ </span>
+ </div>
+ </template>
+ </el-table-column>
+ <el-table-column prop="lastUpdate" label="涓婃鏇存柊鏃堕棿" width="180" />
+ <el-table-column label="鎿嶄綔" width="200" fixed="right">
+ <template #default="scope">
+ <el-button size="small" @click="viewDetails(scope.row)">鏌ョ湅璇︽儏</el-button>
+ <!-- <el-button size="small" type="warning" @click="viewRiskWarnings(scope.row)"
+ >椋庨櫓棰勮璁板綍</el-button
+ > -->
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-tab-pane>
+
+ <!-- 鍦板浘瑙嗗浘 -->
+ <el-tab-pane label="鍦板浘瑙嗗浘" name="map">
+ <div class="map-container">
+ <div class="map-placeholder">
+ <el-empty description="鍦板浘鍔犺浇涓�..." />
+ <!-- 杩欓噷搴旇闆嗘垚鐪熷疄鐨勫湴鍥剧粍浠� -->
+ </div>
+ <div class="map-legend">
+ <div class="legend-item">
+ <div class="legend-dot green"></div>
+ <span>缁跨爜</span>
+ </div>
+ <div class="legend-item">
+ <div class="legend-dot yellow"></div>
+ <span>榛勭爜</span>
+ </div>
+ <div class="legend-item">
+ <div class="legend-dot red"></div>
+ <span>绾㈢爜</span>
+ </div>
+ </div>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+
+ <!-- 璇︽儏鎶藉眽 -->
+ <el-drawer v-model="drawerVisible" title="搴楅摵璇︽儏" direction="rtl" size="70%">
+ <div v-if="selectedShop" class="shop-details">
+ <!-- 鐜俊鐮佸ぇ鍥炬爣鍙婂綋鍓嶈瘎鍒� -->
+ <div class="code-header">
+ <div class="code-icon" :class="selectedShop.code">
+ {{ getCodeText(selectedShop.code) }}
+ </div>
+ <div class="score-info">
+ <div class="score-label">褰撳墠璇勫垎</div>
+ <div class="score-value">{{ selectedShop.score }}</div>
+ </div>
+ </div>
+
+ <!-- 璇勫垎缁村害闆疯揪鍥� -->
+ <div class="chart-section">
+ <h3>璇勫垎缁村害鍒嗘瀽</h3>
+ <div class="radar-chart">
+ <!-- 杩欓噷搴旇闆嗘垚鐪熷疄鐨勯浄杈惧浘缁勪欢 -->
+ <el-empty description="闆疯揪鍥惧姞杞戒腑..." />
+ </div>
+ </div>
+
+ <!-- 璇勫垎鍘嗗彶瓒嬪娍鍥� -->
+ <div class="chart-section">
+ <h3>璇勫垎鍘嗗彶瓒嬪娍</h3>
+ <div class="trend-chart">
+ <!-- 杩欓噷搴旇闆嗘垚鐪熷疄鐨勮秼鍔垮浘缁勪欢 -->
+ <el-empty description="瓒嬪娍鍥惧姞杞戒腑..." />
+ </div>
+ </div>
+
+ <!-- 椋庨櫓棰勮璁板綍 -->
+ <div class="warning-section">
+ <h3>椋庨櫓棰勮璁板綍</h3>
+ <el-table :data="selectedShop.warnings" style="width: 100%">
+ <el-table-column prop="time" label="棰勮鏃堕棿" width="180" />
+ <el-table-column prop="content" label="棰勮鍐呭" />
+ <el-table-column prop="score" label="褰撴椂璇勫垎" width="120" />
+ <el-table-column label="澶勭悊鐘舵��" width="120">
+ <template #default="scope">
+ <el-tag :type="scope.row.handled ? 'success' : 'danger'">
+ {{ scope.row.handled ? '宸插鐞�' : '鏈鐞�' }}
+ </el-tag>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+ </el-drawer>
+
+ <!-- 璇勫垎妯″瀷閰嶇疆寮圭獥 -->
+ <el-dialog v-model="modelConfigVisible" title="璇勫垎妯″瀷閰嶇疆" width="80%">
+ <div class="model-config-content">
+ <!-- 杩欓噷搴旇闆嗘垚鐪熷疄鐨勯厤缃〃鍗� -->
+ <el-empty description="閰嶇疆琛ㄥ崟鍔犺浇涓�..." />
+ </div>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="modelConfigVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="saveModelConfig">淇濆瓨閰嶇疆</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import { Setting, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
+
+// 鐘舵��
+const activeView = ref('list')
+const drawerVisible = ref(false)
+const modelConfigVisible = ref(false)
+const selectedShop = ref(null)
+const isAdmin = ref(true) // 妯℃嫙绠$悊鍛樻潈闄�
+const filterCode = ref('all')
+
+// 缁熻鏁版嵁
+const statistics = reactive({
+ greenCount: 125,
+ greenPercentage: 65.8,
+ yellowCount: 45,
+ yellowPercentage: 23.7,
+ redCount: 20,
+ redPercentage: 10.5,
+})
+
+// 搴楅摵鍚嶇О鍒楄〃
+const shopNames = [
+ '浠樺皬濮愬湪鎴愰兘',
+ '鍚夊埢鑱旂洘',
+ '瀹跺湪濉斿暒',
+ '鐙兼潵浜�',
+ '涔愬嚡鎾掓槦娓稿簵',
+ '棣ㄨ繙缇庨灏忛晣锛堝搱灏肩編椋熷箍鍦猴級',
+ '妫掔害缈�',
+ '寮勫爞鍜亾',
+ '鏉ㄨ榻愰綈鍝堝皵鐑よ倝',
+ '涓婃捣绋斾紶椁愰ギ绠$悊鏈夐檺鍏徃锛堜汉鐢熶竴涓诧級',
+ '缂樺',
+ '娉夌洓椁愰ギ锛堜笂娴凤級鏈夐檺鍏徃锛堥鍏跺锛�',
+ '涓拌寕鐑や覆',
+ '涓婃捣娉扮厡椁愰ギ绠$悊鏈夐檺鍏徃锛堟嘲鐓岄浮锛�',
+ '寰愭眹鍖鸿景鐔欓棣�(灏忛搧鍚涗覆鐑у眳閰掑眿)',
+]
+
+// 寰愭眹鍖鸿闀囧垪琛�
+const xuhuiTowns = [
+ '澶╁钩璺閬�',
+ '婀栧崡璺閬�',
+ '鏂滃湡璺閬�',
+ '鏋灄璺閬�',
+ '闀挎ˉ琛楅亾',
+ '鐢版灄琛楅亾',
+ '铏规璺閬�',
+ '搴峰仴鏂版潙琛楅亾',
+ '寰愬姹囪閬�',
+ '鍑屼簯璺閬�',
+ '榫欏崕琛楅亾',
+ '婕曟渤娉捐閬�',
+ '鍗庢尘闀�',
+]
+
+// 鐢熸垚2023骞�8鏈堝唴鐨勯殢鏈烘椂闂�
+function generateRandomDate() {
+ const year = 2023
+ const month = 7 // 0-11锛�8鏈堟槸7
+ const day = Math.floor(Math.random() * 31) + 1 // 1-31
+ const hour = Math.floor(Math.random() * 24) // 0-23
+ const minute = Math.floor(Math.random() * 60) // 0-59
+
+ const date = new Date(year, month, day, hour, minute)
+ return date.toISOString().slice(0, 16).replace('T', ' ')
+}
+
+// 闅忔満閫夋嫨鏁扮粍鍏冪礌
+function getRandomElement(array) {
+ return array[Math.floor(Math.random() * array.length)]
+}
+
+// 鐢熸垚闅忔満璇勫垎瓒嬪娍
+function generateRandomTrend() {
+ return Math.floor(Math.random() * 11) - 5 // -5 鍒� 5
+}
+
+// 搴楅摵鏁版嵁
+const shopList = ref([
+ {
+ id: 1,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'green',
+ score: 95,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鍑�鍖栧櫒杩愯鏃堕暱涓嶈冻',
+ score: 90,
+ handled: true,
+ },
+ ],
+ },
+ {
+ id: 2,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'yellow',
+ score: 75,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鎶曡瘔娆℃暟杈冨',
+ score: 80,
+ handled: false,
+ },
+ ],
+ },
+ {
+ id: 3,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'red',
+ score: 60,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鎺掓斁娴撳害瓒呮爣',
+ score: 65,
+ handled: false,
+ },
+ {
+ time: generateRandomDate(),
+ content: '娓呮礂棰戞涓嶈冻',
+ score: 62,
+ handled: false,
+ },
+ ],
+ },
+ {
+ id: 4,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'green',
+ score: 92,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [],
+ },
+ {
+ id: 5,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'yellow',
+ score: 78,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '椋庢満鑱斿姩鐜囦綆',
+ score: 75,
+ handled: true,
+ },
+ ],
+ },
+ {
+ id: 6,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'green',
+ score: 90,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [],
+ },
+ {
+ id: 7,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'red',
+ score: 55,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鏈畨瑁呮补鐑熷噣鍖栬澶�',
+ score: 60,
+ handled: false,
+ },
+ ],
+ },
+ {
+ id: 8,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'yellow',
+ score: 72,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鍑�鍖栧櫒娓呮礂涓嶅強鏃�',
+ score: 75,
+ handled: true,
+ },
+ ],
+ },
+ {
+ id: 9,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'green',
+ score: 93,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [],
+ },
+ {
+ id: 10,
+ shopName: getRandomElement(shopNames),
+ district: '寰愭眹鍖�',
+ town: getRandomElement(xuhuiTowns),
+ code: 'yellow',
+ score: 76,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鎺掓斁娴撳害鎺ヨ繎鏍囧噯闄愬��',
+ score: 78,
+ handled: true,
+ },
+ ],
+ },
+])
+
+// 杩囨护鍚庣殑搴楅摵鍒楄〃
+const filteredShopList = computed(() => {
+ if (filterCode.value === 'all') {
+ return shopList.value
+ }
+ return shopList.value.filter((shop) => shop.code === filterCode.value)
+})
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+ // 杩欓噷鍙互浠嶢PI鑾峰彇鏁版嵁
+ console.log('鐜俊鐮佺鐞嗛〉闈㈠姞杞�')
+})
+
+// 鏂规硶
+function onBack() {
+ // 鍥為��閫昏緫
+ console.log('鍥為��')
+}
+
+function filterByCode(code) {
+ filterCode.value = code === filterCode.value ? 'all' : code
+ activeView.value = 'list' // 鍒囨崲鍒板垪琛ㄨ鍥�
+}
+
+function getCodeType(code) {
+ switch (code) {
+ case 'green':
+ return 'success'
+ case 'yellow':
+ return 'warning'
+ case 'red':
+ return 'danger'
+ default:
+ return ''
+ }
+}
+
+function getCodeText(code) {
+ switch (code) {
+ case 'green':
+ return '缁跨爜'
+ case 'yellow':
+ return '榛勭爜'
+ case 'red':
+ return '绾㈢爜'
+ default:
+ return ''
+ }
+}
+
+function viewDetails(shop) {
+ selectedShop.value = shop
+ drawerVisible.value = true
+}
+
+function viewRiskWarnings(shop) {
+ selectedShop.value = shop
+ drawerVisible.value = true
+ // 杩欓噷鍙互婊氬姩鍒伴闄╅璀﹂儴鍒�
+}
+
+function openModelConfig() {
+ modelConfigVisible.value = true
+}
+
+function saveModelConfig() {
+ // 淇濆瓨閰嶇疆閫昏緫
+ modelConfigVisible.value = false
+ console.log('淇濆瓨璇勫垎妯″瀷閰嶇疆')
+}
+</script>
+
+<style scoped>
+.huanxin-code-manage {
+ padding: 20px;
+}
+
+.dashboard {
+ margin-bottom: 30px;
+}
+
+.dashboard-card {
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.dashboard-card:hover {
+ transform: translateY(-5px);
+}
+
+.card-content {
+ text-align: center;
+ padding: 20px 0;
+}
+
+.card-title {
+ font-size: 16px;
+ margin-bottom: 10px;
+}
+
+.card-value {
+ font-size: 32px;
+ font-weight: bold;
+ margin-bottom: 5px;
+}
+
+.card-percentage {
+ font-size: 14px;
+ opacity: 0.8;
+}
+
+.green-card .card-value {
+ color: #67c23a;
+}
+
+.yellow-card .card-value {
+ color: #e6a23c;
+}
+
+.red-card .card-value {
+ color: #f56c6c;
+}
+
+.model-config {
+ text-align: right;
+ margin-bottom: 20px;
+}
+
+.view-tabs {
+ margin-bottom: 20px;
+}
+
+.trend {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.trend-icon {
+ margin-right: 5px;
+}
+
+.trend-icon.up {
+ color: #67c23a;
+}
+
+.trend-icon.down {
+ color: #f56c6c;
+}
+
+.trend .up {
+ color: #67c23a;
+}
+
+.trend .down {
+ color: #f56c6c;
+}
+
+.map-container {
+ position: relative;
+ height: 600px;
+ border: 1px solid #e4e7ed;
+ border-radius: 4px;
+}
+
+.map-placeholder {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.map-legend {
+ position: absolute;
+ bottom: 20px;
+ right: 20px;
+ background: white;
+ padding: 10px;
+ border-radius: 4px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+}
+
+.legend-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 5px;
+}
+
+.legend-dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ margin-right: 8px;
+}
+
+.legend-dot.green {
+ background-color: #67c23a;
+}
+
+.legend-dot.yellow {
+ background-color: #e6a23c;
+}
+
+.legend-dot.red {
+ background-color: #f56c6c;
+}
+
+.shop-details {
+ padding: 20px;
+}
+
+.code-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 30px;
+}
+
+.code-icon {
+ width: 100px;
+ height: 100px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24px;
+ font-weight: bold;
+ color: white;
+ margin-right: 30px;
+}
+
+.code-icon.green {
+ background-color: #67c23a;
+}
+
+.code-icon.yellow {
+ background-color: #e6a23c;
+}
+
+.code-icon.red {
+ background-color: #f56c6c;
+}
+
+.score-info {
+ flex: 1;
+}
+
+.score-label {
+ font-size: 16px;
+ margin-bottom: 5px;
+}
+
+.score-value {
+ font-size: 48px;
+ font-weight: bold;
+}
+
+.chart-section {
+ margin-bottom: 30px;
+}
+
+.chart-section h3 {
+ margin-bottom: 15px;
+ font-size: 18px;
+}
+
+.radar-chart,
+.trend-chart {
+ height: 300px;
+ border: 1px solid #e4e7ed;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.warning-section {
+ margin-top: 30px;
+}
+
+.warning-section h3 {
+ margin-bottom: 15px;
+ font-size: 18px;
+}
+</style>
--
Gitblit v1.9.3