chore: update project files
This commit is contained in:
Binary file not shown.
@@ -35,8 +35,16 @@
|
||||
<section class="panel metric-panel late-panel">
|
||||
<div class="panel-title">未及时开工</div>
|
||||
<div class="metric-content">
|
||||
<img :src="icons.calendar" alt="" />
|
||||
<strong class="orange">{{ summary.lateStart }}</strong>
|
||||
<!-- <img :src="icons.calendar" alt="" />
|
||||
<strong class="orange">{{ summary.lateStart }}</strong> -->
|
||||
<div class="finish-stat2">
|
||||
<span>机加</span>
|
||||
<strong class="orange">{{ summary.lateStart }}</strong>
|
||||
</div>
|
||||
<div class="finish-stat2">
|
||||
<span>外协</span>
|
||||
<strong class="red">{{ summary.outlateStart}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -51,7 +59,6 @@
|
||||
<section class="panel finished-panel">
|
||||
<div class="panel-title">已完工作务 / 合格率</div>
|
||||
<div class="finish-content">
|
||||
<!-- <img :src="icons.clipboard" alt="" /> -->
|
||||
<div class="finish-stat">
|
||||
<span>已完工</span>
|
||||
<strong>{{ summary.finishedTask }}</strong>
|
||||
@@ -77,24 +84,12 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- <section class="panel oee-chart-panel">
|
||||
<div class="panel-title">设备 OEE TOP10</div>
|
||||
<div ref="oeeChart" class="bar-chart"></div>
|
||||
</section> -->
|
||||
<section class="panel late-detail-panel">
|
||||
<div class="panel-title">未及时开工明细</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="lateStartBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
<section class="panel defect-detail-panel">
|
||||
<div class="panel-title">不良品明细</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="defectBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section class="panel assignee-summary-panel">
|
||||
<div class="panel-title">未及时开工汇总(工位)</div>
|
||||
@@ -105,6 +100,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel out-late-detail-panel">
|
||||
<div class="panel-title">外协未及时开工明细</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="outlateStartBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
@@ -112,9 +114,13 @@
|
||||
<script setup>
|
||||
import * as echarts from 'echarts'
|
||||
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
|
||||
const tableData = ref([])
|
||||
const mergedTableData = ref([])
|
||||
const mergedDataMap = ref(new Map())
|
||||
const CreateData = inject('CreateData')
|
||||
const ExecDatabase = inject('ExecDatabase')
|
||||
|
||||
defineOptions({
|
||||
name: 'MachiningOperationDashboard'
|
||||
})
|
||||
@@ -160,11 +166,13 @@ let resizeHandler = null
|
||||
const summary = reactive({
|
||||
equipmentTotal: 18,
|
||||
running: 10,
|
||||
running2: 0,
|
||||
standby: 4,
|
||||
alarm: 2,
|
||||
shutdown: 2,
|
||||
planRate: 92.5,
|
||||
lateStart: 12,
|
||||
outlateStart: 0,
|
||||
defectTotal: 18,
|
||||
finishedTask: 156,
|
||||
passRate: 98.6
|
||||
@@ -178,6 +186,7 @@ const runStatusCards = computed(() => [
|
||||
{ label: '报警', value: summary.alarm, icon: icons.alarm, className: 'red', valueClass: 'red-text' },
|
||||
{ label: '关机', value: summary.shutdown, icon: icons.power, className: 'gray', valueClass: 'gray-text' }
|
||||
])
|
||||
|
||||
const equipmentRows = ref([
|
||||
{ name: '数 1', status: '运行', auto: 'power', auxiliary: 'run', utilization: 86.1, performance: 94.1, passRate: 98.5, oee: 79.8 },
|
||||
{ name: '数 3', status: '运行', auto: 'run', auxiliary: 'run', utilization: 87.2, performance: 94.7, passRate: 98.8, oee: 81.1 },
|
||||
@@ -232,18 +241,9 @@ const defectRows = ref([
|
||||
{ productionOrder: 'MO260422-014', salesOrder: 'SO260408-026', materialName: '箱体', materialCode: 'MP-BOX-001', processName: '粗铣', defectQty: 1, assignee: '数 1' }
|
||||
])
|
||||
|
||||
let lateStartRows = ref([
|
||||
{ productionOrder: 'MO260430-001', salesOrder: 'SO260415-021', materialName: '箱体壳体', materialCode: 'MP-BOX-001', processName: '粗铣', assignQty: 20, prevPassQty: 0, urgentQty: 10, assignee: '数 5' },
|
||||
{ productionOrder: 'MO260430-002', salesOrder: 'SO260416-033', materialName: '轴套', materialCode: 'MP-SHAFT-002', processName: '钻孔', assignQty: 15, prevPassQty: 0, urgentQty: 5, assignee: '普 2' },
|
||||
{ productionOrder: 'MO260429-015', salesOrder: 'SO260414-012', materialName: '端盖', materialCode: 'MP-CAP-003', processName: '攻丝', assignQty: 30, prevPassQty: 0, urgentQty: 0, assignee: '普 1' },
|
||||
{ productionOrder: 'MO260429-017', salesOrder: 'SO260414-018', materialName: '支架', materialCode: 'MP-BRKT-004', processName: '平面铣', assignQty: 12, prevPassQty: 0, urgentQty: 6, assignee: '加 2' },
|
||||
{ productionOrder: 'MO260429-020', salesOrder: 'SO260415-007', materialName: '导轨座', materialCode: 'MP-RAIL-005', processName: '铣槽', assignQty: 8, prevPassQty: 0, urgentQty: 3, assignee: '数 3' },
|
||||
{ productionOrder: 'MO260429-021', salesOrder: 'SO260415-009', materialName: '盖板', materialCode: 'MP-COVER-006', processName: '钻孔', assignQty: 25, prevPassQty: 0, urgentQty: 0, assignee: '数 1' },
|
||||
{ productionOrder: 'MO260428-022', salesOrder: 'SO260414-030', materialName: '法兰盘', materialCode: 'MP-FLANGE-003', processName: '精铣', assignQty: 18, prevPassQty: 0, urgentQty: 4, assignee: '加 1' },
|
||||
{ productionOrder: 'MO260428-025', salesOrder: 'SO260414-035', materialName: '齿轮轴', materialCode: 'MP-GEAR-002', processName: '滚齿', assignQty: 10, prevPassQty: 0, urgentQty: 2, assignee: '数 2' },
|
||||
{ productionOrder: 'MO260428-027', salesOrder: 'SO260413-018', materialName: '轴承座', materialCode: 'MP-HOUS-001', processName: '精铣', assignQty: 16, prevPassQty: 0, urgentQty: 4, assignee: '数 6' },
|
||||
{ productionOrder: 'MO260427-030', salesOrder: 'SO260413-025', materialName: '支撑座', materialCode: 'MP-BRKT-006', processName: '钻孔', assignQty: 22, prevPassQty: 0, urgentQty: 0, assignee: '普 4' }
|
||||
])
|
||||
const lateStartRows = ref([])
|
||||
|
||||
const outlateStartRows = ref([]) // 存储合并过滤后的数据
|
||||
|
||||
const completedRows = ref([
|
||||
{ productionOrder: 'MO260428-003', materialName: '箱体壳体', materialCode: 'MP-BOX-001', processName: '精铣', passRate: 99.1 },
|
||||
@@ -293,7 +293,6 @@ const equipmentBoardConfig = computed(() => ({
|
||||
const defectBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 7,
|
||||
// columnWidth: [124, 124, 70, 128, 62, 54, 54],
|
||||
header: ['生产订单', '销售订单', '物料名称', '物品编码', '工序名称', '不良数量', '指派对象'],
|
||||
data: defectRows.value.map(row => [
|
||||
row.productionOrder,
|
||||
@@ -309,7 +308,6 @@ const defectBoardConfig = computed(() => ({
|
||||
const lateStartBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 7,
|
||||
// columnWidth: [108, 108, 82, 102, 62, 68, 72, 68, 52],
|
||||
header: ['生产订单', '销售订单', '物料名称', '物料编码', '工序名称', '分配数量', '上序合格数', '加急数量', '指派对象'],
|
||||
data: lateStartRows.value.map(row => [
|
||||
row.productionOrder,
|
||||
@@ -324,6 +322,23 @@ const lateStartBoardConfig = computed(() => ({
|
||||
])
|
||||
}))
|
||||
|
||||
const outlateStartBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 7,
|
||||
header: ['生产订单', '销售订单', '物料名称', '物料编码', '工序名称', '分配数量', '上序合格数', '加急数量', '指派对象'],
|
||||
data: outlateStartRows.value.map(row => [
|
||||
row.productionOrder,
|
||||
row.salesOrder,
|
||||
row.materialName,
|
||||
row.materialCode,
|
||||
row.processName,
|
||||
row.assignQty,
|
||||
row.prevPassQty,
|
||||
row.urgentQty,
|
||||
row.assignee
|
||||
])
|
||||
}))
|
||||
|
||||
const completedBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 8,
|
||||
@@ -350,55 +365,179 @@ const lateStartGroupedByAssignee = computed(() => {
|
||||
return Object.values(groupMap)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
refreshClock()
|
||||
clockTimer = window.setInterval(refreshClock, 1000)
|
||||
setScale()
|
||||
resizeHandler = () => {
|
||||
setScale()
|
||||
resizeCharts()
|
||||
}
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
nextTick(() => {
|
||||
initCharts()
|
||||
})
|
||||
searchDashboardData()
|
||||
})
|
||||
// ==================== 数据合并相关函数(从 Vue 2 转换而来) ====================
|
||||
|
||||
onUnmounted(() => {
|
||||
if (clockTimer) {
|
||||
window.clearInterval(clockTimer)
|
||||
clockTimer = null
|
||||
// 检查计划开始时间是否有效(最小计划开始时间小于今天)
|
||||
const checkGroupPlanStartValid = (group) => {
|
||||
const today = new Date()
|
||||
today.setHours(0, 0, 0, 0)
|
||||
|
||||
const minPlanStart = group.reduce((min, item) => {
|
||||
if (!item.计划开始时间) return min
|
||||
const planDate = new Date(item.计划开始时间)
|
||||
planDate.setHours(0, 0, 0, 0)
|
||||
return planDate < min ? planDate : min
|
||||
}, new Date('2099-12-31'))
|
||||
|
||||
return minPlanStart < today
|
||||
}
|
||||
|
||||
// 检查组内所有数据的收料数量是否都为0
|
||||
const checkGroupAllZero = (group) => {
|
||||
return group.every(item => {
|
||||
const 收料数量 = Number(item.收料数量) || 0
|
||||
return 收料数量 === 0
|
||||
})
|
||||
}
|
||||
|
||||
// 根据执行状态判断是否应该包含
|
||||
const shouldIncludeByExecutionStatus = (mergedItem) => {
|
||||
// 执行状态为1(可执行)的包含
|
||||
return mergedItem.执行状态 === 1
|
||||
}
|
||||
|
||||
// 合并组数据
|
||||
const mergeGroup = (group) => {
|
||||
if (group.length === 1) {
|
||||
const item = { ...group[0] }
|
||||
item.uniqueKey = `${item.订单号}_${item.订单行号}_${item.TaskAID}`
|
||||
item.TaskAID = String(item.TaskAID)
|
||||
|
||||
const 上序合格数 = item.上序合格数 || 0
|
||||
const 订单行号 = item.订单行号
|
||||
item.执行状态 = (订单行号 === 1 || 上序合格数 > 0) ? 1 : 2
|
||||
|
||||
return item
|
||||
}
|
||||
if (resizeHandler) {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
resizeHandler = null
|
||||
|
||||
const mergedItem = { ...group[0] }
|
||||
|
||||
// 生成唯一标识key
|
||||
mergedItem.uniqueKey = group.map(item => `${item.订单号}_${item.订单行号}_${item.TaskAID}`).join('|')
|
||||
|
||||
// 拼接工序名称(逗号间隔)
|
||||
const processNames = group.map(item => item.工序名称)
|
||||
mergedItem.工序名称 = processNames.join(',')
|
||||
|
||||
// 拼接TaskAID(逗号间隔)
|
||||
const taskAIDs = [...new Set(group.map(item => String(item.TaskAID)))]
|
||||
mergedItem.TaskAID = taskAIDs.join(',')
|
||||
|
||||
// 取计划开始时间的最小值
|
||||
const startTimes = group.map(item => new Date(item.计划开始时间))
|
||||
mergedItem.计划开始时间 = new Date(Math.min(...startTimes)).toISOString().slice(0, 19).replace('T', ' ')
|
||||
|
||||
// 取计划完成时间的最大值
|
||||
const endTimes = group.map(item => new Date(item.计划完成时间))
|
||||
mergedItem.计划完成时间 = new Date(Math.max(...endTimes)).toISOString().slice(0, 19).replace('T', ' ')
|
||||
|
||||
// 取最大值
|
||||
const wcnum = group.map(item => item.完成数量)
|
||||
mergedItem.完成数量 = Math.max(...wcnum)
|
||||
|
||||
const printnum = group.map(item => item.外协打印次数)
|
||||
mergedItem.外协打印次数 = Math.max(...printnum)
|
||||
|
||||
const slnum = group.map(item => item.收料数量)
|
||||
mergedItem.收料数量 = Math.max(...slnum)
|
||||
|
||||
// 计算上序合格数(取组内最大值)
|
||||
const shxnum = group.map(item => item.上序合格数 || 0)
|
||||
mergedItem.上序合格数 = Math.max(...shxnum)
|
||||
|
||||
// 计算执行状态:只要一组内包含订单行号=1 或者包含上序合格数>0,都属于可执行
|
||||
const hasFirstProcess = group.some(item => item.订单行号 === 1)
|
||||
const hasPreviousQualified = group.some(item => (item.上序合格数 || 0) > 0)
|
||||
mergedItem.执行状态 = (hasFirstProcess || hasPreviousQualified) ? 1 : 2
|
||||
|
||||
// 存储原始组数据引用
|
||||
mergedItem.originalGroup = group
|
||||
|
||||
return mergedItem
|
||||
}
|
||||
|
||||
// 合并表格数据并返回合并后的结果
|
||||
const mergeTableData = (rawData) => {
|
||||
if (!rawData || rawData.length === 0) {
|
||||
return []
|
||||
}
|
||||
Object.keys(charts).forEach(key => {
|
||||
if (charts[key]) {
|
||||
charts[key].dispose()
|
||||
charts[key] = null
|
||||
|
||||
const groupedByOrder = {}
|
||||
rawData.forEach(item => {
|
||||
const groupKey = `${item.订单号}_${item.拆分内码}`
|
||||
|
||||
if (!groupedByOrder[groupKey]) {
|
||||
groupedByOrder[groupKey] = []
|
||||
}
|
||||
groupedByOrder[groupKey].push(item)
|
||||
})
|
||||
|
||||
const mergedData = []
|
||||
|
||||
Object.keys(groupedByOrder).forEach(orderNo => {
|
||||
const orderItems = groupedByOrder[orderNo]
|
||||
orderItems.sort((a, b) => a.订单行号 - b.订单行号)
|
||||
|
||||
let currentGroup = [orderItems[0]]
|
||||
|
||||
for (let i = 1; i < orderItems.length; i++) {
|
||||
const currentItem = orderItems[i]
|
||||
const lastItem = orderItems[i - 1]
|
||||
|
||||
if (currentItem.订单行号 === lastItem.订单行号 + 1 &&
|
||||
currentItem.外协分组 === lastItem.外协分组 &&
|
||||
currentItem.拆分内码 === lastItem.拆分内码) {
|
||||
currentGroup.push(currentItem)
|
||||
} else {
|
||||
// 检查组内最小计划开始时间是否小于今天
|
||||
if (checkGroupPlanStartValid(currentGroup)) {
|
||||
if (checkGroupAllZero(currentGroup)) {
|
||||
const mergedItem = mergeGroup(currentGroup)
|
||||
if (shouldIncludeByExecutionStatus(mergedItem)) {
|
||||
mergedData.push(mergedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
currentGroup = [currentItem]
|
||||
}
|
||||
}
|
||||
|
||||
// 处理最后一组
|
||||
if (currentGroup.length > 0) {
|
||||
if (checkGroupPlanStartValid(currentGroup)) {
|
||||
if (checkGroupAllZero(currentGroup)) {
|
||||
const mergedItem = mergeGroup(currentGroup)
|
||||
if (shouldIncludeByExecutionStatus(mergedItem)) {
|
||||
mergedData.push(mergedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return mergedData
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================== 数据查询相关函数 ====================
|
||||
|
||||
const queryDashboardData = (procedureName, applyData) => {
|
||||
let data
|
||||
if (typeof CreateData !== 'function' || typeof ExecDatabase !== 'function') {
|
||||
initCharts()
|
||||
return
|
||||
}
|
||||
data = CreateData('11', procedureName, [])
|
||||
const data = CreateData('11', procedureName, [])
|
||||
ExecDatabase(data).then(response => {
|
||||
const rows = getResponseRows(response)
|
||||
if (rows.length > 0) {
|
||||
tableData.value = rows
|
||||
applyData(rows)
|
||||
nextTick(() => {
|
||||
initCharts()
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('查询数据失败:', procedureName, error)
|
||||
})
|
||||
}
|
||||
|
||||
const getResponseRows = response => {
|
||||
if (response && Array.isArray(response.data)) {
|
||||
return response.data
|
||||
@@ -408,108 +547,6 @@ const getResponseRows = response => {
|
||||
}
|
||||
return []
|
||||
}
|
||||
const searchDashboardData = () => {
|
||||
searchDeviceStatusData()
|
||||
searchNotStartedData()
|
||||
searchTodayDoneSummaryData()
|
||||
searchTodayDoneDetailData()
|
||||
searchunqualifiedData()
|
||||
searchPlanExecuteData()
|
||||
searchdeviceData()
|
||||
}
|
||||
const searchdeviceData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_设备任务查询', applydeviceData)
|
||||
}
|
||||
const searchunqualifiedData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_不良品查询', applyunqualifiedData)
|
||||
}
|
||||
const searchTodayDoneSummaryData = () => {
|
||||
queryDashboardData('质量任务看板_当天已完成汇总', applyTodayDoneSummaryData)
|
||||
}
|
||||
const searchTodayDoneDetailData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_当天已完成明细', applyTodayDoneDetailData)
|
||||
}
|
||||
const searchDeviceStatusData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_设备运行状态查询', applyDashboardData)
|
||||
}
|
||||
const searchNotStartedData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_未及时开工查询', applyNotStartData)
|
||||
}
|
||||
const searchPlanExecuteData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_计划执行率', applyPlanExecuteData)
|
||||
}
|
||||
|
||||
const applyDashboardData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
console.log(first)
|
||||
// summary.equipmentTotal = first.总数
|
||||
summary.equipmentTotal = 18
|
||||
// summary.running = first.运行数量
|
||||
summary.running = first.运行数量
|
||||
summary.standby = first.待机数量
|
||||
summary.alarm = first.报警数量
|
||||
summary.shutdown = first.关机数量
|
||||
|
||||
}
|
||||
const applydeviceData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
console.log(first)
|
||||
summary.running2 = first.总记录数
|
||||
|
||||
|
||||
}
|
||||
const applyNotStartData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.lateStart = first.总记录数
|
||||
// 假设 rows 是从存储过程返回的未及时开工数据
|
||||
// 如果返回的数据字段名与表格需要的一致,直接映射即可
|
||||
lateStartRows.value = rows.map(row => ({
|
||||
productionOrder: row.订单号,
|
||||
salesOrder: row.合同号,
|
||||
materialName: row.零件名称,
|
||||
materialCode: row.零件编码,
|
||||
processName: row.工序名称,
|
||||
assignQty: row.分配数 || 0,
|
||||
prevPassQty: row.上序合格数 || row.上序合格数量 || 0,
|
||||
urgentQty: row.加急数量 || row.紧急数量 || 0,
|
||||
assignee: row.指派对象
|
||||
}))
|
||||
}
|
||||
const applyTodayDoneSummaryData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.finishedTask = first.totalCount
|
||||
summary.passRate = ((first.passCount / (first.passCount + first.failCount)) * 100).toFixed(2)
|
||||
|
||||
}
|
||||
const applyTodayDoneDetailData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
|
||||
completedRows.value = rows.map(row => ({
|
||||
productionOrder: row.orderNo,
|
||||
materialName: row.materialName,
|
||||
materialCode: row.materialCode,
|
||||
processName: row.processName,
|
||||
passRate: ((row.passQty / (row.passQty + row.failQty)) * 100).toFixed(2)
|
||||
}))
|
||||
}
|
||||
const applyunqualifiedData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.defectTotal = first.总记录数
|
||||
defectRows.value = rows.map(row => ({
|
||||
productionOrder: row.计划号,
|
||||
salesOrder: row.内部合同号,
|
||||
materialName: row.零件名称,
|
||||
materialCode: row.零件编码,
|
||||
processName: row.工序名称,
|
||||
defectQty: row.不合格数,
|
||||
assignee:row.指派对象 || ''
|
||||
}))
|
||||
}
|
||||
const applyPlanExecuteData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.planRate = first.计划执行率_百分数
|
||||
|
||||
}
|
||||
|
||||
const getFirstRow = rows => {
|
||||
if (Array.isArray(rows) && rows.length > 0) {
|
||||
@@ -517,6 +554,217 @@ const getFirstRow = rows => {
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
const searchDashboardData = () => {
|
||||
searchDeviceStatusData()
|
||||
searchNotStartedData()
|
||||
searchTodayDoneSummaryData()
|
||||
searchTodayDoneDetailData()
|
||||
searchPlanExecuteData()
|
||||
searchdeviceData()
|
||||
searchoutNotStartedData()
|
||||
}
|
||||
|
||||
const searchdeviceData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_设备任务查询', applydeviceData)
|
||||
}
|
||||
|
||||
const searchTodayDoneSummaryData = () => {
|
||||
queryDashboardData('质量任务看板_当天已完成汇总', applyTodayDoneSummaryData)
|
||||
}
|
||||
|
||||
const searchTodayDoneDetailData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_当天已完成明细', applyTodayDoneDetailData)
|
||||
}
|
||||
|
||||
const searchDeviceStatusData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_设备运行状态查询', applyDashboardData)
|
||||
}
|
||||
|
||||
const searchNotStartedData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_未及时开工查询', applyNotStartData)
|
||||
}
|
||||
|
||||
const searchoutNotStartedData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_外协未及时开工查询', outapplyNotStartData)
|
||||
}
|
||||
|
||||
const searchPlanExecuteData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_计划执行率', applyPlanExecuteData)
|
||||
}
|
||||
|
||||
const applyDashboardData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.equipmentTotal = 18
|
||||
summary.running = first.运行数量 || 0
|
||||
summary.standby = first.待机数量 || 0
|
||||
summary.alarm = first.报警数量 || 0
|
||||
summary.shutdown = first.关机数量 || 0
|
||||
}
|
||||
|
||||
const applydeviceData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.running2 = first.总记录数 || 0
|
||||
}
|
||||
|
||||
const applyNotStartData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.lateStart = first.总记录数 || 0
|
||||
lateStartRows.value = rows.map(row => ({
|
||||
productionOrder: row.订单号,
|
||||
salesOrder: row.合同号,
|
||||
materialName: row.零件名称,
|
||||
materialCode: row.零件编码,
|
||||
processName: row.工序名称,
|
||||
assignQty: row.分配数 || 0,
|
||||
prevPassQty: row.上序合格数 || row.上序合格数量 || 0,
|
||||
urgentQty: row.加急数量 || row.紧急数量 || 0,
|
||||
assignee: row.指派对象
|
||||
}))
|
||||
}
|
||||
|
||||
// 外协未及时开工数据处理 - 应用合并和过滤逻辑
|
||||
const outapplyNotStartData = rows => {
|
||||
// 1. 先处理原始数据,统一字段名
|
||||
const processedRows = rows.map(row => ({
|
||||
...row,
|
||||
订单号: row.订单号,
|
||||
合同号: row.合同号,
|
||||
零件名称: row.零件名称,
|
||||
零件编码: row.零件编码,
|
||||
工序名称: row.工序名称,
|
||||
分配数: row.分配数 || 0,
|
||||
上序合格数: row.上序合格数 || row.上序合格数量 || 0,
|
||||
加急数量: row.加急数量 || row.紧急数量 || 0,
|
||||
指派对象: row.指派对象,
|
||||
拆分内码: row.拆分内码,
|
||||
外协分组: row.外协分组,
|
||||
订单行号: row.订单行号,
|
||||
计划开始时间: row.计划开始时间,
|
||||
计划完成时间: row.计划完成时间,
|
||||
完成数量: row.完成数量 || 0,
|
||||
外协打印次数: row.外协打印次数 || 0,
|
||||
收料数量: row.收料数量 || 0,
|
||||
TaskAID: row.TaskAID
|
||||
}))
|
||||
|
||||
// 2. 调用合并过滤函数,获取所有合并后的数据(不过滤执行状态)
|
||||
const allMergedData = mergeAllTableData(processedRows)
|
||||
|
||||
// 3. 总数 = 所有合并后的数据条数(包括执行状态为1和2的)
|
||||
summary.outlateStart = allMergedData.length
|
||||
|
||||
// 4. 明细数据只显示执行状态 === 1 的数据
|
||||
const filteredMergedData = allMergedData.filter(item => item.执行状态 === 1)
|
||||
|
||||
// 5. 转换为表格显示格式并赋值给 outlateStartRows
|
||||
outlateStartRows.value = convertMergedDataToRows(filteredMergedData)
|
||||
|
||||
console.log('原始数据条数:', rows.length)
|
||||
console.log('合并后总数(包括状态1和2):', allMergedData.length)
|
||||
console.log('明细显示条数(执行状态=1):', filteredMergedData.length)
|
||||
}
|
||||
|
||||
// 合并表格数据并返回所有合并后的结果(不过滤执行状态)
|
||||
const mergeAllTableData = (rawData) => {
|
||||
if (!rawData || rawData.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const groupedByOrder = {}
|
||||
rawData.forEach(item => {
|
||||
const groupKey = `${item.订单号}_${item.拆分内码}`
|
||||
|
||||
if (!groupedByOrder[groupKey]) {
|
||||
groupedByOrder[groupKey] = []
|
||||
}
|
||||
groupedByOrder[groupKey].push(item)
|
||||
})
|
||||
|
||||
const mergedData = []
|
||||
|
||||
Object.keys(groupedByOrder).forEach(orderNo => {
|
||||
const orderItems = groupedByOrder[orderNo]
|
||||
orderItems.sort((a, b) => a.订单行号 - b.订单行号)
|
||||
|
||||
let currentGroup = [orderItems[0]]
|
||||
|
||||
for (let i = 1; i < orderItems.length; i++) {
|
||||
const currentItem = orderItems[i]
|
||||
const lastItem = orderItems[i - 1]
|
||||
|
||||
if (currentItem.订单行号 === lastItem.订单行号 + 1 &&
|
||||
currentItem.外协分组 === lastItem.外协分组 &&
|
||||
currentItem.拆分内码 === lastItem.拆分内码) {
|
||||
currentGroup.push(currentItem)
|
||||
} else {
|
||||
// 检查组内最小计划开始时间是否小于今天
|
||||
if (checkGroupPlanStartValid(currentGroup)) {
|
||||
if (checkGroupAllZero(currentGroup)) {
|
||||
const mergedItem = mergeGroup(currentGroup)
|
||||
// 不再过滤执行状态,保存所有数据
|
||||
mergedData.push(mergedItem)
|
||||
}
|
||||
}
|
||||
currentGroup = [currentItem]
|
||||
}
|
||||
}
|
||||
|
||||
// 处理最后一组
|
||||
if (currentGroup.length > 0) {
|
||||
if (checkGroupPlanStartValid(currentGroup)) {
|
||||
if (checkGroupAllZero(currentGroup)) {
|
||||
const mergedItem = mergeGroup(currentGroup)
|
||||
// 不再过滤执行状态,保存所有数据
|
||||
mergedData.push(mergedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return mergedData
|
||||
}
|
||||
|
||||
// 将合并后的数据转换为表格显示格式
|
||||
const convertMergedDataToRows = (mergedData) => {
|
||||
return mergedData.map(item => ({
|
||||
productionOrder: item.订单号 || '',
|
||||
salesOrder: item.合同号 || '',
|
||||
materialName: item.零件名称 || '',
|
||||
materialCode: item.零件编码 || '',
|
||||
processName: item.工序名称 || '',
|
||||
assignQty: item.分配数 || 0,
|
||||
prevPassQty: item.上序合格数 || 0,
|
||||
urgentQty: item.加急数量 || item.紧急数量 || 0,
|
||||
assignee: item.指派对象 || ''
|
||||
}))
|
||||
}
|
||||
|
||||
const applyTodayDoneSummaryData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.finishedTask = first.totalCount || 0
|
||||
const passCount = first.passCount || 0
|
||||
const failCount = first.failCount || 0
|
||||
summary.passRate = ((passCount / (passCount + failCount)) * 100).toFixed(2)
|
||||
}
|
||||
|
||||
const applyTodayDoneDetailData = rows => {
|
||||
completedRows.value = rows.map(row => ({
|
||||
productionOrder: row.orderNo,
|
||||
materialName: row.materialName,
|
||||
materialCode: row.materialCode,
|
||||
processName: row.processName,
|
||||
passRate: ((row.passQty / (row.passQty + row.failQty)) * 100).toFixed(2)
|
||||
}))
|
||||
}
|
||||
|
||||
const applyPlanExecuteData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summary.planRate = first.计划执行率_百分数 || 0
|
||||
}
|
||||
|
||||
// ==================== 图表相关函数 ====================
|
||||
|
||||
const initCharts = () => {
|
||||
if (planRateChart.value && !charts.planRate) {
|
||||
charts.planRate = echarts.init(planRateChart.value)
|
||||
@@ -636,6 +884,8 @@ const renderBarChart = (chart, rows) => {
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 辅助函数 ====================
|
||||
|
||||
const refreshClock = () => {
|
||||
const now = new Date()
|
||||
const pad = value => String(value).padStart(2, '0')
|
||||
@@ -659,18 +909,39 @@ const resizeCharts = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const stateClass = status => {
|
||||
if (status === '运行') return 'state-run'
|
||||
if (status === '待机') return 'state-standby'
|
||||
if (status === '报警') return 'state-alarm'
|
||||
return 'state-off'
|
||||
}
|
||||
// ==================== 生命周期 ====================
|
||||
|
||||
const pointClass = value => {
|
||||
if (value === 'run') return 'point point-run'
|
||||
if (value === 'power') return 'point point-power'
|
||||
return 'point point-none'
|
||||
}
|
||||
onMounted(() => {
|
||||
refreshClock()
|
||||
clockTimer = window.setInterval(refreshClock, 1000)
|
||||
setScale()
|
||||
resizeHandler = () => {
|
||||
setScale()
|
||||
resizeCharts()
|
||||
}
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
nextTick(() => {
|
||||
initCharts()
|
||||
})
|
||||
searchDashboardData()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (clockTimer) {
|
||||
window.clearInterval(clockTimer)
|
||||
clockTimer = null
|
||||
}
|
||||
if (resizeHandler) {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
resizeHandler = null
|
||||
}
|
||||
Object.keys(charts).forEach(key => {
|
||||
if (charts[key]) {
|
||||
charts[key].dispose()
|
||||
charts[key] = null
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -1005,18 +1276,12 @@ const pointClass = value => {
|
||||
.finish-content {
|
||||
height: calc(100% - 38px);
|
||||
display: grid;
|
||||
/* grid-template-columns: 82px 1fr 1fr; */
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 7px 14px 15px;
|
||||
}
|
||||
|
||||
.finish-content img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.finish-stat {
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
@@ -1052,51 +1317,24 @@ const pointClass = value => {
|
||||
height: 374px;
|
||||
}
|
||||
|
||||
.oee-chart-panel {
|
||||
left: 746px;
|
||||
top: 196px;
|
||||
width: 520px;
|
||||
height: 374px;
|
||||
}
|
||||
|
||||
/* .defect-detail-panel {
|
||||
left: 1278px;
|
||||
top: 196px;
|
||||
width: 628px;
|
||||
height: 374px;
|
||||
} */
|
||||
|
||||
.late-detail-panel {
|
||||
left: 780px;
|
||||
top: 196px;
|
||||
width: 1126px;
|
||||
height: 374px;
|
||||
}
|
||||
.defect-detail-panel {
|
||||
left: 14px;
|
||||
top: 584px;
|
||||
width: 720px;
|
||||
height: 356px;
|
||||
}
|
||||
|
||||
.plan-chart-panel {
|
||||
left: 746px;
|
||||
.out-late-detail-panel {
|
||||
left: 780px;
|
||||
top: 584px;
|
||||
width: 520px;
|
||||
height: 356px;
|
||||
}
|
||||
|
||||
.complete-detail-panel {
|
||||
left: 1278px;
|
||||
top: 584px;
|
||||
width: 628px;
|
||||
width: 1126px;
|
||||
height: 356px;
|
||||
}
|
||||
|
||||
.assignee-summary-panel {
|
||||
left: 746px;
|
||||
left: 14px;
|
||||
top: 584px;
|
||||
width: 1160px;
|
||||
width: 756px;
|
||||
height: 356px;
|
||||
}
|
||||
|
||||
@@ -1253,20 +1491,6 @@ const pointClass = value => {
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
.defect-detail-panel .datav-table :deep(.header-item:nth-child(6)),
|
||||
.defect-detail-panel .datav-table :deep(.ceil:nth-child(6)),
|
||||
.defect-detail-panel .datav-table :deep(.header-item:nth-child(7)),
|
||||
.defect-detail-panel .datav-table :deep(.ceil:nth-child(7)) {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.defect-detail-panel .datav-table :deep(.header-item:nth-child(1)),
|
||||
.defect-detail-panel .datav-table :deep(.ceil:nth-child(1)),
|
||||
.defect-detail-panel .datav-table :deep(.header-item:nth-child(2)),
|
||||
.defect-detail-panel .datav-table :deep(.ceil:nth-child(2)) {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.datav-table :deep(.rows) {
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -1330,5 +1554,41 @@ const pointClass = value => {
|
||||
height: calc(100% - 45px);
|
||||
margin: 0 11px;
|
||||
}
|
||||
.finish-content2 {
|
||||
height: calc(100% - 38px);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 7px 14px 15px;
|
||||
}
|
||||
|
||||
</style>
|
||||
.finish-stat2 {
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.finish-stat2 span {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
color: #dce7fa;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.finish-stat2 strong {
|
||||
color: #20d8ff;
|
||||
font-size: 50px;
|
||||
line-height: 1;
|
||||
font-weight: 900;
|
||||
letter-spacing: 2px;
|
||||
text-shadow: 0 0 10px rgba(32, 216, 255, .5);
|
||||
}
|
||||
|
||||
.finish-stat2 small {
|
||||
margin-left: 2px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -14,7 +14,6 @@
|
||||
<main class="dashboard-body">
|
||||
<section v-for="card in summaryCards" :key="card.title" class="panel summary-card" :class="card.className">
|
||||
<img class="summary-icon" :src="card.icon" alt="" />
|
||||
<!-- 特殊:在制任务汇总 三列数字 -->
|
||||
<div v-if="card.subValues" class="summary-content summary-triple-content">
|
||||
<div class="summary-title">{{ card.title }}</div>
|
||||
<div class="summary-triple">
|
||||
@@ -30,7 +29,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 其他卡片:原有单数字 -->
|
||||
<div v-else class="summary-content">
|
||||
<div class="summary-title">{{ card.title }}</div>
|
||||
<div class="summary-label">总数</div>
|
||||
@@ -47,43 +45,22 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel work-detail-panel">
|
||||
<div class="panel-title">在制任务明细</div>
|
||||
<div class="table-box datav-table main-task-table">
|
||||
<dv-scroll-board :config="inProcessBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel urgent-list-panel">
|
||||
<div class="panel-title">加急任务列表</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="urgentBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel process-task-panel">
|
||||
<div class="panel-title">关键工序任务明细</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="keyProcessBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel start-task-panel">
|
||||
<div class="panel-title">正在开工任务</div>
|
||||
<div class="table-box datav-table">
|
||||
<dv-scroll-board :config="startedBoardConfig" />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
const tableData = ref([])
|
||||
|
||||
const CreateData = inject('CreateData')
|
||||
const ExecDatabase = inject('ExecDatabase')
|
||||
|
||||
defineOptions({
|
||||
name: 'MachiningOperationTwoDashboard'
|
||||
})
|
||||
@@ -91,8 +68,7 @@ defineOptions({
|
||||
const clientLogoUrl = './public/ClientLogo.png'
|
||||
const svgData = svg => 'data:image/svg+xml;utf8,' + encodeURIComponent(svg)
|
||||
const lineIcon = (color, body, viewBox = '0 0 64 64') => {
|
||||
const size = parseFloat(viewBox.split(' ')[2]) || 64
|
||||
const sw = size <= 28 ? 1.4 : 2.0
|
||||
const sw = parseFloat(viewBox.split(' ')[2]) <= 28 ? 1.4 : 2.0
|
||||
return svgData(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="' + viewBox + '" fill="none">' +
|
||||
'<g stroke="' + color + '" stroke-width="' + sw + '" stroke-linecap="round" stroke-linejoin="round">' +
|
||||
@@ -113,11 +89,11 @@ const style = reactive({
|
||||
height: 1080,
|
||||
transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)'
|
||||
})
|
||||
|
||||
const currentTime = ref('')
|
||||
let clockTimer = null
|
||||
let resizeHandler = null
|
||||
|
||||
// 将 computed 改为 ref
|
||||
const summaryCards = ref([
|
||||
{
|
||||
title: '在制任务汇总',
|
||||
@@ -163,43 +139,7 @@ const summaryCards = ref([
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
|
||||
const inProcessRows = ref([
|
||||
])
|
||||
|
||||
const urgentRows = ref([
|
||||
{ productionOrder: 'MO260428-001', salesOrder: 'SO260413-001', materialName: '主轴壳体', materialCode: 'MP-BOX-001', processName: '精铣', assignQty: 120, prevPassQty: 105, urgentQty: 15, assignee: '张伟' },
|
||||
{ productionOrder: 'MO260428-002', salesOrder: 'SO260413-005', materialName: '法兰盘', materialCode: 'MP-FLANGE-002', processName: '镗孔', assignQty: 80, prevPassQty: 68, urgentQty: 12, assignee: '李强' },
|
||||
{ productionOrder: 'MO260428-003', salesOrder: 'SO260414-002', materialName: '齿轮轴', materialCode: 'MP-GEAR-001', processName: '磨削', assignQty: 60, prevPassQty: 48, urgentQty: 12, assignee: '王磊' },
|
||||
{ productionOrder: 'MO260428-004', salesOrder: 'SO260414-003', materialName: '端盖', materialCode: 'MP-COVER-003', processName: '钻孔', assignQty: 90, prevPassQty: 75, urgentQty: 15, assignee: '刘洋' },
|
||||
{ productionOrder: 'MO260428-005', salesOrder: 'SO260414-007', materialName: '导轨座', materialCode: 'MP-RAIL-002', processName: '精镗', assignQty: 70, prevPassQty: 60, urgentQty: 10, assignee: '赵峰' },
|
||||
{ productionOrder: 'MO260428-006', salesOrder: 'SO260415-001', materialName: '轴承座', materialCode: 'MP-BEAR-001', processName: '铣平面', assignQty: 50, prevPassQty: 42, urgentQty: 8, assignee: '陈晨' },
|
||||
{ productionOrder: 'MO260428-007', salesOrder: 'SO260415-003', materialName: '联轴器', materialCode: 'MP-COUP-001', processName: '车削', assignQty: 40, prevPassQty: 32, urgentQty: 8, assignee: '周杰' },
|
||||
{ productionOrder: 'MO260428-008', salesOrder: 'SO260415-005', materialName: '垫板', materialCode: 'MP-PLATE-001', processName: '钻孔', assignQty: 100, prevPassQty: 88, urgentQty: 12, assignee: '孙鹏' }
|
||||
])
|
||||
|
||||
const keyProcessRows = ref([
|
||||
{ productionOrder: 'MO260428-201', salesOrder: 'SO260413-001', materialName: '主轴壳体', materialCode: 'MP-BOX-001', processName: '精镗面', assignQty: 120, prevPassQty: 105, urgentQty: 15, assignee: '周检' },
|
||||
{ productionOrder: 'MO260428-202', salesOrder: 'SO260413-002', materialName: '法兰盘', materialCode: 'MP-FLANGE-002', processName: '镗孔尺寸', assignQty: 80, prevPassQty: 68, urgentQty: 12, assignee: '吕检' },
|
||||
{ productionOrder: 'MO260428-203', salesOrder: 'SO260413-003', materialName: '齿轮轴', materialCode: 'MP-GEAR-001', processName: '磨削圆度', assignQty: 60, prevPassQty: 48, urgentQty: 12, assignee: '何检' },
|
||||
{ productionOrder: 'MO260428-204', salesOrder: 'SO260413-004', materialName: '端盖', materialCode: 'MP-COVER-003', processName: '平面度', assignQty: 90, prevPassQty: 75, urgentQty: 15, assignee: '郭检' },
|
||||
{ productionOrder: 'MO260428-205', salesOrder: 'SO260414-001', materialName: '导轨座', materialCode: 'MP-RAIL-002', processName: '平行度', assignQty: 70, prevPassQty: 60, urgentQty: 10, assignee: '丁检' },
|
||||
{ productionOrder: 'MO260428-206', salesOrder: 'SO260414-002', materialName: '轴承座', materialCode: 'MP-BEAR-001', processName: '孔距尺寸', assignQty: 50, prevPassQty: 42, urgentQty: 8, assignee: '黄检' },
|
||||
{ productionOrder: 'MO260428-207', salesOrder: 'SO260414-003', materialName: '联轴器', materialCode: 'MP-COUP-001', processName: '端面跳动', assignQty: 40, prevPassQty: 32, urgentQty: 8, assignee: '蒋检' },
|
||||
{ productionOrder: 'MO260428-208', salesOrder: 'SO260414-004', materialName: '垫板', materialCode: 'MP-PLATE-001', processName: '厚度', assignQty: 100, prevPassQty: 88, urgentQty: 12, assignee: '韩检' }
|
||||
])
|
||||
|
||||
const startedRows = ref([
|
||||
{ productionOrder: 'MO260429-301', salesOrder: 'SO260415-101', materialName: '箱体壳体', materialCode: 'MP-BOX-009', processName: '粗铣', assignQty: 30 },
|
||||
{ productionOrder: 'MO260429-302', salesOrder: 'SO260415-102', materialName: '轴套', materialCode: 'MP-SHAFT-008', processName: '轴车', assignQty: 24 },
|
||||
{ productionOrder: 'MO260429-303', salesOrder: 'SO260415-103', materialName: '端盖', materialCode: 'MP-CAP-006', processName: '钻孔', assignQty: 20 },
|
||||
{ productionOrder: 'MO260429-304', salesOrder: 'SO260415-104', materialName: '支架', materialCode: 'MP-BRKT-009', processName: '平面铣', assignQty: 16 },
|
||||
{ productionOrder: 'MO260429-305', salesOrder: 'SO260415-105', materialName: '导轨座', materialCode: 'MP-RAIL-010', processName: '铣槽', assignQty: 18 },
|
||||
{ productionOrder: 'MO260429-306', salesOrder: 'SO260415-106', materialName: '盖板', materialCode: 'MP-COVER-011', processName: '攻丝', assignQty: 22 },
|
||||
{ productionOrder: 'MO260429-307', salesOrder: 'SO260415-107', materialName: '连接板', materialCode: 'MP-PLATE-010', processName: '钻孔', assignQty: 28 },
|
||||
{ productionOrder: 'MO260429-308', salesOrder: 'SO260415-108', materialName: '滑块', materialCode: 'MP-SLIDER-009', processName: '精磨', assignQty: 14 }
|
||||
])
|
||||
const urgentRows = ref([])
|
||||
|
||||
const extendRows = (rows, minRows, idKey = 'productionOrder') => {
|
||||
const result = [...rows]
|
||||
@@ -232,72 +172,286 @@ const boardBaseConfig = {
|
||||
index: false
|
||||
}
|
||||
|
||||
const progressText = value => (
|
||||
'<div class="progress-cell">' +
|
||||
'<span class="progress-track"><span class="progress-fill" style="width:' + value + '%"></span></span>' +
|
||||
'<strong>' + Number(value).toFixed(1) + '%</strong>' +
|
||||
'</div>'
|
||||
)
|
||||
|
||||
const urgentRed = (text, isUrgent) => isUrgent ? `<span style="color:#ff3f37">${text}</span>` : text
|
||||
// 格式化工序进度详情为HTML
|
||||
// const formatProcessDetail = (processDetailStr) => {
|
||||
// if (!processDetailStr || typeof processDetailStr !== 'string') {
|
||||
// return ''
|
||||
// }
|
||||
|
||||
const inProcessBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 12,
|
||||
columnWidth: [100, 100, 116, 180, 88, 80, 80, 80,170],
|
||||
header: ['生产订单', '销售订单', '物料名称', '物料编码', '工序名称', '指派对象','分配数量', '完成数量', '进度百分比%'],
|
||||
data: extendRows(inProcessRows.value, 18).map(row => [
|
||||
urgentRed(row.productionOrder, row.isUrgent),
|
||||
urgentRed(row.salesOrder, row.isUrgent),
|
||||
urgentRed(row.materialName, row.isUrgent),
|
||||
urgentRed(row.materialCode, row.isUrgent),
|
||||
urgentRed(row.processName, row.isUrgent),
|
||||
urgentRed(row.assignee, row.isUrgent),
|
||||
urgentRed(row.assignQty, row.isUrgent),
|
||||
urgentRed(row.finishQty, row.isUrgent),
|
||||
row.isUrgent ? progressText(row.progress).replace(/color:[^;"]+/, 'color:#ff3f37') : progressText(row.progress)
|
||||
])
|
||||
}))
|
||||
// // 处理HTML实体:将 -> 转换为 ->
|
||||
// let cleanedStr = processDetailStr
|
||||
// .replace(/>/g, '>')
|
||||
// .replace(/</g, '<')
|
||||
// .replace(/&/g, '&')
|
||||
// .replace(/"/g, '"')
|
||||
// .replace(/'/g, "'")
|
||||
|
||||
// // 按 ' -> ' 分割工序
|
||||
// const steps = cleanedStr.split(' -> ')
|
||||
|
||||
// // 每行最多显示的工序数量
|
||||
// const maxPerRow = 5
|
||||
|
||||
// // 计算需要多少行
|
||||
// const rows = Math.ceil(steps.length / maxPerRow)
|
||||
|
||||
// // 构建表格
|
||||
// let tableHtml = '<table class="process-table"><tbody>'
|
||||
|
||||
// // 为每一行生成名称行和数量行
|
||||
// for (let row = 0; row < rows; row++) {
|
||||
// const startIndex = row * maxPerRow
|
||||
// const endIndex = Math.min(startIndex + maxPerRow, steps.length)
|
||||
// const rowSteps = steps.slice(startIndex, endIndex)
|
||||
|
||||
// // 如果不是第一行,添加分隔行
|
||||
// if (row > 0) {
|
||||
// tableHtml += '<tr style="height: 4px;"><td colspan="' + (maxPerRow * 2 - 1) + '" style="padding: 0; line-height: 1;"></td></tr>'
|
||||
// }
|
||||
|
||||
// // 工序名称行
|
||||
// tableHtml += '<tr>'
|
||||
// rowSteps.forEach((step, index) => {
|
||||
// const parts = step.split('|')
|
||||
// // 关键修改:直接使用原始名称,不进行任何转换
|
||||
// let name = parts[0] || ''
|
||||
// const status = parts[1] || '0'
|
||||
|
||||
// // 根据状态设置颜色
|
||||
// let colorStyle = ''
|
||||
// const statusNum = parseInt(status)
|
||||
// if (statusNum === 6) {
|
||||
// colorStyle = 'color: #09a8ff; font-weight: 700;'
|
||||
// } else if (statusNum === 2 || statusNum === 4) {
|
||||
// colorStyle = 'color: #28d961; font-weight: 700;'
|
||||
// }
|
||||
|
||||
// tableHtml += `<td style="${colorStyle}">${name}</td>`
|
||||
// // 在本行内部添加工序间箭头(不包括行尾和不补位)
|
||||
// if (index < rowSteps.length - 1) {
|
||||
// tableHtml += '<td class="arrow-cell">→</td>'
|
||||
// }
|
||||
// })
|
||||
// tableHtml += '</tr>'
|
||||
|
||||
// // 完成数量行
|
||||
// tableHtml += '<tr>'
|
||||
// rowSteps.forEach((step, index) => {
|
||||
// const parts = step.split('|')
|
||||
// const count = parts[2] || '0'
|
||||
|
||||
// tableHtml += `<td class="count-cell">${count}</td>`
|
||||
// // 完成数量之间不显示箭头,但保留空列以对齐
|
||||
// if (index < rowSteps.length - 1) {
|
||||
// tableHtml += '<td class="arrow-cell-hidden"></td>'
|
||||
// }
|
||||
// })
|
||||
// tableHtml += '</tr>'
|
||||
// }
|
||||
|
||||
// tableHtml += '</tbody></table>'
|
||||
|
||||
// return tableHtml
|
||||
// }
|
||||
// 格式化工序进度详情为HTML
|
||||
// 格式化工序进度详情为HTML
|
||||
// 格式化工序进度详情为HTML
|
||||
const formatProcessDetail = (processDetailStr) => {
|
||||
if (!processDetailStr || typeof processDetailStr !== 'string') {
|
||||
return ''
|
||||
}
|
||||
|
||||
const urgentBoardConfig = computed(() => makeTaskBoard(urgentRows.value))
|
||||
const keyProcessBoardConfig = computed(() => makeTaskBoard(keyProcessRows.value))
|
||||
|
||||
const startedBoardConfig = computed(() => ({
|
||||
...boardBaseConfig,
|
||||
rowNum: 8,
|
||||
// columnWidth: [160, 170, 140, 176, 140, 128],
|
||||
header: ['生产订单','物料名称', '物料编码', '工序名称', '指派对象','分配数量','完成数量'],
|
||||
data: extendRows(startedRows.value, 12).map(row => [
|
||||
row.productionOrder,
|
||||
// row.salesOrder,
|
||||
row.materialName,
|
||||
row.materialCode,
|
||||
row.processName,
|
||||
row.assignee,
|
||||
row.assignQty,
|
||||
row.finishQty
|
||||
])
|
||||
}))
|
||||
const steps = processDetailStr.split(' -> ')
|
||||
const maxPerRow = 8
|
||||
const rows = Math.ceil(steps.length / maxPerRow)
|
||||
|
||||
// 外层容器左对齐,内部表格正常
|
||||
let tableHtml = '<div style="text-align: left; width: 100%;"><table class="process-table"><tbody>'
|
||||
|
||||
for (let row = 0; row < rows; row++) {
|
||||
const startIndex = row * maxPerRow
|
||||
const endIndex = Math.min(startIndex + maxPerRow, steps.length)
|
||||
const rowSteps = steps.slice(startIndex, endIndex)
|
||||
|
||||
if (row > 0) {
|
||||
tableHtml += '<tr style="height: 4px;"><td colspan="' + (maxPerRow * 2 - 1) + '" style="padding: 0; line-height: 1;"></td></tr>'
|
||||
}
|
||||
|
||||
// 计划开始时间行
|
||||
tableHtml += '<tr>'
|
||||
rowSteps.forEach((step, index) => {
|
||||
const parts = step.split('|')
|
||||
const planDate = parts[3] || ''
|
||||
const status = parts[1] || '0'
|
||||
const count = parts[2] || '0'
|
||||
|
||||
// 获取颜色
|
||||
const colorStyle = getProcessColor(status, count)
|
||||
|
||||
tableHtml += `<td class="plan-date-cell" style="${colorStyle}">${planDate}</td>`
|
||||
if (index < rowSteps.length - 1) {
|
||||
tableHtml += '<td class="arrow-cell-hidden"></td>'
|
||||
}
|
||||
})
|
||||
tableHtml += '</tr>'
|
||||
|
||||
// 工序名称行
|
||||
tableHtml += '<tr>'
|
||||
rowSteps.forEach((step, index) => {
|
||||
const parts = step.split('|')
|
||||
const name = parts[0] || ''
|
||||
const status = parts[1] || '0'
|
||||
const count = parts[2] || '0'
|
||||
|
||||
const colorStyle = getProcessColor(status, count)
|
||||
|
||||
tableHtml += `<td style="${colorStyle}">${name}</td>`
|
||||
if (index < rowSteps.length - 1) {
|
||||
tableHtml += '<td class="arrow-cell">→</td>'
|
||||
}
|
||||
})
|
||||
tableHtml += '</tr>'
|
||||
|
||||
// 完成数量行
|
||||
tableHtml += '<tr>'
|
||||
rowSteps.forEach((step, index) => {
|
||||
const parts = step.split('|')
|
||||
const count = parts[2] || '0'
|
||||
const status = parts[1] || '0'
|
||||
|
||||
const colorStyle = getProcessColor(status, count)
|
||||
|
||||
tableHtml += `<td class="count-cell" style="${colorStyle}">合格${count}</td>`
|
||||
if (index < rowSteps.length - 1) {
|
||||
tableHtml += '<td class="arrow-cell-hidden"></td>'
|
||||
}
|
||||
})
|
||||
tableHtml += '</tr>'
|
||||
}
|
||||
|
||||
tableHtml += '</tbody></table></div>'
|
||||
|
||||
return tableHtml
|
||||
}
|
||||
|
||||
// 获取颜色函数
|
||||
const getProcessColor = (status, count) => {
|
||||
const statusNum = parseInt(status)
|
||||
const countNum = parseInt(count)
|
||||
|
||||
// 加工状态=2或4 绿色
|
||||
if (statusNum === 2 || statusNum === 4) {
|
||||
return 'color: #28d961; font-weight: 700;'
|
||||
}
|
||||
// 加工状态=6 蓝色
|
||||
if (statusNum === 6 || statusNum === 3) {
|
||||
return 'color: #09a8ff; font-weight: 700;'
|
||||
}
|
||||
// 完成数量>0 蓝色
|
||||
if (countNum > 0) {
|
||||
return 'color: #09a8ff; font-weight: 700;'
|
||||
}
|
||||
// 其余红色
|
||||
return 'color: #ff3f37; font-weight: 700;'
|
||||
}
|
||||
function makeTaskBoard(rows) {
|
||||
return {
|
||||
...boardBaseConfig,
|
||||
rowNum: 8,
|
||||
columnWidth: [122, 132, 132, 152, 92, 82, 92, 94],
|
||||
header: ['生产订单', '销售订单', '物料名称', '物料编码', '工序名称', '分配数量', '加急数量', '指派对象'],
|
||||
rowNum: 12,
|
||||
columnWidth: [150, 132, 200, 82, 750],
|
||||
header: ['生产订单', '物料名称', '物料编码', '加急数量', '进度'],
|
||||
data: extendRows(rows, 12).map(row => [
|
||||
row.productionOrder,
|
||||
row.salesOrder,
|
||||
row.materialName,
|
||||
row.materialCode,
|
||||
row.processName,
|
||||
row.assignQty,
|
||||
row.urgentQty,
|
||||
row.assignee
|
||||
formatProcessDetail(row.assignee)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
const urgentBoardConfig = computed(() => makeTaskBoard(urgentRows.value))
|
||||
|
||||
const queryDashboardData = (procedureName, applyData) => {
|
||||
if (typeof CreateData !== 'function' || typeof ExecDatabase !== 'function') {
|
||||
return
|
||||
}
|
||||
const data = CreateData('11', procedureName, [])
|
||||
ExecDatabase(data).then(response => {
|
||||
const rows = getResponseRows(response)
|
||||
if (rows.length > 0) {
|
||||
applyData(rows)
|
||||
nextTick(() => {})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getResponseRows = response => {
|
||||
if (response && Array.isArray(response.data)) {
|
||||
return response.data
|
||||
}
|
||||
if (response && response.data && Array.isArray(response.data.result)) {
|
||||
return response.data.result
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const searchDashboardData = () => {
|
||||
searchUrgentData()
|
||||
}
|
||||
|
||||
const searchUrgentData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_加急任务查询', applyUrgentData)
|
||||
}
|
||||
|
||||
const applyUrgentData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
if (first.加急订单总数 !== undefined) {
|
||||
summaryCards.value[1].value = first.加急订单总数
|
||||
}
|
||||
|
||||
urgentRows.value = rows.map(row => {
|
||||
// 处理HTML实体
|
||||
let processDetail = row.工序进度详情 || ''
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.innerHTML = processDetail
|
||||
processDetail = textarea.value
|
||||
|
||||
return {
|
||||
productionOrder: row.订单编号 + '-' + row.合同号,
|
||||
materialName: row.物料描述,
|
||||
materialCode: row.物料编号,
|
||||
urgentQty: row.加急数量,
|
||||
assignee: processDetail,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getFirstRow = rows => {
|
||||
if (Array.isArray(rows) && rows.length > 0) {
|
||||
return rows[0]
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
const refreshClock = () => {
|
||||
const now = new Date()
|
||||
const pad = value => String(value).padStart(2, '0')
|
||||
const weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
currentTime.value = `${now.getFullYear()}年${pad(now.getMonth() + 1)}月${pad(now.getDate())}日 ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())} ${weeks[now.getDay()]}`
|
||||
}
|
||||
|
||||
const setScale = () => {
|
||||
const scale = getScale()
|
||||
style.transform = `scaleY(${scale.y}) scaleX(${scale.x}) translate(-50%, -50%)`
|
||||
}
|
||||
|
||||
const getScale = () => ({
|
||||
x: window.innerWidth / style.width,
|
||||
y: window.innerHeight / style.height
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
refreshClock()
|
||||
clockTimer = window.setInterval(refreshClock, 1000)
|
||||
@@ -317,125 +471,6 @@ onUnmounted(() => {
|
||||
resizeHandler = null
|
||||
}
|
||||
})
|
||||
const queryDashboardData = (procedureName, applyData) => {
|
||||
let data
|
||||
if (typeof CreateData !== 'function' || typeof ExecDatabase !== 'function') {
|
||||
|
||||
return
|
||||
}
|
||||
data = CreateData('11', procedureName, [])
|
||||
ExecDatabase(data).then(response => {
|
||||
const rows = getResponseRows(response)
|
||||
if (rows.length > 0) {
|
||||
tableData.value = rows
|
||||
applyData(rows)
|
||||
nextTick(() => {
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const getResponseRows = response => {
|
||||
if (response && Array.isArray(response.data)) {
|
||||
return response.data
|
||||
}
|
||||
if (response && response.data && Array.isArray(response.data.result)) {
|
||||
return response.data.result
|
||||
}
|
||||
return []
|
||||
}
|
||||
const searchDashboardData = () => {
|
||||
searchUrgentData()
|
||||
searchInProcessData()
|
||||
searchInProcessData2()
|
||||
}
|
||||
const searchUrgentData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_加急任务查询', applyUrgentData)
|
||||
}
|
||||
const searchInProcessData = () => {
|
||||
queryDashboardData('机加设备生产运营看板_机加在制查询', applyInProcessData)
|
||||
}
|
||||
|
||||
const searchInProcessData2 = () => {
|
||||
queryDashboardData('机加设备生产运营看板_机加在制查询2', applyInProcessData2)
|
||||
}
|
||||
|
||||
// 修改赋值逻辑
|
||||
const applyUrgentData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
console.log(first)
|
||||
// 加急任务汇总卡片是索引1
|
||||
if (first.加急订单总数 !== undefined) {
|
||||
summaryCards.value[1].value = first.加急订单总数
|
||||
}
|
||||
urgentRows .value = rows.map(row => ({
|
||||
productionOrder: row.订单编号,
|
||||
salesOrder:row.合同号,
|
||||
materialName: row.物料描述,
|
||||
materialCode: row.物料编号,
|
||||
assignQty: row.计划数量,
|
||||
urgentQty: row.加急数量,
|
||||
prevPassQty:'',
|
||||
processName:row.工序名称,
|
||||
assignee:row.指派对象,
|
||||
}))
|
||||
|
||||
}
|
||||
const applyInProcessData = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
startedRows .value = rows.map(row => ({
|
||||
productionOrder: row.订单号,
|
||||
salesOrder:row.合同号,
|
||||
materialName: row.零件名称,
|
||||
materialCode: row.零件编码,
|
||||
assignQty: row.分配数,
|
||||
processName:row.工序名称,
|
||||
assignee:row.指派对象,
|
||||
finishQty:row.完成数量
|
||||
}))
|
||||
|
||||
}
|
||||
const applyInProcessData2 = rows => {
|
||||
const first = getFirstRow(rows)
|
||||
summaryCards.value[0].value = first.总记录数
|
||||
summaryCards.value[0].subValues[0].value = first.计划开始_今天之前_数量 || 0
|
||||
summaryCards.value[0].subValues[1].value = first.计划开始_今天及之后_数量 || 0
|
||||
inProcessRows .value = rows.map(row => ({
|
||||
productionOrder: row.订单号,
|
||||
salesOrder:row.合同号,
|
||||
materialName: row.零件名称,
|
||||
materialCode: row.零件编码,
|
||||
assignQty: row.分配数,
|
||||
processName:row.工序名称,
|
||||
assignee: row.指派对象,
|
||||
finishQty: row.完成数量,
|
||||
progress: ((row.完成数量 / row.分配数) * 100).toFixed(2),
|
||||
isUrgent: row.加急 === '加急'
|
||||
})).sort((a, b) => (b.isUrgent ? 1 : 0) - (a.isUrgent ? 1 : 0))
|
||||
|
||||
}
|
||||
const getFirstRow = rows => {
|
||||
if (Array.isArray(rows) && rows.length > 0) {
|
||||
return rows[0]
|
||||
}
|
||||
return {}
|
||||
}
|
||||
const refreshClock = () => {
|
||||
const now = new Date()
|
||||
const pad = value => String(value).padStart(2, '0')
|
||||
const weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||
currentTime.value = `${now.getFullYear()}年${pad(now.getMonth() + 1)}月${pad(now.getDate())}日 ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())} ${weeks[now.getDay()]}`
|
||||
}
|
||||
|
||||
const setScale = () => {
|
||||
const scale = getScale()
|
||||
style.transform = `scaleY(${scale.y}) scaleX(${scale.x}) translate(-50%, -50%)`
|
||||
}
|
||||
|
||||
const getScale = () => ({
|
||||
x: window.innerWidth / style.width,
|
||||
y: window.innerHeight / style.height
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -658,7 +693,6 @@ const getScale = () => ({
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
/* ---- 在制任务汇总 三列数字 ---- */
|
||||
.summary-triple-content {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -765,34 +799,13 @@ const getScale = () => ({
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.work-detail-panel {
|
||||
.urgent-list-panel {
|
||||
left: 14px;
|
||||
top: 149px;
|
||||
width: 938px;
|
||||
width: 1350px;
|
||||
height: 818px;
|
||||
}
|
||||
|
||||
.urgent-list-panel {
|
||||
left: 968px;
|
||||
top: 149px;
|
||||
width: 938px;
|
||||
height: 270px;
|
||||
}
|
||||
|
||||
.process-task-panel {
|
||||
left: 968px;
|
||||
top: 431px;
|
||||
width: 938px;
|
||||
height: 270px;
|
||||
}
|
||||
|
||||
.start-task-panel {
|
||||
left: 968px;
|
||||
top: 713px;
|
||||
width: 938px;
|
||||
height: 254px;
|
||||
}
|
||||
|
||||
.table-box {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
@@ -831,9 +844,8 @@ const getScale = () => ({
|
||||
padding: 0 2px;
|
||||
border-right: 1px solid rgba(0, 164, 255, .55);
|
||||
border-bottom: 1px solid rgba(0, 164, 255, .42);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
white-space: wrap;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.datav-table :deep(.header-item:last-child),
|
||||
@@ -862,43 +874,62 @@ const getScale = () => ({
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.main-task-table :deep(.row-item) {
|
||||
.datav-table :deep(.row-item) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.datav-table :deep(.progress-cell) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
height: 100%;
|
||||
.process-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.datav-table :deep(.progress-track) {
|
||||
position: relative;
|
||||
width: 78px;
|
||||
height: 16px;
|
||||
border: 1px solid rgba(73, 160, 232, .76);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
background: rgba(14, 41, 67, .92);
|
||||
box-shadow: inset 0 0 9px rgba(16, 130, 255, .25);
|
||||
.process-table td {
|
||||
text-align: left; /* 改为左对齐 */
|
||||
padding: 2px 4px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
color: #c2cbe0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.datav-table :deep(.progress-fill) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(90deg, #314dff 0%, #126dff 55%, #22e6ff 100%);
|
||||
box-shadow: 0 0 10px rgba(23, 150, 255, .75);
|
||||
.plan-date-cell {
|
||||
font-size: 10px !important;
|
||||
color: #8899aa !important;
|
||||
padding: 2px 4px !important;
|
||||
}
|
||||
|
||||
.datav-table :deep(.progress-cell strong) {
|
||||
min-width: 46px;
|
||||
color: #62c6ec;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-align: right;
|
||||
.count-cell {
|
||||
font-weight: 700;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
.arrow-cell {
|
||||
color: rgba(0, 164, 255, 0.6) !important;
|
||||
font-size: 10px !important;
|
||||
padding: 2px 1px !important;
|
||||
width: 12px;
|
||||
text-align: center !important; /* 箭头居中 */
|
||||
}
|
||||
|
||||
.arrow-cell-hidden {
|
||||
padding: 2px 1px !important;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
/* 滚动表格中的进度列样式优化 */
|
||||
.datav-table :deep(.ceil .process-table) {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.datav-table :deep(.row-item) {
|
||||
height: auto !important;
|
||||
min-height: 50px;
|
||||
}
|
||||
|
||||
.datav-table :deep(.ceil) {
|
||||
height: auto !important;
|
||||
min-height: 50px;
|
||||
line-height: 1.4 !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user