Files
bj_power/bj_power_mes/frontend/src/pages/DailyPlan.vue
T
SunYF 6ee131a4bd feat: 新增装机绑定功能与权限、BOM工序配置
1.  新增装机绑定实体与相关CRUD逻辑,支持工件工序物料绑定/解绑
2.  为BOM物料新增装配工序字段,支持按工序校验绑定
3.  扩展权限表,新增父权限码字段支持菜单按钮关联
4.  统一各页面帮助弹窗参数,新增角色管理帮助文档
5.  新增公共格式化工具函数,优化侧边栏菜单展开逻辑
6.  新增工位终端绑定代理接口与MES内部绑定API
7.  修复主入口数据库连接与schema初始化逻辑,新增一键迁移工具
2026-09-07 11:58:19 +08:00

141 lines
6.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-card>
<el-form inline>
<el-form-item label="工单号">
<el-select v-model="query.orderNo" filterable allow-create clearable placeholder="请选择/输入工单号" style="width:220px" @change="load">
<el-option v-for="w in workOrders" :key="w.workOrderNo" :label="w.workOrderNo" :value="w.workOrderNo" />
</el-select>
</el-form-item>
<el-form-item label="排产日期">
<el-date-picker v-model="query.planDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择日期" @change="load" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="load">查询</el-button>
<el-button v-if="can('produce.workorder:dailyplan')" type="success" @click="openAdd">新建排产</el-button>
</el-form-item>
</el-form>
<el-table :data="list" border size="small">
<el-table-column prop="orderNo" label="工单号" min-width="180" />
<el-table-column prop="planDate" label="排产日期" width="120" />
<el-table-column prop="planQty" label="计划数量" width="100" />
<el-table-column prop="completedQty" label="已完成" width="90" />
<el-table-column label="送达接驳台" min-width="150">
<template #default="{ row }">
<el-tag v-for="d in (row.dockCodes||[])" :key="d" size="small" class="dock-tag">{{ d }}</el-tag>
<span v-if="!(row.dockCodes||[]).length" class="dock-empty">未指定</span>
</template>
</el-table-column>
<el-table-column label="执行状态" width="110">
<template #default="{ row }">
<el-tag :type="planStatusTag(row.status)" size="small">{{ statusText(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="operator" label="操作人" min-width="90" />
<el-table-column label="操作" width="160">
<template #default="{ row }">
<el-button v-if="can('produce.workorder:dailyplan')" size="small" @click="openEdit(row)">编辑</el-button>
<el-button v-if="can('produce.workorder:dailyplan')" size="small" type="danger" @click="del(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="dialog.show" title="新建/编辑排产" width="520px">
<el-form :model="dialog" label-width="90px">
<el-form-item label="工单号">
<el-select v-model="dialog.orderNo" filterable allow-create placeholder="请选择/输入工单号" style="width:100%" @change="loadSuggest">
<el-option v-for="w in workOrders" :key="w.workOrderNo" :label="w.workOrderNo" :value="w.workOrderNo" />
</el-select>
</el-form-item>
<el-form-item label="排产日期">
<el-date-picker v-model="dialog.planDate" type="date" value-format="YYYY-MM-DD" style="width:100%" />
</el-form-item>
<el-form-item label="计划数量">
<el-input-number v-model="dialog.planQty" :min="1" style="width:100%" />
</el-form-item>
<el-form-item label="送达接驳台" prop="dockCodes">
<el-select v-model="dialog.dockCodes" multiple filterable clearable placeholder="该工单物料送达哪些接驳台(可多选)" style="width:100%">
<el-option-group label="产线接驳台(DOCK n↔工位n)">
<el-option v-for="n in 20" :key="n" :label="`DOCK${String(n).padStart(2,'0')} · 工位${n}`" :value="`DOCK${String(n).padStart(2,'0')}`" />
</el-option-group>
<el-option-group label="库房">
<el-option label="DOCK21 · 库房收货" value="DOCK21" />
</el-option-group>
</el-select>
<div class="dock-tip">选需送达的接驳台建议为当前工单上次使用的接驳台</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialog.show=false">取消</el-button>
<el-button v-if="can('produce.workorder:dailyplan')" type="primary" @click="save">保存</el-button>
</template>
</el-dialog>
</el-card>
<PageHelp :data="helpDailyPlan" page="DailyPlan" />
</template>
<style scoped>
.dock-tag { margin-right: 4px; }
.dock-empty { color: #999; font-size: 12px; }
.dock-tip { width: 100%; font-size: 12px; color: #888780; line-height: 1.5; }
</style>
<script setup>
import { reactive, ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '../utils/request'
import { can } from '../utils/perm'
import PageHelp from '../components/PageHelp.vue'
import { helpDailyPlan } from '../help'
const query = reactive({ orderNo: '', planDate: '' })
const list = ref([])
const workOrders = ref([])
const dialog = reactive({ show: false, id: 0, orderNo: '', planDate: '', planQty: 1, dockCodes: [] })
const dockOptions = [...Array.from({ length: 20 }, (_, i) => `DOCK${String(i + 1).padStart(2, '0')}`), 'DOCK21']
const statusOptions = [
{ v: 'PENDING', l: '待执行' }, { v: 'PROCESSING', l: '执行中' },
{ v: 'DONE', l: '已完成' }, { v: 'CANCELLED', l: '已取消' }
]
const statusText = (s) => (statusOptions.find((x) => x.v === s) || {}).l || s
const planStatusTag = (s) =>
s === 'DONE' ? 'success' : s === 'CANCELLED' ? 'info' : s === 'PROCESSING' ? 'warning' : 'primary'
async function load() {
list.value = (await request.get('/daily-plans', { params: query })) || []
}
// 推荐:该工单上次使用的接驳台
async function loadSuggest() {
if (!dialog.orderNo) return
try {
const d = await request.get('/daily-plans/suggest-docks', { params: { orderNo: dialog.orderNo } })
dialog.dockCodes = d?.dockCodes || []
} catch { dialog.dockCodes = [] }
}
function openAdd() {
Object.assign(dialog, { show: true, id: 0, orderNo: '', planDate: new Date().toISOString().slice(0, 10), planQty: 1, dockCodes: [] })
}
function openEdit(row) {
Object.assign(dialog, { show: true, id: row.id, orderNo: row.orderNo, planDate: row.planDate, planQty: row.planQty, dockCodes: row.dockCodes || [] })
}
async function save() {
if (!dialog.orderNo || !dialog.planDate) return ElMessage.warning('请选择工单号和排产日期')
if (!dialog.dockCodes.length) return ElMessage.warning('请确认送达接驳台(AGV 配送目标)')
const payload = { orderNo: dialog.orderNo, planDate: dialog.planDate, planQty: dialog.planQty, dockCodes: dialog.dockCodes }
if (dialog.id) await request.put(`/daily-plans/${dialog.id}`, payload)
else await request.post('/daily-plans', payload)
ElMessage.success('保存成功')
dialog.show = false
load()
}
async function del(row) {
await ElMessageBox.confirm('确认删除该排产?', '提示', { type: 'warning' })
await request.delete(`/daily-plans/${row.id}`)
load()
}
onMounted(async () => {
workOrders.value = (await request.get('/work-orders')) || []
load()
})
</script>