Pareto 分析

master
huangjinysf 3 months ago
parent 12560fb4a7
commit 32ab2ba2ee

@ -1,67 +1,5 @@
<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">
@ -73,6 +11,32 @@
v-hasPermi="['warehouse:WmsImportResult:add']"
>新增</el-button>
</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-button
type="success"
@ -105,68 +69,90 @@
<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>
<!-- 质检数据显示区域 -->
<el-row v-if="paretoData.length > 0" class="mb8">
<el-col :span="24">
<el-table :data="paretoData" border style="width: 100%" stripe>
<el-table-column prop="item_name" label="检测项" width="180" />
<el-table-column prop="defect_count" label="缺陷数" width="100" />
<el-table-column prop="defect_percentage" label="缺陷百分比" width="120">
<template #default="scope">
{{ scope.row.defect_percentage }}%
</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>
</el-table-column>
</el-table>
<div class="statistics-info">
<p>数据范围: {{ dateRange.start_date }} {{ dateRange.end_date }}</p>
<p>总计检测项: {{ paretoData.length }}</p>
</div>
</template>
<div style="margin-bottom: 10px;">
<el-button
type="success"
icon="ChatDotRound"
@click="handleAIAnalysis"
:loading="aiAnalysisLoading"
>
AI分析
</el-button>
</div>
</el-col>
</el-row>
<!-- AI分析结果对话框 -->
<el-dialog
v-model="aiDialogVisible"
title="AI分析结果"
width="60%"
:close-on-click-modal="false"
>
<div class="ai-analysis-content">
<el-input
v-model="aiAnalysisResult"
type="textarea"
:rows="15"
placeholder="AI分析结果将显示在这里"
readonly
/>
</div>
</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>
</template>
<script setup name="WmsImportResult">
import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
import { listWmsImportResult, getWmsImportResult, delWmsImportResult, addWmsImportResult, updateWmsImportResult } from "@/api/warehouse/WmsImportResult"
const { proxy } = getCurrentInstance()
@ -180,6 +166,24 @@ const single = ref(true)
const multiple = ref(true)
const total = ref(0)
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({
form: {},
@ -201,130 +205,133 @@ const data = reactive({
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() {
//
const endDate = new Date();
const startDate = new Date();
if (queryForm.value.selectedTimeRange === '近1年') {
startDate.setFullYear(endDate.getFullYear() - 1);
} else if (queryForm.value.selectedTimeRange === '近2年') {
startDate.setFullYear(endDate.getFullYear() - 2);
} else if (queryForm.value.selectedTimeRange === '近3年') {
startDate.setFullYear(endDate.getFullYear() - 3);
}
// YYYY-MM-DD
const formatDate = (date) => {
const year = date.getFullYear();
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);
const endDateStr = formatDate(endDate);
console.log(startDateStr, endDateStr);
// API
fetch(`http://192.168.110.38:8100/api/qc/pareto?start_date=${startDateStr}&end_date=${endDateStr}`)
.then(response => response.json())
.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 cancel() {
open.value = false
reset()
// getList()
//
function getProgressColor(percentage) {
if (percentage >= 30) return '#f56c6c'; // -
if (percentage >= 15) return '#e6a23c'; // -
if (percentage >= 5) return '#409eff'; // -
return '#67c23a'; // 绿 -
}
//
function reset() {
form.value = {
model: null,
specification: null,
wireDisc: null,
totalNumber: null,
totalNetWeight: null,
totalGrossWeight: null,
type: null,
warningValue: null,
updateTime: null
// AI
async function handleAIAnalysis() {
if (paretoData.value.length === 0) {
message.value = '请先获取帕累托分析数据'
return
}
proxy.resetForm("WmsImportResultRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
aiAnalysisLoading.value = true
aiDialogVisible.value = true
aiAnalysisResult.value = '正在分析中,请稍候...'
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
try {
//
const prompt = `请分析以下帕累托分析数据,提供专业的质量控制见解:
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.model)
single.value = selection.length != 1
multiple.value = !selection.length
}
数据范围: ${dateRange.value.start_date} ${dateRange.value.end_date}
检测项目总数: ${paretoData.value.length}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加成品查询结果(数据同步)"
}
详细数据:
${paretoData.value.map(item =>
`- ${item.item_name}: 缺陷数 ${item.defect_count}, 缺陷占比 ${item.defect_percentage}%, 累计占比 ${item.cumulative_percentage}%`
).join('\n')}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
// model specification
const params = {
model: row.model,
specification: row.specification,
//
pageNum: 1,
pageSize: 1 //
}
请从以下角度进行分析
1. 主要缺陷项及其影响程度
2. 帕累托原理(80/20法则)在此数据中的体现
3. 针对高缺陷率项的改进建议
4. 质量控制重点优化方向`
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("查询失败")
})
}
// 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
})
})
/** 提交按钮 */
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()
})
}
if (!response.ok) {
throw new Error(`API调用失败: ${response.status}`)
}
})
}
/** 删除按钮操作 */
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`)
const data = await response.json()
const analysisResult = data.choices[0].message.content
aiAnalysisResult.value = analysisResult
//
message.value = analysisResult
} catch (error) {
console.error('AI分析失败:', error)
aiAnalysisResult.value = `AI分析失败: ${error.message}\n\n请检查网络连接或稍后再试。`
} finally {
aiAnalysisLoading.value = false
}
}
getList()
</script>
<style>
@ -336,4 +343,19 @@ top: 40%;
left: 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>

@ -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 }}
</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>
<el-table
@ -55,22 +87,20 @@
width="100"
align="center"
>
<!-- <template #default="scope">-->
<template #default="scope">
<span>
{{ showDiff
? (matrixDiff[scope.$index]?.[colIndex] === 0 ? '' : matrixDiff[scope.$index]?.[colIndex] ?? '')
: matrix[scope.$index]?.[colIndex] ?? '' }}
</span>
</template>
<!-- </template>-->
<template #default="scope">
<span>
{{ showDiff
? (matrixDiff[scope.$index]?.[colIndex] === 0 ? '' : matrixDiff[scope.$index]?.[colIndex] ?? '')
: matrix[scope.$index]?.[colIndex] ?? '' }}
</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ref, onMounted, watch } from 'vue'
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',
'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',
'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'
])
@ -107,27 +137,54 @@ const updateTimes = 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 baseMatrix = ref([])
const showDiff = ref(false) // toggle
//
const nonZeroDiffCount = ref(0);
// matrixDiff
//
const nonZeroDiffCount = ref(0)
//
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) {
let count = 0;
matrixDiff.forEach(row => {
row.forEach(val => {
let nonZeroCount = 0
let positiveCount = 0
let negativeCount = 0
const positiveList = []
const negativeList = []
matrixDiff.forEach((row, rowIndex) => {
row.forEach((val, colIndex) => {
if (val !== '' && val !== 0 && !isNaN(val)) {
count++;
nonZeroCount++
const diffItem = {
specification: specifications.value[rowIndex],
model: modelWireDiscs.value[colIndex],
value: val
}
if (val > 0) {
positiveCount++
positiveList.push(diffItem)
} else if (val < 0) {
negativeCount++
negativeList.push(diffItem)
}
}
});
});
return count;
}
})
})
positiveDiffList.value = positiveList
negativeDiffList.value = negativeList
return { nonZeroCount, positiveCount, negativeCount }
}
watch(selectedUpdateTime, async (newTime) => {
if (!newTime) return
@ -138,15 +195,13 @@ watch(selectedUpdateTime, async (newTime) => {
type: 1,
pageNum: 1,
pageSize: 999,
updateTime: basetime.value,
});
console.log('New date',(basetime.value))
updateTime: basetime.value,
})
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) =>
row.map((val, j) => {
@ -156,11 +211,19 @@ watch(selectedUpdateTime, async (newTime) => {
return isNaN(diff) ? '' : diff
})
)
// console.log(matrixDiff)
//
nonZeroDiffCount.value = calculateNonZeroDiffCount(matrixDiff.value);
const counts = 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) {
const newMatrix = Array(specifications.value.length).fill().map(() =>
Array(modelWireDiscs.value.length).fill('')
@ -181,38 +244,32 @@ function transformToMatrix(rawData) {
function generateUpdateTimes() {
const times = []
const now = new Date()
const currentMinutes = now.getMinutes();
const currentMinutes = now.getMinutes()
if (currentMinutes >= 42) { // 42
now.setMinutes(41); // 41
} else if (currentMinutes >= 11) { // 11
now.setMinutes(11); // 11
if (currentMinutes >= 42) {
now.setMinutes(41)
} else if (currentMinutes >= 11) {
now.setMinutes(11)
} else {
now.setHours(now.getHours() - 1); // 1141
now.setMinutes(41); // 41
now.setHours(now.getHours() - 1)
now.setMinutes(41)
}
now.setSeconds(0)
now.setMilliseconds(0)
// 4830Date
// 3030
// 'YYYY-MM-DD HH:MM:00'
// times
for (let i = 0; i < 48; i++) {
const time = new Date(now.getTime() - i * 30 * 60 * 1000) // 301141
const hours = String(time.getHours()).padStart(2, '0') // '09' '15'
const minutes = String(time.getMinutes()).padStart(2, '0') // '11' '41'
const formatted = `${time.getFullYear()}-${String(time.getMonth() + 1).padStart(2, '0')}-${String(time.getDate()).padStart(2, '0')} ${hours}:${minutes}:00` //
times.push(formatted) //
const time = new Date(now.getTime() - i * 30 * 60 * 1000)
const hours = String(time.getHours()).padStart(2, '0')
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`
times.push(formatted)
}
return times
}
function transformData(rawData) {
matrix.value = transformToMatrix(rawData)
tableData.value = specifications.value.map((spec, index) => ({
specification: spec,
rowIndex: index
@ -229,8 +286,7 @@ async function fetchData() {
}
if (selectedUpdateTime.value) {
query.updateTime = selectedUpdateTime.value;
// console.log('Query object:', query);
query.updateTime = selectedUpdateTime.value
}
const response = await listWmsImportResultHistory(query)
@ -244,7 +300,6 @@ async function fetchData() {
//
function handleTimeChange() {
fetchData()
}

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

Loading…
Cancel
Save