From b1a0d701cf898c8b7812e66a808a1c91f2bae6cc Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期二, 17 三月 2026 16:44:11 +0800
Subject: [PATCH] 2026.3.17
---
src/views/analysis/huanxincode/HuanxinCodeManage.vue | 552 +++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 435 insertions(+), 117 deletions(-)
diff --git a/src/views/analysis/huanxincode/HuanxinCodeManage.vue b/src/views/analysis/huanxincode/HuanxinCodeManage.vue
index 9a75b38..9140d7c 100644
--- a/src/views/analysis/huanxincode/HuanxinCodeManage.vue
+++ b/src/views/analysis/huanxincode/HuanxinCodeManage.vue
@@ -1,5 +1,31 @@
<template>
<div class="huanxin-code-manage">
+ <FYSearchBar @search="onSearch">
+ <template #options>
+ <!-- 鍖哄幙 -->
+ <FYOptionLocation
+ :initValue="false"
+ :allOption="false"
+ :level="3"
+ :checkStrictly="false"
+ v-model:value="formSearch.locations"
+ ></FYOptionLocation>
+ <!-- 鍦烘櫙绫诲瀷 -->
+ <FYOptionScene
+ :initValue="false"
+ :allOption="false"
+ :type="1"
+ v-model:value="formSearch.scenetype"
+ ></FYOptionScene>
+ <!-- 鏃堕棿 -->
+ <FYOptionTime
+ :initValue="false"
+ type="month"
+ v-model:value="formSearch.time"
+ ></FYOptionTime>
+ </template>
+ <template #buttons v-if="$slots.buttons"> </template>
+ </FYSearchBar>
<!-- 椤堕儴瀹忚鐪嬫澘鍖� -->
<el-row :gutter="20" class="dashboard">
<el-col :span="8">
@@ -39,99 +65,96 @@
</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 class="shop-list">
+ <el-table :data="pagedShopList" 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>
- <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>
+ </template>
+ </el-table-column>
+ <el-table-column prop="lastUpdate" label="涓婃鏇存柊鏃堕棿" width="180" />
+ <el-table-column label="鎿嶄綔" width="100" 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>
+ <!-- 鍒嗛〉缁勪欢 -->
+ <div class="pagination">
+ <el-pagination
+ v-model:current-page="currentPage"
+ v-model:page-size="pageSize"
+ :page-sizes="[10, 20, 50, 100]"
+ layout="total, sizes, prev, pager, next, jumper"
+ :total="filteredShopList.length"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+ </div>
<!-- 璇︽儏鎶藉眽 -->
- <el-drawer v-model="drawerVisible" title="搴楅摵璇︽儏" direction="rtl" size="70%">
+ <el-drawer
+ v-model="drawerVisible"
+ :title="selectedShop?.shopName || '搴楅摵璇︽儏'"
+ direction="rtl"
+ size="60%"
+ >
<div v-if="selectedShop" class="shop-details">
- <!-- 鐜俊鐮佸ぇ鍥炬爣鍙婂綋鍓嶈瘎鍒� -->
- <div class="code-header">
- <div class="code-icon" :class="selectedShop.code">
- {{ getCodeText(selectedShop.code) }}
+ <el-row justify="space-between" style="flex-wrap: nowrap">
+ <!-- 鐜俊鐮佸ぇ鍥炬爣鍙婂綋鍓嶈瘎鍒� -->
+ <div class="code-header">
+ <div class="score-info">
+ <div class="score-label">褰撳墠璇勫垎</div>
+ <div class="score-value">{{ selectedShop.score }}</div>
+ </div>
+ <div class="code-icon">
+ <el-image
+ class="image"
+ :src="codeImageUrl"
+ :preview-src-list="[codeImageUrl]"
+ :initial-index="0"
+ fit="cover"
+ lazy
+ />
+ </div>
</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 class="chart-section">
+ <h3>璇勫垎缁村害鍒嗘瀽</h3>
+ <div class="radar-chart">
+ <canvas ref="radarChart" width="500" height="400"></canvas>
+ </div>
</div>
- </div>
+ </el-row>
<!-- 璇勫垎鍘嗗彶瓒嬪娍鍥� -->
<div class="chart-section">
<h3>璇勫垎鍘嗗彶瓒嬪娍</h3>
<div class="trend-chart">
- <!-- 杩欓噷搴旇闆嗘垚鐪熷疄鐨勮秼鍔垮浘缁勪欢 -->
- <el-empty description="瓒嬪娍鍥惧姞杞戒腑..." />
+ <canvas ref="trendChart" width="800" height="350"></canvas>
</div>
</div>
@@ -171,16 +194,46 @@
</template>
<script setup>
-import { ref, reactive, computed, onMounted } from 'vue'
+import dayjs from 'dayjs'
+import { ref, reactive, computed, onMounted, watch } from 'vue'
import { Setting, ArrowUp, ArrowDown } from '@element-plus/icons-vue'
+import * as echarts from 'echarts'
+import userApi from '@/api/fytz/userApi'
+import creditApi from '@/api/fytz/creditApi'
+// 鎼滅储琛ㄥ崟
+const formSearch = ref({
+ locations: {
+ aCode: null,
+ aName: null,
+ cCode: '3100',
+ cName: '涓婃捣甯�',
+ dCode: '310104',
+ dName: '寰愭眹鍖�',
+ mCode: null,
+ mName: null,
+ pCode: '31',
+ pName: '涓婃捣甯�',
+ tCode: null,
+ tName: null,
+ },
+ scenetype: {
+ label: '椁愰ギ',
+ value: '1',
+ },
+ time: dayjs('2023-08-01').date(1).toDate(),
+})
// 鐘舵��
-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 currentPage = ref(1)
+const pageSize = ref(10)
+// 鐜俊鐮佸浘鐗嘦RL
+const codeImageUrl = ref('')
// 缁熻鏁版嵁
const statistics = reactive({
@@ -228,6 +281,61 @@
'鍗庢尘闀�',
]
+function onSearch() {
+ const f = formSearch.value
+ const area = {}
+ // 琛屾斂鍖哄垝
+ area.provinceCode = f.locations.pCode
+ area.provinceName = f.locations.pName
+ if (area.provinceCode == null) {
+ area.provinceCode = null
+ area.provinceName = null
+ }
+ area.cityCode = f.locations.cCode
+ area.cityName = f.locations.cName
+ area.districtCode = f.locations.dCode
+ area.districtName = f.locations.dName
+ area.townCode = f.locations.tCode
+ area.townName = f.locations.tName
+ // 鍦烘櫙绫诲瀷
+ area.sceneTypes = []
+ f.scenetype.value == null ? (area.sceneTypes = []) : (area.sceneTypes = [f.scenetype.value])
+ // 涓婁笅绾跨姸鎬�
+ area.online = true
+ // 鍏抽敭瀛�
+ area.searchText = ''
+
+ userApi.fetchUser(currentPage.value, pageSize.value, area).then((res) => {
+ if (res) {
+ res.data
+ res.head.totalCount
+
+ shopList.value = res.data.map((item, index) => {
+ const { score, code } = generateRandomScore()
+ return {
+ id: index + 1,
+ guid: item.biGuid,
+ shopName: item.biName,
+ district: item.biDistrictName,
+ town: item.biTownName,
+ code: code,
+ score: score,
+ trend: generateRandomTrend(),
+ lastUpdate: generateRandomDate(),
+ warnings: [
+ {
+ time: generateRandomDate(),
+ content: '鍑�鍖栧櫒杩愯鏃堕暱涓嶈冻',
+ score: 90,
+ handled: true,
+ },
+ ],
+ }
+ })
+ }
+ })
+}
+
// 鐢熸垚2023骞�8鏈堝唴鐨勯殢鏈烘椂闂�
function generateRandomDate() {
const year = 2023
@@ -245,6 +353,23 @@
return array[Math.floor(Math.random() * array.length)]
}
+// 鐢熸垚闅忔満璇勫垎鍜屽搴旂幆淇$爜绛夌骇
+function generateRandomScore() {
+ const score = Math.floor(Math.random() * 101) // 0-100
+ let code
+ if (score >= 90) {
+ code = 'green'
+ } else if (score >= 60) {
+ code = 'yellow'
+ } else {
+ code = 'red'
+ }
+ return {
+ score,
+ code,
+ }
+}
+
// 鐢熸垚闅忔満璇勫垎瓒嬪娍
function generateRandomTrend() {
return Math.floor(Math.random() * 11) - 5 // -5 鍒� 5
@@ -258,7 +383,7 @@
district: '寰愭眹鍖�',
town: getRandomElement(xuhuiTowns),
code: 'green',
- score: 95,
+ score: 90,
trend: generateRandomTrend(),
lastUpdate: generateRandomDate(),
warnings: [
@@ -427,10 +552,18 @@
return shopList.value.filter((shop) => shop.code === filterCode.value)
})
+// 鍒嗛〉鍚庣殑搴楅摵鍒楄〃
+const pagedShopList = computed(() => {
+ const start = (currentPage.value - 1) * pageSize.value
+ const end = start + pageSize.value
+ return filteredShopList.value.slice(start, end)
+})
+
// 鐢熷懡鍛ㄦ湡
onMounted(() => {
// 杩欓噷鍙互浠嶢PI鑾峰彇鏁版嵁
console.log('鐜俊鐮佺鐞嗛〉闈㈠姞杞�')
+ onSearch()
})
// 鏂规硶
@@ -441,7 +574,17 @@
function filterByCode(code) {
filterCode.value = code === filterCode.value ? 'all' : code
- activeView.value = 'list' // 鍒囨崲鍒板垪琛ㄨ鍥�
+ currentPage.value = 1 // 閲嶇疆鍒扮涓�椤�
+}
+
+// 鍒嗛〉鏂规硶
+function handleSizeChange(size) {
+ pageSize.value = size
+ currentPage.value = 1
+}
+
+function handleCurrentChange(current) {
+ currentPage.value = current
}
function getCodeType(code) {
@@ -470,9 +613,183 @@
}
}
+// 闆疯揪鍥惧拰瓒嬪娍鍥惧紩鐢�
+const radarChart = ref(null)
+const trendChart = ref(null)
+let radarChartInstance = null
+let trendChartInstance = null
+
function viewDetails(shop) {
selectedShop.value = shop
drawerVisible.value = true
+
+ // 鑾峰彇鐜俊鐮佸浘鐗�
+ if (shop.guid && shop.shopName) {
+ creditApi.fetchCodeUrl(shop.guid, shop.shopName).then((res) => {
+ if (res && res.url) {
+ codeImageUrl.value = res.url
+ }
+ })
+ }
+
+ // 寤惰繜缁樺埗鍥捐〃锛岀‘淇滵OM宸叉洿鏂�
+ setTimeout(() => {
+ drawRadarChart()
+ drawTrendChart()
+ }, 100)
+}
+
+// 缁樺埗闆疯揪鍥�
+function drawRadarChart() {
+ if (!radarChart.value) return
+
+ // 閿�姣佹棫瀹炰緥
+ if (radarChartInstance) {
+ radarChartInstance.dispose()
+ }
+
+ // 鍒濆鍖杄charts瀹炰緥
+ radarChartInstance = echarts.init(radarChart.value)
+
+ // 闆疯揪鍥炬暟鎹�
+ const labels = [
+ '鍦ㄧ嚎鐩戞祴璁惧',
+ '鍑�鍖栬鏂借澶�',
+ '鍦ㄧ嚎鐩戞祴璁惧缁存姢',
+ '鍑�鍖栬鏂借澶囩淮鎶�',
+ '鍦ㄧ嚎鐩戞祴鏁版嵁閲忕骇',
+ '绌鸿皟鍜岄鏈哄櫔澹�',
+ '鍙扮珯绠$悊',
+ '淇$敤鎵胯鑷瘎',
+ ]
+
+ // 鐢熸垚闅忔満璇勫垎鏁版嵁锛堝疄闄呴」鐩腑搴斾粠API鑾峰彇锛�
+ const data = labels.map(() => Math.floor(Math.random() * 40) + 60) // 60-100鍒�
+
+ // 閰嶇疆椤�
+ const option = {
+ radar: {
+ indicator: labels.map((label) => ({
+ name: label,
+ max: 100,
+ })),
+ radius: '70%',
+ },
+ series: [
+ {
+ type: 'radar',
+ data: [
+ {
+ value: data,
+ name: '璇勫垎缁村害',
+ areaStyle: {
+ color: 'rgba(103, 194, 58, 0.2)',
+ },
+ lineStyle: {
+ color: '#67c23a',
+ },
+ itemStyle: {
+ color: '#67c23a',
+ },
+ },
+ ],
+ },
+ ],
+ }
+
+ // 娓叉煋鍥捐〃
+ radarChartInstance.setOption(option)
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', () => {
+ radarChartInstance.resize()
+ })
+}
+
+// 缁樺埗瓒嬪娍鍥�
+function drawTrendChart() {
+ if (!trendChart.value) return
+
+ // 閿�姣佹棫瀹炰緥
+ if (trendChartInstance) {
+ trendChartInstance.dispose()
+ }
+
+ // 鍒濆鍖杄charts瀹炰緥
+ trendChartInstance = echarts.init(trendChart.value)
+
+ // 鐢熸垚杩囧幓12涓湀鐨勬爣绛�
+ const labels = []
+ const data = []
+ const now = dayjs()
+
+ for (let i = 11; i >= 0; i--) {
+ const date = now.subtract(i, 'month')
+ labels.push(date.format('YYYY-MM'))
+ // 鐢熸垚闅忔満璇勫垎鏁版嵁锛堝疄闄呴」鐩腑搴斾粠API鑾峰彇锛�
+ data.push(Math.floor(Math.random() * 30) + 70) // 70-100鍒�
+ }
+
+ // 閰嶇疆椤�
+ const option = {
+ tooltip: {
+ trigger: 'axis',
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ data: labels,
+ axisLabel: {
+ rotate: 45,
+ },
+ },
+ yAxis: {
+ type: 'value',
+ min: 60,
+ max: 100,
+ interval: 8,
+ },
+ series: [
+ {
+ name: '璇勫垎',
+ type: 'line',
+ data: data,
+ smooth: true,
+ lineStyle: {
+ color: '#409eff',
+ },
+ itemStyle: {
+ color: '#409eff',
+ },
+ areaStyle: {
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+ {
+ offset: 0,
+ color: 'rgba(64, 158, 255, 0.3)',
+ },
+ {
+ offset: 1,
+ color: 'rgba(64, 158, 255, 0.1)',
+ },
+ ]),
+ },
+ },
+ ],
+ }
+
+ // 娓叉煋鍥捐〃
+ trendChartInstance.setOption(option)
+
+ // 鐩戝惉绐楀彛澶у皬鍙樺寲
+ window.addEventListener('resize', () => {
+ trendChartInstance.resize()
+ })
}
function viewRiskWarnings(shop) {
@@ -548,8 +865,13 @@
margin-bottom: 20px;
}
-.view-tabs {
+.shop-list {
margin-bottom: 20px;
+}
+
+.pagination {
+ margin-top: 20px;
+ text-align: right;
}
.trend {
@@ -633,33 +955,13 @@
.code-header {
display: flex;
- align-items: center;
- margin-bottom: 30px;
+ align-items: flex-start;
+ flex-direction: column;
+ margin-bottom: 20px;
}
.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 {
@@ -677,17 +979,26 @@
}
.chart-section {
- margin-bottom: 30px;
+ margin-bottom: 20px;
}
.chart-section h3 {
- margin-bottom: 15px;
- font-size: 18px;
+ margin-bottom: 10px;
+ font-size: 16px;
}
-.radar-chart,
+.radar-chart {
+ width: 500px;
+ height: 500px;
+ border: 1px solid #e4e7ed;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
.trend-chart {
- height: 300px;
+ height: 350px;
border: 1px solid #e4e7ed;
border-radius: 4px;
display: flex;
@@ -696,11 +1007,18 @@
}
.warning-section {
- margin-top: 30px;
+ margin-top: 20px;
}
.warning-section h3 {
- margin-bottom: 15px;
- font-size: 18px;
+ margin-bottom: 10px;
+ font-size: 16px;
+}
+
+.image {
+ width: 300px;
+ /* height: 250px; */
+ border-radius: 4px;
+ margin-bottom: 6px;
}
</style>
--
Gitblit v1.9.3