| | |
| | | <div class="warn-body"> |
| | | <div class="warn-list" role="list"> |
| | | <div v-for="item in warnings" :key="item.id" class="warn-item" role="listitem" @click="openWarning(item)"> |
| | | <div class="warn-tag" :class="tagClass(item.type)">{{ item.typeText }}</div> |
| | | <div class="warn-tag" :class="tagClass(item.type)">{{ item.parentProductTitle }}-{{ item.productTitle }} |
| | | </div> |
| | | <div class="warn-text" :title="item.title">{{ item.title }}</div> |
| | | <div class="warn-action" @click.stop="openWarning(item)">查看</div> |
| | | <div class="warn-date">{{ item.date }}</div> |
| | |
| | | <script setup> |
| | | import { computed, getCurrentInstance, ref, onMounted } from 'vue' |
| | | import Echarts from '@/components/Echarts/echarts.vue' |
| | | import { qualityUnqualifiedListPage } from '@/api/qualityManagement/nonconformingManagement.js' |
| | | import { nonComplianceWarning } from '@/api/viewIndex.js' |
| | | |
| | | const { proxy } = getCurrentInstance() || {} |
| | | |
| | | const warnings = ref([ |
| | | { id: '1', type: 'raw', typeText: '原材料', title: '关于企业原材料调整通知', date: '2024.08.24' }, |
| | | { id: '2', type: 'raw', typeText: '原材料', title: '关于原材料消耗方案建设的通知', date: '2024.08.24' }, |
| | | { id: '3', type: 'final', typeText: '成品', title: '成品工作台系统维护计划安排', date: '2024.08.24' }, |
| | | { id: '4', type: 'final', typeText: '成品', title: '成品工作台系统维护计划安排', date: '2024.08.24' }, |
| | | { id: '5', type: 'semi', typeText: '半成品', title: 'HRM系统安全升级公告:加强访问控制…', date: '2024.08.24' }, |
| | | { id: '6', type: 'semi', typeText: '半成品', title: 'HRM系统安全升级公告:加强访问控制…', date: '2024.08.24' }, |
| | | ]) |
| | | const warnings = ref([]) |
| | | |
| | | // 占比数据 |
| | | const ratios = ref({ |
| | | rawMaterialRatio: 0, |
| | | semiFinishedProductRatio: 0, |
| | | finishedProductRatio: 0, |
| | | }) |
| | | |
| | | const TAG_COLORS = { |
| | | raw: '#7C4DFF', |
| | |
| | | return 'tag-semi' |
| | | } |
| | | |
| | | // 根据productTitle映射类型 |
| | | const mapProductTitleToType = (productTitle) => { |
| | | if (productTitle === '原材料') return 'raw' |
| | | if (productTitle === '半成品') return 'semi' |
| | | if (productTitle === '成品') return 'final' |
| | | return 'raw' // 默认值 |
| | | } |
| | | |
| | | const pieChartStyle = { width: '100%', height: '100%' } |
| | | |
| | | const pieOptions = { |
| | |
| | | |
| | | const pieTooltip = { |
| | | trigger: 'item', |
| | | formatter: (p) => `${p.name}:${p.value}`, |
| | | formatter: (p) => `${p.name}:${p.value}%`, |
| | | } |
| | | |
| | | const pieData = computed(() => { |
| | | const counts = { raw: 0, final: 0, semi: 0 } |
| | | warnings.value.forEach((w) => { |
| | | const key = w.type in counts ? w.type : 'raw' |
| | | counts[key] += 1 |
| | | }) |
| | | return [ |
| | | { name: '原材料', value: counts.raw, itemStyle: { color: TAG_COLORS.raw } }, |
| | | { name: '半成品', value: counts.semi, itemStyle: { color: TAG_COLORS.semi } }, |
| | | { name: '成品', value: counts.final, itemStyle: { color: TAG_COLORS.final } }, |
| | | { name: '原材料', value: ratios.value.rawMaterialRatio, itemStyle: { color: TAG_COLORS.raw } }, |
| | | { name: '半成品', value: ratios.value.semiFinishedProductRatio, itemStyle: { color: TAG_COLORS.semi } }, |
| | | { name: '成品', value: ratios.value.finishedProductRatio, itemStyle: { color: TAG_COLORS.final } }, |
| | | ] |
| | | }) |
| | | |
| | |
| | | |
| | | const fetchWarnings = async () => { |
| | | try { |
| | | const res = await qualityUnqualifiedListPage({ pageNum: 1, pageSize: 6 }) |
| | | const rows = res?.rows || res?.data?.rows || res?.data || [] |
| | | if (!Array.isArray(rows) || rows.length === 0) return |
| | | const res = await nonComplianceWarning() |
| | | if (res?.code === 200 && res?.data) { |
| | | const data = res.data |
| | | |
| | | warnings.value = rows.slice(0, 6).map((r, idx) => { |
| | | const typeCode = r.inspectType ?? r.modelType ?? r.type |
| | | const mappedType = typeCode === 0 || typeCode === '0' ? 'raw' : typeCode === 1 || typeCode === '1' ? 'semi' : 'final' |
| | | const title = r.title || r.unqualifiedTitle || r.remark || r.unqualifiedReason || '不合格预警' |
| | | const date = (r.warningTime || r.createTime || r.updateTime || '').slice(0, 10).replace(/-/g, '.') || '2024.08.24' |
| | | // 更新占比数据 |
| | | ratios.value = { |
| | | rawMaterialRatio: data.rawMaterialRatio ?? 0, |
| | | semiFinishedProductRatio: data.semiFinishedProductRatio ?? 0, |
| | | finishedProductRatio: data.finishedProductRatio ?? 0, |
| | | } |
| | | |
| | | // 更新警告列表 |
| | | const children = data.children || [] |
| | | warnings.value = children.map((item, idx) => { |
| | | const type = mapProductTitleToType(item.parentProductTitle) |
| | | const date = item.date ? item.date.replace(/-/g, '.') : '' |
| | | return { |
| | | id: r.id ?? r.unqualifiedId ?? `${idx}`, |
| | | type: mappedType, |
| | | typeText: mappedType === 'raw' ? '原材料' : mappedType === 'semi' ? '半成品' : '成品', |
| | | title, |
| | | id: item.id ?? `warning-${idx}`, |
| | | type, |
| | | parentProductTitle: item.parentProductTitle || '原材料', |
| | | productTitle: item.productTitle || '原材料', |
| | | title: item.description || '不合格预警', |
| | | date, |
| | | } |
| | | }) |
| | | } |
| | | } catch (e) { |
| | | // 接口失败则保持 mock |
| | | // 接口失败则保持空数据 |
| | | console.error('获取不合格预警失败:', e) |
| | | } |
| | | } |
| | | |
| | | const openWarning = (item) => { |
| | | const title = `【${item.typeText}】${item.title}` |
| | | const content = `${title}时间:${item.date}` |
| | | const title = `【${item.parentProductTitle}-${item.productTitle}】${item.title}` |
| | | if (proxy?.$modal?.alert) { |
| | | proxy.$modal.alert(content) |
| | | proxy.$modal.alert(title) |
| | | return |
| | | } |
| | | // 兜底:没有全局 modal 时用 console |
| | |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | border-bottom: 1px solid; |
| | | border-image: linear-gradient( |
| | | 270deg, |
| | | border-image: linear-gradient(270deg, |
| | | rgba(0, 126, 255, 0) 0%, |
| | | rgba(0, 126, 255, 0.4549) 35%, |
| | | #007eff 78%, |
| | | #007eff 100% |
| | | ) |
| | | 1; |
| | | #007eff 100%) 1; |
| | | padding: 10px 0 6px; |
| | | } |
| | | |
| | |
| | | |
| | | .warn-item { |
| | | display: grid; |
| | | grid-template-columns: 88px 1fr auto 110px; |
| | | grid-template-columns: 130px 1fr auto 110px; |
| | | align-items: center; |
| | | gap: 12px; |
| | | color: #b8c8e0; |
| | | font-size: 14px; |
| | | line-height: 1; |
| | | padding: 6px 0; |
| | | line-height: 1.2; |
| | | padding: 8px 0; |
| | | border-radius: 4px; |
| | | transition: background-color 0.2s, color 0.2s; |
| | | } |