|
@@ -1,6 +1,6 @@
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
import { ref, reactive, watch, onMounted, defineEmits, nextTick } from 'vue';
|
|
import { ref, reactive, watch, onMounted, defineEmits, nextTick } from 'vue';
|
|
|
-import { message } from 'ant-design-vue';
|
|
|
|
|
|
|
+import { notification } from 'ant-design-vue';
|
|
|
import { PlusOutlined } from '@ant-design/icons-vue';
|
|
import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
import { branchMethod } from '@/request/api/system.api';
|
|
import { branchMethod } from '@/request/api/system.api';
|
|
|
import { useRequest } from 'alova/client';
|
|
import { useRequest } from 'alova/client';
|
|
@@ -43,10 +43,10 @@ const supplierOptions = ref<any[]>([]);
|
|
|
const supplierArr = ref<any[]>([]);
|
|
const supplierArr = ref<any[]>([]);
|
|
|
supplierOptions.value = [];
|
|
supplierOptions.value = [];
|
|
|
function getSupplier(params: any) {
|
|
function getSupplier(params: any) {
|
|
|
- getAllSupplierMethod(params).then((res) => {
|
|
|
|
|
- if (res?.length > 0) {
|
|
|
|
|
- supplierArr.value = res;
|
|
|
|
|
- supplierOptions.value = res.map((item: any) => ({
|
|
|
|
|
|
|
+ getAllSupplierMethod(params).then((res: unknown) => {
|
|
|
|
|
+ if (Array.isArray(res) && res.length > 0) {
|
|
|
|
|
+ supplierArr.value = res as any[];
|
|
|
|
|
+ supplierOptions.value = (res as any[]).map((item: any) => ({
|
|
|
label: item.name,
|
|
label: item.name,
|
|
|
value: item.id,
|
|
value: item.id,
|
|
|
}));
|
|
}));
|
|
@@ -149,11 +149,19 @@ const handlePreview = async (file: UploadFile) => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
function removeHerb(idx: number) {
|
|
function removeHerb(idx: number) {
|
|
|
- props.data.cpMedicines.splice(idx, 1);
|
|
|
|
|
|
|
+ if (Array.isArray(props.data.cpMedicines)) {
|
|
|
|
|
+ // eslint-disable-next-line vue/no-mutating-props
|
|
|
|
|
+ props.data.cpMedicines.splice(idx, 1);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function addHerb() {
|
|
function addHerb() {
|
|
|
- props.data.cpMedicines.push({ name: '', dosage: '', unit: 'g' });
|
|
|
|
|
|
|
+ if (!Array.isArray(props.data.cpMedicines)) {
|
|
|
|
|
+ // eslint-disable-next-line vue/no-mutating-props
|
|
|
|
|
+ props.data.cpMedicines = [] as any[];
|
|
|
|
|
+ }
|
|
|
|
|
+ // eslint-disable-next-line vue/no-mutating-props
|
|
|
|
|
+ (props.data.cpMedicines as any[]).push({ name: '', dosage: '' } as any);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function handleCancel() {
|
|
function handleCancel() {
|
|
@@ -165,14 +173,141 @@ const emit = defineEmits<{
|
|
|
(e: 'submit', data: SystemItemModel): void;
|
|
(e: 'submit', data: SystemItemModel): void;
|
|
|
}>();
|
|
}>();
|
|
|
|
|
|
|
|
|
|
+function validate(): boolean {
|
|
|
|
|
+ const d = props.data as any;
|
|
|
|
|
+ // 计价规则 必填
|
|
|
|
|
+ if (d.pricingType === undefined || d.pricingType === null || d.pricingType === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择计价规则',
|
|
|
|
|
+ description: '请选择计价规则',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 单价 必填(当一口价时)
|
|
|
|
|
+ if (d.pricingType === '0') {
|
|
|
|
|
+ const unitPrice = d.cpFixedPricingRule?.unitPrice;
|
|
|
|
|
+ if (unitPrice === undefined || unitPrice === null || unitPrice === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写单价',
|
|
|
|
|
+ description: '请填写单价',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 计价单位 必填
|
|
|
|
|
+ if (!d.cpFixedPricingRule?.pricingUnit) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写计价单位',
|
|
|
|
|
+ description: '请填写计价单位',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 转换剂量 必填
|
|
|
|
|
+ if (!d.cpFixedPricingRule?.convertDose) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写转换剂量',
|
|
|
|
|
+ description: '请填写转换剂量',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 转换单位 必填
|
|
|
|
|
+ if (!d.cpFixedPricingRule?.convertUnit) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择转换单位',
|
|
|
|
|
+ description: '请选择转换单位',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 穴位/经络/部位 范围 必填(当动态计价时)
|
|
|
|
|
+ if (d.pricingType === '1') {
|
|
|
|
|
+ const rules = d.cpDynamicPricingRule;
|
|
|
|
|
+ if (!Array.isArray(rules) || rules.length < 2) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请完善穴位/经络/部位的计价规则',
|
|
|
|
|
+ description: '请完善穴位/经络/部位的计价规则',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证计价1
|
|
|
|
|
+ const rule1 = rules[0];
|
|
|
|
|
+ if (!rule1 || rule1.min === undefined || rule1.min === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写计价1的穴位/经络/部位范围',
|
|
|
|
|
+ description: '请填写计价1的穴位/经络/部位范围',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (rule1.priceType === undefined || rule1.priceType === null || rule1.priceType === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择计价1的计价类型',
|
|
|
|
|
+ description: '请选择计价1的计价类型',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!rule1.price || rule1.price === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写计价1的价格',
|
|
|
|
|
+ description: '请填写计价1的价格',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 验证计价2
|
|
|
|
|
+ const rule2 = rules[1];
|
|
|
|
|
+ if (!rule2 || rule2.max === undefined || rule2.max === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写计价2的穴位/经络/部位范围',
|
|
|
|
|
+ description: '请填写计价2的穴位/经络/部位范围',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (rule2.priceType === undefined || rule2.priceType === null || rule2.priceType === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择计价2的计价类型',
|
|
|
|
|
+ description: '请选择计价2的计价类型',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!rule2.price || rule2.price === '') {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请填写计价2的价格',
|
|
|
|
|
+ description: '请填写计价2的价格',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 机构 必填
|
|
|
|
|
+ if (!d.institutionId) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择机构名称',
|
|
|
|
|
+ description: '请选择机构名称',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 供应商 必填
|
|
|
|
|
+ if (!d.conditioningProgramSupplierId) {
|
|
|
|
|
+ notification.error({
|
|
|
|
|
+ message: '请选择供应商',
|
|
|
|
|
+ description: '请选择供应商',
|
|
|
|
|
+ });
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function handleOk() {
|
|
function handleOk() {
|
|
|
|
|
+ if (!validate()) return;
|
|
|
if (showOffLine.value && !props.data.isOffline) {
|
|
if (showOffLine.value && !props.data.isOffline) {
|
|
|
props.data.isOffline = 'N';
|
|
props.data.isOffline = 'N';
|
|
|
}
|
|
}
|
|
|
- confirmOrgConfirmMethod(props.data).then(() => {
|
|
|
|
|
- emit('submit', props.data);
|
|
|
|
|
|
|
+ confirmOrgConfirmMethod(props.data as SystemItemModel).then(() => {
|
|
|
|
|
+ emit('submit', props.data as SystemItemModel);
|
|
|
VxeUI.modal.close('confirm-item-modal');
|
|
VxeUI.modal.close('confirm-item-modal');
|
|
|
- message.success('提交成功');
|
|
|
|
|
|
|
+ notification.success({
|
|
|
|
|
+ message: '提交成功',
|
|
|
|
|
+ description: '提交成功',
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
// 创建一个响应式变量来控制 checkbox 的状态
|
|
// 创建一个响应式变量来控制 checkbox 的状态
|
|
@@ -217,26 +352,26 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
<div>{{ data.conditioningProgramType }}</div>
|
|
<div>{{ data.conditioningProgramType }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
- <label>计价规则:</label>
|
|
|
|
|
|
|
+ <label><span class="required-star">*</span>计价规则:</label>
|
|
|
<div>{{ data.pricingType === '0' ? '一口价' : '按穴位/经络/部位' }}</div>
|
|
<div>{{ data.pricingType === '0' ? '一口价' : '按穴位/经络/部位' }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="form-row" v-if="data.pricingType === '0'">
|
|
<div class="form-row" v-if="data.pricingType === '0'">
|
|
|
- <label>单价:</label>
|
|
|
|
|
- <a-input v-model:value="data.cpFixedPricingRule.unitPrice" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
|
|
|
|
+ <label><span class="required-star">*</span>单价:</label>
|
|
|
|
|
+ <a-input v-model:value="data.cpFixedPricingRule!.unitPrice" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
<span style="margin-left: 20px">元</span>
|
|
<span style="margin-left: 20px">元</span>
|
|
|
<span style="margin-left: 20px">计价单位:</span>
|
|
<span style="margin-left: 20px">计价单位:</span>
|
|
|
- <a-input v-model:value="data.cpFixedPricingRule.pricingUnit" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
|
|
|
|
+ <a-input v-model:value="data.cpFixedPricingRule!.pricingUnit" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
<span style="margin-left: 20px">相当于</span>
|
|
<span style="margin-left: 20px">相当于</span>
|
|
|
- <a-input v-model:value="data.cpFixedPricingRule.convertDose" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
|
|
- <a-select v-model:value="data.cpFixedPricingRule.convertUnit" style="width: 60px; margin-left: 8px" :options="unitOptions" placeholder="请选择" />
|
|
|
|
|
|
|
+ <a-input v-model:value="data.cpFixedPricingRule!.convertDose" placeholder="请输入" style="width: 100px; margin-left: 8px" />
|
|
|
|
|
+ <a-select v-model:value="data.cpFixedPricingRule!.convertUnit" style="width: 60px; margin-left: 8px" :options="unitOptions" placeholder="请选择" />
|
|
|
<span style="color: #aaa; margin-left: 10px">(使用单位)</span>
|
|
<span style="color: #aaa; margin-left: 10px">(使用单位)</span>
|
|
|
</div>
|
|
</div>
|
|
|
<div v-if="data.pricingType === '1'" class="per-rule">
|
|
<div v-if="data.pricingType === '1'" class="per-rule">
|
|
|
<div class="price-row">
|
|
<div class="price-row">
|
|
|
- <span>计价1:</span>
|
|
|
|
|
- <span class="flex items-center">当"穴位/经络/部位" ≤ <a-input placeholder="请输入" class="w-20 ml-2 mr-2" v-model:value="data.cpDynamicPricingRule[0].min" />个时,</span>
|
|
|
|
|
|
|
+ <span><span class="required-star">*</span>计价1:</span>
|
|
|
|
|
+ <span class="flex items-center">当"穴位/经络/部位" ≤ <a-input placeholder="请输入" class="w-20 ml-2 mr-2" v-model:value="data.cpDynamicPricingRule![0].min" />个时,</span>
|
|
|
<a-select
|
|
<a-select
|
|
|
- v-model:value="data.cpDynamicPricingRule[0].priceType"
|
|
|
|
|
|
|
+ v-model:value="data.cpDynamicPricingRule![0].priceType"
|
|
|
:options="[
|
|
:options="[
|
|
|
{ label: '单价', value: 0, priceType: 0 },
|
|
{ label: '单价', value: 0, priceType: 0 },
|
|
|
{ label: '一口价', value: 1, priceType: 1 },
|
|
{ label: '一口价', value: 1, priceType: 1 },
|
|
@@ -245,16 +380,16 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
placeholder="请选择"
|
|
placeholder="请选择"
|
|
|
/>
|
|
/>
|
|
|
<span>=</span>
|
|
<span>=</span>
|
|
|
- <a-input v-model:value="data.cpDynamicPricingRule[0].price" style="width: 80px; margin: 0 4px" placeholder="请输入" />
|
|
|
|
|
|
|
+ <a-input v-model:value="data.cpDynamicPricingRule![0].price" style="width: 80px; margin: 0 4px" placeholder="请输入" />
|
|
|
<span>元</span>
|
|
<span>元</span>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="price-row">
|
|
<div class="price-row">
|
|
|
- <span>计价2:</span>
|
|
|
|
|
|
|
+ <span><span class="required-star">*</span>计价2:</span>
|
|
|
<span class="flex items-center"
|
|
<span class="flex items-center"
|
|
|
- >当"穴位/经络/部位" > <a-input placeholder="请输入" class="w-20 ml-2 mr-2" v-model:value="data.cpDynamicPricingRule[1].max" />个时,</span
|
|
|
|
|
|
|
+ >当"穴位/经络/部位" > <a-input placeholder="请输入" class="w-20 ml-2 mr-2" v-model:value="data.cpDynamicPricingRule![1].max" disabled />个时,</span
|
|
|
>
|
|
>
|
|
|
<a-select
|
|
<a-select
|
|
|
- v-model:value="data.cpDynamicPricingRule[1].priceType"
|
|
|
|
|
|
|
+ v-model:value="data.cpDynamicPricingRule![1].priceType"
|
|
|
:options="[
|
|
:options="[
|
|
|
{ label: '单价', value: 0, priceType: 0 },
|
|
{ label: '单价', value: 0, priceType: 0 },
|
|
|
{ label: '一口价', value: 1, priceType: 1 },
|
|
{ label: '一口价', value: 1, priceType: 1 },
|
|
@@ -263,7 +398,7 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
placeholder="请选择"
|
|
placeholder="请选择"
|
|
|
/>
|
|
/>
|
|
|
<span>=</span>
|
|
<span>=</span>
|
|
|
- <a-input v-model:value="data.cpDynamicPricingRule[1].price" style="width: 80px; margin: 0 4px" placeholder="请输入" />
|
|
|
|
|
|
|
+ <a-input v-model:value="data.cpDynamicPricingRule![1].price" style="width: 80px; margin: 0 4px" placeholder="请输入" />
|
|
|
<span>元</span>
|
|
<span>元</span>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -274,10 +409,12 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
<label>中药组成:</label>
|
|
<label>中药组成:</label>
|
|
|
<div class="herb-list">
|
|
<div class="herb-list">
|
|
|
- <template v-for="(herb, idx) in data.cpMedicines" :key="idx">
|
|
|
|
|
|
|
+ <template v-for="(herb, idx) in data.cpMedicines || []" :key="idx">
|
|
|
<div class="herb-item">
|
|
<div class="herb-item">
|
|
|
<button class="herb-remove" @click="removeHerb(idx)" type="button">×</button>
|
|
<button class="herb-remove" @click="removeHerb(idx)" type="button">×</button>
|
|
|
|
|
+ <!-- eslint-disable-next-line vue/no-mutating-props -->
|
|
|
<RemoteSelect :load="cpMedicinesMethod" key-prop="name" v-model:value="herb.name" />
|
|
<RemoteSelect :load="cpMedicinesMethod" key-prop="name" v-model:value="herb.name" />
|
|
|
|
|
+ <!-- eslint-disable-next-line vue/no-mutating-props -->
|
|
|
<a-input v-model:value="herb.dosage" class="herb-dosage" placeholder="剂量" />
|
|
<a-input v-model:value="herb.dosage" class="herb-dosage" placeholder="剂量" />
|
|
|
<span>g</span>
|
|
<span>g</span>
|
|
|
</div>
|
|
</div>
|
|
@@ -286,7 +423,8 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
- <label>机构名称:</label>
|
|
|
|
|
|
|
+ <label><span class="required-star">*</span>机构名称:</label>
|
|
|
|
|
+ <!-- eslint-disable-next-line vue/no-mutating-props -->
|
|
|
<a-tree-select
|
|
<a-tree-select
|
|
|
v-model:value="data.institutionId"
|
|
v-model:value="data.institutionId"
|
|
|
style="width: 400px"
|
|
style="width: 400px"
|
|
@@ -299,7 +437,8 @@ function handleSelect(value: string, node: any, extra: any) {
|
|
|
></a-tree-select>
|
|
></a-tree-select>
|
|
|
</div>
|
|
</div>
|
|
|
<div class="form-row">
|
|
<div class="form-row">
|
|
|
- <label>供应商:</label>
|
|
|
|
|
|
|
+ <label><span class="required-star">*</span>供应商:</label>
|
|
|
|
|
+ <!-- eslint-disable-next-line vue/no-mutating-props -->
|
|
|
<a-select v-model:value="data.conditioningProgramSupplierId" :options="supplierOptions" placeholder="请选择供应商" style="width: 400px" allow-clear class="mr-10" />
|
|
<a-select v-model:value="data.conditioningProgramSupplierId" :options="supplierOptions" placeholder="请选择供应商" style="width: 400px" allow-clear class="mr-10" />
|
|
|
<a-checkbox v-model:checked="isOffline" style="margin-right: 8px" @change="toggleOnlineStatus" v-show="showOffLine"> 线下项目 </a-checkbox>
|
|
<a-checkbox v-model:checked="isOffline" style="margin-right: 8px" @change="toggleOnlineStatus" v-show="showOffLine"> 线下项目 </a-checkbox>
|
|
|
</div>
|
|
</div>
|
|
@@ -356,6 +495,10 @@ html,
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
color: #222;
|
|
color: #222;
|
|
|
margin-right: 8px;
|
|
margin-right: 8px;
|
|
|
|
|
+ .required-star {
|
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
.form-container {
|
|
.form-container {
|
|
|
position: relative;
|
|
position: relative;
|
|
@@ -374,6 +517,10 @@ html,
|
|
|
width: 110px;
|
|
width: 110px;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
color: #222;
|
|
color: #222;
|
|
|
|
|
+ .required-star {
|
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
input,
|
|
input,
|
|
|
select {
|
|
select {
|
|
@@ -446,4 +593,8 @@ html,
|
|
|
height: 36px;
|
|
height: 36px;
|
|
|
margin-right: 10px;
|
|
margin-right: 10px;
|
|
|
}
|
|
}
|
|
|
|
|
+.required-star {
|
|
|
|
|
+ color: #ff4d4f;
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|