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