fix: 订单管理新增查看处方功能,接诊页面优化
This commit is contained in:
BIN
apps/web-antd/public/img/empty.png
Normal file
BIN
apps/web-antd/public/img/empty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
@@ -175,7 +175,7 @@ function getRes(obj: any, isDecode = true) {
|
||||
if (arr.has(key)) {
|
||||
let aseFile = '';
|
||||
aseFile = isDecode
|
||||
? customBase64Decode(obj[key])
|
||||
? customBase64Decode(obj[key], key)
|
||||
: customBase64Encode(obj[key]);
|
||||
const isGarbled =
|
||||
// eslint-disable-next-line no-control-regex
|
||||
@@ -232,8 +232,9 @@ function getRes(obj: any, isDecode = true) {
|
||||
/**
|
||||
* 解密
|
||||
* @param data
|
||||
* @param key
|
||||
*/
|
||||
function customBase64Decode(data: string) {
|
||||
function customBase64Decode(data: string, key = '') {
|
||||
// return data
|
||||
try {
|
||||
// 第一次Base64解码
|
||||
@@ -244,7 +245,10 @@ function customBase64Decode(data: string) {
|
||||
const base64 = Base64.decode(subStr);
|
||||
return base64.length > 0 ? base64 : data;
|
||||
} catch (error) {
|
||||
console.error(`解码Base64字符串【${data}】时发生错误`, error);
|
||||
console.error(
|
||||
`解码Base64字符串【${data}】时发生错误,KEY:【${key}】`,
|
||||
error,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
34
apps/web-antd/src/components/modal/ImagePreview.vue
Normal file
34
apps/web-antd/src/components/modal/ImagePreview.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message, Image } from 'ant-design-vue';
|
||||
|
||||
const url = ref('');
|
||||
const previewTitle = ref('二维码');
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
fullscreenButton: false,
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
modalApi.close();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
const { values, title } = modalApi.getData<Record<string, any>>();
|
||||
if (values) {
|
||||
url.value = values;
|
||||
previewTitle.value = title;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal :title="previewTitle" class="w-[50%]">
|
||||
<Image :src="url" height="30" width="30" />
|
||||
</Modal>
|
||||
</template>
|
||||
135
apps/web-antd/src/components/modal/QrCodePreview.vue
Normal file
135
apps/web-antd/src/components/modal/QrCodePreview.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
import html2canvas from 'html2canvas';
|
||||
|
||||
const qrCodeUrl = ref('');
|
||||
const htmlToImage = ref('');
|
||||
const url = ref('');
|
||||
const previewTitle = ref('二维码');
|
||||
const previewAddress = ref('');
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
fullscreenButton: false,
|
||||
footer: false,
|
||||
header: false,
|
||||
showCancelButton: true,
|
||||
showConfirmButton: true,
|
||||
confirmText: '保存诊所卡片图片',
|
||||
cancelText: '保存诊所二维码图片',
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
modalApi.close();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
const { values, title, address } =
|
||||
modalApi.getData<Record<string, any>>();
|
||||
if (values) {
|
||||
url.value = values;
|
||||
qrCodeUrl.value = values;
|
||||
previewTitle.value = title;
|
||||
previewAddress.value = address;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
/**
|
||||
* 下载二维码
|
||||
* @param name
|
||||
* @param isQr
|
||||
*/
|
||||
const downloadQRCode = async (name: string, isQr = false) => {
|
||||
const element = isQr ? qrCodeUrl.value : htmlToImage.value;
|
||||
html2canvas(element, {
|
||||
useCORS: true,
|
||||
allowTaint: true,
|
||||
logging: false,
|
||||
}).then((canvas) => {
|
||||
// 创建a标签下载
|
||||
const link = document.createElement('a'); // 创建a标签
|
||||
link.href = canvas.toDataURL(); // 是canvas对象的一种方法,用于将canvas对象转换为base64位编码
|
||||
link.setAttribute('download', `${previewTitle.value}${name}.png`); // 利用了a标签的download 来下载 canvas图片
|
||||
link.style.display = 'none'; // 将图片隐藏起来
|
||||
document.body.append(link); // 插入到其中
|
||||
link.click();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<Modal :title="`${previewTitle}二维码`" class="w-[50%]">
|
||||
<div class="qrBox" style="text-align: center">
|
||||
<div ref="htmlToImage" class="qrModal">
|
||||
<div id="qrcode" ref="qrCodeUrl" class="qrcode">
|
||||
<div class="qrTitle">{{ previewTitle }}</div>
|
||||
<Image :preview="false" :src="url" height="30" width="30" />
|
||||
<div class="qrAddress">
|
||||
<span class="addressTitle">诊所地址:</span>{{ previewAddress }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
style="margin: 20px auto"
|
||||
type="primary"
|
||||
@click="downloadQRCode('二维码卡片下载')"
|
||||
>
|
||||
二维码卡片下载
|
||||
</Button>
|
||||
<Button
|
||||
style="margin: 20px auto 20px 20px"
|
||||
type="primary"
|
||||
@click="downloadQRCode('二维码下载', true)"
|
||||
>
|
||||
二维码下载
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.qrModal {
|
||||
// 宽度适应文本长度
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
background: radial-gradient(
|
||||
circle at center,
|
||||
rgba(173, 216, 230, 0.8),
|
||||
rgba(135, 206, 235, 0.8),
|
||||
rgba(100, 149, 237, 0.8)
|
||||
);
|
||||
padding: 20px 30px;
|
||||
|
||||
.qrTitle {
|
||||
font-size: 20px;
|
||||
margin-bottom: 30px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qrAddress {
|
||||
font-size: 12px;
|
||||
margin-top: 30px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.addressTitle {
|
||||
color: #3a8ee6;
|
||||
}
|
||||
|
||||
.qrcode {
|
||||
width: fit-content;
|
||||
//width: 50%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding: 20px 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -160,11 +160,11 @@ function getColor(status: any) {
|
||||
<div
|
||||
class="mr-6 h-32 w-32 overflow-hidden rounded-lg bg-gray-200 dark:bg-gray-800"
|
||||
>
|
||||
<Image :src="item.drug_image" alt="" height="100%" width="100%" />
|
||||
<Image :src="item.drug_image || '/img/empty.png'" alt="/img/empty.png" height="100%" width="100%" />
|
||||
</div>
|
||||
<div>
|
||||
<h4>{{ item.drug_name }}</h4>
|
||||
<p>规格: {{ item.drug.specification }}</p>
|
||||
<p>规格: {{ item.drug.specification || 'g' }}</p>
|
||||
<p>数量: {{ item.number }}</p>
|
||||
<p>单价: {{ item.price }} 元</p>
|
||||
<p>
|
||||
|
||||
@@ -43,6 +43,7 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
slots: { default: 'delivery-method' },
|
||||
},
|
||||
{ field: 'items_price', title: '总价' },
|
||||
{ field: 'is_sync_erp', title: 'Erp状态', slots: { default: 'is-sync-erp' } },
|
||||
{ field: 'pay_time', title: '支付时间', slots: { default: 'pay-time' } },
|
||||
{ field: 'created_at', title: '下单时间' },
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@ import FormModalDemo from './components/modal.vue';
|
||||
import DetailModal from './components/detail.vue';
|
||||
import { formOptions } from './config/search';
|
||||
import { gridOptions } from './config/table';
|
||||
import PrescrtionDetail from "#/views/doctor/doctor-reception/components/PrescrtionDetail.vue";
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
|
||||
@@ -80,12 +81,25 @@ const expandAll = () => {
|
||||
const collapseAll = () => {
|
||||
gridApi.grid?.setAllRowExpand(false);
|
||||
};
|
||||
|
||||
|
||||
const [PrescrtionDetailModal, PrescrtionDetailModalApi] = useVbenModal({
|
||||
connectedComponent: PrescrtionDetail,
|
||||
});
|
||||
const openPrescriptionDetail = (values) => {
|
||||
// 打开西药处方模态框逻辑
|
||||
PrescrtionDetailModalApi.setData({
|
||||
values,
|
||||
});
|
||||
PrescrtionDetailModalApi.open();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height title="订单管理">
|
||||
<FormModal />
|
||||
<Modal />
|
||||
<PrescrtionDetailModal />
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
@@ -131,6 +145,10 @@ const collapseAll = () => {
|
||||
<template #pay-time="{ row }">
|
||||
{{ row?.pay_time || '未支付' }}
|
||||
</template>
|
||||
<template #is-sync-erp="{ row }">
|
||||
<Tag v-if="row.is_sync_erp === 1" color="green">已同步</Tag>
|
||||
<Tag v-else color="red">未同步</Tag>
|
||||
</template>
|
||||
<template #delivery-method="{ row }">
|
||||
<div v-if="row.order_type === 1">
|
||||
<Tag v-if="row.prescription_type === 1" color="orange">中药订单</Tag>
|
||||
@@ -191,16 +209,13 @@ const collapseAll = () => {
|
||||
},
|
||||
]"
|
||||
:drop-down-actions="[
|
||||
// {
|
||||
// label: '发货',
|
||||
// type: 'link',
|
||||
// icon: 'ri:send-plane-fill',
|
||||
// // auth: ['超级订单', 'sys:user:save'],
|
||||
// popConfirm: {
|
||||
// title: '确定发货吗?',
|
||||
// confirm: wareSend.bind(null, false),
|
||||
// },
|
||||
// },
|
||||
{
|
||||
label: '查看处方',
|
||||
type: 'link',
|
||||
icon: 'ri:send-plane-fill',
|
||||
// auth: ['超级订单', 'sys:user:save'],
|
||||
onClick: openPrescriptionDetail.bind(null, row.prescription),
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
@@ -266,7 +281,8 @@ const collapseAll = () => {
|
||||
:key="index"
|
||||
class="custom-list-item"
|
||||
>
|
||||
【{{ item.drug.drug_number }}】 {{ item.drug_name }} (* {{item.number}})
|
||||
【{{ item.drug.drug_number }}】 {{ item.drug_name }} (*
|
||||
{{ item.number * (item.dosage > 0 ? item.dosage : 1) }})
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||
if (isOpen) {
|
||||
const { values } = modalApi.getData<Record<string, any>>();
|
||||
if (values) item.value = values;
|
||||
console.log(item.value, 'sssssssssssssssss');
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -125,14 +124,14 @@ const decrypt = (str: string) => str; // 简单base64解码示例
|
||||
class="recipe-item"
|
||||
>
|
||||
<!-- <div class="medicine-item" v-for="drug in JSON.parse(recipe.content)" :key="drug?.id">-->
|
||||
<div v-if="item.prescription_type === 1">
|
||||
<div v-for="drug in JSON.parse(recipe.content)" :key="drug?.id">
|
||||
<div v-if="item.prescription_type === 1" class="w-full">
|
||||
<div v-for="drug in JSON.parse(recipe.content)" :key="drug?.id" class="w-1/3" style="display: inline-block">
|
||||
<div class="medicine-item">
|
||||
<!-- {{ drug }}-->
|
||||
<span class="drug-name">{{
|
||||
drug?.name || drug?.drug_name
|
||||
}}</span>
|
||||
<span class="drug-quantity ml-5">{{ drug?.number }} /g</span>
|
||||
<span class="drug-quantity mr-5">{{ drug?.number }} /g</span>
|
||||
</div>
|
||||
<div class="">煎服方法: {{ drug.use_way?.name || '煎服' }}</div>
|
||||
</div>
|
||||
@@ -278,6 +277,9 @@ const decrypt = (str: string) => str; // 简单base64解码示例
|
||||
margin: 8px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
.chinese-item {
|
||||
width: 28%;
|
||||
}
|
||||
|
||||
.drug-name {
|
||||
font-weight: 500;
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
Row,
|
||||
Select,
|
||||
SelectOption,
|
||||
Modal,
|
||||
Tag,
|
||||
Textarea,
|
||||
Timeline,
|
||||
@@ -702,6 +703,22 @@ function updateChineseNumber() {
|
||||
updateLocalStorage();
|
||||
}
|
||||
|
||||
const showNewDrugModal = ref(false);
|
||||
|
||||
/**
|
||||
* 在新的药品数量框失去焦点后弹出新药品弹窗
|
||||
*/
|
||||
function newDrugBlur() {
|
||||
if (newDrugInfo.value.id > 0 && newDrugInfo.value.number > 0) {
|
||||
showNewDrugModal.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
function newDrugModalOk() {
|
||||
addDrugByChinese();
|
||||
showNewDrugModal.value = false;
|
||||
}
|
||||
|
||||
function updateChineseNumberGoNewDrug(event: KeyboardEvent) {
|
||||
console.log(event.key);
|
||||
if (event.key === 'Enter') {
|
||||
@@ -771,6 +788,7 @@ 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;
|
||||
setTimeout(() => {
|
||||
// 获取新药品卡片中的克数输入框并聚焦
|
||||
const newDrugNumberInput = document.querySelector(
|
||||
@@ -875,6 +893,31 @@ function searchOption(inputValue) {
|
||||
getDrugListByWesternModal(inputValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加中药
|
||||
* @param inputValue
|
||||
*/
|
||||
function addDrugByChinese() {
|
||||
// 如果是新药品输入框,调用添加新药品方法
|
||||
const check = currentDrugs.value.find(
|
||||
(v) => v.id === newDrugInfo.value.id,
|
||||
);
|
||||
if (check) {
|
||||
message.error('该药品已经在处方中了!');
|
||||
return;
|
||||
}
|
||||
const data = drugList.value.find(
|
||||
(v) => v.drug_id === newDrugInfo.value.id,
|
||||
);
|
||||
if (data === null || data === undefined) {
|
||||
message.error('请选择药品');
|
||||
return;
|
||||
}
|
||||
data.drug.number = newDrugInfo.value.number;
|
||||
data.drug.way_id = newDrugInfo.value.way_id;
|
||||
addProducts(data);
|
||||
newDrugInfo.value = {};
|
||||
}
|
||||
/**
|
||||
* 添加操作
|
||||
*/
|
||||
@@ -886,24 +929,7 @@ function selectDrugByNewDrugInfo(event: KeyboardEvent, isNewDrug: boolean) {
|
||||
|
||||
if (isNewDrug) {
|
||||
// 如果是新药品输入框,调用添加新药品方法
|
||||
const check = currentDrugs.value.find(
|
||||
(v) => v.id === newDrugInfo.value.id,
|
||||
);
|
||||
if (check) {
|
||||
message.error('该药品已经在处方中了!');
|
||||
return;
|
||||
}
|
||||
const data = drugList.value.find(
|
||||
(v) => v.drug_id === newDrugInfo.value.id,
|
||||
);
|
||||
if (data === null || data === undefined) {
|
||||
message.error('请选择药品');
|
||||
return;
|
||||
}
|
||||
data.drug.number = newDrugInfo.value.number;
|
||||
data.drug.way_id = newDrugInfo.value.way_id;
|
||||
addProducts(data);
|
||||
newDrugInfo.value = {};
|
||||
addDrugByChinese();
|
||||
} else {
|
||||
// 如果是已有药品输入框,调用更新数量方法
|
||||
updateChineseNumber();
|
||||
@@ -1011,40 +1037,61 @@ function updateLocalStorageStoreInfo() {
|
||||
tabType.value = 0;
|
||||
getPatientListByReception();
|
||||
}
|
||||
const leftShow = ref(true)
|
||||
// 获取doctorReceptionLeftShow
|
||||
function getDoctorReceptionLeftShow() {
|
||||
const localStorageLeftShow = localStorage.getItem(`doctorReceptionLeftShow`);
|
||||
leftShow.value = localStorageLeftShow !== 'false';
|
||||
}
|
||||
getDoctorReceptionLeftShow();
|
||||
// 监听leftShow存入缓存
|
||||
watch(
|
||||
() => leftShow.value,
|
||||
async (enable) => {
|
||||
localStorage.setItem(`doctorReceptionLeftShow`, enable);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container-box">
|
||||
<!-- 左侧患者列表 -->
|
||||
<div class="patient-panel">
|
||||
<Select v-model:value="myStoreId" class="w-full" @change="switchStore">
|
||||
<SelectOption v-for="item in myStoreList" :value="item.id">
|
||||
{{ item.name }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
<RadioGroup
|
||||
v-model:value="listType"
|
||||
class="w-full"
|
||||
style="text-align: center"
|
||||
@change="updatePatientList"
|
||||
>
|
||||
<RadioButton :value="1" class="w-1/2">当前</RadioButton>
|
||||
<RadioButton :value="2" class="w-1/2">历史</RadioButton>
|
||||
</RadioGroup>
|
||||
<div
|
||||
v-for="patient in patients"
|
||||
:key="patient.user_patient.id"
|
||||
:class="{ active: selectPatientId === patient.id }"
|
||||
class="patient-card"
|
||||
@click="selectPatient(patient)"
|
||||
>
|
||||
<div class="patient-info">
|
||||
<h3>{{ patient.user_patient.name }}</h3>
|
||||
<p class="phone">{{ patient.user_patient.mobile }}</p>
|
||||
<span :class="getRegisterStatus(patient.status)" class="status">{{
|
||||
getRegisterStatus(patient.status)
|
||||
}}</span>
|
||||
{{ patient.updated_at }}
|
||||
<div :class="leftShow === true? 'container-box-grid':'container-box'">
|
||||
<!-- 如果leftShow === true展示收起,反之则显示展开-->
|
||||
<div>
|
||||
<Button :class="`${leftShow === true? 'w-full': 'sticky top-5 left-5'}`" type="primary" @click="leftShow = !leftShow">{{ leftShow === true ? '收起患者列表' : '展开患者列表' }}</Button>
|
||||
<!-- 左侧患者列表 -->
|
||||
<div v-if="leftShow" class="patient-panel">
|
||||
<Select v-model:value="myStoreId" class="w-full" @change="switchStore">
|
||||
<SelectOption v-for="item in myStoreList" :value="item.id">
|
||||
{{ item.name }}
|
||||
</SelectOption>
|
||||
</Select>
|
||||
<RadioGroup
|
||||
v-model:value="listType"
|
||||
class="w-full"
|
||||
style="text-align: center"
|
||||
@change="updatePatientList"
|
||||
>
|
||||
<RadioButton :value="1" class="w-1/2">当前</RadioButton>
|
||||
<RadioButton :value="2" class="w-1/2">历史</RadioButton>
|
||||
</RadioGroup>
|
||||
<div
|
||||
v-for="patient in patients"
|
||||
:key="patient.user_patient.id"
|
||||
:class="{ active: selectPatientId === patient.id }"
|
||||
class="patient-card"
|
||||
@click="selectPatient(patient)"
|
||||
>
|
||||
<div class="patient-info">
|
||||
<h3>{{ patient.user_patient.name }}</h3>
|
||||
<p class="phone">{{ patient.user_patient.mobile }}</p>
|
||||
<span :class="getRegisterStatus(patient.status)" class="status">{{
|
||||
getRegisterStatus(patient.status)
|
||||
}}</span>
|
||||
{{ patient.updated_at }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1229,9 +1276,6 @@ function updateLocalStorageStoreInfo() {
|
||||
|
||||
<div class="prescription-header">
|
||||
<h2>{{ activePatient.name }} 的处方</h2>
|
||||
<Button class="send-btn" type="primary" @click="sendPrescription">
|
||||
发送处方
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- 药品分类导航 -->
|
||||
@@ -1288,9 +1332,9 @@ function updateLocalStorageStoreInfo() {
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xl="12"
|
||||
:xs="24"
|
||||
:xxl="8"
|
||||
:xl="leftShow ? 12 : 8"
|
||||
:xs="leftShow ? 12 : 8"
|
||||
:xxl="leftShow ? 8 : 6"
|
||||
>
|
||||
<Card class="mt-0" title="">
|
||||
<div>
|
||||
@@ -1368,11 +1412,11 @@ function updateLocalStorageStoreInfo() {
|
||||
</Col>
|
||||
<Col
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xl="12"
|
||||
:xs="24"
|
||||
:xxl="8"
|
||||
:md="12"
|
||||
:sm="12"
|
||||
:xl="leftShow ? 12 : 8"
|
||||
:xs="leftShow ? 12 : 8"
|
||||
:xxl="leftShow ? 8 : 6"
|
||||
>
|
||||
<Card title="">
|
||||
<div>
|
||||
@@ -1401,7 +1445,7 @@ function updateLocalStorageStoreInfo() {
|
||||
v-model:value="newDrugInfo.number"
|
||||
class="new-number-input w-1/5"
|
||||
style="min-width: 100px"
|
||||
@blur="updateChineseNumber"
|
||||
@blur="newDrugBlur"
|
||||
@keydown="selectDrugByNewDrugInfo($event, true)"
|
||||
>
|
||||
<template #addonAfter> g</template>
|
||||
@@ -1559,6 +1603,7 @@ function updateLocalStorageStoreInfo() {
|
||||
<Select
|
||||
v-model:value="newDrugInfo.way_id"
|
||||
placeholder="用法"
|
||||
@blur="updateChineseNumber"
|
||||
@keydown="selectDrugByNewDrugInfo($event, true)"
|
||||
disabled
|
||||
>
|
||||
@@ -1777,6 +1822,10 @@ function updateLocalStorageStoreInfo() {
|
||||
商品价格:¥{{ totalProductCost.toFixed(2) }}
|
||||
</div>
|
||||
<div class="total-cost">总计:¥{{ totalCost.toFixed(2) }}</div>
|
||||
|
||||
<Button class="mt-5 w-full" style="display: block" type="primary" @click="sendPrescription">
|
||||
发送处方
|
||||
</Button>
|
||||
</div>
|
||||
</Page>
|
||||
<div v-else-if="tabType === 0" class="prescription-panel">
|
||||
@@ -1786,6 +1835,9 @@ function updateLocalStorageStoreInfo() {
|
||||
<DoctorOrderModals/>
|
||||
<WesternDrugModal/>
|
||||
<PrescrtionDetailModal/>
|
||||
<Modal v-model:open="showNewDrugModal" @ok="newDrugModalOk">
|
||||
要把【{{ newDrugInfo.name }}】添加到清单吗?
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1812,9 +1864,12 @@ function updateLocalStorageStoreInfo() {
|
||||
}
|
||||
|
||||
.container-box {
|
||||
min-height: 90vh;
|
||||
}
|
||||
.container-box-grid {
|
||||
min-height: 90vh;
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
min-height: 90vh;
|
||||
}
|
||||
|
||||
.patient-panel {
|
||||
|
||||
@@ -57,3 +57,13 @@ export async function openPcWindowsApiByStore(id: number) {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启后台登录
|
||||
* @param id
|
||||
*/
|
||||
export async function openQrCodeApi(id: number) {
|
||||
return requestClient.post<any>(`${prefix}open-qr-code`, {
|
||||
id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -135,10 +135,6 @@ export const modalFormProps: VbenFormProps = {
|
||||
componentProps: {
|
||||
placeholder: '请选省市区',
|
||||
options: addressOption,
|
||||
onChange: (value: any) => {
|
||||
console.log(value);
|
||||
},
|
||||
|
||||
},
|
||||
fieldName: 'address',
|
||||
label: '省市区',
|
||||
@@ -216,6 +212,12 @@ export const modalFormProps: VbenFormProps = {
|
||||
label: 'x',
|
||||
rules: 'required',
|
||||
hideLabel: true,
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
renderComponentContent: () => {
|
||||
return {
|
||||
default: () => {
|
||||
@@ -230,6 +232,12 @@ export const modalFormProps: VbenFormProps = {
|
||||
componentProps: {
|
||||
placeholder: '请输入开户人姓名',
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
fieldName: 'bank_user_name',
|
||||
label: '开户人姓名',
|
||||
rules: 'required',
|
||||
@@ -240,6 +248,12 @@ export const modalFormProps: VbenFormProps = {
|
||||
componentProps: {
|
||||
placeholder: '请输入银行卡号',
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
fieldName: 'bank_card',
|
||||
label: '银行卡号',
|
||||
rules: 'required',
|
||||
@@ -250,6 +264,12 @@ export const modalFormProps: VbenFormProps = {
|
||||
componentProps: {
|
||||
placeholder: '请输入开户行',
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
fieldName: 'bank_name',
|
||||
label: '开户行',
|
||||
rules: 'required',
|
||||
@@ -260,6 +280,12 @@ export const modalFormProps: VbenFormProps = {
|
||||
componentProps: {
|
||||
placeholder: '请输入银联行号',
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
fieldName: 'bank_no',
|
||||
label: '银联行号',
|
||||
},
|
||||
@@ -274,8 +300,8 @@ export const modalFormProps: VbenFormProps = {
|
||||
placeholder: '请选择银行账户类型',
|
||||
},
|
||||
dependencies: {
|
||||
disabled: (values) => {
|
||||
return values.id != null;
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
|
||||
@@ -15,6 +15,15 @@ export const formOptions: VbenFormProps = {
|
||||
fieldName: 'name',
|
||||
label: '诊所名称',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
placeholder: '输入联系人手机号',
|
||||
},
|
||||
defaultValue: '',
|
||||
fieldName: 'mobile',
|
||||
label: '联系人手机号',
|
||||
},
|
||||
// {
|
||||
// component: 'RangePicker',
|
||||
// componentProps: {
|
||||
|
||||
@@ -35,8 +35,9 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
// { field: 'erp_id', title: 'erpID' },
|
||||
// { field: 'shouzimu', title: '诊所首字母' },
|
||||
{ field: 'position', title: '详细地址' },
|
||||
{ field: 'contact', title: '联系人' },
|
||||
{ field: 'mobile', title: '联系电话' },
|
||||
// { field: 'contact', title: '联系人' },
|
||||
{ field: 'mobile', title: '联系人、电话', slots: { default: 'mobile' } },
|
||||
{ field: 'start_time', title: '营业时间', slots: { default: 'start-time' } },
|
||||
{ field: 'created_at', title: '注册时间' },
|
||||
{ type: 'html', title: '操作', align: 'right', slots: { default: 'action' } },
|
||||
],
|
||||
|
||||
@@ -5,15 +5,18 @@ import { ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button, Image, message } from 'ant-design-vue';
|
||||
import { Button, Image, message, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
|
||||
import { deleteStore, openPcWindowsApiByStore } from './api';
|
||||
import {deleteStore, openPcWindowsApiByStore, openQrCodeApi} from './api';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import FormModalDemo from './components/modal.vue';
|
||||
import QrCodePreview from "#/components/modal/QrCodePreview.vue";
|
||||
import { formOptions } from './config/search';
|
||||
import { gridOptions } from './config/table';
|
||||
import {Icon} from "#/components/icon";
|
||||
|
||||
const hasTopTableDropDownActions = ref(false);
|
||||
|
||||
@@ -36,6 +39,20 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridEvents,
|
||||
});
|
||||
|
||||
const [QrCodePreviewModal, QrCodePreviewApi] = useVbenModal({
|
||||
connectedComponent: QrCodePreview,
|
||||
});
|
||||
|
||||
const openQrCodeModal = (url, title, address) => {
|
||||
QrCodePreviewApi.setData({
|
||||
// 表单值
|
||||
values: url,
|
||||
title,
|
||||
address,
|
||||
});
|
||||
QrCodePreviewApi.open();
|
||||
};
|
||||
|
||||
const [FormModal, formModalApi] = useVbenModal({
|
||||
connectedComponent: FormModalDemo,
|
||||
});
|
||||
@@ -71,11 +88,27 @@ function openPcWindows(id) {
|
||||
gridApi.reload();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 开启后台账号
|
||||
*/
|
||||
function openQrCode(id) {
|
||||
openQrCodeApi(id).then(() => {
|
||||
message.success('操作成功!');
|
||||
gridApi.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function copyText(source) {
|
||||
copy(source);
|
||||
message.success('复制成功');
|
||||
}
|
||||
const { copy } = useClipboard({ legacy: true });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height title="诊所管理">
|
||||
<FormModal />
|
||||
<QrCodePreviewModal />
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
@@ -109,8 +142,38 @@ function openPcWindows(id) {
|
||||
</template>
|
||||
</TableAction>
|
||||
</template>
|
||||
<template #mobile="{ row }">
|
||||
<div>
|
||||
诊所联系人:{{ row.contact }}
|
||||
<Button type="link" @click="copyText(row.contact)">复制</Button>
|
||||
</div>
|
||||
<div>
|
||||
号码:{{ row.mobile }}
|
||||
<Button type="link" @click="copyText(row.mobile)">复制</Button>
|
||||
</div>
|
||||
</template>
|
||||
<template #qr_code="{ row }">
|
||||
<Image :src="row.qr_code" height="30" width="30" />
|
||||
<div class="qr_code">
|
||||
<Image
|
||||
:preview="false"
|
||||
:src="row.qr_code"
|
||||
height="30"
|
||||
width="30"
|
||||
@click="
|
||||
openQrCodeModal(
|
||||
row.qr_code,
|
||||
row.name,
|
||||
`${row.province.name}${row.city.name}${row.position}`,
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #start-time="{ row }">
|
||||
早:<Tag color="success">{{ row.start_time }}</Tag>
|
||||
<br />
|
||||
<br />
|
||||
晚:<Tag color="error">{{ row.end_time }}</Tag>
|
||||
</template>
|
||||
<template #toolbar-tools></template>
|
||||
<template #action="{ row }">
|
||||
@@ -167,9 +230,26 @@ function openPcWindows(id) {
|
||||
confirm: openPcWindows.bind(null, row.id),
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '生成诊所二维码',
|
||||
type: 'link',
|
||||
icon: 'uil:edit',
|
||||
size: 'small',
|
||||
// auth: ['store', 'sys:role:detail'],
|
||||
popConfirm: {
|
||||
title: '确定生成诊所二维码吗?',
|
||||
confirm: openQrCode.bind(null, row.id),
|
||||
},
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</Grid>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.qr_code:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-base64": "^3.7.7",
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
|
||||
58
pnpm-lock.yaml
generated
58
pnpm-lock.yaml
generated
@@ -469,6 +469,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
html2canvas:
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
js-base64:
|
||||
specifier: ^3.7.7
|
||||
version: 3.7.7
|
||||
@@ -3146,8 +3149,8 @@ packages:
|
||||
resolution: {integrity: sha512-6GT1BJ852gZ0gItNZN2krX5QAmea+cmdjMvsWohArAZ3GmHdnNANEcF9JjPXAMRtQ6Ux5E269ymamg/+WU6tQA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/message-compiler@12.0.0-alpha.1':
|
||||
resolution: {integrity: sha512-rS1Lc99D2uaGqWxlrpGPWdgkq2Jox8xxOS9gdIRhuF2CsuJISWQmwd/TjMnWNhwv9olE0aPEBh1323a61Tfp+g==}
|
||||
'@intlify/message-compiler@12.0.0-alpha.2':
|
||||
resolution: {integrity: sha512-PD9C+oQbb7BF52hec0+vLnScaFkvnfX+R7zSbODYuRo/E2niAtGmHd0wPvEMsDhf9Z9b8f/qyDsVeZnD/ya9Ug==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@10.0.5':
|
||||
@@ -3158,8 +3161,8 @@ packages:
|
||||
resolution: {integrity: sha512-dF2iMMy8P9uKVHV/20LA1ulFLL+MKSbfMiixSmn6fpwqzvix38OIc7ebgnFbBqElvghZCW9ACtzKTGKsTGTWGA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@12.0.0-alpha.1':
|
||||
resolution: {integrity: sha512-ZZ5rtlUcEnhhFS+MTrl0V1UoN3yRninGawP3f1YituJN9217xJvpqCSLa9t8NLaVwVIxsRcq4lQe48D0SigmBg==}
|
||||
'@intlify/shared@12.0.0-alpha.2':
|
||||
resolution: {integrity: sha512-P2DULVX9nz3y8zKNqLw9Es1aAgQ1JGC+kgpx5q7yLmrnAKkPR5MybQWoEhxanefNJgUY5ehsgo+GKif59SrncA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/unplugin-vue-i18n@6.0.1':
|
||||
@@ -4372,6 +4375,10 @@ packages:
|
||||
bare-events@2.5.0:
|
||||
resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==}
|
||||
|
||||
base64-arraybuffer@1.0.2:
|
||||
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
@@ -4870,6 +4877,9 @@ packages:
|
||||
peerDependencies:
|
||||
postcss: ^8.4
|
||||
|
||||
css-line-break@2.1.0:
|
||||
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
|
||||
|
||||
css-prefers-color-scheme@10.0.0:
|
||||
resolution: {integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -5987,6 +5997,10 @@ packages:
|
||||
resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
html2canvas@1.4.1:
|
||||
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
htmlparser2@8.0.2:
|
||||
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
|
||||
|
||||
@@ -6603,6 +6617,7 @@ packages:
|
||||
|
||||
lodash.get@4.4.2:
|
||||
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
|
||||
deprecated: This package is deprecated. Use the optional chaining (?.) operator instead.
|
||||
|
||||
lodash.isarguments@3.1.0:
|
||||
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
|
||||
@@ -8658,6 +8673,9 @@ packages:
|
||||
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
text-segmentation@1.0.3:
|
||||
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
|
||||
|
||||
theme-colors@0.1.0:
|
||||
resolution: {integrity: sha512-6gTEHQqWlQNiOEGHCSSQmU//E5SnXHJ4H7oHQOD8x77CvNYNQAmt73dqR71mzw5ULV87zaHLxK5pIBnsToFuZw==}
|
||||
|
||||
@@ -9007,6 +9025,9 @@ packages:
|
||||
util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
|
||||
utrie@1.0.2:
|
||||
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||
|
||||
@@ -11184,8 +11205,8 @@ snapshots:
|
||||
|
||||
'@intlify/bundle-utils@10.0.0(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 12.0.0-alpha.1
|
||||
'@intlify/shared': 12.0.0-alpha.1
|
||||
'@intlify/message-compiler': 12.0.0-alpha.2
|
||||
'@intlify/shared': 12.0.0-alpha.2
|
||||
acorn: 8.14.0
|
||||
escodegen: 2.1.0
|
||||
estree-walker: 2.0.2
|
||||
@@ -11206,16 +11227,16 @@ snapshots:
|
||||
'@intlify/shared': 10.0.5
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@intlify/message-compiler@12.0.0-alpha.1':
|
||||
'@intlify/message-compiler@12.0.0-alpha.2':
|
||||
dependencies:
|
||||
'@intlify/shared': 12.0.0-alpha.1
|
||||
'@intlify/shared': 12.0.0-alpha.2
|
||||
source-map-js: 1.2.1
|
||||
|
||||
'@intlify/shared@10.0.5': {}
|
||||
|
||||
'@intlify/shared@11.1.2': {}
|
||||
|
||||
'@intlify/shared@12.0.0-alpha.1': {}
|
||||
'@intlify/shared@12.0.0-alpha.2': {}
|
||||
|
||||
'@intlify/unplugin-vue-i18n@6.0.1(@vue/compiler-dom@3.5.13)(eslint@9.17.0(jiti@2.4.2))(rollup@4.28.1)(typescript@5.7.2)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||
dependencies:
|
||||
@@ -12677,6 +12698,8 @@ snapshots:
|
||||
bare-events@2.5.0:
|
||||
optional: true
|
||||
|
||||
base64-arraybuffer@1.0.2: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
better-path-resolve@1.0.0:
|
||||
@@ -13259,6 +13282,10 @@ snapshots:
|
||||
postcss-selector-parser: 7.0.0
|
||||
postcss-value-parser: 4.2.0
|
||||
|
||||
css-line-break@2.1.0:
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
|
||||
css-prefers-color-scheme@10.0.0(postcss@8.4.49):
|
||||
dependencies:
|
||||
postcss: 8.4.49
|
||||
@@ -14537,6 +14564,11 @@ snapshots:
|
||||
|
||||
html-tags@3.3.1: {}
|
||||
|
||||
html2canvas@1.4.1:
|
||||
dependencies:
|
||||
css-line-break: 2.1.0
|
||||
text-segmentation: 1.0.3
|
||||
|
||||
htmlparser2@8.0.2:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
@@ -17326,6 +17358,10 @@ snapshots:
|
||||
|
||||
text-extensions@2.4.0: {}
|
||||
|
||||
text-segmentation@1.0.3:
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
|
||||
theme-colors@0.1.0: {}
|
||||
|
||||
thenify-all@1.6.0:
|
||||
@@ -17664,6 +17700,10 @@ snapshots:
|
||||
|
||||
util-deprecate@1.0.2: {}
|
||||
|
||||
utrie@1.0.2:
|
||||
dependencies:
|
||||
base64-arraybuffer: 1.0.2
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
dependencies:
|
||||
spdx-correct: 3.2.0
|
||||
|
||||
Reference in New Issue
Block a user