feat(renderer): 新增方案管理功能并优化界面
- 新增方案复制、导入、导出功能 - 添加错误日志展示 - 优化方案配置界面布局 - 调整图标样式 - 修复部分功能逻辑
This commit is contained in:
parent
52597dde2e
commit
e980f5f39f
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "calibration-pc",
|
"name": "gy-calibration",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"description": "谷云开发部开发的断路器标定软件",
|
"description": "谷云开发部开发的断路器标定软件",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "example.com",
|
"author": "example.com",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>谷云标定工具</title>
|
<title>谷云校表产测</title>
|
||||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||||
<link rel="stylesheet" href="/src/assets/iconfont/iconfont.css">
|
<link rel="stylesheet" href="/src/assets/iconfont/iconfont.css">
|
||||||
<!-- <meta-->
|
<!-- <meta-->
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4622943 */
|
font-family: "iconfont"; /* Project id 4622943 */
|
||||||
src: url('iconfont.woff2?t=1752127229460') format('woff2'),
|
src: url('iconfont.woff2?t=1752478848997') format('woff2'),
|
||||||
url('iconfont.woff?t=1752127229460') format('woff'),
|
url('iconfont.woff?t=1752478848997') format('woff'),
|
||||||
url('iconfont.ttf?t=1752127229460') format('truetype');
|
url('iconfont.ttf?t=1752478848997') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
@ -145,6 +145,10 @@
|
||||||
content: "\e772";
|
content: "\e772";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-icon_duanluqi2:before {
|
||||||
|
content: "\e9c2";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-icon_caid:before {
|
.icon-icon_caid:before {
|
||||||
content: "\e75f";
|
content: "\e75f";
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -5,6 +5,7 @@ import { createApp } from 'vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
import ElementPlus from 'element-plus'
|
import ElementPlus from 'element-plus'
|
||||||
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
|
|
||||||
import App from '@renderer/App.vue'
|
import App from '@renderer/App.vue'
|
||||||
|
@ -18,7 +19,9 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus, {
|
||||||
|
locale: zhCn,
|
||||||
|
})
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button icon="CaretRight" type="primary" :disabled="playState" @click="startExecution">开始执行</el-button>
|
<el-button icon="CaretRight" type="primary" :disabled="playState" @click="startExecution">开始执行</el-button>
|
||||||
<el-button icon="RemoveFilled" type="danger" @click="stopExecution">停止</el-button>
|
<el-button icon="RemoveFilled" type="danger" @click="stopExecution">停止</el-button>
|
||||||
<span style="margin-left: 10px;">操作员编号:</span>
|
<span style="margin-left: 10px">操作员编号:</span>
|
||||||
<el-input v-model="operatorCode" placeholder="请输入操作员编号" style="width: 150px; margin-left: 10px" />
|
<el-input v-model="operatorCode" placeholder="请输入操作员编号" style="width: 150px; margin-left: 10px" />
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<el-button icon="RefreshRight" type="primary" :disabled="playState" @click="generateDeviceList">刷新列表</el-button>
|
<el-button icon="RefreshRight" type="primary" :disabled="playState" @click="generateDeviceList">刷新列表</el-button>
|
||||||
|
<el-button icon="Download" type="success" style="margin-left: 10px" @click="showExportProdDialog = true">导出生产数据</el-button>
|
||||||
<el-button icon="Setting" :disabled="playState" @click="openSettings">配置方案</el-button>
|
<el-button icon="Setting" :disabled="playState" @click="openSettings">配置方案</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
|
@ -25,17 +26,26 @@
|
||||||
<span class="scheme-item"
|
<span class="scheme-item"
|
||||||
>P位: <span class="scheme-value">{{ activeScheme.schemeType }}</span></span
|
>P位: <span class="scheme-value">{{ activeScheme.schemeType }}</span></span
|
||||||
>
|
>
|
||||||
|
<span class="scheme-item"
|
||||||
|
>额定电压(V): <span class="scheme-value">{{ activeScheme.configParam.format[1].value }}</span></span
|
||||||
|
>
|
||||||
<span class="scheme-item"
|
<span class="scheme-item"
|
||||||
>额定电流(A): <span class="scheme-value">{{ activeScheme.configParam.format[2].value }}</span></span
|
>额定电流(A): <span class="scheme-value">{{ activeScheme.configParam.format[2].value }}</span></span
|
||||||
>
|
>
|
||||||
|
<span class="scheme-item"
|
||||||
|
>漏电流(mA): <span class="scheme-value">{{ activeScheme.configParam.format[5].value }}</span></span
|
||||||
|
>
|
||||||
|
<span class="scheme-item"></span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeScheme && activeScheme.series" class="scheme-list list-two">
|
<div v-if="activeScheme && activeScheme.series" class="scheme-list list-two">
|
||||||
<template v-for="(item, index) in activeScheme.configParam.format">
|
<template v-for="(item, index) in activeScheme.configParam.format">
|
||||||
<span v-if="item.key !== 'reserve'" :key="index" class="scheme-item"
|
<span v-if="item.key !== 'reserve' && index !== 1 && index !== 2 && index !== 5" :key="index" class="scheme-item"
|
||||||
>{{ item.unit ? item.name + '(' + item.unit + ')' : item.name }}: <span class="scheme-value">{{ item.value }}</span></span
|
>{{ item.unit ? item.name + '(' + item.unit + ')' : item.name }}:
|
||||||
|
<span v-if="index === 6 || index === 7 || index === 8" class="scheme-value"
|
||||||
|
>2<sup style="margin-left:1px;font-size:10px">{{ item.value }}</sup></span
|
||||||
|
><span v-else class="scheme-value">{{ item.value }}</span></span
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-main class="calibration-main">
|
<el-main class="calibration-main">
|
||||||
|
@ -56,30 +66,35 @@
|
||||||
v-if="device.connectStatus === 1"
|
v-if="device.connectStatus === 1"
|
||||||
:class="[
|
:class="[
|
||||||
'iconfont',
|
'iconfont',
|
||||||
'icon-icon_duanluqi',
|
'icon-icon_duanluqi2',
|
||||||
'circuit-breaker',
|
'circuit-breaker',
|
||||||
|
device.switch === 0 ? 'upsideDown' : '',
|
||||||
device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : device.result === 2 ? 'color-orange' : ''
|
device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : device.result === 2 ? 'color-orange' : ''
|
||||||
]"
|
]"
|
||||||
></div>
|
></div>
|
||||||
<div v-else :class="['iconfont', 'icon-icon_duanluqi', 'circuit-breaker', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : '']"></div>
|
<div
|
||||||
|
v-else
|
||||||
|
:class="['iconfont', 'icon-icon_duanluqi2', 'circuit-breaker', device.switch === 0 ? 'upsideDown' : '', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : '']"
|
||||||
|
></div>
|
||||||
<p>
|
<p>
|
||||||
芯片ID:
|
芯片ID:
|
||||||
<span
|
<span v-if="device.cpuId"
|
||||||
><el-tooltip class="box-item" effect="dark" :content="device.cpuId" placement="top-start">
|
><el-tooltip class="box-item" effect="dark" :content="device.cpuId" placement="top-start">
|
||||||
{{ device.cpuId || '无' }}
|
{{ device.cpuId || '无' }}
|
||||||
</el-tooltip></span
|
</el-tooltip></span
|
||||||
>
|
>
|
||||||
|
<span v-else>{{ device.cpuId || '无' }}</span>
|
||||||
</p>
|
</p>
|
||||||
<p>设备端口: {{ device.devicePort || '无' }}</p>
|
<p>设备端口: {{ device.devicePort || '无' }}</p>
|
||||||
<p>
|
<p>
|
||||||
标定结果:
|
标定结果:
|
||||||
<span :class="['device-result', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : device.result === 2 ? 'color-orange' : '']">{{
|
<span :class="['device-result', device.result === 1 ? 'color-green' : device.result === -1 ? 'color-red' : device.result === 2 ? 'color-orange' : '']">{{
|
||||||
device.result === 1 ? '成功' : device.result === -1 ? '失败' : device.result === 2 ? '标定中' : '未标定' || '无'
|
device.result === 1 ? '成功' : device.result === -1 ? '失败' : device.result === 2 ? '标定中' : '无' || '无'
|
||||||
}}</span>
|
}}</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
结果描述:
|
结果描述:
|
||||||
<span v-if="device.resultTxt"
|
<span v-if="device.resultTxt" class="color-red"
|
||||||
><el-tooltip class="box-item" effect="dark" :content="device.resultTxt" placement="top-start">
|
><el-tooltip class="box-item" effect="dark" :content="device.resultTxt" placement="top-start">
|
||||||
{{ device.resultTxt || '无' }}
|
{{ device.resultTxt || '无' }}
|
||||||
</el-tooltip></span
|
</el-tooltip></span
|
||||||
|
@ -201,15 +216,22 @@
|
||||||
<el-drawer v-model="schemeDrawerVisible" title="方案配置" size="80%" :destroy-on-close="true">
|
<el-drawer v-model="schemeDrawerVisible" title="方案配置" size="80%" :destroy-on-close="true">
|
||||||
<div class="scheme-drawer-content">
|
<div class="scheme-drawer-content">
|
||||||
<div class="scheme-list-header">
|
<div class="scheme-list-header">
|
||||||
|
<div class="scheme-list-header-left">
|
||||||
<el-button type="primary" @click="addScheme">新增方案</el-button>
|
<el-button type="primary" @click="addScheme">新增方案</el-button>
|
||||||
|
<el-button type="success" @click="exportSelectedSchemes">导出方案</el-button>
|
||||||
|
<el-button type="warning" @click="importSchemes">导入方案</el-button>
|
||||||
|
<input ref="importInputRef" type="file" accept="application/json" style="display: none" @change="handleImportFile" />
|
||||||
|
</div>
|
||||||
<el-button type="primary" @click="loadSchemes">刷新</el-button>
|
<el-button type="primary" @click="loadSchemes">刷新</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table v-loading="loading" :data="schemeList" style="width: 100%">
|
<el-table ref="schemeTableRef" v-loading="loading" :data="schemeList" style="width: 100%" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column type="index" width="50" />
|
||||||
<el-table-column prop="schemeName" label="方案名称" />
|
<el-table-column prop="schemeName" label="方案名称" />
|
||||||
<el-table-column prop="schemeType" label="断路器类型"></el-table-column>
|
<el-table-column prop="schemeType" label="断路器类型"></el-table-column>
|
||||||
<el-table-column label="操作" width="200">
|
<el-table-column label="操作" width="200">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
<el-button type="success" link @click="copyScheme(scope.row)">复制</el-button>
|
||||||
<el-button type="primary" link @click="viewScheme(scope.row)">修改</el-button>
|
<el-button type="primary" link @click="viewScheme(scope.row)">修改</el-button>
|
||||||
<el-button type="danger" link @click="deleteScheme(scope.row)">删除</el-button>
|
<el-button type="danger" link @click="deleteScheme(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -222,7 +244,7 @@
|
||||||
<el-dialog v-model="schemeDetailVisible" :title="currentScheme.schemeName" width="95%" :destroy-on-close="true" align-center :close-on-click-modal="false">
|
<el-dialog v-model="schemeDetailVisible" :title="currentScheme.schemeName" width="95%" :destroy-on-close="true" align-center :close-on-click-modal="false">
|
||||||
<el-form :model="currentScheme" label-width="100px">
|
<el-form :model="currentScheme" label-width="100px">
|
||||||
<el-form-item label="方案名称">
|
<el-form-item label="方案名称">
|
||||||
<el-input v-model="currentScheme.schemeName" />
|
<el-input v-model="currentScheme.schemeName" :disabled="isEditMode" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
|
@ -243,10 +265,10 @@
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<el-form-item label="断路器类型">
|
<el-form-item label="断路器类型">
|
||||||
<el-select v-model="currentScheme.schemeType" placeholder="请选择断路器类型">
|
<el-select v-model="currentScheme.schemeType" placeholder="请选择断路器类型">
|
||||||
<el-option label="1p" value="1p" />
|
<el-option label="1P" value="1P" />
|
||||||
<el-option label="2p" value="2p" />
|
<el-option label="2P" value="2P" />
|
||||||
<el-option label="3p" value="3p" />
|
<el-option label="3P" value="3P" />
|
||||||
<el-option label="4p" value="4p" />
|
<el-option label="4P" value="4P" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -450,10 +472,49 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="错误日志" name="second"> 错误日志 </el-tab-pane>
|
<el-tab-pane label="错误日志" name="second">
|
||||||
|
<el-table :data="errorLogList" size="small" style="width: 100%">
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column prop="errorCode" label="错误码" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span style="color: red">
|
||||||
|
{{ scope.row.errorCode }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="logMsg" label="错误日志">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tooltip effect="dark" :content="scope.row.logMsg" placement="top">
|
||||||
|
<span class="log-msg">{{ scope.row.logMsg }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
|
<!-- 导出生产数据弹窗 -->
|
||||||
|
<el-dialog v-model="showExportProdDialog" title="导出生产数据" width="450px" :close-on-click-modal="false">
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="时间范围">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="exportProdRange"
|
||||||
|
type="daterange"
|
||||||
|
unlink-panels
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
:shortcuts="exportProdPickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showExportProdDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleExportProd">导出</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -571,7 +632,7 @@ const shortcutKeyList = ref([
|
||||||
|
|
||||||
const currentScheme = ref({
|
const currentScheme = ref({
|
||||||
schemeName: '',
|
schemeName: '',
|
||||||
schemeType: '1p',
|
schemeType: '1P',
|
||||||
series: 'B7',
|
series: 'B7',
|
||||||
framework: '100ZS',
|
framework: '100ZS',
|
||||||
middleDetect: true,
|
middleDetect: true,
|
||||||
|
@ -603,6 +664,7 @@ const currentScheme = ref({
|
||||||
// 1. 新增:设备日志参数集合和step分组数据
|
// 1. 新增:设备日志参数集合和step分组数据
|
||||||
const logParamColumns = ref([]); // [{ valueKey, valueName, valueUnit }]
|
const logParamColumns = ref([]); // [{ valueKey, valueName, valueUnit }]
|
||||||
const stepLogRows = ref([]); // [{ step, paramMap: { valueKey: item }, result: 0/1 }]
|
const stepLogRows = ref([]); // [{ step, paramMap: { valueKey: item }, result: 0/1 }]
|
||||||
|
const errorLogList = ref([]);
|
||||||
|
|
||||||
const logTabChange = (tab, event) => {
|
const logTabChange = (tab, event) => {
|
||||||
console.log(tab, event);
|
console.log(tab, event);
|
||||||
|
@ -626,6 +688,7 @@ const fetchDeviceLogs = async deviceId => {
|
||||||
|
|
||||||
if (response.data.code === 0) {
|
if (response.data.code === 0) {
|
||||||
processLogData(response.data.data.result);
|
processLogData(response.data.data.result);
|
||||||
|
errorLogList.value = response.data.data.log || [];
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.data.message || '获取设备日志失败');
|
ElMessage.error(response.data.message || '获取设备日志失败');
|
||||||
}
|
}
|
||||||
|
@ -801,7 +864,6 @@ const socketStatus = computed(() => {
|
||||||
return webSocketStore.socket_open;
|
return webSocketStore.socket_open;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
logBoxRef.value = document.querySelector('#log-box-main');
|
logBoxRef.value = document.querySelector('#log-box-main');
|
||||||
initSocket();
|
initSocket();
|
||||||
|
@ -899,8 +961,39 @@ const stopExecution = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const openSettings = () => {
|
const openSettings = () => {
|
||||||
|
ElMessageBox.prompt('请输入管理员密码', '密码验证', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
inputType: 'password',
|
||||||
|
inputValue: 'gy999',
|
||||||
|
inputPlaceholder: '请输入密码',
|
||||||
|
closeOnClickModal: false
|
||||||
|
// inputValidator: (value) => {
|
||||||
|
// if (!value) return '请输入密码';
|
||||||
|
// if (value !== 'gy999') return '密码错误';
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
.then(async ({ value }) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(config.url + '/master/scheme/auth?secret=' + value);
|
||||||
|
if (response.data.code === 0) {
|
||||||
|
if (response.data.data.result) {
|
||||||
schemeDrawerVisible.value = true;
|
schemeDrawerVisible.value = true;
|
||||||
loadSchemes();
|
loadSchemes();
|
||||||
|
} else {
|
||||||
|
ElMessage.error(response.data.message || '密码错误');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.error(response.data.message || '密码验证失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('密码验证失败');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 用户取消,无需处理
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取默认标定参数
|
// 获取默认标定参数
|
||||||
|
@ -1042,7 +1135,7 @@ const deleteScheme = scheme => {
|
||||||
const addScheme = () => {
|
const addScheme = () => {
|
||||||
currentScheme.value = {
|
currentScheme.value = {
|
||||||
schemeName: `方案${schemeList.value.length + 1}`,
|
schemeName: `方案${schemeList.value.length + 1}`,
|
||||||
schemeType: '1p',
|
schemeType: '1P',
|
||||||
series: 'B7',
|
series: 'B7',
|
||||||
framework: '100ZS',
|
framework: '100ZS',
|
||||||
middleDetect: true,
|
middleDetect: true,
|
||||||
|
@ -1070,12 +1163,14 @@ const addScheme = () => {
|
||||||
steps: [],
|
steps: [],
|
||||||
iLeakDetectObj: defaultiLeakDetectObj
|
iLeakDetectObj: defaultiLeakDetectObj
|
||||||
};
|
};
|
||||||
|
isEditMode.value = false;
|
||||||
schemeDetailVisible.value = true;
|
schemeDetailVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 查看方案
|
// 修改方案
|
||||||
const viewScheme = scheme => {
|
const viewScheme = scheme => {
|
||||||
currentScheme.value = JSON.parse(JSON.stringify(scheme));
|
currentScheme.value = JSON.parse(JSON.stringify(scheme));
|
||||||
|
isEditMode.value = true;
|
||||||
schemeDetailVisible.value = true;
|
schemeDetailVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1243,6 +1338,165 @@ const playCalibration = async () => {
|
||||||
// ElMessage.error('开始执行失败');
|
// ElMessage.error('开始执行失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyScheme = scheme => {
|
||||||
|
const newScheme = JSON.parse(JSON.stringify(scheme));
|
||||||
|
delete newScheme.id;
|
||||||
|
if (typeof newScheme.schemeName === 'string') {
|
||||||
|
newScheme.schemeName = newScheme.schemeName + '_1';
|
||||||
|
}
|
||||||
|
currentScheme.value = newScheme;
|
||||||
|
isEditMode.value = false;
|
||||||
|
schemeDetailVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const importInputRef = ref(null);
|
||||||
|
|
||||||
|
const exportAllSchemes = () => {
|
||||||
|
if (!schemeList.value.length) {
|
||||||
|
ElMessage.warning('暂无可导出的方案');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const exportArr = schemeList.value.map(sch => {
|
||||||
|
const obj = JSON.parse(JSON.stringify(sch));
|
||||||
|
obj.id = '';
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
const blob = new Blob([JSON.stringify(exportArr, null, 2)], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = '谷云校表方案' + dayjs().format('YYYY-MM-DD HH:mm:ss') + '.json';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
ElMessage.success('导出成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
const importSchemes = () => {
|
||||||
|
if (importInputRef.value) {
|
||||||
|
importInputRef.value.value = '';
|
||||||
|
importInputRef.value.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImportFile = async e => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = async evt => {
|
||||||
|
try {
|
||||||
|
const arr = JSON.parse(evt.target.result);
|
||||||
|
if (!Array.isArray(arr)) {
|
||||||
|
ElMessage.error('导入文件格式错误,应为方案数组');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let successCount = 0,
|
||||||
|
failCount = 0;
|
||||||
|
const duplicateNames = [];
|
||||||
|
for (const sch of arr) {
|
||||||
|
const newSch = JSON.parse(JSON.stringify(sch));
|
||||||
|
delete newSch.id;
|
||||||
|
try {
|
||||||
|
const res = await axios.post(config.url + '/master/scheme/add', newSch);
|
||||||
|
if (res.data.code === 0) successCount++;
|
||||||
|
else {
|
||||||
|
failCount++;
|
||||||
|
if (res.data.code === 50 && res.data.message && res.data.message.includes('方案名称重复')) {
|
||||||
|
duplicateNames.push(newSch.schemeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
failCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let msg = `导入完成,成功${successCount}条,失败${failCount}条`;
|
||||||
|
if (duplicateNames.length) {
|
||||||
|
msg += `\n名称重复:${duplicateNames.join(',')}`;
|
||||||
|
}
|
||||||
|
ElMessage({ message: msg, type: duplicateNames.length ? 'error' : 'success', duration: 8000 });
|
||||||
|
loadSchemes();
|
||||||
|
} catch {
|
||||||
|
ElMessage.error('导入文件解析失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
const schemeTableRef = ref(null);
|
||||||
|
const selectedSchemes = ref([]);
|
||||||
|
const isEditMode = ref(false);
|
||||||
|
|
||||||
|
const handleSelectionChange = val => {
|
||||||
|
selectedSchemes.value = val;
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportSelectedSchemes = () => {
|
||||||
|
const exportArr = selectedSchemes.value.length ? selectedSchemes.value : [];
|
||||||
|
if (!exportArr.length) {
|
||||||
|
ElMessage.warning('请先选择要导出的方案');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const arr = exportArr.map(sch => {
|
||||||
|
const obj = JSON.parse(JSON.stringify(sch));
|
||||||
|
obj.id = '';
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
const blob = new Blob([JSON.stringify(arr, null, 2)], { type: 'application/json' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = '谷云校表方案' + dayjs().format('YYYY-MM-DD HH:mm:ss') + '.json';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
ElMessage.success('导出成功');
|
||||||
|
};
|
||||||
|
|
||||||
|
const showExportProdDialog = ref(false);
|
||||||
|
const exportProdRange = ref([]);
|
||||||
|
const exportProdPickerOptions = [
|
||||||
|
{
|
||||||
|
text: '最近一周',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最近一个月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '最近三个月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleExportProd = () => {
|
||||||
|
if (!exportProdRange.value || exportProdRange.value.length !== 2) {
|
||||||
|
ElMessage.warning('请选择导出时间范围');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: 调用实际导出生产数据接口
|
||||||
|
// exportProdRange.value[0]、exportProdRange.value[1] 为起止时间
|
||||||
|
showExportProdDialog.value = false;
|
||||||
|
ElMessage.success('导出请求已发起(请补充实际导出逻辑)');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@ -1273,10 +1527,11 @@ const playCalibration = async () => {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
&.list-two {
|
&.list-two {
|
||||||
justify-content: space-between;
|
// justify-content: space-between;
|
||||||
}
|
}
|
||||||
.scheme-item {
|
.scheme-item {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
width: 14%;
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1542,7 @@ const playCalibration = async () => {
|
||||||
&.list-one {
|
&.list-one {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
.scheme-item {
|
.scheme-item {
|
||||||
margin-right: 55px;
|
// margin-right: 55px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1373,6 +1628,10 @@ const playCalibration = async () => {
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.upsideDown {
|
||||||
|
transform: scaleY(-1);
|
||||||
|
}
|
||||||
|
|
||||||
.color-green {
|
.color-green {
|
||||||
color: #67c23a;
|
color: #67c23a;
|
||||||
/* Green for connected */
|
/* Green for connected */
|
||||||
|
@ -1383,11 +1642,6 @@ const playCalibration = async () => {
|
||||||
/* Green for connected */
|
/* Green for connected */
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-red {
|
|
||||||
color: #f56c6c;
|
|
||||||
/* Red for disconnected */
|
|
||||||
}
|
|
||||||
|
|
||||||
.calibration-footer {
|
.calibration-footer {
|
||||||
height: 200px; /* Fixed height for logs */
|
height: 200px; /* Fixed height for logs */
|
||||||
background-color: #303030; /* Darker grey for logs */
|
background-color: #303030; /* Darker grey for logs */
|
||||||
|
@ -1440,19 +1694,12 @@ const playCalibration = async () => {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
font-size: 14px;
|
font-size: 12px;
|
||||||
line-height: 18px;
|
line-height: 18px;
|
||||||
&.icon-icon_fuzhi {
|
|
||||||
line-height: 26px;
|
|
||||||
margin-left: 8px;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #0066cc;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.log-item-txt {
|
.log-item-txt {
|
||||||
user-select: auto;
|
user-select: text;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1741,4 +1988,8 @@ const playCalibration = async () => {
|
||||||
background: #303030 !important;
|
background: #303030 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.color-red {
|
||||||
|
color: #f56c6c !important;
|
||||||
|
/* Red for disconnected */
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue