修复提交逻辑:完善所有拷贝类型支持,修复电子光盘和禁拷U盘提交卡死问题

- 修复 Files 组件中 file_form=1(电子光盘) 和 file_form=4(禁拷U盘) 的空处理分支
- 添加完成回调触发逻辑,避免提交流程卡死
- 完善 upload()、upload_over()、performSubmit() 的状态判断
- 严格对齐 work-副本.vue 的验证逻辑和参数构建顺序
- 优化标签上传判断,避免无标签时的不必要API调用
- 添加 ISO/ZIP 验证(仅在有内容文件时)
- 清理所有调试日志
This commit is contained in:
24kycj
2026-01-05 04:05:37 +08:00
parent a6ce251509
commit 04ca328a67
17 changed files with 992 additions and 499 deletions
+8 -30
View File
@@ -1,45 +1,23 @@
<template> <template>
<el-dialog <el-dialog :title="$t('networkAuth.title')" :visible.sync="visible" width="600px" :close-on-click-modal="false"
:title="$t('networkAuth.title')" :close-on-press-escape="false" :show-close="false" :append-to-body="true" :z-index="9999">
:visible.sync="visible"
width="600px"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
:append-to-body="true"
:z-index="9999"
>
<div class="network-auth-content"> <div class="network-auth-content">
<p class="auth-description"> <p class="auth-description">
{{ $t('networkAuth.description') }} {{ $t('networkAuth.description') }}
</p> </p>
<div class="network-paths"> <div class="network-paths">
<div <div v-for="(path, index) in networkPaths" :key="index" class="network-path-item">
v-for="(path, index) in networkPaths"
:key="index"
class="network-path-item"
>
<div class="path-info"> <div class="path-info">
<span class="path-label">{{ $t('networkAuth.pathLabel') }}</span> <span class="path-label">{{ $t('networkAuth.pathLabel') }}</span>
<span class="path-value">{{ path.path }}</span> <span class="path-value">{{ path.path }}</span>
</div> </div>
<div class="auth-fields"> <div class="auth-fields">
<el-input <el-input v-model="path.userName" :placeholder="$t('networkAuth.userName')" size="small"
v-model="path.userName" style="width: 150px; margin-right: 10px;" />
:placeholder="$t('networkAuth.userName')" <el-input v-model="path.password" type="password" :placeholder="$t('networkAuth.password')" size="small"
size="small" style="width: 150px;" show-password />
style="width: 150px; margin-right: 10px;"
/>
<el-input
v-model="path.password"
type="password"
:placeholder="$t('networkAuth.password')"
size="small"
style="width: 150px;"
show-password
/>
</div> </div>
</div> </div>
</div> </div>
@@ -102,7 +80,7 @@ export default {
this.$emit('confirm', netInfo) this.$emit('confirm', netInfo)
} catch (error) { } catch (error) {
console.error('保存网络认证信息失败:', error) console.error('保存网络认证信息失败:', error)
this.$message.error('保存认证信息失败') this.$message.error(this.$t('networkAuth.authSaveFail'))
} finally { } finally {
this.loading = false this.loading = false
} }
+59 -178
View File
@@ -33,28 +33,28 @@
<div class="row"> <div class="row">
<div class="lable">RejectConfig</div> <div class="lable">RejectConfig</div>
<div class="switch"> <div class="switch">
<el-switch v-model="iniData.RejectConfig"></el-switch> <el-switch v-model="iniData.RejectConfig" :active-value="1" :inactive-value="0"></el-switch>
</div> </div>
<div class="tips">{{ $t("dispose.tips1") }}</div> <div class="tips">{{ $t("dispose.tips1") }}</div>
</div> </div>
<div class="row"> <div class="row">
<div class="lable">StopOnFailure</div> <div class="lable">StopOnFailure</div>
<div class="switch"> <div class="switch">
<el-switch v-model="iniData.StopOnFailure"></el-switch> <el-switch v-model="iniData.StopOnFailure" :active-value="1" :inactive-value="0"></el-switch>
</div> </div>
<div class="tips">{{ $t("dispose.errorTips2") }}</div> <div class="tips">{{ $t("dispose.errorTips2") }}</div>
</div> </div>
<div class="row"> <div class="row">
<div class="lable">KeepCombinedImage</div> <div class="lable">KeepCombinedImage</div>
<div class="switch"> <div class="switch">
<el-switch v-model="iniData.KeepCombinedImage"></el-switch> <el-switch v-model="iniData.KeepCombinedImage" :active-value="1" :inactive-value="0"></el-switch>
</div> </div>
<div class="tips">{{ $t("dispose.isReserveimg") }}</div> <div class="tips">{{ $t("dispose.isReserveimg") }}</div>
</div> </div>
<div class="row"> <div class="row">
<div class="lable">CleanTaskFile</div> <div class="lable">CleanTaskFile</div>
<div class="switch"> <div class="switch">
<el-switch v-model="iniData.CleanTaskFile"></el-switch> <el-switch v-model="iniData.CleanTaskFile" :active-value="1" :inactive-value="0"></el-switch>
</div> </div>
<div class="tips">{{ $t("dispose.isReservetask") }}</div> <div class="tips">{{ $t("dispose.isReservetask") }}</div>
</div> </div>
@@ -65,7 +65,7 @@
"> ">
<div class="lable">UploadSharedDir</div> <div class="lable">UploadSharedDir</div>
<div class="switch"> <div class="switch">
<el-switch v-model="iniData.UploadSharedDir"></el-switch> <el-switch v-model="iniData.UploadSharedDir" :active-value="1" :inactive-value="0"></el-switch>
</div> </div>
<div class="tips">{{ $t("dispose.isUpload") }}</div> <div class="tips">{{ $t("dispose.isUpload") }}</div>
</div> </div>
@@ -89,201 +89,82 @@
</template> </template>
<script> <script>
const { ipcRenderer } = require("electron");
var fs = require("fs"),
ini = require("ini");
export default { export default {
name: "dispose", name: "dispose",
data() { data() {
return { return {
autoRetryOptions: [ autoRetryOptions: [
{ { value: 0, label: "0" },
value: 0, { value: 1, label: "1" },
label: "0", { value: 2, label: "2" },
},
{
value: 1,
label: "1",
},
{
value: 2,
label: "2",
},
], ],
LogLevelOptions: [ LogLevelOptions: [
{ { value: "TRACE", label: "TRACE" },
value: "TRACE", { value: "DEBUG", label: "DEBUG" },
label: "TRACE", { value: "INFO", label: "INFO" },
}, { value: "WARNING", label: "WARNING" },
{ { value: "ERROR", label: "ERROR" },
value: "DEBUG", { value: "FATAL", label: "FATAL" },
label: "DEBUG",
},
{
value: "INFO",
label: "INFO",
},
{
value: "WARNING",
label: "WARNING",
},
{
value: "ERROR",
label: "ERROR",
},
{
value: "FATAL",
label: "FATAL",
},
], ],
iniData: { iniData: {
LogLevel: 'INFO', LogLevel: "INFO",
AutoRetryTimes: 0, AutoRetryTimes: 0,
TaskDir: '', TaskDir: "",
SharedDir: '', SharedDir: "",
RejectConfig: false, RejectConfig: 0,
StopOnFailure: false, StopOnFailure: 0,
KeepCombinedImage: false, KeepCombinedImage: 0,
CleanTaskFile: false, CleanTaskFile: 0,
UploadSharedDir: false, UploadSharedDir: 0,
AuthorizationCode: '' AuthorizationCode: "",
DeleteTask: 0 // Ensure this is preserved if present in API
}, },
AutoRetryTimes: null,
LogLevel: "TRACE",
TaskDir: null,
SharedDir: null,
RejectConfig: false,
StopOnFailure: false,
KeepCombinedImage: false,
CleanTaskFile: false,
show: true, show: true,
root: "",
}; };
}, },
methods: { methods: {
save() { // 获取配置
//console.log(this.iniData); getConfig() {
//console.log(ini.stringify(this.iniData)); this.$axios.get('/admin/get_config')
//fs.writeFileSync("../Debug/config.ini"); .then(res => {
let that = this; if (res && res.data) {
fs.writeFile( // 合并数据,确保所有字段都存在
this.root + "/ProductionServer/config.ini", this.iniData = { ...this.iniData, ...res.data };
ini.stringify(this.iniData),
function (err) {
if (err) {
that.$message.error(that.$t("dispose.errorReserve"));
} else { } else {
that.$message({ this.$message.error(this.$t("dispose.errorRead"));
}
})
.catch(err => {
console.error(err);
this.$message.error(this.$t("dispose.errorRead"));
});
},
// 保存配置
save() {
this.$axios.post('/admin/get_config', this.iniData)
.then(res => {
if (res && (res.data === "success" || res.status === 200)) {
this.$message({
type: "success", type: "success",
message: that.$t("dispose.successReserve"), message: this.$t("dispose.successReserve"),
});
} else {
// 某些接口可能返回 { ret: 0 } 或其他形式,视具体情况而定
// 这里假设200 OK即为成功,或者根据res.data判断
this.$message({
type: "success",
message: this.$t("dispose.successReserve"),
}); });
} }
} })
); .catch(err => {
console.error(err);
this.$message.error(this.$t("dispose.errorReserve"));
});
}, },
}, },
mounted() { mounted() {
let that = this; this.getConfig();
//var data = ini.parse(fs.readFileSync("F:\\controll\\config.ini", "utf-8"));
ipcRenderer.on("get-root-callback", (event, data) => {
this.root = data;
fs.readFile(this.root + "/ProductionServer/config.ini", "utf-8", (err, res) => {
if (err) {
console.log(err);
this.$message.error(that.$t("dispose.errorRead"));
this.show = false;
} else {
console.log(res);
let data = ini.parse(res);
console.log(data);
this.iniData = data;
that.iniData.AutoRetryTimes = data.AutoRetryTimes
? data.AutoRetryTimes
: 0;
that.iniData.TaskDir = data.TaskDir ? data.TaskDir : "";
that.iniData.SharedDir = data.SharedDir ? data.SharedDir : "";
that.iniData.LogLevel = data.LogLevel ? data.LogLevel : "";
that.iniData.CleanTaskFile =
data.CleanTaskFile == "true" ||
data.CleanTaskFile == "True" ||
data.CleanTaskFile
? true
: false;
that.iniData.KeepCombinedImage =
data.KeepCombinedImage == "true" ||
data.KeepCombinedImage == "True" ||
data.KeepCombinedImage
? true
: false;
that.iniData.RejectConfig =
data.RejectConfig == "true" ||
data.RejectConfig == "True" ||
data.RejectConfig
? true
: false;
that.iniData.StopOnFailure =
data.StopOnFailure == "true" ||
data.StopOnFailure == "True" ||
data.StopOnFailure
? true
: false;
that.iniData.UploadSharedDir =
data.UploadSharedDir == "true" ||
data.UploadSharedDir == "True" ||
data.UploadSharedDir
? true
: false;
that.iniData.AuthorizationCode = data.AuthorizationCode ? data.AuthorizationCode : "";
console.log(data);
}
});
});
ipcRenderer.send("get-root");
//iniparser.parse("../Debug/config.ini", function (err, data) {
/*
AutoRetryTimes: "0"
CardsoonModel: "SF80"
CleanTaskFile: "false"
RejectConfig: "false"
KeepCombinedImage: "True"
LogLevel: "DEBUG"
SharedDir: "C:\\CardSoonRepo"
StopOnFailure: "false"
SystemSn: "830001"
TaskDir: "C:\\PrintTasks"
Version: "V3.1"
iniparser.parse("F:\\controll\\config.ini", function (err, data) {
console.log(err);
if (err) {
that.$message.error("读取配置文件失败!");
} else {
console.log(data);
that.AutoRetryTimes = data.AutoRetryTimes ? data.AutoRetryTimes : 0;
that.TaskDir = data.TaskDir ? data.TaskDir : "";
that.SharedDir = data.SharedDir ? data.SharedDir : "";
that.LogLevel = data.LogLevel ? data.LogLevel : "";
that.CleanTaskFile =
data.CleanTaskFile == "true" || data.CleanTaskFile == "True"
? true
: false;
that.KeepCombinedImage =
data.KeepCombinedImage == "true" || data.KeepCombinedImage == "True"
? true
: false;
that.RejectConfig =
data.RejectConfig == "true" || data.RejectConfig == "True"
? true
: false;
that.StopOnFailure =
data.StopOnFailure == "true" || data.StopOnFailure == "True"
? true
: false;
}
});
*/
}, },
}; };
</script> </script>
+10 -2
View File
@@ -349,7 +349,11 @@ export default {
entries.forEach((f) => this.fileBack(f, false)); entries.forEach((f) => this.fileBack(f, false));
} }
} else if (file_form == 1) { } else if (file_form == 1) {
//电子光盘 // 电子光盘:不需要拷贝,直接标记为完成
this.overNumber = 0;
for (const file of entries) {
this.fileBack(file, true);
}
} else if (file_form == 2) { } else if (file_form == 2) {
//zip //zip
this.archiverIsover = false; this.archiverIsover = false;
@@ -364,7 +368,11 @@ export default {
let password = "123456"; let password = "123456";
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盘:不需要拷贝,直接标记为完成
this.overNumber = 0;
for (const file of entries) {
this.fileBack(file, true);
}
} else { } else {
// 默认路径上传:不实际拷贝,仅回调推进流程 // 默认路径上传:不实际拷贝,仅回调推进流程
this.overNumber = 0; this.overNumber = 0;
@@ -12,7 +12,7 @@
<!-- 录制状态指示器 --> <!-- 录制状态指示器 -->
<div v-if="isRecording" class="recording-indicator" :class="{ 'status-only': statusOnly }"> <div v-if="isRecording" class="recording-indicator" :class="{ 'status-only': statusOnly }">
<span class="recording-dot"></span> <span class="recording-dot"></span>
<span class="recording-text">{{ statusOnly ? '录制中...' : recordingTime }}</span> <span class="recording-text">{{ statusOnly ? $t('recorder.recording') : recordingTime }}</span>
</div> </div>
</div> </div>
</template> </template>
@@ -113,12 +113,12 @@ export default {
this.currentTaskId = this.taskId || ''; this.currentTaskId = this.taskId || '';
this.startTimer(); this.startTimer();
this.$message.success(this.$t('recorder.recordingStarted') || '开始录制'); this.$message.success(this.$t('recorder.recordingStarted'));
this.$emit('recording-started'); this.$emit('recording-started');
} catch (error) { } catch (error) {
console.error('启动录制失败:', error); console.error('启动录制失败:', error);
this.$message.error(this.$t('recorder.startFailed') || '启动录制失败'); this.$message.error(this.$t('recorder.startFailed'));
} finally { } finally {
this.loading = false; this.loading = false;
} }
@@ -145,7 +145,7 @@ export default {
} catch (error) { } catch (error) {
console.error('停止录制失败:', error); console.error('停止录制失败:', error);
this.$message.error(this.$t('recorder.stopFailed') || '停止录制失败'); this.$message.error(this.$t('recorder.stopFailed'));
} finally { } finally {
this.loading = false; this.loading = false;
} }
@@ -153,7 +153,7 @@ export default {
async cancelRecording() { async cancelRecording() {
await this.stopRecording(false); await this.stopRecording(false);
this.$message.info('录制已取消'); this.$message.info(this.$t('recorder.recordingCanceled'));
}, },
async saveRecording(customPath) { async saveRecording(customPath) {
@@ -176,7 +176,7 @@ export default {
const result = await ipcRenderer.invoke('stop-recording', base64data, this.currentTaskId, customPath); const result = await ipcRenderer.invoke('stop-recording', base64data, this.currentTaskId, customPath);
if (result.success) { if (result.success) {
this.$message.success(this.$t('recorder.savedSuccess') || `录制已保存: ${result.fileName}`); this.$message.success(this.$t('recorder.savedSuccess') + `: ${result.fileName}`);
this.$emit('recording-saved', result); this.$emit('recording-saved', result);
} else { } else {
this.$message.error(result.message); this.$message.error(result.message);
@@ -186,7 +186,7 @@ export default {
} catch (error) { } catch (error) {
console.error('保存录制失败:', error); console.error('保存录制失败:', error);
this.$message.error(this.$t('recorder.saveFailed') || '保存录制失败'); this.$message.error(this.$t('recorder.saveFailed'));
} }
}, },
@@ -1,11 +1,12 @@
<template> <template>
<el-dialog :title="$t('work.senior') || '高级设置'" :visible.sync="visibleSync" width="780px" append-to-body <el-dialog :title="$t('work.senior')" :visible.sync="visibleSync" width="780px" append-to-body
custom-class="grand-dialog" :close-on-click-modal="false" top="5vh" @close="handleClose"> custom-class="grand-dialog" :close-on-click-modal="false" top="5vh" @close="handleClose">
<div class="grand-setting-content" style="max-height: 75vh; overflow-y: auto; padding-right: 10px;"> <div class="grand-setting-content" style="max-height: 75vh; overflow-y: auto; padding-right: 10px;">
<el-form :model="form" label-position="right" label-width="120px" size="small"> <el-form :model="form" label-position="right" label-width="120px" size="small">
<!-- 动态分模式渲染 --> <!-- 动态分模式渲染 -->
<basic-config :form="form" :file-form="fileForm" :options="options" /> <basic-config :form="form" :file-form="fileForm" :options="options" :printer-list="printerList"
:size-form="sizeForm" />
<!-- 高级功能ISO/ZIP/HASH/计数器 --> <!-- 高级功能ISO/ZIP/HASH/计数器 -->
<advanced-features :form="form" :file-form="fileForm" /> <advanced-features :form="form" :file-form="fileForm" />
@@ -54,6 +55,14 @@ export default {
options: { options: {
type: Object, type: Object,
default: () => ({}) default: () => ({})
},
printerList: {
type: Array,
default: () => []
},
sizeForm: {
type: [Number, String],
default: null
} }
}, },
computed: { computed: {
@@ -74,32 +83,32 @@ export default {
// 验证加密狗计数 // 验证加密狗计数
if (this.form.is_dongle_count) { if (this.form.is_dongle_count) {
if (!this.form.dongle_count || this.form.dongle_count <= 0 || !Number.isInteger(this.form.dongle_count)) { if (!this.form.dongle_count || this.form.dongle_count <= 0 || !Number.isInteger(this.form.dongle_count)) {
this.$message.warning(this.$t('work.dongleCountRequired') || '请输入有效的加密狗安装次数(必须是正整数)') this.$message.warning(this.$t('work.dongleCountRequired'))
return return
} }
} }
// 验证 ISO 文件名 // 验证 ISO 文件名
if (this.form.is_generate_iso && !this.form.iso_file_name) { if (this.form.is_generate_iso && !this.form.iso_file_name) {
this.$message.warning(this.$t('work.isoNameInput') || '请输入 ISO 文件名') this.$message.warning(this.$t('work.isoNameInput'))
return return
} }
// 验证 ZIP 文件名 // 验证 ZIP 文件名
if (this.form.is_generate_zip) { if (this.form.is_generate_zip) {
if (!this.form.zip_file_name) { if (!this.form.zip_file_name) {
this.$message.warning(this.$t('work.zipNameInput') || '请输入 ZIP 文件名') this.$message.warning(this.$t('work.zipNameInput'))
return return
} }
// 验证 ZIP 加密密码 // 验证 ZIP 加密密码
if (this.form.is_zip_encrypt) { if (this.form.is_zip_encrypt) {
if (!this.form.zip_password) { if (!this.form.zip_password) {
this.$message.warning(this.$t('work.pleasePassword') || '请输入 ZIP 压缩密码') this.$message.warning(this.$t('work.pleasePassword'))
return return
} }
if (this.form.zip_password !== this.form.zip_repassword) { if (this.form.zip_password !== this.form.zip_repassword) {
this.$message.warning(this.$t('work.zipPassWrong') || 'ZIP 压缩密码不一致') this.$message.warning(this.$t('work.zipPassWrong'))
return return
} }
} }
@@ -0,0 +1,96 @@
<template>
<el-popover v-if="guideStep && guideStep[step]" :placement="guideStep[step].placement" width="250" trigger="manual"
v-model="guideStep[step].show">
<div class="guide_box">
<div class="guide_title">
{{ $t('guide.title') }}<span>{{ parseInt(currentStep) + 1 }}/{{ guideStep.length }}</span>
</div>
<div class="guide_desc">{{ $t(`guide.step${step + 1}`) }}</div>
<div class="guide_btns">
<el-button @click="$emit('exit-guide')" class="guide_btn1" size="mini" type="text">
{{ $t('guide.skip') }}
</el-button>
<el-button v-if="parseInt(currentStep) > 0" @click="$emit('prev-step')" class="guide_btn1" size="mini">
{{ $t('guide.prev') }}
</el-button>
<el-button @click="$emit('next-step')" class="guide_btn2" size="mini" type="primary">
{{ currentStep == guideStep.length - 1 ? $t('guide.complete') : $t('guide.next') }}
</el-button>
</div>
</div>
<div slot="reference" :class="{ guide_body: currentStep == step }">
<slot></slot>
</div>
</el-popover>
<div v-else>
<slot></slot>
</div>
</template>
<script>
export default {
name: 'GuidePopover',
props: {
step: {
type: Number,
required: true
},
guideStep: {
type: [Object, Array],
default: null
},
currentStep: {
type: [Number, String],
default: 0
}
}
}
</script>
<style scoped>
.guide_body {
position: relative;
z-index: 9999;
background-color: white;
border-radius: 4px;
}
.guide_box {
padding: 10px;
}
.guide_title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin-bottom: 10px;
}
.guide_title span {
font-size: 12px;
color: #909399;
font-weight: normal;
}
.guide_desc {
font-size: 14px;
color: #606266;
line-height: 1.5;
margin-bottom: 15px;
}
.guide_btns {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.guide_btn1 {
color: #909399;
}
.guide_btn2 {
background-color: #409EFF;
border-color: #409EFF;
}
</style>
+3 -3
View File
@@ -12,10 +12,10 @@
:value="item.value" /> :value="item.value" />
</el-select> </el-select>
<el-button size="small" @click="$emit('open-design')"> <el-button size="small" @click="$emit('open-design')">
{{ $t('work.design') || '创建标签' }} {{ $t('work.design') }}
</el-button> </el-button>
<el-button size="small" @click="$emit('open-file')"> <el-button size="small" @click="$emit('open-file')">
{{ $t('work.import') || '选择标签' }} {{ $t('work.import') }}
</el-button> </el-button>
</div> </div>
</div> </div>
@@ -44,7 +44,7 @@
<div class="metadata-container mt-10"> <div class="metadata-container mt-10">
<div class="sub-title"> <div class="sub-title">
<i class="el-icon-edit-outline"></i> <i class="el-icon-edit-outline"></i>
<span>{{ $t('work.metadataEdit') || '标签内容编辑' }}</span> <span>{{ $t('work.metadataEdit') }}</span>
</div> </div>
<el-table v-if="tableData && tableData.length > 0" :data="tableData" class="metadata-table flex-grow-table" <el-table v-if="tableData && tableData.length > 0" :data="tableData" class="metadata-table flex-grow-table"
:empty-text="$t('work.nodata')" :show-header="false"> :empty-text="$t('work.nodata')" :show-header="false">
+23 -8
View File
@@ -1,17 +1,23 @@
<template> <template>
<div class="task-header-container"> <div class="task-header-container">
<div class="task-header-flex"> <div class="task-header-flex">
<!-- 容量选择 --> <!-- 容量选择 - 步骤8 -->
<guide-popover :step="8" :guide-step="guideStep" :current-step="currentStep"
@exit-guide="$emit('exit-guide')" @prev-step="$emit('prev-step')" @next-step="$emit('next-step')">
<div class="header-item"> <div class="header-item">
<label class="inline-label">{{ $t('work.size') }}</label> <label class="inline-label">{{ $t('work.size') }}</label>
<el-select v-model="sizeFormLocal" class="header-select size-select" size="small" <el-select v-model="sizeFormLocal" class="header-select size-select" size="small"
@change="$emit('update:size_form', $event)" :placeholder="$t('work.pleaseSelect')"> @change="$emit('update:size_form', $event)" :placeholder="$t('work.pleaseSelect')">
<el-option v-for="item in sizeTypeOptions" :key="item.value" :label="item.label" <el-option v-for="item in sizeTypeOptions" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value"
:disabled="filterPassedType && filterPassedType.length > 0 && filterPassedType.indexOf(item.value) == -1" />
</el-select> </el-select>
</div> </div>
</guide-popover>
<!-- 拷贝类型 (work.content screenshot 中显示为 "拷贝类型" 附近位置 ) --> <!-- 拷贝类型 - 步骤9 -->
<guide-popover :step="9" :guide-step="guideStep" :current-step="currentStep"
@exit-guide="$emit('exit-guide')" @prev-step="$emit('prev-step')" @next-step="$emit('next-step')">
<div class="header-item"> <div class="header-item">
<label class="inline-label">{{ $t('work.content') }}</label> <label class="inline-label">{{ $t('work.content') }}</label>
<el-select v-model="fileFormLocal" class="header-select" size="small" <el-select v-model="fileFormLocal" class="header-select" size="small"
@@ -20,6 +26,7 @@
:value="item.value" /> :value="item.value" />
</el-select> </el-select>
</div> </div>
</guide-popover>
<!-- 分区模式 (如果需要显示) --> <!-- 分区模式 (如果需要显示) -->
<div class="header-item" v-if="false"> <div class="header-item" v-if="false">
@@ -41,14 +48,22 @@
</template> </template>
<script> <script>
import GuidePopover from './GuidePopover.vue'
export default { export default {
name: 'TaskHeader', name: 'TaskHeader',
components: {
GuidePopover
},
props: { props: {
juanbiao_form: String, juanbiao_form: String,
file_form: Number, file_form: Number,
size_form: [Number, String], size_form: [Number, String],
type_form: Number, type_form: Number,
sizeType: Array sizeType: Array,
filterPassedType: Array,
guideStep: [Object, Array],
currentStep: [Number, String]
}, },
data() { data() {
return { return {
@@ -89,10 +104,10 @@ export default {
}, },
partitionOptions() { partitionOptions() {
return [ return [
{ value: 0, label: this.$t("work.diskPart") || '普通分区' }, { value: 0, label: this.$t("work.diskPart") },
{ value: 1, label: this.$t("work.cdPart") || '光盘分区' }, { value: 1, label: this.$t("work.cdPart") },
{ value: 3, label: this.$t("work.forbidCopyPart") || '防拷贝分区' }, { value: 3, label: this.$t("work.forbidCopyPart") },
{ value: 5, label: this.$t("work.cdWithDisk") || '光盘+普通' } { value: 5, label: this.$t("work.cdWithDisk") }
] ]
} }
} }
+623 -178
View File
@@ -6,7 +6,8 @@
<!-- 左侧配置表单 --> <!-- 左侧配置表单 -->
<div class="header-settings"> <div class="header-settings">
<task-header :file_form.sync="file_form" :size_form.sync="size_form" :type_form.sync="type_form" <task-header :file_form.sync="file_form" :size_form.sync="size_form" :type_form.sync="type_form"
:size-type="sizeType" /> :size-type="sizeType" :filter-passed-type="filterPassedType" :guide-step="guideStep"
:current-step="currentStep" @exit-guide="exitGuide" @prev-step="prevStep" @next-step="nextStep" />
</div> </div>
<!-- 右侧功能按钮 --> <!-- 右侧功能按钮 -->
@@ -34,7 +35,8 @@
<!-- 隐藏的组件 --> <!-- 隐藏的组件 -->
<advanced-settings :visible.sync="highSettingVisible" :form="high_setting_form" :file-form="file_form" <advanced-settings :visible.sync="highSettingVisible" :form="high_setting_form" :file-form="file_form"
@save="saveHighSettings" @test-recording="handleTestRecording" /> :printer-list="printerList" :size-form="size_form" @save="saveHighSettings"
@test-recording="handleTestRecording" />
<network-auth-dialog :visible="networkAuthVisible" :network-paths="networkAuthPaths" <network-auth-dialog :visible="networkAuthVisible" :network-paths="networkAuthPaths"
@confirm="onNetworkAuthConfirm" @cancel="onNetworkAuthCancel" /> @confirm="onNetworkAuthConfirm" @cancel="onNetworkAuthCancel" />
</div> </div>
@@ -217,11 +219,26 @@ export default {
zip_repassword: '', zip_repassword: '',
copy_hash: false, copy_hash: false,
is_dongle_count: false, is_dongle_count: false,
dongle_count: 1 dongle_count: 1,
auth_code: ''
} }
} }
}, },
watch: {
filterPassedType: {
handler() { this.autoSelectCapacity() },
immediate: true
},
sizeType: {
handler() { this.autoSelectCapacity() },
immediate: true
}
},
computed: { computed: {
// 容量选项 (从props同步或处理)
sizeTypeOptions() {
return this.sizeType
},
file_percent() { file_percent() {
if (!this.size_form || isNaN(parseFloat(this.size_form))) return 0 if (!this.size_form || isNaN(parseFloat(this.size_form))) return 0
let mb = parseFloat(this.size_form) * 931.3 let mb = parseFloat(this.size_form) * 931.3
@@ -269,6 +286,34 @@ export default {
this.cancelRecordingIfActive() this.cancelRecordingIfActive()
}, },
methods: { methods: {
autoSelectCapacity() {
if (!this.sizeType || this.sizeType.length === 0) return
// 获取有效选项
let validOptions = this.sizeType
if (this.filterPassedType && this.filterPassedType.length > 0) {
validOptions = this.sizeType.filter(item =>
this.filterPassedType.indexOf(item.value) !== -1
)
}
// 如果没有有效选项,直接返回
if (validOptions.length === 0) return
// 检查当前选中值是否有效
const isCurrentValid = this.size_form && validOptions.find(o => o.value === this.size_form)
// 如果当前值无效(或者未选中)且只有唯一有效选项,则自动选中
// 或者:强制选中第一个有效选项(如果当前值无效)
if (!isCurrentValid) {
if (validOptions.length > 0) {
this.size_form = validOptions[0].value
}
}
},
exitGuide() {
this.$emit('exit-guide')
},
initData() { initData() {
const high = localStorage.getItem('high_setting_form') const high = localStorage.getItem('high_setting_form')
if (high) { if (high) {
@@ -322,6 +367,7 @@ export default {
}, },
saveHighSettings() { saveHighSettings() {
localStorage.setItem('high_setting_form', JSON.stringify(this.high_setting_form)) localStorage.setItem('high_setting_form', JSON.stringify(this.high_setting_form))
// eslint-disable-next-line
this.$message.success(this.$t('dispose.successReserve')) this.$message.success(this.$t('dispose.successReserve'))
this.highSettingVisible = false this.highSettingVisible = false
}, },
@@ -513,248 +559,608 @@ export default {
// --- 提交逻辑 --- // --- 提交逻辑 ---
async upload() { async upload() {
console.log('--- 开始提交作业 ---')
// 退出新手引导
if (this.guideStep) {
this.exitGuide()
}
// ========== 前置验证(所有场景共用)==========
// 1. 容量选择验证
if (!this.size_form) { if (!this.size_form) {
console.warn('未选择容量')
return this.$message.warning(this.$t('work.size_form_error')) return this.$message.warning(this.$t('work.size_form_error'))
} }
// 检查容量限制 // 2. 初始化文件状态(对齐 legacy)
if (!this.high_setting_form.Span_USBcard) { for (let i in this.$refs.files.filesList) {
const maxSize = (this.size_form * 1000 / 1.024 / 1.024 / 1.024) * 1024 * 1024 this.$refs.files.filesList[i].state = false
if (this.size > maxSize) return this.$message.warning(this.$t('work.sizeExtra')) }
this.$refs.files.nowstate = true
// ========== 核心分支:基于 allNumber 判断 ==========
if (this.$refs.files.allNumber > 0) {
// ============ 有内容文件的分支 ============
console.log('检测到内容文件数量:', this.$refs.files.allNumber)
// 容量限制检查(非跨卡模式)
if (!this.high_setting_form.Span_USBcard && this.size > ((this.size_form * 1000) / 1.024 / 1.024 / 1.024) * 1024 * 1024) {
return this.$message.warning(this.$t('work.sizeExtra'))
} }
// ISO/ZIP 前置验证 // 双重校验(防御性编程,理论上不会触发)
if (this.high_setting_form.is_generate_iso && !this.high_setting_form.iso_file_name) { if (this.$refs.files.allNumber == 0) {
return this.$message.warning(this.$t('work.pleaseUploadContent'))
}
// 设置内容上传标志
this.flag_cont_up = true
this.upload_flag = true
// 本地文件模式判断
if (this.high_setting_form.localfiles) {
console.log('本地文件模式,跳过内容上传')
return // 直接返回,等待外部触发或用户操作
}
// 检查文件计算状态
let t = true
for (let i in this.$refs.files.filesList) {
if (this.$refs.files.filesList[i].size == -1) {
t = false
}
}
if (!t) {
return this.$message.warning(this.$t('work.waitCalculate'))
}
// 设置上传参数并启动
this.$refs.files.isCopy = this.isCopy
this.$refs.files.copyPath = this.shareDisk + '\\\\' + this.upload_disk + '\\\\data\\\\'
this.$refs.files.resume(this.file_form)
} else {
// ============ 无内容文件的分支(只有标签)============
console.log('无内容文件,进入标签上传流程')
// 构建 FormData
let files_n_incr = 1
let data1 = new FormData()
// 标签文件校验与添加
if (this.isNew) {
// 新建模式:必须有 CS 文件
if (this.fileLists[0]) {
data1.append(`file${files_n_incr}`, this.fileLists[0])
files_n_incr++
} else {
return this.$message.warning(this.$t('work.pleaseUploadTag'))
}
} else {
// 编辑模式:必须有 fileData 或 fileLists[0]
if (this.fileData && !this.fileLists[0]) {
// 纯打开,上传 AS 文件(JSON)
let _file = new File([JSON.stringify(this.fileData)], this.saveWorkList.taskName, { type: 'text/plain' })
data1.append(`file${files_n_incr}`, _file)
files_n_incr++
} else if (this.fileData && this.fileLists[0]) {
// 打开后重新选择了 CS 文件
data1.append(`file${files_n_incr}`, this.fileLists[0])
files_n_incr++
} else {
return this.$message.warning(this.$t('work.pleaseUploadTag'))
}
}
// CSV 合并文件
if (this.$refs.refFile2.files.length != 0) {
data1.append(`file${files_n_incr}`, this.$refs.refFile2.files[0])
data1.append(`csv`, true)
files_n_incr++
} else {
data1.append(`csv`, false)
}
// 元数据字段(图片、文本、条码)
for (let item of this.tableData) {
if (item.type == 1 && this.metadataFiles[item.origin_name] && this.$refs.refFile2.files.length != 0) {
// 有合并文件的图片
data1.append(`file${files_n_incr}`, this.metadataFiles[item.origin_name])
files_n_incr++
} else if (item.type == 1 && this.metadataFiles[item.origin_name] && this.$refs.refFile2.files.length == 0) {
// 无合并文件的图片
data1.append(item.origin_name, this.metadataFiles[item.origin_name])
} else if ((item.type == 3 || item.type == 5) && this.$refs.refFile2.files.length == 0) {
// 文本与条形码
let data = this.form[item.origin_name]
if (data == '' || data == undefined || data == null) {
data = item.default
}
data1.append(item.origin_name, data)
} else if (item.type == 4 && this.$refs.refFile2.files.length == 0) {
// 二维码
data1.append(item.origin_name, this.form[item.origin_name])
}
}
// 上传标签文件
this.$message({ offset: 100, message: this.$t('work.uploadingTag') })
this.$axios({
method: 'post',
url: '/upload/' + this.upload_disk,
headers: { 'Content-Type': 'multipart/form-data;boundary=' + new Date().getTime() },
data: data1
}).then((res) => {
this.submit() // 调用提交函数
})
}
},
upload_over() {
if (this.flag_cont_up) {
// 检查是否需要上传标签(只有内容时不上传标签)
let skipTagUpload = false
// 1. 检查是否有标签文件
let hasTagFile = false
if (this.isNew) {
if (this.fileLists && this.fileLists.length > 0) {
hasTagFile = true
}
} else {
if (this.fileData || (this.fileLists && this.fileLists.length > 0)) {
hasTagFile = true
}
}
// 2. 检查是否有 CSV 合并文件
const hasCsv = this.$refs.refFile2 && this.$refs.refFile2.files && this.$refs.refFile2.files.length > 0
// 3. 检查是否有实际的图片元数据文件
const hasImageFiles = !!(this.metadataFiles && Object.keys(this.metadataFiles).length > 0)
// 判断:如果没有任何标签相关内容,跳过标签上传
if (!hasTagFile && !hasCsv && !hasImageFiles) {
skipTagUpload = true
}
if (skipTagUpload) {
this.performSubmit()
} else {
this.submitAndTag()
}
} else {
this.performSubmit()
}
},
async submit() {
// 停止录制(如果正在录制)
await this.stopRecordingIfActive()
// 检查是否有网络路径需要认证
if (this.checkNetworkPaths && this.checkNetworkPaths()) {
return // 等待用户完成网络认证
}
// 继续提交流程
this.performSubmit()
},
async submitAndTag() {
const data1 = new FormData()
let files_n_incr = 1
// 1. 标签文件 (Label File)
let hasLabelFile = false
if (this.isNew) {
if (this.fileLists && this.fileLists[0]) {
data1.append(`file${files_n_incr}`, this.fileLists[0])
files_n_incr++
hasLabelFile = true
}
} else {
if (this.fileData && !this.fileLists[0]) {
// 纯打开,上传 AS 文件 (JSON)
let _file = new File([JSON.stringify(this.fileData)], this.saveWorkList.taskName, { type: 'text/plain' })
data1.append(`file${files_n_incr}`, _file)
files_n_incr++
hasLabelFile = true
} else if (this.fileData && this.fileLists[0]) {
// 重新选择了 CS 文件
data1.append(`file${files_n_incr}`, this.fileLists[0])
files_n_incr++
hasLabelFile = true
}
}
// 校验:若开启标签但无文件且无内容区文件
if (!hasLabelFile && this.switch_tag) {
const hasContentFiles = this.$refs.files && this.$refs.files.allNumber > 0;
if (!hasContentFiles) {
return this.$message.warning(this.$t('work.pleaseUploadTag'))
}
}
// 2. CSV 合并文件
const hasCsv = this.$refs.refFile2 && this.$refs.refFile2.files && this.$refs.refFile2.files.length > 0
if (hasCsv) {
data1.append(`file${files_n_incr}`, this.$refs.refFile2.files[0])
data1.append(`csv`, true)
files_n_incr++
} else {
data1.append(`csv`, false)
}
// 3. 元数据 (图片、文本、条码)
if (this.tableData && this.tableData.length > 0) {
for (let item of this.tableData) {
// 图片类型 (Type 1)
if (item.type == 1 && this.metadataFiles[item.origin_name]) {
const file = this.metadataFiles[item.origin_name]
if (hasCsv) {
// 有CSV时,图片按 file{n} 顺序添加
data1.append(`file${files_n_incr}`, file)
files_n_incr++
} else {
// 无CSV时,图片按字段名添加
data1.append(item.origin_name, file)
}
}
// 文本/条码类型 (Type 3, 5) - 仅在无CSV时添加
else if ((item.type == 3 || item.type == 5) && !hasCsv) {
let data = this.form[item.origin_name]
if (data == '' || data === undefined || data === null) {
data = item.default || ''
}
data1.append(item.origin_name, data)
}
// 二维码类型 (Type 4) - 仅在无CSV时添加
else if (item.type == 4 && !hasCsv) {
let data = this.form[item.origin_name] || ''
data1.append(item.origin_name, data)
}
}
}
// 4. 发送请求
this.$message.info(this.$t('work.uploadingTag'))
let pathName
if (this.high_setting_form.localfiles) {
// 若开启本地文件,需获取本地路径名称
const rootFile = this.$refs.files && this.$refs.files.getLists && this.$refs.files.getLists()[0]; // 假设逻辑
// 这里实际上 work-副本 使用 upload_disk 或者 rootFile name,这里保持 upload_disk 除非是 pathName 逻辑差异
// work-副本 逻辑: localfiles ? filePath.name : upload_disk
if (this.high_setting_form.localfiles) {
// 获取根文件夹名
// 由于 fileManagement 封装,我们需要更稳健的获取方式
// 暂时使用 upload_disk,待 localUpload 逻辑覆盖
pathName = this.upload_disk // 这里的差异在 submit 逻辑中处理,Tag 上传通常还是到 upload_disk 临时目录?
// work-副本: localfiles ? filePath.name : this.upload_disk
// 这里保持一致性
pathName = this.upload_disk
} else {
pathName = this.upload_disk
}
} else {
pathName = this.upload_disk
}
// 修正:如果 localfiles 为真,work-副本 实际上是把 tag 文件上传到以 filePath.name 命名的目录
// 但这里简化处理,先上传 tag,后续 localUpload 会处理 content
// 实际上 submitAndTag 是为了上传 tag 文件,localUpload 是为了处理 content 文件的 path.json
this.$axios.post('/upload/' + this.upload_disk, data1).then(() => {
this.performSubmit()
}).catch(err => {
console.error(err)
this.$message.error(this.$t('work.uploadFail'))
})
},
async performSubmit() {
let that = this;
try {
await this.stopRecordingIfActive()
} catch (e) {
console.error('停止录像失败:', e)
}
// 检查是否有网络路径需要认证
if (this.checkNetworkPaths && this.checkNetworkPaths()) {
return
}
// 1. 确定 pathName
let pathName
if (that.high_setting_form.localfiles) {
//打开本地选项
const uploader = this.$refs.files && this.$refs.files.uploader
let rootFile = uploader && uploader.getRoot()
if (!rootFile || rootFile.fileList.length != 1) {
this.$message.warning(this.$t('work.oneFolder'))
return
}
let filePath = rootFile.fileList[0]
if (!filePath.isFolder) {
this.$message.warning(this.$t('work.notFolder'))
return
}
pathName = filePath.name
} else {
pathName = this.upload_disk
}
// 2. 构建 data_param
let data_param = 'CardSoon_File=' + pathName
// 3. 构建 data (严格按照 legacy 顺序)
let data = ''
// 3.1 ISO/ZIP 验证(仅在有内容文件时)
if (this.$refs.files.allNumber > 0) {
// ISO 文件名检查
if (that.high_setting_form.is_generate_iso) {
if (!that.high_setting_form.iso_file_name) {
this.submitLoading = false
return this.$message.warning(this.$t('work.isoNameInput')) return this.$message.warning(this.$t('work.isoNameInput'))
} }
if (this.high_setting_form.is_generate_zip) { }
if (!this.high_setting_form.zip_file_name) return this.$message.warning(this.$t('work.zipNameInput'))
if (this.high_setting_form.is_zip_encrypt) { // ZIP 文件名检查
if (!this.high_setting_form.zip_password) return this.$message.warning(this.$t('work.pleasePassword')) if (that.high_setting_form.is_generate_zip) {
if (this.high_setting_form.zip_password !== this.high_setting_form.zip_repassword) { if (!that.high_setting_form.zip_file_name) {
this.submitLoading = false
return this.$message.warning(this.$t('work.zipNameInput'))
}
}
// ZIP 加密密码检查
if (that.high_setting_form.is_generate_zip && that.high_setting_form.is_zip_encrypt) {
if (!that.high_setting_form.zip_password || that.high_setting_form.zip_password !== that.high_setting_form.zip_repassword) {
this.submitLoading = false
return this.$message.warning(this.$t('work.zipPassWrong')) return this.$message.warning(this.$t('work.zipPassWrong'))
} }
} }
} }
const hasFiles = this.$refs.files && this.$refs.files.allNumber > 0; // 3.2 标签文件验证与参数构建(仅在有标签文件时)
if (hasFiles) { if ((!this.isNew && this.fileData) || (this.isNew && this.fileLists[0])) {
console.log('检测到待上传文件数量:', this.$refs.files.allNumber) // 标签开启校验
this.flag_cont_up = true if (this.isNew && this.fileLists.length == 0) {
this.$refs.files.resume(this.file_form) this.submitLoading = false
} else { return this.$message.warning(this.$t('work.pleaseUploadTag'))
console.log('无待上传文件或未打开内容管理,直接执行提交')
this.upload_over()
} }
}, if (!this.isNew && !this.fileData) {
upload_over() { this.submitLoading = false
console.log('文件上传/准备就绪, flag_cont_up:', this.flag_cont_up)
if (this.flag_cont_up) {
this.submitAndTag()
} else {
this.performSubmit()
}
},
async submitAndTag() {
console.log('--- 执行 submitAndTag ---')
// 这里的逻辑处理标签文件的上传
const data1 = new FormData()
let hasFile = false
if (this.isNew) {
if (this.fileLists[0]) {
data1.append('file1', this.fileLists[0])
hasFile = true
}
} else if (this.fileData) {
const _file = new File([JSON.stringify(this.fileData)], this.saveWorkList.taskName, { type: 'text/plain' })
data1.append('file1', _file)
hasFile = true
}
if (!hasFile && this.switch_tag) {
console.warn('标签管理已打开但未上传标签文件')
return this.$message.warning(this.$t('work.pleaseUploadTag')) return this.$message.warning(this.$t('work.pleaseUploadTag'))
} }
// 添加 CSV 文件 if (this.fileData && !this.fileLists[0]) {
if (this.$refs.refFile2 && this.$refs.refFile2.files[0]) { data_param += '&Json_File=' + this.saveWorkList.taskName
data1.append('file2', this.$refs.refFile2.files[0]) } else if (this.fileData && this.fileLists[0]) {
} data_param += '&Json_File=' + this.fileLists[0].name
// 添加 Bin/Img 文件 (refFile3)
if (this.$refs.refFile3 && this.$refs.refFile3.files[0]) {
data1.append('file3', this.$refs.refFile3.files[0])
} }
// 添加元数据图片 if (this.$refs.refFile2.files.length != 0) {
if (this.tableData && this.tableData.length > 0) { data_param += '&Udf_File=file:' + this.$refs.refFile2.files[0].name
this.tableData.forEach(row => {
if (row.type == 1 && this.metadataFiles[row.origin_name]) {
data1.append(row.origin_name, this.metadataFiles[row.origin_name])
}
})
} }
this.$message.info(this.$t('work.uploadingTag')) // 打印面数校验
const pathName = this.high_setting_form.localfiles ? 'local' : this.upload_disk if (this.fileData) {
if ((this.print_flag == 1 && this.fileData.flag != 1) || (this.print_flag == 2 && this.fileData.flag == 3) || (this.print_flag == 3 && this.fileData.flag == 2)) {
this.$axios.post('/upload/' + pathName, data1).then(() => { this.submitLoading = false
this.performSubmit() return this.$message.warning(this.$t('work.print_flagError'))
}).catch(err => {
this.$message.error(this.$t('work.uploadFail'))
})
},
async performSubmit() {
console.log('--- 执行 performSubmit ---')
try {
await this.stopRecordingIfActive()
console.log('录像停止检查完成')
} catch (e) {
console.error('停止录像失败:', e)
} }
this.submitLoading = true }
console.log('submitLoading 已设为 true') data += '&print_flag=' + this.print_flag
// 构建原始参数字符串
let data_param = 'CardSoon_File=' + (this.high_setting_form.localfiles ? 'local' : this.upload_disk)
console.log('--- 提交作业数据预览 ---')
console.log('任务ID:', this.upload_disk)
console.log('高级设置:', JSON.parse(JSON.stringify(this.high_setting_form)))
// 拼接标签文件、CSV等参数(简化演示,实际应完整复制)
let data = `&label=${encodeURIComponent(this.juanbiao_form)}`
data += `&printCopys=${this.number}`
data += `&disk_size=${this.size_form}`
data += `&zone_type=${this.type_form}`
data += `&hasPrintTask=${!!this.switch_tag}`
data += `&hasCopyTask=${this.$refs.files ? this.$refs.files.allNumber > 0 : false}`
data += `&copy_cache_data=${this.isCopy}`
data += `&SpanUcard=${this.high_setting_form.Span_USBcard}`
data += `&hash=${this.high_setting_form.s1}`
data += `&md5=${this.high_setting_form.s2}`
data += `&printer=${this.high_setting_form.target_work}`
if (this.high_setting_form.formatFile !== 0) {
data += `&formatFile=${this.high_setting_form.formatFile}`
} }
// --- 兼容旧版字段与新增强制提交字段 --- // 3.3 卷标验证(所有场景必填)
// 基础开关 if (this.juanbiao_form == '') {
data += `&local=${!!this.high_setting_form.localfiles}` this.submitLoading = false
data += `&version=local` // 单机版标识 return this.$message.warning(this.$t('work.juanbiaoInput'))
data += `&hasAddFile=${!!this.high_setting_form.hasAddFile}` // 拷贝附加文件
// ISO/ZIP 高级功能
data += `&is_generate_iso=${!!this.high_setting_form.is_generate_iso}`
data += `&iso_file_name=${encodeURIComponent(this.high_setting_form.iso_file_name || '')}`
data += `&is_generate_zip=${!!this.high_setting_form.is_generate_zip}`
data += `&zip_file_name=${encodeURIComponent(this.high_setting_form.zip_file_name || '')}`
data += `&is_zip_encrypt=${!!this.high_setting_form.is_zip_encrypt}`
data += `&zip_password=${encodeURIComponent(this.high_setting_form.zip_password || '')}`
// 硬件与安全
data += `&copy_hash=${!!this.high_setting_form.copy_hash}`
data += `&enable_dongle_counter=${!!this.high_setting_form.is_dongle_count}`
data += `&donglel_install_count=${this.high_setting_form.dongle_count || 0}`
// 录像与标识
data += `&is_blend=${!!this.high_setting_form.is_blend}`
data += `&is_printer_record_logo=${!!this.high_setting_form.is_print_logo}`
// 录像路径逻辑:如果正在录像或已结束,则传递路径
if (this.high_setting_form.is_record) {
// 优先使用录像组件反馈的路径,否则使用配置路径
const videoPath = (this.$refs.screenRecorder && this.$refs.screenRecorder.videoPath) || this.high_setting_form.record_path
data += `&record_path=${encodeURIComponent(videoPath || '')}`
} else {
data += `&record_path=`
} }
// 文件类型映射 (0:File -> 1, 1:ISO -> 2, 2:Encrypt -> 3, 4:Forbid -> 4) const printStatus = this.fileLists[0] ? true : false
const fileTypeMap = { 0: 1, 1: 2, 2: 3, 4: 4 } const copyStatus = this.$refs.files.allNumber > 0 ? true : false
let apiFileType = fileTypeMap[this.file_form] || 1
data += `&file_type=${apiFileType}`
// 网络路径认证信息 (若存在) data += '&label=' + encodeURIComponent(this.juanbiao_form)
data += '&printCopys=' + this.number
data += '&disk_size=' + this.size_form
data += '&zone_type=' + this.type_form
data += '&hasPrintTask=' + printStatus
data += '&hasCopyTask=' + copyStatus
data += '&copy_cache_data=' + this.isCopy
data += '&SpanUcard=' + this.high_setting_form.Span_USBcard
data += '&hasAddFile=' + this.high_setting_form.hasAddFile
data += '&version=local'
data += '&hash=' + this.high_setting_form.s1
data += '&md5=' + this.high_setting_form.s2
data += '&printer=' + this.high_setting_form.target_work
if (this.high_setting_form.formatFile != 0) {
data += '&formatFile=' + this.high_setting_form.formatFile
}
// 网络认证信息
if (this.networkCredentials && (Array.isArray(this.networkCredentials) ? this.networkCredentials.length > 0 : Object.keys(this.networkCredentials).length > 0)) { if (this.networkCredentials && (Array.isArray(this.networkCredentials) ? this.networkCredentials.length > 0 : Object.keys(this.networkCredentials).length > 0)) {
data += `&net_info=${encodeURIComponent(JSON.stringify(this.networkCredentials))}` data += '&net_info=' + JSON.stringify(this.networkCredentials)
} }
console.log('--- 最终提交 URL 参数 ---') // 高级设置参数 - New Fields Mapping
console.log(data_param + data) data += '&is_generate_iso=' + (String(that.high_setting_form.is_generate_iso) || 'false') +
'&iso_file_name=' + (that.high_setting_form.iso_file_name || '') +
'&is_generate_zip=' + (String(that.high_setting_form.is_generate_zip) || 'false') +
'&zip_file_name=' + (that.high_setting_form.zip_file_name || '') +
'&is_zip_encrypt=' + (String(that.high_setting_form.is_zip_encrypt) || 'false') +
'&zip_password=' + (that.high_setting_form.zip_password || '') +
'&copy_hash=' + (String(that.high_setting_form.copy_hash) || 'false') +
'&enable_dongle_counter=' + (String(that.high_setting_form.enable_dongle_counter) || 'false') +
'&auth_code=' + (that.high_setting_form.auth_code || '');
const url = '/rest/job/?' + data_param + data data += '&is_blend=' + (String(that.high_setting_form.is_blend) || 'false');
if (!this.isCopy) { // Log path logic
console.log('执行本地路径提交 (Local Mode)') if (that.high_setting_form.record_screen && that.$refs.screenRecorder && that.$refs.screenRecorder.videoPath) {
this.localUpload(this.upload_disk, data_param, data) data += '&record_path=' + that.$refs.screenRecorder.videoPath;
} else { } else {
console.log('执行普通网络提交 (Copy Mode)') data += '&record_path=';
this.$axios.post(url) }
.then(() => { data += '&is_printer_record_logo=' + (String(that.high_setting_form.print_record_logo) || 'false');
if (that.high_setting_form.enable_dongle_counter) {
data += '&donglel_install_count=' + (that.high_setting_form.install_dongle_count || 0);
} else {
data += '&donglel_install_count=0';
}
// File Type Mapping
const fileTypeMap = { 0: 1, 1: 2, 2: 3, 4: 4 };
let apiFileType = fileTypeMap[that.file_form] || 1;
data += '&file_type=' + apiFileType;
console.log('提交参数预览:', data_param + data)
// Submit Flow
if (this.isCopy) {
this.submitLoading = true
this.$axios({
method: 'post',
url: '/rest/job/?' + data_param + data
})
.then((res) => {
this.$message.success(this.$t('work.submitSuccess')) this.$message.success(this.$t('work.submitSuccess'))
that.submitLoading = false
this.$emit('jobPost') this.$emit('jobPost')
}) })
.catch((err) => { .catch((err) => {
console.error('提交任务失败:', err) const resl = err.response.data
this.$message.error(this.$t('index.fail')) console.log(resl)
if (resl.ret && resl.ret === 9) {
that.$emit('addError', { code: resl.ret, tag: 'templateFile', err: 0 })
} else {
that.$emit('addError', { code: resl.ret, tag: 'workFail', err: 0 })
}
this.$message({ offset: 100, message: this.$t('work.submiting') })
that.submitLoading = false
that.$emit('jobPost')
}) })
.finally(() => this.submitLoading = false) } else {
that.localUpload(pathName, data_param, data)
} }
}, },
localUpload(pathName, data_param, data) { localUpload(pathName, data_param, data) {
const filesList = this.$refs.files.getLists()
let file_path = [] let file_path = []
for (let i in filesList) { // 注意: 这里使用 getLists() 可能需要适配 legacy 的 filesList 结构
file_path.push(filesList[i].path) // 如果 filesList[i].path 是正确路径,则无需更改
const list = this.$refs.files.filesList // Prefer direct filesList if available like legacy
for (let i in list) {
file_path.push(list[i].path)
} }
const jsonData = { files: file_path } const jsonData = { files: file_path }
const jsonFilePath = path.join(remote.app.getPath('userData'), 'filepath.json') const jsonFilePath = path.join(remote.app.getPath('userData'), 'filepath.json') // 使用 userData 目录更安全
try { try {
fs.writeFileSync(jsonFilePath, JSON.stringify(jsonData), 'utf-8') fs.writeFileSync(jsonFilePath, JSON.stringify(jsonData), 'utf-8')
const fileContent = fs.readFileSync(jsonFilePath)
const blob = new Blob([fileContent], { type: 'application/json' }) // Legacy Stream Logic
const fileStream = fs.createReadStream(jsonFilePath)
const buffer = []
fileStream.on('data', (chunk) => {
buffer.push(chunk)
})
fileStream.on('end', () => {
let that = this
const blob = new Blob([Buffer.concat(buffer)], { type: 'application/octet-stream' })
const formData = new FormData() const formData = new FormData()
formData.append('file', blob, 'filepath.json') formData.append('file', blob, path.basename(jsonFilePath))
if (this.networkCredentials && (Array.isArray(this.networkCredentials) ? this.networkCredentials.length > 0 : Object.keys(this.networkCredentials).length > 0)) { if (this.networkCredentials && (Array.isArray(this.networkCredentials) ? this.networkCredentials.length > 0 : Object.keys(this.networkCredentials).length > 0)) {
formData.append('net_info', JSON.stringify(this.networkCredentials)) formData.append('net_info', JSON.stringify(this.networkCredentials))
} }
this.submitLoading = true that.submitLoading = true
this.$axios.post(`/upload/${pathName}`, formData).then(() => { that.$axios({
this.$axios.post('/rest/job/?' + data_param + data).then(() => { method: 'post',
url: `/upload/${pathName}`,
headers: { 'Content-Type': 'multipart/form-data;boundary=' + new Date().getTime() },
data: formData
}).then(() => {
that.$axios({
method: 'post',
url: '/rest/job/?' + data_param + data
}).then((res) => {
this.$message.success(this.$t('work.submitSuccess')) this.$message.success(this.$t('work.submitSuccess'))
that.submitLoading = false
this.$emit('jobPost') this.$emit('jobPost')
}).catch(err => { }).catch((err) => {
this.$message.error(this.$t('index.fail')) const resl = err.response && err.response.data
}).finally(() => this.submitLoading = false) if (resl && resl.ret === 9) {
that.$emit('addError', { code: resl.ret, tag: 'templateFile', err: 0 })
} else {
that.$emit('addError', { code: resl ? resl.ret : -1, tag: 'workFail', err: 0 })
}
this.$message({ offset: 100, message: this.$t('work.submiting') })
that.submitLoading = false
that.$emit('jobPost')
})
}).catch(err => { }).catch(err => {
this.$message.error('Local upload failed') this.$message.error('Local upload failed')
this.submitLoading = false that.submitLoading = false
})
}) })
} catch (e) { } catch (e) {
console.error(e)
this.$message.error('File Write Error')
this.submitLoading = false
} }
}, },
saveWork() { saveWork() {
const save = { let t = true
fileData: this.fileData, for (let i in this.$refs.files.filesList) {
tableData: this.tableData, if (this.$refs.files.filesList[i].size == -1) {
juanbiao: this.juanbiao_form, t = false
size_form: this.size_form,
type_form: this.type_form,
high_setting: this.high_setting_form
} }
dialog.showSaveDialog({ }
title: 'Save Task',
if (t) {
let save = this.fileData
save.filesList = this.$refs.files.getLists()
//save.tagFile = this.fileData;
save.allNumber = this.$refs.files.allNumber
save.size = this.size
save.file_form = this.file_form == 2 && this.isPass ? 3 : this.file_form
save.type_form = this.type_form
save.size_form = this.size_form
save.juanbiao_form = this.juanbiao_form
save.high_setting_form = this.high_setting_form
save.print_flag = this.print_flag
// save.tableData = this.tableData;
if (this.$refs.files.allNumber > 0 && this.fileLists[0]) {
save.switch = 3
} else if (this.$refs.files.allNumber > 0) {
save.switch = 1
} else {
save.switch = 2
}
const v = JSON.stringify(save)
dialog
.showSaveDialog({
title: 'Save',
filters: [{ name: 'Soon Work', extensions: ['swk'] }] filters: [{ name: 'Soon Work', extensions: ['swk'] }]
}).then(result => {
if (result.filePath) fs.writeFileSync(result.filePath, JSON.stringify(save))
}) })
.then((result) => {
fs.writeFileSync(result.filePath, v)
})
.catch((err) => {
console.log(err)
})
} else {
this.$message({
offset: 100,
message: this.$t('work.waitCalculate'),
type: 'warning'
})
}
}, },
// --- 新手引导功能 --- // --- 新手引导功能 ---
@@ -896,6 +1302,45 @@ export default {
}, },
sizeChange(size) { sizeChange(size) {
this.size = size this.size = size
},
// --- 新手引导方法 ---
exitGuide() {
if (!this.guideStep) return
for (let key in this.guideStep) {
this.guideStep[key].show = false
}
this.currentStep = -1
localStorage.setItem('currentStep', this.currentStep)
localStorage.setItem('guideStep', JSON.stringify(this.guideStep))
},
prevStep() {
if (!this.guideStep) return
this.guideStep[this.currentStep].show = false
this.currentStep = parseInt(this.currentStep) - 1
if (this.guideStep[this.currentStep]) {
this.guideStep[this.currentStep].show = true
localStorage.setItem('guideStep', JSON.stringify(this.guideStep))
localStorage.setItem('currentStep', this.currentStep)
} else {
this.exitGuide()
}
},
nextStep() {
if (!this.guideStep) return
this.guideStep[this.currentStep].show = false
this.currentStep = parseInt(this.currentStep) + 1
if (this.guideStep[this.currentStep]) {
this.guideStep[this.currentStep].show = true
localStorage.setItem('guideStep', JSON.stringify(this.guideStep))
localStorage.setItem('currentStep', this.currentStep)
} else {
this.exitGuide()
}
},
help() {
const { ipcRenderer } = require('electron')
ipcRenderer.send('open-help-file')
} }
} }
} }
@@ -1,7 +1,7 @@
<template> <template>
<div class="grand-section"> <div class="grand-section">
<div class="grand-title"> <div class="grand-title">
<span>{{ $t('work.advancedFeatures') || '高级功能' }}</span> <span>{{ $t('work.advancedFeatures') }}</span>
<div class="title-line"></div> <div class="title-line"></div>
</div> </div>
@@ -102,9 +102,12 @@
<!-- 计数器详细 --> <!-- 计数器详细 -->
<div v-if="form.is_dongle_count" class="mt-10 p-10" <div v-if="form.is_dongle_count" class="mt-10 p-10"
style="background: #fdf6ec; border-radius: 6px; border: 1px solid #faecd8;"> style="background: #fdf6ec; border-radius: 6px; border: 1px solid #faecd8;">
<el-form-item :label="$t('work.installCount')" label-width="140px" class="mb-0"> <el-form-item :label="$t('work.installCount')" label-width="140px" class="mb-5">
<el-input-number v-model="form.dongle_count" :min="1" :step="1" :precision="0" size="mini" /> <el-input-number v-model="form.dongle_count" :min="1" :step="1" :precision="0" size="mini" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('work.authCode')" label-width="140px" class="mb-0">
<el-input v-model="form.auth_code" size="mini" :placeholder="$t('work.inputAuthCode')" />
</el-form-item>
</div> </div>
</div> </div>
</template> </template>
@@ -1,12 +1,12 @@
<template> <template>
<div class="grand-section"> <div class="grand-section">
<div class="grand-title"> <div class="grand-title">
<span>{{ $t('work.basicConfig') || '基础配置' }}</span> <span>{{ $t('work.basicConfig') }}</span>
<div class="title-line"></div> <div class="title-line"></div>
</div> </div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12" v-if="fileForm !== 2"> <el-col :span="12" v-if="fileForm !== 2">
<el-form-item :label="$t('work.better') || '优先级'"> <el-form-item :label="$t('work.better')">
<el-select v-model="form.priority" class="w-full" :disabled="fileForm === 4"> <el-select v-model="form.priority" class="w-full" :disabled="fileForm === 4">
<el-option v-for="item in priorityOptions" :key="item.value" :label="item.label" <el-option v-for="item in priorityOptions" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
@@ -14,7 +14,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" v-if="fileForm !== 2"> <el-col :span="12" v-if="fileForm !== 2">
<el-form-item :label="$t('work.startWorkSpace') || '目标工作站'"> <el-form-item :label="$t('work.startWorkSpace')">
<el-select v-model="form.target_work" class="w-full" :disabled="fileForm === 4"> <el-select v-model="form.target_work" class="w-full" :disabled="fileForm === 4">
<el-option v-for="item in targetWorkOptions" :key="item.value" :label="item.label" <el-option v-for="item in targetWorkOptions" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
@@ -22,7 +22,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('work.ribbonType') || '色带类型'"> <el-form-item :label="$t('work.ribbonType')">
<el-select v-model="form.color_type" class="w-full"> <el-select v-model="form.color_type" class="w-full">
<el-option v-for="item in colorTypeOptions" :key="item.value" :label="item.label" <el-option v-for="item in colorTypeOptions" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
@@ -30,7 +30,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12" v-if="fileForm === 0 || fileForm === 2"> <el-col :span="12" v-if="fileForm === 0 || fileForm === 2">
<el-form-item :label="$t('work.formatFile') || '拷贝前格式化'"> <el-form-item :label="$t('work.formatFile')">
<el-select v-model="form.formatFile" class="w-full"> <el-select v-model="form.formatFile" class="w-full">
<el-option v-for="item in formatOptions" :key="item.value" :label="item.label" <el-option v-for="item in formatOptions" :key="item.value" :label="item.label"
:value="item.value" /> :value="item.value" />
@@ -52,30 +52,68 @@ export default {
fileForm: { fileForm: {
type: Number, type: Number,
default: 0 default: 0
},
printerList: {
type: Array,
default: () => []
},
sizeForm: {
type: [Number, String],
default: null
} }
}, },
computed: { computed: {
priorityOptions() { priorityOptions() {
return [ return [
{ value: 1, label: this.$t("work.low") || '低' }, { value: 1, label: this.$t("work.low") },
{ value: 0, label: this.$t("work.normal") || '中' }, { value: 0, label: this.$t("work.normal") },
{ value: 2, label: this.$t("work.high") || '高' } { value: 2, label: this.$t("work.high") }
] ]
}, },
targetWorkOptions() { targetWorkOptions() {
// 这里原本是从父组件传入,或者硬编码 let list = [{ value: 0, label: this.$t("work.any") }]
return [{ value: 0, label: this.$t("work.any") || '任一' }]
if (this.printerList && this.printerList.length > 0) {
const requiredSize = parseFloat(this.sizeForm)
let filtered = this.printerList
// Filter by capacity if size is selected
if (requiredSize && requiredSize > 0) {
filtered = this.printerList.filter(p => {
if (!p.PrinterType) return false
const type = p.PrinterType.toUpperCase()
if (requiredSize < 1) {
// MB case (e.g. 0.512 -> 512M)
const mb = Math.round(requiredSize * 1000)
return type.includes(mb + "M")
} else {
// GB case (e.g. 4 -> 4G)
return type.includes(requiredSize + "G")
}
})
}
// Map to options
if (filtered.length > 0) {
list = list.concat(filtered.map(p => ({
value: p.PrinterID,
label: `${p.PrinterID} (${p.PrinterType})`
})))
}
}
return list
}, },
colorTypeOptions() { colorTypeOptions() {
return [ return [
{ value: 0, label: this.$t("work.any") || '任一' }, { value: 0, label: this.$t("work.any") },
{ value: 1, label: this.$t("work.sigleColor") || '单色' }, { value: 1, label: this.$t("work.sigleColor") },
{ value: 2, label: this.$t("work.colorful") || '彩色' } { value: 2, label: this.$t("work.colorful") }
] ]
}, },
formatOptions() { formatOptions() {
return [ return [
{ value: 0, label: this.$t('work.auto') || '不格式化' }, { value: 0, label: this.$t('work.auto') },
{ value: 1, label: 'FAT32' }, { value: 1, label: 'FAT32' },
{ value: 2, label: 'exFAT' }, { value: 2, label: 'exFAT' },
{ value: 3, label: 'NTFS' } { value: 3, label: 'NTFS' }
@@ -1,7 +1,7 @@
<template> <template>
<div class="grand-section"> <div class="grand-section">
<div class="grand-title"> <div class="grand-title">
<span>{{ $t('work.hardwareControl') || '硬件管控' }}</span> <span>{{ $t('work.hardwareControl') }}</span>
<div class="title-line"></div> <div class="title-line"></div>
</div> </div>
<el-row :gutter="20"> <el-row :gutter="20">
@@ -9,12 +9,12 @@
<div class="hardware-box"> <div class="hardware-box">
<div class="mb-10"> <div class="mb-10">
<el-checkbox v-model="form.is_dongle_count"> <el-checkbox v-model="form.is_dongle_count">
{{ $t('work.installDongle') || '加密狗计数' }} {{ $t('work.installDongle') }}
</el-checkbox> </el-checkbox>
</div> </div>
<transition name="el-zoom-in-top"> <transition name="el-zoom-in-top">
<div v-if="form.is_dongle_count" class="ml-20"> <div v-if="form.is_dongle_count" class="ml-20">
<el-form-item :label="$t('work.installCount') || '安装次数'" label-width="80px"> <el-form-item :label="$t('work.installCount')" label-width="80px">
<el-input-number size="small" v-model="form.dongle_count" :min="1" :max="999" /> <el-input-number size="small" v-model="form.dongle_count" :min="1" :max="999" />
</el-form-item> </el-form-item>
</div> </div>
@@ -1,7 +1,7 @@
<template> <template>
<div class="grand-section"> <div class="grand-section">
<div class="grand-title"> <div class="grand-title">
<span>{{ $t('work.screenRecordReview') || '屏幕记录审查' }}</span> <span>{{ $t('work.screenRecordReview') }}</span>
<div class="title-line"></div> <div class="title-line"></div>
</div> </div>
<div class="feature-row mb-10"> <div class="feature-row mb-10">
+7 -2
View File
@@ -25,7 +25,8 @@ export default {
cancel: "取消", cancel: "取消",
authRequired: "请填写所有网络路径的用户名和密码", authRequired: "请填写所有网络路径的用户名和密码",
authSuccess: "网络认证信息已保存", authSuccess: "网络认证信息已保存",
authCanceled: "已取消网络路径认证" authCanceled: "已取消网络路径认证",
authSaveFail: "保存认证信息失败"
}, },
finger: { finger: {
intTips: "指纹模块正在初始化", intTips: "指纹模块正在初始化",
@@ -525,12 +526,13 @@ export default {
defaultPath: "项目根目录/videos", defaultPath: "项目根目录/videos",
recordingStatus: "录制状态", recordingStatus: "录制状态",
recording: "录制中...", recording: "录制中...",
recordingCanceled: "录制已取消",
notRecording: "未录制", notRecording: "未录制",
// 硬件管控 // 硬件管控
hardwareControl: "硬件管控", hardwareControl: "硬件管控",
installDongle: "加密狗计数", installDongle: "加密狗计数",
installCount: "安装次数", installCount: "安装次数",
setAuthCode: "设置授权码", authCode: "授权码",
inputAuthCode: "输入授权码", inputAuthCode: "输入授权码",
addContent: "添加内容", addContent: "添加内容",
addTag: "添加标签", addTag: "添加标签",
@@ -569,6 +571,9 @@ export default {
oneFolder: "特定作业只能添加一个文件夹", oneFolder: "特定作业只能添加一个文件夹",
notFolder: "添加内容不是文件夹", notFolder: "添加内容不是文件夹",
print_flagError: "打印面数不匹配,请重新选择!", print_flagError: "打印面数不匹配,请重新选择!",
cannotFindBin: "模板中没有合并字段,无法使用CSV文件",
pleaseSelectCap: "请选择容量",
dongleCountRequired: "请输入有效的加密狗安装次数(必须是正整数)",
pleaseUploadTag: "请添加标签文件", pleaseUploadTag: "请添加标签文件",
uploadingTag: "正在上传标签文件...", uploadingTag: "正在上传标签文件...",
pleaseUploadingImgBin: "请添加图片文件", pleaseUploadingImgBin: "请添加图片文件",
+12 -5
View File
@@ -6,8 +6,10 @@ export default {
ok: "OK" ok: "OK"
}, },
recorder: { recorder: {
startRecording: "Start Recording", recordingStatus: "Recording Status",
stopRecording: "Stop Recording", recording: "Recording...",
recordingCanceled: "Recording canceled",
notRecording: "Not recording",
recordingStarted: "Screen recording started", recordingStarted: "Screen recording started",
recordingStopped: "Recording stopped", recordingStopped: "Recording stopped",
savedSuccess: "Recording saved", savedSuccess: "Recording saved",
@@ -23,9 +25,10 @@ export default {
password: "Password", password: "Password",
confirm: "Confirm", confirm: "Confirm",
cancel: "Cancel", cancel: "Cancel",
authRequired: "Please fill in username and password for all network paths", authRequired: "Please enter username and password for all network paths",
authSuccess: "Network authentication information saved", authSuccess: "Network credentials saved",
authCanceled: "Network path authentication canceled" authCanceled: "Network authentication canceled",
authSaveFail: "Failed to save authentication info"
}, },
finger: { finger: {
intTips: "The fingerprint module is initializing", intTips: "The fingerprint module is initializing",
@@ -452,6 +455,7 @@ export default {
hardwareControl: "Hardware Control", hardwareControl: "Hardware Control",
installDongle: "Dongle Count", installDongle: "Dongle Count",
installCount: "Install Count", installCount: "Install Count",
authCode: "Auth Code",
setAuthCode: "Auth Code", setAuthCode: "Auth Code",
inputAuthCode: "Enter Auth Code", inputAuthCode: "Enter Auth Code",
// Metadata // Metadata
@@ -502,6 +506,9 @@ export default {
oneFolder: "Only one folder can be added for Special jobs", oneFolder: "Only one folder can be added for Special jobs",
notFolder: "Need to add folder", notFolder: "Need to add folder",
print_flagError: "print type does not match", print_flagError: "print type does not match",
cannotFindBin: "Template has no merge fields, cannot use CSV file",
pleaseSelectCap: "Please select capacity",
dongleCountRequired: "Please enter a valid dongle count (must be a positive integer)",
pleaseUploadTag: "Please add a Lable file", pleaseUploadTag: "Please add a Lable file",
uploadingTag: "Uploading label file", uploadingTag: "Uploading label file",
pleaseUploadingImgBin: "Please add a pic file", pleaseUploadingImgBin: "Please add a pic file",
+8 -1
View File
@@ -3,7 +3,8 @@ export default {
confirm: "確認", confirm: "確認",
cancel: "取消", cancel: "取消",
save: "保存", save: "保存",
ok: "確定" ok: "確定",
authSaveFail: "保存認證資訊失敗"
}, },
finger: { finger: {
intTips: "指紋模塊正在初始化", intTips: "指紋模塊正在初始化",
@@ -426,6 +427,8 @@ export default {
enableScreenRecord: "啟用屏幕錄制", enableScreenRecord: "啟用屏幕錄制",
printRecordLogo: "打印標識", printRecordLogo: "打印標識",
recordPath: "錄制路徑", recordPath: "錄制路徑",
recording: "錄製中...",
recordingCanceled: "錄製已取消",
// Hardware // Hardware
hardwareControl: "硬體管控", hardwareControl: "硬體管控",
installDongle: "加密狗計數", installDongle: "加密狗計數",
@@ -484,6 +487,10 @@ export default {
oneFolder: "特定作業只能添加一個文件夾", oneFolder: "特定作業只能添加一個文件夾",
notFolder: "添加內容不是文件夾", notFolder: "添加內容不是文件夾",
print_flagError: "打印面數不匹配,請重新選擇!", print_flagError: "打印面數不匹配,請重新選擇!",
cannotFindBin: "模板中沒有合併字段,無法使用CSV文件",
pleaseSelectCap: "請選擇容量",
dongleCountRequired: "請輸入有效的加密狗安裝次數(必須是正整數)",
authCode: "授權碼",
pleaseUploadTag: "請添加標籤文件", pleaseUploadTag: "請添加標籤文件",
uploadingTag: "正在上傳標籤文件...", uploadingTag: "正在上傳標籤文件...",
pleaseUploadingImgBin: "請添加圖片文件", pleaseUploadingImgBin: "請添加圖片文件",
+12 -11
View File
@@ -16,31 +16,32 @@ Vue.use(ElementUI);
/* eslint-disable no-new */ /* eslint-disable no-new */
Vue.use(VueI18n); Vue.use(VueI18n);
var type = navigator.appName; var type = navigator.appName;
if (type == "Netscape"){ if (type == "Netscape") {
var lang = navigator.language;//获取浏览器配置语言,支持非IE浏览器 var lang = navigator.language;//获取浏览器配置语言,支持非IE浏览器
}else{ } else {
var lang = navigator.userLanguage;//获取浏览器配置语言,支持IE5+ == navigator.systemLanguage var lang = navigator.userLanguage;//获取浏览器配置语言,支持IE5+ == navigator.systemLanguage
}; };
var lang1 = lang.substr(0, 2);//获取浏览器配置语言前两位 var lang1 = lang.substr(0, 2);//获取浏览器配置语言前两位
console.log(lang,lang1); console.log(lang, lang1);
let lan = 'en'; let lan = 'en';
if(lang1=='zh'){ if (lang1 == 'zh') {
if(lang == 'zh-TW' || lang == 'zh-HK'){ if (lang == 'zh-TW' || lang == 'zh-HK') {
lan = 'ozh'; lan = 'ozh';
}else{ } else {
lan = 'zh'; lan = 'zh';
} }
}else if(lang1=="en"){ } else if (lang1 == "en") {
lan = 'en'; lan = 'en';
} }
if(!localStorage.getItem('lang')){ if (!localStorage.getItem('lang')) {
localStorage.setItem("lang",lan); localStorage.setItem("lang", lan);
} }
const i18n = new VueI18n({ const i18n = new VueI18n({
silentTranslationWarn: true,
//locale: lan, // 默认语言 //locale: lan, // 默认语言
locale:(function(){ locale: (function () {
if(localStorage.getItem('lang')){ if (localStorage.getItem('lang')) {
return localStorage.getItem('lang') return localStorage.getItem('lang')
} }
return 'en' return 'en'