Browse Source

机加工

master
han\hanst 2 weeks ago
parent
commit
c1794ac23f
  1. 7
      src/api/longchuang/productionPlan.js
  2. 1
      src/router/index.js
  3. 7
      src/views/modules/longtron/production-plan-cable-cop-task.vue
  4. 7
      src/views/modules/longtron/production-plan-home-order.vue
  5. 780
      src/views/modules/longtron/production-plan-machining-task.vue
  6. 9
      src/views/modules/longtron/production-plan-renovation-order.vue
  7. 75
      src/views/modules/longtron/production-work-report.vue
  8. 132
      src/views/modules/longtron/screen-machining-progress.vue

7
src/api/longchuang/productionPlan.js

@ -21,6 +21,13 @@ export const finishRenovationOrder = data => createAPI(`/longchuang/productionPl
export const reportRenovationOrderNode = data => createAPI(`/longchuang/productionPlan/renovationOrder/reportNode`, 'post', data)
export const deleteRenovationOrder = data => createAPI(`/longchuang/productionPlan/renovationOrder/delete`, 'post', data)
// ================= 序号4:机加工生产任务单 =================
export const getMachiningTaskList = data => createAPI(`/longchuang/productionPlan/machiningTask/list`, 'post', data)
export const saveMachiningTask = data => createAPI(`/longchuang/productionPlan/machiningTask/save`, 'post', data)
export const finishMachiningTask = data => createAPI(`/longchuang/productionPlan/machiningTask/finish`, 'post', data)
export const reportMachiningTaskNode = data => createAPI(`/longchuang/productionPlan/machiningTask/reportNode`, 'post', data)
export const deleteMachiningTask = data => createAPI(`/longchuang/productionPlan/machiningTask/delete`, 'post', data)
// ================= 节点负责人分配 =================
export const getNodeAssigneeList = data => createAPI(`/longchuang/productionPlan/nodeAssignee/list`, 'post', data)
export const saveNodeAssignee = data => createAPI(`/longchuang/productionPlan/nodeAssignee/save`, 'post', data)

1
src/router/index.js

@ -25,6 +25,7 @@ const globalRoutes = [
{ path: '/screen-whole-lift-progress', component: _import('modules/longtron/screen-whole-lift-progress'), name: 'screen-whole-lift-progress', meta: { title: '整梯生产进度看板' } },
{ path: '/screen-cable-cop-progress', component: _import('modules/longtron/screen-cable-cop-progress'), name: 'screen-cable-cop-progress', meta: { title: '线缆/COP生产进度看板' } },
{ path: '/screen-renovation-progress', component: _import('modules/longtron/screen-renovation-progress'), name: 'screen-renovation-progress', meta: { title: '改造项目生产进度看板' } },
{ path: '/screen-machining-progress', component: _import('modules/longtron/screen-machining-progress'), name: 'screen-machining-progress', meta: { title: '机加工生产进度看板' } },
{ path: '/screen-factory-overview', component: _import('modules/longtron/screen-factory-overview'), name: 'screen-factory-overview', meta: { title: '工厂综合运营看板' } },
]

7
src/views/modules/longtron/production-plan-cable-cop-task.vue

@ -73,7 +73,7 @@
<el-table-column label="操作" width="300" align="center">
<template slot-scope="scope">
<a type="text" @click="openEditDialog(scope.row)" v-if="scope.row.status === '已排产'">修改</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成'">分配人员</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成' && scope.row.currentNode!=='全部完成'">分配人员</a>
<a type="text" @click="finishTask(scope.row)" v-if="scope.row.status !== '已完成'">完工</a>
<a type="text" style="color:#F56C6C" @click="deleteTask(scope.row)" v-if="scope.row.status !== '已完成'">删除</a>
</template>
@ -481,10 +481,7 @@ export default {
const nextNode = row.nodeList.find(item => item.status !== '已完成')
row.currentNode = nextNode ? nextNode.nodeName : '全部完成'
row.nodeDoneCount = row.nodeList.filter(item => item.status === '已完成').length
if (!nextNode) {
row.status = '已完成'
row.finishDate = this.dayjs().format('YYYY-MM-DD')
}
row.finishDate = ''
},
finishTask(row) {
finishCableCopTask({ orderNo: row.orderNo }).then(({data}) => {

7
src/views/modules/longtron/production-plan-home-order.vue

@ -68,7 +68,7 @@
<el-table-column label="操作" width="300" align="center" >
<template slot-scope="scope">
<a type="text" @click="openEditDialog(scope.row)" v-if="scope.row.status === '已排产'">修改</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成'">分配人员</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成' && scope.row.currentNode!=='全部完成'">分配人员</a>
<a type="text" @click="finishOrder(scope.row)" v-if="scope.row.status !== '已完成'">完工</a>
<a type="text" style="color:#F56C6C" @click="deleteOrder(scope.row)" v-if="scope.row.status !== '已完成'">删除</a>
</template>
@ -444,10 +444,7 @@ export default {
const nextNode = row.nodeList.find(item => item.status !== '已完成')
row.currentNode = nextNode ? nextNode.nodeName : '全部完成'
row.nodeDoneCount = row.nodeList.filter(item => item.status === '已完成').length
if (!nextNode) {
row.status = '已完成'
row.finishDate = this.dayjs().format('YYYY-MM-DD')
}
row.finishDate = ''
},
finishOrder(row) {
finishHomeLiftOrder({ orderNo: row.orderNo }).then(({data}) => {

780
src/views/modules/longtron/production-plan-machining-task.vue

@ -0,0 +1,780 @@
<template>
<div class="mod-config">
<el-form :inline="true" label-position="top" class="query-form">
<el-form-item label="物料号">
<el-input v-model="searchData.modelNo" clearable placeholder="请输入物料号" style="width: 160px"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchData.status" clearable placeholder="全部" style="width: 120px">
<el-option label="已排产" value="已排产"></el-option>
<el-option label="进行中" value="进行中"></el-option>
<el-option label="已完成" value="已完成"></el-option>
</el-select>
</el-form-item>
<el-form-item label="计划完工日期">
<el-date-picker v-model="searchData.planStartDate" type="date" value-format="yyyy-MM-dd" placeholder="开始" style="width: 130px"></el-date-picker>
</el-form-item>
<el-form-item label="至">
<el-date-picker v-model="searchData.planEndDate" type="date" value-format="yyyy-MM-dd" placeholder="结束" style="width: 130px"></el-date-picker>
</el-form-item>
<el-form-item label=" " style="margin-top: -11px">
<el-button @click="searchTable('Y')" plain class="search-btn">查询</el-button>
<el-button @click="resetQuery()" plain class="reset-btn">重置</el-button>
<el-button @click="openEditDialog()" plain class="add-btn">新增任务单</el-button>
</el-form-item>
</el-form>
<el-table
ref="orderTable"
class="data-table"
:data="dataList"
:height="tableHeight"
border
highlight-current-row
v-loading="dataListLoading"
style="width: 100%"
@current-change="onCurrentRowChange">
<el-table-column type="index" label="#" width="50" align="center"></el-table-column>
<el-table-column prop="orderNo" label="任务单号" width="180" align="center"></el-table-column>
<el-table-column prop="modelNo" label="物料号" width="160" align="center"></el-table-column>
<el-table-column prop="taskQty" label="计划数量" width="100" align="center"></el-table-column>
<el-table-column prop="reportQty" label="累计报工数量" width="120" align="center"></el-table-column>
<el-table-column prop="currentNode" label="当前节点" width="120" align="center"></el-table-column>
<el-table-column prop="assigneeSummary" label="节点负责人" min-width="160" show-overflow-tooltip></el-table-column>
<el-table-column label="节点进度" width="100" align="center">
<template slot-scope="scope">
<el-tag size="small" type="info">{{ scope.row.nodeDoneCount }}/{{ scope.row.nodeTotalCount }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="90" align="center">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.status)" size="small">{{ scope.row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="planFinishDate" label="计划完工日期" width="120" align="center"></el-table-column>
<el-table-column prop="finishDate" label="完工日期" width="120" align="center">
<template slot-scope="scope">{{ scope.row.finishDate || '-' }}</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center">
<template slot-scope="scope">
<a type="text" @click="openEditDialog(scope.row)" v-if="scope.row.status === '已排产'">修改</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成' && scope.row.currentNode!=='全部完成'">分配人员</a>
<a type="text" @click="finishTask(scope.row)" v-if="scope.row.status !== '已完成'">完工</a>
<a type="text" style="color:#F56C6C" @click="deleteTask(scope.row)" v-if="scope.row.status !== '已完成'">删除</a>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
style="margin-top: 20px; text-align: right">
</el-pagination>
<div class="detail-tabs-wrap">
<el-tabs v-model="detailTabName" type="border-card">
<el-tab-pane label="节点状态和日志" name="statusLogs">
<div v-if="selectedOrder.orderNo" class="two-column-layout">
<div class="stages-column">
<div class="column-header">
<i class="el-icon-s-order"></i>
<span>节点流程</span>
<span class="progress-badge">{{ selectedOrderProgressPercent }}%</span>
</div>
<div class="stages-list">
<div
v-for="(stage, index) in selectedOrderNodeList"
:key="stage.nodeCode || index"
class="stage-item"
:class="'stage-' + getStageClass(stage.status)">
<div class="stage-icon">
<i :class="getStageIcon(stage.status)"></i>
</div>
<div class="stage-content">
<div class="stage-name">{{ stage.nodeName }}</div>
<div class="stage-meta">
<el-tag :type="getStageTagType(stage.status)" size="mini" effect="plain">{{ stage.status || '未开始' }}</el-tag>
<span class="stage-owner">负责人{{ stage.assigneeUserName || '-' }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="logs-column">
<div class="column-header">
<i class="el-icon-tickets"></i>
<span>操作日志</span>
<span class="logs-count">{{ selectedOrderLogList.length }}</span>
</div>
<div class="logs-table-wrapper">
<el-table :data="selectedOrderLogList" border size="small" class="detail-table" v-loading="detailLogLoading" height="295px">
<el-table-column prop="logTime" label="时间" width="160" align="center"></el-table-column>
<el-table-column prop="action" label="操作" width="95" align="center"></el-table-column>
<el-table-column prop="nodeName" label="节点" width="130" align="center">
<template slot-scope="scope">{{ scope.row.nodeName || scope.row.nodeCode || '-' }}</template>
</el-table-column>
<el-table-column prop="operatorName" label="操作人" width="100" align="center"></el-table-column>
<el-table-column prop="comment" label="备注" min-width="220" show-overflow-tooltip>
<template slot-scope="scope">{{ scope.row.comment || '-' }}</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
<el-empty v-else description="请先选择一条任务记录"></el-empty>
</el-tab-pane>
</el-tabs>
</div>
<el-dialog :title="saveHeaderData.orderNo ? '修改机加工生产任务单' : '新增机加工生产任务单'" :visible.sync="setUp.reviewFlag" width="550px" :close-on-click-modal="false" v-drag>
<el-form
ref="editForm"
:model="saveHeaderData"
label-position="top"
class="edit-form">
<el-row :gutter="20">
<el-col :span="12"><el-form-item label="物料号" required><el-input v-model="saveHeaderData.modelNo"></el-input></el-form-item></el-col>
<el-col :span="12"><el-form-item label="计划数量" required><el-input v-model="saveHeaderData.taskQty" :min="1" :max="999999" style="width: 100%"></el-input></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12"><el-form-item label="计划完工日期" required><el-date-picker v-model="saveHeaderData.planFinishDate" type="date" value-format="yyyy-MM-dd" style="width: 100%"></el-date-picker></el-form-item></el-col>
<el-col :span="12"><el-form-item label="状态"><el-select disabled v-model="saveHeaderData.status" style="width: 100%"><el-option label="已排产" value="已排产"></el-option><el-option label="进行中" value="进行中"></el-option><el-option label="已完成" value="已完成"></el-option></el-select></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item>
<template slot="label">
人员分配策略
<el-tooltip effect="dark" placement="top">
<div slot="content">
默认分配创建订单后系统会按节点角色自动分配该角色下全部人员<br>
手动分配创建订单后不自动分配需要在分配人员里手工选择负责人
</div>
<i class="el-icon-question" style="margin-left:6px;color:#909399;cursor:pointer;"></i>
</el-tooltip>
</template>
<el-radio-group v-model="saveHeaderData.autoAssignAllUsers">
<el-radio :label="true">默认分配</el-radio>
<el-radio :label="false">手动分配</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="节点报工模式">
<el-radio-group v-model="saveHeaderData.nodeReportMode">
<el-radio label="PARALLEL">并行</el-radio>
<el-radio label="SEQUENTIAL">串行</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-footer style="height: 40px; margin-top: 50px; text-align: center">
<el-button plain class="reset-btn" @click="setUp.reviewFlag = false">取消</el-button>
<el-button plain class="add-btn" :loading="setUp.saveButton" @click="saveTask">保存</el-button>
</el-footer>
</el-dialog>
<el-dialog title="机加工生产报工" :visible.sync="setUp.reportFlag" width="460px" :close-on-click-modal="false" v-drag>
<el-form :model="reportData" label-width="110px" label-position="top">
<el-form-item label="任务单号"><el-input v-model="reportData.taskNo" disabled></el-input></el-form-item>
<el-form-item label="本次报工数量"><el-input v-model="reportData.reportQty" :min="1" :max="999999" style="width: 100%"></el-input></el-form-item>
<el-form-item label="报工备注"><el-input v-model="reportData.remark" type="textarea" :rows="2"></el-input></el-form-item>
</el-form>
<el-footer style="height: 40px; margin-top: 50px; text-align: center">
<el-button plain class="reset-btn" @click="setUp.reportFlag = false">取消</el-button>
<el-button plain class="search-btn" :loading="setUp.reportButton" @click="submitNodeReport">提交报工</el-button>
</el-footer>
</el-dialog>
<el-dialog title="节点负责人分配" :visible.sync="setUp.assignFlag" width="550px" :close-on-click-modal="false" v-drag>
<el-table :data="assignNodeList" border class="data-table">
<el-table-column prop="nodeName" label="节点" width="150"></el-table-column>
<el-table-column label="负责人" width="370">
<template slot-scope="scope">
<el-select v-model="scope.row.assigneeUserIdList" filterable clearable multiple placeholder="请选择负责人" style="width: 100%">
<el-option v-for="user in scope.row.userOptions" :key="user.userId" :label="user.displayName || user.username" :value="user.userId"></el-option>
</el-select>
</template>
</el-table-column>
</el-table>
<el-footer style="height: 40px; margin-top: 20px; text-align: center">
<el-button plain class="reset-btn" @click="setUp.assignFlag = false">取消</el-button>
<el-button plain class="add-btn" :loading="setUp.assignButton" @click="saveNodeAssigneeAction">保存分配</el-button>
</el-footer>
</el-dialog>
</div>
</template>
<script>
import { deleteMachiningTask, finishMachiningTask, getMachiningTaskList, getNodeAssigneeList, getNodeAssigneeUsers, getReportLogList, reportMachiningTaskNode, saveMachiningTask, saveNodeAssignee } from '@/api/longchuang/productionPlan'
export default {
name: 'ProductionPlanMachiningTask',
data() {
return {
searchData: { modelNo: '', status: '', planStartDate: '', planEndDate: '', page: 1, limit: 20 },
saveHeaderData: {},
reportData: { orderNo: '', taskNo: '', nodeCode: 'machiningProduction', reportQty: '', remark: '' },
setUp: { reviewFlag: false, reportFlag: false, assignFlag: false, saveButton: false, reportButton: false, assignButton: false },
dataList: [],
currentAssignOrder: { orderNo: '', orderType: 'MACHINING' },
assignNodeList: [],
selectedOrder: {},
detailTabName: 'statusLogs',
selectedOrderLogList: [],
detailLogLoading: false,
pageIndex: 1,
pageSize: 20,
totalPage: 0,
dataListLoading: false,
tableHeight: (window.innerHeight - 320) / 2
}
},
activated() {
this.searchTable()
},
methods: {
searchTable(flag) {
if (flag === 'Y') this.pageIndex = 1
this.searchData.page = this.pageIndex
this.searchData.limit = this.pageSize
this.dataListLoading = true
getMachiningTaskList(this.searchData).then(({ data }) => {
this.dataListLoading = false
if (data && data.code === 0) {
this.dataList = (data.page.list || []).map(this.normalizeRow)
this.totalPage = data.page.totalCount || 0
this.syncSelectedOrder()
} else this.loadMockData()
}).catch(() => {
this.dataListLoading = false
this.loadMockData()
})
},
normalizeRow(row) {
const list = row.nodeList || []
const done = list.filter(item => item.status === '已完成').length
const currentNode = (list.find(item => item.status !== '已完成') || {}).nodeName || '全部完成'
const assigneeSummary = list.filter(item => item.assigneeUserName).map(item => `${item.nodeName}:${item.assigneeUserName}`).join(';')
return { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL', nodeList: list, nodeDoneCount: done, nodeTotalCount: list.length, currentNode: row.currentNode || currentNode, reportQty: row.reportQty || 0, assigneeSummary: assigneeSummary || '-' }
},
loadMockData() {
this.dataList = [
{
orderNo: 'MOCK-MACH-001',
projectNo: 'MAT-120001',
modelNo: 'MAT-120001',
taskQty: 120,
reportQty: 30,
autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
planFinishDate: '2026-05-25',
finishDate: '',
status: '进行中',
nodeList: [
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '进行中' }
]
},
{
orderNo: 'MOCK-MACH-002',
projectNo: 'MAT-120188',
modelNo: 'MAT-120188',
taskQty: 240,
reportQty: 0,
autoAssignAllUsers: true,
nodeReportMode: 'PARALLEL',
planFinishDate: '2026-05-27',
finishDate: '',
status: '已排产',
nodeList: [
{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '未开始' }
]
}
].map(this.normalizeRow)
this.totalPage = this.dataList.length
this.syncSelectedOrder()
},
syncSelectedOrder() {
if (!this.dataList.length) {
this.selectedOrder = {}
this.selectedOrderLogList = []
return
}
const selectedOrderNo = this.selectedOrder && this.selectedOrder.orderNo
const matched = selectedOrderNo ? this.dataList.find(item => item.orderNo === selectedOrderNo) : null
const current = matched || this.dataList[0]
this.selectedOrder = current
this.$nextTick(() => {
if (this.$refs.orderTable && current) {
this.$refs.orderTable.setCurrentRow(current)
}
})
this.loadSelectedOrderLogList(current)
},
onCurrentRowChange(row) {
if (!row || !row.orderNo) {
this.selectedOrder = {}
this.selectedOrderLogList = []
return
}
this.selectedOrder = row
this.loadSelectedOrderLogList(row)
},
loadSelectedOrderLogList(row) {
if (!row || !row.orderNo) {
this.selectedOrderLogList = []
return
}
this.detailLogLoading = true
getReportLogList({ orderNo: row.orderNo, orderType: 'MACHINING' }).then(({ data }) => {
this.detailLogLoading = false
this.selectedOrderLogList = data && data.code === 0 ? (data.rows || []) : []
}).catch(() => {
this.detailLogLoading = false
this.selectedOrderLogList = []
})
},
resetQuery() {
this.searchData = { modelNo: '', status: '', planStartDate: '', planEndDate: '', page: 1, limit: 20 }
this.searchTable('Y')
},
openEditDialog(row) {
this.saveHeaderData = row
? { ...row, autoAssignAllUsers: !!row.autoAssignAllUsers, nodeReportMode: row.nodeReportMode || 'PARALLEL' }
: { orderNo: '', modelNo: '', taskQty: 1, reportQty: 0, planFinishDate: '', status: '已排产', autoAssignAllUsers: true, nodeReportMode: 'PARALLEL', nodeList: [] }
this.setUp.reviewFlag = true
},
saveTask() {
if (!this.saveHeaderData.modelNo) return this.$message.warning('请先填写物料号')
if (!this.saveHeaderData.taskQty || Number(this.saveHeaderData.taskQty) <= 0) return this.$message.warning('请输入有效的计划数量')
if (!this.saveHeaderData.planFinishDate) return this.$message.warning('请选择计划完工日期')
const payload = {
...this.saveHeaderData,
projectNo: this.saveHeaderData.modelNo,
nodeList: this.saveHeaderData.nodeList && this.saveHeaderData.nodeList.length
? this.saveHeaderData.nodeList
: [{ nodeCode: 'machiningProduction', nodeName: '机加工生产', status: '未开始' }]
}
this.setUp.saveButton = true
saveMachiningTask(payload).then(({ data }) => {
this.setUp.saveButton = false
if (data && data.code === 0) {
this.$message.success(data.msg || '保存成功')
this.setUp.reviewFlag = false
this.searchTable()
} else this.$message.error(data.msg || '保存失败')
}).catch(() => {
this.setUp.saveButton = false
const orderNo = this.saveHeaderData.orderNo || String(Date.now())
const index = this.dataList.findIndex(item => item.orderNo === orderNo)
const saveData = this.normalizeRow({
...payload,
orderNo: orderNo
})
if (index > -1) this.$set(this.dataList, index, saveData)
else this.dataList.unshift(saveData)
this.totalPage = this.dataList.length
this.setUp.reviewFlag = false
this.$message.success('后端未完成,已在前端演示保存')
})
},
openReportDialog(row) {
const defaultNode = (row.nodeList || []).find(item => item.status !== '已完成') || {}
this.reportData = {
orderNo: row.orderNo,
taskNo: row.orderNo,
nodeCode: defaultNode.nodeCode || 'machiningProduction',
reportQty: '',
remark: ''
}
this.setUp.reportFlag = true
},
openAssignDialog(row) {
if (!row.orderNo) return this.$message.warning('请先保存任务单后再分配人员')
this.currentAssignOrder = { orderNo: row.orderNo, orderType: 'MACHINING' }
getNodeAssigneeList({ orderNo: row.orderNo, orderType: 'MACHINING' }).then(({ data }) => {
const assignRows = data && data.code === 0 ? (data.rows || []) : []
this.assignNodeList = assignRows.map(item => ({ ...item, assigneeUserIdList: item.assigneeUserIdList || [], userOptions: [] }))
const requests = this.assignNodeList.map(item =>
getNodeAssigneeUsers({ orderType: 'MACHINING', nodeCode: item.nodeCode }).then(({ data: userData }) => {
item.userOptions = userData && userData.code === 0 ? (userData.rows || []) : []
}).catch(() => { item.userOptions = [] })
)
Promise.all(requests).finally(() => { this.setUp.assignFlag = true })
}).catch(() => {
this.$message.error('加载节点分配信息失败')
})
},
saveNodeAssigneeAction() {
this.setUp.assignButton = true
const assigneeList = this.assignNodeList.map(item => ({
nodeCode: item.nodeCode,
nodeName: item.nodeName,
assigneeUserIdList: item.assigneeUserIdList || []
}))
saveNodeAssignee({
orderNo: this.currentAssignOrder.orderNo,
orderType: this.currentAssignOrder.orderType,
assigneeList: assigneeList
}).then(({ data }) => {
this.setUp.assignButton = false
if (data && data.code === 0) {
this.$message.success(data.msg || '分配成功')
this.setUp.assignFlag = false
this.searchTable()
} else this.$message.error(data.msg || '分配失败')
}).catch(() => {
this.setUp.assignButton = false
this.$message.error('分配失败')
})
},
submitNodeReport() {
if (!this.reportData.reportQty || Number(this.reportData.reportQty) <= 0) return this.$message.warning('请输入有效报工数量')
if (!this.reportData.nodeCode) this.reportData.nodeCode = 'machiningProduction'
this.setUp.reportButton = true
reportMachiningTaskNode(this.reportData).then(({ data }) => {
this.setUp.reportButton = false
if (data && data.code === 0) {
this.$message.success(data.msg || '报工成功')
this.setUp.reportFlag = false
this.searchTable()
} else this.$message.error(data.msg || '报工失败')
}).catch(() => {
this.setUp.reportButton = false
this.simulateNodeReport(this.reportData.orderNo, this.reportData.nodeCode, this.reportData.reportQty)
this.setUp.reportFlag = false
this.$message.success('后端未完成,已在前端演示节点报工')
})
},
simulateNodeReport(orderNo, nodeCode, qty) {
const row = this.dataList.find(item => item.orderNo === orderNo)
if (!row) return
const node = row.nodeList.find(item => item.nodeCode === nodeCode)
if (!node) return
node.status = '已完成'
row.reportQty = Number(row.reportQty || 0) + Number(qty || 0)
row.status = '进行中'
const nextNode = row.nodeList.find(item => item.status !== '已完成')
row.currentNode = nextNode ? nextNode.nodeName : '全部完成'
row.nodeDoneCount = row.nodeList.filter(item => item.status === '已完成').length
row.finishDate = ''
},
finishTask(row) {
finishMachiningTask({ orderNo: row.orderNo }).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '完工成功')
this.searchTable()
} else this.$message.error(data.msg || '完工失败')
}).catch(() => {
row.status = '已完成'
row.finishDate = this.dayjs().format('YYYY-MM-DD')
row.nodeList = row.nodeList.map(item => ({ ...item, status: '已完成' }))
row.currentNode = '全部完成'
row.nodeDoneCount = row.nodeTotalCount
this.$message.success('后端未完成,已在前端演示完工')
})
},
deleteTask(row) {
this.$confirm('确定删除该任务单吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
deleteMachiningTask({ orderNo: row.orderNo }).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success(data.msg || '删除成功')
this.searchTable()
} else this.$message.error(data.msg || '删除失败')
}).catch(() => {
this.dataList = this.dataList.filter(item => item.orderNo !== row.orderNo)
this.totalPage = this.dataList.length
this.$message.success('后端未完成,已在前端演示删除')
})
}).catch(() => {})
},
getStatusType(status) {
const map = { 已排产: 'info', 进行中: 'warning', 已完成: 'success' }
return map[status] || 'info'
},
getStageClass(status) {
if (status === '已完成') return 'done'
if (status === '进行中') return 'processing'
return 'pending'
},
getStageIcon(status) {
if (status === '已完成') return 'el-icon-check'
if (status === '进行中') return 'el-icon-loading'
return 'el-icon-time'
},
getStageTagType(status) {
if (status === '已完成') return 'success'
if (status === '进行中') return 'warning'
return 'info'
},
sizeChangeHandle(val) {
this.pageSize = val
this.pageIndex = 1
this.searchTable()
},
currentChangeHandle(val) {
this.pageIndex = val
this.searchTable()
}
},
computed: {
selectedOrderNodeList() {
return (this.selectedOrder && this.selectedOrder.nodeList) ? this.selectedOrder.nodeList : []
},
selectedOrderProgressPercent() {
const total = this.selectedOrderNodeList.length
if (!total) {
return 0
}
const done = this.selectedOrderNodeList.filter(item => item.status === '已完成').length
return Math.round((done * 100) / total)
}
}
}
</script>
<style scoped>
.data-table {
background-color: #fff;
border-radius: 4px;
}
.data-table >>> .cell {
line-height: 20px;
height: 20px;
}
.data-table >>> .el-table__header-wrapper th,
.data-table >>> .el-table__fixed-header-wrapper th {
background-color: #f5f7fa !important;
color: #333;
font-weight: 600;
border-color: #ebeef5;
padding: 8px 0;
}
.data-table >>> .el-table__header-wrapper .cell,
.data-table >>> .el-table__fixed-header-wrapper .cell,
.data-table >>> .el-table__body-wrapper .cell,
.data-table >>> .el-table__fixed-body-wrapper .cell {
padding: 0 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px !important;
}
.data-table >>> .el-table__body tr:hover > td {
background-color: #f5f7fa !important;
}
.data-table >>> .el-table__body tr.current-row > td {
background-color: #ecf5ff !important;
}
.query-form {
background-color: #fff;
padding: 15px 15px 5px 15px;
border-radius: 4px;
margin-bottom: 12px;
}
.query-form >>> .el-form-item__label {
color: #333;
font-size: 13px;
padding-bottom: 5px;
}
.query-form >>> .el-input__inner {
height: 32px;
line-height: 32px;
border-radius: 4px;
font-size: 13px;
}
.query-form >>> .el-button {
height: 32px;
padding: 0 15px;
font-size: 13px;
border-radius: 4px;
}
.search-btn {
background-color: #ecf5ff;
border-color: #b3d8ff;
color: #409eff;
}
.search-btn:hover {
background-color: #409eff;
border-color: #409eff;
color: #fff;
}
.reset-btn {
background-color: #f5f7fa;
border-color: #d3d4d6;
color: #606266;
}
.reset-btn:hover {
background-color: #909399;
border-color: #909399;
color: #fff;
}
.add-btn {
background-color: #f0f9eb;
border-color: #c2e7b0;
color: #67c23a;
}
.add-btn:hover {
background-color: #67c23a;
border-color: #67c23a;
color: #fff;
}
.dialog-footer {
text-align: right;
}
.edit-form {
margin-left: 5px;
margin-top: -5px;
}
.detail-tabs-wrap {
margin-top: 12px;
background-color: #fff;
border-radius: 4px;
}
.detail-table {
width: 100%;
}
.detail-table >>> .el-table__header-wrapper th,
.detail-table >>> .el-table__fixed-header-wrapper th {
background-color: #f5f7fa !important;
color: #333;
font-weight: 600;
border-color: #ebeef5;
}
.two-column-layout {
display: flex;
gap: 12px;
}
.stages-column {
width: 38%;
min-width: 320px;
border: 1px solid #ebeef5;
border-radius: 4px;
background: #fff;
}
.logs-column {
flex: 1;
border: 1px solid #ebeef5;
border-radius: 4px;
background: #fff;
}
.column-header {
height: 24px;
display: flex;
align-items: center;
gap: 6px;
padding: 0 12px;
border-bottom: 1px solid #ebeef5;
font-weight: 600;
color: #303133;
}
.progress-badge,
.logs-count {
margin-left: auto;
color: #409eff;
font-size: 12px;
font-weight: 500;
}
.stages-list {
max-height: 295px;
overflow-y: auto;
padding: 10px;
}
.stage-item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 3px 8px;
border-radius: 4px;
}
.stage-item + .stage-item {
margin-top: 2px;
}
.stage-item.stage-done {
background: #f0f9eb;
}
.stage-item.stage-processing {
background: #fdf6ec;
}
.stage-item.stage-pending {
background: #f5f7fa;
}
.stage-icon {
width: 22px;
height: 22px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
background: #fff;
border: 1px solid #dcdfe6;
color: #606266;
}
.stage-content {
flex: 1;
}
.stage-name {
font-size: 13px;
color: #303133;
line-height: 20px;
}
.stage-meta {
margin-top: 6px;
display: flex;
align-items: center;
gap: 8px;
}
.stage-owner {
color: #606266;
font-size: 12px;
}
.logs-table-wrapper {
padding: 8px;
}
.el-icon-check {
color: #67c23a;
font-weight: 1000;
}
</style>

9
src/views/modules/longtron/production-plan-renovation-order.vue

@ -65,7 +65,7 @@
<el-table-column label="操作" width="300" align="center" >
<template slot-scope="scope">
<a type="text" @click="openEditDialog(scope.row)" v-if="scope.row.status === '已排产'">修改</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成'">分配人员</a>
<a type="text" @click="openAssignDialog(scope.row)" v-if="scope.row.status !== '已完成' && scope.row.currentNode!=='全部完成'">分配人员</a>
<a type="text" @click="finishOrder(scope.row)" v-if="scope.row.status !== '已完成'">完工</a>
<a type="text" style="color:#F56C6C" @click="deleteOrder(scope.row)" v-if="scope.row.status !== '已完成'">删除</a>
</template>
@ -154,7 +154,7 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12"><el-form-item label="计划发货日期"><el-date-picker v-model="saveHeaderData.planDeliveryDate" type="date" value-format="yyyy-MM-dd" style="width: 100%"></el-date-picker></el-form-item></el-col>
<el-col :span="12"><el-form-item label="状态"><el-select v-model="saveHeaderData.status" style="width: 100%"><el-option label="已排产" value="已排产"></el-option><el-option label="进行中" value="进行中"></el-option><el-option label="已完成" value="已完成"></el-option></el-select></el-form-item></el-col>
<el-col :span="12"><el-form-item label="状态"><el-select disabled v-model="saveHeaderData.status" style="width: 100%"><el-option label="已排产" value="已排产"></el-option><el-option label="进行中" value="进行中"></el-option><el-option label="已完成" value="已完成"></el-option></el-select></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
@ -474,10 +474,7 @@ export default {
const nextNode = row.nodeList.find(item => item.status !== '已完成')
row.currentNode = nextNode ? nextNode.nodeName : '全部完成'
row.nodeDoneCount = row.nodeList.filter(item => item.status === '已完成').length
if (!nextNode) {
row.status = '已完成'
row.finishDate = this.dayjs().format('YYYY-MM-DD')
}
row.finishDate = ''
},
finishOrder(row) {
finishRenovationOrder({ orderNo: row.orderNo }).then(({data}) => {

75
src/views/modules/longtron/production-work-report.vue

@ -5,7 +5,7 @@
<h2 class="page-title">
<i class="el-icon-s-order"></i> 生产报工
</h2>
<p class="page-subtitle">家用电梯 / 线缆COP / 改造项目节点报工管理</p>
<p class="page-subtitle">家用电梯 / 线缆COP / 改造项目 / 机加工生产节点报工管理</p>
</div>
<div class="header-right">
<div class="stat-cards">
@ -44,6 +44,7 @@
<el-option label="家用电梯" value="HOME_LIFT"></el-option>
<el-option label="线缆COP" value="CABLE_COP"></el-option>
<el-option label="改造项目" value="RENOVATION"></el-option>
<el-option label="机加工生产" value="MACHINING"></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态">
@ -103,7 +104,7 @@
<div class="card-details">
<div class="detail-row">
<span class="detail-label"><i class="el-icon-goods"></i> 型号</span>
<span class="detail-label"><i class="el-icon-goods"></i> {{ getModelFieldLabel(item.orderType) }}</span>
<span class="detail-value">{{ item.modelNo }}</span>
</div>
<div class="detail-row">
@ -133,7 +134,7 @@
type="primary"
plain
:disabled="node.status === '已完成' || !canReportNode(item, node)"
@click="directReportNode(item, node)">
@click="handleReportNode(item, node)">
报工
</el-button>
</div>
@ -171,7 +172,7 @@
<el-dialog
title="节点报工"
:visible.sync="reportDialogVisible"
width="520px"
width="400px"
:close-on-click-modal="false"
v-drag>
<el-form :model="reportData" label-position="top">
@ -182,30 +183,25 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报工节点">
<el-input v-model="reportData.nodeName" disabled></el-input>
<el-form-item label="报工人员">
<el-input v-model="reportData.reportBy" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="12">
<el-col :span="12">
<el-row :gutter="24">
<el-col :span="24">
<el-form-item label="报工数量" required>
<el-input v-model="reportData.reportQty" style="width: 100%"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报工人员">
<el-input v-model="reportData.reportBy" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="报工备注">
<el-input v-model="reportData.remark" type="textarea" :rows="3" placeholder="请输入报工说明"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="reportDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="reportLoading" @click="submitNodeReport">
<el-button size="mini" class="reset-btn"
plain @click="reportDialogVisible = false">取消</el-button>
<el-button size="mini"
type="primary"
plain :loading="reportLoading" @click="submitNodeReport">
{{ reportLoading ? '提交中...' : '确认报工' }}
</el-button>
</div>
@ -243,7 +239,7 @@
</template>
<script>
import { getWorkReportOrderList, reportCableCopTaskNode, reportHomeLiftOrderNode, reportRenovationOrderNode } from '@/api/longchuang/productionPlan'
import { getWorkReportOrderList, reportCableCopTaskNode, reportHomeLiftOrderNode, reportMachiningTaskNode, reportRenovationOrderNode } from '@/api/longchuang/productionPlan'
export default {
name: 'ProductionWorkReport',
@ -340,10 +336,14 @@ export default {
const map = {
HOME_LIFT: '家用电梯',
CABLE_COP: '线缆COP',
RENOVATION: 'VL2.5升级'
RENOVATION: 'VL2.5升级',
MACHINING: '机加工生产'
}
return map[orderType] || orderType || '-'
},
getModelFieldLabel(orderType) {
return orderType === 'MACHINING' ? '物料号' : '型号'
},
resetQuery() {
this.searchData = {
projectNo: '',
@ -360,7 +360,8 @@ export default {
const tagMap = {
HOME_LIFT: 'primary',
CABLE_COP: 'warning',
RENOVATION: 'success'
RENOVATION: 'success',
MACHINING: 'danger'
}
return tagMap[type] || 'info'
},
@ -398,6 +399,13 @@ export default {
}
return !!order.currentNodeCode && order.currentNodeCode === node.nodeCode
},
handleReportNode(order, node) {
if (order && order.orderType === 'MACHINING') {
this.openReportDialog(order, node, true)
return
}
this.directReportNode(order, node)
},
directReportNode(order, node) {
this.reportData = {
orderNo: order.orderNo,
@ -411,14 +419,14 @@ export default {
}
this.submitNodeReport()
},
openReportDialog(order, node) {
openReportDialog(order, node, forceManualQty = false) {
this.reportData = {
orderNo: order.orderNo,
orderType: order.orderType,
nodeCode: node.nodeCode,
projectNo: order.projectNo,
nodeName: node.nodeName,
reportQty: 1,
reportQty: forceManualQty ? '' : 1,
reportBy: this.$store.state.user.userDisplay || this.$store.state.user.name || '当前用户',
remark: ''
}
@ -429,10 +437,18 @@ export default {
this.$message.warning('请选择报工节点')
return
}
if (['CABLE_COP', 'MACHINING'].includes(this.reportData.orderType)) {
const qty = Number(this.reportData.reportQty)
if (!Number.isFinite(qty) || qty <= 0) {
this.$message.warning('请填写大于0的实际生产数量')
return
}
}
const apiMap = {
HOME_LIFT: reportHomeLiftOrderNode,
CABLE_COP: reportCableCopTaskNode,
RENOVATION: reportRenovationOrderNode
RENOVATION: reportRenovationOrderNode,
MACHINING: reportMachiningTaskNode
}
const apiFn = apiMap[this.reportData.orderType]
if (!apiFn) {
@ -865,4 +881,15 @@ export default {
.status-success {
color: #67C23A;
}
.reset-btn {
background-color: #f5f7fa;
border-color: #d3d4d6;
color: #606266;
}
.reset-btn:hover {
background-color: #909399;
border-color: #909399;
color: #fff;
}
</style>

132
src/views/modules/longtron/screen-machining-progress.vue

@ -0,0 +1,132 @@
<template>
<div class="screen-wrap">
<div class="top-bar">
<div class="header-left"><img class="site-navbar__brand-logo" src="~@/assets/img/lc.png" alt="龙闯电梯"></div>
<div class="header-center">
<div class="title">机加工生产进度看板</div>
</div>
<div class="tools">
<span class="time">{{ currentTime }}</span>
</div>
</div>
<div class="kpi-row">
<div class="kpi-card"><div class="kpi-label">排产任务</div><div class="kpi-value">{{ kpi.total }}</div></div>
<div class="kpi-card"><div class="kpi-label">进行中</div><div class="kpi-value warning">{{ kpi.processing }}</div></div>
<div class="kpi-card"><div class="kpi-label">已完成</div><div class="kpi-value success">{{ kpi.finished }}</div></div>
<div class="kpi-card"><div class="kpi-label">完工达成率</div><div class="kpi-value highlight">{{ kpi.finishRate }}%</div></div>
</div>
<el-table class="board-table" :data="boardList" :height="tableHeight" border stripe>
<el-table-column type="index" label="序号" width="70" align="center"></el-table-column>
<el-table-column prop="modelNo" label="物料号" min-width="180" align="center"></el-table-column>
<el-table-column prop="taskQty" label="计划数量" min-width="130" align="center"></el-table-column>
<el-table-column prop="reportQty" label="实际数量" min-width="130" align="center"></el-table-column>
<el-table-column prop="planFinishDate" label="计划完工日期" min-width="170" align="center"></el-table-column>
<el-table-column prop="finishDate" label="实际完工日期" min-width="170" align="center">
<template slot-scope="scope">{{ scope.row.finishDate || '-' }}</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getMachiningTaskList } from '@/api/longchuang/productionPlan'
export default {
name: 'ScreenMachiningProgress',
data() {
return {
loading: false,
boardTimerId: null,
tableHeight: 640,
currentTime: '',
timerId: null,
boardList: [],
kpi: { total: 0, processing: 0, finished: 0, finishRate: 0 }
}
},
mounted() {
this.setTableHeight()
this.loadBoardData()
this.updateTime()
this.timerId = setInterval(this.updateTime, 1000)
this.boardTimerId = setInterval(() => {
this.loadBoardData()
}, 10000)
window.addEventListener('resize', this.setTableHeight)
},
beforeDestroy() {
if (this.timerId) clearInterval(this.timerId)
if (this.boardTimerId) clearInterval(this.boardTimerId)
window.removeEventListener('resize', this.setTableHeight)
},
methods: {
setTableHeight() {
this.tableHeight = Math.max(420, window.innerHeight - 220)
},
loadBoardData() {
if (this.loading) return
this.loading = true
getMachiningTaskList({ page: 1, limit: 300, statusList: ['已排产', '进行中', '已完成'] }).then(({ data }) => {
this.loading = false
const source = (data && data.code === 0 && data.page && data.page.list) ? data.page.list : this.getMockList()
this.boardList = this.buildBoardList(source)
this.buildKpi()
}).catch(() => {
this.loading = false
this.boardList = this.buildBoardList(this.getMockList())
this.buildKpi()
})
},
buildBoardList(sourceList) {
const statusAllow = ['已排产', '进行中', '已完成']
return (sourceList || []).filter(item => statusAllow.includes(item.status)).map(item => ({
...item,
taskQty: item.taskQty == null ? 0 : item.taskQty,
reportQty: item.reportQty == null ? 0 : item.reportQty
}))
},
buildKpi() {
const total = this.boardList.length
const processing = this.boardList.filter(item => item.status === '进行中').length
const finished = this.boardList.filter(item => item.status === '已完成').length
this.kpi = { total, processing, finished, finishRate: total ? Math.round((finished / total) * 100) : 0 }
},
updateTime() {
const now = new Date()
const weekList = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const d = this.dayjs(now)
this.currentTime = `${d.format('YYYY/MM/DD')} ${weekList[now.getDay()]} ${d.format('HH:mm:ss')}`
},
getMockList() {
return []
}
}
}
</script>
<style>
.screen-wrap{height:100vh;padding:16px;background:linear-gradient(165deg,#0a1f36 0%,#0f2b47 50%,#0a2037 100%);display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden}
.top-bar{display:flex;justify-content:space-between;align-items:center;padding:14px 18px;border-radius:12px;border:1px solid rgba(109,167,219,.24);background:rgba(9,29,49,.82)}
.top-bar{position:relative}
.header-left{display:flex;align-items:center;min-width:110px;z-index:2}
.header-center{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);text-align:center;pointer-events:none;max-width:70%;width:auto;padding:6px 24px 8px;border-radius:8px;border:1px solid rgba(96,170,232,.34);background:linear-gradient(180deg,rgba(33,73,116,.52),rgba(16,44,77,.42))}
.header-center::before{content:'';position:absolute;left:50%;transform:translateX(-50%);top:-8px;width:68%;height:1px;background:linear-gradient(90deg,rgba(87,164,230,0),rgba(87,164,230,.9),rgba(87,164,230,0))}
.top-bar .tools{margin-left:auto;z-index:2}
.title{color:#8fe7ff;font-size:30px;font-weight:800;letter-spacing:3px;line-height:1.05;text-shadow:0 0 14px rgba(79,179,255,.36)}
.tools{display:flex;align-items:center;gap:12px}.time{color:#89d7ff;font-size:20px;font-weight:600}
.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:12px 0 10px}
.kpi-card{border-radius:10px;padding:12px 14px;background:rgba(14,43,70,.82);border:1px solid rgba(101,157,209,.22)}
.kpi-label{color:#b7d3ee;font-size:13px}.kpi-value{margin-top:6px;font-size:30px;font-weight:700;color:#edf6ff}
.kpi-value.warning{color:#ffd166}.kpi-value.success{color:#74dfa3}.kpi-value.highlight{color:#79d5ff}
.board-table{border-radius:10px;overflow:hidden;border:1px solid rgba(86,140,190,.35);flex:1;min-height:0}
.board-table .cell{line-height:30px;font-size:16px;height:30px}
.screen-wrap .board-table .el-table,.screen-wrap .board-table .el-table__expanded-cell,.screen-wrap .board-table .el-table__body-wrapper,.screen-wrap .board-table .el-table__empty-block,.screen-wrap .board-table .el-table__fixed-body-wrapper{background:rgba(12,39,64,.96)!important;color:#fff!important}
.screen-wrap .board-table .el-table__header-wrapper th,.screen-wrap .board-table .el-table__fixed-header-wrapper th{background:#123a5e!important;color:#d9e9f8!important;border-color:rgba(80,133,181,.6)!important;font-size:14px!important;padding:12px 0!important}
.screen-wrap .board-table .el-table__body tr>td,.screen-wrap .board-table .el-table__fixed-body-wrapper tr>td,.screen-wrap .board-table .el-table__fixed-right .el-table__fixed-body-wrapper tr>td{background:rgba(20,52,83,.96)!important;border-color:rgba(88,139,187,.4)!important;color:#fff!important;height:46px!important;vertical-align:middle!important}
.screen-wrap .board-table .el-table--striped .el-table__body tr.el-table__row--striped>td,.screen-wrap .board-table .el-table__fixed-body-wrapper tr.el-table__row--striped>td{background:rgba(29,66,102,.96)!important}
.screen-wrap .board-table .el-table--enable-row-hover .el-table__body tr:hover>td,.screen-wrap .board-table .el-table__fixed-body-wrapper tr:hover>td{background:rgba(39,81,123,.96)!important}
.screen-wrap .board-table .el-table .cell{color:#fff!important;line-height:24px!important;overflow:visible!important}
.screen-wrap .board-table .el-table__empty-text{color:#9ac2e7!important}
</style>
Loading…
Cancel
Save