feat(production): add production work order management page
This commit is contained in:
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>
|
||||||
Reference in new issue
Block a user