Pareto 分析

master
huangjinysf 3 months ago
parent 12560fb4a7
commit 32ab2ba2ee

@ -1,67 +1,5 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="型号" prop="model">
<el-input
v-model="queryParams.model"
placeholder="请输入型号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="规格" prop="specification">
<el-input
v-model="queryParams.specification"
placeholder="请输入规格"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="轴型" prop="wireDisc">
<el-input
v-model="queryParams.wireDisc"
placeholder="请输入轴型"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总数量" prop="totalNumber">
<el-input
v-model="queryParams.totalNumber"
placeholder="请输入总数量"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总净重" prop="totalNetWeight">
<el-input
v-model="queryParams.totalNetWeight"
placeholder="请输入总净重"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总毛重" prop="totalGrossWeight">
<el-input
v-model="queryParams.totalGrossWeight"
placeholder="请输入总毛重"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="警戒值" prop="warningValue">
<el-input
v-model="queryParams.warningValue"
placeholder="请输入警戒值"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
@ -73,6 +11,32 @@
v-hasPermi="['warehouse:WmsImportResult:add']" v-hasPermi="['warehouse:WmsImportResult:add']"
>新增</el-button> >新增</el-button>
</el-col> </el-col>
<el-col :span="3">
<el-form :model="queryForm" label-width="80px">
<el-form-item label="数据范围">
<el-select v-model="queryForm.selectedTimeRange" placeholder="选择时间范围" style="width: 100%">
<el-option
v-for="item in timeRangeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
</el-col>
<el-col :span="1.5">
<el-button
type="primary"
plain
@click="handleMinus"
v-hasPermi="['warehouse:WmsImportResult:add']"
>帕累托分析</el-button>
</el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
type="success" type="success"
@ -105,68 +69,90 @@
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="WmsImportResultList" @selection-change="handleSelectionChange"> <!-- 质检数据显示区域 -->
<el-table-column type="selection" width="55" align="center" /> <el-row v-if="paretoData.length > 0" class="mb8">
<el-table-column label="型号" align="center" prop="model" /> <el-col :span="24">
<el-table-column label="规格" align="center" prop="specification" />
<el-table-column label="轴型" align="center" prop="wireDisc" />
<el-table-column label="总数量" align="center" prop="totalNumber" /> <el-table :data="paretoData" border style="width: 100%" stripe>
<el-table-column label="总净重" align="center" prop="totalNetWeight" /> <el-table-column prop="item_name" label="检测项" width="180" />
<el-table-column label="总毛重" align="center" prop="totalGrossWeight" /> <el-table-column prop="defect_count" label="缺陷数" width="100" />
<el-table-column label="类型" align="center" prop="type" /> <el-table-column prop="defect_percentage" label="缺陷百分比" width="120">
<el-table-column label="警戒值" align="center" prop="warningValue" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['warehouse:WmsImportResult:edit']"></el-button> {{ scope.row.defect_percentage }}%
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['warehouse:WmsImportResult:remove']"></el-button> </template>
</el-table-column>
<el-table-column prop="cumulative_percentage" label="累计百分比" width="120">
<template #default="scope">
{{ scope.row.cumulative_percentage }}%
</template>
</el-table-column>
<el-table-column label="缺陷占比">
<template #default="scope">
<el-progress
:percentage="scope.row.defect_percentage"
:show-text="false"
:color="getProgressColor(scope.row.defect_percentage)"
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="statistics-info">
<p>数据范围: {{ dateRange.start_date }} {{ dateRange.end_date }}</p>
<p>总计检测项: {{ paretoData.length }}</p>
</div>
<pagination <div style="margin-bottom: 10px;">
v-show="total>0" <el-button
:total="total" type="success"
v-model:page="queryParams.pageNum" icon="ChatDotRound"
v-model:limit="queryParams.pageSize" @click="handleAIAnalysis"
@pagination="getList" :loading="aiAnalysisLoading"
/> >
AI分析
</el-button>
</div>
<!-- 添加或修改成品查询结果(数据同步)对话框 --> </el-col>
<el-dialog :title="title" v-model="open" width="500px" append-to-body align-center> </el-row>
<el-form ref="WmsImportResultRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="型号" prop="model"> <!-- AI分析结果对话框 -->
<el-input v-model="form.model" placeholder="请输入型号" /> <el-dialog
</el-form-item> v-model="aiDialogVisible"
<el-form-item label="规格" prop="specification"> title="AI分析结果"
<el-input v-model="form.specification" placeholder="请输入规格" /> width="60%"
</el-form-item> :close-on-click-modal="false"
<el-form-item label="轴型" prop="wireDisc"> >
<el-input v-model="form.wireDisc" placeholder="请输入轴型" /> <div class="ai-analysis-content">
</el-form-item> <el-input
<el-form-item label="总数量" prop="totalNumber"> v-model="aiAnalysisResult"
<el-input v-model="form.totalNumber" placeholder="请输入总数量" /> type="textarea"
</el-form-item> :rows="15"
<el-form-item label="总净重" prop="totalNetWeight"> placeholder="AI分析结果将显示在这里"
<el-input v-model="form.totalNetWeight" placeholder="请输入总净重" /> readonly
</el-form-item> />
<el-form-item label="总毛重" prop="totalGrossWeight">
<el-input v-model="form.totalGrossWeight" placeholder="请输入总毛重" />
</el-form-item>
<el-form-item label="警戒值" prop="warningValue">
<el-input v-model="form.warningValue" placeholder="请输入警戒值" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div> </div>
</template>
</el-dialog> </el-dialog>
<!-- 消息显示文本框 -->
<el-row>
<el-col :span="24">
<el-input
v-model="message"
type="textarea"
:rows="6"
placeholder="API返回的消息将显示在这里"
clearable
/>
</el-col>
</el-row>
</div> </div>
</template> </template>
<script setup name="WmsImportResult"> <script setup name="WmsImportResult">
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
import { listWmsImportResult, getWmsImportResult, delWmsImportResult, addWmsImportResult, updateWmsImportResult } from "@/api/warehouse/WmsImportResult" import { listWmsImportResult, getWmsImportResult, delWmsImportResult, addWmsImportResult, updateWmsImportResult } from "@/api/warehouse/WmsImportResult"
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
@ -180,6 +166,24 @@ const single = ref(true)
const multiple = ref(true) const multiple = ref(true)
const total = ref(0) const total = ref(0)
const title = ref("") const title = ref("")
const message = ref("")
const selectedTimeRange = ref("近1年")
const timeRangeOptions = ref([
{ value: "近1年", label: "近1年" },
{ value: "近2年", label: "近2年" },
{ value: "近3年", label: "近3年" }
])
const queryForm = ref({
selectedTimeRange: "近1年"
})
const paretoData = ref([])
const dateRange = ref({
start_date: '',
end_date: ''
})
const aiDialogVisible = ref(false)
const aiAnalysisResult = ref("")
const aiAnalysisLoading = ref(false)
const data = reactive({ const data = reactive({
form: {}, form: {},
@ -201,130 +205,133 @@ const data = reactive({
const { queryParams, form, rules } = toRefs(data) const { queryParams, form, rules } = toRefs(data)
/** 查询成品查询结果(数据同步)列表 */
function getList() {
loading.value = true
// console.log(queryParams)
listWmsImportResult(queryParams.value).then(response => {
WmsImportResultList.value = response.rows
total.value = response.total
loading.value = false
})
}
// function handleMinus() {
function cancel() { //
open.value = false const endDate = new Date();
reset() const startDate = new Date();
}
// if (queryForm.value.selectedTimeRange === '近1年') {
function reset() { startDate.setFullYear(endDate.getFullYear() - 1);
form.value = { } else if (queryForm.value.selectedTimeRange === '近2年') {
model: null, startDate.setFullYear(endDate.getFullYear() - 2);
specification: null, } else if (queryForm.value.selectedTimeRange === '近3年') {
wireDisc: null, startDate.setFullYear(endDate.getFullYear() - 3);
totalNumber: null,
totalNetWeight: null,
totalGrossWeight: null,
type: null,
warningValue: null,
updateTime: null
} }
proxy.resetForm("WmsImportResultRef")
}
/** 搜索按钮操作 */ // YYYY-MM-DD
function handleQuery() { const formatDate = (date) => {
queryParams.value.pageNum = 1 const year = date.getFullYear();
getList() const month = String(date.getMonth() + 1).padStart(2, '0');
} const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
/** 重置按钮操作 */ const startDateStr = formatDate(startDate);
function resetQuery() { const endDateStr = formatDate(endDate);
proxy.resetForm("queryRef")
handleQuery()
}
// console.log(startDateStr, endDateStr);
function handleSelectionChange(selection) { // API
ids.value = selection.map(item => item.model) fetch(`http://192.168.110.38:8100/api/qc/pareto?start_date=${startDateStr}&end_date=${endDateStr}`)
single.value = selection.length != 1 .then(response => response.json())
multiple.value = !selection.length .then(data => {
message.value = data.message || `质检数据获取成功 (${queryForm.value.selectedTimeRange})`
//
if (data.code === 200 && data.data) {
paretoData.value = data.data;
dateRange.value = {
start_date: data.start_date,
end_date: data.end_date
};
}
})
.catch(error => {
console.error('质检API调用失败:', error)
message.value = '质检API调用失败'
})
} }
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加成品查询结果(数据同步)"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
// model specification
const params = {
model: row.model,
specification: row.specification,
//
pageNum: 1,
pageSize: 1 //
}
listWmsImportResult(params).then(response => { // getList()
if (response.rows && response.rows.length > 0) { //
form.value = response.rows[0] // function getProgressColor(percentage) {
open.value = true if (percentage >= 30) return '#f56c6c'; // -
title.value = "修改成品查询结果(数据同步)" if (percentage >= 15) return '#e6a23c'; // -
} else { if (percentage >= 5) return '#409eff'; // -
proxy.$modal.msgError("未找到对应数据") return '#67c23a'; // 绿 -
}
}).catch(error => {
proxy.$modal.msgError("查询失败")
})
} }
/** 提交按钮 */ // AI
function submitForm() { async function handleAIAnalysis() {
proxy.$refs["WmsImportResultRef"].validate(valid => { if (paretoData.value.length === 0) {
if (valid) { message.value = '请先获取帕累托分析数据'
if (form.value.model != null) { return
updateWmsImportResult(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addWmsImportResult(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
} }
aiAnalysisLoading.value = true
aiDialogVisible.value = true
aiAnalysisResult.value = '正在分析中,请稍候...'
try {
//
const prompt = `请分析以下帕累托分析数据,提供专业的质量控制见解:
数据范围: ${dateRange.value.start_date} ${dateRange.value.end_date}
检测项目总数: ${paretoData.value.length}
详细数据:
${paretoData.value.map(item =>
`- ${item.item_name}: 缺陷数 ${item.defect_count}, 缺陷占比 ${item.defect_percentage}%, 累计占比 ${item.cumulative_percentage}%`
).join('\n')}
请从以下角度进行分析
1. 主要缺陷项及其影响程度
2. 帕累托原理(80/20法则)在此数据中的体现
3. 针对高缺陷率项的改进建议
4. 质量控制重点优化方向`
// DeepSeek API
const response = await fetch('https://api.deepseek.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer sk-4fa66e674e57479d961e4ad2036cbc52`
},
body: JSON.stringify({
model: 'deepseek-chat',
messages: [
{
role: 'system',
content: '你是一位专业的质量控制专家,擅长分析缺陷数据并提供专业的改进建议。'
},
{
role: 'user',
content: prompt
} }
],
temperature: 0.7,
max_tokens: 1500
})
}) })
}
/** 删除按钮操作 */ if (!response.ok) {
function handleDelete(row) { throw new Error(`API调用失败: ${response.status}`)
const _models = row.model || ids.value }
proxy.$modal.confirm('是否确认删除成品查询结果(数据同步)编号为"' + _models + '"的数据项?').then(function() {
return delWmsImportResult(_models)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */ const data = await response.json()
function handleExport() { const analysisResult = data.choices[0].message.content
proxy.download('warehouse/WmsImportResult/export', { aiAnalysisResult.value = analysisResult
...queryParams.value //
}, `WmsImportResult_${new Date().getTime()}.xlsx`) message.value = analysisResult
} catch (error) {
console.error('AI分析失败:', error)
aiAnalysisResult.value = `AI分析失败: ${error.message}\n\n请检查网络连接或稍后再试。`
} finally {
aiAnalysisLoading.value = false
}
} }
getList()
</script> </script>
<style> <style>
@ -336,4 +343,19 @@ top: 40%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
.statistics-info {
margin-top: 10px;
padding: 10px;
background-color: #f5f7fa;
border-radius: 4px;
}
.statistics-info p {
margin: 5px 0;
font-size: 14px;
}
.ai-analysis-content {
padding: 10px 0;
}
</style> </style>

@ -0,0 +1,341 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="型号" prop="model">
<el-input
v-model="queryParams.model"
placeholder="请输入型号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="规格" prop="specification">
<el-input
v-model="queryParams.specification"
placeholder="请输入规格"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="轴型" prop="wireDisc">
<el-input
v-model="queryParams.wireDisc"
placeholder="请输入轴型"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总数量" prop="totalNumber">
<el-input
v-model="queryParams.totalNumber"
placeholder="请输入总数量"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总净重" prop="totalNetWeight">
<el-input
v-model="queryParams.totalNetWeight"
placeholder="请输入总净重"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="总毛重" prop="totalGrossWeight">
<el-input
v-model="queryParams.totalGrossWeight"
placeholder="请输入总毛重"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="警戒值" prop="warningValue">
<el-input
v-model="queryParams.warningValue"
placeholder="请输入警戒值"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['warehouse:WmsImportResult:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['warehouse:WmsImportResult:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['warehouse:WmsImportResult:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['warehouse:WmsImportResult:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="WmsImportResultList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="型号" align="center" prop="model" />
<el-table-column label="规格" align="center" prop="specification" />
<el-table-column label="轴型" align="center" prop="wireDisc" />
<el-table-column label="总数量" align="center" prop="totalNumber" />
<el-table-column label="总净重" align="center" prop="totalNetWeight" />
<el-table-column label="总毛重" align="center" prop="totalGrossWeight" />
<el-table-column label="类型" align="center" prop="type" />
<el-table-column label="警戒值" align="center" prop="warningValue" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['warehouse:WmsImportResult:edit']"></el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['warehouse:WmsImportResult:remove']"></el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改成品查询结果(数据同步)对话框 -->
<el-dialog :title="title" v-model="open" width="500px" append-to-body align-center>
<el-form ref="WmsImportResultRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="型号" prop="model">
<el-input v-model="form.model" placeholder="请输入型号" />
</el-form-item>
<el-form-item label="规格" prop="specification">
<el-input v-model="form.specification" placeholder="请输入规格" />
</el-form-item>
<el-form-item label="轴型" prop="wireDisc">
<el-input v-model="form.wireDisc" placeholder="请输入轴型" />
</el-form-item>
<el-form-item label="总数量" prop="totalNumber">
<el-input v-model="form.totalNumber" placeholder="请输入总数量" />
</el-form-item>
<el-form-item label="总净重" prop="totalNetWeight">
<el-input v-model="form.totalNetWeight" placeholder="请输入总净重" />
</el-form-item>
<el-form-item label="总毛重" prop="totalGrossWeight">
<el-input v-model="form.totalGrossWeight" placeholder="请输入总毛重" />
</el-form-item>
<el-form-item label="警戒值" prop="warningValue">
<el-input v-model="form.warningValue" placeholder="请输入警戒值" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="WmsImportResult">
import { listWmsImportResult, getWmsImportResult, delWmsImportResult, addWmsImportResult, updateWmsImportResult } from "@/api/warehouse/WmsImportResult"
const { proxy } = getCurrentInstance()
const WmsImportResultList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
model: null,
specification: null,
wireDisc: null,
totalNumber: null,
totalNetWeight: null,
totalGrossWeight: null,
type: 1,
warningValue: null,
},
rules: {
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询成品查询结果(数据同步)列表 */
function getList() {
loading.value = true
// console.log(queryParams)
listWmsImportResult(queryParams.value).then(response => {
WmsImportResultList.value = response.rows
total.value = response.total
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
model: null,
specification: null,
wireDisc: null,
totalNumber: null,
totalNetWeight: null,
totalGrossWeight: null,
type: null,
warningValue: null,
updateTime: null
}
proxy.resetForm("WmsImportResultRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.model)
single.value = selection.length != 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加成品查询结果(数据同步)"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
// model specification
const params = {
model: row.model,
specification: row.specification,
//
pageNum: 1,
pageSize: 1 //
}
listWmsImportResult(params).then(response => {
if (response.rows && response.rows.length > 0) {
form.value = response.rows[0] //
open.value = true
title.value = "修改成品查询结果(数据同步)"
} else {
proxy.$modal.msgError("未找到对应数据")
}
}).catch(error => {
proxy.$modal.msgError("查询失败")
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["WmsImportResultRef"].validate(valid => {
if (valid) {
if (form.value.model != null) {
updateWmsImportResult(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addWmsImportResult(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _models = row.model || ids.value
proxy.$modal.confirm('是否确认删除成品查询结果(数据同步)编号为"' + _models + '"的数据项?').then(function() {
return delWmsImportResult(_models)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('warehouse/WmsImportResult/export', {
...queryParams.value
}, `WmsImportResult_${new Date().getTime()}.xlsx`)
}
getList()
</script>
<style>
/* 在全局样式文件中添加 */
.el-dialog {
margin-top: 0 !important;
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

@ -29,7 +29,39 @@
非零差值总数: {{ nonZeroDiffCount }} 非零差值总数: {{ nonZeroDiffCount }}
</span> </span>
<span style="margin-left: 20px">
正差值总数: {{ positiveDiffCount }}
<el-select
v-model="selectedPositiveDiff"
placeholder="查看正差值详情"
style="width: 300px; margin-left: 10px"
:disabled="positiveDiffCount === 0"
>
<el-option
v-for="(item, index) in positiveDiffList"
:key="index"
:label="`Spec: ${item.specification}, Model: ${item.model}, Value: ${item.value}`"
:value="index"
/>
</el-select>
</span>
<span style="margin-left: 20px">
负差值总数: {{ negativeDiffCount }}
<el-select
v-model="selectedNegativeDiff"
placeholder="查看负差值详情"
style="width: 300px; margin-left: 10px"
:disabled="negativeDiffCount === 0"
>
<el-option
v-for="(item, index) in negativeDiffList"
:key="index"
:label="`Spec: ${item.specification}, Model: ${item.model}, Value: ${item.value}`"
:value="index"
/>
</el-select>
</span>
</div> </div>
<el-table <el-table
@ -55,7 +87,6 @@
width="100" width="100"
align="center" align="center"
> >
<!-- <template #default="scope">-->
<template #default="scope"> <template #default="scope">
<span> <span>
{{ showDiff {{ showDiff
@ -63,14 +94,13 @@
: matrix[scope.$index]?.[colIndex] ?? '' }} : matrix[scope.$index]?.[colIndex] ?? '' }}
</span> </span>
</template> </template>
<!-- </template>-->
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted, watch } from 'vue'
import { listWmsImportResultHistory } from "@/api/system/WmsImportResultHistory" import { listWmsImportResultHistory } from "@/api/system/WmsImportResultHistory"
// //
@ -86,7 +116,7 @@ const specifications = ref([
'0.900', '0.930', '0.950', '1.000', '1.040', '1.060', '1.160', '1.180', '0.900', '0.930', '0.950', '1.000', '1.040', '1.060', '1.160', '1.180',
'1.200', '1.250', '1.300', '1.350', '1.400', '1.450', '1.200', '1.250', '1.300', '1.350', '1.400', '1.450',
'1.500', '1.560', '1.600', '1.680', '1.700', '1.740', '1.800', '1.900', '1.500', '1.560', '1.600', '1.680', '1.700', '1.740', '1.800', '1.900',
'2.000', '2.120', '2.165', '2.240', '2.360', '2.400', '2.500', '2.000', '2.000', '2.120', '2.165', '2.240', '2.360', '2.400', '2.500', '2.600',
'3.000' '3.000'
]) ])
@ -107,27 +137,54 @@ const updateTimes = ref([])
// //
const selectedUpdateTime = ref('') const selectedUpdateTime = ref('')
const basetime = ref('2025-06-26 09:11:00') const basetime = ref('2025-07-02 09:11:00')
const matrixDiff = ref([]) const matrixDiff = ref([])
const baseMatrix = ref([]) const baseMatrix = ref([])
const showDiff = ref(false) // toggle const showDiff = ref(false) // toggle
// //
const nonZeroDiffCount = ref(0); const nonZeroDiffCount = ref(0)
//
// matrixDiff const positiveDiffCount = ref(0)
const positiveDiffList = ref([])
const selectedPositiveDiff = ref(null) //
//
const negativeDiffCount = ref(0)
const negativeDiffList = ref([])
const selectedNegativeDiff = ref(null) //
// matrixDiff
function calculateNonZeroDiffCount(matrixDiff) { function calculateNonZeroDiffCount(matrixDiff) {
let count = 0; let nonZeroCount = 0
matrixDiff.forEach(row => { let positiveCount = 0
row.forEach(val => { let negativeCount = 0
const positiveList = []
const negativeList = []
matrixDiff.forEach((row, rowIndex) => {
row.forEach((val, colIndex) => {
if (val !== '' && val !== 0 && !isNaN(val)) { if (val !== '' && val !== 0 && !isNaN(val)) {
count++; nonZeroCount++
const diffItem = {
specification: specifications.value[rowIndex],
model: modelWireDiscs.value[colIndex],
value: val
} }
}); if (val > 0) {
}); positiveCount++
return count; positiveList.push(diffItem)
} } else if (val < 0) {
negativeCount++
negativeList.push(diffItem)
}
}
})
})
positiveDiffList.value = positiveList
negativeDiffList.value = negativeList
return { nonZeroCount, positiveCount, negativeCount }
}
watch(selectedUpdateTime, async (newTime) => { watch(selectedUpdateTime, async (newTime) => {
if (!newTime) return if (!newTime) return
@ -139,14 +196,12 @@ watch(selectedUpdateTime, async (newTime) => {
pageNum: 1, pageNum: 1,
pageSize: 999, pageSize: 999,
updateTime: basetime.value, updateTime: basetime.value,
}); })
console.log('New date',(basetime.value))
if (response.rows) { if (response.rows) {
baseMatrix.value = transformToMatrix(response.rows); baseMatrix.value = transformToMatrix(response.rows)
} }
// console.log('basematrix',baseMatrix)
// console.log('matrix',matrix)
// //
matrixDiff.value = matrix.value.map((row, i) => matrixDiff.value = matrix.value.map((row, i) =>
row.map((val, j) => { row.map((val, j) => {
@ -156,11 +211,19 @@ watch(selectedUpdateTime, async (newTime) => {
return isNaN(diff) ? '' : diff return isNaN(diff) ? '' : diff
}) })
) )
// console.log(matrixDiff)
// const counts = calculateNonZeroDiffCount(matrixDiff.value)
nonZeroDiffCount.value = calculateNonZeroDiffCount(matrixDiff.value); nonZeroDiffCount.value = counts.nonZeroCount
positiveDiffCount.value = counts.positiveCount
negativeDiffCount.value = counts.negativeCount
}) })
/**
* 将原始数据转换为矩阵格式
*
* @param rawData 原始数据数组每个元素包含 modelwireDiscspecification totalNumber 属性
* @returns 转换后的矩阵矩阵的行数等于 specifications.value 的长度列数等于 modelWireDiscs.value 的长度
*/
function transformToMatrix(rawData) { function transformToMatrix(rawData) {
const newMatrix = Array(specifications.value.length).fill().map(() => const newMatrix = Array(specifications.value.length).fill().map(() =>
Array(modelWireDiscs.value.length).fill('') Array(modelWireDiscs.value.length).fill('')
@ -181,38 +244,32 @@ function transformToMatrix(rawData) {
function generateUpdateTimes() { function generateUpdateTimes() {
const times = [] const times = []
const now = new Date() const now = new Date()
const currentMinutes = now.getMinutes(); const currentMinutes = now.getMinutes()
if (currentMinutes >= 42) {
if (currentMinutes >= 42) { // 42 now.setMinutes(41)
now.setMinutes(41); // 41 } else if (currentMinutes >= 11) {
} else if (currentMinutes >= 11) { // 11 now.setMinutes(11)
now.setMinutes(11); // 11
} else { } else {
now.setHours(now.getHours() - 1); // 1141 now.setHours(now.getHours() - 1)
now.setMinutes(41); // 41 now.setMinutes(41)
} }
now.setSeconds(0) now.setSeconds(0)
now.setMilliseconds(0) now.setMilliseconds(0)
// 4830Date
// 3030
// 'YYYY-MM-DD HH:MM:00'
// times
for (let i = 0; i < 48; i++) { for (let i = 0; i < 48; i++) {
const time = new Date(now.getTime() - i * 30 * 60 * 1000) // 301141 const time = new Date(now.getTime() - i * 30 * 60 * 1000)
const hours = String(time.getHours()).padStart(2, '0') // '09' '15' const hours = String(time.getHours()).padStart(2, '0')
const minutes = String(time.getMinutes()).padStart(2, '0') // '11' '41' const minutes = String(time.getMinutes()).padStart(2, '0')
const formatted = `${time.getFullYear()}-${String(time.getMonth() + 1).padStart(2, '0')}-${String(time.getDate()).padStart(2, '0')} ${hours}:${minutes}:00` // const formatted = `${time.getFullYear()}-${String(time.getMonth() + 1).padStart(2, '0')}-${String(time.getDate()).padStart(2, '0')} ${hours}:${minutes}:00`
times.push(formatted) // times.push(formatted)
} }
return times return times
} }
function transformData(rawData) { function transformData(rawData) {
matrix.value = transformToMatrix(rawData) matrix.value = transformToMatrix(rawData)
tableData.value = specifications.value.map((spec, index) => ({ tableData.value = specifications.value.map((spec, index) => ({
specification: spec, specification: spec,
rowIndex: index rowIndex: index
@ -229,8 +286,7 @@ async function fetchData() {
} }
if (selectedUpdateTime.value) { if (selectedUpdateTime.value) {
query.updateTime = selectedUpdateTime.value; query.updateTime = selectedUpdateTime.value
// console.log('Query object:', query);
} }
const response = await listWmsImportResultHistory(query) const response = await listWmsImportResultHistory(query)
@ -244,7 +300,6 @@ async function fetchData() {
// //
function handleTimeChange() { function handleTimeChange() {
fetchData() fetchData()
} }

@ -2,7 +2,7 @@ import { defineConfig, loadEnv } from 'vite'
import path from 'path' import path from 'path'
import createVitePlugins from './vite/plugins' import createVitePlugins from './vite/plugins'
const baseUrl = 'http://localhost:8080' // 后端接口 const baseUrl = 'http://localhost:8085' // 后端接口
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => { export default defineConfig(({ mode, command }) => {

Loading…
Cancel
Save