fix: 各种提交(日志相关、组件封装相关、订单相关
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Select } from 'ant-design-vue';
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请输入',
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['update:value']);
|
||||
const mValue = useVModel(props, 'value', emits, {
|
||||
defaultValue: props.value,
|
||||
passive: true,
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Select
|
||||
v-model:value="mValue"
|
||||
:placeholder="placeholder"
|
||||
list-type="picture-card"
|
||||
mode="tags"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</template>
|
||||
<style lang="less" scoped></style>
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
getProcessRuleList,
|
||||
getProductListDoctorReception,
|
||||
} from '#/views/doctor/doctor-reception/api';
|
||||
import traditionalJson from '#/views/business/chat/config/traditional.json';
|
||||
|
||||
export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
// 基础数据
|
||||
@@ -73,6 +74,11 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
const isInitialized = ref(false);
|
||||
const isPatientInfoLoaded = ref(false);
|
||||
|
||||
const traditionalChineseMedicine = ref(traditionalJson);
|
||||
const diseasesSelected = ref();
|
||||
const methodSelected = ref();
|
||||
const syndromeSelected = ref();
|
||||
|
||||
// 获取localStorage key
|
||||
const getStorageKey = () =>
|
||||
`prescriptionData-chat-${currentRegisterId.value}`;
|
||||
@@ -590,6 +596,7 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
|
||||
// 发送处方
|
||||
const sendPrescription = async (doctorSecondSignValue = 0) => {
|
||||
|
||||
if (currentDrugs.value.length === 0) {
|
||||
message.error('请选择药品');
|
||||
return false;
|
||||
@@ -625,7 +632,6 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
message.error('医嘱不能为空');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await addWestPrescription({
|
||||
patient: activePatient.value,
|
||||
@@ -647,6 +653,10 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
dosage: dosage.value,
|
||||
day_dosage: dayDosage.value,
|
||||
doctor_second_sign: doctorSecondSignValue,
|
||||
// 中医在线问诊所需的东西
|
||||
diseases_id: diseasesSelected.value,
|
||||
method_id: methodSelected.value,
|
||||
syndrome_id: syndromeSelected.value,
|
||||
}).then((res) => {
|
||||
message.success('处方已发送');
|
||||
sendMessage({
|
||||
@@ -798,5 +808,9 @@ export const usePrescriptionStore = defineStore('prescription', () => {
|
||||
syncToLocalStorage,
|
||||
loadFromLocalStorage,
|
||||
updateCurrentDrugs,
|
||||
traditionalChineseMedicine,
|
||||
diseasesSelected,
|
||||
methodSelected,
|
||||
syndromeSelected,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,25 +1,39 @@
|
||||
<script setup>
|
||||
import {computed, ref} from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import {Avatar, Button, Image} from 'ant-design-vue';
|
||||
import { Avatar, Button, Image } from 'ant-design-vue';
|
||||
|
||||
import {getChatMessageRegisterInfoApi} from "#/views/business/chat/api";
|
||||
import {getPrescriptionCheckStatusApi} from "#/views/business/order/prescription/api";
|
||||
import { getChatMessageRegisterInfoApi } from '#/views/business/chat/api';
|
||||
import { useChatStore } from '#/views/business/chat/stores/chat';
|
||||
import { sendMessage } from '#/views/business/chat/utils/request';
|
||||
import { getPrescriptionCheckStatusApi } from '#/views/business/order/prescription/api';
|
||||
import { receptionApi } from '#/views/doctor/doctor-reception/api';
|
||||
import PrescriptionDetail from '#/views/doctor/doctor-reception/components/PrescriptionDetail.vue';
|
||||
import RefusalOfTreatmentModal from '#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue';
|
||||
|
||||
import previewMedia from '../composables/useMediaPreview.ts';
|
||||
import {useThemeStore} from '../stores/theme.ts';
|
||||
import AudioMessage from './AudioMessage.vue';
|
||||
import {receptionApi} from "#/views/doctor/doctor-reception/api";
|
||||
import {useChatStore} from "#/views/business/chat/stores/chat";
|
||||
import { useThemeStore } from '../stores/theme.ts';
|
||||
import { useUserStore as chatUseUserStore } from '../stores/user';
|
||||
import {sendMessage} from "#/views/business/chat/utils/request";
|
||||
import RefusalOfTreatmentModal
|
||||
from "#/views/doctor/doctor-reception/components/RefusalOfTreatmentModal.vue";
|
||||
import AudioMessage from './AudioMessage.vue';
|
||||
|
||||
const props = defineProps({
|
||||
message: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
isSent: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
senderInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(['show-user-profile']);
|
||||
const chatUserStore = chatUseUserStore();
|
||||
const userStore = useUserStore();
|
||||
const chatStore = useChatStore();
|
||||
@@ -29,23 +43,6 @@ const [RefusalOfTreatmentModals, RefusalOfTreatmentModalApi] = useVbenModal({
|
||||
connectedComponent: RefusalOfTreatmentModal,
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
message: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
isSent: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
senderInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['show-user-profile']);
|
||||
|
||||
const avatarStyle = computed(() => ({
|
||||
background: props.senderInfo.color,
|
||||
}));
|
||||
@@ -85,18 +82,20 @@ const payStatusMap = {
|
||||
|
||||
const checkPrescriptionStatus = (id) => {
|
||||
if (!id) return;
|
||||
getPrescriptionCheckStatusApi({id}).then((res) => {
|
||||
getPrescriptionCheckStatusApi({ id }).then((res) => {
|
||||
statusInfo.value.status = res.status;
|
||||
statusInfo.value.text = prescriptionStatusMap[res.status];
|
||||
return prescriptionStatusMap[res.status]
|
||||
})
|
||||
return prescriptionStatusMap[res.status];
|
||||
});
|
||||
};
|
||||
|
||||
const getRegisterCardInfo = () => {
|
||||
getChatMessageRegisterInfoApi({ id: props.message.content.id }).then((res) => {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.message.content = res;
|
||||
});
|
||||
getChatMessageRegisterInfoApi({ id: props.message.content.id }).then(
|
||||
(res) => {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.message.content = res;
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
// 接诊操作
|
||||
@@ -105,7 +104,6 @@ const acceptRegister = async (registerId, orderNo) => {
|
||||
|
||||
registerOperating.value = true;
|
||||
|
||||
|
||||
try {
|
||||
// 模拟API调用
|
||||
|
||||
@@ -124,7 +122,8 @@ const acceptRegister = async (registerId, orderNo) => {
|
||||
read: true,
|
||||
duration: 0,
|
||||
};
|
||||
|
||||
localStorage.setItem('currentRegisterId', reregisterId);
|
||||
// chatStore.currentFriend?.register_id = reregisterId;
|
||||
chatStore.addMessage(messageObj, chatUserStore.currentUser.id);
|
||||
await sendMessage({
|
||||
senderId: chatUserStore.currentUser.id,
|
||||
@@ -134,7 +133,6 @@ const acceptRegister = async (registerId, orderNo) => {
|
||||
content: '我已接诊,请简单说明您的情况~',
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('接诊失败:', error);
|
||||
} finally {
|
||||
@@ -192,7 +190,7 @@ const formatDuration = (seconds) => {
|
||||
};
|
||||
|
||||
const formatTextWithLinks = (text) => {
|
||||
console.log(text, props.message)
|
||||
console.log(text, props.message);
|
||||
if (!text) return text; // 或 return text (但可能返回 undefined/null,根据需求调整)
|
||||
const urlRegex = /(https?:\/\/\S+)/g;
|
||||
return text.replaceAll(
|
||||
@@ -231,9 +229,9 @@ const [PrescriptionDetailModal, PrescriptionDetailModalApi] = useVbenModal({
|
||||
const viewPrescription = (item) => {
|
||||
PrescriptionDetailModalApi.setData({
|
||||
values: item.id,
|
||||
})
|
||||
});
|
||||
PrescriptionDetailModalApi.open();
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化日期时间
|
||||
const formatDateTime = (timestamp) => {
|
||||
@@ -244,7 +242,7 @@ const formatDateTime = (timestamp) => {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
@@ -253,7 +251,6 @@ const getSexText = (sex) => {
|
||||
return sex === 1 ? '男' : '女';
|
||||
};
|
||||
|
||||
|
||||
if (props.message.type === 'register') {
|
||||
getRegisterCardInfo();
|
||||
}
|
||||
@@ -270,16 +267,22 @@ if (props.message.type === 'register') {
|
||||
<div
|
||||
v-if="isSent"
|
||||
:style="avatarStyle"
|
||||
class="rounded-full cursor-pointer"
|
||||
class="cursor-pointer rounded-full"
|
||||
@click="showUserProfile"
|
||||
>
|
||||
<Avatar v-if="userStore.userInfo?.avatar" :size="48" :src="userStore.userInfo?.avatar" />
|
||||
<Avatar v-else :size="48">{{ userStore.userInfo?.nick_name.charAt(0) }}</Avatar>
|
||||
<Avatar
|
||||
v-if="userStore.userInfo?.avatar"
|
||||
:size="48"
|
||||
:src="userStore.userInfo?.avatar"
|
||||
/>
|
||||
<Avatar v-else :size="48">
|
||||
{{ userStore.userInfo?.nick_name.charAt(0) }}
|
||||
</Avatar>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
:style="avatarStyle"
|
||||
class="rounded-full cursor-pointer"
|
||||
class="cursor-pointer rounded-full"
|
||||
@click="showUserProfile"
|
||||
>
|
||||
<Avatar v-if="senderInfo.avatar" :size="48" :src="senderInfo.avatar" />
|
||||
@@ -289,10 +292,13 @@ if (props.message.type === 'register') {
|
||||
<!-- 消息内容区域 -->
|
||||
<div
|
||||
:class="isSent ? 'items-end' : 'items-start'"
|
||||
class="flex flex-col max-w-xs md:max-w-md lg:max-w-lg xl:max-w-xl"
|
||||
class="flex max-w-xs flex-col md:max-w-md lg:max-w-lg xl:max-w-xl"
|
||||
>
|
||||
<!-- 发送者名称 -->
|
||||
<div v-if="isSent" class="mb-1 px-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
<div
|
||||
v-if="isSent"
|
||||
class="mb-1 px-2 text-xs text-gray-500 dark:text-gray-400"
|
||||
>
|
||||
{{ userStore.userInfo?.nick_name }}
|
||||
</div>
|
||||
<div v-else class="mb-1 px-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
@@ -310,7 +316,7 @@ if (props.message.type === 'register') {
|
||||
<Image
|
||||
:src="message.content"
|
||||
alt="图片消息"
|
||||
class="rounded-lg max-w-full"
|
||||
class="max-w-full rounded-lg"
|
||||
@error="handleImageError"
|
||||
/>
|
||||
</div>
|
||||
@@ -323,7 +329,7 @@ if (props.message.type === 'register') {
|
||||
>
|
||||
<video
|
||||
:src="message.content"
|
||||
class="rounded-lg max-w-full video-thumbnail"
|
||||
class="video-thumbnail max-w-full rounded-lg"
|
||||
preload="metadata"
|
||||
@error="handleVideoError"
|
||||
></video>
|
||||
@@ -372,39 +378,49 @@ if (props.message.type === 'register') {
|
||||
/>
|
||||
|
||||
<!-- 挂号卡片消息 -->
|
||||
<div
|
||||
v-else-if="message.type === 'register'"
|
||||
class="register-card"
|
||||
>
|
||||
<div v-else-if="message.type === 'register'" class="register-card">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-green-100 dark:bg-green-900 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-calendar-check text-green-500 dark:text-green-300 text-xl"></i>
|
||||
<div
|
||||
class="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-green-100 dark:bg-green-900"
|
||||
>
|
||||
<i
|
||||
class="fas fa-calendar-check text-xl text-green-500 dark:text-green-300"
|
||||
></i>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="font-semibold text-gray-800 dark:text-gray-100">挂号信息</div>
|
||||
<div class="font-semibold text-gray-800 dark:text-gray-100">
|
||||
挂号信息
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'bg-yellow-100 text-yellow-800': message.content.status === 0,
|
||||
'bg-yellow-100 text-yellow-800':
|
||||
message.content.status === 0,
|
||||
'bg-blue-100 text-blue-800': message.content.status === 1,
|
||||
'bg-green-100 text-green-800': message.content.status === 2,
|
||||
'bg-red-100 text-red-800': message.content.status === 3,
|
||||
'bg-gray-100 text-gray-800': message.content.status === 4,
|
||||
'bg-purple-100 text-purple-800': message.content.status === 5,
|
||||
'bg-indigo-100 text-indigo-800': message.content.status === 6,
|
||||
'bg-purple-100 text-purple-800':
|
||||
message.content.status === 5,
|
||||
'bg-indigo-100 text-indigo-800':
|
||||
message.content.status === 6,
|
||||
'bg-pink-100 text-pink-800': message.content.status === 7,
|
||||
}"
|
||||
class="text-xs px-2 py-1 rounded-full font-medium"
|
||||
class="rounded-full px-2 py-1 text-xs font-medium"
|
||||
>
|
||||
{{ registerStatusMap[message.content.status] || '未知状态' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-1 flex flex-wrap gap-2 text-xs text-gray-600 dark:text-gray-300">
|
||||
<div
|
||||
class="mt-1 flex flex-wrap gap-2 text-xs text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-hashtag text-xs"></i>
|
||||
<span class="truncate max-w-[120px]">{{ message.content.order_no }}</span>
|
||||
<span class="max-w-[120px] truncate">{{
|
||||
message.content.order_no
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
@@ -416,21 +432,25 @@ if (props.message.type === 'register') {
|
||||
</div>
|
||||
|
||||
<!-- 患者信息 -->
|
||||
<div class="mt-3 p-3 bg-gray-50 dark:bg-gray-800 rounded-lg">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="font-medium text-gray-700 dark:text-gray-200">患者信息</div>
|
||||
<div class="mt-3 rounded-lg bg-gray-50 p-3 dark:bg-gray-800">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<div class="font-medium text-gray-700 dark:text-gray-200">
|
||||
患者信息
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'bg-red-100 text-red-800': message.content.is_pay === 0,
|
||||
'bg-green-100 text-green-800': message.content.is_pay === 1
|
||||
'bg-green-100 text-green-800': message.content.is_pay === 1,
|
||||
}"
|
||||
class="text-xs px-2 py-1 rounded-full font-medium"
|
||||
class="rounded-full px-2 py-1 text-xs font-medium"
|
||||
>
|
||||
{{ payStatusMap[message.content.is_pay] || '未知' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div
|
||||
class="grid grid-cols-2 gap-2 text-sm text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-user text-xs"></i>
|
||||
<span>{{ message.content.user_patient?.name || '未知' }}</span>
|
||||
@@ -445,37 +465,44 @@ if (props.message.type === 'register') {
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-phone text-xs"></i>
|
||||
<span>{{ message.content.user_patient?.mobile ? '已绑定' : '未绑定' }}</span>
|
||||
<span>{{
|
||||
message.content.user_patient?.mobile ? '已绑定' : '未绑定'
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<div class="mt-3 pt-3 border-t border-gray-200 dark:border-gray-600">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="mt-3 border-t border-gray-200 pt-3 dark:border-gray-600">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<div class="text-sm font-medium text-gray-700 dark:text-gray-200">
|
||||
挂号费用: <span class="text-green-500 dark:text-green-400">¥{{ message.content.price }}</span>
|
||||
挂号费用:
|
||||
<span class="text-green-500 dark:text-green-400">¥{{ message.content.price }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 接诊/拒诊按钮 - 只在待就诊状态显示 -->
|
||||
<div v-if="message.content.status === 1" class="flex gap-2 mt-2">
|
||||
<div v-if="message.content.status === 1" class="mt-2 flex gap-2">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
:loading="registerOperating"
|
||||
@click="acceptRegister(message.content.id, message.content.order_no)"
|
||||
class="flex-1"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="
|
||||
acceptRegister(message.content.id, message.content.order_no)
|
||||
"
|
||||
>
|
||||
<i class="fas fa-check mr-1"></i>
|
||||
接诊
|
||||
</Button>
|
||||
<Button
|
||||
:loading="registerOperating"
|
||||
class="flex-1"
|
||||
danger
|
||||
size="small"
|
||||
:loading="registerOperating"
|
||||
@click="rejectRegister(message.content.id, message.content.order_no)"
|
||||
class="flex-1"
|
||||
@click="
|
||||
rejectRegister(message.content.id, message.content.order_no)
|
||||
"
|
||||
>
|
||||
<i class="fas fa-times mr-1"></i>
|
||||
拒诊
|
||||
@@ -483,12 +510,12 @@ if (props.message.type === 'register') {
|
||||
</div>
|
||||
|
||||
<!-- 查看详情按钮 -->
|
||||
<div class="flex items-center justify-center mt-2">
|
||||
<div class="flex items-center text-blue-500 dark:text-blue-300 hover:text-blue-600 dark:hover:text-blue-200 transition-colors cursor-pointer">
|
||||
<span class="text-sm font-medium">查看详情</span>
|
||||
<i class="fas fa-chevron-right ml-1 text-xs"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="flex items-center justify-center mt-2">-->
|
||||
<!-- <div class="flex items-center text-blue-500 dark:text-blue-300 hover:text-blue-600 dark:hover:text-blue-200 transition-colors cursor-pointer">-->
|
||||
<!-- <span class="text-sm font-medium">查看详情</span>-->
|
||||
<!-- <i class="fas fa-chevron-right ml-1 text-xs"></i>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
|
||||
<!-- 时间信息 -->
|
||||
@@ -507,31 +534,45 @@ if (props.message.type === 'register') {
|
||||
@click="viewPrescription(message.content)"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-12 h-12 rounded-full bg-blue-100 dark:bg-blue-900 flex items-center justify-center flex-shrink-0">
|
||||
<i class="fas fa-file-prescription text-blue-500 dark:text-blue-300 text-xl"></i>
|
||||
<div
|
||||
class="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900"
|
||||
>
|
||||
<i
|
||||
class="fas fa-file-prescription text-xl text-blue-500 dark:text-blue-300"
|
||||
></i>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="font-semibold text-gray-800 dark:text-gray-100">电子处方</div>
|
||||
<div class="font-semibold text-gray-800 dark:text-gray-100">
|
||||
电子处方
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'bg-yellow-100 text-yellow-800': statusInfo.status === 0,
|
||||
'bg-green-100 text-green-800': statusInfo.status === 1,
|
||||
'bg-red-100 text-red-800': statusInfo.status === 2,
|
||||
'bg-blue-100 text-blue-800': statusInfo.status === 3,
|
||||
'bg-gray-100 text-gray-800': statusInfo.status === 4
|
||||
}"
|
||||
class="text-xs px-2 py-1 rounded-full font-medium"
|
||||
'bg-yellow-100 text-yellow-800': statusInfo.status === 0,
|
||||
'bg-green-100 text-green-800': statusInfo.status === 1,
|
||||
'bg-red-100 text-red-800': statusInfo.status === 2,
|
||||
'bg-blue-100 text-blue-800': statusInfo.status === 3,
|
||||
'bg-gray-100 text-gray-800': statusInfo.status === 4,
|
||||
}"
|
||||
class="rounded-full px-2 py-1 text-xs font-medium"
|
||||
>
|
||||
{{ checkPrescriptionStatus(message.content.id) || statusInfo.text || '加载中' }}
|
||||
{{
|
||||
checkPrescriptionStatus(message.content.id) ||
|
||||
statusInfo.text ||
|
||||
'加载中'
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-1 flex flex-wrap gap-2 text-xs text-gray-600 dark:text-gray-300">
|
||||
<div
|
||||
class="mt-1 flex flex-wrap gap-2 text-xs text-gray-600 dark:text-gray-300"
|
||||
>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-hashtag text-xs"></i>
|
||||
<span class="truncate max-w-[100px]">{{ message.content.order_no }}</span>
|
||||
<span class="max-w-[100px] truncate">{{
|
||||
message.content.order_no
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
@@ -542,21 +583,107 @@ if (props.message.type === 'register') {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 pt-2 border-t border-gray-200 dark:border-gray-600 flex items-center justify-between">
|
||||
<div
|
||||
class="mt-3 flex items-center justify-between border-t border-gray-200 pt-2 dark:border-gray-600"
|
||||
>
|
||||
<div class="text-sm font-medium text-gray-700 dark:text-gray-200">
|
||||
支付金额: <span class="text-red-500 dark:text-red-400">¥{{ message.content.total_pay_price }}</span>
|
||||
支付金额:
|
||||
<span class="text-red-500 dark:text-red-400">
|
||||
¥{{ message.content.total_pay_price }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center text-blue-500 dark:text-blue-300 hover:text-blue-600 dark:hover:text-blue-200 transition-colors">
|
||||
<div
|
||||
class="flex items-center text-blue-500 transition-colors hover:text-blue-600 dark:text-blue-300 dark:hover:text-blue-200"
|
||||
>
|
||||
<span class="text-sm font-medium">查看处方</span>
|
||||
<i class="fas fa-chevron-right ml-1 text-xs"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 在线复诊|购药信息 -->
|
||||
<div
|
||||
v-else-if="message.type === 'follow-up-visit'"
|
||||
class="group transition-all duration-200"
|
||||
>
|
||||
<!-- 卡片容器 -->
|
||||
<div
|
||||
:class="{
|
||||
'border-green-200': message.content.hasVisited === '1', // 已到访状态
|
||||
'border-yellow-200': message.content.hasVisited === '0', // 未到访状态
|
||||
}"
|
||||
class="rounded-lg border p-4 shadow-sm"
|
||||
>
|
||||
<!-- 标题区域 -->
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<h3 class="flex items-center text-lg font-semibold">
|
||||
<svg
|
||||
class="mr-2 h-4 w-4 text-green-500"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
{{ message.content.drug_name }} 复诊信息
|
||||
</h3>
|
||||
<span
|
||||
:class="{
|
||||
'text-green-800': message.content.hasVisited === '1',
|
||||
'bg-yellow-100 text-yellow-800':
|
||||
message.content.hasVisited === '0',
|
||||
}"
|
||||
class="rounded-full px-2 py-1 text-xs"
|
||||
>
|
||||
{{ message.content.hasVisited === '1' ? '就诊过' : '未就诊过' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 症状信息 -->
|
||||
<div class="space-y-2">
|
||||
<p class="flex items-start text-sm">
|
||||
<span class="w-20">症状描述:</span>
|
||||
<span class="flex-1">{{ message.content.illnessInfo }}</span>
|
||||
</p>
|
||||
|
||||
<!-- 用药状态 -->
|
||||
<p
|
||||
:class="{
|
||||
'font-medium text-blue-600':
|
||||
message.content.hasUsedDrug === '1',
|
||||
'text-gray-500': message.content.hasUsedDrug === '0',
|
||||
}"
|
||||
class="text-sm"
|
||||
>
|
||||
<span class="w-20 text-gray-500">用药情况:</span>
|
||||
{{
|
||||
message.content.hasUsedDrug === '1' ? '使用过' : '未使用过'
|
||||
}}
|
||||
</p>
|
||||
|
||||
<!-- 医生信息 -->
|
||||
<p
|
||||
class="mt-3 border-t border-gray-100 pt-3 text-sm text-gray-500"
|
||||
>
|
||||
<span class="w-20 text-gray-400">主诊医生:</span>
|
||||
ID: {{ message.content.doctor_id }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 通话消息 -->
|
||||
<div
|
||||
v-else-if="message.type === 'video-call' || message.type === 'voice-call'"
|
||||
v-else-if="
|
||||
message.type === 'video-call' || message.type === 'voice-call'
|
||||
"
|
||||
class="call-message"
|
||||
>
|
||||
<div class="call-info">
|
||||
@@ -865,29 +992,29 @@ if (props.message.type === 'register') {
|
||||
|
||||
/* 挂号卡片样式 */
|
||||
.register-card {
|
||||
@apply w-full max-w-xs md:max-w-sm cursor-pointer rounded-xl bg-white dark:bg-gray-700 p-4 shadow-sm transition-all duration-300;
|
||||
@apply border border-gray-200 dark:border-gray-600 hover:shadow-md hover:border-green-300 dark:hover:border-green-500;
|
||||
@apply w-full max-w-xs cursor-pointer rounded-xl bg-white p-4 shadow-sm transition-all duration-300 md:max-w-sm dark:bg-gray-700;
|
||||
@apply border border-gray-200 hover:border-green-300 hover:shadow-md dark:border-gray-600 dark:hover:border-green-500;
|
||||
}
|
||||
|
||||
.message-bubble.sent .register-card {
|
||||
@apply bg-green-50/30 dark:bg-green-900/30 border-green-200/50 dark:border-green-700/70;
|
||||
@apply border-green-200/50 bg-green-50/30 dark:border-green-700/70 dark:bg-green-900/30;
|
||||
}
|
||||
|
||||
.register-card:hover {
|
||||
@apply transform -translate-y-0.5;
|
||||
@apply -translate-y-0.5 transform;
|
||||
}
|
||||
|
||||
/* 处方卡片样式 - 使用TailwindCSS类替代 */
|
||||
.prescription-card {
|
||||
@apply w-full max-w-xs md:max-w-sm cursor-pointer rounded-xl bg-white dark:bg-gray-700 p-4 shadow-sm transition-all duration-300;
|
||||
@apply border border-gray-200 dark:border-gray-600 hover:shadow-md hover:border-blue-300 dark:hover:border-blue-500;
|
||||
@apply w-full max-w-xs cursor-pointer rounded-xl bg-white p-4 shadow-sm transition-all duration-300 md:max-w-sm dark:bg-gray-700;
|
||||
@apply border border-gray-200 hover:border-blue-300 hover:shadow-md dark:border-gray-600 dark:hover:border-blue-500;
|
||||
}
|
||||
|
||||
.message-bubble.sent .prescription-card {
|
||||
@apply bg-blue-50/30 dark:bg-blue-900/30 border-blue-200/50 dark:border-blue-700/70;
|
||||
@apply border-blue-200/50 bg-blue-50/30 dark:border-blue-700/70 dark:bg-blue-900/30;
|
||||
}
|
||||
|
||||
.prescription-card:hover {
|
||||
@apply transform -translate-y-0.5;
|
||||
@apply -translate-y-0.5 transform;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { usePrescriptionStore } from '#/store/prescription';
|
||||
|
||||
// import { getTraditionalChineseMedicineAllApi } from '#/views/doctor/doctor-reception/api';
|
||||
// 导入子组件
|
||||
import DiagnosisModal from '#/views/doctor/doctor-reception/components/DiagnosisModal.vue';
|
||||
import DoctorOrderModal from '#/views/doctor/doctor-reception/components/DoctorOrderModal.vue';
|
||||
@@ -82,7 +82,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
await prescriptionStore.initializePrescription(
|
||||
modalData.value.registerId,
|
||||
);
|
||||
prescriptionStore.loadFromLocalStorage()
|
||||
prescriptionStore.loadFromLocalStorage();
|
||||
} else {
|
||||
console.warn('未提供registerId');
|
||||
}
|
||||
@@ -228,6 +228,20 @@ const openPrescriptionDetail = (prescription: any) => {
|
||||
});
|
||||
PrescriptionDetailModalApi.open();
|
||||
};
|
||||
|
||||
/**
|
||||
* 拆选
|
||||
* @param input
|
||||
* @param option
|
||||
*/
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return (
|
||||
option.initials_of_pinyin.includes(input) ||
|
||||
option.name.includes(input) ||
|
||||
option.alias.includes(input) ||
|
||||
option.code.includes(input)
|
||||
);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -710,7 +724,16 @@ const openPrescriptionDetail = (prescription: any) => {
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col v-if="prescriptionStore.currentDrugs.length < 3" style="opacity: 0" :lg="12" :md="24" :sm="24" :xl="12" :xs="24" :xxl="8">
|
||||
<Col
|
||||
v-if="prescriptionStore.currentDrugs.length < 3"
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xl="12"
|
||||
:xs="24"
|
||||
:xxl="8"
|
||||
style="opacity: 0"
|
||||
>
|
||||
<Card class="prescription-card" title="">
|
||||
<div>
|
||||
<span class="card-index">{{ prescriptionStore.currentDrugs.length + 1 }}、</span>
|
||||
@@ -778,7 +801,16 @@ const openPrescriptionDetail = (prescription: any) => {
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col v-if="prescriptionStore.currentDrugs.length < 3" style="opacity: 0" :lg="12" :md="24" :sm="24" :xl="12" :xs="24" :xxl="8">
|
||||
<Col
|
||||
v-if="prescriptionStore.currentDrugs.length < 3"
|
||||
:lg="12"
|
||||
:md="24"
|
||||
:sm="24"
|
||||
:xl="12"
|
||||
:xs="24"
|
||||
:xxl="8"
|
||||
style="opacity: 0"
|
||||
>
|
||||
<Card class="prescription-card" title="">
|
||||
<div>
|
||||
<span class="card-index">{{ prescriptionStore.currentDrugs.length + 1 }}、</span>
|
||||
@@ -918,15 +950,110 @@ const openPrescriptionDetail = (prescription: any) => {
|
||||
|
||||
<!-- 诊断和医嘱区域 -->
|
||||
<div class="diagnosis-area">
|
||||
<!-- 中医证候 -->
|
||||
<div v-if="prescriptionStore.activeCategory === 1" class="mb-3">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label class="font-medium">中医证候</label>
|
||||
<!-- <Button type="primary" @click="openDiagnosisModal">中医证候</Button>-->
|
||||
</div>
|
||||
|
||||
<!-- <Select-->
|
||||
<!-- v-if="traditionalChineseMedicine"-->
|
||||
<!-- v-model:value="diseasesSelected"-->
|
||||
<!-- :filter-option="false"-->
|
||||
<!-- class="w-full mt-3"-->
|
||||
<!-- placeholder="中医证候"-->
|
||||
<!-- show-search-->
|
||||
<!-- @search="searchTraditionalDiseases"-->
|
||||
<!-- >-->
|
||||
<Select
|
||||
v-if="prescriptionStore.traditionalChineseMedicine"
|
||||
v-model:value="prescriptionStore.diseasesSelected"
|
||||
:field-names="{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}"
|
||||
:filter-option="filterOption"
|
||||
:options="prescriptionStore.traditionalChineseMedicine.diseases"
|
||||
class="mt-3 w-full"
|
||||
placeholder="中医证候"
|
||||
show-search
|
||||
>
|
||||
<!-- <SelectOption-->
|
||||
<!-- v-for="(value, index) in traditionalChineseMedicine.diseases"-->
|
||||
<!-- :key="index"-->
|
||||
<!-- :value="value.id"-->
|
||||
<!-- >-->
|
||||
<!-- {{ value.name }}({{ value.code }})-->
|
||||
<!-- </SelectOption>-->
|
||||
</Select>
|
||||
<!-- <Textarea-->
|
||||
<!-- v-model:value="prescriptionStore.diagnosis"-->
|
||||
<!-- placeholder="输入中医证候..."-->
|
||||
<!-- disabled-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
<!-- 中医治法 -->
|
||||
<div v-if="prescriptionStore.activeCategory === 1" class="mb-3">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label class="font-medium">中医治法</label>
|
||||
<!-- <Button type="primary" @click="openDiagnosisModal">中医治法</Button>-->
|
||||
</div>
|
||||
<Select
|
||||
v-if="prescriptionStore.traditionalChineseMedicine"
|
||||
v-model:value="prescriptionStore.methodSelected"
|
||||
:field-names="{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}"
|
||||
:filter-option="filterOption"
|
||||
:options="prescriptionStore.traditionalChineseMedicine.method"
|
||||
class="mt-3 w-full"
|
||||
placeholder="中医证候"
|
||||
show-search
|
||||
/>
|
||||
<!-- <Textarea-->
|
||||
<!-- v-model:value="prescriptionStore.diagnosis"-->
|
||||
<!-- placeholder="输入中医治法..."-->
|
||||
<!-- disabled-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
<!-- 中医疾病 -->
|
||||
<div v-if="prescriptionStore.activeCategory === 1" class="mb-3">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label class="font-medium">中医疾病</label>
|
||||
<!-- <Button type="primary" @click="openDiagnosisModal">中医疾病</Button>-->
|
||||
</div>
|
||||
|
||||
<Select
|
||||
v-if="prescriptionStore.traditionalChineseMedicine"
|
||||
v-model:value="prescriptionStore.syndromeSelected"
|
||||
:field-names="{
|
||||
label: 'name',
|
||||
value: 'id',
|
||||
}"
|
||||
:filter-option="filterOption"
|
||||
:options="prescriptionStore.traditionalChineseMedicine.syndrome"
|
||||
class="mt-3 w-full"
|
||||
placeholder="中医证候"
|
||||
show-search
|
||||
/>
|
||||
<!-- <Textarea-->
|
||||
<!-- v-model:value="prescriptionStore.diagnosis"-->
|
||||
<!-- placeholder="输入中医疾病..."-->
|
||||
<!-- disabled-->
|
||||
<!-- />-->
|
||||
</div>
|
||||
<!-- 诊断输入 -->
|
||||
<div class="mb-3">
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label class="font-medium">诊断结果</label>
|
||||
<label class="font-medium">常用诊断</label>
|
||||
<Button type="primary" @click="openDiagnosisModal">常用诊断</Button>
|
||||
</div>
|
||||
<Textarea
|
||||
v-model:value="prescriptionStore.diagnosis"
|
||||
placeholder="输入诊断结果..."
|
||||
disabled
|
||||
placeholder="输入常用诊断..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
id: message.id,
|
||||
type: getMessageType(message.message_type),
|
||||
content:
|
||||
message.message_type === 4 || message.message_type === 10
|
||||
message.message_type === 4 || message.message_type === 10 || message.message_type === 11
|
||||
? JSON.parse(message.message_content)
|
||||
: message.message_content,
|
||||
time: message.created_at_text,
|
||||
@@ -383,6 +383,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
'file',
|
||||
'',
|
||||
'register',
|
||||
'follow-up-visit',
|
||||
];
|
||||
return types[type] || 'text';
|
||||
};
|
||||
|
||||
@@ -77,6 +77,12 @@ function getColor(status: any) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const orderTypeMap = {
|
||||
1: '处方订单',
|
||||
2: '预约购药订单',
|
||||
3: '商城处方订单',
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Modal class="w-[80%]" title="订单详情">
|
||||
@@ -91,7 +97,7 @@ function getColor(status: any) {
|
||||
{{ data.order_no }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="订单类型">
|
||||
{{ data.order_type === 1 ? '普通订单' : '其他' }}
|
||||
{{ orderTypeMap[data.order_type] || '其他' }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="总支付价格">
|
||||
{{ data.total_pay_price }} 元
|
||||
@@ -99,7 +105,7 @@ function getColor(status: any) {
|
||||
<Descriptions.Item label="物品总价">
|
||||
{{ data.items_price }} 元
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="市场价">
|
||||
<Descriptions.Item label="供货价">
|
||||
{{ data.market_price }} 元
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="运费">
|
||||
@@ -216,7 +222,7 @@ function getColor(status: any) {
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<div class="mt-4" v-if="data.order_type !== 2 && data.order_type !== 3 && data.prescription.content">
|
||||
<h3>处方信息</h3>
|
||||
<Descriptions
|
||||
:column="{ xxl: 2, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 }"
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { VbenFormProps } from '#/adapter/form';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
import {getOrderStatusOption} from "#/views/business/order/product-order/api";
|
||||
import {getStoreOption} from "#/views/system/store/api";
|
||||
|
||||
export const formOptions: VbenFormProps = {
|
||||
// 默认展开
|
||||
@@ -16,6 +17,25 @@ export const formOptions: VbenFormProps = {
|
||||
fieldName: 'order_no',
|
||||
label: '订单号',
|
||||
},
|
||||
{
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
filterOption: true,
|
||||
// showSearch: true,
|
||||
// 菜单接口转options格式
|
||||
afterFetch: (data: { id: number; name: string }[]) => {
|
||||
return data.map((item: any) => ({
|
||||
label: `${item.name}【${item.id}】`,
|
||||
value: item.id,
|
||||
}));
|
||||
},
|
||||
api: getStoreOption,
|
||||
placeholder: '请选择',
|
||||
},
|
||||
fieldName: 'store_id',
|
||||
label: '门店',
|
||||
},
|
||||
{
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
|
||||
@@ -174,7 +174,7 @@ const openRefundModal = (id) => {
|
||||
<Modal />
|
||||
<RefundModal />
|
||||
<PrescriptionDetailModal />
|
||||
<AnalysisOverview :items="overviewItems" :my-card="false" class="mt-5" />
|
||||
<AnalysisOverview :items="overviewItems" :my-card="false" />
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
@@ -233,16 +233,28 @@ const openRefundModal = (id) => {
|
||||
<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>
|
||||
<!-- 判断是否为非处方订单-->
|
||||
<div v-if="row.order_type === 2">
|
||||
<Tag v-if="row.order_type === 1" color="yellow">处方订单</Tag>
|
||||
<Tag v-else-if="row.order_type === 2" color="yellow">
|
||||
预约购药订单
|
||||
</Tag>
|
||||
<Tag v-else-if="row.order_type === 3" color="yellow">
|
||||
商城处方订单
|
||||
</Tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Tag v-if="row.prescription_type === 1" color="orange">
|
||||
处方订单【中药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 2" color="blue">
|
||||
商品订单【西药】
|
||||
处方订单【西药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 3" color="purple">
|
||||
商品订单【非处方药】
|
||||
处方订单【非处方药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 4" color="green">
|
||||
已退款
|
||||
处方订单【西药】
|
||||
</Tag>
|
||||
<Tag v-else-if="row.prescription_type === 5" color="pink">
|
||||
产品服务包
|
||||
@@ -283,6 +295,7 @@ const openRefundModal = (id) => {
|
||||
label: '处方',
|
||||
type: 'link',
|
||||
icon: 'marketeq:eye',
|
||||
ifShow: row.order_type !== 2 && row.order_type !== 3,
|
||||
// auth: ['超级订单', 'sys:user:save'],
|
||||
onClick: openPrescriptionDetail.bind(null, row.p_id),
|
||||
},
|
||||
|
||||
@@ -175,6 +175,27 @@ export const modalFormProps: VbenFormProps = {
|
||||
label: '商品状态',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
placeholder: '请选择',
|
||||
options: [
|
||||
{
|
||||
label: '否',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '是',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultValue: 1,
|
||||
formItemClass: 'col-span-12',
|
||||
fieldName: 'is_otc',
|
||||
label: '是否处方药',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'Textarea',
|
||||
componentProps: {
|
||||
@@ -184,6 +205,24 @@ export const modalFormProps: VbenFormProps = {
|
||||
label: '药品主治功能',
|
||||
rules: 'required',
|
||||
},
|
||||
// {
|
||||
// component: 'Textarea',
|
||||
// componentProps: {
|
||||
// placeholder: '请输入对应症状',
|
||||
// },
|
||||
// fieldName: 'indications',
|
||||
// label: '对应症状',
|
||||
// rules: 'required',
|
||||
// },
|
||||
{
|
||||
component: 'InputSelect',
|
||||
componentProps: {
|
||||
placeholder: '请输入对应症状',
|
||||
},
|
||||
fieldName: 'indications',
|
||||
label: '对应症状',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'Avatar',
|
||||
fieldName: 'instruction',
|
||||
|
||||
@@ -45,7 +45,7 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
{ field: 'specification', title: '规格' },
|
||||
{ field: 'status', title: '状态', slots: { default: 'status' } },
|
||||
{ field: 'created_at', title: '发布时间' },
|
||||
{ type: 'html', title: '操作', slots: { default: 'action' } },
|
||||
{ type: 'html', title: '操作', width: 230, slots: { default: 'action' } },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
|
||||
@@ -95,6 +95,7 @@ const openExcelUploadModal = () => {
|
||||
<Grid>
|
||||
<template #toolbar-buttons>
|
||||
<TableAction
|
||||
:flex="false"
|
||||
:actions="[
|
||||
{
|
||||
label: '新增',
|
||||
|
||||
@@ -67,3 +67,10 @@ export async function salespersonListApi() {
|
||||
export async function salespersonCreateApi(data) {
|
||||
return requestClient.post<any>(`salesperson/create`, data);
|
||||
}
|
||||
/**
|
||||
* 编辑推广员
|
||||
* @param data
|
||||
*/
|
||||
export async function salespersonUpdateApi(data) {
|
||||
return requestClient.post<any>(`salesperson/update`, data);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import {useVbenModal} from '@vben/common-ui';
|
||||
|
||||
import { Button, Card, message } from 'ant-design-vue';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import {Button, Card, message} from 'ant-design-vue';
|
||||
import {PlusOutlined} from '@ant-design/icons-vue';
|
||||
|
||||
import QrCodePreview from '#/views/business/store/settings/components/SalespersonQrCodePreview.vue';
|
||||
import salespersonCreateModal from "#/views/business/store/settings/components/SalespersonCreateModal.vue";
|
||||
import salespersonCreateModal
|
||||
from "#/views/business/store/settings/components/SalespersonCreateModal.vue";
|
||||
import {ref} from "vue";
|
||||
import {salespersonListApi} from "#/views/business/store/settings/api";
|
||||
|
||||
@@ -40,84 +41,87 @@ const openSalespersonModal = () => {
|
||||
|
||||
SalespersonCreateModalApi.open();
|
||||
};
|
||||
|
||||
const openUpdateSalespersonModal = (values) => {
|
||||
|
||||
SalespersonCreateModalApi.setData({
|
||||
values,
|
||||
getList,
|
||||
update: true
|
||||
})
|
||||
SalespersonCreateModalApi.open();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
<SalespersonCreateModal />
|
||||
<QrCodePreviewModal />
|
||||
<Card
|
||||
class="rounded-xl shadow-md hover:shadow-lg transition-all duration-300 cursor-pointer border border-gray-200 p-6 items-center justify-center"
|
||||
@click="openSalespersonModal"
|
||||
>
|
||||
<!-- 内容容器:居中布局 + 垂直排列 -->
|
||||
<div class="flex flex-col items-center justify-center gap-3">
|
||||
<!-- 图标增强视觉引导 -->
|
||||
<PlusOutlined class="text-blue-500 text-2xl transition-transform duration-200 hover:scale-110" />
|
||||
|
||||
<!-- 按钮文字居中 + 优化字体样式 -->
|
||||
<Button
|
||||
type="link"
|
||||
@click.stop="openSalespersonModal"
|
||||
class="
|
||||
text-sm font-medium text-blue-600
|
||||
hover:text-blue-700 hover:underline-offset-4
|
||||
underline-decoration-clone
|
||||
"
|
||||
<div>
|
||||
<SalespersonCreateModal/>
|
||||
<QrCodePreviewModal/>
|
||||
<Card :title="`您拥有${data.total}个推广员`" class="w-full">
|
||||
<template #extra>
|
||||
<Button type="primary" @click="openSalespersonModal">新增推广员</Button>
|
||||
</template>
|
||||
<div
|
||||
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
<Card
|
||||
v-for="(item, index) in data.items"
|
||||
:key="index"
|
||||
class="rounded-lg shadow-sm"
|
||||
>
|
||||
添加推广员
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card
|
||||
v-for="(item, index) in data.items"
|
||||
:key="index"
|
||||
class="rounded-lg shadow-sm"
|
||||
>
|
||||
<!-- 顶部信息栏 -->
|
||||
<div class="mb-4 flex items-start justify-between">
|
||||
<h3 class="text-lg font-semibold text-gray-800">
|
||||
{{ item.nick_name || '未知医生' }}
|
||||
</h3>
|
||||
</div>
|
||||
<!-- 顶部信息栏 -->
|
||||
<div class="mb-4 flex items-start justify-between">
|
||||
<h3 class="text-lg font-semibold ">
|
||||
{{ item.nick_name || '未知' }}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<!-- 医生信息 -->
|
||||
<div class="mb-4 space-y-2 text-sm text-gray-600">
|
||||
<div class="flex justify-between">
|
||||
<span>手机号:</span>
|
||||
<span class="text-gray-800">{{ item.phone }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>加入时间:</span>
|
||||
<span>{{
|
||||
item.created_at
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>累计获客:</span>
|
||||
<span class="font-medium text-blue-600">100</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>本月获客:</span>
|
||||
<span class="font-medium text-blue-600">10</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 医生信息 -->
|
||||
<div class="mb-4 space-y-2 text-sm">
|
||||
<div class="flex justify-between">
|
||||
<span>手机号:</span>
|
||||
<span class="">{{ item.phone }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>加入时间:</span>
|
||||
<span>{{
|
||||
item.created_at
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>累计获客:</span>
|
||||
<span class="font-medium text-blue-600">{{ item.count.user_number }}</span>
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span>总佣金:</span>
|
||||
<span class="font-medium text-blue-600">{{ item.count.money }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 二维码区域 -->
|
||||
<div class="border-t border-gray-100 pt-4">
|
||||
<p class="mb-2 text-sm text-gray-600">联系二维码:</p>
|
||||
<div
|
||||
v-if="item.qr_code.qr_code"
|
||||
class="cursor-pointer"
|
||||
@click="openDoctorQrCode(item)"
|
||||
>
|
||||
<Button class="w-full" size="small" type="primary">查看二维码</Button>
|
||||
</div>
|
||||
<div v-else class="py-2 text-center text-sm text-gray-400">
|
||||
暂无二维码
|
||||
</div>
|
||||
<!-- 二维码区域 -->
|
||||
<div class="border-t border-gray-100 pt-4">
|
||||
<p class="mb-2 text-sm">联系二维码:</p>
|
||||
<div
|
||||
v-if="item.qr_code.qr_code"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<Button
|
||||
class="w-full"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="openDoctorQrCode(item)"
|
||||
>
|
||||
查看二维码
|
||||
</Button>
|
||||
</div>
|
||||
<div v-else class="py-2 text-center text-sm text-gray-400">
|
||||
暂无二维码
|
||||
</div>
|
||||
<Button @click="openUpdateSalespersonModal(item)" class="w-full mt-3" size="small"
|
||||
type="primary">编辑
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,16 @@ import { useVbenModal } from '@vben/common-ui';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import {salespersonCreateApi, saveNavUrlApi} from '#/views/business/store/settings/api';
|
||||
import {
|
||||
salespersonCreateApi,
|
||||
salespersonUpdateApi,
|
||||
saveNavUrlApi
|
||||
} from '#/views/business/store/settings/api';
|
||||
|
||||
import { salespersonModalFormProps } from '../config/form';
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const gridApi = ref();
|
||||
const getMyInfoApi = ref();
|
||||
|
||||
const [Form, formApi] = useVbenForm(salespersonModalFormProps);
|
||||
|
||||
@@ -27,12 +30,13 @@ const [Modal, modalApi] = useVbenModal({
|
||||
if (e.valid) {
|
||||
const values = await formApi.getValues();
|
||||
modalApi.setState({ loading: true, confirmLoading: true });
|
||||
const submitApi = salespersonCreateApi;
|
||||
const submitApi = isUpdate.value
|
||||
? salespersonUpdateApi
|
||||
: salespersonCreateApi;
|
||||
submitApi(values)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
gridApi.value?.reload();
|
||||
getMyInfoApi.value();
|
||||
modalApi.close();
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -43,9 +47,8 @@ const [Modal, modalApi] = useVbenModal({
|
||||
await formApi.validateAndSubmitForm();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
|
||||
gridApi.value = isOpen ? modalApi.getData()?.getList : null;
|
||||
if (isOpen) {
|
||||
getMyInfoApi.value = isOpen ? modalApi.getData()?.getMyInfo : null;
|
||||
const { values, update } = modalApi.getData<Record<string, any>>();
|
||||
if (values) {
|
||||
isUpdate.value = update;
|
||||
|
||||
@@ -36,6 +36,16 @@ export const salespersonModalFormProps: VbenFormProps = {
|
||||
// handleSubmit: onSubmit,
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
fieldName: 'id',
|
||||
label: 'ID',
|
||||
formItemClass: 'col-span-6',
|
||||
dependencies: {
|
||||
show: false,
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'phone',
|
||||
@@ -50,9 +60,32 @@ export const salespersonModalFormProps: VbenFormProps = {
|
||||
fieldName: 'nick_name',
|
||||
label: '名称',
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
fieldName: 'split_type',
|
||||
label: '分成类型',
|
||||
rules: 'required',
|
||||
componentProps: {
|
||||
minLength: 11,
|
||||
placeholder: '请选择',
|
||||
options: [
|
||||
{
|
||||
label: '元',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '百分比(%)',
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'split',
|
||||
label: '分成',
|
||||
rules: 'required',
|
||||
},
|
||||
// {
|
||||
// component: 'UploadImage',
|
||||
|
||||
@@ -93,12 +93,12 @@ const openExcelUploadModal = (type = 1) => {
|
||||
ExcelUploadModalApi.open();
|
||||
};
|
||||
|
||||
const updateStatus = (id) => {
|
||||
const updateStatus = (id: number) => {
|
||||
updateWarehouseDrugManagementStatusApi(id).then(() => {
|
||||
message.success('修改成功!');
|
||||
gridApi.reload();
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -160,7 +160,14 @@ const updateStatus = (id) => {
|
||||
</TableAction>
|
||||
</template>
|
||||
<template #image="{ row }">
|
||||
<Image :src="row.drug?.image || 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250510/cd470ebf97e31c4048ba502ba71b66a3.jpg'" height="30" width="30" />
|
||||
<Image
|
||||
:src="
|
||||
row.drug?.image ||
|
||||
'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk_upload_20250510/cd470ebf97e31c4048ba502ba71b66a3.jpg'
|
||||
"
|
||||
height="30"
|
||||
width="30"
|
||||
/>
|
||||
</template>
|
||||
<template #instruction="{ row }">
|
||||
<div class="div" style="width: 120px; height: 120px; overflow: scroll">
|
||||
@@ -168,9 +175,9 @@ const updateStatus = (id) => {
|
||||
</div>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<Tag :color="row.status === 2 ? 'green' : 'red'">{{
|
||||
row.status === 2 ? '上架' : '下架'
|
||||
}}</Tag>
|
||||
<Tag :color="row.status === 2 ? 'green' : 'red'">
|
||||
{{ row.status === 2 ? '上架' : '下架' }}
|
||||
</Tag>
|
||||
</template>
|
||||
<template #toolbar-tools></template>
|
||||
<template #action="{ row }">
|
||||
|
||||
@@ -102,3 +102,17 @@ export async function syncDrugApi(data: Record<string, any>) {
|
||||
export async function syncDrugPriceApi(data: Record<string, any>) {
|
||||
return requestClient.get(`${prefix}sync-drug-price`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查订阅总仓库价格api
|
||||
*/
|
||||
export async function checkSubscribeApi() {
|
||||
return requestClient.get(`${prefix}check-subscribe`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅总仓库价格api
|
||||
*/
|
||||
export async function subscribeApi() {
|
||||
return requestClient.get(`${prefix}subscribe`);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ import { TableAction } from '#/components/table-action';
|
||||
import { downloadByData } from '#/util/tool';
|
||||
|
||||
import {
|
||||
checkSubscribeApi,
|
||||
deleteWarehouseDrugManagementStore,
|
||||
exportWarehouseDrugManagementStoreApi, syncDrugApi, syncDrugPriceApi,
|
||||
exportWarehouseDrugManagementStoreApi, subscribeApi, syncDrugApi, syncDrugPriceApi,
|
||||
updateWarehouseDrugManagementStoreStatusApi
|
||||
} from './api';
|
||||
import FormModalDemo from './components/modal.vue';
|
||||
@@ -116,6 +117,22 @@ const syncDrugPrice = () => {
|
||||
gridApi.reload();
|
||||
});
|
||||
}
|
||||
|
||||
const isSubscribe = ref(true);
|
||||
|
||||
const checkSubscribe = () =>{
|
||||
checkSubscribeApi().then((res) => {
|
||||
isSubscribe.value = res;
|
||||
})
|
||||
};
|
||||
|
||||
const subscribe = () =>{
|
||||
subscribeApi().then(() => {
|
||||
message.success('操作成功!');
|
||||
})
|
||||
};
|
||||
|
||||
checkSubscribe();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -148,6 +165,14 @@ const syncDrugPrice = () => {
|
||||
// auth: ['超级西(中成)药', 'sys:user:save'],
|
||||
onClick: syncDrugPrice,
|
||||
},
|
||||
{
|
||||
label: '订阅仓库价格',
|
||||
type: 'primary',
|
||||
ifShow: !isSubscribe,
|
||||
icon: 'gridicons:reader-following',
|
||||
// auth: ['超级西(中成)药', 'sys:user:save'],
|
||||
onClick: subscribe,
|
||||
},
|
||||
]"
|
||||
:drop-down-actions="[
|
||||
{
|
||||
|
||||
@@ -172,16 +172,23 @@ const todayDate = getTodayDate();
|
||||
|
||||
<div class="mt-5 flex flex-col lg:flex-row">
|
||||
<div class="mr-4 w-full lg:w-3/5">
|
||||
<WorkbenchProject :items="projectItems" title="项目" @click="navTo" />
|
||||
<WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />
|
||||
</div>
|
||||
<div class="w-full lg:w-2/5">
|
||||
<!-- <WorkbenchProject :items="projectItems" title="项目" @click="navTo" />-->
|
||||
<!-- <WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />-->
|
||||
<WorkbenchQuickNav
|
||||
:items="quickNavItems"
|
||||
class="mt-5 lg:mt-0"
|
||||
title="快捷导航"
|
||||
@click="navTo"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full lg:w-2/5">
|
||||
<WorkbenchTrends :items="trendItems" class="mt-5" title="最新动态" />
|
||||
<!-- <WorkbenchQuickNav-->
|
||||
<!-- :items="quickNavItems"-->
|
||||
<!-- class="mt-5 lg:mt-0"-->
|
||||
<!-- title="快捷导航"-->
|
||||
<!-- @click="navTo"-->
|
||||
<!-- />-->
|
||||
<!-- <WorkbenchTodo :items="todoItems" class="mt-5" title="待办事项" />-->
|
||||
<!-- <AnalysisChartCard class="mt-5" title="访问来源">-->
|
||||
<!-- <AnalyticsVisitsSource />-->
|
||||
|
||||
@@ -642,8 +642,8 @@ function updateProductNumber(id, number) {
|
||||
<PlusOutlined key="add" @click="addProducts(item)" />
|
||||
</template>
|
||||
<CardMeta
|
||||
:description="item.drug?.pinyin_simple"
|
||||
:title="item.drug?.drug_name"
|
||||
:description="item.drug?.function"
|
||||
:title="`${item.drug?.drug_name}(${item.drug?.pinyin_simple})`"
|
||||
>
|
||||
<template #avatar>
|
||||
<a-avatar src="https://joeschmoe.io/api/v1/random" />
|
||||
@@ -651,9 +651,9 @@ function updateProductNumber(id, number) {
|
||||
</CardMeta>
|
||||
<div class="card-box mt-5" style="padding: 10px 5px">
|
||||
<Popover>
|
||||
<p class="drug-function text-xs">
|
||||
功效:{{ item.drug?.function }}
|
||||
</p>
|
||||
<!-- <p class="drug-function text-xs">-->
|
||||
<!-- 功效:{{ item.drug?.function }}-->
|
||||
<!-- </p>-->
|
||||
<template #content>
|
||||
<p>功效:{{ item.drug?.function }}</p>
|
||||
<p>用法:{{ item.drug?.usage }}</p>
|
||||
|
||||
@@ -7,6 +7,14 @@ const prefix = 'settlement/';
|
||||
export async function getSettlementList(data: any) {
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
/**
|
||||
* 分页查询用户列表
|
||||
* @param data
|
||||
*/
|
||||
export async function getSettlementItemsList(data: any) {
|
||||
data.type = 'items';
|
||||
return requestClient.get<any>(`${prefix}list`, { params: data });
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取管理员详情
|
||||
|
||||
@@ -31,6 +31,7 @@ const withdrawnFrozenAmount = ref(0);
|
||||
const frozenAmount = ref(0);
|
||||
// const arrivedAmount = ref(0);
|
||||
const fee = ref(0);
|
||||
const isShow = ref(false);
|
||||
const myCard = ref();
|
||||
|
||||
const overviewItems = ref<AnalysisOverviewItem[]>([]);
|
||||
@@ -136,6 +137,10 @@ function refresh() {
|
||||
showCard();
|
||||
}
|
||||
|
||||
function updateShowStatus() {
|
||||
isShow.value = !isShow.value;
|
||||
}
|
||||
|
||||
const showModal = (data = {}) => {
|
||||
formModalApi.setData({
|
||||
// 表单值
|
||||
@@ -164,6 +169,9 @@ const showCardModal = () => {
|
||||
:title="`${myCard?.user_name || myCard?.store?.name || myCard?.supplier?.name}--账户信息`"
|
||||
class="p-5"
|
||||
>
|
||||
<!-- <template #extra>-->
|
||||
<!-- <Button type="link" @click="updateShowStatus">{{ isShow === false ? '展开' : '收起' }}</Button>-->
|
||||
<!-- </template>-->
|
||||
<FormModal />
|
||||
<saveMyCardModal />
|
||||
<Button class="ml-5" type="primary" @click="showModal"> 申请提现 </Button>
|
||||
|
||||
@@ -4,6 +4,15 @@ export const formOptions2: VbenFormProps = {
|
||||
// 默认展开
|
||||
collapsed: false,
|
||||
schema: [
|
||||
// {
|
||||
// component: 'VbenInput',
|
||||
// componentProps: {
|
||||
// placeholder: '选择费用类型',
|
||||
// },
|
||||
// defaultValue: '',
|
||||
// fieldName: 'order_no',
|
||||
// label: '订单号',
|
||||
// },
|
||||
{
|
||||
component: 'VbenSelect',
|
||||
componentProps: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { VxeGridProps } from '#/adapter/vxe-table';
|
||||
|
||||
import { getSettlementList } from '#/views/finance/withdrawal/api/settlement';
|
||||
import {getSettlementItemsList, getSettlementList} from '#/views/finance/withdrawal/api/settlement';
|
||||
|
||||
interface RowType {
|
||||
id: string;
|
||||
@@ -40,6 +40,64 @@ export const gridOptions2: VxeGridProps<RowType> = {
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
// 请求后端接口方法
|
||||
query: async ({ page }, formValues) => {
|
||||
return await getSettlementItemsList({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
// height: 'auto',
|
||||
border: false,
|
||||
toolbarConfig: {
|
||||
// 是否显示搜索表单控制按钮
|
||||
// @ts-ignore 正式环境时有完整的类型声明
|
||||
search: true,
|
||||
refresh: true, // 刷新
|
||||
print: false, // 打印
|
||||
export: false, // 导出
|
||||
// custom: true, // 自定义列
|
||||
zoom: true, // 最大化最小化
|
||||
slots: {
|
||||
buttons: 'toolbar-buttons',
|
||||
},
|
||||
custom: {
|
||||
// 自定义列-图标
|
||||
icon: 'vxe-icon-menu',
|
||||
},
|
||||
},
|
||||
showOverflow: false,
|
||||
};
|
||||
|
||||
export const gridOptions3: VxeGridProps<RowType> = {
|
||||
checkboxConfig: {
|
||||
highlight: true,
|
||||
labelField: '',
|
||||
},
|
||||
columnConfig: {
|
||||
useKey: true,
|
||||
},
|
||||
rowConfig: {
|
||||
useKey: true,
|
||||
},
|
||||
columns: [
|
||||
// { type: 'checkbox', width: 60 },
|
||||
// { field: 'id', align: 'left', title: 'ID', width: 100 },
|
||||
{ field: 'order_no', title: '订单号' },
|
||||
{ field: 'user_id', title: '名称', slots: { default: 'user_id' } },
|
||||
{ field: 'money', title: '分账金额' },
|
||||
// { field: 'fee_type_txt', title: '费用类型' },
|
||||
// { field: 'status_txt', title: '结算状态' },
|
||||
{ field: 'created_at', title: '创建时间' },
|
||||
{ type: 'html', title: '操作', slots: { default: 'action' } },
|
||||
],
|
||||
keepSource: true,
|
||||
pagerConfig: {},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
// 请求后端接口方法
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AnalysisChartsTabs, Page } from '@vben/common-ui';
|
||||
|
||||
import { FloatButton, FloatButtonGroup, Popover, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { TableAction } from '#/components/table-action';
|
||||
import { Tag } from 'ant-design-vue';
|
||||
|
||||
import Statistics from './components/statistics.vue';
|
||||
import { formOptions } from './config/search';
|
||||
import { formOptions2 } from './config/settlement-search';
|
||||
import { gridOptions2 } from './config/settlement-table';
|
||||
import { gridOptions2, gridOptions3 } from './config/settlement-table';
|
||||
import { gridOptions } from './config/table';
|
||||
|
||||
const [Grid, GridApi] = useVbenVxeGrid({
|
||||
@@ -21,6 +24,11 @@ const [Grid2] = useVbenVxeGrid({
|
||||
gridOptions: gridOptions2,
|
||||
});
|
||||
|
||||
const [Grid3] = useVbenVxeGrid({
|
||||
formOptions: formOptions2,
|
||||
gridOptions: gridOptions3,
|
||||
});
|
||||
|
||||
const chartTabs = [
|
||||
{
|
||||
label: '提现记录',
|
||||
@@ -30,7 +38,17 @@ const chartTabs = [
|
||||
label: '结算记录',
|
||||
value: 'visits',
|
||||
},
|
||||
{
|
||||
label: '结算明细',
|
||||
value: 'visitsItems',
|
||||
},
|
||||
];
|
||||
|
||||
const isShow = ref(true);
|
||||
|
||||
function updateShowStatus() {
|
||||
isShow.value = !isShow.value;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -39,7 +57,7 @@ const chartTabs = [
|
||||
description="提现前请确认好您的打款账户"
|
||||
title="提现管理"
|
||||
>
|
||||
<Statistics :grid-api="GridApi" />
|
||||
<Statistics v-show="isShow" :grid-api="GridApi" />
|
||||
<AnalysisChartsTabs :tabs="chartTabs" class="mt-5">
|
||||
<template #trends>
|
||||
<Grid>
|
||||
@@ -69,7 +87,9 @@ const chartTabs = [
|
||||
<span v-else-if="row.dakuan_status === 1">打款成功</span>
|
||||
</template>
|
||||
<template #check_id="{ row }">
|
||||
<span>{{ row.check_admin?.username || row.check_admin?.nick_name || '暂无' }}</span>
|
||||
<span>{{
|
||||
row.check_admin?.username || row.check_admin?.nick_name || '暂无'
|
||||
}}</span>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
@@ -88,6 +108,34 @@ const chartTabs = [
|
||||
</Grid>
|
||||
</template>
|
||||
<template #visits>
|
||||
<!-- 提现记录 --->
|
||||
<Grid3>
|
||||
<template #toolbar-buttons></template>
|
||||
<template #toolbar-tools></template>
|
||||
<template #user_id="{ row }">
|
||||
<span v-if="row.user_type === 1">{{ row.store.name }}</span>
|
||||
<span v-else-if="row.user_type === 2">萧康平台</span>
|
||||
<span v-else-if="row.user_type === 3">{{ row.supplier.name }}</span>
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<TableAction
|
||||
:actions="[
|
||||
// {
|
||||
// label: '编辑',
|
||||
// type: 'link',
|
||||
// icon: 'uil:edit',
|
||||
// size: 'small',
|
||||
// // auth: ['admin', 'sys:role:detail'],
|
||||
// onClick: showModal.bind(null, row, true),
|
||||
// },
|
||||
]"
|
||||
:drop-down-actions="[]"
|
||||
/>
|
||||
</template>
|
||||
</Grid3>
|
||||
</template>
|
||||
<template #visitsItems>
|
||||
<!-- 结算明细 --->
|
||||
<Grid2>
|
||||
<template #toolbar-buttons></template>
|
||||
<template #toolbar-tools></template>
|
||||
@@ -114,5 +162,24 @@ const chartTabs = [
|
||||
</Grid2>
|
||||
</template>
|
||||
</AnalysisChartsTabs>
|
||||
<!-- 浮动按钮组 -->
|
||||
<FloatButtonGroup :style="{ right: '24px', bottom: '84px' }" shape="circle">
|
||||
<!-- 打开显示余额卡片的按钮 -->
|
||||
<Popover placement="left" title="显示余额卡片">
|
||||
<template #content>
|
||||
<p>点击展开卡片信息,再次点击收起</p>
|
||||
</template>
|
||||
<FloatButton
|
||||
:badge="{ dot: true }"
|
||||
:type="isShow === true ? 'primary' : 'dashed'"
|
||||
shape="circle"
|
||||
@click="updateShowStatus"
|
||||
>
|
||||
<template #icon>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="24" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"><path d="M21.5 16.052V7.948a4.14 4.14 0 0 0-1.236-2.945a4.25 4.25 0 0 0-2.985-1.22H6.72a4.25 4.25 0 0 0-2.985 1.22A4.14 4.14 0 0 0 2.5 7.948v8.104c0 1.105.445 2.164 1.236 2.945a4.25 4.25 0 0 0 2.985 1.22H17.28c1.12 0 2.193-.44 2.985-1.22a4.14 4.14 0 0 0 1.236-2.945"/><path d="M8.552 12.14a2.054 2.054 0 1 0 0-4.108a2.054 2.054 0 0 0 0 4.108m3.081 3.828c0-.812-.324-1.59-.902-2.165a3.09 3.09 0 0 0-4.358 0a3.05 3.05 0 0 0-.902 2.165m9.097-7.049h3.594M14.568 12h1.54m-1.54 3.081h3.594"/></g></svg>
|
||||
</template>
|
||||
</FloatButton>
|
||||
</Popover>
|
||||
</FloatButtonGroup>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
@@ -50,7 +50,8 @@ const [Modal, modalApi] = useVbenModal({
|
||||
{{ data.controller }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="IP">
|
||||
{{ data.ip === '127.0.0.1' ? '本地' : data.ip }}
|
||||
IP地址:{{ data.ip }}
|
||||
<p>归属地:{{data.ip_address}}</p>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="类型">
|
||||
{{ data.type === 0 ? '访问成功' : '访问失败' }}
|
||||
|
||||
@@ -6,6 +6,18 @@ export const formOptions: VbenFormProps = {
|
||||
// 默认展开
|
||||
collapsed: false,
|
||||
schema: [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
// defaultValue: [dayjs().startOf('month'), dayjs()],
|
||||
fieldName: 'user_id',
|
||||
label: '用户ID',
|
||||
},
|
||||
{
|
||||
component: 'VbenInput',
|
||||
// defaultValue: [dayjs().startOf('month'), dayjs()],
|
||||
fieldName: 'router',
|
||||
label: 'api接口',
|
||||
},
|
||||
{
|
||||
component: 'RangePicker',
|
||||
componentProps: {
|
||||
@@ -22,7 +34,7 @@ export const formOptions: VbenFormProps = {
|
||||
content: '查询',
|
||||
},
|
||||
// 是否在字段值改变时提交表单
|
||||
submitOnChange: true,
|
||||
submitOnChange: false,
|
||||
// 按下回车时是否提交表单
|
||||
submitOnEnter: false,
|
||||
submitOnEnter: true,
|
||||
};
|
||||
|
||||
@@ -33,6 +33,7 @@ export const gridOptions: VxeGridProps<RowType> = {
|
||||
},
|
||||
{ field: 'url', title: '访问路由' },
|
||||
{ field: 'ip', title: '用户IP地址' },
|
||||
{ field: 'ip_address', title: 'IP归属地' },
|
||||
{ field: 'controller', title: '访问控制器' },
|
||||
// { field: 'param', title: '携带参数' },
|
||||
{ field: 'equipment', title: '操作系统', slots: { default: 'equipment' }, width: 80 },
|
||||
|
||||
@@ -68,7 +68,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
// 自定义过滤逻辑,确保可以根据 name 进行搜索
|
||||
return option?.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
},
|
||||
showSearch: true,
|
||||
// showSearch: true,
|
||||
// 菜单接口转options格式
|
||||
afterFetch: (data: { id: number; name: string }[]) => {
|
||||
return data.map((item: any) => ({
|
||||
|
||||
Reference in New Issue
Block a user