feat(crm): 投标保证金迁移到销售管理并接入销售台账
- 新增销售管理 → 投标保证金页面:客户(招标方)筛选与登记,展示中标结果、
退回状态、退回金额与日期,可关联该客户已审核的销售订单并显示订单金额
- 选中销售订单自动置为已中标/无需退回,改未中标自动清空订单与退款字段,
换客户清空已选订单;提交前清理无效退款金额与日期
- 删除原供应商管理下的投标保证金页面与接口定义,权限串改为 crm:bid-bond:*
Co-Authored-By: Claude Code <noreply@anthropic.com>
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { PageParam, PageResult } from '@vben/request'; |
| | | |
| | | import { requestClient } from '#/api/request'; |
| | | |
| | | export namespace CrmBidBondApi { |
| | | /** ææ ä¿è¯é */ |
| | | export interface BidBond { |
| | | id?: number; |
| | | no?: string; |
| | | customerId?: number; |
| | | customerName?: string; |
| | | projectName?: string; |
| | | tenderNo?: string; |
| | | saleOrderId?: number; |
| | | saleOrderNo?: string; |
| | | saleOrderAmount?: number; |
| | | bondAmount?: number; |
| | | payDate?: string; |
| | | /** 䏿 ç»æï¼0 å¾
弿 ã1 已䏿 ã2 æªä¸æ */ |
| | | bidResult?: number; |
| | | /** éåç¶æï¼0 æªéåã1 é¨åéåã2 å·²éåã3 æ ééå */ |
| | | refundStatus?: number; |
| | | refundAmount?: number; |
| | | refundDate?: string; |
| | | remark?: string; |
| | | createTime?: string; |
| | | } |
| | | |
| | | /** å¯å
³èçéå®è®¢åï¼éå®å°è´¦ï¼ */ |
| | | export interface SaleOrderOption { |
| | | id: number; |
| | | no: string; |
| | | customerId: number; |
| | | status: number; |
| | | statusName?: string; |
| | | totalPrice?: number; |
| | | contractNo?: string; |
| | | } |
| | | } |
| | | |
| | | /** å页æ¥è¯¢ææ ä¿è¯é */ |
| | | export function getBidBondPage(params: PageParam) { |
| | | return requestClient.get<PageResult<CrmBidBondApi.BidBond>>( |
| | | '/crm/bid-bond/page', |
| | | { params }, |
| | | ); |
| | | } |
| | | |
| | | /** æ¥è¯¢ææ ä¿è¯é详æ
*/ |
| | | export function getBidBond(id: number) { |
| | | return requestClient.get<CrmBidBondApi.BidBond>( |
| | | `/crm/bid-bond/get?id=${id}`, |
| | | ); |
| | | } |
| | | |
| | | /** åå»ºææ ä¿è¯é */ |
| | | export function createBidBond(data: CrmBidBondApi.BidBond) { |
| | | return requestClient.post<number>('/crm/bid-bond/create', data); |
| | | } |
| | | |
| | | /** æ´æ°ææ ä¿è¯é */ |
| | | export function updateBidBond(data: CrmBidBondApi.BidBond) { |
| | | return requestClient.put('/crm/bid-bond/update', data); |
| | | } |
| | | |
| | | /** å 餿æ ä¿è¯é */ |
| | | export function deleteBidBond(id: number) { |
| | | return requestClient.delete('/crm/bid-bond/delete', { params: { id } }); |
| | | } |
| | | |
| | | /** æ¥è¯¢å®¢æ·ä¸å¯å
³èçéå®è®¢åï¼ä»
å·²å®¡æ ¸ï¼ */ |
| | | export function getSaleOrderOptions(customerId: number) { |
| | | return requestClient.get<CrmBidBondApi.SaleOrderOption[]>( |
| | | '/crm/bid-bond/sale-order-list', |
| | | { params: { customerId } }, |
| | | ); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { VbenFormSchema } from '#/adapter/form'; |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | |
| | | import { getCustomerSimpleList } from '#/api/crm/customer'; |
| | | import { getSaleOrderOptions } from '#/api/crm/bidBond'; |
| | | |
| | | export const BID_RESULT_OPTIONS = [ |
| | | { label: 'å¾
弿 ', value: 0, color: 'processing' }, |
| | | { label: '已䏿 ', value: 1, color: 'success' }, |
| | | { label: 'æªä¸æ ', value: 2, color: 'default' }, |
| | | ]; |
| | | |
| | | export const REFUND_STATUS_OPTIONS = [ |
| | | { label: 'æªéå', value: 0, color: 'warning' }, |
| | | { label: 'é¨åéå', value: 1, color: 'processing' }, |
| | | { label: 'å·²éå', value: 2, color: 'success' }, |
| | | { label: 'æ ééå', value: 3, color: 'default' }, |
| | | ]; |
| | | |
| | | export function getBidResultLabel(result?: number) { |
| | | return BID_RESULT_OPTIONS.find((item) => item.value === result)?.label ?? '-'; |
| | | } |
| | | |
| | | export function getBidResultColor(result?: number) { |
| | | return BID_RESULT_OPTIONS.find((item) => item.value === result)?.color ?? 'default'; |
| | | } |
| | | |
| | | export function getRefundStatusLabel(status?: number) { |
| | | return REFUND_STATUS_OPTIONS.find((item) => item.value === status)?.label ?? '-'; |
| | | } |
| | | |
| | | export function getRefundStatusColor(status?: number) { |
| | | return REFUND_STATUS_OPTIONS.find((item) => item.value === status)?.color ?? 'default'; |
| | | } |
| | | |
| | | /** æ°å¢/ä¿®æ¹ææ ä¿è¯éç表å */ |
| | | export function useFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'customerId', |
| | | label: '客æ·ï¼ææ æ¹ï¼', |
| | | component: 'ApiSelect', |
| | | rules: 'required', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©å®¢æ·', |
| | | allowClear: true, |
| | | showSearch: true, |
| | | api: getCustomerSimpleList, |
| | | labelField: 'name', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'projectName', |
| | | label: '项ç®åç§°', |
| | | component: 'Input', |
| | | componentProps: { placeholder: '请è¾å
¥æ¬æ¬¡ææ 项ç®åç§°' }, |
| | | }, |
| | | { |
| | | fieldName: 'tenderNo', |
| | | label: 'ææ ç¼å·', |
| | | component: 'Input', |
| | | componentProps: { placeholder: '请è¾å
¥ææ æ¹åå¸çææ ç¼å·' }, |
| | | }, |
| | | { |
| | | fieldName: 'saleOrderId', |
| | | label: 'å
³èéå®è®¢å', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | placeholder: '请å
鿩客æ·', |
| | | allowClear: true, |
| | | showSearch: true, |
| | | labelField: 'no', |
| | | valueField: 'id', |
| | | optionFilterProp: 'label', |
| | | }, |
| | | dependencies: { |
| | | triggerFields: ['customerId'], |
| | | componentProps: (values) => { |
| | | const customerId = values.customerId as number | undefined; |
| | | return { |
| | | placeholder: customerId |
| | | ? 'è¯·éæ©è¯¥å®¢æ·å·²å®¡æ ¸çéå®è®¢åï¼éå®å°è´¦ï¼' |
| | | : '请å
鿩客æ·', |
| | | disabled: !customerId, |
| | | api: customerId |
| | | ? () => getSaleOrderOptions(customerId) |
| | | : () => Promise.resolve([]), |
| | | }; |
| | | }, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'bondAmount', |
| | | label: 'ä¿è¯ééé¢', |
| | | component: 'InputNumber', |
| | | rules: 'required', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | placeholder: '请è¾å
¥ç¼´çº³çä¿è¯ééé¢', |
| | | min: 0, |
| | | precision: 2, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'payDate', |
| | | label: 'ç¼´çº³æ¥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: 'w-full', |
| | | placeholder: 'è¯·éæ©å客æ·ç¼´çº³ä¿è¯éçæ¥æ', |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'bidResult', |
| | | label: '䏿 ç»æ', |
| | | component: 'Select', |
| | | rules: 'required', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©ä¸æ ç»æ', |
| | | options: BID_RESULT_OPTIONS.map(({ label, value }) => ({ |
| | | label, |
| | | value, |
| | | })), |
| | | }, |
| | | defaultValue: 0, |
| | | }, |
| | | { |
| | | fieldName: 'refundStatus', |
| | | label: 'éåç¶æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'æªä¸æ æ¶è·è¸ªä¿è¯éæ¯å¦éå', |
| | | options: REFUND_STATUS_OPTIONS.map(({ label, value }) => ({ |
| | | label, |
| | | value, |
| | | })), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'refundAmount', |
| | | label: 'éåéé¢', |
| | | component: 'InputNumber', |
| | | componentProps: { |
| | | class: '!w-full', |
| | | placeholder: 'å·²éåæ¶é¡»çäºä¿è¯ééé¢ï¼é¨åéåæ¶é¡»å°äºä¿è¯ééé¢', |
| | | min: 0, |
| | | precision: 2, |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'refundDate', |
| | | label: 'é忥æ', |
| | | component: 'DatePicker', |
| | | componentProps: { |
| | | class: 'w-full', |
| | | placeholder: 'è¯·éæ©å®¢æ·å®é
éåä¿è¯éçæ¥æ', |
| | | format: 'YYYY-MM-DD', |
| | | valueFormat: 'YYYY-MM-DD', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'remark', |
| | | label: '夿³¨', |
| | | component: 'Textarea', |
| | | componentProps: { placeholder: '请è¾å
¥å¤æ³¨', rows: 2 }, |
| | | formItemClass: 'col-span-2', |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** æç´¢è¡¨å */ |
| | | export function useGridFormSchema(): VbenFormSchema[] { |
| | | return [ |
| | | { |
| | | fieldName: 'no', |
| | | label: 'ä¿è¯éåå·', |
| | | component: 'Input', |
| | | componentProps: { placeholder: '请è¾å
¥ä¿è¯éåå·', allowClear: true }, |
| | | }, |
| | | { |
| | | fieldName: 'customerId', |
| | | label: '客æ·', |
| | | component: 'ApiSelect', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©å®¢æ·', |
| | | allowClear: true, |
| | | showSearch: true, |
| | | api: getCustomerSimpleList, |
| | | labelField: 'name', |
| | | valueField: 'id', |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'projectName', |
| | | label: '项ç®åç§°', |
| | | component: 'Input', |
| | | componentProps: { placeholder: '请è¾å
¥é¡¹ç®åç§°', allowClear: true }, |
| | | }, |
| | | { |
| | | fieldName: 'saleOrderNo', |
| | | label: 'éå®è®¢åå·', |
| | | component: 'Input', |
| | | componentProps: { placeholder: '请è¾å
¥å
³èéå®è®¢åå·', allowClear: true }, |
| | | }, |
| | | { |
| | | fieldName: 'bidResult', |
| | | label: '䏿 ç»æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©', |
| | | allowClear: true, |
| | | options: BID_RESULT_OPTIONS.map(({ label, value }) => ({ |
| | | label, |
| | | value, |
| | | })), |
| | | }, |
| | | }, |
| | | { |
| | | fieldName: 'refundStatus', |
| | | label: 'éåç¶æ', |
| | | component: 'Select', |
| | | componentProps: { |
| | | placeholder: 'è¯·éæ©', |
| | | allowClear: true, |
| | | options: REFUND_STATUS_OPTIONS.map(({ label, value }) => ({ |
| | | label, |
| | | value, |
| | | })), |
| | | }, |
| | | }, |
| | | ]; |
| | | } |
| | | |
| | | /** è¡¨æ ¼å */ |
| | | export function useGridColumns(): VxeTableGridOptions['columns'] { |
| | | return [ |
| | | { field: 'no', title: 'ä¿è¯éåå·', minWidth: 150 }, |
| | | { field: 'customerName', title: '客æ·ï¼ææ æ¹ï¼', minWidth: 160 }, |
| | | { field: 'projectName', title: '项ç®åç§°', minWidth: 180 }, |
| | | { field: 'tenderNo', title: 'ææ ç¼å·', minWidth: 140 }, |
| | | { |
| | | field: 'saleOrderNo', |
| | | title: 'å
³èéå®è®¢å', |
| | | minWidth: 160, |
| | | slots: { default: 'saleOrderNo' }, |
| | | }, |
| | | { |
| | | field: 'saleOrderAmount', |
| | | title: '订åéé¢', |
| | | minWidth: 120, |
| | | formatter: 'formatAmount2', |
| | | }, |
| | | { |
| | | field: 'bondAmount', |
| | | title: 'ä¿è¯ééé¢', |
| | | minWidth: 120, |
| | | formatter: 'formatAmount2', |
| | | }, |
| | | { field: 'payDate', title: 'ç¼´çº³æ¥æ', minWidth: 110 }, |
| | | { |
| | | field: 'bidResult', |
| | | title: '䏿 ç»æ', |
| | | minWidth: 100, |
| | | slots: { default: 'bidResult' }, |
| | | }, |
| | | { |
| | | field: 'refundStatus', |
| | | title: 'éåç¶æ', |
| | | minWidth: 110, |
| | | slots: { default: 'refundStatus' }, |
| | | }, |
| | | { |
| | | field: 'refundAmount', |
| | | title: 'éåéé¢', |
| | | minWidth: 120, |
| | | formatter: 'formatAmount2', |
| | | }, |
| | | { field: 'refundDate', title: 'é忥æ', minWidth: 110 }, |
| | | { field: 'remark', title: '夿³¨', minWidth: 150 }, |
| | | { |
| | | title: 'æä½', |
| | | width: 130, |
| | | fixed: 'right', |
| | | slots: { default: 'actions' }, |
| | | }, |
| | | ]; |
| | | } |
| ÎļþÃû´Ó src/views/srm/bidBond/index.vue ÐÞ¸Ä |
| | |
| | | <script lang="ts" setup> |
| | | import type { VxeTableGridOptions } from '#/adapter/vxe-table'; |
| | | import type { SrmBidBondApi } from '#/api/srm/bidBond'; |
| | | import type { CrmBidBondApi } from '#/api/crm/bidBond'; |
| | | |
| | | import { Page, useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { message, Tag } from 'ant-design-vue'; |
| | | |
| | | import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; |
| | | import { |
| | | deleteBidBond, |
| | | getBidBondPage, |
| | | } from '#/api/srm/bidBond'; |
| | | import { deleteBidBond, getBidBondPage } from '#/api/crm/bidBond'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { |
| | | getBidResultColor, |
| | | getBidResultLabel, |
| | | getRefundStatusColor, |
| | | getRefundStatusLabel, |
| | | useGridColumns, |
| | |
| | | } from './data'; |
| | | import BidBondForm from './modules/form.vue'; |
| | | |
| | | defineOptions({ name: 'SrmBidBond' }); |
| | | defineOptions({ name: 'CrmBidBond' }); |
| | | |
| | | const [FormModal, formModalApi] = useVbenModal({ |
| | | connectedComponent: BidBondForm, |
| | |
| | | formModalApi.setData(null).open(); |
| | | } |
| | | |
| | | function handleEdit(row: SrmBidBondApi.BidBond) { |
| | | function handleEdit(row: CrmBidBondApi.BidBond) { |
| | | formModalApi.setData({ id: row.id }).open(); |
| | | } |
| | | |
| | | async function handleDelete(row: SrmBidBondApi.BidBond) { |
| | | async function handleDelete(row: CrmBidBondApi.BidBond) { |
| | | await deleteBidBond(row.id!); |
| | | message.success($t('ui.actionMessage.deleteSuccess', [row.no])); |
| | | handleRefresh(); |
| | |
| | | }, |
| | | rowConfig: { keyField: 'id', isHover: true }, |
| | | toolbarConfig: { refresh: true, search: true }, |
| | | } as VxeTableGridOptions<SrmBidBondApi.BidBond>, |
| | | } as VxeTableGridOptions<CrmBidBondApi.BidBond>, |
| | | }); |
| | | </script> |
| | | |
| | |
| | | label: $t('ui.actionTitle.create', ['ææ ä¿è¯é']), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.ADD, |
| | | auth: ['srm:bid-bond:create'], |
| | | auth: ['crm:bid-bond:create'], |
| | | onClick: handleCreate, |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #won="{ row }"> |
| | | <Tag :color="row.won ? 'success' : 'default'"> |
| | | {{ row.won ? '䏿 ' : 'æªä¸æ ' }} |
| | | <template #saleOrderNo="{ row }"> |
| | | <span v-if="row.saleOrderNo">{{ row.saleOrderNo }}</span> |
| | | <span v-else class="text-gray-400">æªå
³è</span> |
| | | </template> |
| | | <template #bidResult="{ row }"> |
| | | <Tag :color="getBidResultColor(row.bidResult)"> |
| | | {{ getBidResultLabel(row.bidResult) }} |
| | | </Tag> |
| | | </template> |
| | | <template #refundStatus="{ row }"> |
| | |
| | | label: $t('common.edit'), |
| | | type: 'link', |
| | | icon: ACTION_ICON.EDIT, |
| | | auth: ['srm:bid-bond:update'], |
| | | auth: ['crm:bid-bond:update'], |
| | | onClick: handleEdit.bind(null, row), |
| | | }, |
| | | { |
| | |
| | | type: 'link', |
| | | danger: true, |
| | | icon: ACTION_ICON.DELETE, |
| | | auth: ['srm:bid-bond:delete'], |
| | | auth: ['crm:bid-bond:delete'], |
| | | popConfirm: { |
| | | title: $t('ui.actionMessage.deleteConfirm', [row.no]), |
| | | confirm: handleDelete.bind(null, row), |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <script lang="ts" setup> |
| | | import type { CrmBidBondApi } from '#/api/crm/bidBond'; |
| | | |
| | | import { computed, ref } from 'vue'; |
| | | |
| | | import { useVbenModal } from '@vben/common-ui'; |
| | | |
| | | import { message } from 'ant-design-vue'; |
| | | |
| | | import { useVbenForm } from '#/adapter/form'; |
| | | import { |
| | | createBidBond, |
| | | getBidBond, |
| | | updateBidBond, |
| | | } from '#/api/crm/bidBond'; |
| | | import { $t } from '#/locales'; |
| | | |
| | | import { useFormSchema } from '../data'; |
| | | |
| | | const emit = defineEmits(['success']); |
| | | const formData = ref<CrmBidBondApi.BidBond>(); |
| | | /** æå¼å¼¹çªåå¡«æ°æ®æ¶ä¸è§¦ååæ®µèå¨ï¼é¿å
åå¡«æå·²ééå®è®¢åæ¸
空 */ |
| | | const loading = ref(false); |
| | | |
| | | const getTitle = computed(() => { |
| | | return formData.value?.id |
| | | ? $t('ui.actionTitle.edit', ['ææ ä¿è¯é']) |
| | | : $t('ui.actionTitle.create', ['ææ ä¿è¯é']); |
| | | }); |
| | | |
| | | const [Form, formApi] = useVbenForm({ |
| | | commonConfig: { |
| | | componentProps: { class: 'w-full' }, |
| | | labelWidth: 120, |
| | | }, |
| | | wrapperClass: 'grid-cols-2', |
| | | layout: 'horizontal', |
| | | schema: useFormSchema(), |
| | | showDefaultActions: false, |
| | | handleValuesChange: async (values, changedFields) => { |
| | | if (loading.value) { |
| | | return; |
| | | } |
| | | // æ¢å®¢æ·åï¼åéå®è®¢åä¸å®ä¸åå±äºè¯¥å®¢æ·ï¼å¿
é¡»æ¸
空éé |
| | | if (changedFields.includes('customerId') && values.saleOrderId) { |
| | | await formApi.setValues({ saleOrderId: undefined }); |
| | | return; |
| | | } |
| | | // éäºéå®è®¢å说æå·²ä¸æ ï¼æ¸
空订ååéåå¾
弿 |
| | | if (changedFields.includes('saleOrderId')) { |
| | | if (values.saleOrderId && values.bidResult !== 1) { |
| | | await formApi.setValues({ bidResult: 1 }); |
| | | return; |
| | | } |
| | | if (!values.saleOrderId && values.bidResult === 1) { |
| | | await formApi.setValues({ bidResult: 0 }); |
| | | return; |
| | | } |
| | | } |
| | | // æªä¸æ ä¸å¯è½æéå®è®¢åï¼æ¸
空订åé¿å
åç«¯æ ¡éªå¤±è´¥ |
| | | if (changedFields.includes('bidResult') && values.bidResult === 2) { |
| | | if (values.saleOrderId) { |
| | | await formApi.setValues({ saleOrderId: undefined }); |
| | | } |
| | | if (values.refundStatus === 3) { |
| | | await formApi.setValues({ refundStatus: 0 }); |
| | | } |
| | | return; |
| | | } |
| | | // 已䏿 ä¸åå¨éæ¬¾åºæ¯ |
| | | if (changedFields.includes('bidResult') && values.bidResult === 1) { |
| | | if (values.refundStatus !== 3) { |
| | | await formApi.setValues({ |
| | | refundStatus: 3, |
| | | refundAmount: undefined, |
| | | refundDate: undefined, |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | | }); |
| | | |
| | | const [Modal, modalApi] = useVbenModal({ |
| | | async onConfirm() { |
| | | const { valid } = await formApi.validate(); |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | const data = (await formApi.getValues()) as CrmBidBondApi.BidBond; |
| | | // æªéå / æ ééåä¸å
è®¸å¸¦éæ¬¾éé¢ä¸æ¥æï¼é¿å
åç«¯ç¶æä¸éé¢å²çªæ ¡éª |
| | | if ( |
| | | data.refundStatus === 0 || |
| | | data.refundStatus === 3 || |
| | | data.refundStatus === undefined || |
| | | data.refundStatus === null |
| | | ) { |
| | | data.refundAmount = undefined; |
| | | data.refundDate = undefined; |
| | | } |
| | | modalApi.lock(); |
| | | try { |
| | | await (formData.value?.id |
| | | ? updateBidBond({ ...data, id: formData.value.id }) |
| | | : createBidBond(data)); |
| | | await modalApi.close(); |
| | | emit('success'); |
| | | message.success($t('ui.actionMessage.operationSuccess')); |
| | | } finally { |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | async onOpenChange(isOpen: boolean) { |
| | | if (!isOpen) { |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | const data = modalApi.getData<{ id?: number }>(); |
| | | if (!data?.id) { |
| | | formData.value = undefined; |
| | | return; |
| | | } |
| | | modalApi.lock(); |
| | | loading.value = true; |
| | | try { |
| | | formData.value = await getBidBond(data.id); |
| | | await formApi.setValues(formData.value); |
| | | } finally { |
| | | loading.value = false; |
| | | modalApi.unlock(); |
| | | } |
| | | }, |
| | | }); |
| | | |
| | | defineExpose({ modalApi }); |
| | | </script> |
| | | |
| | | <template> |
| | | <Modal :title="getTitle" class="w-3/4"> |
| | | <Form class="mx-4" /> |
| | | </Modal> |
| | | </template> |