style:Dashboard1数据大屏适配中英文

main
黄伟杰 5 days ago
parent 8006dc018b
commit 7c08bb7154

@ -99,6 +99,78 @@ export default {
messageRouteMissing: 'Preview route is not configured', messageRouteMissing: 'Preview route is not configured',
messageDevicePointRequired: 'Please configure at least one device and point group', messageDevicePointRequired: 'Please configure at least one device and point group',
messageMissingId: 'Missing record ID, unable to edit' messageMissingId: 'Missing record ID, unable to edit'
},
Dashboard1: {
header: {
title: 'Production Line Dashboard',
weather: {
cloudyToClear: 'Cloudy to clear'
},
weekDays: {
Sunday: 'Sunday',
Monday: 'Monday',
Tuesday: 'Tuesday',
Wednesday: 'Wednesday',
Thursday: 'Thursday',
Friday: 'Friday',
Saturday: 'Saturday'
}
},
deviceIdPrefix: 'ID:',
defaultDeviceName: 'Default Device',
statusOffline: 'Offline',
statusRunning: 'Running',
statusStandby: 'Standby',
statusFault: 'Fault',
deviceOverview: {
title: 'Device Overview',
device: 'Devices',
running: 'Running',
idle: 'Standby',
alarm: 'Alarms',
utilization: 'Utilization',
faultRate: 'Fault Rate'
},
alarms: {
title: 'Real-time Alarms',
tag: 'Scrolling',
levelSevere: 'Severe',
levelWarn: 'Warning',
levelInfo: 'Info'
},
productionTrend: {
title: 'Output Trend',
tagToday: 'Today',
seriesOutput: 'Output'
},
eventReminder: {
title: 'Event Reminder',
modeDevice: 'Device',
modeMold: 'Mold',
check: 'Inspection',
maintain: 'Maintenance',
repair: 'Repair'
},
taskList: {
title: 'Task List',
columns: {
code: 'Code',
name: 'Name',
type: 'Type',
finishStatus: 'Completion',
result: 'Result'
},
finishPending: 'Pending',
finishDone: 'Completed',
finishCanceled: 'Canceled',
resultPass: 'Pass',
resultFail: 'Fail'
},
energyMonitor: {
title: 'Energy Monitor',
selectPlaceholder: 'Please select',
seriesEnergy: 'Energy'
}
} }
}, },
Dashboard8: { Dashboard8: {

@ -99,6 +99,78 @@ export default {
messageRouteMissing: '未配置预览路由', messageRouteMissing: '未配置预览路由',
messageDevicePointRequired: '请至少配置一组设备和点位', messageDevicePointRequired: '请至少配置一组设备和点位',
messageMissingId: '缺少数据编号,无法编辑' messageMissingId: '缺少数据编号,无法编辑'
},
Dashboard1: {
header: {
title: '产线运行看板',
weather: {
cloudyToClear: '多云转晴'
},
weekDays: {
Sunday: '星期日',
Monday: '星期一',
Tuesday: '星期二',
Wednesday: '星期三',
Thursday: '星期四',
Friday: '星期五',
Saturday: '星期六'
}
},
deviceIdPrefix: 'ID:',
defaultDeviceName: '默认设备',
statusOffline: '离线',
statusRunning: '运行',
statusStandby: '待机',
statusFault: '故障',
deviceOverview: {
title: '设备概况',
device: '设备数量',
running: '运行数量',
idle: '待机数量',
alarm: '报警数量',
utilization: '稼动率',
faultRate: '故障率'
},
alarms: {
title: '实时报警信息',
tag: '滚动展示',
levelSevere: '严重',
levelWarn: '警告',
levelInfo: '提示'
},
productionTrend: {
title: '产量趋势',
tagToday: '今日',
seriesOutput: '产量'
},
eventReminder: {
title: '事件提醒',
modeDevice: '设备',
modeMold: '模具',
check: '点检',
maintain: '保养',
repair: '维修'
},
taskList: {
title: '任务列表',
columns: {
code: '编号',
name: '名称',
type: '类型',
finishStatus: '完成状态',
result: '结果'
},
finishPending: '待完成',
finishDone: '已完成',
finishCanceled: '已取消',
resultPass: '通过',
resultFail: '不通过'
},
energyMonitor: {
title: '能耗监测',
selectPlaceholder: '请选择',
seriesEnergy: '能耗'
}
} }
}, },
Dashboard8: { Dashboard8: {

@ -43,7 +43,7 @@
filter="url(#frameGlow)" filter="url(#frameGlow)"
/> />
</svg> </svg>
<div class="title">产线运行看板</div> <div class="title">{{ t('Dashboard1.header.title') }}</div>
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
@ -64,13 +64,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
const router = useRouter() const router = useRouter()
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const timeStr = ref('') const timeStr = ref('')
const dateStr = ref('') const dateStr = ref('')
const weather = ref({ temp: '27°C', desc: 'Cloudy to clear' }) const weather = ref({ temp: '27°C', desc: t('Dashboard1.header.weather.cloudyToClear') })
let timer: number | undefined let timer: number | undefined
const goBack = () => { const goBack = () => {
@ -87,8 +91,9 @@ const updateTime = () => {
const y = d.getFullYear() const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0') const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0') const day = String(d.getDate()).padStart(2, '0')
const weekMap = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] const weekKeys = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
dateStr.value = `${weekMap[d.getDay()]}, ${y}-${m}-${day}` const weekKey = weekKeys[d.getDay()] || 'Sunday'
dateStr.value = `${t(`Dashboard1.header.weekDays.${weekKey}`)}, ${y}-${m}-${day}`
} }
onMounted(() => { onMounted(() => {
@ -96,6 +101,14 @@ onMounted(() => {
timer = window.setInterval(updateTime, 1000) timer = window.setInterval(updateTime, 1000)
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
weather.value.desc = t('Dashboard1.header.weather.cloudyToClear')
updateTime()
}
)
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer) if (timer) clearInterval(timer)
}) })

@ -2,7 +2,7 @@
<div class="card"> <div class="card">
<div class="panel-title"> <div class="panel-title">
<span class="title-dot"></span> <span class="title-dot"></span>
<span>设备概况</span> <span>{{ t('Dashboard1.deviceOverview.title') }}</span>
</div> </div>
<div class="panel-body overview-body"> <div class="panel-body overview-body">
<div v-for="item in overviewItems" :key="item.key" class="gauge-item"> <div v-for="item in overviewItems" :key="item.key" class="gauge-item">
@ -18,10 +18,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { colors } from '../utils' import { colors } from '../utils'
import { DashboardApi } from '@/api/dashboard' import { DashboardApi } from '@/api/dashboard'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
type OverviewItemKey = 'device' | 'running' | 'idle' | 'alarm' | 'utilization' | 'faultRate' type OverviewItemKey = 'device' | 'running' | 'idle' | 'alarm' | 'utilization' | 'faultRate'
@ -35,14 +37,25 @@ interface OverviewItem {
const route = useRoute() const route = useRoute()
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const getLabel = (key: OverviewItemKey) => {
if (key === 'device') return t('Dashboard1.deviceOverview.device')
if (key === 'running') return t('Dashboard1.deviceOverview.running')
if (key === 'idle') return t('Dashboard1.deviceOverview.idle')
if (key === 'alarm') return t('Dashboard1.deviceOverview.alarm')
if (key === 'utilization') return t('Dashboard1.deviceOverview.utilization')
return t('Dashboard1.deviceOverview.faultRate')
}
const overviewItems = ref<OverviewItem[]>([ const overviewItems = ref<OverviewItem[]>([
{ key: 'device', label: '设备数量', value: '0', percent: 0, color: colors.cyan }, { key: 'device', label: getLabel('device'), value: '0', percent: 0, color: colors.cyan },
{ key: 'running', label: '运行数量', value: '0', percent: 0, color: colors.blue }, { key: 'running', label: getLabel('running'), value: '0', percent: 0, color: colors.blue },
{ key: 'idle', label: '待机数量', value: '0', percent: 0, color: colors.warn }, { key: 'idle', label: getLabel('idle'), value: '0', percent: 0, color: colors.warn },
{ key: 'alarm', label: '报警数量', value: '0', percent: 0, color: colors.danger }, { key: 'alarm', label: getLabel('alarm'), value: '0', percent: 0, color: colors.danger },
{ key: 'utilization', label: '稼动率', value: '0%', percent: 0, color: colors.green }, { key: 'utilization', label: getLabel('utilization'), value: '0%', percent: 0, color: colors.green },
{ key: 'faultRate', label: '故障率', value: '0%', percent: 0, color: colors.purple } { key: 'faultRate', label: getLabel('faultRate'), value: '0%', percent: 0, color: colors.purple }
]) ])
const getGaugeStyle = (percent: number, color: string) => { const getGaugeStyle = (percent: number, color: string) => {
@ -55,7 +68,8 @@ const getGaugeStyle = (percent: number, color: string) => {
const formatNumber = (value: number | string | undefined | null) => { const formatNumber = (value: number | string | undefined | null) => {
const n = Number(value ?? 0) const n = Number(value ?? 0)
if (!Number.isFinite(n)) return '0' if (!Number.isFinite(n)) return '0'
return n.toLocaleString('zh-CN') const lang = localeStore.getCurrentLocale.lang
return n.toLocaleString(lang === 'zh-CN' ? 'zh-CN' : 'en-US')
} }
const calcPercent = (part: number, total: number) => { const calcPercent = (part: number, total: number) => {
@ -137,6 +151,14 @@ const loadOverview = async () => {
onMounted(() => { onMounted(() => {
loadOverview() loadOverview()
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
overviewItems.value = overviewItems.value.map((item) => ({ ...item, label: getLabel(item.key) }))
loadOverview()
}
)
</script> </script>
<style scoped> <style scoped>

@ -3,11 +3,11 @@
<div class="panel-title panel-title-between"> <div class="panel-title panel-title-between">
<div class="panel-title-left"> <div class="panel-title-left">
<span class="title-dot"></span> <span class="title-dot"></span>
<span>能耗监测</span> <span>{{ t('Dashboard1.energyMonitor.title') }}</span>
</div> </div>
<div class="tabs"> <div class="tabs">
<el-select <el-select
v-model="selectedEnergyTypeId" placeholder="请选择" style="width: 120px" size="small" v-model="selectedEnergyTypeId" :placeholder="t('Dashboard1.energyMonitor.selectPlaceholder')" style="width: 120px" size="small"
@change="getChartData"> @change="getChartData">
<el-option v-for="item in energyTypes" :key="item.id" :label="item.name" :value="item.id" /> <el-option v-for="item in energyTypes" :key="item.id" :label="item.name" :value="item.id" />
</el-select> </el-select>
@ -20,15 +20,19 @@ v-model="selectedEnergyTypeId" placeholder="请选择" style="width: 120px" size
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue' import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { colors, style } from '../utils' import { colors, style } from '../utils'
import { EnergyTypeApi, EnergyTypeVO } from '@/api/mes/energytype' import { EnergyTypeApi, EnergyTypeVO } from '@/api/mes/energytype'
import { EnergyDeviceApi } from '@/api/mes/energydevice' import { EnergyDeviceApi } from '@/api/mes/energydevice'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
const route = useRoute() const route = useRoute()
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const energyTypes = ref<EnergyTypeVO[]>([]) const energyTypes = ref<EnergyTypeVO[]>([])
const selectedEnergyTypeId = ref<number | undefined>(undefined) const selectedEnergyTypeId = ref<number | undefined>(undefined)
@ -62,6 +66,31 @@ const getChartData = async () => {
} }
} }
const buildOption = (x: string[], y: number[]) => {
return {
backgroundColor: 'transparent',
tooltip: { trigger: 'axis' },
grid: { top: '18%', left: '6%', right: '4%', bottom: '12%', containLabel: true },
xAxis: { type: 'category', data: x, axisLine: style.axisLine, axisLabel: { ...style.axisLabel, fontSize: 10, rotate: 40 } },
yAxis: { type: 'value', axisLine: { show: false }, axisLabel: { ...style.axisLabel, fontSize: 10 }, splitLine: style.splitLine },
series: [
{
name: t('Dashboard1.energyMonitor.seriesEnergy'),
type: 'bar',
barWidth: 12,
itemStyle: {
borderRadius: [6, 6, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors.blue },
{ offset: 1, color: 'rgba(30,144,255,0.10)' }
])
},
data: y
}
]
}
}
const render = (data: any = []) => { const render = (data: any = []) => {
if (!chart) return if (!chart) return
@ -89,27 +118,7 @@ const render = (data: any = []) => {
y = [] y = []
} }
chart.setOption({ chart.setOption(buildOption(x, y))
backgroundColor: 'transparent',
tooltip: { trigger: 'axis' },
grid: { top: '18%', left: '6%', right: '4%', bottom: '12%', containLabel: true },
xAxis: { type: 'category', data: x, axisLine: style.axisLine, axisLabel: { ...style.axisLabel, fontSize: 10, rotate: 40 } },
yAxis: { type: 'value', axisLine: { show: false }, axisLabel: { ...style.axisLabel, fontSize: 10 }, splitLine: style.splitLine },
series: [
{
type: 'bar',
barWidth: 12,
itemStyle: {
borderRadius: [6, 6, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: colors.blue },
{ offset: 1, color: 'rgba(30,144,255,0.10)' }
])
},
data: y
}
]
})
} }
const resize = () => { const resize = () => {
@ -119,13 +128,19 @@ const resize = () => {
onMounted(() => { onMounted(() => {
if (!chartRef.value) return if (!chartRef.value) return
chart = echarts.init(chartRef.value, 'dark', { renderer: 'canvas' }) chart = echarts.init(chartRef.value, 'dark', { renderer: 'canvas' })
// chart.setOption(buildOption([], []))
render([])
// //
getEnergyTypes() getEnergyTypes()
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
getChartData()
}
)
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
chart?.dispose() chart?.dispose()

@ -3,12 +3,12 @@
<div class="panel-title"> <div class="panel-title">
<div class="panel-title-left"> <div class="panel-title-left">
<span class="title-dot"></span> <span class="title-dot"></span>
<span>事件提醒</span> <span>{{ t('Dashboard1.eventReminder.title') }}</span>
</div> </div>
<div class="panel-title-right"> <div class="panel-title-right">
<el-radio-group v-model="mode" size="small"> <el-radio-group v-model="mode" size="small">
<el-radio-button label="device">设备</el-radio-button> <el-radio-button label="device">{{ t('Dashboard1.eventReminder.modeDevice') }}</el-radio-button>
<el-radio-button label="mold">模具</el-radio-button> <el-radio-button label="mold">{{ t('Dashboard1.eventReminder.modeMold') }}</el-radio-button>
</el-radio-group> </el-radio-group>
</div> </div>
</div> </div>
@ -37,6 +37,8 @@ import { useRoute } from 'vue-router'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { DashboardApi, TaskStatisticsData } from '@/api/dashboard' import { DashboardApi, TaskStatisticsData } from '@/api/dashboard'
import { colors } from '../utils' import { colors } from '../utils'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
interface EventItem { interface EventItem {
key: string key: string
@ -48,6 +50,8 @@ interface EventItem {
const route = useRoute() const route = useRoute()
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const chartRef = ref<HTMLElement | null>(null) const chartRef = ref<HTMLElement | null>(null)
let chart: echarts.ECharts | null = null let chart: echarts.ECharts | null = null
@ -108,21 +112,21 @@ const applyTaskStatistics = (data: TaskStatisticsData) => {
eventItems.value = [ eventItems.value = [
{ {
key: 'check', key: 'check',
name: '点检', name: t('Dashboard1.eventReminder.check'),
count: inspection, count: inspection,
percent: toPercent(inspection), percent: toPercent(inspection),
color: colors.cyan color: colors.cyan
}, },
{ {
key: 'maintain', key: 'maintain',
name: '保养', name: t('Dashboard1.eventReminder.maintain'),
count: maintenance, count: maintenance,
percent: toPercent(maintenance), percent: toPercent(maintenance),
color: colors.warn color: colors.warn
}, },
{ {
key: 'repair', key: 'repair',
name: '维修', name: t('Dashboard1.eventReminder.repair'),
count: repair, count: repair,
percent: toPercent(repair), percent: toPercent(repair),
color: colors.danger color: colors.danger
@ -149,6 +153,14 @@ watch(mode, () => {
applyTaskStatistics(rawStats.value) applyTaskStatistics(rawStats.value)
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
if (!rawStats.value) return
applyTaskStatistics(rawStats.value)
}
)
const resize = () => { const resize = () => {
chart?.resize() chart?.resize()
} }

@ -5,9 +5,9 @@
<span class="card-title-icon"> <span class="card-title-icon">
<Icon icon="fa-solid:bell" /> <Icon icon="fa-solid:bell" />
</span> </span>
<span>实时报警信息</span> <span>{{ t('Dashboard1.alarms.title') }}</span>
</div> </div>
<span class="tag">滚动展示</span> <span class="tag">{{ t('Dashboard1.alarms.tag') }}</span>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul ref="listRef" class="alarm-list"> <ul ref="listRef" class="alarm-list">
@ -28,17 +28,35 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { DeviceWarningRecordApi, DeviceWarningRecordVO } from '@/api/iot/deviceWarningRecord' import { DeviceWarningRecordApi, DeviceWarningRecordVO } from '@/api/iot/deviceWarningRecord'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
const route = useRoute() const route = useRoute()
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const alarms = ref<any[]>([]) const alarms = ref<any[]>([])
const isAnimating = ref(false) const isAnimating = ref(false)
let timer: ReturnType<typeof setInterval> | null = null let timer: ReturnType<typeof setInterval> | null = null
const mapAlarmLevel = (alarmLevel: unknown) => {
const raw = String(alarmLevel ?? '').trim()
if (raw === '2' || raw === '严重' || raw.toLowerCase() === 'severe') {
return { type: 'danger', levelText: t('Dashboard1.alarms.levelSevere') }
}
if (raw === '1' || raw === '警告' || raw.toLowerCase() === 'warning' || raw.toLowerCase() === 'warn') {
return { type: 'warn', levelText: t('Dashboard1.alarms.levelWarn') }
}
if (raw === '0' || raw === '提示' || raw.toLowerCase() === 'info' || raw.toLowerCase() === 'notice') {
return { type: 'safe', levelText: t('Dashboard1.alarms.levelInfo') }
}
return { type: 'safe', levelText: raw || t('Dashboard1.alarms.levelInfo') }
}
const getAlarms = async () => { const getAlarms = async () => {
try { try {
const data = (await DeviceWarningRecordApi.getList({ orgId })) || [] const data = (await DeviceWarningRecordApi.getList({ orgId })) || []
@ -49,28 +67,12 @@ const getAlarms = async () => {
timeStr = d.toTimeString().slice(0, 8) timeStr = d.toTimeString().slice(0, 8)
} }
let type = 'safe' const mapped = mapAlarmLevel(item.alarmLevel)
let levelText = item.alarmLevel
if (item.alarmLevel === '2') {
type = 'danger'
levelText = '严重'
} else if (item.alarmLevel === '1') {
type = 'warn'
levelText = '警告'
} else if (item.alarmLevel === '0') {
type = 'safe'
levelText = '提示'
} else {
if (item.alarmLevel === '严重') type = 'danger'
else if (item.alarmLevel === '警告') type = 'warn'
else if (item.alarmLevel === '提示') type = 'safe'
}
return { return {
time: timeStr, time: timeStr,
level: levelText, level: mapped.levelText,
type, type: mapped.type,
msg: `${item.deviceName}-${item.ruleName}` msg: `${item.deviceName}-${item.ruleName}`
} }
}) })
@ -101,6 +103,13 @@ onMounted(() => {
getAlarms() getAlarms()
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
getAlarms()
}
)
onUnmounted(() => { onUnmounted(() => {
if (timer) clearInterval(timer) if (timer) clearInterval(timer)
}) })

@ -2,8 +2,8 @@
<div class="card"> <div class="card">
<div class="panel-title"> <div class="panel-title">
<span class="title-dot"></span> <span class="title-dot"></span>
<span>产量趋势</span> <span>{{ t('Dashboard1.productionTrend.title') }}</span>
<span class="tag">今日</span> <span class="tag">{{ t('Dashboard1.productionTrend.tagToday') }}</span>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div ref="chartRef" class="chart"></div> <div ref="chartRef" class="chart"></div>
@ -12,15 +12,19 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue' import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { colors, style } from '../utils' import { colors, style } from '../utils'
import { DeviceWarningRecordApi } from '@/api/iot/deviceWarningRecord' import { DeviceWarningRecordApi } from '@/api/iot/deviceWarningRecord'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
const route = useRoute() const route = useRoute()
const chartRef = ref<HTMLElement | null>(null) const chartRef = ref<HTMLElement | null>(null)
let chart: echarts.ECharts | null = null let chart: echarts.ECharts | null = null
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const render = async () => { const render = async () => {
if (!chart) return if (!chart) return
@ -69,7 +73,7 @@ const render = async () => {
}, },
series: [ series: [
{ {
name: '产量', name: t('Dashboard1.productionTrend.seriesOutput'),
type: 'bar', type: 'bar',
barWidth: 12, barWidth: 12,
itemStyle: { itemStyle: {
@ -96,6 +100,13 @@ onMounted(() => {
window.addEventListener('resize', resize) window.addEventListener('resize', resize)
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
render()
}
)
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', resize) window.removeEventListener('resize', resize)
chart?.dispose() chart?.dispose()

@ -2,7 +2,7 @@
<div class="card"> <div class="card">
<div class="panel-title"> <div class="panel-title">
<span class="title-dot"></span> <span class="title-dot"></span>
<span>任务列表</span> <span>{{ t('Dashboard1.taskList.title') }}</span>
</div> </div>
<div class="panel-body table-body"> <div class="panel-body table-body">
<el-table <el-table
@ -14,10 +14,10 @@
:border="false" :border="false"
:highlight-current-row="false" :highlight-current-row="false"
> >
<el-table-column prop="code" label="编号" width="100" show-overflow-tooltip /> <el-table-column prop="code" :label="t('Dashboard1.taskList.columns.code')" width="100" show-overflow-tooltip />
<el-table-column prop="name" label="名称" /> <el-table-column prop="name" :label="t('Dashboard1.taskList.columns.name')" />
<el-table-column prop="type" label="类型" /> <el-table-column prop="type" :label="t('Dashboard1.taskList.columns.type')" />
<el-table-column label="完成状态"> <el-table-column :label="t('Dashboard1.taskList.columns.finishStatus')">
<template #default="scope"> <template #default="scope">
<el-tag <el-tag
v-if="scope.row.finishStatusLabel" v-if="scope.row.finishStatusLabel"
@ -32,7 +32,7 @@
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="结果"> <el-table-column :label="t('Dashboard1.taskList.columns.result')">
<template #default="scope"> <template #default="scope">
<div class="status-cell"> <div class="status-cell">
<el-tag <el-tag
@ -56,10 +56,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue' import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import type { ElTable } from 'element-plus' import type { ElTable } from 'element-plus'
import { DashboardApi, DashboardTaskItem } from '@/api/dashboard' import { DashboardApi, DashboardTaskItem } from '@/api/dashboard'
import { useI18n } from '@/hooks/web/useI18n'
import { useLocaleStore } from '@/store/modules/locale'
interface TaskRow { interface TaskRow {
id: string id: string
@ -74,29 +76,32 @@ interface TaskRow {
const route = useRoute() const route = useRoute()
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n('ReportDashboard')
const localeStore = useLocaleStore()
const taskRows = ref<TaskRow[]>([]) const taskRows = ref<TaskRow[]>([])
const rawItems = ref<DashboardTaskItem[]>([])
const tableRef = ref<InstanceType<typeof ElTable> | null>(null) const tableRef = ref<InstanceType<typeof ElTable> | null>(null)
let scrollTimer: number | undefined let scrollTimer: number | undefined
const mapItemToRow = (item: DashboardTaskItem, index: number): TaskRow => { const mapItemToRow = (item: DashboardTaskItem, index: number): TaskRow => {
const resultStatus = Number(item.resultStatus) || 0 const resultStatus = Number(item.resultStatus) || 0
const finishCode = String(item.finishStatus ?? '').trim() const finishCode = String(item.finishStatus ?? '').trim()
let finishStatusLabel = item.finishStatus let finishStatusLabel = String(item.finishStatus ?? '')
let finishStatusType: TaskRow['finishStatusType'] = '' let finishStatusType: TaskRow['finishStatusType'] = ''
if (finishCode === '0') finishStatusLabel = '待完成' if (finishCode === '0') finishStatusLabel = t('Dashboard1.taskList.finishPending')
else if (finishCode === '1') finishStatusLabel = '已完成' else if (finishCode === '1') finishStatusLabel = t('Dashboard1.taskList.finishDone')
else if (finishCode === '2') finishStatusLabel = '已取消' else if (finishCode === '2') finishStatusLabel = t('Dashboard1.taskList.finishCanceled')
if (finishCode === '0') finishStatusType = 'warning' if (finishCode === '0') finishStatusType = 'warning'
else if (finishCode === '1') finishStatusType = 'success' else if (finishCode === '1') finishStatusType = 'success'
else if (finishCode === '2') finishStatusType = 'info' else if (finishCode === '2') finishStatusType = 'info'
let resultStatusLabel = '-' let resultStatusLabel = '-'
let resultStatusType: TaskRow['resultStatusType'] = '' let resultStatusType: TaskRow['resultStatusType'] = ''
if (resultStatus === 1) { if (resultStatus === 1) {
resultStatusLabel = '通过' resultStatusLabel = t('Dashboard1.taskList.resultPass')
resultStatusType = 'success' resultStatusType = 'success'
} else if (resultStatus === 2) { } else if (resultStatus === 2) {
resultStatusLabel = '不通过' resultStatusLabel = t('Dashboard1.taskList.resultFail')
resultStatusType = 'danger' resultStatusType = 'danger'
} }
return { return {
@ -118,12 +123,15 @@ const loadTaskList = async () => {
| DashboardTaskItem[] | DashboardTaskItem[]
| null | null
if (!payload || !Array.isArray(payload)) { if (!payload || !Array.isArray(payload)) {
rawItems.value = []
taskRows.value = [] taskRows.value = []
return return
} }
rawItems.value = payload
taskRows.value = payload.map(mapItemToRow) taskRows.value = payload.map(mapItemToRow)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
rawItems.value = []
taskRows.value = [] taskRows.value = []
} }
} }
@ -161,6 +169,13 @@ onMounted(async () => {
startAutoScroll() startAutoScroll()
}) })
watch(
() => localeStore.getCurrentLocale.lang,
() => {
taskRows.value = rawItems.value.map(mapItemToRow)
}
)
onUnmounted(() => { onUnmounted(() => {
if (scrollTimer) { if (scrollTimer) {
clearInterval(scrollTimer) clearInterval(scrollTimer)

@ -48,7 +48,7 @@
</el-tag> </el-tag>
</div> </div>
<div class="header-right"> <div class="header-right">
<span class="device-id">{{ t('ReportDashboard.Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span> <span class="device-id">{{ t('Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span>
</div> </div>
</div> </div>
<div class="device-body"> <div class="device-body">
@ -80,7 +80,7 @@
</el-tag> </el-tag>
</div> </div>
<div class="header-right"> <div class="header-right">
<span class="device-id">{{ t('ReportDashboard.Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span> <span class="device-id">{{ t('Dashboard1.deviceIdPrefix') }}{{ item.deviceId }}</span>
</div> </div>
</div> </div>
<div class="device-body"> <div class="device-body">
@ -128,7 +128,7 @@ import ProductionTrend from './components/ProductionTrend.vue'
const route = useRoute() const route = useRoute()
const goviewId = route.query.goviewId as string const goviewId = route.query.goviewId as string
const orgId = route.query.orgId const orgId = route.query.orgId
const { t } = useI18n() const { t } = useI18n('ReportDashboard')
interface DeviceAttribute { interface DeviceAttribute {
attributeName: string attributeName: string
@ -165,7 +165,7 @@ const loadDeviceAttributes = async () => {
const cards: DeviceCardData[] = list.map((d: any) => { const cards: DeviceCardData[] = list.map((d: any) => {
return { return {
deviceName: d.deviceName || t('ReportDashboard.Dashboard1.defaultDeviceName'), deviceName: d.deviceName || t('Dashboard1.defaultDeviceName'),
deviceId: d.deviceId, deviceId: d.deviceId,
operatingStatus: d.operatingStatus, operatingStatus: d.operatingStatus,
attributes: (d.attributes || []).map((attr: any) => ({ attributes: (d.attributes || []).map((attr: any) => ({
@ -194,8 +194,14 @@ const getDeviceStatusType = (status?: string) => {
} }
const getDeviceStatusText = (status?: string) => { const getDeviceStatusText = (status?: string) => {
if (!status) return t('ReportDashboard.Dashboard1.statusOffline') if (!status) return t('Dashboard1.statusOffline')
return status const raw = String(status).trim()
const s = raw.toLowerCase()
if (s.includes('故障') || s === 'fault') return t('Dashboard1.statusFault')
if (s.includes('待机') || s === 'standby') return t('Dashboard1.statusStandby')
if (s.includes('运行') || s === 'run' || s === 'running') return t('Dashboard1.statusRunning')
if (s.includes('离线') || s === 'offline') return t('Dashboard1.statusOffline')
return raw
} }
onMounted(() => { onMounted(() => {

Loading…
Cancel
Save