录制和网络路径
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>卡树自动拷贝打印系统 V3.0</title>
|
<title>卡树自动拷贝打印系统 V3.1</title>
|
||||||
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
<% if (htmlWebpackPlugin.options.nodeModules) { %>
|
||||||
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
|
<!-- Add `node_modules/` to global paths so `require` works properly in development -->
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ function createWindow() {
|
|||||||
height: 800,
|
height: 800,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
width: 1280,
|
width: 1280,
|
||||||
title: "卡树自动拷贝打印系统 V3.0",
|
title: "卡树自动拷贝打印系统 V3.1",
|
||||||
icon: "static/images/logo64.ico", // sets window icon
|
icon: "static/images/logo64.ico", // sets window icon
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
|||||||
+6
-2
@@ -1,8 +1,11 @@
|
|||||||
const { Menu, app, BrowserWindow } = require("electron");
|
const { Menu, app, BrowserWindow } = require("electron");
|
||||||
import "../renderer/store";
|
// Note: Store should be handled in renderer process, not main
|
||||||
|
// import "../renderer/store";
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
// 导入录制器模块(设置全局变量)
|
||||||
|
require('./recorder');
|
||||||
// require("./fingerprint/win");
|
// require("./fingerprint/win");
|
||||||
let root = "";
|
let root = "";
|
||||||
if (process.env.NODE_ENV !== "development") {
|
if (process.env.NODE_ENV !== "development") {
|
||||||
@@ -49,7 +52,7 @@ function createWindow() {
|
|||||||
height: 800,
|
height: 800,
|
||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
width: 1280,
|
width: 1280,
|
||||||
title: "卡树自动拷贝打印系统 V3.0",
|
title: "卡树自动拷贝打印系统 V3.1",
|
||||||
icon: "static/images/logo64.ico", // sets window icon
|
icon: "static/images/logo64.ico", // sets window icon
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
@@ -65,6 +68,7 @@ function createWindow() {
|
|||||||
//mainWindow.webContents.openDevTools({mode:'bottom'});
|
//mainWindow.webContents.openDevTools({mode:'bottom'});
|
||||||
require("@electron/remote/main").initialize();
|
require("@electron/remote/main").initialize();
|
||||||
require("@electron/remote/main").enable(mainWindow.webContents);
|
require("@electron/remote/main").enable(mainWindow.webContents);
|
||||||
|
global.setMainWindow(mainWindow);
|
||||||
mainWindow.loadURL(winURL);
|
mainWindow.loadURL(winURL);
|
||||||
|
|
||||||
mainWindow.on("closed", () => {
|
mainWindow.on("closed", () => {
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
const { desktopCapturer, ipcMain, app } = require('electron');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
class ScreenRecorder {
|
||||||
|
constructor() {
|
||||||
|
this.mediaRecorder = null;
|
||||||
|
this.recordedChunks = [];
|
||||||
|
this.isRecording = false;
|
||||||
|
this.mainWindow = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMainWindow(window) {
|
||||||
|
this.mainWindow = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
async startRecording() {
|
||||||
|
if (this.isRecording) {
|
||||||
|
return { success: false, message: '正在录制中' };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取屏幕源
|
||||||
|
const sources = await desktopCapturer.getSources({
|
||||||
|
types: ['screen'],
|
||||||
|
thumbnailSize: { width: 1920, height: 1080 }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sources.length === 0) {
|
||||||
|
return { success: false, message: '无法获取屏幕源' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送源ID到渲染进程
|
||||||
|
const sourceId = sources[0].id;
|
||||||
|
this.isRecording = true;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
sourceId: sourceId,
|
||||||
|
message: '开始录制'
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('启动录制失败:', error);
|
||||||
|
return { success: false, message: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async stopRecording(videoData) {
|
||||||
|
if (!this.isRecording) {
|
||||||
|
return { success: false, message: '当前没有进行录制' };
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
if (!fs.existsSync(videosDir)) {
|
||||||
|
fs.mkdirSync(videosDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成文件名:soonworker+时间戳
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
||||||
|
const fileName = `soonworker_${timestamp}.webm`;
|
||||||
|
const filePath = path.join(videosDir, fileName);
|
||||||
|
|
||||||
|
// 将base64数据转换为Buffer并保存
|
||||||
|
const buffer = Buffer.from(videoData.replace('data:video/webm;base64,', ''), 'base64');
|
||||||
|
fs.writeFileSync(filePath, buffer);
|
||||||
|
|
||||||
|
console.log('视频已保存到:', filePath);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
filePath: filePath,
|
||||||
|
fileName: fileName,
|
||||||
|
message: '录制已保存'
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('停止录制失败:', error);
|
||||||
|
return { success: false, message: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取videos目录路径
|
||||||
|
getVideosPath() {
|
||||||
|
const appPath = process.env.NODE_ENV === 'development'
|
||||||
|
? path.join(__dirname, '../../')
|
||||||
|
: path.dirname(app.getPath('exe'));
|
||||||
|
return path.join(appPath, 'videos');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建录制器实例
|
||||||
|
const recorder = new ScreenRecorder();
|
||||||
|
|
||||||
|
// IPC事件处理
|
||||||
|
ipcMain.handle('start-recording', async () => {
|
||||||
|
return await recorder.startRecording();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('stop-recording', async (event, videoData) => {
|
||||||
|
return await recorder.stopRecording(videoData);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('get-videos-path', () => {
|
||||||
|
return recorder.getVideosPath();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用全局变量方式,避免webpack模块转换问题
|
||||||
|
global.ScreenRecorderInstance = recorder;
|
||||||
|
global.setMainWindow = (window) => recorder.setMainWindow(window);
|
||||||
|
|
||||||
|
// 不导出任何内容,完全依赖全局变量
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="$t('networkAuth.title')"
|
||||||
|
: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">
|
||||||
|
<p class="auth-description">
|
||||||
|
{{ $t('networkAuth.description') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="network-paths">
|
||||||
|
<div
|
||||||
|
v-for="(path, index) in networkPaths"
|
||||||
|
:key="index"
|
||||||
|
class="network-path-item"
|
||||||
|
>
|
||||||
|
<div class="path-info">
|
||||||
|
<span class="path-label">{{ $t('networkAuth.pathLabel') }}</span>
|
||||||
|
<span class="path-value">{{ path.path }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="auth-fields">
|
||||||
|
<el-input
|
||||||
|
v-model="path.userName"
|
||||||
|
:placeholder="$t('networkAuth.userName')"
|
||||||
|
size="small"
|
||||||
|
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 slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleCancel">{{ $t('networkAuth.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirm" :loading="loading">
|
||||||
|
{{ $t('networkAuth.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'NetworkAuthDialog',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
networkPaths: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleCancel() {
|
||||||
|
this.$emit('cancel')
|
||||||
|
},
|
||||||
|
|
||||||
|
async handleConfirm() {
|
||||||
|
// 验证所有路径都填写了用户名和密码
|
||||||
|
for (let path of this.networkPaths) {
|
||||||
|
if (!path.userName || !path.password) {
|
||||||
|
this.$message.error(this.$t('networkAuth.authRequired'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 保存到本地存储
|
||||||
|
this.saveNetworkCredentials()
|
||||||
|
|
||||||
|
// 构建 net_info 数据
|
||||||
|
const netInfo = this.networkPaths.map(path => ({
|
||||||
|
host_name: this.extractHostName(path.path),
|
||||||
|
user_name: path.userName,
|
||||||
|
password: path.password
|
||||||
|
}))
|
||||||
|
|
||||||
|
this.$emit('confirm', netInfo)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存网络认证信息失败:', error)
|
||||||
|
this.$message.error('保存认证信息失败')
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
extractHostName(path) {
|
||||||
|
// 从网络路径中提取主机名
|
||||||
|
// 支持格式:\\hostname\path, //hostname/path, \\192.168.1.1\path
|
||||||
|
if (path.startsWith('\\\\')) {
|
||||||
|
// Windows 网络路径 \\hostname\path
|
||||||
|
const parts = path.substring(2).split('\\')
|
||||||
|
return parts[0]
|
||||||
|
} else if (path.startsWith('//')) {
|
||||||
|
// Unix 网络路径 //hostname/path
|
||||||
|
const parts = path.substring(2).split('/')
|
||||||
|
return parts[0]
|
||||||
|
} else if (path.includes(':')) {
|
||||||
|
// 可能包含 IP 地址
|
||||||
|
const match = path.match(/^([^\\\/:]+)/)
|
||||||
|
return match ? match[1] : 'unknown'
|
||||||
|
}
|
||||||
|
return 'unknown'
|
||||||
|
},
|
||||||
|
|
||||||
|
saveNetworkCredentials() {
|
||||||
|
// 保存到 localStorage
|
||||||
|
const credentials = {}
|
||||||
|
this.networkPaths.forEach(path => {
|
||||||
|
const hostName = this.extractHostName(path.path)
|
||||||
|
credentials[hostName] = {
|
||||||
|
userName: path.userName,
|
||||||
|
password: path.password,
|
||||||
|
lastUsed: new Date().toISOString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
localStorage.setItem('networkCredentials', JSON.stringify(credentials))
|
||||||
|
|
||||||
|
// 同时保存到 Vuex store(若可用)
|
||||||
|
if (this.$store && this.$store.commit) {
|
||||||
|
this.$store.commit('SET_NETWORK_CREDENTIALS', credentials)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.network-auth-content {
|
||||||
|
.auth-description {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-paths {
|
||||||
|
.network-path-item {
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
|
||||||
|
.path-info {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.path-label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #303133;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-value {
|
||||||
|
color: #409eff;
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: #f0f9ff;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-fields {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -251,7 +251,7 @@ export default {
|
|||||||
StopOnFailure: "false"
|
StopOnFailure: "false"
|
||||||
SystemSn: "830001"
|
SystemSn: "830001"
|
||||||
TaskDir: "C:\\PrintTasks"
|
TaskDir: "C:\\PrintTasks"
|
||||||
Version: "V3.0"
|
Version: "V3.1"
|
||||||
|
|
||||||
iniparser.parse("F:\\controll\\config.ini", function (err, data) {
|
iniparser.parse("F:\\controll\\config.ini", function (err, data) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"files":["C:\\Users\\jerry\\Desktop\\cardsoon\\卡树产品保修条款.docx"]}
|
{"files":["\\\\NAS\\study\\research_reports\\餐饮服务\\“保健水晶鸡、鸭皮蛋”商业计划书.docx"]}
|
||||||
@@ -61,6 +61,32 @@ import archiverdialog from "./archiverdialog";
|
|||||||
import { calcSize, getFileName, isFolder } from "./calc";
|
import { calcSize, getFileName, isFolder } from "./calc";
|
||||||
import { copy } from "./copy";
|
import { copy } from "./copy";
|
||||||
import { zip } from "./archiver";
|
import { zip } from "./archiver";
|
||||||
|
|
||||||
|
// 网络路径检测工具函数
|
||||||
|
const isNetworkPath = (path) => {
|
||||||
|
// 检测是否为网络路径
|
||||||
|
// Windows 网络路径: \\hostname\path 或 \\IP\path
|
||||||
|
// Unix 网络路径: //hostname/path 或 //IP/path
|
||||||
|
return path.startsWith('\\\\') || path.startsWith('//') ||
|
||||||
|
(path.includes(':') && !path.includes('\\') && !path.includes('/'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractHostName = (path) => {
|
||||||
|
if (path.startsWith('\\\\')) {
|
||||||
|
// Windows 网络路径 \\hostname\path
|
||||||
|
const parts = path.substring(2).split('\\')
|
||||||
|
return parts[0]
|
||||||
|
} else if (path.startsWith('//')) {
|
||||||
|
// Unix 网络路径 //hostname/path
|
||||||
|
const parts = path.substring(2).split('/')
|
||||||
|
return parts[0]
|
||||||
|
} else if (path.includes(':')) {
|
||||||
|
// 可能包含 IP 地址
|
||||||
|
const match = path.match(/^([^\\\/:]+)/)
|
||||||
|
return match ? match[1] : 'unknown'
|
||||||
|
}
|
||||||
|
return 'unknown'
|
||||||
|
};
|
||||||
export default {
|
export default {
|
||||||
name: "Files",
|
name: "Files",
|
||||||
props: {
|
props: {
|
||||||
@@ -96,6 +122,7 @@ export default {
|
|||||||
isCopy: false,
|
isCopy: false,
|
||||||
isSucess: true,
|
isSucess: true,
|
||||||
copyPath: "",
|
copyPath: "",
|
||||||
|
networkPaths: [], // 存储检测到的网络路径
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -132,6 +159,12 @@ export default {
|
|||||||
// 是文件夹
|
// 是文件夹
|
||||||
this.sizeChange(f.size);
|
this.sizeChange(f.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检测是否为网络路径
|
||||||
|
if (isNetworkPath(f.path)) {
|
||||||
|
this.addNetworkPath(f.path);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
//有了,不用加入
|
//有了,不用加入
|
||||||
@@ -145,6 +178,7 @@ export default {
|
|||||||
properties: ["multiSelections"],
|
properties: ["multiSelections"],
|
||||||
})
|
})
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
|
console.log(res)
|
||||||
for (const item of res.filePaths) {
|
for (const item of res.filePaths) {
|
||||||
await fs.stat(item, function (err, res) {
|
await fs.stat(item, function (err, res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -167,6 +201,7 @@ export default {
|
|||||||
properties: ["openDirectory", "multiSelections"],
|
properties: ["openDirectory", "multiSelections"],
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
console.log(res)
|
||||||
for (const item of res.filePaths) {
|
for (const item of res.filePaths) {
|
||||||
const result = _this.insertList({
|
const result = _this.insertList({
|
||||||
name: getFileName(item),
|
name: getFileName(item),
|
||||||
@@ -309,6 +344,62 @@ export default {
|
|||||||
getLists() {
|
getLists() {
|
||||||
return this.filesList;
|
return this.filesList;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 添加网络路径到列表(按主机去重,仅认证根目录,如 \\\\NAS)
|
||||||
|
addNetworkPath(path) {
|
||||||
|
const hostName = extractHostName(path);
|
||||||
|
const existingIndex = this.networkPaths.findIndex(p => p.hostName === hostName);
|
||||||
|
|
||||||
|
if (existingIndex === -1) {
|
||||||
|
// 尝试从本地存储获取已保存的认证信息
|
||||||
|
let userName = '';
|
||||||
|
let password = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem('networkCredentials');
|
||||||
|
if (stored) {
|
||||||
|
const credentials = JSON.parse(stored);
|
||||||
|
if (credentials[hostName]) {
|
||||||
|
userName = credentials[hostName].userName;
|
||||||
|
password = credentials[hostName].password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('无法获取已保存的认证信息');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 仅保存根路径用于展示与认证
|
||||||
|
const rootPath = `\\\\${hostName}`;
|
||||||
|
this.networkPaths.push({
|
||||||
|
path: rootPath,
|
||||||
|
hostName: hostName,
|
||||||
|
userName: userName,
|
||||||
|
password: password
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取网络路径列表(按主机去重,返回根路径)
|
||||||
|
getNetworkPaths() {
|
||||||
|
const uniqueByHost = {};
|
||||||
|
for (const item of this.networkPaths) {
|
||||||
|
if (!uniqueByHost[item.hostName]) {
|
||||||
|
uniqueByHost[item.hostName] = {
|
||||||
|
path: `\\\\${item.hostName}`,
|
||||||
|
hostName: item.hostName,
|
||||||
|
userName: item.userName || '',
|
||||||
|
password: item.password || ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Object.values(uniqueByHost);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查是否有网络路径
|
||||||
|
hasNetworkPaths() {
|
||||||
|
return this.networkPaths.length > 0;
|
||||||
|
},
|
||||||
|
|
||||||
haveFolderIsCalc() {},
|
haveFolderIsCalc() {},
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ export default {
|
|||||||
},
|
},
|
||||||
onSubmituser() {
|
onSubmituser() {
|
||||||
if (this.ruleForm.name == '1') {
|
if (this.ruleForm.name == '1') {
|
||||||
|
this.setStep()
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/main'
|
path: '/main'
|
||||||
})
|
})
|
||||||
@@ -234,6 +235,31 @@ export default {
|
|||||||
console.log(res.data)
|
console.log(res.data)
|
||||||
localStorage.setItem('loginrole', res.data.resultinfo.userRole)
|
localStorage.setItem('loginrole', res.data.resultinfo.userRole)
|
||||||
localStorage.setItem('loginname', res.data.resultinfo.userName)
|
localStorage.setItem('loginname', res.data.resultinfo.userName)
|
||||||
|
this.setStep()
|
||||||
|
this.$router.push({
|
||||||
|
path: '/main'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if (res.data.resultcode === 2) {
|
||||||
|
this.$message.error(this.$t('login.serviceOut'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (res.data.resultcode === -1) {
|
||||||
|
this.$message.error(this.$t('login.errorLogin'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$message.error(res.data.resultstr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
this.$message.error(e.data.resultstr)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('error user!!')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
setStep() {
|
||||||
const guideStep = [
|
const guideStep = [
|
||||||
{
|
{
|
||||||
show: false,
|
show: false,
|
||||||
@@ -323,28 +349,6 @@ export default {
|
|||||||
]
|
]
|
||||||
localStorage.setItem('guideStep', JSON.stringify(guideStep))
|
localStorage.setItem('guideStep', JSON.stringify(guideStep))
|
||||||
localStorage.setItem('currentStep', 0)
|
localStorage.setItem('currentStep', 0)
|
||||||
this.$router.push({
|
|
||||||
path: '/main'
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
if (res.data.resultcode === 2) {
|
|
||||||
this.$message.error(this.$t('login.serviceOut'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (res.data.resultcode === -1) {
|
|
||||||
this.$message.error(this.$t('login.errorLogin'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.$message.error(res.data.resultstr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
this.$message.error(e.data.resultstr)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
console.log('error user!!')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// 监听回车键执行事件
|
// 监听回车键执行事件
|
||||||
keyDown(e) {
|
keyDown(e) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,252 @@
|
|||||||
|
<template>
|
||||||
|
<div class="screen-recorder">
|
||||||
|
<el-tooltip
|
||||||
|
:content="isRecording ? $t('recorder.stopRecording') : $t('recorder.startRecording')"
|
||||||
|
placement="top">
|
||||||
|
<el-button
|
||||||
|
:type="isRecording ? 'danger' : 'primary'"
|
||||||
|
:icon="isRecording ? 'el-icon-video-pause' : 'el-icon-video-camera'"
|
||||||
|
circle
|
||||||
|
@click="toggleRecording"
|
||||||
|
:loading="loading"
|
||||||
|
class="record-btn"
|
||||||
|
>
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
|
<!-- 录制状态指示器 -->
|
||||||
|
<div v-if="isRecording" class="recording-indicator">
|
||||||
|
<span class="recording-dot"></span>
|
||||||
|
<span class="recording-text">{{ recordingTime }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const { ipcRenderer } = require('electron');
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ScreenRecorder',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isRecording: false,
|
||||||
|
loading: false,
|
||||||
|
mediaRecorder: null,
|
||||||
|
recordedChunks: [],
|
||||||
|
startTime: null,
|
||||||
|
recordingTime: '00:00',
|
||||||
|
timer: null,
|
||||||
|
stream: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async toggleRecording() {
|
||||||
|
if (this.isRecording) {
|
||||||
|
await this.stopRecording();
|
||||||
|
} else {
|
||||||
|
await this.startRecording();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async startRecording() {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用主进程开始录制
|
||||||
|
const result = await ipcRenderer.invoke('start-recording');
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
this.$message.error(result.message);
|
||||||
|
this.loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取屏幕流
|
||||||
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
|
audio: false,
|
||||||
|
video: {
|
||||||
|
mandatory: {
|
||||||
|
chromeMediaSource: 'desktop',
|
||||||
|
chromeMediaSourceId: result.sourceId,
|
||||||
|
minWidth: 1280,
|
||||||
|
maxWidth: 1920,
|
||||||
|
minHeight: 720,
|
||||||
|
maxHeight: 1080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.stream = stream;
|
||||||
|
this.recordedChunks = [];
|
||||||
|
|
||||||
|
// 创建MediaRecorder
|
||||||
|
this.mediaRecorder = new MediaRecorder(stream, {
|
||||||
|
mimeType: 'video/webm'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.mediaRecorder.ondataavailable = (event) => {
|
||||||
|
if (event.data.size > 0) {
|
||||||
|
this.recordedChunks.push(event.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.mediaRecorder.onstop = async () => {
|
||||||
|
await this.saveRecording();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始录制
|
||||||
|
this.mediaRecorder.start();
|
||||||
|
this.isRecording = true;
|
||||||
|
this.startTime = Date.now();
|
||||||
|
this.startTimer();
|
||||||
|
|
||||||
|
this.$message.success(this.$t('recorder.recordingStarted') || '开始录制');
|
||||||
|
this.$emit('recording-started');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('启动录制失败:', error);
|
||||||
|
this.$message.error(this.$t('recorder.startFailed') || '启动录制失败');
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async stopRecording() {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
|
||||||
|
this.mediaRecorder.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 停止所有轨道
|
||||||
|
if (this.stream) {
|
||||||
|
this.stream.getTracks().forEach(track => track.stop());
|
||||||
|
this.stream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isRecording = false;
|
||||||
|
this.stopTimer();
|
||||||
|
this.$emit('recording-stopped');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('停止录制失败:', error);
|
||||||
|
this.$message.error(this.$t('recorder.stopFailed') || '停止录制失败');
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async saveRecording() {
|
||||||
|
if (this.recordedChunks.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 将录制的数据块合并为Blob
|
||||||
|
const blob = new Blob(this.recordedChunks, {
|
||||||
|
type: 'video/webm'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 转换为base64
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = async () => {
|
||||||
|
const base64data = reader.result;
|
||||||
|
|
||||||
|
// 发送到主进程保存
|
||||||
|
const result = await ipcRenderer.invoke('stop-recording', base64data);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存录制失败:', error);
|
||||||
|
this.$message.error(this.$t('recorder.saveFailed') || '保存录制失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
startTimer() {
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
|
||||||
|
const minutes = Math.floor(elapsed / 60).toString().padStart(2, '0');
|
||||||
|
const seconds = (elapsed % 60).toString().padStart(2, '0');
|
||||||
|
this.recordingTime = `${minutes}:${seconds}`;
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
stopTimer() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = null;
|
||||||
|
this.recordingTime = '00:00';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 外部调用的方法,用于在提交作业时自动停止录制
|
||||||
|
async stopIfRecording() {
|
||||||
|
if (this.isRecording) {
|
||||||
|
await this.stopRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
// 组件销毁时确保停止录制
|
||||||
|
if (this.isRecording) {
|
||||||
|
this.stopRecording();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.screen-recorder {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.record-btn {
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recording-indicator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: rgba(245, 108, 108, 0.1);
|
||||||
|
border-radius: 15px;
|
||||||
|
|
||||||
|
.recording-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: #f56c6c;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: blink 1s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recording-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #f56c6c;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -251,6 +251,22 @@
|
|||||||
{{ $t('work.senior') }}
|
{{ $t('work.senior') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
<!-- 屏幕录制按钮 -->
|
||||||
|
<screen-recorder
|
||||||
|
ref="screenRecorder"
|
||||||
|
@recording-started="onRecordingStarted"
|
||||||
|
@recording-stopped="onRecordingStopped"
|
||||||
|
@recording-saved="onRecordingSaved"
|
||||||
|
style="margin-left: 10px; display: inline-block;"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 网络路径认证对话框 -->
|
||||||
|
<network-auth-dialog
|
||||||
|
:visible="networkAuthVisible"
|
||||||
|
:network-paths="networkAuthPaths"
|
||||||
|
@confirm="onNetworkAuthConfirm"
|
||||||
|
@cancel="onNetworkAuthCancel"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-row
|
<el-row
|
||||||
@@ -1145,6 +1161,8 @@ function getNowFormatDate() {
|
|||||||
return currentdate
|
return currentdate
|
||||||
}
|
}
|
||||||
import Files from './files/file.vue'
|
import Files from './files/file.vue'
|
||||||
|
import ScreenRecorder from './recorder/ScreenRecorder.vue'
|
||||||
|
import NetworkAuthDialog from './NetworkAuthDialog.vue'
|
||||||
let fs = require('fs')
|
let fs = require('fs')
|
||||||
let path = require('path')
|
let path = require('path')
|
||||||
const { app, dialog } = require('@electron/remote')
|
const { app, dialog } = require('@electron/remote')
|
||||||
@@ -1182,10 +1200,17 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Files
|
Files,
|
||||||
|
ScreenRecorder,
|
||||||
|
NetworkAuthDialog
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
// 网络路径认证相关
|
||||||
|
networkAuthVisible: false,
|
||||||
|
networkAuthPaths: [],
|
||||||
|
networkCredentials: {},
|
||||||
|
|
||||||
// 模板列表
|
// 模板列表
|
||||||
templates: [],
|
templates: [],
|
||||||
currentTemplate: '',
|
currentTemplate: '',
|
||||||
@@ -1392,10 +1417,77 @@ export default {
|
|||||||
this.guideStep[this.currentStep].show = true
|
this.guideStep[this.currentStep].show = true
|
||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载网络认证信息
|
||||||
|
this.loadNetworkCredentials()
|
||||||
|
|
||||||
this.getTemplates()
|
this.getTemplates()
|
||||||
},
|
},
|
||||||
updated() {},
|
updated() {},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 录制相关方法
|
||||||
|
onRecordingStarted() {
|
||||||
|
console.log('录制已开始')
|
||||||
|
},
|
||||||
|
onRecordingStopped() {
|
||||||
|
console.log('录制已停止')
|
||||||
|
},
|
||||||
|
onRecordingSaved(result) {
|
||||||
|
console.log('录制已保存:', result)
|
||||||
|
this.$message.success(`录制已保存: ${result.fileName}`)
|
||||||
|
},
|
||||||
|
async stopRecordingIfActive() {
|
||||||
|
// 如果正在录制,则停止录制
|
||||||
|
if (this.$refs.screenRecorder) {
|
||||||
|
await this.$refs.screenRecorder.stopIfRecording()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 网络路径认证相关方法
|
||||||
|
loadNetworkCredentials() {
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem('networkCredentials')
|
||||||
|
if (stored) {
|
||||||
|
this.networkCredentials = JSON.parse(stored)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载网络认证信息失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查是否有网络路径需要认证
|
||||||
|
checkNetworkPaths() {
|
||||||
|
if (this.$refs.files && this.$refs.files.hasNetworkPaths()) {
|
||||||
|
const networkPaths = this.$refs.files.getNetworkPaths()
|
||||||
|
if (networkPaths.length > 0) {
|
||||||
|
this.networkAuthPaths = networkPaths
|
||||||
|
this.networkAuthVisible = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
// 网络认证确认回调
|
||||||
|
onNetworkAuthConfirm(netInfo) {
|
||||||
|
this.networkCredentials = netInfo
|
||||||
|
this.networkAuthVisible = false
|
||||||
|
|
||||||
|
// 继续提交流程
|
||||||
|
this.continueSubmit()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 网络认证取消回调
|
||||||
|
onNetworkAuthCancel() {
|
||||||
|
this.networkAuthVisible = false
|
||||||
|
this.$message.info(this.$t('networkAuth.authCanceled'))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 继续提交流程
|
||||||
|
continueSubmit() {
|
||||||
|
// 这里继续原来的提交逻辑
|
||||||
|
this.performSubmit()
|
||||||
|
},
|
||||||
addFolder() {
|
addFolder() {
|
||||||
this.$refs.files.addFolder()
|
this.$refs.files.addFolder()
|
||||||
},
|
},
|
||||||
@@ -2025,7 +2117,21 @@ export default {
|
|||||||
//}, 0);
|
//}, 0);
|
||||||
//console.log(1);
|
//console.log(1);
|
||||||
},
|
},
|
||||||
submit() {
|
async submit() {
|
||||||
|
// 停止录制(如果正在录制)
|
||||||
|
await this.stopRecordingIfActive()
|
||||||
|
|
||||||
|
// 检查是否有网络路径需要认证
|
||||||
|
if (this.checkNetworkPaths()) {
|
||||||
|
return // 等待用户完成网络认证
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续提交流程
|
||||||
|
this.performSubmit()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 实际的提交逻辑
|
||||||
|
async performSubmit() {
|
||||||
//提交最终的任务请求
|
//提交最终的任务请求
|
||||||
let data = ''
|
let data = ''
|
||||||
let pathName
|
let pathName
|
||||||
@@ -2201,6 +2307,12 @@ export default {
|
|||||||
if (this.high_setting_form.formatFile != 0) {
|
if (this.high_setting_form.formatFile != 0) {
|
||||||
data += '&formatFile=' + this.high_setting_form.formatFile //拷贝前类型
|
data += '&formatFile=' + this.high_setting_form.formatFile //拷贝前类型
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加网络路径认证信息
|
||||||
|
if (this.networkCredentials && this.networkCredentials.length > 0) {
|
||||||
|
data += '&net_info=' + JSON.stringify(this.networkCredentials)
|
||||||
|
}
|
||||||
|
|
||||||
// if (this.file_form == 0 || this.file_form == 1 || this.file_form == 4 || this.file_form == 2 || this.file_form == 3 || this.file_form == 7) {
|
// if (this.file_form == 0 || this.file_form == 1 || this.file_form == 4 || this.file_form == 2 || this.file_form == 3 || this.file_form == 7) {
|
||||||
|
|
||||||
// } else {
|
// } else {
|
||||||
@@ -2286,6 +2398,11 @@ export default {
|
|||||||
// 使用FormData上传文件
|
// 使用FormData上传文件
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', blob, path.basename(jsonFilePath))
|
formData.append('file', blob, path.basename(jsonFilePath))
|
||||||
|
|
||||||
|
// 添加网络路径认证信息
|
||||||
|
if (this.networkCredentials && this.networkCredentials.length > 0) {
|
||||||
|
formData.append('net_info', JSON.stringify(this.networkCredentials))
|
||||||
|
}
|
||||||
that.submitLoading = true
|
that.submitLoading = true
|
||||||
// 发送HTTP请求上传文件
|
// 发送HTTP请求上传文件
|
||||||
that
|
that
|
||||||
@@ -2517,7 +2634,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
file_percent() {
|
file_percent() {
|
||||||
let t = (this.size / (((this.size_form * 1000) / 1.024 / 1.024 / 1.024) * 1024 * 1024)) * 100
|
let t = (this.size / (((this.size_form * 1000) / 1.024 / 1.024 / 1.024) * 1024 * 1024)) * 100
|
||||||
return t > 100 ? 100.1 : t
|
return t ? t > 100 ? 100.1 : t : 0
|
||||||
},
|
},
|
||||||
print_op() {
|
print_op() {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -1637,7 +1637,7 @@ export default {
|
|||||||
(this.size /
|
(this.size /
|
||||||
(((this.size_form * 1000) / 1.024 / 1.024 / 1.024) * 1024 * 1024)) *
|
(((this.size_form * 1000) / 1.024 / 1.024 / 1.024) * 1024 * 1024)) *
|
||||||
100;
|
100;
|
||||||
return t > 100 ? 100.1 : t;
|
return t ? t > 100 ? 100.1 : t : 0
|
||||||
},
|
},
|
||||||
print_op() {
|
print_op() {
|
||||||
return [
|
return [
|
||||||
|
|||||||
+23
-1
@@ -1,4 +1,26 @@
|
|||||||
export default {
|
export default {
|
||||||
|
recorder: {
|
||||||
|
startRecording: "开始录制",
|
||||||
|
stopRecording: "停止录制",
|
||||||
|
recordingStarted: "开始录制屏幕",
|
||||||
|
recordingStopped: "录制已停止",
|
||||||
|
savedSuccess: "录制已保存",
|
||||||
|
startFailed: "启动录制失败",
|
||||||
|
stopFailed: "停止录制失败",
|
||||||
|
saveFailed: "保存录制失败"
|
||||||
|
},
|
||||||
|
networkAuth: {
|
||||||
|
title: "网络路径认证",
|
||||||
|
description: "检测到以下网络路径,请输入对应的用户名和密码:",
|
||||||
|
pathLabel: "网络路径:",
|
||||||
|
userName: "用户名",
|
||||||
|
password: "密码",
|
||||||
|
confirm: "确认",
|
||||||
|
cancel: "取消",
|
||||||
|
authRequired: "请填写所有网络路径的用户名和密码",
|
||||||
|
authSuccess: "网络认证信息已保存",
|
||||||
|
authCanceled: "已取消网络路径认证"
|
||||||
|
},
|
||||||
finger: {
|
finger: {
|
||||||
intTips: "指纹模块正在初始化",
|
intTips: "指纹模块正在初始化",
|
||||||
errorInttips: "指纹模块初始化失败",
|
errorInttips: "指纹模块初始化失败",
|
||||||
@@ -18,7 +40,7 @@ export default {
|
|||||||
login: "登录",
|
login: "登录",
|
||||||
fingerLogin: "使用指纹登录",
|
fingerLogin: "使用指纹登录",
|
||||||
title1: "CARDSOON USB存储卡",
|
title1: "CARDSOON USB存储卡",
|
||||||
title2: "自动拷贝打印系统 V3.0",
|
title2: "自动拷贝打印系统 V3.1",
|
||||||
successLogin: "登录成功!",
|
successLogin: "登录成功!",
|
||||||
errorFingerlogin: "登录失败,请重试指纹!",
|
errorFingerlogin: "登录失败,请重试指纹!",
|
||||||
errorLogin: "登录失败,请检查账号密码!",
|
errorLogin: "登录失败,请检查账号密码!",
|
||||||
|
|||||||
@@ -1,4 +1,26 @@
|
|||||||
export default {
|
export default {
|
||||||
|
recorder: {
|
||||||
|
startRecording: "Start Recording",
|
||||||
|
stopRecording: "Stop Recording",
|
||||||
|
recordingStarted: "Screen recording started",
|
||||||
|
recordingStopped: "Recording stopped",
|
||||||
|
savedSuccess: "Recording saved",
|
||||||
|
startFailed: "Failed to start recording",
|
||||||
|
stopFailed: "Failed to stop recording",
|
||||||
|
saveFailed: "Failed to save recording"
|
||||||
|
},
|
||||||
|
networkAuth: {
|
||||||
|
title: "Network Path Authentication",
|
||||||
|
description: "The following network paths were detected. Please enter the corresponding username and password:",
|
||||||
|
pathLabel: "Network Path:",
|
||||||
|
userName: "Username",
|
||||||
|
password: "Password",
|
||||||
|
confirm: "Confirm",
|
||||||
|
cancel: "Cancel",
|
||||||
|
authRequired: "Please fill in username and password for all network paths",
|
||||||
|
authSuccess: "Network authentication information saved",
|
||||||
|
authCanceled: "Network path authentication canceled"
|
||||||
|
},
|
||||||
finger: {
|
finger: {
|
||||||
intTips: "The fingerprint module is initializing",
|
intTips: "The fingerprint module is initializing",
|
||||||
errorInttips: "Fingerprint module initialization fail",
|
errorInttips: "Fingerprint module initialization fail",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export default {
|
|||||||
login:"登入",
|
login:"登入",
|
||||||
fingerLogin:"使用指紋登入",
|
fingerLogin:"使用指紋登入",
|
||||||
title1:"CARDSOON USB存儲卡",
|
title1:"CARDSOON USB存儲卡",
|
||||||
title2:"自動拷貝列印系統V3.0",
|
title2:"自動拷貝列印系統V3.1",
|
||||||
successLogin:"登入成功! ",
|
successLogin:"登入成功! ",
|
||||||
errorFingerlogin:"登入失敗,請重試指紋! ",
|
errorFingerlogin:"登入失敗,請重試指紋! ",
|
||||||
errorLogin:"登入失敗,請檢查帳號密碼! ",
|
errorLogin:"登入失敗,請檢查帳號密碼! ",
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
const state = {
|
||||||
|
networkCredentials: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mutations = {
|
||||||
|
SET_NETWORK_CREDENTIALS(state, credentials) {
|
||||||
|
state.networkCredentials = { ...state.networkCredentials, ...credentials }
|
||||||
|
},
|
||||||
|
|
||||||
|
CLEAR_NETWORK_CREDENTIALS(state) {
|
||||||
|
state.networkCredentials = {}
|
||||||
|
},
|
||||||
|
|
||||||
|
UPDATE_NETWORK_CREDENTIAL(state, { hostName, credentials }) {
|
||||||
|
state.networkCredentials = {
|
||||||
|
...state.networkCredentials,
|
||||||
|
[hostName]: credentials
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
// 从 localStorage 加载网络认证信息
|
||||||
|
loadNetworkCredentials({ commit }) {
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem('networkCredentials')
|
||||||
|
if (stored) {
|
||||||
|
const credentials = JSON.parse(stored)
|
||||||
|
commit('SET_NETWORK_CREDENTIALS', credentials)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载网络认证信息失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 保存网络认证信息到 localStorage
|
||||||
|
saveNetworkCredentials({ state }) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem('networkCredentials', JSON.stringify(state.networkCredentials))
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存网络认证信息失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取指定主机的认证信息
|
||||||
|
getCredentialsForHost({ state }, hostName) {
|
||||||
|
return state.networkCredentials[hostName] || null
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新指定主机的认证信息
|
||||||
|
updateCredentialsForHost({ commit }, { hostName, credentials }) {
|
||||||
|
commit('UPDATE_NETWORK_CREDENTIAL', { hostName, credentials })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getters = {
|
||||||
|
// 获取所有网络认证信息
|
||||||
|
allNetworkCredentials: state => state.networkCredentials,
|
||||||
|
|
||||||
|
// 检查是否有网络认证信息
|
||||||
|
hasNetworkCredentials: state => Object.keys(state.networkCredentials).length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
|
getters
|
||||||
|
}
|
||||||
Binary file not shown.
Reference in New Issue
Block a user