feat(production): add production work order management page

This commit is contained in:
zlwu committed 2026-05-20 00:59:51 +08:00
1 parent eec59de5dc
commit f464c22b9e
1 file changed
+206
@@ -0,0 +1,206 @@
<!-- 生产管理 — 入库生产工单 -->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<div class="page-container">
<header class="page-head">
<h1>入库生产工单</h1>
<p class="page-desc">入库生产工单管理,查看工单详情并完成待配置工单。</p>
</header>
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">工单列表</h2>
</div>
<div class="filter-block">
<el-form :model="searchForm" class="filter-form" @submit.prevent>
<div class="filter-grid">
<el-form-item label="工单号">
<el-input v-model="searchForm.keyword" placeholder="请输入工单号" clearable />
</el-form-item>
<el-form-item label="工单状态">
<el-select v-model="searchForm.workOrderStatus" placeholder="全部" clearable style="width: 100%">
<el-option label="待配置" value="dpz" />
<el-option label="已完成" value="ywc" />
</el-select>
</el-form-item>
</div>
<div class="filter-actions-row">
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
</div>
</div>
</el-form>
</div>
<div class="list-body list-wrap">
<el-table class="list-table" :data="tableData" v-loading="loading" stripe @row-dblclick="handleView">
<el-table-column type="index" label="序号" width="68" align="center" :index="(i) => (pagination.page - 1) * pagination.pageSize + i + 1" />
<el-table-column prop="workOrderNo" label="工单号" min-width="150" align="center" />
<el-table-column prop="protocolNo" label="协议号" min-width="140" align="center" />
<el-table-column prop="sampleCode" label="样本编码" min-width="120" align="center" />
<el-table-column prop="receptionSource" label="来源类型" width="110" align="center">
<template #default="{ row }">
<el-tag :type="sourceTag(row.receptionSource).type" size="small">
{{ row.receptionSourceLabel || sourceTag(row.receptionSource).label }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="workOrderStatus" label="工单状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="woStatusTag(row.workOrderStatus).type" size="small">
{{ woStatusTag(row.workOrderStatus).label }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="170" align="center" />
<el-table-column label="操作" width="280" fixed="right" align="center">
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看详情</el-button>
<el-button
v-if="row.workOrderStatus === 'dpz'"
class="btn-op-item primary"
@click="handleComplete(row)"
>
<el-icon><Check /></el-icon>完成工单
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination list-pager-bar">
<el-pagination
:current-page="pagination.page"
:page-size="pagination.pageSize"
:total="pagination.total"
layout="total, sizes, prev, pager, next"
@size-change="(v) => ((pagination.page = 1), (pagination.pageSize = v), loadData())"
@current-change="(v) => ((pagination.page = v), loadData())"
/>
</div>
</div>
<SystemViewDialog
v-model:visible="viewVisible"
title="工单详情"
:icon="Document"
:meta="detail?.workOrderNo || ''"
:sections="viewSections"
/>
</section>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, RefreshLeft, View, Check, Document } from '@element-plus/icons-vue'
import {
fetchProductionWorkOrderList,
fetchProductionWorkOrderDetail,
fetchCompleteProductionWorkOrder
} from '@/api/production-work-order'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import type { ViewSection } from '@/components/business/system-view-dialog/index.vue'
defineOptions({ name: 'ProductionProductionWorkOrder' })
/* ---- 标签映射 ---- */
const woStatusTag = (status: string) => {
const map: Record<string, { label: string; type: string }> = {
dpz: { label: '待配置', type: 'info' },
ywc: { label: '已完成', type: 'success' }
}
return map[status] || { label: status, type: 'info' }
}
const sourceTag = (source: string) => {
const map: Record<string, { label: string; type: string }> = {
cell_storage: { label: '细胞存储', type: 'success' },
research_donation: { label: '科研捐赠', type: 'primary' }
}
return map[source] || { label: source, type: 'info' }
}
/* ---- 搜索 & 列表 ---- */
const searchForm = reactive({ keyword: '', workOrderStatus: '' })
const tableData = ref<any[]>([])
const loading = ref(false)
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
async function loadData() {
loading.value = true
try {
const res = await fetchProductionWorkOrderList({
page: pagination.page,
pageSize: pagination.pageSize,
keyword: searchForm.keyword || undefined,
workOrderStatus: searchForm.workOrderStatus || undefined
})
tableData.value = res.list || []
pagination.total = res.total ?? 0
} finally {
loading.value = false
}
}
function handleSearch() {
pagination.page = 1
loadData()
}
function handleReset() {
searchForm.keyword = ''
searchForm.workOrderStatus = ''
pagination.page = 1
loadData()
}
/* ---- 查看详情 ---- */
const viewVisible = ref(false)
const detail = ref<any>(null)
const viewSections = computed<ViewSection[]>(() => {
if (!detail.value) return []
const d = detail.value
return [
{
title: '基本信息',
fields: [
{ label: '工单号', value: d.workOrderNo },
{ label: '协议号', value: d.protocolNo },
{ label: '样本编码', value: d.sampleCode },
{
label: '来源类型',
value: sourceTag(d.receptionSource).label,
tagType: sourceTag(d.receptionSource).type as any
},
{
label: '工单状态',
value: woStatusTag(d.workOrderStatus).label,
tagType: woStatusTag(d.workOrderStatus).type as any
},
{ label: '创建时间', value: d.createTime || '—' },
{ label: '备注', value: d.remark || '—', span: true }
]
}
]
})
async function handleView(row: any) {
detail.value = await fetchProductionWorkOrderDetail(row.id)
viewVisible.value = true
}
/* ---- 完成工单 ---- */
async function handleComplete(row: any) {
await ElMessageBox.confirm('确定要完成该工单吗?', '提示', { type: 'warning' })
await fetchCompleteProductionWorkOrder(row.id, {})
ElMessage.success('工单已完成')
loadData()
}
onMounted(() => loadData())
</script>
<style scoped lang="scss"></style>