mirror of
https://github.com/huge-dream/django-vue3-admin.git
synced 2026-10-02 16:37:50 +00:00
新增 杂采比议价、询价履历记录 实现;调整部分ui效果
This commit is contained in:
@@ -10,6 +10,27 @@ export const DelObj = (id: string | number) => request({ url: baseUrl + id + '/'
|
||||
export const ConfirmObj = (id: string | number) => request({ url: `${baseUrl}${id}/confirm/`, method: 'put' })
|
||||
export const RestoreObj = (id: string | number) => request({ url: `${baseUrl}${id}/restore/`, method: 'put' })
|
||||
export const PublishObj = (id: string | number) => request({ url: `${baseUrl}${id}/publish/`, method: 'put' })
|
||||
export const StartBargainingObj = (id: string | number) => request({ url: `${baseUrl}${id}/start_bargaining/`, method: 'put' })
|
||||
export const ConfirmNegotiationObj = (id: string | number) => request({ url: `${baseUrl}${id}/confirm_negotiation/`, method: 'put' })
|
||||
export const SubmitPriceAuditObj = (id: string | number) => request({ url: `${baseUrl}${id}/submit_price_audit/`, method: 'put' })
|
||||
/** 查询杂采议价记录(比价议价价格存此表,非报价明细「中标价格」) */
|
||||
export const GetNegotiationRecordsObj = (id: string | number, params: { part_id?: string }) =>
|
||||
request({ url: `${baseUrl}${id}/negotiation_records/`, method: 'get', params })
|
||||
/** 保存比价中的议价后价格、中标否至杂采议价记录表 */
|
||||
export const SaveNegotiationRecordsObj = (
|
||||
id: string | number,
|
||||
data: {
|
||||
part_id: string
|
||||
records: {
|
||||
quotation_no: string
|
||||
supplier_code?: string
|
||||
is_awarded: number
|
||||
bargaining_price: number | null
|
||||
total_price_excl_tax?: number | null
|
||||
total_price_incl_tax?: number | null
|
||||
}[]
|
||||
}
|
||||
) => request({ url: `${baseUrl}${id}/save_negotiation_records/`, method: 'put', data })
|
||||
export const UploadFile = (data: FormData) =>
|
||||
request({
|
||||
url: '/api/system/file/',
|
||||
|
||||
@@ -15,6 +15,11 @@ const statusDict = [
|
||||
{ value: 0, label: '作废' }
|
||||
]
|
||||
|
||||
const buyingMethodDict = [
|
||||
{ value: 1, label: '询价' },
|
||||
{ value: 2, label: '招标' }
|
||||
]
|
||||
|
||||
const paymentMethods = [
|
||||
{ value: 1, label: '月结30天' },
|
||||
{ value: 2, label: '月结60天' },
|
||||
@@ -59,8 +64,12 @@ type ExtraHooks = {
|
||||
onAdd?: () => void
|
||||
onEdit?: (row: any) => void
|
||||
onView?: (row: any) => void
|
||||
/** 打开比价/议价弹窗(比议价中、价格审核、核价通过);保存时按报价单写入杂采议价记录(议价前总价快照等) */
|
||||
onComparison?: (row: any) => void
|
||||
/** 列表多选变化(用于后续多询价单比价等) */
|
||||
onTableSelectionChange?: (rows: any[]) => void
|
||||
/** 与勾选列同步:由页面 ref 维护当前选中行,工具栏按钮据此取行(fast-crud 的 tableRef 往往拿不到 selection) */
|
||||
getTableSelection?: () => any[]
|
||||
}
|
||||
|
||||
const STATUS_OPEN = 1
|
||||
@@ -97,6 +106,10 @@ const getRowStatus = (row: any) => Number(row?.status)
|
||||
const isOpenStatus = (row: any) => getRowStatus(row) === STATUS_OPEN
|
||||
const isConfirmedStatus = (row: any) => getRowStatus(row) === STATUS_CONFIRMED
|
||||
const canPublishStatus = (row: any) => isConfirmedStatus(row)
|
||||
/** 报价中(4)、报价结束(5) 可开启比价 */
|
||||
const isQuotingOrEndedStatus = (row: any) => [4, 5].includes(getRowStatus(row))
|
||||
/** 比议价中(6)、价格审核(7)、核价通过(8) 可打开比价窗口 */
|
||||
const canOpenComparison = (row: any) => [6, 7, 8].includes(getRowStatus(row))
|
||||
const getErrorMessage = (err: any, fallback: string) => formatRfqApiErrorMessage(err, fallback)
|
||||
|
||||
/** 列表行含 `suppliers` 时可先做提示;未返回嵌套时交由接口校验 */
|
||||
@@ -106,12 +119,12 @@ const rowHasSuppliersList = (row: any): boolean | null => {
|
||||
return list.length > 0
|
||||
}
|
||||
|
||||
/** 成本模板版本号两位展示(与 pricetemplate 一致) */
|
||||
export const formatCostTemplateVersionTwoDigits = (v: unknown) => {
|
||||
if (v == null || v === '') return '00'
|
||||
/** 成本模板版本号展示(不做位数补零) */
|
||||
export const formatCostTemplateVersion = (v: unknown) => {
|
||||
if (v == null || v === '') return ''
|
||||
const n = Number(v)
|
||||
if (!Number.isFinite(n)) return String(v)
|
||||
return String(Math.trunc(n)).padStart(2, '0')
|
||||
if (!Number.isFinite(n)) return String(v).trim()
|
||||
return String(Math.trunc(n))
|
||||
}
|
||||
|
||||
export const createCrudOptions = function ({
|
||||
@@ -120,27 +133,23 @@ export const createCrudOptions = function ({
|
||||
onAdd,
|
||||
onEdit,
|
||||
onView,
|
||||
onTableSelectionChange
|
||||
onComparison,
|
||||
onTableSelectionChange,
|
||||
getTableSelection
|
||||
}: Partial<CreateCrudOptionsProps> & ExtraHooks): CreateCrudOptionsRet {
|
||||
void context
|
||||
|
||||
const normalizeSelection = (raw: unknown): any[] => {
|
||||
if (Array.isArray(raw)) return raw
|
||||
if (raw != null && typeof raw === 'object') return [raw as any]
|
||||
return []
|
||||
}
|
||||
|
||||
const getSelectedRows = () => {
|
||||
if (typeof getTableSelection === 'function') {
|
||||
const rows = normalizeSelection(getTableSelection())
|
||||
if (rows.length > 0) return rows
|
||||
const rows = getTableSelection()
|
||||
if (Array.isArray(rows) && rows.length > 0) return rows
|
||||
}
|
||||
const expose = crudExpose as any
|
||||
// Element Plus:当前勾选行(与列表第一列选择列一致)
|
||||
const baseTable = expose?.getBaseTableRef?.()
|
||||
if (baseTable?.getSelectionRows) {
|
||||
const fromEl = normalizeSelection(baseTable.getSelectionRows())
|
||||
if (fromEl.length) return fromEl
|
||||
const fromEl = baseTable.getSelectionRows()
|
||||
if (Array.isArray(fromEl) && fromEl.length) return fromEl
|
||||
}
|
||||
const tableRef: any = expose?.getTableRef?.() || expose?.tableRef
|
||||
const selection =
|
||||
@@ -149,20 +158,20 @@ export const createCrudOptions = function ({
|
||||
tableRef?.getSelections?.() ||
|
||||
tableRef?.getSelected?.() ||
|
||||
[]
|
||||
return normalizeSelection(selection)
|
||||
}
|
||||
if (Array.isArray(selection)) return selection
|
||||
return [] }
|
||||
|
||||
/** 工具栏批量操作:取当前勾选的全部行(与列表选择列一致) */
|
||||
const pickSelectedRows = (): any[] | null => {
|
||||
const pickSelectedRow = (): any | null => {
|
||||
const rows = getSelectedRows()
|
||||
if (!rows.length) {
|
||||
ElMessage.warning('请先选择询价单')
|
||||
return null
|
||||
}
|
||||
// if (rows.length > 1) {
|
||||
// ElMessage.warning('仅支持单条操作')
|
||||
// return null
|
||||
// }
|
||||
if (rows.length > 1) {
|
||||
ElMessage.warning('仅支持单条操作')
|
||||
return null
|
||||
}
|
||||
return rows[0]
|
||||
}
|
||||
|
||||
@@ -208,12 +217,39 @@ export const createCrudOptions = function ({
|
||||
click() {
|
||||
onAdd && onAdd()
|
||||
}
|
||||
}
|
||||
},
|
||||
startBargaining: {
|
||||
show: true,
|
||||
text: '开启比价',
|
||||
order: 2,
|
||||
type: 'warning',
|
||||
async click() {
|
||||
const row = pickSelectedRow()
|
||||
if (!row) return
|
||||
if (!isQuotingOrEndedStatus(row)) {
|
||||
ElMessage.warning('仅报价中或报价结束状态可开启比价')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确认将状态改为【比议价中】?', '提示', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
await api.StartBargainingObj(row.id)
|
||||
onComparison && onComparison(row)
|
||||
crudExpose?.doRefresh?.()
|
||||
} catch (err: any) {
|
||||
if (err === 'cancel' || err === 'close') return
|
||||
ElMessage.error(getErrorMessage(err, '开启比价失败'))
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
rowHandle: {
|
||||
fixed: 'right',
|
||||
width: 420,
|
||||
width: 500,
|
||||
buttons: {
|
||||
view: { show: false },
|
||||
edit: { show: false },
|
||||
@@ -321,6 +357,17 @@ export const createCrudOptions = function ({
|
||||
throw err
|
||||
}
|
||||
}
|
||||
},
|
||||
viewComparison: {
|
||||
text: '比价',
|
||||
type: compute(({ row }) => (canOpenComparison(row) ? 'primary' : 'info')),
|
||||
order: 0.25,
|
||||
show: true,
|
||||
disabled: compute(({ row }) => !canOpenComparison(row)),
|
||||
click({ row }) {
|
||||
if (!canOpenComparison(row)) return
|
||||
onComparison && onComparison(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -337,7 +384,7 @@ export const createCrudOptions = function ({
|
||||
columnSetDisabled: true
|
||||
}
|
||||
},
|
||||
company_short_name: {
|
||||
company_short_name: {
|
||||
title: '交易厂区',
|
||||
type: 'text',
|
||||
form: { show: false },
|
||||
@@ -351,6 +398,25 @@ company_short_name: {
|
||||
}
|
||||
}
|
||||
},
|
||||
buying_method: {
|
||||
title: '采购方式',
|
||||
type: 'dict-select',
|
||||
dict: dict({ data: buyingMethodDict }),
|
||||
search: {
|
||||
show: true,
|
||||
component: { props: { placeholder: '采购方式', clearable: true } }
|
||||
},
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 100,
|
||||
formatter: ({ row, value }: { row: any; value: unknown }) => {
|
||||
const v = value ?? row?.buying_method
|
||||
const n = Number(v)
|
||||
if (!Number.isFinite(n)) return v != null && v !== '' ? String(v) : ''
|
||||
return buyingMethodDict.find((d) => d.value === n)?.label ?? String(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
inquiry_no: {
|
||||
title: '询价单号',
|
||||
type: 'input',
|
||||
@@ -361,7 +427,7 @@ company_short_name: {
|
||||
form: {
|
||||
show: false
|
||||
},
|
||||
column: { minWidth: 140 }
|
||||
column: { minWidth: 120, showOverflowTooltip: true }
|
||||
},
|
||||
title: {
|
||||
title: '询价单名称',
|
||||
@@ -377,13 +443,13 @@ company_short_name: {
|
||||
title: '询价模版',
|
||||
type: 'input',
|
||||
column: {
|
||||
minWidth: 180,
|
||||
minWidth: 120,
|
||||
showOverflowTooltip: true,
|
||||
formatter: ({ row, value }: { row: any; value: unknown }) => {
|
||||
const code = String(value ?? row?.template ?? row?.template_code ?? '').trim()
|
||||
const verRaw = row?.template_version ?? row?.templateVersion ?? row?.cost_template_version
|
||||
if (!code) return ''
|
||||
if (verRaw != null && verRaw !== '') return `${code}(V${formatCostTemplateVersionTwoDigits(verRaw)})`
|
||||
if (verRaw != null && verRaw !== '') return `${code}(V${formatCostTemplateVersion(verRaw)})`
|
||||
return code
|
||||
}
|
||||
}
|
||||
@@ -392,10 +458,28 @@ company_short_name: {
|
||||
title: '报价截止时',
|
||||
type: 'datetime',
|
||||
column: {
|
||||
width: 160,
|
||||
width: 150,
|
||||
formatter: ({ value }: { value: unknown }) => formatQuoteDeadlineDisplay(value)
|
||||
}
|
||||
},
|
||||
bid_start_time: {
|
||||
title: '投标开始时间',
|
||||
type: 'datetime',
|
||||
column: {
|
||||
width: 150,
|
||||
formatter: ({ row, value }: { row: any; value: unknown }) =>
|
||||
Number(row?.buying_method) === 1 ? '-' : formatQuoteDeadlineDisplay(value)
|
||||
}
|
||||
},
|
||||
bid_end_time: {
|
||||
title: '投标截止时间',
|
||||
type: 'datetime',
|
||||
column: {
|
||||
width: 150,
|
||||
formatter: ({ row, value }: { row: any; value: unknown }) =>
|
||||
Number(row?.buying_method) === 1 ? '-' : formatQuoteDeadlineDisplay(value)
|
||||
}
|
||||
},
|
||||
buyer: {
|
||||
title: '采购负责人',
|
||||
type: 'input',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,11 @@ type Quote = {
|
||||
inquiryStatus: string
|
||||
/** 询价主表 `Inquiry.status`(数字),用于中标列与 status=9 判断 */
|
||||
inquiryStatusCode?: number | null
|
||||
/** 报价主表 `QuotationMaster.buying_method`(发布时自询价单拷贝) */
|
||||
buyingMethod?: number | null
|
||||
/** 报价主表投标时间(询价=1 时列表/表单显示「-」) */
|
||||
bidStartTime?: string
|
||||
bidEndTime?: string
|
||||
template: string
|
||||
currency: string
|
||||
quoteDeadline: string
|
||||
@@ -75,6 +80,33 @@ type Quote = {
|
||||
|
||||
type SummaryRow = { section: string; amount: number; isSubtotal?: boolean }
|
||||
|
||||
/** 与杂采询价列表列展示一致 */
|
||||
export const buyingMethodDict = [
|
||||
{ value: 1, label: '询价' },
|
||||
{ value: 2, label: '招标' }
|
||||
]
|
||||
|
||||
export function formatQuoteDeadlineDisplay(value: unknown) {
|
||||
if (!value) return ''
|
||||
const text = String(value).trim()
|
||||
if (!text) return ''
|
||||
const matched = text.match(/^(\d{4}-\d{2}-\d{2})[ T](\d{2})/)
|
||||
if (matched) {
|
||||
return `${matched[1]} ${matched[2]}:00`
|
||||
}
|
||||
const dateOnly = text.match(/^(\d{4}-\d{2}-\d{2})$/)
|
||||
if (dateOnly) {
|
||||
return `${dateOnly[1]} 00:00`
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
/** 列表「投标开始/截止」列:采购方式=询价 时显示「-」 */
|
||||
export function formatBidTimeColumn(row: any, value: unknown) {
|
||||
if (Number(row?.buyingMethod ?? row?.buying_method) === 1) return '-'
|
||||
return formatQuoteDeadlineDisplay(value)
|
||||
}
|
||||
|
||||
export type InquiryAttachmentRow = {
|
||||
id?: number | string
|
||||
part_id?: string
|
||||
@@ -1048,6 +1080,9 @@ function blankQuote(): Quote {
|
||||
inquiryStatusCode: undefined,
|
||||
template: '',
|
||||
currency: 'CNY',
|
||||
buyingMethod: 1,
|
||||
bidStartTime: '',
|
||||
bidEndTime: '',
|
||||
quoteDeadline: '',
|
||||
quoteAmount: '',
|
||||
quoteTime: '',
|
||||
@@ -1072,6 +1107,7 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
const filters = reactive<{
|
||||
inquiryPlant: string
|
||||
isAwarded: string | number | ''
|
||||
buyingMethod: string | number | ''
|
||||
quoteNo?: string
|
||||
inquiryCode?: string
|
||||
inquiryTitle?: string
|
||||
@@ -1080,6 +1116,7 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
}>({
|
||||
inquiryPlant: '',
|
||||
isAwarded: '',
|
||||
buyingMethod: '',
|
||||
quoteNo: '',
|
||||
inquiryCode: '',
|
||||
inquiryTitle: '',
|
||||
@@ -1303,6 +1340,14 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
if (tpl) q.template = tpl
|
||||
if (inv.currency) q.currency = inv.currency
|
||||
if (inv.quote_deadline) q.quoteDeadline = inv.quote_deadline
|
||||
if (q.buyingMethod == null && inv.buying_method != null && inv.buying_method !== '') {
|
||||
const n = Number(inv.buying_method)
|
||||
if (Number.isFinite(n)) q.buyingMethod = n
|
||||
}
|
||||
if (Number(q.buyingMethod) !== 1) {
|
||||
if (!q.bidStartTime && inv.bid_start_time) q.bidStartTime = String(inv.bid_start_time).trim()
|
||||
if (!q.bidEndTime && inv.bid_end_time) q.bidEndTime = String(inv.bid_end_time).trim()
|
||||
}
|
||||
const cc = inv.company_code != null && inv.company_code !== '' ? String(inv.company_code).trim() : ''
|
||||
if (cc) q.inquiryCompanyCode = cc
|
||||
const invSt = inv.status ?? inv.inquiry_status
|
||||
@@ -1338,6 +1383,20 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
/** 询价主表 `Inquiry.template` 存模板编号,与报价主表无该字段时需关联询价补全 */
|
||||
template: item.template || item.template_code || '',
|
||||
currency: item.currency || 'CNY',
|
||||
buyingMethod: (() => {
|
||||
const raw = item.buying_method ?? item.buyingMethod
|
||||
if (raw === null || raw === undefined || raw === '') return null
|
||||
const n = Number(raw)
|
||||
return Number.isFinite(n) ? n : null
|
||||
})(),
|
||||
bidStartTime: (() => {
|
||||
const raw = item.bid_start_time ?? item.bidStartTime
|
||||
return raw != null && String(raw).trim() !== '' ? String(raw).trim() : ''
|
||||
})(),
|
||||
bidEndTime: (() => {
|
||||
const raw = item.bid_end_time ?? item.bidEndTime
|
||||
return raw != null && String(raw).trim() !== '' ? String(raw).trim() : ''
|
||||
})(),
|
||||
quoteDeadline: item.quote_deadline || item.quoteDeadline || '',
|
||||
quoteAmount:
|
||||
item.quote_amount ??
|
||||
@@ -1498,6 +1557,7 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
const resetFilter = () => {
|
||||
filters.inquiryPlant = ''
|
||||
filters.isAwarded = ''
|
||||
filters.buyingMethod = ''
|
||||
filters.quoteNo = ''
|
||||
filters.inquiryCode = ''
|
||||
filters.inquiryTitle = ''
|
||||
@@ -1521,8 +1581,21 @@ export function useQuoteCrud(options?: { onChange?: () => void }) {
|
||||
filters.isAwarded === '' || filters.isAwarded === undefined || filters.isAwarded === null
|
||||
? true
|
||||
: Number(q.isAwarded) === Number(filters.isAwarded)
|
||||
const matchBuying =
|
||||
filters.buyingMethod === '' || filters.buyingMethod === undefined || filters.buyingMethod === null
|
||||
? true
|
||||
: Number(q.buyingMethod) === Number(filters.buyingMethod)
|
||||
const matchDate = !start || !end || (new Date(q.quoteDeadline) >= start && new Date(q.quoteDeadline) <= end)
|
||||
return matchQuoteNo && matchInquiryCode && matchInquiryTitle && matchCurrency && matchPlant && matchAwarded && matchDate
|
||||
return (
|
||||
matchQuoteNo &&
|
||||
matchInquiryCode &&
|
||||
matchInquiryTitle &&
|
||||
matchCurrency &&
|
||||
matchPlant &&
|
||||
matchAwarded &&
|
||||
matchBuying &&
|
||||
matchDate
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -30,41 +30,57 @@
|
||||
|
||||
<el-tabs v-model="activeTab" type="card" class="tabs-fill quote-dialog-tabs">
|
||||
<el-tab-pane label="询价单信息" name="inquiry">
|
||||
<el-descriptions :column="2" border size="small" class="mb8">
|
||||
<el-descriptions-item label="询价单号">{{ current.inquiryCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="询价单名称">{{ current.inquiryTitle }}</el-descriptions-item>
|
||||
<el-descriptions-item label="询价模板">{{ templateLabel(current.template) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="交易币别">{{ current.currency }}</el-descriptions-item>
|
||||
<el-descriptions-item label="报价截止日">{{ current.quoteDeadline }}</el-descriptions-item>
|
||||
<el-descriptions-item label="交易厂区">{{ current.companyShortName || current.inquiryCompanyCode || '—' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-divider content-position="left">询价附件</el-divider>
|
||||
<div class="inquiry-attachments">
|
||||
<div v-for="group in inquiryAttachmentGroups" :key="group.fileType" class="inquiry-attachments__block">
|
||||
<div class="inquiry-attachments__type">{{ group.label }}</div>
|
||||
<div class="inquiry-attachments__links">
|
||||
<template v-for="(file, idx) in group.items" :key="`${group.fileType}-${file.id ?? idx}-${file.file_name}`">
|
||||
<el-link
|
||||
v-if="inquiryAttachmentHref(file) !== '#'"
|
||||
type="primary"
|
||||
:href="inquiryAttachmentHref(file)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inquiry-attachments__link"
|
||||
>
|
||||
{{ file.file_name || '(未命名)' }}
|
||||
</el-link>
|
||||
<span v-else class="inquiry-attachments__link inquiry-attachments__link--text">
|
||||
{{ file.file_name || '(未命名)' }}
|
||||
</span>
|
||||
</template>
|
||||
<el-divider content-position="left"></el-divider>
|
||||
<div class="inquiry-tab-pane">
|
||||
<el-form class="grid-form inquiry-form-readonly" label-width="120px">
|
||||
<el-form-item label="询价单号">
|
||||
<el-input :model-value="current.inquiryCode" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="询价单名称">
|
||||
<el-input :model-value="current.inquiryTitle" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="询价模板">
|
||||
<el-input :model-value="templateLabel(current.template)" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="交易币别">
|
||||
<el-input :model-value="current.currency" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="报价截止日">
|
||||
<el-input :model-value="current.quoteDeadline" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="交易厂区">
|
||||
<el-input :model-value="current.companyShortName || current.inquiryCompanyCode || '—'" disabled />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-divider content-position="left">询价附件</el-divider>
|
||||
<div class="inquiry-attachments">
|
||||
<div v-for="group in inquiryAttachmentGroups" :key="group.fileType" class="inquiry-attachments__block">
|
||||
<div class="inquiry-attachments__type">{{ group.label }}</div>
|
||||
<div class="inquiry-attachments__links">
|
||||
<template v-for="(file, idx) in group.items" :key="`${group.fileType}-${file.id ?? idx}-${file.file_name}`">
|
||||
<el-link
|
||||
v-if="inquiryAttachmentHref(file) !== '#'"
|
||||
type="primary"
|
||||
:href="inquiryAttachmentHref(file)"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inquiry-attachments__link"
|
||||
>
|
||||
{{ file.file_name || '(未命名)' }}
|
||||
</el-link>
|
||||
<span v-else class="inquiry-attachments__link inquiry-attachments__link--text">
|
||||
{{ file.file_name || '(未命名)' }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!inquiryAttachmentGroups.length" class="inquiry-attachments__empty">暂无询价附件</div>
|
||||
</div>
|
||||
<div v-if="!inquiryAttachmentGroups.length" class="inquiry-attachments__empty">暂无询价附件</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="报价基础信息" name="base">
|
||||
<el-divider content-position="left"></el-divider>
|
||||
<el-form :model="current.base" label-width="120px" class="grid-form">
|
||||
<el-form-item label="联系人">
|
||||
<el-input v-model="current.base.contact" :disabled="isReadOnly" />
|
||||
@@ -299,7 +315,13 @@ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { Flag } from '@element-plus/icons-vue'
|
||||
import { compute, dict, useCrud, useExpose } from '@fast-crud/fast-crud'
|
||||
import { getBaseURL } from '/@/utils/baseUrl'
|
||||
import { useQuoteCrud, formatAwardBidStatus, type InquiryAttachmentRow } from './crud'
|
||||
import {
|
||||
useQuoteCrud,
|
||||
formatAwardBidStatus,
|
||||
type InquiryAttachmentRow,
|
||||
buyingMethodDict,
|
||||
formatBidTimeColumn
|
||||
} from './crud'
|
||||
|
||||
const INQUIRY_FILE_TYPE_ORDER = [1, 2, 3] as const
|
||||
const INQUIRY_FILE_TYPE_LABELS: Record<number, string> = {
|
||||
@@ -479,6 +501,10 @@ const syncFilters = (form: any = {}) => {
|
||||
filters.inquiryCode = form.inquiryCode || ''
|
||||
filters.inquiryTitle = form.inquiryTitle || ''
|
||||
filters.currency = form.currency || ''
|
||||
filters.buyingMethod =
|
||||
form.buyingMethod !== undefined && form.buyingMethod !== null && form.buyingMethod !== ''
|
||||
? form.buyingMethod
|
||||
: ''
|
||||
filters.isAwarded =
|
||||
form.isAwarded !== undefined && form.isAwarded !== null && form.isAwarded !== '' ? form.isAwarded : ''
|
||||
if (Array.isArray(form.quoteDeadline) && form.quoteDeadline.length === 2) {
|
||||
@@ -558,6 +584,24 @@ const crudOptions = {
|
||||
search: { show: false },
|
||||
column: { minWidth: 100, showOverflowTooltip: true }
|
||||
},
|
||||
buyingMethod: {
|
||||
title: '采购方式',
|
||||
type: 'dict-select',
|
||||
dict: dict({ data: buyingMethodDict }),
|
||||
search: {
|
||||
show: true,
|
||||
component: { props: { placeholder: '采购方式', clearable: true } }
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
formatter: ({ row, value }: any) => {
|
||||
const v = value ?? row?.buyingMethod
|
||||
const n = Number(v)
|
||||
if (!Number.isFinite(n)) return v != null && v !== '' ? String(v) : ''
|
||||
return buyingMethodDict.find((d) => d.value === n)?.label ?? String(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
quoteNo: {
|
||||
title: '报价单号',
|
||||
type: 'text',
|
||||
@@ -601,7 +645,23 @@ const crudOptions = {
|
||||
}
|
||||
}
|
||||
},
|
||||
column: { width: 180 }
|
||||
column: { width: 150 }
|
||||
},
|
||||
bidStartTime: {
|
||||
title: '投标开始时间',
|
||||
type: 'datetime',
|
||||
column: {
|
||||
width: 150,
|
||||
formatter: ({ row, value }: any) => formatBidTimeColumn(row, value)
|
||||
}
|
||||
},
|
||||
bidEndTime: {
|
||||
title: '投标截止时间',
|
||||
type: 'datetime',
|
||||
column: {
|
||||
width: 150,
|
||||
formatter: ({ row, value }: any) => formatBidTimeColumn(row, value)
|
||||
}
|
||||
},
|
||||
status: {
|
||||
title: '报价状态',
|
||||
@@ -701,7 +761,9 @@ onMounted(() => {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
/* 与 max-height 相同,避免短内容页签(如询价单信息)把弹窗整体压矮 */
|
||||
.quote-dialog-scroll {
|
||||
min-height: min(72vh, calc(100vh - 200px));
|
||||
max-height: min(72vh, calc(100vh - 200px));
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
@@ -710,6 +772,22 @@ onMounted(() => {
|
||||
background: var(--el-bg-color, #fff);
|
||||
isolation: isolate;
|
||||
}
|
||||
.inquiry-tab-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
}
|
||||
.inquiry-form-readonly :deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.inquiry-form-readonly :deep(.el-input.is-disabled .el-input__wrapper) {
|
||||
box-shadow: 0 0 0 1px var(--el-border-color) inset;
|
||||
background-color: var(--el-fill-color-blank);
|
||||
}
|
||||
.inquiry-form-readonly :deep(.el-input.is-disabled .el-input__inner) {
|
||||
color: var(--el-text-color-primary);
|
||||
-webkit-text-fill-color: var(--el-text-color-primary);
|
||||
}
|
||||
.quote-dialog-sticky-status {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
Reference in New Issue
Block a user