| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108 |
- <script setup lang="ts">
- import { useRoute } from 'vue-router';
- import { ref, computed, nextTick, h, watch, onMounted } from 'vue';
- import { MinusCircleOutlined, EyeOutlined } from '@ant-design/icons-vue';
- import { notification } from 'ant-design-vue';
- import { message } from 'ant-design-vue';
- import type { OpenConditioningSchemeModel, SystemCwModel } from '@/model/care.model';
- import PatientTagWidget from '@/widgets/PatientTagWidget.vue';
- import AcupointEdit from '@/service/AcupointEdit.vue';
- import ServiceDetail from '@/service/ServiceDetail.vue';
- import {
- getCpContentListMethod,
- getPatientListMethod,
- getConditioningRecordDetailMethod,
- getPatientConditioningRecordMethod,
- addConditioningSchemeMethod,
- getCpDetailMethod,
- getProvinceMethod,
- getCityMethod,
- getAreaMethod,
- getAvailableCwMethod,
- } from '@/request/api/care.api';
- import { patientMethod, patientTags } from '@/request/api/patient.api';
- import { useRequest, usePagination } from 'alova/client';
- import ServicePackageDetail from '@/service/ServicePackageDetail.vue';
- import { VxeUI } from 'vxe-pc-ui';
- import type { PatientTagModel } from '@/model/patient.model';
- import dayjs from 'dayjs';
- type FollowModel = Partial<OpenConditioningSchemeModel>;
- const props = defineProps<{ data: FollowModel }>();
- const form = reactive<FollowModel>({
- id: 0,
- patientId: '',
- patientName: '',
- patientSex: '',
- patientAge: 0,
- diagnosis: '',
- symptom: '',
- conditioningWrapId: '',
- conditioningWrapName: '',
- estimatedStartDate: '',
- estimatedEndDate: '',
- isDelivery: null,
- cost: 0,
- healthAnalysisReport: {
- willillStateName: '',
- willillDegreeName: '',
- willillSocialName: '',
- willillFunctionName: '',
- },
- patientMedicalRecord: {
- patientId: '', // 患者ID
- institutionId: '', // 机构ID
- institutionName: '', // 机构名称
- diagnosis: '', // 疾病
- symptom: '', // 症型
- syndrome: '', // 证状
- },
- items: [],
- provinceName: '',
- cityName: '',
- districtName: '',
- areaName: '',
- detailAddress: '',
- phone: '',
- progress: '0',
- photo: '',
- });
- const searchName = ref('');
- const selectedPackage = ref('');
- const currentSelectedPackage = ref<any>(null);
- const deliveryChecked = ref(true);
- const address = ref({
- province: '',
- city: '',
- district: '',
- detail: '',
- phone: '',
- });
- // 机构调理包
- const lifeCwData = ref([]);
- // 获取可用的服务包
- const suggestCwData = ref<string[]>([]);
- async function loadAvailableCw(patientId: string) {
- const res: any = await getAvailableCwMethod(patientId);
- if (res.length > 0) {
- lifeCwData.value = res;
- // 筛选出可推荐的
- suggestCwData.value = lifeCwData.value.filter((item: any) => item.isSuggest);
- }
- }
- export interface PatientModel {
- id: string;
- patientId: string;
- patientName: string;
- patientSex: string;
- patientAge: number;
- diagnosis: string;
- symptom: string;
- healthAnalysisReport: {
- willillStateName: string;
- willillDegreeName: string;
- willillSocialName: string;
- willillFunctionName: string;
- };
- constitutionGroupName: string;
- status?: string;
- }
- // 患者列表
- const patients = ref([]);
- // 患者详细信息
- interface CpDetail {
- womenSpecialPeriod?: string;
- cardno?: string;
- }
- let cpDetail = ref<CpDetail>({});
- async function getCpDetail(id: string) {
- await patientMethod(id).then((res2) => {
- cpDetail.value = res2;
- });
- }
- interface PatientRecord {
- id: string;
- estimatedStartDate: string;
- estimatedEndDate: string;
- }
- const patientRecord = ref<PatientRecord[]>([]);
- // 获取患者调养记录
- function getPatientRecord(id: any) {
- patientRecord.value = [];
- getPatientConditioningRecordMethod(id).then((res) => {
- if (res && res.length > 0) {
- patientRecord.value = res;
- }
- });
- }
- // const report=ref({})
- async function getCpRecordDetail(id: string) {
- await getCpDetailMethod({ id }).then((res) => {
- formData.items = res?.items ?? [];
- // form = res;
- form.conditioningWrapName = res?.conditioningWrapName;
- form.estimatedStartDate = res?.estimatedStartDate;
- form.estimatedEndDate = res?.estimatedEndDate;
- form.provinceName = res?.provinceName;
- form.cityName = res?.cityName;
- form.districtName = res?.districtName;
- form.areaName = res?.areaName;
- form.detailAddress = res?.detailAddress;
- form.phone = res?.phone;
- form.healthAnalysisReport = res.healthAnalysisReport;
- });
- }
- async function getPatientList(id: string) {
- console.log(id, '切换');
- if (id) {
- getCpDetail(id);
- loadTags(id);
- getPatientRecord(id);
- }
- }
- const route = useRoute();
- onMounted(async () => {
- const id = Number(route.query.id); // 获取查询参数 id
- // 获取患者列表
- const res: any = await getPatientListMethod();
- if (res && res.length > 0) {
- if (id) {
- let index = res.findIndex((item: any) => item.patientId === id);
- currentPatient.value = res[index];
- } else {
- currentPatient.value = res[0];
- }
- patients.value = res;
- }
- if (currentPatient.value?.patientId) {
- // 获取患者列表
- await getPatientList(currentPatient.value?.patientId || '');
- // 获取服务包选择列表
- await loadAvailableCw(currentPatient.value?.patientId || '');
- }
- if (currentPatient.value?.id) {
- // 获取调养记录
- await getCpRecordDetail(currentPatient.value?.id || '');
- }
- // 获取省份
- await loadProvinces();
- });
- // 患者标签
- const tags = ref<PatientTagModel>({ id: '', tags: [] });
- function loadTags(patientId: string) {
- patientTags(patientId).then((res) => {
- tags.value = res;
- });
- }
- // 展示的患者数据
- const filteredPatients: any = computed(() => patients.value.filter((p: any) => p.patientName.includes(searchName.value)));
- // 默认显示第一个患者
- const currentPatient = ref<PatientModel>();
- // 点击切换患者
- async function selectPatient(item: any) {
- currentPatient.value = item;
- // 获取患者信息
- await getPatientList(item.patientId);
- await loadAvailableCw(item.patientId || '');
- // 获取患者调养记录
- await getCpRecordDetail(item.id);
- // 清空服务包选择
- selectedPackage.value = '';
- currentSelectedPackage.value = null;
- }
- // 打开调养记录
- function openRecord(item: any) {
- const types = 'record';
- VxeUI.modal.open({
- id: 'servicePackageDetail-modal',
- title: '调养记录',
- height: 700,
- width: 1200,
- escClosable: true,
- destroyOnClose: true,
- slots: {
- default() {
- return h(ServicePackageDetail, <any>{
- data: { ...item, types },
- });
- },
- },
- });
- }
- const formData = reactive<FollowModel>({
- price: 0, //总计价格
- cwPatientMatchRules: [
- {
- diagnoseDiseaseNames: [],
- diagnoseSyndromeNames: [],
- constitutionGroupNames: [],
- diagnoseDisease: {
- id: '',
- code: '',
- name: '',
- optionalWords: '',
- attributes: [],
- children: [],
- },
- diagnoseSyndrome: {
- code: '',
- name: '',
- analysis: '',
- remark: '',
- },
- constitutionGroup: {
- id: '',
- code: '',
- name: '',
- definition: '',
- remark: '',
- },
- },
- ], // 适用情况
- items: [], // Initialize as empty array
- });
- const emptyRow = {
- id: '',
- conditioningWrapId: '',
- conditioningProgramId: 0,
- days: '',
- frequencyType: '',
- frequencyMeasure: '',
- totalMeasure: '',
- totalPrice: '',
- initialDay: '',
- conditioningProgramDetail: {
- id: '',
- name: '',
- conditioningProgramType: '',
- pricingType: '',
- cpFixedPricingRule: {
- unitPrice: 0,
- pricingUnit: '',
- convertDose: 0,
- convertUnit: '',
- },
- cpDynamicPricingRule: [],
- cpMedicines: [],
- effect: '',
- isOffline: null,
- isDelivery: null,
- photo: '',
- institutionId: '',
- institutionName: '',
- remark: '',
- },
- cwcpAcuMeridians: [],
- cwcpAcuPoints: [],
- conditioningProgramSupplierName: '',
- };
- const projectSearch = ref('');
- const showProjectPopover = ref(false);
- const displayTableData = computed(() => {
- return [...(formData.items ?? []), { ...emptyRow }];
- });
- const isShowDelivery = ref<boolean>(false);
- // 监听 displayTableData 的变化
- watch(displayTableData, (newValue, oldValue) => {
- console.log('displayTableData 变化了:', newValue);
- if (newValue.length > 0) {
- isShowDelivery.value = newValue.some((item) => {
- return item.conditioningProgramDetail?.isDelivery === 'Y';
- });
- }
- });
- const totalPrice = computed(() => {
- return (formData.items ?? []).reduce((sum, row) => {
- const price = Number(row?.totalPrice) || 0;
- return sum + price;
- }, 0);
- });
- function onSelectProject({ row }: any) {
- if ((formData.items ?? []).some((item) => item.conditioningProgramDetail?.name === row.name)) {
- message.warning('不能重复添加该项目');
- return;
- }
- // 添加新行到主表格
- if (!formData.items) formData.items = [];
- formData.items.push({
- id: '',
- conditioningProgramId: row.id || '',
- // conditioningProgramId: 0,
- days: '',
- frequencyType: '',
- frequencyMeasure: '',
- totalMeasure: '',
- totalPrice: '',
- initialDay: '',
- cwcpAcuMeridians: [
- {
- id: 0,
- name: '',
- code: '',
- type: '',
- photo: '',
- },
- ],
- cwcpAcuPoints: [
- {
- id: 0,
- name: '',
- code: '',
- type: '',
- merName: '',
- photo: '',
- },
- ],
- conditioningProgramDetail: {
- ...row,
- id: row.id || '',
- name: row.name || '',
- conditioningProgramType: row.conditioningProgramType || '',
- effect: row.effect || '',
- pricingType: row.pricingType || '',
- cpFixedPricingRule: {
- unitPrice: row?.cpFixedPricingRule?.unitPrice || 0,
- pricingUnit: row?.cpFixedPricingRule?.pricingUnit || '',
- convertDose: row?.cpFixedPricingRule?.convertDose || 0,
- convertUnit: row?.cpFixedPricingRule?.convertUnit || '',
- },
- cpDynamicPricingRule: row?.cpDynamicPricingRule || [],
- cpMedicines: row?.cpMedicines || [],
- isOffline: row?.isOffline || null,
- isDelivery: row?.isDelivery || null,
- photo: row?.photo || '',
- conditioningProgramSupplierName: row?.conditioningProgramSupplierName || '',
- },
- remark: '',
- });
- // 关闭弹窗
- showProjectPopover.value = false;
- // 清空搜索
- projectSearch.value = '';
- }
- function removeTableRow(idx: number) {
- if (idx < (formData.items ?? []).length) {
- formData.items?.splice(idx, 1);
- }
- }
- function onPreview(row) {
- if (row.conditioningProgramDetail.id) {
- // 这里写你的预览逻辑
- VxeUI.modal.open({
- title: `预览`,
- height: 600,
- width: 950,
- escClosable: true,
- destroyOnClose: true,
- id: `preview-modal`,
- remember: true,
- storage: true,
- slots: {
- default() {
- return h(ServiceDetail, {
- data: row.conditioningProgramDetail,
- onSubmit(data: SystemCwModel) {
- VxeUI.modal.close(`preview-modal`);
- },
- });
- },
- },
- });
- } else {
- message.warning('请先添加服务包');
- }
- }
- function detailPreview(row) {
- if (row.id) {
- // 这里写你的预览逻辑
- VxeUI.modal.open({
- title: `预览`,
- height: 600,
- width: 950,
- escClosable: true,
- destroyOnClose: true,
- id: `preview-modal`,
- remember: true,
- storage: true,
- slots: {
- default() {
- return h(ServiceDetail, {
- data: row,
- onSubmit: (data) => {
- VxeUI.modal.close(`preview-modal`);
- },
- });
- },
- },
- });
- showProjectPopover.value = false;
- } else {
- message.warning('请先添加服务包');
- }
- }
- function editPart(row) {
- if (row.conditioningProgramDetail.id) {
- VxeUI.modal.open({
- title: `编辑部位`,
- height: 700,
- width: 750,
- escClosable: true,
- destroyOnClose: true,
- id: `edit-part-modal`,
- remember: true,
- storage: true,
- slots: {
- default() {
- return h(AcupointEdit, <any>{
- data: row,
- onSubmit(data: PlanModel) {
- refresh(page.value);
- VxeUI.modal.close(`edit-part-modal`);
- },
- });
- },
- },
- });
- } else {
- message.warning('请先添加服务包');
- }
- }
- const allProjects = ref<
- Array<{
- name: string;
- conditioningProgramType?: string;
- effect?: string;
- }>
- >([]);
- const {
- loading: projectLoading,
- onSuccess,
- refresh,
- remove,
- } = usePagination(() => getCpContentListMethod(), {
- initialData: { data: [], total: 0 },
- immediate: true,
- });
- onSuccess(({ data }) => {
- allProjects.value = data;
- });
- const filteredProjects = computed(() => {
- const searchText = projectSearch.value.toLowerCase();
- return allProjects.value.filter(
- (p) => p.name.toLowerCase().includes(searchText) || p?.conditioningProgramType?.toLowerCase().includes(searchText) || p.effect?.toLowerCase().includes(searchText)
- );
- });
- // 添加计算数量的函数
- function calculateCount(row: any) {
- const period = Number(row.days) || 0;
- const frequency = Number(row.frequencyMeasure) || 0;
- let count = 0;
- count = Math.ceil(period / (Number(row.frequencyType) || 1)) * frequency;
- row.totalMeasure = count;
- // 取单价
- const unitPrice = Number(row.conditioningProgramDetail?.cpFixedPricingRule?.unitPrice) || 0;
- // 计算总价
- row.totalPrice = (count * unitPrice).toFixed(2);
- }
- // 添加监听器
- watch(totalPrice, (val) => {
- formData.price = val;
- form.cost = val;
- });
- // 获取调理包详情
- async function selectCw(item: any) {
- currentSelectedPackage.value = item;
- selectedPackage.value = item.id;
- item.types = 'institution';
- const res: any = await getConditioningRecordDetailMethod(item);
- Object.assign(formData, res);
- formData.items = res?.items ?? [];
- form.conditioningWrapName = item.name;
- form.conditioningWrapId = item.id;
- form.phone = item.phone;
- }
- function handleCancel() {
- console.log('取消');
- }
- // 添加电话号码验证函数
- function isValidPhone(phone: string): boolean {
- // 中国大陆手机号码正则表达式
- const phoneRegex = /^1[3-9]\d{9}$/;
- return phoneRegex.test(phone);
- }
- async function handleSubmit() {
- if (!currentPatient.value) {
- message.error('请选择患者');
- return;
- }
- if (formData.items) {
- formData.items.forEach((item) => {
- delete item.id;
- });
- }
- form.id = Number(currentPatient.value.id);
- form.patientId = currentPatient.value.patientId;
- form.patientName = currentPatient.value.patientName;
- form.patientSex = currentPatient.value.patientSex;
- form.patientAge = currentPatient.value.patientAge;
- form.diagnosis = currentPatient.value.diagnosis;
- form.symptom = currentPatient.value.symptom;
- form.items = formData.items;
- // 添加电话号码验证
- if (form.phone && !isValidPhone(form.phone)) {
- message.error('请输入有效的手机号码');
- return;
- }
- await addConditioningSchemeMethod(form).then(async () => {
- notification.success({ message: '开立成功' });
- // 开立成功之后 刷新列表
- // 刷新患者列表,并保持当前患者高亮
- const patientList = await getPatientListMethod();
- patients.value = patientList;
- // 重新设置 currentPatient 为刚才的患者
- if (currentPatient.value) {
- const newCurrent = patientList.find((p) => p.patientId === currentPatient.value.patientId);
- if (newCurrent) {
- currentPatient.value = newCurrent;
- // 获取患者列表
- await getPatientList(currentPatient.value?.patientId || '');
- // 获取服务包选择列表
- await loadAvailableCw(currentPatient.value?.patientId || '');
- // 获取调养记录
- await getCpRecordDetail(currentPatient.value?.id || '');
- }
- }
- });
- }
- // 省市区的数据
- const provinceOptions = ref([]);
- const cityOptions = ref([]);
- const areaOptions = ref([]);
- const selectedProvince = ref('');
- const selectedCity = ref('');
- const selectedArea = ref('');
- async function loadProvinces() {
- const res: any = await getProvinceMethod();
- provinceOptions.value = res.map((item) => ({
- value: item.code,
- label: item.name,
- }));
- }
- async function loadCities(name: string, provincecode: string) {
- if (!provincecode) {
- cityOptions.value = [];
- areaOptions.value = [];
- selectedCity.value = '';
- selectedArea.value = '';
- return;
- }
- const res: any = await getCityMethod(name, provincecode);
- cityOptions.value = res.map((item) => ({
- value: item.code,
- label: item.name,
- }));
- }
- async function loadAreas(name: string, citycode: string) {
- if (!citycode) {
- areaOptions.value = [];
- selectedArea.value = '';
- return;
- }
- const res: any = await getAreaMethod(name, citycode);
- areaOptions.value = res.map((item) => ({
- value: item.code,
- label: item.name,
- }));
- }
- function handleProvinceChange(value: string) {
- selectedProvince.value = value;
- const selectedProvinceOption = provinceOptions.value.find((p) => p.value === value);
- form.provinceName = selectedProvinceOption?.label || '';
- loadCities(selectedProvinceOption?.name, value);
- }
- function handleCityChange(value: string) {
- selectedCity.value = value;
- const selectedCityOption = cityOptions.value.find((c) => c.value === value);
- form.cityName = selectedCityOption?.label || '';
- loadAreas(selectedCityOption?.name, value);
- }
- function handleAreaChange(value: string) {
- selectedArea.value = value;
- const selectedAreaOption = areaOptions.value.find((a) => a.value === value);
- form.districtName = selectedAreaOption?.label || '';
- }
- interface PatientInfo {
- patientName?: string;
- patientSex?: string;
- patientAge?: number;
- }
- interface CpDetailInfo {
- womenSpecialPeriod?: string;
- cardno?: string;
- }
- function formatPatientInfo(patient: PatientInfo | null, cpDetail: CpDetailInfo | null): string {
- if (!patient) return '';
- const parts: string[] = [];
- // 姓名
- if (patient.patientName) {
- parts.push(patient.patientName);
- }
- // 性别
- if (patient.patientSex) {
- const gender = patient.patientSex === '1' ? '女' : patient.patientSex === '0' ? '男' : '';
- if (gender) {
- parts.push(gender);
- }
- }
- // 年龄
- if (patient.patientAge) {
- parts.push(`${patient.patientAge}岁`);
- }
- // 特殊时期
- parts.push(getWomenSpecialPeriod(cpDetail?.womenSpecialPeriod || '0'));
- // 身份证号
- if (cpDetail?.cardno) {
- parts.push(`身份证号:${cpDetail.cardno}`);
- }
- return parts.join(',');
- }
- function getWomenSpecialPeriod(type: string) {
- if (type === '0') {
- return '无';
- } else if (type === '1') {
- return '月经期';
- } else if (type === '2') {
- return '孕期';
- } else if (type === '3') {
- return '产后';
- } else if (type === '4') {
- return '哺乳期';
- }
- }
- // 处理日期选择
- const handleDateChange = (date: any) => {
- if (date) {
- form.estimatedStartDate = dayjs(date).format('YYYY-MM-DD');
- } else {
- form.estimatedStartDate = '';
- }
- };
- watch(showProjectPopover, (val) => {
- if (!val) {
- projectSearch.value = '';
- }
- });
- </script>
- <template>
- <div class="issue-service-page">
- <!-- 左侧患者列表 -->
- <div class="left-panel">
- <a-input v-model:value="searchName" placeholder="输入姓名搜索" style="margin-bottom: 12px" />
- <div v-if="filteredPatients.length > 0">
- <div
- class="patient-item"
- v-for="item in filteredPatients"
- :key="item.patientId"
- @click="selectPatient(item)"
- :class="{ active: currentPatient?.patientId === item.patientId }"
- style="cursor: pointer"
- >
- {{ item.patientName }} {{ item.patientAge }}岁
- <span v-if="item.status === '0'" style="color: #aaa">(已开)</span>
- </div>
- </div>
- <div v-else style="padding-bottom: 8px; text-align: center; margin-top: 40px">暂无数据</div>
- </div>
- <!-- 中间主内容 -->
- <div class="main-panel">
- <!-- 顶部患者信息 -->
- <div class="patient-info">
- <div style="font-size: 12px">
- {{ formatPatientInfo(currentPatient || null, cpDetail) }}
- </div>
- <div style="margin: 12px 0 12px 0; font-size: 12px">
- <!-- <div>{{ form.healthAnalysisReport }}</div> -->
- <span style="color: lightgray" v-if="currentPatient?.diagnosis">诊断:</span><span v-if="currentPatient?.diagnosis">{{ currentPatient?.diagnosis }}</span>
- <span style="margin-left: 20px; color: lightgray" v-if="form?.healthAnalysisReport?.willillStateName">欲病状态:</span
- ><span>{{ form?.healthAnalysisReport?.willillStateName }}</span>
- <span style="margin-left: 20px; color: lightgray" v-if="form?.healthAnalysisReport?.willillDegreeName">欲病程度:</span
- ><span>{{ form?.healthAnalysisReport?.willillDegreeName }}</span>
- <span style="margin-left: 20px; color: lightgray" v-if="form?.healthAnalysisReport?.willillSocialName">欲病类型:</span
- ><span>{{ form?.healthAnalysisReport?.willillSocialName }}</span>
- <span style="margin-left: 20px; color: lightgray" v-if="form?.healthAnalysisReport?.willillFunctionName">欲病表现:</span
- ><span>{{ form?.healthAnalysisReport?.willillFunctionName }}</span>
- <span style="margin-left: 20px; color: lightgray" v-if="form?.healthAnalysisReport?.constitutionGroupName">体质:</span>
- <span>{{ form?.healthAnalysisReport?.constitutionGroupName }}</span>
- </div>
- </div>
- <!-- 服务包选择 -->
- <div v-if="filteredPatients.length > 0">
- <div class="service-select-row">
- <span>服务包选择:</span>
- <template v-if="currentPatient?.status === '0'">
- <span>{{ form.conditioningWrapName }}</span>
- </template>
- <template v-else>
- <a-select v-model:value="selectedPackage" style="width: 180px" placeholder="请选择服务包">
- <a-select-option v-for="item in lifeCwData" :key="item.id" :value="item.id" @click="selectCw(item)">
- {{ item.name }}
- </a-select-option>
- </a-select>
- </template>
- <div v-if="currentPatient?.status === '1' && lifeCwData.length > 0">
- <span style="margin-left: 16px; color: #1890ff">推荐:</span>
- <a class="suggest-cw" v-for="item in suggestCwData" :key="item.id" @click="selectCw(item)">{{ item.name }}</a>
- </div>
- </div>
- <!-- 服务包内容表格 -->
- <div class="table-section">
- <div class="table-title">服务包内容</div>
- <vxe-table :data="displayTableData" border style="margin-top: 8px">
- <vxe-column width="60" title="">
- <template #default="{ rowIndex }">
- <a-button type="text" danger @click="removeTableRow(rowIndex)" :disabled="rowIndex === displayTableData.length - 1">
- <MinusCircleOutlined />
- </a-button>
- </template>
- </vxe-column>
- <vxe-column field="conditioningProgramDetail.name" title="项目名称" width="180">
- <template #default="{ row, rowIndex }">
- <template v-if="rowIndex === displayTableData.length - 1">
- <a-popover v-model:open="showProjectPopover" trigger="click" placement="bottomLeft" :overlayStyle="{ width: '350px', padding: 0 }">
- <template #content>
- <a-input v-model:value="projectSearch" placeholder="输入项目名称搜索" style="margin: 8px; width: 90%" @input="() => nextTick()" />
- <vxe-table :data="filteredProjects" border size="small" style="max-height: 240px; overflow-y: auto" @cell-click="onSelectProject">
- <vxe-column field="name" title="项目名称" />
- <vxe-column field="conditioningProgramType" title="方案类型" />
- <vxe-column field="effect" title="功效" />
- <vxe-column title="预览" width="60">
- <template #default="{ row }">
- <EyeOutlined style="font-size: 18px; color: #1890ff; cursor: pointer" @click.stop="detailPreview(row)" />
- </template>
- </vxe-column>
- </vxe-table>
- </template>
- <a-input v-model:value="row.name" placeholder="请搜索" style="width: 120px" @click="showProjectPopover = true" />
- </a-popover>
- </template>
- <template v-else>
- {{ row.conditioningProgramDetail?.name }}
- </template>
- </template>
- </vxe-column>
- <vxe-column title="预览" width="60">
- <template #default="{ row }">
- <EyeOutlined style="font-size: 18px; color: #1890ff; cursor: pointer" @click="onPreview(row)" />
- </template>
- </vxe-column>
- <vxe-column field="days" title="周期" width="120">
- <template #default="{ row }">
- <div style="display: flex; align-items: center">
- <a-input v-model:value="row.days" @change="() => calculateCount(row)" :disabled="currentPatient?.status === '0' ? true : false" />
- <span>天</span>
- </div>
- </template>
- </vxe-column>
- <vxe-column field="frequencyType" title="频率" width="auto">
- <template #default="{ row }">
- <div style="display: flex; align-items: center">
- <span>每</span>
- <a-input v-model:value="row.frequencyType" style="width: 60px" @change="() => calculateCount(row)" :disabled="currentPatient?.status === '0' ? true : false" />
- <span>天</span>
- <a-input v-model:value="row.frequencyMeasure" style="width: 60px" @change="() => calculateCount(row)" :disabled="currentPatient?.status === '0' ? true : false" />
- <span>{{ row.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit }}</span>
- </div>
- </template>
- </vxe-column>
- <vxe-column field="row?.conditioningProgramDetail?.conditioningProgramType" title="方案类型" width="120">
- <template #default="{ row }">
- {{ row?.conditioningProgramDetail?.conditioningProgramType || '-' }}
- </template>
- </vxe-column>
- <vxe-column field="row.totalMeasure" title="数量" width="60">
- <template #default="{ row }">
- {{ row.totalMeasure || 0 }}
- </template>
- </vxe-column>
- <vxe-column field="row?.conditioningProgramDetail?.cpFixedPricingRule?.unit" title="单位" width="60">
- <template #default="{ row }">
- {{ row?.conditioningProgramDetail?.cpFixedPricingRule?.pricingUnit || '-' }}
- </template>
- </vxe-column>
- <vxe-column field="row.conditioningProgramDetail.cpFixedPricingRule.unitPrice" title="单价(元)" width="100">
- <template #default="{ row }">
- {{ row.conditioningProgramDetail?.cpFixedPricingRule?.unitPrice ?? '-' }}
- </template>
- </vxe-column>
- <vxe-column field="row.totalPrice" title="总价(元)" width="auto" @change="() => calculateCount(row)">
- <template #default="{ row }">
- <span>{{ row.totalPrice || 0 }}</span>
- </template>
- </vxe-column>
- <vxe-column field="start" title="开始时间" width="190">
- <template #default="{ row }">
- <div style="display: flex; align-items: center">
- <span>调养开始第</span>
- <a-input v-model:value="row.initialDay" style="width: 80px" :disabled="currentPatient?.status === '0' ? true : false" />
- <span>天</span>
- </div>
- </template>
- </vxe-column>
- <vxe-column field="conditioningProgramDetail.isOffline" title="线下项目" width="100">
- <template #default="{ row }">
- <span v-if="row.conditioningProgramDetail?.isOffline">
- {{ row.conditioningProgramDetail.isOffline === 'Y' ? '是' : '否' }}
- </span>
- <span v-else>-</span>
- </template>
- </vxe-column>
- <vxe-column field="conditioningProgramDetail.pricingType" title="穴位/经络/部位" width="160">
- <template #default="{ row }">
- <!-- <a-input v-model:value="row.desc" style="width: 120px" :disabled="currentPatient?.status === '0' ? true : false" /> -->
- <span>
- <a @click="editPart(row)" style="color: #1890ff; cursor: pointer" v-if="row.conditioningProgramDetail.pricingType === '1'">编辑</a>
- </span>
- </template>
- </vxe-column>
- <vxe-column field="remark" title="说明" width="180">
- <template #default="{ row }">
- <a-input v-model:value="row.remark" style="width: 120px" :disabled="currentPatient?.status === '0' ? true : false" />
- </template>
- </vxe-column>
- </vxe-table>
- </div>
- <div style="display: flex; justify-content: flex-end; margin-top: 16px">
- <span style="font-weight: bold">合计:{{ totalPrice }}元</span>
- </div>
- <!-- 调养日期 -->
- <div class="delivery-row">
- <span>开始调养日期:</span>
- <span v-if="currentPatient?.status === '0'">
- {{ form.estimatedStartDate }}
- </span>
- <span v-else>
- <a-date-picker
- :value="form.estimatedStartDate ? dayjs(form.estimatedStartDate) : null"
- @change="handleDateChange"
- placeholder="请选择日期"
- :disabledDate="(current) => current && current < dayjs().startOf('day')"
- />
- </span>
- </div>
- <!-- 配送信息 -->
- <div class="delivery-row" v-if="isShowDelivery">
- <div v-if="!form.progress || currentPatient?.status === '1'">
- <a-checkbox v-model:checked="deliveryChecked">配送</a-checkbox>
- <template v-if="deliveryChecked">
- <span>地址:</span>
- <a-select v-model:value="selectedProvince" :options="provinceOptions" placeholder="请选择省" style="width: 100px; margin-right: 4px" @change="handleProvinceChange" />
- <a-select
- v-model:value="selectedCity"
- :options="cityOptions"
- placeholder="请选择市"
- style="width: 100px; margin-right: 4px"
- :disabled="!selectedProvince"
- @change="handleCityChange"
- />
- <a-select
- v-model:value="selectedArea"
- :options="areaOptions"
- placeholder="请选择区"
- style="width: 100px; margin-right: 4px"
- :disabled="!selectedCity"
- @change="handleAreaChange"
- />
- <a-input v-model:value="form.detailAddress" placeholder="详细地址" style="width: 120px; margin-right: 4px" />
- <span>电话:</span>
- <a-input v-model:value="form.phone" placeholder="请输入" style="width: 120px" />
- </template>
- </div>
- <div v-else>
- <a-checkbox v-model:checked="deliveryChecked" disabled>配送</a-checkbox>
- <span>地址:</span>
- <span>{{ form.provinceName }}{{ form.cityName }}{{ form.districtName }}{{ form.detailAddress }}</span>
- <span style="margin-left: 16px" v-if="form.phone">电话:</span>
- <span>{{ form.phone }}</span>
- </div>
- </div>
- <!-- 操作按钮 -->
- <div class="footer-btns" v-if="currentPatient?.status === '1'">
- <a-button @click="handleCancel">取消</a-button>
- <a-button type="primary" style="margin-left: 24px" @click="handleSubmit">确认</a-button>
- </div>
- </div>
- <a-result class="area" v-else style="background-color: #fff" status="warning" title="暂无数据" />
- </div>
- <!-- 右侧调养记录 -->
- <div class="right-panel">
- <PatientTagWidget
- style="min-height: 112px; flex: none"
- :style="{ height: `${height}px` }"
- :dataset="tags"
- editable
- @refresh="loadTags(currentPatient.patientId)"
- :data="currentPatient"
- />
- <!-- <a-button
- type="primary"
- size="small"
- :disabled="!reportId"
- :loading="reportLoading || historyReportPreviewOpening"
- @click="
- historyReportPreviewOpening = true;
- openHistoryPreviewHandle();
- "
- >
- 健康档案
- </a-button> -->
- <div class="record-title">调养记录</div>
- <div class="record-list" v-if="patientRecord.length > 0">
- <div class="record-item" v-for="item in patientRecord" :key="item.id" @click="openRecord(item)">{{ item.estimatedStartDate }}~{{ item.estimatedEndDate }}</div>
- </div>
- <div v-else style="padding-bottom: 8px; text-align: center; margin-top: 40px">暂无数据</div>
- </div>
- </div>
- </template>
- <style scoped>
- .issue-service-page {
- display: flex;
- flex-direction: row;
- width: 100vw;
- min-height: 100vh;
- background: #fff;
- }
- .left-panel {
- flex: none;
- width: 180px;
- border-right: 1px solid #eee;
- padding: 16px 8px 0 16px;
- background: #fafbfc;
- min-height: 100vh;
- box-sizing: border-box;
- }
- .patient-item {
- padding: 10px 0;
- font-size: 14px;
- color: #333;
- }
- .patient-item.active {
- background: #e6f7ff;
- color: #1890ff;
- }
- .main-panel {
- flex: 1 1 0;
- min-width: 0;
- padding: 16px 32px 0 32px;
- display: flex;
- flex-direction: column;
- box-sizing: border-box;
- }
- .patient-info {
- font-size: 14px;
- color: #333;
- }
- .service-select-row {
- margin-bottom: 16px;
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 14px;
- }
- .table-section {
- margin-bottom: 16px;
- }
- .table-title {
- font-weight: bold;
- margin-bottom: 8px;
- }
- .table-total {
- text-align: right;
- margin-top: 8px;
- font-weight: bold;
- }
- .delivery-row {
- display: flex;
- align-items: center;
- gap: 4px;
- margin-bottom: 24px;
- margin-top: 16px;
- }
- .footer-btns {
- display: flex;
- justify-content: flex-end;
- gap: 24px;
- }
- .right-panel {
- flex: none;
- width: 190px;
- border-left: 1px solid #eee;
- padding: 16px 8px 0 8px;
- background: #fafbfc;
- min-height: 100vh;
- box-sizing: border-box;
- }
- .record-title {
- font-weight: bold;
- margin-bottom: 8px;
- text-align: center;
- }
- .record-list {
- display: flex;
- flex-direction: column;
- gap: 8px;
- }
- .record-item {
- background: #fff;
- border: 1px solid #eee;
- border-radius: 4px;
- padding: 8px;
- text-align: center;
- font-size: 12px;
- font-weight: bold;
- cursor: pointer;
- }
- .suggest-cw {
- color: #1890ff;
- cursor: pointer;
- margin-right: 10px;
- }
- </style>
|