From 077ab59c700b85efdd057265bf752ad5942395b2 Mon Sep 17 00:00:00 2001
From: ZN <zhang_12370@163.com>
Date: 星期二, 17 三月 2026 17:36:13 +0800
Subject: [PATCH] feat(quality): 新增质量管理模块的API接口和移动端页面
---
src/pages/qualityManagement/visualization/qualityDashboard.vue | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 276 insertions(+), 0 deletions(-)
diff --git a/src/pages/qualityManagement/visualization/qualityDashboard.vue b/src/pages/qualityManagement/visualization/qualityDashboard.vue
new file mode 100644
index 0000000..d39e256
--- /dev/null
+++ b/src/pages/qualityManagement/visualization/qualityDashboard.vue
@@ -0,0 +1,276 @@
+<template>
+ <view class="quality-dashboard-page">
+ <PageHeader title="璐ㄩ噺鐪嬫澘" @back="goBack" />
+
+ <scroll-view scroll-y class="dashboard-scroll">
+ <!-- 鏍峰搧鐘舵�佸垪琛� -->
+ <view class="dashboard-card">
+ <view class="card-header">
+ <text class="card-title">妫�娴嬫牱鍝佸姩鎬佺姸鎬�</text>
+ <up-switch v-model="voiceEnabled" size="18" activeText="璇煶" inactiveText="闈欓煶"></up-switch>
+ </view>
+ <view class="status-list">
+ <view v-for="item in sampleStatus" :key="item.id" class="status-item">
+ <view class="status-left">
+ <view class="status-dot" :class="item.status"></view>
+ <text class="sample-name">{{ item.name }}</text>
+ </view>
+ <view class="status-right">
+ <up-tag :text="statusLabel(item.status)" :type="statusTagType(item.status)" size="mini"></up-tag>
+ <text class="sample-time">{{ item.time }}</text>
+ </view>
+ </view>
+ </view>
+ </view>
+
+ <!-- 鍚堟牸鐜囧垎鏋� (浠〃鐩�) -->
+ <view class="dashboard-card">
+ <view class="card-header">
+ <text class="card-title">鍚堟牸鐜囧垎鏋�</text>
+ </view>
+ <view class="chart-box">
+ <qiun-data-charts
+ type="gauge"
+ :opts="gaugeOpts"
+ :chartData="gaugeData"
+ />
+ </view>
+ <view class="passrate-summary">
+ <text>褰撳墠鍚堟牸鐜囷細</text>
+ <text class="highlight">{{ (passRate * 100).toFixed(1) }}%</text>
+ </view>
+ </view>
+
+ <!-- 浠诲姟鎺掕 (鏌辩姸鍥�) -->
+ <view class="dashboard-card">
+ <view class="card-header">
+ <text class="card-title">浠诲姟鎺掕 (Top 10)</text>
+ </view>
+ <view class="chart-box">
+ <qiun-data-charts
+ type="column"
+ :opts="columnOpts"
+ :chartData="columnData"
+ />
+ </view>
+ </view>
+
+ <!-- 鍘嗗彶瓒嬪娍 (鎶樼嚎鍥�) -->
+ <view class="dashboard-card">
+ <view class="card-header">
+ <text class="card-title">鍘嗗彶瓒嬪娍</text>
+ </view>
+ <view class="chart-box">
+ <qiun-data-charts
+ type="line"
+ :opts="lineOpts"
+ :chartData="lineData"
+ />
+ </view>
+ </view>
+ </scroll-view>
+ </view>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
+
+const voiceEnabled = ref(false);
+let dataTimer = null;
+
+// 1) 鏍峰搧鍔ㄦ�佺姸鎬�
+const sampleStatus = ref([]);
+const statusPool = ['processing', 'warning', 'error', 'success'];
+
+const statusLabel = (s) => {
+ const labels = { 'processing': '妫�娴嬩腑', 'warning': '棰勮', 'error': '涓嶅悎鏍�', 'success': '鍚堟牸' };
+ return labels[s] || '鏈煡';
+};
+
+const statusTagType = (s) => {
+ const types = { 'processing': 'primary', 'warning': 'warning', 'error': 'error', 'success': 'success' };
+ return types[s] || 'info';
+};
+
+const randomSample = () => {
+ const id = Math.random().toString(36).slice(2, 8);
+ const status = statusPool[Math.floor(Math.random() * statusPool.length)];
+ const name = `鏍峰搧-${Math.floor(Math.random() * 900 + 100)}`;
+ const time = new Date().toLocaleTimeString('zh-CN', { hour12: false });
+ return { id, name, status, time };
+};
+
+// 2) 鍚堟牸鐜囧垎鏋� (浠〃鐩�)
+const passRate = ref(0.92);
+const gaugeData = ref({
+ categories: [{ value: 0.92, color: "#2fc25b" }],
+ series: [{ name: "鍚堟牸鐜�", data: 0.92 }]
+});
+const gaugeOpts = {
+ title: { name: "鍚堟牸鐜�", color: "#2fc25b", fontSize: 16 },
+ subtitle: { name: "92%", color: "#666666", fontSize: 12 },
+ extra: { gauge: { type: "default", width: 15, labelColor: "#666666", splitLine: { fixRadius: -10 } } }
+};
+
+// 3) 浠诲姟鎺掕 (鏌辩姸鍥�)
+const columnData = ref({
+ categories: ["浠诲姟1", "浠诲姟2", "浠诲姟3", "浠诲姟4", "浠诲姟5"],
+ series: [{ name: "瀹屾垚鏁�", data: [35, 36, 31, 33, 13] }]
+});
+const columnOpts = {
+ color: ["#1890FF"],
+ padding: [15, 15, 0, 5],
+ enableScroll: false,
+ xAxis: { disableGrid: true },
+ yAxis: { data: [{ min: 0 }] },
+ extra: { column: { type: "group", width: 30, activeBgColor: "#000000", activeBgOpacity: 0.08 } }
+};
+
+// 4) 鍘嗗彶瓒嬪娍 (鎶樼嚎鍥�)
+const lineData = ref({
+ categories: ["10:00", "10:05", "10:10", "10:15", "10:20"],
+ series: [
+ { name: "鏉ユ牱鏁�", data: [35, 8, 25, 37, 4, 20] },
+ { name: "瀹屾垚鏁�", data: [70, 40, 65, 100, 44, 68] }
+ ]
+});
+const lineOpts = {
+ color: ["#1890FF", "#91CB74"],
+ padding: [15, 10, 0, 15],
+ enableScroll: false,
+ xAxis: { disableGrid: true },
+ yAxis: { gridType: "dash", dashLength: 2 },
+ legend: { position: "top" },
+ extra: { line: { type: "straight", width: 2 } }
+};
+
+const refreshData = () => {
+ // 妯℃嫙鏁版嵁鏇存柊
+ const next = randomSample();
+ sampleStatus.value = [next, ...sampleStatus.value].slice(0, 5);
+
+ const delta = (Math.random() - 0.5) * 0.02;
+ passRate.value = Math.min(0.99, Math.max(0.6, passRate.value + delta));
+ gaugeData.value = {
+ series: [{ name: "鍚堟牸鐜�", data: passRate.value }]
+ };
+ gaugeOpts.subtitle.name = (passRate.value * 100).toFixed(1) + '%';
+};
+
+const goBack = () => {
+ uni.navigateBack();
+};
+
+onMounted(() => {
+ for (let i = 0; i < 5; i++) {
+ sampleStatus.value.push(randomSample());
+ }
+ dataTimer = setInterval(refreshData, 3000);
+});
+
+onBeforeUnmount(() => {
+ if (dataTimer) clearInterval(dataTimer);
+});
+</script>
+
+<style lang="scss" scoped>
+.quality-dashboard-page {
+ background-color: #f5f7fa;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.dashboard-scroll {
+ flex: 1;
+ padding: 20rpx;
+}
+
+.dashboard-card {
+ background-color: #ffffff;
+ border-radius: 16rpx;
+ padding: 30rpx;
+ margin-bottom: 30rpx;
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 30rpx;
+ border-left: 8rpx solid #3c9cff;
+ padding-left: 20rpx;
+}
+
+.card-title {
+ font-size: 30rpx;
+ font-weight: bold;
+ color: #303133;
+}
+
+.status-list {
+ display: flex;
+ flex-direction: column;
+ gap: 20rpx;
+}
+
+.status-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10rpx 0;
+}
+
+.status-left {
+ display: flex;
+ align-items: center;
+ gap: 15rpx;
+}
+
+.status-dot {
+ width: 12rpx;
+ height: 12rpx;
+ border-radius: 50%;
+
+ &.processing { background-color: #3c9cff; }
+ &.warning { background-color: #f9ae3d; }
+ &.error { background-color: #f56c6c; }
+ &.success { background-color: #5ac725; }
+}
+
+.sample-name {
+ font-size: 28rpx;
+ color: #303133;
+}
+
+.status-right {
+ display: flex;
+ align-items: center;
+ gap: 20rpx;
+}
+
+.sample-time {
+ font-size: 24rpx;
+ color: #909399;
+}
+
+.chart-box {
+ width: 100%;
+ height: 400rpx;
+}
+
+.passrate-summary {
+ text-align: center;
+ margin-top: 20rpx;
+ font-size: 28rpx;
+ color: #606266;
+
+ .highlight {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: #3c9cff;
+ margin-left: 10rpx;
+ }
+}
+</style>
--
Gitblit v1.9.3