This commit is contained in:
2026-10-26 13:43:20 +08:00
parent 3ffa706b89
commit fe6d925e7c
5 changed files with 52 additions and 19 deletions
@@ -10,7 +10,7 @@ import QueryToolbar, { type QueryField, type QueryModel } from '@/components/com
import type { TableAction } from '@/components/common/tableActions'
import ProcurementDetailPanel from '../components/ProcurementDetailPanel.vue'
import { createProcurement, getProcurement, listProcurements, type ProcurementDetail, type ProcurementSummary } from '../api/procurement'
import { buildProcurementCreate, dateTime, draftBudgetTotal, emptyProcurementDraft, money, procurementStatuses, statusLabel, statusTone } from '../procurementPresentation'
import { procurementDirections, directionLabel, regionText, buildProcurementCreate, dateTime, draftBudgetTotal, emptyProcurementDraft, money, procurementStatuses, statusLabel, statusTone } from '../procurementPresentation'
import { procurementRequestKey } from '../procurementSubmission'
const props = withDefaults(defineProps<{ createPage?: boolean; detailPage?: boolean }>(), { createPage: false, detailPage: false })
@@ -35,10 +35,11 @@ const queryModel = computed<QueryModel>({
const queryFields: QueryField[] = [
{ key: 'orderNo', label: '采购单号', type: 'input' }, { key: 'purchaseCategory', label: '采购品类', type: 'input' },
{ key: 'productName', label: '商品名称', type: 'input' },
{ key: 'status', label: '履约进度', type: 'select', options: Object.entries(procurementStatuses).map(([value, label]) => ({ value, label })) },
{ key: 'status', label: '履约进度', type: 'select', options: Object.entries(procurementStatuses).map(([value, label]) => ({ value, label: ({ WAIT_OVERSEAS_RECEIPT: '待起运仓收货', OVERSEAS_RECEIVING: '起运地收货中', WAIT_OVERSEAS_SHIPMENT: '待国际交寄', DOMESTIC_RECEIVING: '目的地收货中', WAIT_CHARGES: '待目的地核费' } as Record<string, string>)[value] || label })) },
]
const columns: DataTableColumn[] = [
{ key: 'actions', label: '操作', width: 90, fixed: 'left', slotName: 'actions' },
{ prop: 'procurementDirection', label: '采购方向', minWidth: 170, slotName: 'direction' },
{ prop: 'orderNo', label: '采购单号', minWidth: 250, slotName: 'orderNo' },
{ prop: 'purchaseCategory', label: '采购品类', width: 120 }, { prop: 'productName', label: '商品名称', minWidth: 200 },
{ prop: 'productSpecification', label: '商品规格', minWidth: 160 }, { prop: 'purchaseQuantity', label: '采购数量(件)', width: 135 },
@@ -104,23 +105,25 @@ onBeforeUnmount(() => { active = false; ++requestSequence })
<template v-if="error" #error><div class="procurement-error" role="alert"><span>{{ error }}</span><el-button :disabled="loading" @click="loadList">重新加载</el-button></div></template>
<template #orderNo="{ row }"><button class="procurement-link" type="button" @click="openDetail(row as ProcurementSummary)">{{ (row as ProcurementSummary).orderNo || '—' }}</button></template>
<template #budget="{ row }">{{ money((row as ProcurementSummary).budgetUnitPrice, (row as ProcurementSummary).currency) }}</template>
<template #status="{ row }"><el-tag :type="statusTone((row as ProcurementSummary).status)" size="small">{{ statusLabel((row as ProcurementSummary).status) }}</el-tag></template>
<template #direction="{ row }">{{ directionLabel((row as ProcurementSummary).procurementDirection) }}</template>
<template #status="{ row }"><el-tag :type="statusTone((row as ProcurementSummary).status)" size="small">{{ statusLabel((row as ProcurementSummary).status, (row as ProcurementSummary).procurementDirection) }}</el-tag></template>
<template #createdAt="{ row }">{{ dateTime((row as ProcurementSummary).createdAt) }}</template>
</DataTable>
</div>
</template>
<section v-else-if="mode === 'detail'" v-loading="loading" class="procurement-detail" aria-label="采购订单详情">
<header class="procurement-heading"><div><el-button link type="primary" @click="returnToList">← 返回列表</el-button><h2>{{ detail?.order.orderNo || '采购订单详情' }}</h2></div><div><el-tag v-if="detail" :type="statusTone(detail.order.status)">{{ statusLabel(detail.order.status) }}</el-tag><el-button :disabled="loading" @click="loadDetail">刷新</el-button></div></header>
<header class="procurement-heading"><div><el-button link type="primary" @click="returnToList">← 返回列表</el-button><h2>{{ detail?.order.orderNo || '采购订单详情' }}</h2></div><div><el-tag v-if="detail" :type="statusTone(detail.order.status)">{{ statusLabel(detail.order.status, detail.order.procurementDirection) }}</el-tag><el-button :disabled="loading" @click="loadDetail">刷新</el-button></div></header>
<div v-if="error" class="procurement-error" role="alert"><span>{{ error }}</span><el-button :disabled="loading" @click="loadDetail">重新加载</el-button></div>
<ProcurementDetailPanel v-else-if="detail" :detail="detail" /><el-skeleton v-else :rows="8" animated />
</section>
<section v-else class="procurement-create" aria-label="采购下单">
<header class="procurement-heading"><div><h2>海外采购下单</h2><p>一单一个商品及规格;预算仅授权样品货款,运费及关税另行核定。</p></div><el-button v-if="canList" @click="returnToList">返回列表</el-button></header>
<header class="procurement-heading"><div><h2>采购下单</h2><p>一单一个商品及规格;预算仅授权样品货款,运费及关税另行核定。</p></div><el-button v-if="canList" @click="returnToList">返回列表</el-button></header>
<el-result v-if="!canCreate" icon="warning" title="没有采购下单权限" sub-title="请联系企业管理员配置权限" />
<el-result v-else-if="submittedOrder" icon="success" title="采购订单已提交" :sub-title="submittedOrder"><template #extra><el-button @click="resetForm">新建另一单</el-button></template></el-result>
<template v-else>
<el-alert v-if="submitError" class="submit-error" :title="submitError" type="error" :closable="false" />
<el-form :model="form" label-position="top" :disabled="submitting" @submit.prevent="submit">
<el-form-item label="采购方向" required><el-select v-model="form.procurementDirection"><el-option v-for="(label, value) in procurementDirections" :key="value" :label="label" :value="value" /></el-select></el-form-item>
<h3>商品与预算</h3><div class="procurement-form-grid">
<el-form-item label="采购品类"><el-input v-model.trim="form.purchaseCategory" maxlength="128" placeholder="" /></el-form-item>
<el-form-item label="商品名称" required><el-input v-model.trim="form.productName" maxlength="255" placeholder="" /></el-form-item>
@@ -130,10 +133,10 @@ onBeforeUnmount(() => { active = false; ++requestSequence })
<el-form-item label="预算币种" required><el-select v-model="form.currency"><el-option label="美元 USD" value="USD" /><el-option label="人民币 CNY" value="CNY" /></el-select></el-form-item>
<el-form-item class="full" label="商品链接"><el-input v-model.trim="form.productUrl" maxlength="2000" placeholder="https://…" /></el-form-item>
</div><p class="procurement-hint">货款预算总上限:<strong>{{ money(draftBudgetTotal(form), form.currency) }}</strong>。零预算仅授权免费样品;实际货款按供应商实付核定。</p>
<h3>最终国内收件资料</h3><div class="procurement-form-grid">
<h3>{{ regionText('最终国内收件资料', form.procurementDirection) }}</h3><div class="procurement-form-grid">
<el-form-item label="收件人" required><el-input v-model.trim="form.contactName" maxlength="128" placeholder="实际收件人姓名" /></el-form-item>
<el-form-item label="联系电话" required><el-input v-model.trim="form.contactPhone" maxlength="64" type="tel" placeholder="快递可联系的电话" /></el-form-item>
<el-form-item class="full" label="完整国内地址" required><el-input v-model.trim="form.receivingAddress" maxlength="1000" placeholder="省、市、区县、街道及详细门牌" /></el-form-item>
<el-form-item class="full" :label="regionText('完整国内地址', form.procurementDirection)" required><el-input v-model.trim="form.receivingAddress" maxlength="1000" :placeholder="form.procurementDirection === 'DOMESTIC_TO_OVERSEAS' ? '国家、州/省、市、邮编及详细地址' : '省、市、区县、街道及详细门牌'" /></el-form-item>
<el-form-item class="full" label="采购要求"><el-input v-model="form.remark" type="textarea" :rows="3" maxlength="1000" show-word-limit placeholder="" /></el-form-item>
</div>
</el-form>