feat: 优化储存卡能量格组件EnergyBar(更紧凑、可调尺寸、充能特效);修复样式命名冲突;微调色带进度条底色与不换行显示;清理调试信息
This commit is contained in:
@@ -74,7 +74,7 @@ function startRenderer () {
|
||||
}
|
||||
)
|
||||
|
||||
server.listen(9080)
|
||||
server.listen(9081)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ if (process.env.NODE_ENV !== "development") {
|
||||
let mainWindow;
|
||||
const winURL =
|
||||
process.env.NODE_ENV === "development"
|
||||
? `http://localhost:9080`
|
||||
? `http://localhost:9081`
|
||||
: `file://${__dirname}/index.html`;
|
||||
|
||||
function createWindow() {
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ if (process.env.NODE_ENV !== "development") {
|
||||
let mainWindow;
|
||||
const winURL =
|
||||
process.env.NODE_ENV === "development"
|
||||
? `http://localhost:9080`
|
||||
? `http://localhost:9081`
|
||||
: `file://${__dirname}/index.html`;
|
||||
|
||||
function createWindow() {
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="energy-bar compact energy-dash" :title="tooltip">
|
||||
<div class="energy-cells" :style="{ gap: gap + 'px' }">
|
||||
<div
|
||||
v-for="n in segments"
|
||||
:key="n"
|
||||
:class="cellClass(n)"
|
||||
:style="{ width: cellWidth + 'px', height: cellHeight + 'px', borderRadius: borderRadius + 'px' }" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'EnergyBar',
|
||||
props: {
|
||||
// 百分比 0-100
|
||||
percent: { type: Number, default: 0 },
|
||||
// 段数 6 或 8
|
||||
segments: { type: Number, default: 8 },
|
||||
// 显示文本
|
||||
showText: { type: Boolean, default: true },
|
||||
// 自定义文本
|
||||
text: { type: String, default: '' },
|
||||
// 尺寸控制(像素)
|
||||
cellWidth: { type: Number, default: 4 },
|
||||
cellHeight: { type: Number, default: 10 },
|
||||
gap: { type: Number, default: 1 },
|
||||
borderRadius: { type: Number, default: 1 },
|
||||
},
|
||||
computed: {
|
||||
litCells() {
|
||||
const clamped = Math.max(0, Math.min(100, Math.round(this.percent || 0)))
|
||||
// 一个能量格代表10(进1制向上取整)
|
||||
const cells = Math.ceil(clamped / 10)
|
||||
return Math.max(0, Math.min(this.segments, cells))
|
||||
},
|
||||
displayText() {
|
||||
return this.text || `${Math.max(0, Math.min(100, Math.round(this.percent || 0)))}%`
|
||||
},
|
||||
tooltip() {
|
||||
return this.displayText
|
||||
},
|
||||
tone() {
|
||||
// 低电量红 / 中电量橙 / 高电量绿
|
||||
const p = Math.max(0, Math.min(100, this.percent || 0))
|
||||
if (p <= 20) return 'danger'
|
||||
if (p <= 50) return 'warning'
|
||||
return 'success'
|
||||
},
|
||||
chargingIndex() {
|
||||
// 若不是整十,最后一格视为“充能中”
|
||||
const p = Math.max(0, Math.min(100, this.percent || 0))
|
||||
if (p % 10 === 0 || this.litCells === 0) return -1
|
||||
return this.litCells
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cellClass(n) {
|
||||
const lit = n <= this.litCells
|
||||
// 仿数码表样式:前2格为红色,其余为绿色(只在被点亮时着色)
|
||||
const zone = n <= 2 ? 'low' : 'high'
|
||||
return [
|
||||
'energy-cell',
|
||||
lit ? (zone === 'low' ? 'is-red' : 'is-green') : 'is-off',
|
||||
(this.chargingIndex === n && lit) ? 'is-charging' : ''
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.energy-bar {
|
||||
display: inline-flex;
|
||||
}
|
||||
.energy-dash {
|
||||
/* 取消黑色底,采用透明背景以突出分隔与未点亮格 */
|
||||
background: transparent;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.compact .energy-cells {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.energy-cell {
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
}
|
||||
.energy-cell.is-red {
|
||||
background: linear-gradient(180deg, #ff6b6b, #ff3f3f);
|
||||
box-shadow: 0 0 2px rgba(255,58,58,.45);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: pulse 2.8s ease-in-out infinite;
|
||||
}
|
||||
.energy-cell.is-green {
|
||||
background: linear-gradient(180deg, #6dff55, #30cc42);
|
||||
box-shadow: 0 0 2px rgba(103,255,77,.35);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: pulse 2.8s ease-in-out infinite;
|
||||
}
|
||||
.energy-cell.is-off {
|
||||
/* 提高对比度:更亮的灰底+更明显边框,便于在深色背景下辨识格数 */
|
||||
background: #2f3643;
|
||||
border: 1px solid #556179;
|
||||
box-shadow: inset 0 1px 1px rgba(255,255,255,.06);
|
||||
}
|
||||
.energy-cell.is-charging {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.energy-cell.is-charging::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -120%;
|
||||
top: 0;
|
||||
width: 120%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.28), rgba(255,255,255,0));
|
||||
animation: sweep 2.4s linear infinite;
|
||||
}
|
||||
/* 所有点亮的格子也有较弱的扫光效果与更高亮度 */
|
||||
.energy-cell.is-green::before,
|
||||
.energy-cell.is-red::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -120%;
|
||||
top: 0;
|
||||
width: 120%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.18), rgba(255,255,255,0));
|
||||
animation: sweep 3s linear infinite;
|
||||
}
|
||||
@keyframes pulse {
|
||||
0% { filter: brightness(0.98); }
|
||||
50% { filter: brightness(1.08); }
|
||||
100% { filter: brightness(0.98); }
|
||||
}
|
||||
@keyframes sweep {
|
||||
0% { left: -120%; }
|
||||
100% { left: 120%; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":["E:\\TortoiseGit License.txt"]}
|
||||
{"files":["\\\\NAS\\study\\research_reports\\2025\\数据资产价值释放之行业应用场景解析与合规框架——科学研究和技术服务业.pdf"]}
|
||||
@@ -223,7 +223,8 @@
|
||||
:class="{ guide_body: beginStep && currentStep == 7 }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="newWork">
|
||||
@click="newWork"
|
||||
:disabled="infoData.length == 0 && state == false">
|
||||
{{ $t('index.newWork') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -408,7 +409,7 @@
|
||||
prop="status"
|
||||
:label="$t('main.tableState')"
|
||||
min-width="80">
|
||||
<template slot-scope="scope">{{ $t('main.tableOnline') }}</template>
|
||||
<template slot-scope="{}">{{ $t('main.tableOnline') }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="SerialNo"
|
||||
@@ -540,7 +541,9 @@
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
:empty-text="$t('index.nodata')"
|
||||
row-class-name="rowclass">
|
||||
row-class-name="rowclass"
|
||||
:row-key="row => row.JobID || row.AssUuid"
|
||||
:tree-props="{ children: 'children' }">
|
||||
<el-table-column
|
||||
label="#"
|
||||
width="50">
|
||||
@@ -552,6 +555,10 @@
|
||||
prop="jId"
|
||||
:label="$t('index.wordID')"
|
||||
min-width="85">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!scope.row.AssUuid">{{ scope.row.jId }}</span>
|
||||
<span v-else>{{ (scope.row.ParentJobID || '') | shortJobId }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="DataSource"
|
||||
@@ -562,20 +569,23 @@
|
||||
:label="$t('index.wordSpace')"
|
||||
min-width="45">
|
||||
<template slot-scope="scope">
|
||||
{{ getPrintName(scope.row.PrinterID, true) }}
|
||||
<span v-if="!scope.row.AssUuid">{{ getPrintName(scope.row.PrinterID, true) }}</span>
|
||||
<span v-else>{{ getPrintName(scope.row.ParentPrinterID || scope.row.PrinterID, true) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('main.USBType')"
|
||||
min-width="55">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.PrinterType }}
|
||||
{{ !scope.row.AssUuid ? scope.row.PrinterType : (scope.row.ParentPrinterType || scope.row.PrinterType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="60"
|
||||
prop="TaskCapacity"
|
||||
:label="$t('main.TaskCapacity')">
|
||||
<template slot-scope="scope">
|
||||
{{ !scope.row.AssUuid ? scope.row.TaskCapacity : (scope.row.ParentTaskCapacity || '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="false"
|
||||
@@ -583,9 +593,11 @@
|
||||
:label="$t('main.taskFile')">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="CreateTime"
|
||||
:label="$t('index.createTime')"
|
||||
min-width="75">
|
||||
<template slot-scope="scope">
|
||||
{{ !scope.row.AssUuid ? scope.row.CreateTime : (scope.row.StartTime || '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="false"
|
||||
@@ -598,48 +610,64 @@
|
||||
:filter-method="filterHandler">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="FinishTime"
|
||||
:label="$t('index.finishedTime')"
|
||||
min-width="75">
|
||||
<template slot-scope="scope">
|
||||
{{ !scope.row.AssUuid ? scope.row.FinishTime : (scope.row.FinishTime || '') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="JobCompletion"
|
||||
min-width="40"
|
||||
:label="$t('index.finishedNumber')">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!scope.row.AssUuid">{{ scope.row.JobCompletion }}</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('index.state')"
|
||||
prop="JobStatus"
|
||||
width="135">
|
||||
<template slot-scope="scope">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(e) => handleTaskCommand(e, scope.row.JobID)"
|
||||
:disabled="scope.row.JobStatus != 'Fail'">
|
||||
<span
|
||||
class="el-dropdown-link"
|
||||
style="color: #000; font-size: 12px">
|
||||
{{ jobState(scope.row.JobStatus) }}<b v-if="scope.row.JobStatus === 'Copying'" style="margin-left: 3px;">{{ scope.row.CopySpeed ? Math.ceil(parseFloat(scope.row.CopySpeed)*10)/10 : '0.0' }}MB/s</b>
|
||||
<i
|
||||
class="el-icon-arrow-down el-icon--right"
|
||||
v-if="scope.row.JobStatus == 'Fail'"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="refresh">
|
||||
<span style="color: #000; font-size: 12px">{{ $t('main.commandRefresh') }}</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete">
|
||||
<span style="color: #000; font-size: 12px">{{ $t('main.commandDelete') }}</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-progress
|
||||
:color="customColors"
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:stroke-width="3"
|
||||
:percentage="parseFloat(scope.row.TaskPercentage.replace(`%`, ``))"
|
||||
v-if="scope.row.JobStatus == `Copying`"></el-progress>
|
||||
<template v-if="!scope.row.AssUuid">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(e) => handleTaskCommand(e, scope.row.JobID)"
|
||||
:disabled="scope.row.JobStatus != 'Fail'">
|
||||
<span
|
||||
class="el-dropdown-link"
|
||||
style="color: #000; font-size: 12px">
|
||||
{{ jobState(scope.row.JobStatus) }}<b v-if="scope.row.JobStatus === 'Copying'" style="margin-left: 3px;">{{ scope.row.CopySpeed ? Math.ceil(parseFloat(scope.row.CopySpeed)*10)/10 : '0.0' }}MB/s</b>
|
||||
<i
|
||||
class="el-icon-arrow-down el-icon--right"
|
||||
v-if="scope.row.JobStatus == 'Fail'"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="refresh">
|
||||
<span style="color: #000; font-size: 12px">{{ $t('main.commandRefresh') }}</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete">
|
||||
<span style="color: #000; font-size: 12px">{{ $t('main.commandDelete') }}</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-progress
|
||||
:color="customColors"
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:stroke-width="3"
|
||||
:percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
|
||||
v-if="scope.row.JobStatus == `Copying`"></el-progress>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ jobState(scope.row.TaskStatus) }}
|
||||
<el-progress
|
||||
:color="customColors"
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:stroke-width="3"
|
||||
:percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
|
||||
v-if="scope.row.TaskStatus == `Copying`"></el-progress>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -823,6 +851,12 @@ export default {
|
||||
warnCard,
|
||||
sFooter
|
||||
},
|
||||
filters: {
|
||||
shortJobId(v) {
|
||||
if (!v) return ''
|
||||
return String(v).split('-')[0]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
guideStep: null,
|
||||
@@ -1085,12 +1119,12 @@ export default {
|
||||
this.getSystemInfo()
|
||||
this.selectLan = localStorage.getItem('lang')
|
||||
this.isAdmin = localStorage.getItem('loginrole') == 'administrator'
|
||||
// const tempTimer = setInterval(() => {
|
||||
// if (JSON.stringify(this.ribbonList) != '{}') {
|
||||
// this.getData(1) //首次触发需要先获取到Ribbon数据
|
||||
// clearInterval(tempTimer)
|
||||
// }
|
||||
// }, 200)
|
||||
const tempTimer = setInterval(() => {
|
||||
if (JSON.stringify(this.ribbonList) != '{}') {
|
||||
this.getData(1) //首次触发需要先获取到Ribbon数据
|
||||
clearInterval(tempTimer)
|
||||
}
|
||||
}, 200)
|
||||
ipcRenderer.on('open-program-callback', (event, data) => {
|
||||
console.log(data)
|
||||
this.openFile(data)
|
||||
@@ -1105,13 +1139,12 @@ export default {
|
||||
ipcRenderer.send('get-root')
|
||||
ipcRenderer.send('open-program')
|
||||
this.guideStep = JSON.parse(localStorage.getItem('guideStep'))
|
||||
console.log(this.guideStep)
|
||||
this.currentStep = localStorage.getItem('currentStep')
|
||||
if ((!localStorage.getItem('hideStep') || localStorage.getItem('hideStep') == 0)&&this.currentStep>-1) this.showStep = true
|
||||
setTimeout(() => {
|
||||
this.doingWorkStatus = false
|
||||
}, 10000)
|
||||
// this.timer2 = setInterval(this.getPrintData, this.refreshTime2)
|
||||
this.timer2 = setInterval(this.getPrintData, this.refreshTime2)
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.stopTimer()
|
||||
@@ -1265,13 +1298,31 @@ export default {
|
||||
this.state = true
|
||||
let tasks = [...this.tasks]
|
||||
this.tasks = []
|
||||
for (let item of res.data.unfinishedTasks) {
|
||||
item.jId = item.JobID.split('-')[0] //+ "...";
|
||||
this.tasks.push(item)
|
||||
const normalize = (task) => {
|
||||
const jId = (task.JobID || '').split('-')[0]
|
||||
const parentCommon = {
|
||||
jId,
|
||||
ParentJobID: task.JobID,
|
||||
ParentPrinterID: task.PrinterID,
|
||||
ParentPrinterType: task.PrinterType,
|
||||
ParentTaskCapacity: task.TaskCapacity
|
||||
}
|
||||
const children = Array.isArray(task.AssTask) ? task.AssTask.map((child) => ({
|
||||
...child,
|
||||
...parentCommon
|
||||
})) : []
|
||||
return {
|
||||
...task,
|
||||
jId,
|
||||
children
|
||||
}
|
||||
}
|
||||
for (let item of res.data.finishedTasks) {
|
||||
item.jId = item.JobID.split('-')[0] //+ "...";
|
||||
this.tasks.push(item)
|
||||
|
||||
for (let item of (res.data.unfinishedTasks || [])) {
|
||||
this.tasks.push(normalize(item))
|
||||
}
|
||||
for (let item of (res.data.finishedTasks || [])) {
|
||||
this.tasks.push(normalize(item))
|
||||
}
|
||||
let total1 = 0
|
||||
let total2 = 0
|
||||
@@ -1681,6 +1732,19 @@ export default {
|
||||
}
|
||||
this.isNew = true
|
||||
this.dialogVisible = true
|
||||
// 新建任务时重置文件列表与网络认证状态,避免上一次残留导致卡顿
|
||||
this.$nextTick(() => {
|
||||
const workRef = this.$refs.work
|
||||
if (workRef && workRef.$refs && workRef.$refs.files && workRef.$refs.files.reset) {
|
||||
workRef.$refs.files.reset()
|
||||
}
|
||||
if (workRef) {
|
||||
workRef.networkAuthVisible = false
|
||||
workRef.networkAuthPaths = []
|
||||
workRef.networkCredentials = {}
|
||||
workRef.submitLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
newNetWork() {
|
||||
//this.isNew = true;
|
||||
@@ -1869,15 +1933,15 @@ export default {
|
||||
watch: {
|
||||
hasDoingWork: {
|
||||
handler() {
|
||||
// if (this.hasDoingWork) {
|
||||
// this.intervalTime = parseInt(this.refreshTime1)
|
||||
// clearInterval(this.timer1)
|
||||
// this.timer1 = setInterval(this.initData, this.intervalTime)
|
||||
// } else {
|
||||
// this.intervalTime = parseInt(this.refreshTime2)
|
||||
// clearInterval(this.timer1)
|
||||
// this.timer1 = setInterval(this.initData, this.intervalTime)
|
||||
// }
|
||||
if (this.hasDoingWork) {
|
||||
this.intervalTime = parseInt(this.refreshTime1)
|
||||
clearInterval(this.timer1)
|
||||
this.timer1 = setInterval(this.initData, this.intervalTime)
|
||||
} else {
|
||||
this.intervalTime = parseInt(this.refreshTime2)
|
||||
clearInterval(this.timer1)
|
||||
this.timer1 = setInterval(this.initData, this.intervalTime)
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
||||
@@ -223,8 +223,7 @@
|
||||
:class="{ guide_body: beginStep && currentStep == 7 }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="newWork"
|
||||
:disabled="infoData.length == 0 && state == false">
|
||||
@click="newWork">
|
||||
{{ $t('index.newWork') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -427,16 +426,13 @@
|
||||
min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-progress
|
||||
class="ribbon-progress"
|
||||
:color="customColors"
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:format="() => scope.row.RibbonAmount"
|
||||
:width="60"
|
||||
define-back-color="#dfe4ed"
|
||||
:format="() => String(scope.row.RibbonAmount || 0)"
|
||||
:stroke-width="3"
|
||||
:percentage="
|
||||
scope.row.RibbonAmount == undefined || scope.row.RibbonAmount == '0'
|
||||
? 0
|
||||
: parseFloat(((scope.row.RibbonAmount / getRibbonAmount(scope.row.ModeName, scope.row.RibbonType)) * 100).toFixed(0))
|
||||
"></el-progress>
|
||||
:percentage="safePercent(scope.row.RibbonAmount, getRibbonAmount(scope.row.ModeName, scope.row.RibbonType))"></el-progress>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -474,17 +470,11 @@
|
||||
:label="$t('main.tablePrinterRemaCapa')"
|
||||
min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-progress
|
||||
:color="customColors"
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:format="() => (scope.row.PrinterRemaCapa > 0 ? scope.row.PrinterRemaCapa : 0)"
|
||||
:stroke-width="3"
|
||||
:percentage="
|
||||
scope.row.PrinterRemaCapa == undefined || scope.row.PrinterRemaCapa == '0'
|
||||
? 0
|
||||
: parseFloat((((scope.row.PrinterRemaCapa > 0 ? scope.row.PrinterRemaCapa : 0) / getPrinterRemaCapaAmount(scope.row.ModeName)) * 100).toFixed(0))
|
||||
"></el-progress>
|
||||
<EnergyBar
|
||||
:percent="safePercent((scope.row.PrinterRemaCapa > 0 ? scope.row.PrinterRemaCapa : 0), getPrinterRemaCapaAmount(scope.row.ModeName))"
|
||||
:segments="(scope.row.ModeName === 'TH80N' ? 6 : 8)"
|
||||
:showText="true"
|
||||
:text="String(scope.row.PrinterRemaCapa > 0 ? scope.row.PrinterRemaCapa : 0)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -541,14 +531,14 @@
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
:empty-text="$t('index.nodata')"
|
||||
row-class-name="rowclass"
|
||||
:row-class-name="rowClassName"
|
||||
:row-key="row => row.JobID || row.AssUuid"
|
||||
:tree-props="{ children: 'children' }">
|
||||
<el-table-column
|
||||
label="#"
|
||||
width="50">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
<span v-if="!scope.row.AssUuid">{{ parentIndex(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -557,13 +547,16 @@
|
||||
min-width="85">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!scope.row.AssUuid">{{ scope.row.jId }}</span>
|
||||
<span v-else>{{ (scope.row.ParentJobID || '') | shortJobId }}</span>
|
||||
<span v-else></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="DataSource"
|
||||
:label="$t('index.wordOrigin')"
|
||||
min-width="50">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="!scope.row.AssUuid">{{ scope.row.DataSource }}</span>
|
||||
<span v-else></span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('index.wordSpace')"
|
||||
@@ -655,7 +648,7 @@
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:stroke-width="3"
|
||||
:percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
|
||||
:percentage="Math.max(0, Math.min(100, Number(String(scope.row.TaskPercentage || '0').replace('%','')) || 0))"
|
||||
v-if="scope.row.JobStatus == `Copying`"></el-progress>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -665,7 +658,7 @@
|
||||
:width="45"
|
||||
define-back-color="#ebeef5"
|
||||
:stroke-width="3"
|
||||
:percentage="parseFloat((scope.row.TaskPercentage || '0').replace(`%`, ``))"
|
||||
:percentage="Math.max(0, Math.min(100, Number(String(scope.row.TaskPercentage || '0').replace('%','')) || 0))"
|
||||
v-if="scope.row.TaskStatus == `Copying`"></el-progress>
|
||||
</template>
|
||||
</template>
|
||||
@@ -842,6 +835,7 @@ import sFooter from './footer.vue'
|
||||
import warnCard from './warn-card.vue'
|
||||
import N80N from '../assets/80N.png'
|
||||
import N800N from '../assets/800N.png'
|
||||
import EnergyBar from './EnergyBar.vue'
|
||||
|
||||
export default {
|
||||
name: 'Main',
|
||||
@@ -849,7 +843,8 @@ export default {
|
||||
work,
|
||||
worknet,
|
||||
warnCard,
|
||||
sFooter
|
||||
sFooter,
|
||||
EnergyBar
|
||||
},
|
||||
filters: {
|
||||
shortJobId(v) {
|
||||
@@ -1150,6 +1145,27 @@ export default {
|
||||
this.stopTimer()
|
||||
},
|
||||
methods: {
|
||||
rowClassName({ row }) {
|
||||
// 子任务行更紧凑
|
||||
return row.AssUuid ? 'ass-row' : ''
|
||||
},
|
||||
safePercent(value, total) {
|
||||
const v = Number(value)
|
||||
const t = Number(total)
|
||||
if (!isFinite(v) || !isFinite(t) || t <= 0) return 0
|
||||
const p = (v / t) * 100
|
||||
if (!isFinite(p) || isNaN(p)) return 0
|
||||
return Math.max(0, Math.min(100, Math.round(p)))
|
||||
},
|
||||
parentIndex(row) {
|
||||
// 只对父任务计算序号:按 tasks 顶层数组索引 + 1
|
||||
if (row && !row.AssUuid) {
|
||||
const id = row.JobID
|
||||
const idx = (this.tasks || []).findIndex(t => t.JobID === id)
|
||||
return idx >= 0 ? idx + 1 : ''
|
||||
}
|
||||
return ''
|
||||
},
|
||||
initData() {
|
||||
this.getData()
|
||||
this.getLogData()
|
||||
@@ -1305,7 +1321,8 @@ export default {
|
||||
ParentJobID: task.JobID,
|
||||
ParentPrinterID: task.PrinterID,
|
||||
ParentPrinterType: task.PrinterType,
|
||||
ParentTaskCapacity: task.TaskCapacity
|
||||
ParentTaskCapacity: task.TaskCapacity,
|
||||
ParentDataSource: task.DataSource
|
||||
}
|
||||
const children = Array.isArray(task.AssTask) ? task.AssTask.map((child) => ({
|
||||
...child,
|
||||
@@ -1741,7 +1758,6 @@ export default {
|
||||
if (workRef) {
|
||||
workRef.networkAuthVisible = false
|
||||
workRef.networkAuthPaths = []
|
||||
workRef.networkCredentials = {}
|
||||
workRef.submitLoading = false
|
||||
}
|
||||
})
|
||||
@@ -1755,10 +1771,12 @@ export default {
|
||||
return String.fromCharCode(65 + parseInt(n))
|
||||
},
|
||||
getPrintName(id, onlyId) {
|
||||
const safeId = (id && typeof id === 'string') ? id : ''
|
||||
const tail = safeId.length >= 5 ? safeId.substr(-5) : safeId || '--'
|
||||
if (onlyId === true) {
|
||||
return id.substr(-5)
|
||||
return tail
|
||||
}
|
||||
return this.$t('index.wordSpace') + id.substr(-5)
|
||||
return this.$t('index.wordSpace') + tail
|
||||
},
|
||||
getPrinterRemaCapaAmount(ModeName) {
|
||||
// console.log('PrinterRemaCapa', this.ribbonList[ModeName].PrinterRemaCapa)
|
||||
@@ -2158,6 +2176,30 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
/* 子任务行紧凑显示 */
|
||||
/deep/ .el-table__row.ass-row > td {
|
||||
padding-top: 2px !important;
|
||||
padding-bottom: 2px !important;
|
||||
}
|
||||
/deep/ .el-table__row.ass-row .cell {
|
||||
line-height: 18px !important;
|
||||
}
|
||||
/* 去除树结构行默认左侧过大缩进,让箭头与内容更紧凑 */
|
||||
/deep/ .el-table__expand-icon {
|
||||
margin-right: 2px;
|
||||
}
|
||||
/* 缩小树结构图标列宽与缩进 */
|
||||
/deep/ .el-table__indent {
|
||||
padding-left: 8px !important;
|
||||
}
|
||||
/deep/ .el-table__expand-icon > i {
|
||||
font-size: 12px;
|
||||
}
|
||||
/* 进度条内数字不换行 */
|
||||
/deep/ .ribbon-progress .el-progress-bar__innerText {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.user {
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
@@ -2217,6 +2259,38 @@ a {
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 色带进度条样式优化 */
|
||||
/deep/ .ribbon-progress .el-progress-bar__outer {
|
||||
background: linear-gradient(180deg, #f3f6fa, #e5ebf5);
|
||||
border-radius: 6px;
|
||||
border: 1px solid #cfd6e3;
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,.08);
|
||||
}
|
||||
/deep/ .ribbon-progress .el-progress-bar__inner {
|
||||
border-radius: 6px;
|
||||
}
|
||||
+.ribbon-wrap {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
background: rgba(255,255,255,.35);
|
||||
backdrop-filter: blur(3px);
|
||||
}
|
||||
+.ribbon-badge {
|
||||
min-width: 30px;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
padding: 0 8px;
|
||||
border-radius: 9px;
|
||||
background: linear-gradient(145deg, #1f2430, #0e1118);
|
||||
color: #bfe3ff;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,.15), inset 0 0 8px rgba(120,180,255,.25);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.rowclass {
|
||||
|
||||
@@ -1209,6 +1209,10 @@ export default {
|
||||
this.loadNetworkCredentials()
|
||||
|
||||
this.getTemplates()
|
||||
// 加载已保存的网络认证,支持二次新建直接使用
|
||||
if (this.loadNetworkCredentials) {
|
||||
this.loadNetworkCredentials()
|
||||
}
|
||||
},
|
||||
updated() {},
|
||||
methods: {
|
||||
@@ -1244,14 +1248,50 @@ export default {
|
||||
|
||||
// 检查是否有网络路径需要认证
|
||||
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
|
||||
if (!(this.$refs.files && this.$refs.files.hasNetworkPaths())) {
|
||||
return false
|
||||
}
|
||||
const networkPaths = this.$refs.files.getNetworkPaths() || []
|
||||
if (networkPaths.length === 0) return false
|
||||
|
||||
// 从本地存储的 credentials 中匹配已有主机
|
||||
let stored = {}
|
||||
try {
|
||||
stored = JSON.parse(localStorage.getItem('networkCredentials') || '{}')
|
||||
} catch (e) {
|
||||
stored = {}
|
||||
}
|
||||
const missing = []
|
||||
const prepared = []
|
||||
for (const item of networkPaths) {
|
||||
const host = item.hostName || this.getHostFromPath(item.path) || ''
|
||||
if (host && stored[host] && stored[host].userName && stored[host].password) {
|
||||
prepared.push({
|
||||
host_name: host,
|
||||
user_name: stored[host].userName,
|
||||
password: stored[host].password,
|
||||
})
|
||||
} else {
|
||||
missing.push({ ...item, hostName: host })
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.length > 0) {
|
||||
// 仅对缺失凭据的主机弹窗
|
||||
this.networkAuthPaths = missing.map(m => ({
|
||||
path: m.path,
|
||||
hostName: m.hostName,
|
||||
userName: '',
|
||||
password: ''
|
||||
}))
|
||||
this.networkAuthVisible = true
|
||||
// 先保存已准备好的,等用户补齐再一起提交
|
||||
this.networkCredentials = prepared
|
||||
return true
|
||||
}
|
||||
|
||||
// 全部已有凭据,直接使用
|
||||
this.networkCredentials = prepared
|
||||
return false
|
||||
},
|
||||
|
||||
@@ -2426,6 +2466,20 @@ export default {
|
||||
},
|
||||
help() {
|
||||
ipcRenderer.send('open-help-file')
|
||||
},
|
||||
// 从路径提取主机名(兼容 \\host\path 与 //host/path)
|
||||
getHostFromPath(p) {
|
||||
if (!p || typeof p !== 'string') return ''
|
||||
if (p.indexOf('\\\\') === 0) {
|
||||
const parts = p.slice(2).split('\\')
|
||||
return parts[0] || ''
|
||||
}
|
||||
if (p.indexOf('//') === 0) {
|
||||
const parts = p.slice(2).split('/')
|
||||
return parts[0] || ''
|
||||
}
|
||||
const m = p.match(/^([^\\\/:]+)/)
|
||||
return (m && m[1]) ? m[1] : ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
Reference in New Issue
Block a user