This commit is contained in:
24kycj
2026-01-19 02:48:29 +08:00
parent 04ca328a67
commit 0001ecc000
12 changed files with 531 additions and 163 deletions
+28 -5
View File
@@ -14,6 +14,14 @@ class ScreenRecorder {
this.mainWindow = window;
}
// 重置录制状态(用于前端初始化时清理可能的僵尸状态)
resetRecording() {
this.isRecording = false;
this.recordedChunks = [];
console.log('Recording state reset by renderer');
return { success: true, message: 'State reset' };
}
async startRecording() {
if (this.isRecording) {
return { success: false, message: '正在录制中' };
@@ -45,7 +53,7 @@ class ScreenRecorder {
}
}
async stopRecording(videoData, taskId = '') {
async stopRecording(videoData, taskId = '', customPath = null) {
if (!this.isRecording) {
return { success: false, message: '当前没有进行录制' };
}
@@ -53,11 +61,22 @@ class ScreenRecorder {
try {
this.isRecording = false;
// 确保videos目录存在 - 在应用根目录
// 获取应用根目录
const appPath = process.env.NODE_ENV === 'development'
? path.join(__dirname, '../../')
: path.dirname(app.getPath('exe'));
const videosDir = path.join(appPath, 'videos');
let videosDir;
if (customPath) {
// 如果是绝对路径直接使用,否则拼接应用根目录
videosDir = path.isAbsolute(customPath)
? customPath
: path.join(appPath, customPath);
} else {
// 默认目录:应用根目录/videos
videosDir = path.join(appPath, 'videos');
}
if (!fs.existsSync(videosDir)) {
fs.mkdirSync(videosDir, { recursive: true });
}
@@ -113,14 +132,18 @@ ipcMain.handle('start-recording', async () => {
return await recorder.startRecording();
});
ipcMain.handle('stop-recording', async (event, videoData, taskId) => {
return await recorder.stopRecording(videoData, taskId);
ipcMain.handle('stop-recording', async (event, videoData, taskId, customPath) => {
return await recorder.stopRecording(videoData, taskId, customPath);
});
ipcMain.handle('get-videos-path', () => {
return recorder.getVideosPath();
});
ipcMain.handle('reset-recording', async () => {
return recorder.resetRecording();
});
// 使用全局变量方式,避免webpack模块转换问题
global.ScreenRecorderInstance = recorder;
global.setMainWindow = (window) => recorder.setMainWindow(window);
+17 -17
View File
@@ -125,11 +125,11 @@ export default {
methods: {
// 获取配置
getConfig() {
this.$axios.get('/admin/get_config')
this.$axios.get('/web/get_config')
.then(res => {
if (res && res.data) {
// 合并数据,确保所有字段都存在
this.iniData = { ...this.iniData, ...res.data };
this.iniData = { ...this.iniData, ...res.data.data };
} else {
this.$message.error(this.$t("dispose.errorRead"));
}
@@ -139,23 +139,23 @@ export default {
this.$message.error(this.$t("dispose.errorRead"));
});
},
// 保存配置
save() {
this.$axios.post('/admin/get_config', this.iniData)
// 构造 query string
let params = [];
for (let key in this.iniData) {
if (this.iniData.hasOwnProperty(key)) {
// 使用 encodeURIComponent 确保特殊字符正确传输
params.push(`${key}=${encodeURIComponent(this.iniData[key])}`);
}
}
const queryString = params.join('&');
this.$axios.post(`/web/update_config?${queryString}`)
.then(res => {
if (res && (res.data === "success" || res.status === 200)) {
this.$message({
type: "success",
message: this.$t("dispose.successReserve"),
});
} else {
// 某些接口可能返回 { ret: 0 } 或其他形式,视具体情况而定
// 这里假设200 OK即为成功,或者根据res.data判断
this.$message({
type: "success",
message: this.$t("dispose.successReserve"),
});
}
this.$message({
type: "success",
message: this.$t("dispose.successReserve"),
});
})
.catch(err => {
console.error(err);
@@ -3,7 +3,7 @@
<template v-if="!statusOnly">
<el-tooltip :content="isRecording ? $t('recorder.stopRecording') : $t('recorder.startRecording')" placement="top">
<el-button size="medium" :type="isRecording ? 'danger' : 'primary'"
:icon="isRecording ? 'el-icon-video-pause' : 'el-icon-video-camera'" circle @click="toggleRecording"
:icon="isRecording ? 'el-icon-switch-button' : 'el-icon-video-camera'" circle @click="toggleRecording"
:loading="loading" class="record-btn">
</el-button>
</el-tooltip>
@@ -43,7 +43,9 @@ export default {
timer: null,
stream: null,
currentTaskId: '', // 录屏开始时的任务ID
autoSave: true // 是否在停止时保存
autoSave: true, // 是否在停止时保存
videoPath: '', // 录制视频的绝对路径
customSavePath: '' // 存储启动时传入的保存路径
};
},
methods: {
@@ -86,6 +88,7 @@ export default {
this.stream = stream;
this.recordedChunks = [];
this.customSavePath = options.savePath || ''; // 保存自定义路径
// 创建MediaRecorder
this.mediaRecorder = new MediaRecorder(stream, {
@@ -100,7 +103,7 @@ export default {
this.mediaRecorder.onstop = async () => {
if (this.autoSave) {
await this.saveRecording(options.savePath);
await this.saveRecording(this.customSavePath); // 使用保存的路径
}
this.recordedChunks = [];
};
@@ -130,7 +133,22 @@ export default {
try {
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
this.mediaRecorder.stop();
// 创建 Promise 等待 onstop 回调完成
await new Promise((resolve) => {
// 保存原有的 onstop 处理器
const originalOnStop = this.mediaRecorder.onstop;
// 包装 onstop,在原处理器完成后 resolve
this.mediaRecorder.onstop = async (event) => {
if (originalOnStop) {
await originalOnStop.call(this, event);
}
resolve();
};
// 触发 stop 事件
this.mediaRecorder.stop();
});
}
// 停止所有轨道
@@ -161,33 +179,47 @@ export default {
return;
}
try {
// 将录制的数据块合并为Blob
const blob = new Blob(this.recordedChunks, {
type: 'video/webm'
});
return new Promise((resolve, reject) => {
try {
// 将录制的数据块合并为Blob
const blob = new Blob(this.recordedChunks, {
type: 'video/webm'
});
// 转换为base64
const reader = new FileReader();
reader.onloadend = async () => {
const base64data = reader.result;
// 转换为base64
const reader = new FileReader();
reader.onloadend = async () => {
if (this._isDestroyed) return;
try {
const base64data = reader.result;
// 发送到主进程保存,传递任务ID和可选路径
const result = await ipcRenderer.invoke('stop-recording', base64data, this.currentTaskId, customPath);
// 发送到主进程保存,传递任务ID和可选路径
const result = await ipcRenderer.invoke('stop-recording', base64data, this.currentTaskId, customPath);
if (result.success) {
this.$message.success(this.$t('recorder.savedSuccess') + `: ${result.fileName}`);
this.$emit('recording-saved', result);
} else {
this.$message.error(result.message);
}
};
reader.readAsDataURL(blob);
if (this._isDestroyed) return;
} catch (error) {
console.error('保存录制失败:', error);
this.$message.error(this.$t('recorder.saveFailed'));
}
if (result.success) {
this.$message.success(this.$t('recorder.savedSuccess') + `: ${result.fileName}`);
this.videoPath = result.filePath; // 保存视频绝对路径供外部使用
this.$emit('recording-saved', result);
resolve(result);
} else {
this.$message.error(result.message);
reject(new Error(result.message));
}
} catch (err) {
reject(err);
}
};
reader.onerror = reject;
reader.readAsDataURL(blob);
} catch (error) {
console.error('保存录制失败:', error);
this.$message.error(this.$t('recorder.saveFailed'));
reject(error);
}
});
},
startTimer() {
@@ -17,13 +17,6 @@
</el-form>
</div>
<span slot="footer" class="dialog-footer grand-footer">
<div class="footer-buttons">
<el-button @click="handleClose" size="medium" icon="el-icon-close">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="handleSave" size="medium" icon="el-icon-check">{{ $t('common.confirm')
}}</el-button>
</div>
</span>
</el-dialog>
</template>
@@ -81,8 +74,8 @@ export default {
},
handleSave() {
// 验证加密狗计数
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.enable_dongle_counter) {
if (!this.form.install_dongle_count || this.form.install_dongle_count < 0 || !Number.isInteger(this.form.install_dongle_count)) {
this.$message.warning(this.$t('work.dongleCountRequired'))
return
}
+280 -25
View File
@@ -45,39 +45,63 @@
<div class="sub-title">
<i class="el-icon-edit-outline"></i>
<span>{{ $t('work.metadataEdit') }}</span>
<span class="field-count" v-if="tableData && tableData.length > 0">({{ tableData.length }})</span>
</div>
<el-table v-if="tableData && tableData.length > 0" :data="tableData" class="metadata-table flex-grow-table"
:empty-text="$t('work.nodata')" :show-header="false">
<el-table-column prop="name" min-width="110"></el-table-column>
<el-table-column min-width="240">
<template slot-scope="scope">
<div v-if="scope.row.type == 1">
<input type="file" title="" accept="image/*" :ref="scope.row.origin_name"
:data-name="scope.row.origin_name"
@change="(e) => $emit('image-change', scope.row.origin_name, e.target.files[0])" />
<!-- 卡片式布局替代表格 -->
<div v-if="tableData && tableData.length > 0" class="metadata-fields-list">
<div v-for="(item, index) in tableData" :key="index" class="field-item"
:class="{ 'field-disabled': csvIsExist && (item.type == 3 || item.type == 4 || item.type == 5) }">
<!-- 左侧字段名称区域 -->
<div class="field-label-area">
<div class="field-info">
<div class="field-name-row">
<span class="field-name" :title="item.name">{{ item.name }}</span>
<span v-if="item.sideLabel" class="side-badge"
:class="{ 'side-front': item.sideLabel.includes('正'), 'side-back': item.sideLabel.includes('背') }">
{{ item.sideLabel.replace('[', '').replace(']', '') }}
</span>
</div>
</div>
<div v-else-if="scope.row.type == 3 || scope.row.type == 4 || scope.row.type == 5">
<el-input v-model="form[scope.row.origin_name]" clearable size="mini"
:disabled="csvIsExist" />
</div>
<!-- 右侧输入区域 -->
<div class="field-input-area">
<!-- 图片类型 -->
<div v-if="item.type == 1" class="image-upload-wrapper">
<label :for="'upload-' + item.origin_name" class="upload-label">
<i class="el-icon-picture-outline"></i>
<span>{{ $t('work.selectImage') }}</span>
</label>
<input :id="'upload-' + item.origin_name" type="file" accept="image/*"
:ref="item.origin_name" :data-name="item.origin_name" class="hidden-file-input"
@change="(e) => $emit('image-change', item.origin_name, e.target.files[0])" />
</div>
<div v-else>{{ scope.row.origin_name }}</div>
</template>
</el-table-column>
<el-table-column min-width="90">
<template slot-scope="scope">
<div v-if="scope.row.type == 3 || scope.row.type == 4 || scope.row.type == 5">
<el-button size="mini" icon="el-icon-upload2" @click="$emit('open-csv')">
{{ file_name ? file_name : $t('work.binfile') }}
<!-- 文本/条码类型 -->
<div v-else-if="item.type == 3 || item.type == 4 || item.type == 5" class="text-input-wrapper">
<el-input v-model="form[item.origin_name]" :placeholder="$t('work.pleaseInput')" clearable
size="small" :disabled="csvIsExist" class="modern-input" />
<el-button size="small" icon="el-icon-upload2" @click="$emit('open-csv')"
class="csv-import-btn" :title="$t('work.binfile')">
<span class="btn-text">{{ file_name || $t('work.binfile') }}</span>
</el-button>
</div>
</template>
</el-table-column>
</el-table>
<!-- 其他类型 -->
<div v-else class="field-value-display">
{{ item.origin_name }}
</div>
</div>
</div>
</div>
<!-- 空状态占位框 (当无数据时显示) -->
<div v-else class="empty-placeholder-box">
<span class="empty-text">{{ $t('work.nodata') }}</span>
<div v-else class="empty-state-modern">
<i class="el-icon-document"></i>
<p class="empty-title">{{ $t('work.noTemplate') }}</p>
<p class="empty-hint">{{ $t('work.selectTemplateHint') }}</p>
</div>
</div>
</div>
@@ -150,4 +174,235 @@ export default {
.template-select {
width: 240px;
}
/* ================== 现代化卡片式字段列表 ================== */
.metadata-fields-list {
flex: 1;
overflow-y: auto;
padding: 4px;
display: flex;
flex-direction: column;
gap: 10px;
}
/* 字段项卡片 */
.field-item {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 10px;
padding: 14px 16px;
display: flex;
align-items: center;
gap: 16px;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.field-item:hover {
border-color: #cbd5e1;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08);
transform: translateY(-1px);
}
.field-disabled {
opacity: 0.6;
pointer-events: none;
}
/* 左侧:字段名称区域 */
.field-label-area {
display: flex;
align-items: center;
gap: 12px;
min-width: 180px;
flex-shrink: 0;
}
.field-info {
flex: 1;
min-width: 0;
}
.field-name {
font-size: 14px;
font-weight: 600;
color: #1f2937;
margin-bottom: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.field-name-row {
display: flex;
align-items: center;
gap: 8px;
}
.side-badge {
font-size: 11px;
padding: 1px 6px;
border-radius: 4px;
font-weight: 500;
}
.side-front {
background-color: #e0f2fe;
color: #0369a1;
border: 1px solid #bae6fd;
}
.side-back {
background-color: #fce7f3;
color: #be185d;
border: 1px solid #fbcfe8;
}
/* 右侧:输入区域 */
.field-input-area {
flex: 1;
display: flex;
align-items: center;
gap: 8px;
}
/* 图片上传样式 */
.image-upload-wrapper {
width: 100%;
}
.upload-label {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 7px 14px;
background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
border: 1px solid #d1d5db;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
color: #4b5563;
font-weight: 500;
transition: all 0.2s;
}
.upload-label:hover {
background: linear-gradient(135deg, #e5e7eb 0%, #d1d5db 100%);
border-color: #9ca3af;
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.upload-label i {
font-size: 16px;
color: #6b7280;
}
.hidden-file-input {
display: none;
}
/* 文本输入样式 */
.text-input-wrapper {
flex: 1;
display: flex;
gap: 8px;
align-items: center;
}
.modern-input {
flex: 1;
}
.csv-import-btn {
border-radius: 8px;
border-color: #d1d5db;
background: #ffffff;
transition: all 0.2s;
max-width: 140px;
overflow: hidden;
}
.csv-import-btn:hover {
background: #f9fafb;
border-color: #9ca3af;
transform: translateY(-1px);
}
.csv-import-btn .btn-text {
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100px;
display: inline-block;
}
.field-value-display {
padding: 7px 12px;
background: #f9fafb;
border-radius: 6px;
font-size: 13px;
color: #6b7280;
}
/* ================== 字段计数 ================== */
.field-count {
font-size: 12px;
color: #9ca3af;
font-weight: 600;
margin-left: 4px;
padding: 2px 8px;
background: #f3f4f6;
border-radius: 12px;
}
/* ================== 现代化空状态 ================== */
.empty-state-modern {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 48px 24px;
text-align: center;
}
.empty-state-modern i {
font-size: 56px;
color: #cbd5e1;
margin-bottom: 16px;
}
.empty-title {
font-size: 15px;
font-weight: 600;
color: #64748b;
margin: 0 0 8px 0;
}
.empty-hint {
font-size: 13px;
color: #94a3b8;
margin: 0;
}
/* ================== 滚动条美化 ================== */
.metadata-fields-list::-webkit-scrollbar {
width: 6px;
}
.metadata-fields-list::-webkit-scrollbar-thumb {
background: #cbd5e1;
border-radius: 3px;
}
.metadata-fields-list::-webkit-scrollbar-thumb:hover {
background: #94a3b8;
}
.metadata-fields-list::-webkit-scrollbar-track {
background: #f1f5f9;
border-radius: 3px;
}
</style>
+77 -40
View File
@@ -13,17 +13,12 @@
<!-- 右侧功能按钮 -->
<div class="header-buttons">
<!-- 录制组件 (绿色圆形) -->
<div class="recorder-wrapper" v-if="isRecording || high_setting_form.is_print_logo">
<div class="recorder-wrapper"
v-if="isRecording || high_setting_form.record_screen || high_setting_form.print_record_logo">
<screen-recorder ref="screenRecorder" :task-id="upload_disk" :status-only="true"
@recording-started="onRecordingStarted" @recording-stopped="onRecordingStopped"
@recording-saved="onRecordingSaved" />
<el-tooltip content="打印" placement="top">
<div v-if="high_setting_form.is_print_logo" class="print-logo-indicator">
<img src="static/images/luzhi.png" @error="onLogoError" v-if="!logoError"
class="logo-img" />
<i v-else class="el-icon-printer"></i>
</div>
</el-tooltip>
</div>
<!-- 高级设置按钮 (白色) -->
@@ -168,6 +163,7 @@ export default {
switch_cont: true,
switch_tag: true,
submitLoading: false,
sysAuthCode: '', // 系统配置授权码
// 新手引导
guideStep: null,
@@ -191,25 +187,31 @@ export default {
// 高级设置表单
high_setting_form: {
// 基础配置
priority: 0,
fileSystem: 0,
target_work: 0,
color_type: 0,
s1: false,
s2: false,
s3: false,
formatFile: 0,
// 开关选项
s1: false, // 生成MD5 HASH文件
s2: false, // 打印MD5到HASH字段
s3: false, // 失败打印标签
s4: false,
s5: false,
// 密码相关
pass: '',
repass: '',
localfiles: false,
formatFile: 0,
Span_USBcard: false,
hasAddFile: false,
is_blend: false,
is_record: false,
record_path: '',
is_print_logo: false,
// 功能开关
localfiles: false, // 本地文件
Span_USBcard: false, // 允许跨卡
hasAddFile: false, // 预设内容拷贝
is_blend: false, // 混合模式
// ISO/ZIP 生成
is_generate_iso: false,
iso_file_name: '',
is_generate_zip: false,
@@ -217,10 +219,17 @@ export default {
is_zip_encrypt: false,
zip_password: '',
zip_repassword: '',
copy_hash: false,
is_dongle_count: false,
dongle_count: 1,
auth_code: ''
copy_hash: false, // 拷贝HASH文件到存储卡
// 屏幕录制(重要:确保字段名称一致)
record_screen: false, // 启用屏幕录制
record_screen_path: '', // 录制路径
print_record_logo: false, // 打印录制标识
// 硬件管控(重要:确保字段名称与提交逻辑一致)
enable_dongle_counter: false, // 启用加密狗计数
install_dongle_count: 0, // 安装次数(默认为0而不是1
auth_code: '' // 授权码
}
}
},
@@ -276,6 +285,8 @@ export default {
}
},
created() {
// 重置后台录制状态,防止刷新后状态卡死
ipcRenderer.invoke('reset-recording').catch(e => console.error('Reset recording failed:', e))
extendStringPrototypes()
this.upload_disk = genTaskUUID()
},
@@ -328,15 +339,15 @@ export default {
this.high_setting_form = { ...this.high_setting_form, ...savedForm, ...defaults }
// 仅在路径为空时初始化默认路径(兼容三端)
if (!this.high_setting_form.record_path) {
this.high_setting_form.record_path = this.getDefaultRecordPath();
if (!this.high_setting_form.record_screen_path) {
this.high_setting_form.record_screen_path = this.getDefaultRecordPath();
}
} catch (e) {
console.error('Failed to parse high settings')
}
} else {
// 无缓存时初始化默认路径
this.high_setting_form.record_path = this.getDefaultRecordPath();
this.high_setting_form.record_screen_path = this.getDefaultRecordPath();
}
this.juanbiao_form = getNowFormatDate()
this.print_flag = this.dice === 1 ? 2 : 1
@@ -352,6 +363,17 @@ export default {
this.guideStep[this.currentStep].show = true
}, 200)
}
this.getSystemConfig(); // 获取系统配置
},
getSystemConfig() {
this.$axios.get('/web/get_config').then((res) => {
if (res.data.code === 200 && res.data.data) {
this.sysAuthCode = res.data.data.AuthorizationCode || '';
}
}).catch(err => {
console.error('Failed to get system config', err);
});
},
// --- 高级设置与录制 ---
@@ -391,8 +413,9 @@ export default {
const recorder = this.$refs.screenRecorder;
if (recorder) {
if (recorder.isRecording) {
recorder.stopRecording(true);
this.$message.warning(this.$t('recorder.recording'));
} else {
this.highSettingVisible = false;
recorder.startRecording({
savePath: recordPath || this.getDefaultRecordPath()
});
@@ -440,7 +463,8 @@ export default {
if ([1, 3, 4, 5].includes(item.type)) {
const defaultVal = item.DefaultText !== undefined ? item.DefaultText : ''
this.tableData.push({
name: item.name + this.$t('work.front_tag'),
name: item.name,
sideLabel: this.$t('work.front_tag'),
val: defaultVal,
origin_name: item.name,
type: item.type,
@@ -457,7 +481,8 @@ export default {
if ([1, 3, 4, 5].includes(item.type)) {
const defaultVal = item.DefaultText !== undefined ? item.DefaultText : ''
this.tableData.push({
name: item.name + this.$t('work.back_tag'),
name: item.name,
sideLabel: this.$t('work.back_tag'),
val: defaultVal,
origin_name: item.name,
type: item.type,
@@ -991,14 +1016,12 @@ export default {
'&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 || '');
'&copy_hash=' + (String(that.high_setting_form.copy_hash) || 'false');
data += '&is_blend=' + (String(that.high_setting_form.is_blend) || 'false');
// Log path logic
if (that.high_setting_form.record_screen && that.$refs.screenRecorder && that.$refs.screenRecorder.videoPath) {
if (that.$refs.screenRecorder && that.$refs.screenRecorder.videoPath) {
data += '&record_path=' + that.$refs.screenRecorder.videoPath;
} else {
data += '&record_path=';
@@ -1006,16 +1029,31 @@ export default {
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);
data += '&dongle_install_count=' + (that.high_setting_form.install_dongle_count || 1);
} else {
data += '&donglel_install_count=0';
data += '&dongle_install_count=-1';
}
// 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)
// --- DEBUG: 输出提交数据 ---
console.group('任务提交数据详情');
// 将查询字符串解析为对象,方便查看
const queryString = data_param + data;
const params = {};
queryString.split('&').forEach(part => {
if (part) {
const [key, val] = part.split('=');
params[key] = decodeURIComponent(val || '');
}
});
console.log('提交参数对象 (JSON):', params);
console.log('高级设置表单:', JSON.parse(JSON.stringify(that.high_setting_form))); // 深拷贝打印
console.groupEnd();
// Submit Flow
if (this.isCopy) {
this.submitLoading = true
@@ -1047,9 +1085,8 @@ export default {
localUpload(pathName, data_param, data) {
let file_path = []
// 注意: 这里使用 getLists() 可能需要适配 legacy 的 filesList 结构
// 如果 filesList[i].path 是正确路径,则无需更改
const list = this.$refs.files.filesList // Prefer direct filesList if available like legacy
// FileManagement 组件不直接暴露 filesList,需使用 getLists()
const list = this.$refs.files.getLists()
for (let i in list) {
file_path.push(list[i].path)
}
@@ -95,18 +95,15 @@
</div>
<div class="g-switch-item">
<span class="g-label">{{ $t('work.installDongle') }}</span>
<el-switch v-model="form.is_dongle_count"></el-switch>
<el-switch v-model="form.enable_dongle_counter"></el-switch>
</div>
</div>
<!-- 计数器详细 -->
<div v-if="form.is_dongle_count" class="mt-10 p-10"
<div v-if="form.enable_dongle_counter" class="mt-10 p-10"
style="background: #fdf6ec; border-radius: 6px; border: 1px solid #faecd8;">
<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-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 :label="$t('work.installCount')" label-width="140px" class="mb-0">
<el-input-number v-model="form.install_dongle_count" :min="0" :step="1" :precision="0" size="mini" />
</el-form-item>
</div>
</div>
@@ -8,14 +8,14 @@
<el-col :span="12">
<div class="hardware-box">
<div class="mb-10">
<el-checkbox v-model="form.is_dongle_count">
<el-checkbox v-model="form.enable_dongle_counter">
{{ $t('work.installDongle') }}
</el-checkbox>
</div>
<transition name="el-zoom-in-top">
<div v-if="form.is_dongle_count" class="ml-20">
<div v-if="form.enable_dongle_counter" class="ml-20">
<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.install_dongle_count" :min="0" :max="999" />
</el-form-item>
</div>
</transition>
@@ -8,22 +8,21 @@
<div class="grand-switch-grid mb-10">
<div class="g-switch-item">
<span class="g-label">{{ $t('work.enableScreenRecord') }}</span>
<el-switch v-model="form.is_record"></el-switch>
<el-switch v-model="form.record_screen"></el-switch>
</div>
<div class="g-switch-item" v-if="form.is_record">
<div class="g-switch-item" v-if="form.record_screen">
<div class="flex-align-center">
<span class="g-label">{{ $t('work.printRecordLogo') }}</span>
<i v-if="form.is_print_logo" class="el-icon-picture ml-5 logo-icon-active"
title="luzhi.png"></i>
</div>
<el-switch v-model="form.is_print_logo"></el-switch>
<el-switch v-model="form.print_record_logo"></el-switch>
</div>
</div>
<div v-if="form.is_record" class="path-box-container">
<div v-if="form.record_screen" class="path-box-container">
<div class="path-box">
<el-form-item :label="$t('work.recordPath')" label-width="110px">
<el-input v-model="form.record_path" :placeholder="$t('work.defaultPath')" size="small">
<el-input v-model="form.record_screen_path" :placeholder="$t('work.defaultPath')" size="small">
<el-button slot="append" icon="el-icon-folder-opened" @click="selectRecordPath"></el-button>
</el-input>
</el-form-item>
@@ -59,12 +58,12 @@ export default {
properties: ['openDirectory']
}).then(result => {
if (!result.canceled && result.filePaths.length > 0) {
this.$set(this.form, 'record_path', result.filePaths[0])
this.$set(this.form, 'record_screen_path', result.filePaths[0])
}
})
},
testRecording() {
this.$emit('test-recording', this.form.record_path);
this.$emit('test-recording', this.form.record_screen_path);
}
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long