feat:优化了订单、药品这些交互
This commit is contained in:
@@ -561,7 +561,9 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item) => item.id === data.drug.frequency_id,
|
||||
),
|
||||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
unit:
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
price: data.price,
|
||||
buy_price: data.buy_price,
|
||||
way_id: data.drug?.way_id,
|
||||
@@ -658,6 +660,11 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
if (data) {
|
||||
newDrugInfo.value.price = data.price;
|
||||
newDrugInfo.value.name = data.drug.drug_name;
|
||||
// 选药后立刻带上真实单位,供新行数量后缀展示
|
||||
newDrugInfo.value.unit =
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug?.unit_id);
|
||||
newDrugInfo.value.unit_id = data.drug?.unit_id;
|
||||
nextTick(() => {
|
||||
const input = document.querySelector(
|
||||
'.new-number-input input',
|
||||
@@ -693,7 +700,9 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item) => item.id === data.drug.frequency_id,
|
||||
),
|
||||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
unit:
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
price: data.price,
|
||||
buy_price: data.buy_price,
|
||||
way_id: data.drug?.way_id,
|
||||
|
||||
@@ -1124,7 +1124,7 @@ const cancelSaveCommonPrescription = () => {
|
||||
prescriptionStore.updateChineseNumberGoNewDrug($event)
|
||||
"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ drug.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
|
||||
<Select
|
||||
@@ -1203,7 +1203,7 @@ const cancelSaveCommonPrescription = () => {
|
||||
prescriptionStore.selectDrugByNewDrugInfo($event, true)
|
||||
"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ prescriptionStore.newDrugInfo.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
|
||||
<Select
|
||||
|
||||
@@ -403,14 +403,14 @@ function prescriptionStatusColor() {
|
||||
<div class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
供货价:{{
|
||||
item.buy_price != null && item.buy_price !== ''
|
||||
? `${item.buy_price} 元/g`
|
||||
? `${item.buy_price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
|
||||
: '—'
|
||||
}}
|
||||
</div>
|
||||
<div class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
售价:{{
|
||||
item.buy_price != null && item.buy_price !== ''
|
||||
? `${item.price} 元/g`
|
||||
? `${item.price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
|
||||
: '—'
|
||||
}}
|
||||
</div>
|
||||
@@ -436,7 +436,7 @@ function prescriptionStatusColor() {
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ item.drug_name }}</h4>
|
||||
<p>规格: {{ item.drug.specification || 'g' }}</p>
|
||||
<p>规格: {{ item.drug.specification || item.drug?.unit?.name || 'g' }}</p>
|
||||
<p>数量: {{ item.number }}</p>
|
||||
<p>单价: {{ item.price }} 元</p>
|
||||
<p>
|
||||
|
||||
@@ -17,7 +17,7 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
},
|
||||
columns: [
|
||||
{ type: 'expand', width: 80, slots: { content: 'expand-content' } },
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 100 },
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 50 },
|
||||
{
|
||||
field: 'order_no',
|
||||
align: 'left',
|
||||
|
||||
@@ -1394,14 +1394,14 @@ const openOrderAmountVerify = () => {
|
||||
<div class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
供货价:{{
|
||||
item.buy_price != null && item.buy_price !== ''
|
||||
? `${item.buy_price} 元/g`
|
||||
? `${item.buy_price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
|
||||
: '—'
|
||||
}}
|
||||
</div>
|
||||
<div class="mt-1 text-gray-600 dark:text-gray-400">
|
||||
售价:{{
|
||||
item.buy_price != null && item.buy_price !== ''
|
||||
? `${item.price} 元/g`
|
||||
? `${item.price} 元/${item.drug?.unit?.name || item.unit?.name || 'g'}`
|
||||
: '—'
|
||||
}}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
// 后端路由前缀:patient-call-log-dict(routes/admin.php 中 cc_auto_route_register 注册)
|
||||
const prefix = 'patient-call-log-dict/';
|
||||
|
||||
/** 列表(分页 + 搜索 name/type/status) */
|
||||
export async function getPatientCallLogDictList(data: any) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
|
||||
/** 下拉:可选 type 过滤(type=1 结果 / type=2 标签) */
|
||||
export async function getPatientCallLogDictOption(data?: any) {
|
||||
return requestClient.get<any>(`${prefix}option`, { params: data });
|
||||
}
|
||||
|
||||
/** 详情 */
|
||||
export async function getPatientCallLogDictInfo(id: number) {
|
||||
return requestClient.get<any>(`${prefix}detail`, { params: { id } });
|
||||
}
|
||||
|
||||
/** 新增 */
|
||||
export async function createPatientCallLogDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}create`, data);
|
||||
}
|
||||
|
||||
/** 更新 */
|
||||
export async function updatePatientCallLogDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}update`, data);
|
||||
}
|
||||
|
||||
/** 删除(软删;ids 数组) */
|
||||
export async function deletePatientCallLogDict(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`${prefix}delete`, data);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
|
||||
import {
|
||||
createPatientCallLogDict,
|
||||
updatePatientCallLogDict,
|
||||
} from '../api';
|
||||
import { modalFormProps } from '../config/form';
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const gridApi = ref();
|
||||
|
||||
const [Form, formApi] = useVbenForm(modalFormProps);
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
fullscreenButton: false,
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
formApi.validate().then(async (e: any) => {
|
||||
if (e.valid) {
|
||||
const values = await formApi.getValues();
|
||||
modalApi.setState({ loading: true, confirmLoading: true });
|
||||
const submitApi = isUpdate.value
|
||||
? updatePatientCallLogDict
|
||||
: createPatientCallLogDict;
|
||||
submitApi(values)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
gridApi.value?.reload();
|
||||
modalApi.close();
|
||||
})
|
||||
.finally(() => {
|
||||
modalApi.setState({ loading: false, confirmLoading: false });
|
||||
});
|
||||
}
|
||||
});
|
||||
await formApi.validateAndSubmitForm();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
|
||||
if (isOpen) {
|
||||
const { values, update } = modalApi.getData<Record<string, any>>();
|
||||
if (values && update) {
|
||||
// 编辑:回填后端返回的字段
|
||||
isUpdate.value = true;
|
||||
formApi.setValues({
|
||||
id: values.id || '',
|
||||
type: values.type ?? 1,
|
||||
name: values.name || '',
|
||||
value: values.value || '',
|
||||
color: values.color || '#6acdbb',
|
||||
sort: values.sort ?? 0,
|
||||
status: values.status ?? 1,
|
||||
});
|
||||
} else {
|
||||
// 新增:默认值
|
||||
isUpdate.value = false;
|
||||
formApi.resetForm();
|
||||
formApi.setValues({
|
||||
id: '',
|
||||
type: 1,
|
||||
name: '',
|
||||
value: '',
|
||||
color: '#6acdbb',
|
||||
sort: 0,
|
||||
status: 1,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
formApi.resetForm();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal :title="`${isUpdate === true ? '编辑' : '新增'}回访字典`" class="w-[50%]">
|
||||
<Form />
|
||||
</Modal>
|
||||
</template>
|
||||
@@ -0,0 +1,96 @@
|
||||
import type { VbenFormProps } from '#/adapter/form';
|
||||
|
||||
export const modalFormProps: VbenFormProps = {
|
||||
wrapperClass: 'grid-cols-12',
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-12',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'id',
|
||||
label: 'ID',
|
||||
formItemClass: 'col-span-6',
|
||||
defaultValue: '',
|
||||
dependencies: {
|
||||
show: false,
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
},
|
||||
{
|
||||
// 1 回访结果 / 2 回访标签;区分后续列表渲染
|
||||
component: 'VbenSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择类型',
|
||||
options: [
|
||||
{ label: '回访结果', value: 1 },
|
||||
{ label: '回访标签', value: 2 },
|
||||
],
|
||||
},
|
||||
fieldName: 'type',
|
||||
label: '类型',
|
||||
rules: 'required',
|
||||
defaultValue: 1,
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入展示名(如 接通/关怀)',
|
||||
},
|
||||
fieldName: 'name',
|
||||
label: '名称',
|
||||
rules: 'required',
|
||||
defaultValue: '',
|
||||
},
|
||||
{
|
||||
// 小程序存储的英文/拼音 value;与历史记录匹配
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入存储值(如 connected/care)',
|
||||
},
|
||||
fieldName: 'value',
|
||||
label: '存储值',
|
||||
rules: 'required',
|
||||
defaultValue: '',
|
||||
},
|
||||
{
|
||||
// hex 颜色,用于小程序彩色 tag
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '请输入 hex 颜色,如 #6acdbb',
|
||||
},
|
||||
fieldName: 'color',
|
||||
label: '颜色',
|
||||
defaultValue: '#6acdbb',
|
||||
},
|
||||
{
|
||||
component: 'VbenInputNumber',
|
||||
componentProps: {
|
||||
min: 0,
|
||||
precision: 0,
|
||||
},
|
||||
fieldName: 'sort',
|
||||
label: '排序',
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
component: 'VbenSelect',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态',
|
||||
options: [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 0 },
|
||||
],
|
||||
},
|
||||
fieldName: 'status',
|
||||
label: '状态',
|
||||
formItemClass: 'col-span-6',
|
||||
defaultValue: 1,
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { VbenFormProps } from '@vben/common-ui';
|
||||
|
||||
// 列表搜索:按名称模糊、类型精确、状态精确
|
||||
export const formOptions: VbenFormProps = {
|
||||
layout: 'inline',
|
||||
showResetButton: true,
|
||||
showSubmitButton: true,
|
||||
schemas: [
|
||||
{
|
||||
fieldName: 'name',
|
||||
component: 'Input',
|
||||
label: '名称',
|
||||
componentProps: {
|
||||
placeholder: '请输入名称',
|
||||
allowClear: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'type',
|
||||
component: 'Select',
|
||||
label: '类型',
|
||||
componentProps: {
|
||||
placeholder: '请选择类型',
|
||||
allowClear: true,
|
||||
options: [
|
||||
{ label: '回访结果', value: 1 },
|
||||
{ label: '回访标签', value: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'status',
|
||||
component: 'Select',
|
||||
label: '状态',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态',
|
||||
allowClear: true,
|
||||
options: [
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '禁用', value: 0 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { getPatientCallLogDictList } from '../api';
|
||||
|
||||
interface RowType {
|
||||
id: number;
|
||||
type: number;
|
||||
type_txt: string;
|
||||
name: string;
|
||||
value: string;
|
||||
color: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
status_txt: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export const gridOptions: VxeGridProps<RowType> = {
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: '',
|
||||
},
|
||||
columnConfig: {
|
||||
useKey: true,
|
||||
},
|
||||
rowConfig: {
|
||||
useKey: true,
|
||||
isHover: true,
|
||||
isCurrent: true,
|
||||
},
|
||||
columns: [
|
||||
{ type: 'checkbox', width: 60 },
|
||||
{ field: 'id', align: 'left', title: 'ID', width: 80 },
|
||||
{ field: 'type_txt', align: 'left', title: '类型', width: 110 },
|
||||
{ field: 'name', align: 'left', title: '名称', minWidth: 140 },
|
||||
{ field: 'value', align: 'left', title: '存储值', minWidth: 140 },
|
||||
{
|
||||
field: 'color',
|
||||
align: 'left',
|
||||
title: '颜色',
|
||||
width: 120,
|
||||
// 用色块+hex 直观预览,避免放函数调用导致渲染异常
|
||||
slots: { default: 'color' },
|
||||
},
|
||||
{ field: 'sort', align: 'left', title: '排序', width: 90 },
|
||||
{ field: 'status_txt', align: 'left', title: '状态', width: 90 },
|
||||
{ field: 'created_at', title: '创建时间', width: 180 },
|
||||
{ type: 'html', title: '操作', slots: { default: 'action' }, width: 160 },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
return await getPatientCallLogDictList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
border: false,
|
||||
toolbarConfig: {
|
||||
search: true,
|
||||
refresh: true,
|
||||
print: false,
|
||||
export: false,
|
||||
zoom: true,
|
||||
slots: {
|
||||
buttons: 'toolbar-buttons',
|
||||
},
|
||||
custom: {
|
||||
icon: 'vxe-icon-menu',
|
||||
},
|
||||
},
|
||||
showOverflow: false,
|
||||
};
|
||||
124
apps/web-antd/src/views/business/patient-call-log-dict/index.vue
Normal file
124
apps/web-antd/src/views/business/patient-call-log-dict/index.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<script lang="ts" setup>
|
||||
import type { VxeGridListeners } from '#/adapter/vxe-table';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import { deletePatientCallLogDict } from './api';
|
||||
import DictModal from './components/modal.vue';
|
||||
import { formOptions as searchFormOptions } from './config/search';
|
||||
import { gridOptions } from './config/table';
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
|
||||
const gridEvents: VxeGridListeners<any> = {
|
||||
checkboxChange() {
|
||||
const records = gridApi.grid.getCheckboxRecords();
|
||||
hasTopTableDropDownActions.value = records.length > 0;
|
||||
},
|
||||
checkboxAll() {
|
||||
const records = gridApi.grid.getCheckboxRecords();
|
||||
hasTopTableDropDownActions.value = records.length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions: searchFormOptions,
|
||||
gridOptions,
|
||||
gridEvents,
|
||||
});
|
||||
|
||||
const [DictFormModal, dictFormModalApi] = useVbenModal({
|
||||
connectedComponent: DictModal,
|
||||
});
|
||||
|
||||
const showDictModal = (data = {}, isUpdate = false) => {
|
||||
dictFormModalApi.setData({
|
||||
values: data,
|
||||
update: isUpdate,
|
||||
gridApi,
|
||||
});
|
||||
dictFormModalApi.open();
|
||||
};
|
||||
|
||||
const deleteDictApi = (row: any) => {
|
||||
let ids: (string | number)[] = [];
|
||||
if (row) {
|
||||
ids.push(row);
|
||||
} else {
|
||||
ids = gridApi.grid.getCheckboxRecords().map((item: any) => item.id);
|
||||
}
|
||||
deletePatientCallLogDict({ ids }).then(() => {
|
||||
message.success('删除成功!');
|
||||
gridApi.query();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height title="回访字典管理">
|
||||
<DictFormModal />
|
||||
|
||||
<div class="p-4">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '新增',
|
||||
type: 'primary',
|
||||
icon: 'ant-design:plus-outlined',
|
||||
onClick: () => showDictModal({}, false),
|
||||
},
|
||||
]"
|
||||
/>
|
||||
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<Button
|
||||
v-if="hasTopTableDropDownActions"
|
||||
danger
|
||||
type="primary"
|
||||
@click="deleteDictApi()"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<!-- 颜色列:色块 + hex 直观预览 -->
|
||||
<template #color="{ row }">
|
||||
<div class="flex items-center gap-2">
|
||||
<span
|
||||
class="inline-block h-4 w-4 rounded"
|
||||
:style="{ background: row.color, border: '1px solid #e5e7eb' }"
|
||||
/>
|
||||
<span>{{ row.color }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: () => showDictModal(row, true),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
color: 'error',
|
||||
popConfirm: {
|
||||
title: '确定要删除该项吗?',
|
||||
onConfirm: () => deleteDictApi(row.id),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
@@ -33,6 +33,8 @@ export interface ChineseDrugItem {
|
||||
price: number;
|
||||
buy_price?: number;
|
||||
way_id: number;
|
||||
unit_id?: number;
|
||||
unit?: { id: number; name: string } | null;
|
||||
}
|
||||
|
||||
const props = withDefaults(
|
||||
@@ -123,6 +125,8 @@ const newDrugInfo = ref<{
|
||||
number?: number;
|
||||
price?: number;
|
||||
way_id?: number;
|
||||
unit_id?: number;
|
||||
unit?: { id: number; name: string } | null;
|
||||
}>({});
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -180,6 +184,10 @@ function selectNewDrug(drugId: number) {
|
||||
newDrugInfo.value.name = selectedItem.drug?.drug_name || '';
|
||||
newDrugInfo.value.price = selectedItem.price || 0;
|
||||
newDrugInfo.value.way_id = 0;
|
||||
newDrugInfo.value.unit =
|
||||
selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
newDrugInfo.value.unit_id =
|
||||
selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector('.new-chinese-number input') as HTMLInputElement;
|
||||
numberInput?.focus();
|
||||
@@ -204,6 +212,8 @@ function addChineseDrug() {
|
||||
number: newDrugInfo.value.number,
|
||||
price: newDrugInfo.value.price || 0,
|
||||
way_id: newDrugInfo.value.way_id || 0,
|
||||
unit_id: newDrugInfo.value.unit_id || 0,
|
||||
unit: newDrugInfo.value.unit || null,
|
||||
});
|
||||
newDrugInfo.value = {};
|
||||
chineseSearchResults.value = [];
|
||||
@@ -244,6 +254,8 @@ function changeChineseDrug(index: number, drugId: number) {
|
||||
drug.drug_id = drugId;
|
||||
drug.drug_name = selectedItem.drug?.drug_name || '';
|
||||
drug.price = selectedItem.price || 0;
|
||||
drug.unit = selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
drug.unit_id = selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
syncToParent();
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector(`.chinese-number-${index} input`) as HTMLInputElement;
|
||||
@@ -287,6 +299,8 @@ function loadDrugs(recipes: any[], dosage?: number, dayDosage?: number, drugPric
|
||||
price: zeroPrice ? 0 : (configured?.sell_price ?? recipe.price ?? 0),
|
||||
buy_price: zeroPrice ? 0 : (configured?.buy_price ?? recipe.buy_price ?? 0),
|
||||
way_id: recipe.way_id || 0,
|
||||
unit_id: recipe.unit_id || 0,
|
||||
unit: recipe.unit || null,
|
||||
};
|
||||
});
|
||||
if (dosage !== undefined) dosageLocal.value = dosage;
|
||||
@@ -404,7 +418,7 @@ defineExpose({
|
||||
<div v-if="structureReadonly" class="chinese-drug-readonly">
|
||||
<span class="chinese-drug-name-text">{{ drug.drug_name }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<span>{{ drug.number }}g</span>
|
||||
<span>{{ drug.number }}{{ drug.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<span>{{ getWayName(drug.way_id) }}</span>
|
||||
</div>
|
||||
@@ -439,7 +453,7 @@ defineExpose({
|
||||
style="width: 60px"
|
||||
@change="onDrugNumberChange"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ drug.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="drug.way_id"
|
||||
@@ -535,7 +549,7 @@ defineExpose({
|
||||
style="width: 60px"
|
||||
@keydown="(e) => handleChineseKeydown(e, true)"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ newDrugInfo.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="newDrugInfo.way_id"
|
||||
|
||||
@@ -142,7 +142,8 @@ function getDrugNames(recipes: any[], nameField = 'drug_name', showNumber = fals
|
||||
return recipes.map((item) => {
|
||||
const name = item[nameField] || item.name;
|
||||
if (showNumber && item.number) {
|
||||
return `${name}(${item.number}g)`;
|
||||
const unit = item.unit?.name || item.unit_name || 'g';
|
||||
return `${name}(${item.number}${unit})`;
|
||||
}
|
||||
return name;
|
||||
}).join('、');
|
||||
|
||||
@@ -250,7 +250,7 @@ function parseRecipeContent(content: string | Record<string, unknown>) {
|
||||
<span class="drug-name">{{
|
||||
drug?.name || drug?.drug_name
|
||||
}}</span>
|
||||
<span class="drug-quantity mr-5">{{ drug?.number }} /g</span>
|
||||
<span class="drug-quantity mr-5">{{ drug?.number }} /{{ drug?.unit?.name || drug?.use_unit?.name || 'g' }}</span>
|
||||
</div>
|
||||
<div>
|
||||
方法:
|
||||
|
||||
@@ -122,6 +122,13 @@ const getDrugListByWesternModal = debounce(async (searchText = '') => {
|
||||
|
||||
drugList.value = res.map((item) => {
|
||||
const matched = selectList.value.find((v) => v.index_id === item.id);
|
||||
const unitId = matched?.unit_id || item.drug?.unit_id;
|
||||
// 优先接口返回的 unit,再回退本地字典,保证中药网格展示真实单位
|
||||
const unitObj =
|
||||
matched?.unit ||
|
||||
item.drug?.unit ||
|
||||
item.unit ||
|
||||
drugUnit.value.find((u) => u.id === unitId);
|
||||
return {
|
||||
...item,
|
||||
select_number: matched?.select_number || 0,
|
||||
@@ -133,7 +140,8 @@ const getDrugListByWesternModal = debounce(async (searchText = '') => {
|
||||
frequency_id: matched?.frequency_id || item.drug.frequency_id,
|
||||
type_id: matched?.type_id || item.drug.type_id,
|
||||
time_id: matched?.time_id || item.drug.time_id,
|
||||
unit_id: matched?.unit_id || item.drug.unit_id,
|
||||
unit_id: unitId,
|
||||
unit: unitObj,
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -190,8 +198,10 @@ function addProducts(data) {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item) => item.id === data.drug.frequency_id,
|
||||
),
|
||||
// 药品单位信息
|
||||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品单位:优先用选药接口返回的 unit,再回退本地字典
|
||||
unit:
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品价格
|
||||
price: data.price,
|
||||
// 药品使用方式ID
|
||||
@@ -751,7 +761,7 @@ function updateProductNumber(id, number) {
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-red-500">¥{{ item.price }}</div>
|
||||
<div class="text-xs text-gray-400 dark:text-gray-500">/g</div>
|
||||
<div class="text-xs text-gray-400 dark:text-gray-500">/{{ item.drug?.unit?.name || item.unit?.name || 'g' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -785,7 +795,7 @@ function updateProductNumber(id, number) {
|
||||
class="flex-1 !bg-transparent !border-0 shadow-none text-center"
|
||||
@change="updateProductNumber(item.id, item.drug.number)"
|
||||
/>
|
||||
<span class="text-gray-400 dark:text-gray-500 text-xs px-1">g</span>
|
||||
<span class="text-gray-400 dark:text-gray-500 text-xs px-1">{{ item.drug?.unit?.name || item.unit?.name || 'g' }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 加减按钮 (Action) -->
|
||||
|
||||
@@ -1672,7 +1672,7 @@ function mapWestRepiceToProduct(recipe: any): Record<string, any> | null {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item: any) => item.id === freqId,
|
||||
),
|
||||
unit: drugUnit.value.find((item: any) => item.id === unitId),
|
||||
unit: drugObj.unit || drugUnit.value.find((item: any) => item.id === unitId),
|
||||
price: Number(drugObj.sell_price ?? drugObj.price ?? 0),
|
||||
way_id: drugObj.way_id,
|
||||
use_ways: drugUseWay.value.find((item: any) => item.id === drugObj.way_id),
|
||||
@@ -1755,7 +1755,7 @@ async function applyHistoricalPrescriptionDetail(detail: any): Promise<boolean>
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item: any) => item.id === d.frequency_id,
|
||||
),
|
||||
unit: drugUnit.value.find((item: any) => item.id === d.unit_id),
|
||||
unit: d.unit || drugUnit.value.find((item: any) => item.id === d.unit_id),
|
||||
time_id: d.time_id,
|
||||
type_id: d.type_id,
|
||||
frequency_id: d.frequency_id,
|
||||
@@ -2103,8 +2103,13 @@ function selectNewDrugInfo() {
|
||||
const data = drugList.value.find((v) => v.drug_id === newDrugInfo.value.id);
|
||||
newDrugInfo.value.price = data.price;
|
||||
newDrugInfo.value.name = data.drug.drug_name;
|
||||
// 选药后立刻带上真实单位,供新行数量后缀展示(优先接口返回的 unit)
|
||||
newDrugInfo.value.unit =
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug?.unit_id);
|
||||
newDrugInfo.value.unit_id = data.drug?.unit_id;
|
||||
setTimeout(() => {
|
||||
// 获取新药品卡片中的克数输入框并聚焦
|
||||
// 获取新药品卡片中的数量输入框并聚焦
|
||||
const newDrugNumberInput = document.querySelector(
|
||||
'.new-number-input input',
|
||||
);
|
||||
@@ -2154,8 +2159,10 @@ function selectOldDrugInfo(id) {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item) => item.id === data.drug.frequency_id,
|
||||
),
|
||||
// 药品单位信息
|
||||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品单位:优先用选药接口返回的 unit,再回退本地字典
|
||||
unit:
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品价格
|
||||
price: data.price,
|
||||
buy_price: data.buy_price,
|
||||
@@ -2295,8 +2302,10 @@ function addProducts(data) {
|
||||
use_frequency: drugUseFrequency.value.find(
|
||||
(item) => item.id === data.drug.frequency_id,
|
||||
),
|
||||
// 药品单位信息
|
||||
unit: drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品单位:优先用选药接口返回的 unit,再回退本地字典
|
||||
unit:
|
||||
data.drug?.unit ||
|
||||
drugUnit.value.find((item) => item.id === data.drug.unit_id),
|
||||
// 药品价格
|
||||
price: data.price,
|
||||
buy_price: data.buy_price,
|
||||
@@ -2910,7 +2919,7 @@ watch(
|
||||
@blur="updateChineseNumber"
|
||||
@keydown="updateChineseNumberGoNewDrug($event)"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ drug.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
,
|
||||
<span>
|
||||
@@ -2993,7 +3002,7 @@ watch(
|
||||
@blur="newDrugBlur"
|
||||
@keydown="selectDrugByNewDrugInfo($event, true)"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
,
|
||||
<span>
|
||||
@@ -3067,7 +3076,7 @@ watch(
|
||||
@keydown="selectDrugByNewDrugInfo($event, true)"
|
||||
disabled
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
,
|
||||
<span>
|
||||
@@ -3141,7 +3150,7 @@ watch(
|
||||
@keydown="selectDrugByNewDrugInfo($event, true)"
|
||||
disabled
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ newDrugInfo.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
,
|
||||
<span>
|
||||
@@ -3270,7 +3279,7 @@ watch(
|
||||
class="w-full"
|
||||
@blur="updateChineseNumber"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
<template #addonAfter>{{ drug.unit?.name || 'g' }}</template>
|
||||
</InputNumber>
|
||||
</div>
|
||||
<div v-else class="quantity-control">
|
||||
|
||||
@@ -187,6 +187,8 @@ const newDrugInfo = ref<{
|
||||
number?: number;
|
||||
price?: number;
|
||||
way_id?: number;
|
||||
unit_id?: number;
|
||||
unit?: { id: number; name: string } | null;
|
||||
}>({});
|
||||
|
||||
// ==================== 计算属性 ====================
|
||||
@@ -418,8 +420,12 @@ function selectNewDrug(drugId: number) {
|
||||
newDrugInfo.value.name = selectedItem.drug?.drug_name || '';
|
||||
newDrugInfo.value.price = selectedItem.price || 0;
|
||||
newDrugInfo.value.way_id = 0;
|
||||
newDrugInfo.value.unit =
|
||||
selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
newDrugInfo.value.unit_id =
|
||||
selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
|
||||
// 聚焦到克数输入框
|
||||
// 聚焦到数量输入框
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector('.new-chinese-number input') as HTMLInputElement;
|
||||
if (numberInput) {
|
||||
@@ -462,6 +468,8 @@ function addChineseDrug() {
|
||||
number: newDrugInfo.value.number,
|
||||
price: newDrugInfo.value.price || 0,
|
||||
way_id: newDrugInfo.value.way_id || 0,
|
||||
unit_id: newDrugInfo.value.unit_id || 0,
|
||||
unit: newDrugInfo.value.unit || null,
|
||||
});
|
||||
|
||||
// 清空并准备下一次输入
|
||||
@@ -512,9 +520,11 @@ function changeChineseDrug(index: number, drugId: number) {
|
||||
drug.drug_id = drugId;
|
||||
drug.drug_name = selectedItem.drug?.drug_name || '';
|
||||
drug.price = selectedItem.price || 0;
|
||||
drug.unit = selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
drug.unit_id = selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
}
|
||||
|
||||
// 聚焦到克数输入框
|
||||
// 聚焦到数量输入框
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector(`.chinese-number-${index} input`) as HTMLInputElement;
|
||||
if (numberInput) {
|
||||
@@ -705,6 +715,8 @@ async function handleSave() {
|
||||
number: drug.number || 1,
|
||||
price: drug.price || 0,
|
||||
way_id: drug.way_id || 0,
|
||||
unit_id: drug.unit_id || 0,
|
||||
unit: drug.unit || null,
|
||||
}));
|
||||
|
||||
await saveChineseCommonPrescriptionApi({
|
||||
@@ -731,6 +743,8 @@ async function handleSave() {
|
||||
number: drug.number || 1,
|
||||
price: drug.price || 0,
|
||||
way_id: drug.way_id || 0,
|
||||
unit_id: drug.unit_id || 0,
|
||||
unit: drug.unit || null,
|
||||
}));
|
||||
|
||||
await saveGranularCommonPrescriptionApi({
|
||||
@@ -1118,7 +1132,7 @@ async function handleSave() {
|
||||
:min="1"
|
||||
style="width: 60px"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ drug.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="drug.way_id"
|
||||
@@ -1181,7 +1195,7 @@ async function handleSave() {
|
||||
style="width: 60px"
|
||||
@keydown="(e) => handleChineseKeydown(e, true)"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ newDrugInfo.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="newDrugInfo.way_id"
|
||||
|
||||
@@ -187,6 +187,8 @@ const newDrugInfo = ref<{
|
||||
number?: number;
|
||||
price?: number;
|
||||
way_id?: number;
|
||||
unit_id?: number;
|
||||
unit?: { id: number; name: string } | null;
|
||||
}>({});
|
||||
|
||||
// ==================== 计算属性 ====================
|
||||
@@ -460,8 +462,13 @@ function selectNewDrug(drugId: number) {
|
||||
newDrugInfo.value.name = selectedItem.drug?.drug_name || '';
|
||||
newDrugInfo.value.price = selectedItem.price || 0;
|
||||
newDrugInfo.value.way_id = 0;
|
||||
// 选药后带上真实单位,供数量后缀展示
|
||||
newDrugInfo.value.unit =
|
||||
selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
newDrugInfo.value.unit_id =
|
||||
selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
|
||||
// 聚焦到克数输入框
|
||||
// 聚焦到数量输入框
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector('.edit-new-chinese-number input') as HTMLInputElement;
|
||||
if (numberInput) {
|
||||
@@ -504,6 +511,8 @@ function addChineseDrug() {
|
||||
number: newDrugInfo.value.number,
|
||||
price: newDrugInfo.value.price || 0,
|
||||
way_id: newDrugInfo.value.way_id || 0,
|
||||
unit_id: newDrugInfo.value.unit_id || 0,
|
||||
unit: newDrugInfo.value.unit || null,
|
||||
});
|
||||
|
||||
// 清空并准备下一次输入
|
||||
@@ -554,9 +563,11 @@ function changeChineseDrug(index: number, drugId: number) {
|
||||
drug.drug_id = drugId;
|
||||
drug.drug_name = selectedItem.drug?.drug_name || '';
|
||||
drug.price = selectedItem.price || 0;
|
||||
drug.unit = selectedItem.drug?.unit || selectedItem.unit || null;
|
||||
drug.unit_id = selectedItem.drug?.unit_id || selectedItem.unit_id || 0;
|
||||
}
|
||||
|
||||
// 聚焦到克数输入框
|
||||
// 聚焦到数量输入框
|
||||
nextTick(() => {
|
||||
const numberInput = document.querySelector(`.edit-chinese-number-${index} input`) as HTMLInputElement;
|
||||
if (numberInput) {
|
||||
@@ -733,6 +744,8 @@ async function handleSave() {
|
||||
number: drug.number || 1,
|
||||
price: drug.price || 0,
|
||||
way_id: drug.way_id || 0,
|
||||
unit_id: drug.unit_id || 0,
|
||||
unit: drug.unit || null,
|
||||
}));
|
||||
|
||||
await updateChineseCommonPrescriptionApi({
|
||||
@@ -759,6 +772,8 @@ async function handleSave() {
|
||||
number: drug.number || 1,
|
||||
price: drug.price || 0,
|
||||
way_id: drug.way_id || 0,
|
||||
unit_id: drug.unit_id || 0,
|
||||
unit: drug.unit || null,
|
||||
}));
|
||||
|
||||
await updateGranularCommonPrescriptionApi({
|
||||
@@ -1136,7 +1151,7 @@ async function handleSave() {
|
||||
:min="1"
|
||||
style="width: 60px"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ drug.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="drug.way_id"
|
||||
@@ -1199,7 +1214,7 @@ async function handleSave() {
|
||||
style="width: 60px"
|
||||
@keydown="(e) => handleChineseKeydown(e, true)"
|
||||
/>
|
||||
<span class="chinese-drug-unit">g</span>
|
||||
<span class="chinese-drug-unit">{{ newDrugInfo.unit?.name || 'g' }}</span>
|
||||
<span class="chinese-drug-comma">,</span>
|
||||
<Select
|
||||
v-model:value="newDrugInfo.way_id"
|
||||
|
||||
@@ -16,13 +16,6 @@ export async function getDeliveryWarehouseOrderDetail(id: number | string) {
|
||||
return requestClient.get<any>(`${prefix}detail`, { params: { id } });
|
||||
}
|
||||
|
||||
/**
|
||||
* 按订单查物流轨迹(复用平台 express-detail 接口)
|
||||
*/
|
||||
export async function expressDetailByOrderId(data: Record<string, any>) {
|
||||
return requestClient.post<any>(`express-detail/detail-by-order`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配送仓库订单发货
|
||||
*/
|
||||
|
||||
@@ -5,17 +5,13 @@ import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, Descriptions, Image, Tabs, Tag, Timeline } from 'ant-design-vue';
|
||||
|
||||
import {
|
||||
expressDetailByOrderId,
|
||||
getDeliveryWarehouseOrderDetail,
|
||||
} from '#/views/system/delivery-warehouse-order/api';
|
||||
import { getDeliveryWarehouseOrderDetail } from '#/views/system/delivery-warehouse-order/api';
|
||||
|
||||
defineOptions({
|
||||
name: 'DeliveryWarehouseOrderDetailModal',
|
||||
});
|
||||
|
||||
const data = ref<Record<string, any>>({});
|
||||
const expressDetail = ref<Record<string, any>>({});
|
||||
const scrollToLogistics = ref(false);
|
||||
const logisticsAnchorRef = ref<HTMLElement | null>(null);
|
||||
/** 待发货时由列表传入,点击后关详情并打开发货弹窗 */
|
||||
@@ -29,13 +25,9 @@ const canShip = computed(() => {
|
||||
Number(data.value.status) === 1;
|
||||
return (mineUnsent || legacy) && typeof onShipFn.value === 'function';
|
||||
});
|
||||
/** 仅使用仓侧详情返回的本仓 packages,避免平台物流接口带出他仓商品 */
|
||||
const packageTabs = computed(() => {
|
||||
const packages = Array.isArray(data.value.packages)
|
||||
? data.value.packages
|
||||
: Array.isArray(expressDetail.value.packages)
|
||||
? expressDetail.value.packages
|
||||
: [];
|
||||
return packages;
|
||||
return Array.isArray(data.value.packages) ? data.value.packages : [];
|
||||
});
|
||||
const activePkg = ref('0');
|
||||
|
||||
@@ -58,27 +50,17 @@ const deliveryMethodMap: Record<number, string> = {
|
||||
};
|
||||
|
||||
/**
|
||||
* 拉取订单详情;已发货时继续拉物流轨迹
|
||||
* 拉取仓侧订单详情(含本仓药品 + 本仓包裹物流)
|
||||
*/
|
||||
async function loadDetail(id: number | string) {
|
||||
data.value = (await getDeliveryWarehouseOrderDetail(id)) || {};
|
||||
expressDetail.value = {};
|
||||
const sent =
|
||||
Number(data.value.is_send) === 1 ||
|
||||
Number(data.value.status) >= 2 ||
|
||||
!!data.value.express_no_id;
|
||||
if (sent && data.value.id) {
|
||||
try {
|
||||
expressDetail.value = await expressDetailByOrderId({
|
||||
order_id: data.value.id,
|
||||
});
|
||||
} catch {
|
||||
expressDetail.value = {};
|
||||
}
|
||||
}
|
||||
activePkg.value = '0';
|
||||
if (scrollToLogistics.value) {
|
||||
await nextTick();
|
||||
logisticsAnchorRef.value?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
logisticsAnchorRef.value?.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +101,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
data.value = {};
|
||||
expressDetail.value = {};
|
||||
scrollToLogistics.value = false;
|
||||
onShipFn.value = null;
|
||||
return;
|
||||
@@ -233,7 +214,11 @@ const [Modal, modalApi] = useVbenModal({
|
||||
|
||||
<section ref="logisticsAnchorRef">
|
||||
<h3 class="section-title">物流信息</h3>
|
||||
<Tabs v-if="packageTabs.length" v-model:active-key="activePkg" type="card">
|
||||
<Tabs
|
||||
v-if="packageTabs.length"
|
||||
v-model:active-key="activePkg"
|
||||
type="card"
|
||||
>
|
||||
<Tabs.TabPane
|
||||
v-for="(pkg, idx) in packageTabs"
|
||||
:key="String(idx)"
|
||||
@@ -256,7 +241,9 @@ const [Modal, modalApi] = useVbenModal({
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<div
|
||||
v-if="Array.isArray(pkg.express.detail) && pkg.express.detail.length"
|
||||
v-if="
|
||||
Array.isArray(pkg.express.detail) && pkg.express.detail.length
|
||||
"
|
||||
class="mt-4"
|
||||
>
|
||||
<Timeline>
|
||||
@@ -264,7 +251,9 @@ const [Modal, modalApi] = useVbenModal({
|
||||
v-for="(detail, dIdx) in pkg.express.detail"
|
||||
:key="dIdx"
|
||||
>
|
||||
<Tag :color="getColor(detail.status)">{{ detail.status }}</Tag>
|
||||
<Tag :color="getColor(detail.status)">{{
|
||||
detail.status
|
||||
}}</Tag>
|
||||
<p>{{ detail.detail_at }}</p>
|
||||
<p>{{ detail.detail }}</p>
|
||||
</Timeline.Item>
|
||||
@@ -279,8 +268,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
v-else-if="
|
||||
Number(data.is_send) === 1 ||
|
||||
Number(data.status) >= 2 ||
|
||||
expressNoRow().express_no ||
|
||||
expressDetail.express_no
|
||||
expressNoRow().express_no
|
||||
"
|
||||
>
|
||||
<Descriptions
|
||||
@@ -289,33 +277,12 @@ const [Modal, modalApi] = useVbenModal({
|
||||
size="small"
|
||||
>
|
||||
<Descriptions.Item label="物流公司">
|
||||
{{
|
||||
expressDetail.express_company_name ||
|
||||
expressNoRow().express_company_name ||
|
||||
'-'
|
||||
}}
|
||||
{{ expressNoRow().express_company_name || '-' }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="运单号">
|
||||
{{
|
||||
expressDetail.express_no || expressNoRow().express_no || '-'
|
||||
}}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="最新状态">
|
||||
{{ expressDetail.state_txt || '-' }}
|
||||
{{ expressNoRow().express_no || '-' }}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
<div v-if="Array.isArray(expressDetail.detail) && expressDetail.detail.length" class="mt-4">
|
||||
<Timeline>
|
||||
<Timeline.Item
|
||||
v-for="(detail, index) in expressDetail.detail"
|
||||
:key="index"
|
||||
>
|
||||
<Tag :color="getColor(detail.status)">{{ detail.status }}</Tag>
|
||||
<p>{{ detail.detail_at }}</p>
|
||||
<p>{{ detail.detail }}</p>
|
||||
</Timeline.Item>
|
||||
</Timeline>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="empty-tip">暂无物流</div>
|
||||
</section>
|
||||
|
||||
@@ -48,9 +48,11 @@ const [Modal, modalApi] = useVbenModal({
|
||||
onOpenChange(isOpen: boolean) {
|
||||
gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
|
||||
if (isOpen) {
|
||||
const { values, update } = modalApi.getData<Record<string, any>>();
|
||||
const { values, update } = modalApi.getData<Record<string, any>>() || {};
|
||||
isUpdate.value = !!update;
|
||||
// 新建时清空表单,避免残留编辑态的 id/证照
|
||||
formApi.resetForm();
|
||||
if (values) {
|
||||
isUpdate.value = update;
|
||||
formApi.setValues(values);
|
||||
}
|
||||
}
|
||||
@@ -60,7 +62,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
<template>
|
||||
<Modal
|
||||
:title="`${isUpdate === true ? '编辑' : '新增'}配送仓库`"
|
||||
class="w-[40%]"
|
||||
class="w-[720px]"
|
||||
>
|
||||
<Form />
|
||||
</Modal>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type { VbenFormProps } from '#/adapter/form';
|
||||
|
||||
/**
|
||||
* 配送仓库新建/编辑:仅基本信息
|
||||
* 合同与银行卡走独立报备入口,不在此表单填写
|
||||
* 配送仓库新建/编辑
|
||||
* - 三证必填,其余证照/合同选填
|
||||
* - 联系人/手机号仅新建时展示,用于开通仓管理员
|
||||
* - 银行卡仍走独立报备入口
|
||||
*/
|
||||
export const modalFormProps: VbenFormProps = {
|
||||
wrapperClass: 'grid-cols-12',
|
||||
@@ -41,6 +43,87 @@ export const modalFormProps: VbenFormProps = {
|
||||
fieldName: 'introduce',
|
||||
label: '仓库介绍',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '联系人姓名(将作为仓管理员昵称)',
|
||||
},
|
||||
fieldName: 'contact_name',
|
||||
label: '联系人',
|
||||
rules: 'required',
|
||||
help: '新建时用于开通配送仓库管理员账号',
|
||||
dependencies: {
|
||||
// 仅新建展示;编辑改账号请走「配送仓管理员」菜单
|
||||
if({ id }: { id?: number | string }) {
|
||||
return !id;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '手机号(仓管理员登录手机)',
|
||||
},
|
||||
fieldName: 'phone',
|
||||
label: '手机号',
|
||||
rules: 'required',
|
||||
help: '默认初始密码 Xk123456@',
|
||||
dependencies: {
|
||||
if({ id }: { id?: number | string }) {
|
||||
return !id;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'business_license_image',
|
||||
label: '营业执照',
|
||||
rules: 'required',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'drug_license_image',
|
||||
label: '药品经营许可证',
|
||||
rules: 'required',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'medical_device_license_image',
|
||||
label: '医疗器械经营许可证',
|
||||
rules: 'required',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'food_license_image',
|
||||
label: '食品经营许可证',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'pharmacist_certificate_image',
|
||||
label: '药师资格证',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'internet_drug_license_image',
|
||||
label: '互联网药品经营许可证',
|
||||
formItemClass: 'col-span-4',
|
||||
},
|
||||
{
|
||||
component: 'UploadOssFile',
|
||||
componentProps: {
|
||||
maxCount: 1,
|
||||
},
|
||||
fieldName: 'contract_attachment',
|
||||
label: '合同附件',
|
||||
formItemClass: 'col-span-12',
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* 平台配送仓库列表
|
||||
* 新建/编辑仅基本信息;银行卡报备对齐诊所,走独立弹窗
|
||||
* 新建/编辑含证照与建仓开号;银行卡报备对齐诊所,走独立弹窗
|
||||
*/
|
||||
import type { VxeGridListeners } from '#/adapter/vxe-table';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user