优化调整新建作业流程与子任务

This commit is contained in:
24kycj
2025-09-09 18:43:20 +08:00
parent b51df3caf9
commit 859a8a985e
5 changed files with 215 additions and 291 deletions
+1 -1
View File
@@ -1 +1 @@
{"files":["\\\\NAS\\study\\research_reports\\餐饮服务\\“保健水晶鸡、鸭皮蛋”商业计划书.docx"]} {"files":["E:\\TortoiseGit License.txt"]}
+88 -26
View File
@@ -54,6 +54,7 @@
<script> <script>
const { dialog } = require("@electron/remote"); const { dialog } = require("@electron/remote");
const fs = require("fs"); const fs = require("fs");
const path = require("path");
import fileEmpty from "./fileEmpty"; import fileEmpty from "./fileEmpty";
import fileList from "./fileList"; import fileList from "./fileList";
import progressdialog from "./progressdialog"; import progressdialog from "./progressdialog";
@@ -128,7 +129,7 @@ export default {
mounted() { mounted() {
// this.$set(this, filesList, this.saveWorkList) // this.$set(this, filesList, this.saveWorkList)
const _this = this; const _this = this;
document.addEventListener("drop", (e) => { this._handleDrop = (e) => {
e.preventDefault(); e.preventDefault();
// e.stopPropagation(); // e.stopPropagation();
for (const f of e.dataTransfer.files) { for (const f of e.dataTransfer.files) {
@@ -144,13 +145,43 @@ export default {
calcSize(f.path, _this.folderCalcCallback); calcSize(f.path, _this.folderCalcCallback);
} }
} }
}); };
document.addEventListener("dragover", (e) => { this._handleDragOver = (e) => {
e.preventDefault(); e.preventDefault();
// e.stopPropagation(); // e.stopPropagation();
}); };
document.addEventListener("drop", this._handleDrop);
document.addEventListener("dragover", this._handleDragOver);
},
beforeDestroy() {
if (this._handleDrop) {
document.removeEventListener("drop", this._handleDrop);
this._handleDrop = null;
}
if (this._handleDragOver) {
document.removeEventListener("dragover", this._handleDragOver);
this._handleDragOver = null;
}
}, },
methods: { methods: {
reset() {
this.filesList = {};
this.key++;
this.allSize = 0;
this.progressVisible = false;
this.archiverVisible = false;
this.overNumber = 0;
this.allNumber = 0;
this.nowstate = true;
this.archiverIsover = false;
this.archiverIsfalse = false;
this.zip_path = "";
this.isCopy = false;
this.isSucess = true;
this.copyPath = "";
this.networkPaths = [];
this.$emit('network-paths-changed', []);
},
insertList(f) { insertList(f) {
if (!this.filesList[f.path]) { if (!this.filesList[f.path]) {
this.allNumber++; this.allNumber++;
@@ -227,6 +258,12 @@ export default {
delete this.filesList[path]; delete this.filesList[path];
this.key++; this.key++;
this.allNumber--; this.allNumber--;
// 若为网络路径,则同步按主机清理认证项
if (isNetworkPath(path)) {
const hostName = extractHostName(path)
this.networkPaths = this.networkPaths.filter(p => p.hostName !== hostName)
}
this.$emit('network-paths-changed', this.getNetworkPaths());
}, },
dropFolderCheck(f) { dropFolderCheck(f) {
//T是文件夹 F不是文件夹 //T是文件夹 F不是文件夹
@@ -284,34 +321,52 @@ export default {
this.changeArchivervisible(false); this.changeArchivervisible(false);
}, 500); }, 500);
}, },
resume(file_form) { async resume(file_form) {
//if (file_form == 0) { // 统一走优化流程
if (1) { const entries = Object.values(this.filesList || {});
if (entries.length === 0) {
return;
}
if (this.isCopy) { if (this.isCopy) {
// 拷贝到共享目录:确保目标目录存在,顺序执行避免过多并发导致卡顿
try {
if (!this.copyPath || typeof this.copyPath !== 'string') {
console.warn('Invalid copyPath');
// 回退为直接完成,避免卡住
entries.forEach((f) => this.fileBack(f, true));
return;
}
// 确保目录以分隔符结尾拼接正确
const targetDir = this.copyPath;
try {
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
} catch (e) {
console.error('ensure target dir failed', e);
}
this.overNumber = 0; this.overNumber = 0;
this.changeProgressvisible(true); this.changeProgressvisible(true);
for (let i in this.filesList) {
// const path = "D:\\copytest\\1\\" + this.filesList[i].name; for (const file of entries) {
const path = this.copyPath + this.filesList[i].name; const dest = path.join(targetDir, file.name);
console.log(this.copyPath); await new Promise((resolve) => {
console.log(path);
copy( copy(
i, file.path,
path, dest,
this.filesList[i].folder, file.folder,
this.fileBack, (fl, ok) => {
this.filesList[i] this.fileBack(fl, ok);
resolve();
},
file
); );
});
} }
} else { } catch (err) {
//2023-04-24修改为所有都只上传文件路径,不需要压缩 console.error('copy flow error', err);
//文件和文件夹 // 出错时也推进为完成,避免停滞
this.overNumber = 0; entries.forEach((f) => this.fileBack(f, false));
for (let i in this.filesList) {
// const path = "D:\\copytest\\1\\" + this.filesList[i].name;
// copy(i, path, this.filesList[i].folder, this.back, this.filesList[i]);
this.fileBack(this.filesList[i], true);
}
} }
} else if (file_form == 1) { } else if (file_form == 1) {
//电子光盘 //电子光盘
@@ -330,6 +385,12 @@ export default {
zip(this.filesList, this.zip_path, this.archiverBack, true, password); zip(this.filesList, this.zip_path, this.archiverBack, true, password);
} else if (file_form == 4) { } else if (file_form == 4) {
//u盘 //u盘
} else {
// 默认路径上传:不实际拷贝,仅回调推进流程
this.overNumber = 0;
for (const file of entries) {
this.fileBack(file, true);
}
} }
}, },
changeProgressvisible(visiable) { changeProgressvisible(visiable) {
@@ -376,6 +437,7 @@ export default {
userName: userName, userName: userName,
password: password password: password
}); });
this.$emit('network-paths-changed', this.getNetworkPaths());
} }
}, },
+80 -16
View File
@@ -409,7 +409,7 @@
prop="status" prop="status"
:label="$t('main.tableState')" :label="$t('main.tableState')"
min-width="80"> min-width="80">
<template slot-scope="scope">{{ $t('main.tableOnline') }}</template> <template slot-scope="{}">{{ $t('main.tableOnline') }}</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="SerialNo" prop="SerialNo"
@@ -541,7 +541,9 @@
style="width: 100%" style="width: 100%"
size="mini" size="mini"
:empty-text="$t('index.nodata')" :empty-text="$t('index.nodata')"
row-class-name="rowclass"> row-class-name="rowclass"
:row-key="row => row.JobID || row.AssUuid"
:tree-props="{ children: 'children' }">
<el-table-column <el-table-column
label="#" label="#"
width="50"> width="50">
@@ -553,6 +555,10 @@
prop="jId" prop="jId"
:label="$t('index.wordID')" :label="$t('index.wordID')"
min-width="85"> min-width="85">
<template slot-scope="scope">
<span v-if="!scope.row.AssUuid">{{ scope.row.jId }}</span>
<span v-else>{{ (scope.row.ParentJobID || '') | shortJobId }}</span>
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="DataSource" prop="DataSource"
@@ -563,20 +569,23 @@
:label="$t('index.wordSpace')" :label="$t('index.wordSpace')"
min-width="45"> min-width="45">
<template slot-scope="scope"> <template slot-scope="scope">
{{ getPrintName(scope.row.PrinterID, true) }} <span v-if="!scope.row.AssUuid">{{ getPrintName(scope.row.PrinterID, true) }}</span>
<span v-else>{{ getPrintName(scope.row.ParentPrinterID || scope.row.PrinterID, true) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('main.USBType')" :label="$t('main.USBType')"
min-width="55"> min-width="55">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.PrinterType }} {{ !scope.row.AssUuid ? scope.row.PrinterType : (scope.row.ParentPrinterType || scope.row.PrinterType) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
min-width="60" min-width="60"
prop="TaskCapacity"
:label="$t('main.TaskCapacity')"> :label="$t('main.TaskCapacity')">
<template slot-scope="scope">
{{ !scope.row.AssUuid ? scope.row.TaskCapacity : (scope.row.ParentTaskCapacity || '') }}
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-if="false" v-if="false"
@@ -584,9 +593,11 @@
:label="$t('main.taskFile')"> :label="$t('main.taskFile')">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="CreateTime"
:label="$t('index.createTime')" :label="$t('index.createTime')"
min-width="75"> min-width="75">
<template slot-scope="scope">
{{ !scope.row.AssUuid ? scope.row.CreateTime : (scope.row.StartTime || '') }}
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
v-if="false" v-if="false"
@@ -599,20 +610,25 @@
:filter-method="filterHandler"> :filter-method="filterHandler">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="FinishTime"
:label="$t('index.finishedTime')" :label="$t('index.finishedTime')"
min-width="75"> min-width="75">
<template slot-scope="scope">
{{ !scope.row.AssUuid ? scope.row.FinishTime : (scope.row.FinishTime || '') }}
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="JobCompletion"
min-width="40" min-width="40"
:label="$t('index.finishedNumber')"> :label="$t('index.finishedNumber')">
<template slot-scope="scope">
<span v-if="!scope.row.AssUuid">{{ scope.row.JobCompletion }}</span>
<span v-else>-</span>
</template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
:label="$t('index.state')" :label="$t('index.state')"
prop="JobStatus"
width="135"> width="135">
<template slot-scope="scope"> <template slot-scope="scope">
<template v-if="!scope.row.AssUuid">
<el-dropdown <el-dropdown
trigger="click" trigger="click"
@command="(e) => handleTaskCommand(e, scope.row.JobID)" @command="(e) => handleTaskCommand(e, scope.row.JobID)"
@@ -639,9 +655,20 @@
:width="45" :width="45"
define-back-color="#ebeef5" define-back-color="#ebeef5"
:stroke-width="3" :stroke-width="3"
:percentage="parseFloat(scope.row.TaskPercentage.replace(`%`, ``))" :percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
v-if="scope.row.JobStatus == `Copying`"></el-progress> v-if="scope.row.JobStatus == `Copying`"></el-progress>
</template> </template>
<template v-else>
{{ jobState(scope.row.TaskStatus) }}
<el-progress
:color="customColors"
:width="45"
define-back-color="#ebeef5"
:stroke-width="3"
:percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
v-if="scope.row.TaskStatus == `Copying`"></el-progress>
</template>
</template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</div> </div>
@@ -824,6 +851,12 @@ export default {
warnCard, warnCard,
sFooter sFooter
}, },
filters: {
shortJobId(v) {
if (!v) return ''
return String(v).split('-')[0]
}
},
data() { data() {
return { return {
guideStep: null, guideStep: null,
@@ -1265,13 +1298,31 @@ export default {
this.state = true this.state = true
let tasks = [...this.tasks] let tasks = [...this.tasks]
this.tasks = [] this.tasks = []
for (let item of res.data.unfinishedTasks) { const normalize = (task) => {
item.jId = item.JobID.split('-')[0] //+ "..."; const jId = (task.JobID || '').split('-')[0]
this.tasks.push(item) const parentCommon = {
jId,
ParentJobID: task.JobID,
ParentPrinterID: task.PrinterID,
ParentPrinterType: task.PrinterType,
ParentTaskCapacity: task.TaskCapacity
} }
for (let item of res.data.finishedTasks) { const children = Array.isArray(task.AssTask) ? task.AssTask.map((child) => ({
item.jId = item.JobID.split('-')[0] //+ "..."; ...child,
this.tasks.push(item) ...parentCommon
})) : []
return {
...task,
jId,
children
}
}
for (let item of (res.data.unfinishedTasks || [])) {
this.tasks.push(normalize(item))
}
for (let item of (res.data.finishedTasks || [])) {
this.tasks.push(normalize(item))
} }
let total1 = 0 let total1 = 0
let total2 = 0 let total2 = 0
@@ -1681,6 +1732,19 @@ export default {
} }
this.isNew = true this.isNew = true
this.dialogVisible = true this.dialogVisible = true
// 新建任务时重置文件列表与网络认证状态,避免上一次残留导致卡顿
this.$nextTick(() => {
const workRef = this.$refs.work
if (workRef && workRef.$refs && workRef.$refs.files && workRef.$refs.files.reset) {
workRef.$refs.files.reset()
}
if (workRef) {
workRef.networkAuthVisible = false
workRef.networkAuthPaths = []
workRef.networkCredentials = {}
workRef.submitLoading = false
}
})
}, },
newNetWork() { newNetWork() {
//this.isNew = true; //this.isNew = true;
@@ -4,6 +4,7 @@
:content="isRecording ? $t('recorder.stopRecording') : $t('recorder.startRecording')" :content="isRecording ? $t('recorder.stopRecording') : $t('recorder.startRecording')"
placement="top"> placement="top">
<el-button <el-button
size="medium"
:type="isRecording ? 'danger' : 'primary'" :type="isRecording ? 'danger' : 'primary'"
:icon="isRecording ? 'el-icon-video-pause' : 'el-icon-video-camera'" :icon="isRecording ? 'el-icon-video-pause' : 'el-icon-video-camera'"
circle circle
+15 -218
View File
@@ -193,18 +193,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label="$t('work.formatFile')"> <!-- 移除不需要的U盘格式列 -->
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="high_setting_form.formatFile">
<el-option
v-for="item in high_setting.formatFile"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('work.hash')"> <el-form-item :label="$t('work.hash')">
<el-switch v-model="high_setting_form.s1"> </el-switch> <el-switch v-model="high_setting_form.s1"> </el-switch>
</el-form-item> </el-form-item>
@@ -257,7 +246,7 @@
@recording-started="onRecordingStarted" @recording-started="onRecordingStarted"
@recording-stopped="onRecordingStopped" @recording-stopped="onRecordingStopped"
@recording-saved="onRecordingSaved" @recording-saved="onRecordingSaved"
style="margin-left: 10px; display: inline-block;" style="margin-right: 10px; display: inline-block;"
/> />
<!-- 网络路径认证对话框 --> <!-- 网络路径认证对话框 -->
@@ -269,210 +258,7 @@
/> />
</div> </div>
</div> </div>
<el-row <!-- 删除无效布局v-if=0 -->
:gutter="20"
v-if="0">
<el-col :span="6">
<el-row :gutter="0">
<el-col :span="8">
<div class="grid-content bg-purple">
<span style="font-size: 16px; line-height: 32px; float: left">
{{ $t('work.size') }}
</span>
</div>
</el-col>
<el-col :span="14">
<div class="grid-content bg-purple">
<el-select
:placeholder="$t('work.pleaseSelect')"
style="width: 160px"
v-model="size_form">
<el-option
v-for="item in size_type"
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="filterPassedType.indexOf(item.value) == -1">
</el-option>
</el-select>
</div>
</el-col>
</el-row>
<!--
<el-input v-model="juanbiao_form" :placeholder="$t('work.pleaseInput')" style="width:280px;float:left">
<template slot="prepend">
{{$t("work.sign")}}
</template>
</el-input>
-->
</el-col>
<el-col :span="6">
<el-row :gutter="0">
<el-col :span="8">
<div class="grid-content bg-purple">
<span style="font-size: 16px; line-height: 32px; float: left">
{{ $t('work.content') }}
</span>
</div>
</el-col>
<el-col :span="14">
<div class="grid-content bg-purple">
<el-select
:placeholder="$t('work.pleaseSelect')"
style="float: left; margin-left: 10px"
v-model="file_form">
<el-option
v-for="item in file_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<el-row :gutter="0">
<el-col :span="8">
<div class="grid-content bg-purple">
<span style="font-size: 16px; line-height: 32px">
{{ $t('work.partType') }}
</span>
</div>
</el-col>
<el-col :span="14">
<div class="grid-content bg-purple">
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="type_form">
<el-option
v-for="item in type"
:key="item.value"
:label="item.label"
:value="item.value"
:disabled="item.disabled">
</el-option>
</el-select>
</div>
</el-col>
</el-row>
</el-col>
<el-col :span="6">
<el-popover
style="float: right"
placement="left"
width="600"
trigger="click">
<div>
<el-form
:label-position="'right'"
label-width="250px">
<el-form-item :label="$t('work.better')">
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="high_setting_form.priority">
<el-option
v-for="item in high_setting.priority"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<!--<el-form-item :label="$t('work.gshType')">
<el-select :placeholder="$t('work.pleaseSelect')" v-model="high_setting_form.fileSystem">
<el-option v-for="item in high_setting.fileSystem" :key="item.value" :label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>-->
<el-form-item :label="$t('work.startWorkSpace')">
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="high_setting_form.target_work">
<el-option
v-for="item in high_setting.target_work"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('work.ribbonType')">
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="high_setting_form.color_type">
<el-option
v-for="item in high_setting.color_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('work.formatFile')">
<el-select
:placeholder="$t('work.pleaseSelect')"
v-model="high_setting_form.formatFile">
<el-option
v-for="item in high_setting.formatFile"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('work.hash')">
<el-switch v-model="high_setting_form.s1"> </el-switch>
</el-form-item>
<el-form-item :label="$t('work.md5')">
<el-switch v-model="high_setting_form.s2"> </el-switch>
</el-form-item>
<el-form-item :label="$t('work.fail')">
<el-switch v-model="high_setting_form.s3"> </el-switch>
</el-form-item>
<el-form-item :label="$t('work.spanUSBcard')">
<el-switch v-model="high_setting_form.Span_USBcard"> </el-switch>
</el-form-item>
<!--<el-form-item :label="$t('work.disk')">
<el-switch v-model="high_setting_form.s4">
</el-switch>
</el-form-item>
<el-form-item :label="$t('work.bitlocker')">
<el-switch v-model="high_setting_form.s5">
</el-switch>
</el-form-item>-->
<!-- <el-form-item :label="$t('work.localFiles')"> -->
<!-- <el-switch v-model="high_setting_form.localfiles"> -->
<!-- </el-switch> -->
<!-- </el-form-item> -->
</el-form>
<!--<el-descriptions :column="2" v-if="high_setting_form.s5">
<el-descriptions-item :label="$t('work.password')">
<el-input placeholder="$t('work.pleasePassword')" v-model="high_setting_form.pass" show-password
size="mini">
</el-input>
</el-descriptions-item>
<el-descriptions-item :label="$t('work.comfirm')">
<el-input placeholder="$t('work.pleasePassword')" v-model="high_setting_form.repass" show-password
size="mini">
</el-input>
</el-descriptions-item>
</el-descriptions>-->
</div>
<el-button
slot="reference"
size="medium"
style="height: 32px; padding: 0 15px; line-height: 32px">
{{ $t('work.senior') }}
</el-button>
</el-popover>
</el-col>
</el-row>
</div> </div>
<!-- <el-row <!-- <el-row
:gutter="20" :gutter="20"
@@ -650,6 +436,7 @@
:onSizechange="sizeChange" :onSizechange="sizeChange"
:complete="upload_over" :complete="upload_over"
:saveWorkList="saveWorkList" :saveWorkList="saveWorkList"
@network-paths-changed="onNetworkPathsChanged"
><el-progress ><el-progress
:text-inside="true" :text-inside="true"
:percentage="file_percent" :percentage="file_percent"
@@ -1295,7 +1082,7 @@ export default {
// value: 4, // value: 4,
// label: this.$t("work.forbidCopyU") // label: this.$t("work.forbidCopyU")
//}], //}],
size_form: null, size_form: 4,
type_form: 0, type_form: 0,
file_form: 0, file_form: 0,
number: 1, number: 1,
@@ -1468,6 +1255,16 @@ export default {
return false return false
}, },
// 文件列表网络路径变化时触发,若为空则关闭弹窗
onNetworkPathsChanged(paths) {
if (!paths || paths.length === 0) {
this.networkAuthVisible = false
this.networkAuthPaths = []
} else {
this.networkAuthPaths = paths
}
},
// 网络认证确认回调 // 网络认证确认回调
onNetworkAuthConfirm(netInfo) { onNetworkAuthConfirm(netInfo) {
this.networkCredentials = netInfo this.networkCredentials = netInfo