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:
175
apps/web-antd/src/components/form/components/upload-image.vue
Normal file
175
apps/web-antd/src/components/form/components/upload-image.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Modal, Upload } from 'ant-design-vue';
|
||||
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { Icon } from '#/components/icon';
|
||||
|
||||
defineOptions({
|
||||
name: 'UploadImage',
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array as () => string[],
|
||||
default: () => [],
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
maxCount: {
|
||||
type: Number,
|
||||
default: 9,
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:modelValue']);
|
||||
|
||||
const mValue = useVModel(props, 'modelValue', emits, {
|
||||
passive: true,
|
||||
});
|
||||
|
||||
const fileList = ref(
|
||||
props.modelValue.map((url) => ({
|
||||
uid: url,
|
||||
name: url.split('/').pop() || 'file',
|
||||
status: 'done',
|
||||
url,
|
||||
})),
|
||||
);
|
||||
|
||||
// 监听 modelValue 变化,同步到 fileList
|
||||
watch(props.modelValue, (newVal) => {
|
||||
fileList.value = newVal.map((url) => ({
|
||||
uid: url,
|
||||
name: url.split('/').pop() || 'file',
|
||||
status: 'done',
|
||||
url,
|
||||
}));
|
||||
});
|
||||
|
||||
// 监听 fileList 变化,同步到 modelValue
|
||||
watch(fileList, (newVal) => {
|
||||
mValue.value = newVal
|
||||
.filter((file) => file.status === 'done' && file.url)
|
||||
.map((file) => file.url);
|
||||
});
|
||||
|
||||
const customRequest = async (e: any) => {
|
||||
try {
|
||||
const res = await uploadFile({
|
||||
file: e.file,
|
||||
});
|
||||
|
||||
// 更新 fileList
|
||||
fileList.value = [
|
||||
...fileList.value.filter((file) => file.status !== 'uploading'),
|
||||
{
|
||||
uid: res.url,
|
||||
name: e.file.name,
|
||||
status: 'done',
|
||||
url: res.url,
|
||||
},
|
||||
];
|
||||
|
||||
// 更新 modelValue
|
||||
mValue.value = fileList.value.map((file) => file.url);
|
||||
|
||||
// 触发上传完成回调
|
||||
e.onSuccess?.(res);
|
||||
} catch (error) {
|
||||
console.error('上传失败', error);
|
||||
e.onError?.(error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemove = (file: any) => {
|
||||
// 从 fileList 中移除
|
||||
fileList.value = fileList.value.filter((item) => item.uid !== file.uid);
|
||||
|
||||
// 更新 modelValue
|
||||
mValue.value = fileList.value.map((file) => file.url);
|
||||
};
|
||||
|
||||
const previewVisible = ref(false);
|
||||
const previewImage = ref('');
|
||||
const previewTitle = ref('');
|
||||
|
||||
const handlePreview = async (file) => {
|
||||
previewImage.value = file.response.url || file.preview;
|
||||
previewVisible.value = true;
|
||||
previewTitle.value =
|
||||
file.name || file.url.slice(Math.max(0, file.url.lastIndexOf('/') + 1));
|
||||
};
|
||||
|
||||
// 计算是否还能上传更多图片
|
||||
const showUploadButton = computed(() =>
|
||||
props.multiple
|
||||
? fileList.value.length < props.maxCount
|
||||
: fileList.value.length === 0,
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Upload
|
||||
v-model:value="fileList"
|
||||
:custom-request="customRequest"
|
||||
:multiple="multiple"
|
||||
:limit="maxCount"
|
||||
:show-upload-list="{ showPreviewIcon: true, showRemoveIcon: true }"
|
||||
list-type="picture-card"
|
||||
@remove="handleRemove"
|
||||
@preview="handlePreview"
|
||||
>
|
||||
<div v-if="showUploadButton" class="upload-button">
|
||||
<Icon icon="ant-design:plus-outlined" />
|
||||
<div class="ant-upload-text">上传图片</div>
|
||||
</div>
|
||||
</Upload>
|
||||
<Modal
|
||||
v-model:visible="previewVisible"
|
||||
:title="previewTitle"
|
||||
footer=""
|
||||
width="60%"
|
||||
>
|
||||
<img alt="example" style="width: 100%" :src="previewImage" />
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.m-avatar-wrap {
|
||||
position: relative;
|
||||
height: 102px;
|
||||
width: 102px;
|
||||
|
||||
.m-avatar-icon-delete {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
border-radius: 0 0 0 4px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
&:hover .m-avatar-icon-delete {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-button {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -13,6 +13,9 @@ import previewMedia from '../composables/useMediaPreview.ts';
|
||||
import {useThemeStore} from '../stores/theme.ts';
|
||||
import AudioMessage from './AudioMessage.vue';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
const props = defineProps({
|
||||
message: {
|
||||
type: Object,
|
||||
@@ -30,10 +33,6 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['show-user-profile']);
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
const avatarStyle = computed(() => ({
|
||||
background: props.senderInfo.color,
|
||||
}));
|
||||
@@ -43,6 +42,8 @@ const statusInfo = ref({
|
||||
text: '',
|
||||
});
|
||||
|
||||
// 挂号操作状态
|
||||
const registerOperating = ref(false);
|
||||
|
||||
// 添加处方状态映射
|
||||
const prescriptionStatusMap = {
|
||||
@@ -51,6 +52,21 @@ const prescriptionStatusMap = {
|
||||
2: '未通过',
|
||||
};
|
||||
|
||||
// 添加挂号状态映射
|
||||
const registerStatusMap = {
|
||||
0: '待就诊',
|
||||
1: '已缴费',
|
||||
2: '已就诊',
|
||||
3: '已取消',
|
||||
4: '已退费'
|
||||
};
|
||||
|
||||
// 添加支付状态映射
|
||||
const payStatusMap = {
|
||||
0: '未支付',
|
||||
1: '已支付'
|
||||
};
|
||||
|
||||
const checkPrescriptionStatus = (id) => {
|
||||
if (!id) return;
|
||||
getPrescriptionCheckStatusApi({id}).then((res) => {
|
||||
@@ -60,6 +76,62 @@ const checkPrescriptionStatus = (id) => {
|
||||
})
|
||||
};
|
||||
|
||||
// 接诊操作
|
||||
const acceptRegister = async (registerId, orderNo) => {
|
||||
if (registerOperating.value) return;
|
||||
|
||||
registerOperating.value = true;
|
||||
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
|
||||
// 更新消息状态
|
||||
if (props.message.content && props.message.content.id === registerId) {
|
||||
props.message.content.status = 2; // 已就诊
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
console.log(`接诊成功 - 挂号ID: ${registerId}, 订单号: ${orderNo}`);
|
||||
|
||||
// 这里可以调用实际的API
|
||||
// await acceptRegisterApi({ id: registerId, order_no: orderNo });
|
||||
|
||||
} catch (error) {
|
||||
console.error('接诊失败:', error);
|
||||
} finally {
|
||||
registerOperating.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 拒诊操作
|
||||
const rejectRegister = async (registerId, orderNo) => {
|
||||
if (registerOperating.value) return;
|
||||
|
||||
registerOperating.value = true;
|
||||
|
||||
try {
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
|
||||
// 更新消息状态
|
||||
if (props.message.content && props.message.content.id === registerId) {
|
||||
props.message.content.status = 3; // 已取消
|
||||
}
|
||||
|
||||
// 显示成功提示
|
||||
console.log(`拒诊成功 - 挂号ID: ${registerId}, 订单号: ${orderNo}`);
|
||||
|
||||
// 这里可以调用实际的API
|
||||
// await rejectRegisterApi({ id: registerId, order_no: orderNo, reason: '医生拒诊' });
|
||||
|
||||
} catch (error) {
|
||||
console.error('拒诊失败:', error);
|
||||
} finally {
|
||||
registerOperating.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const bubbleClasses = computed(() => {
|
||||
const baseClasses = ['message-bubble'];
|
||||
|
||||
@@ -125,8 +197,6 @@ const handleVideoError = (event) => {
|
||||
console.error('视频加载失败:', event);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const [PrescriptionDetailModal, PrescriptionDetailModalApi] = useVbenModal({
|
||||
connectedComponent: PrescriptionDetail,
|
||||
});
|
||||
@@ -138,6 +208,24 @@ const viewPrescription = (item) => {
|
||||
PrescriptionDetailModalApi.open();
|
||||
}
|
||||
|
||||
// 格式化日期时间
|
||||
const formatDateTime = (timestamp) => {
|
||||
if (!timestamp) return '';
|
||||
const date = new Date(timestamp * 1000);
|
||||
return date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
};
|
||||
|
||||
// 获取性别文本
|
||||
const getSexText = (sex) => {
|
||||
return sex === 1 ? '男' : '女';
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -147,11 +235,6 @@ const viewPrescription = (item) => {
|
||||
>
|
||||
<PrescriptionDetailModal />
|
||||
<!-- 头像 -->
|
||||
<!-- <div-->
|
||||
<!-- :style="avatarStyle"-->
|
||||
<!-- class="w-10 h-10 rounded-full flex items-center justify-center text-white font-bold text-sm flex-shrink-0 cursor-pointer"-->
|
||||
<!-- @click="showUserProfile"-->
|
||||
<!-- >-->
|
||||
<div
|
||||
v-if="isSent"
|
||||
:style="avatarStyle"
|
||||
@@ -256,7 +339,132 @@ const viewPrescription = (item) => {
|
||||
:message="message"
|
||||
/>
|
||||
|
||||
<!-- 处方卡片消息 -->
|
||||
<!-- 挂号卡片消息 -->
|
||||
<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>
|
||||
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between">
|
||||
<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-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
|
||||
}"
|
||||
class="text-xs px-2 py-1 rounded-full 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="flex items-center gap-1">
|
||||
<i class="fas fa-hashtag text-xs"></i>
|
||||
<span class="truncate max-w-[120px]">{{ message.content.order_no }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-list-ol text-xs"></i>
|
||||
<span>第{{ message.content.order_number }}号</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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="{
|
||||
'bg-red-100 text-red-800': message.content.is_pay === 0,
|
||||
'bg-green-100 text-green-800': message.content.is_pay === 1
|
||||
}"
|
||||
class="text-xs px-2 py-1 rounded-full 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="flex items-center gap-1">
|
||||
<i class="fas fa-user text-xs"></i>
|
||||
<span>{{ message.content.user_patient?.name || '未知' }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-birthday-cake text-xs"></i>
|
||||
<span>{{ message.content.user_patient?.age || 0 }}岁</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-venus-mars text-xs"></i>
|
||||
<span>{{ getSexText(message.content.user_patient?.sex) }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<i class="fas fa-phone text-xs"></i>
|
||||
<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="text-sm font-medium text-gray-700 dark:text-gray-200">
|
||||
挂号费用: <span class="text-green-500 dark:text-green-400">¥{{ message.content.price }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 接诊/拒诊按钮 - 只在待就诊状态显示 -->
|
||||
<div v-if="message.content.status === 0" class="flex gap-2 mt-2">
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
:loading="registerOperating"
|
||||
@click="acceptRegister(message.content.id, message.content.order_no)"
|
||||
class="flex-1"
|
||||
>
|
||||
<i class="fas fa-check mr-1"></i>
|
||||
接诊
|
||||
</Button>
|
||||
<Button
|
||||
danger
|
||||
size="small"
|
||||
:loading="registerOperating"
|
||||
@click="rejectRegister(message.content.id, message.content.order_no)"
|
||||
class="flex-1"
|
||||
>
|
||||
<i class="fas fa-times mr-1"></i>
|
||||
拒诊
|
||||
</Button>
|
||||
</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>
|
||||
|
||||
<!-- 时间信息 -->
|
||||
<div class="mt-2 text-xs text-gray-500 dark:text-gray-400">
|
||||
创建时间: {{ message.content.created_at }}
|
||||
<span v-if="message.content.pay_time" class="ml-2">
|
||||
支付时间: {{ formatDateTime(message.content.pay_time) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 处方卡片消息 -->
|
||||
<div
|
||||
v-else-if="message.type === 'prescription'"
|
||||
@@ -282,7 +490,6 @@ const viewPrescription = (item) => {
|
||||
class="text-xs px-2 py-1 rounded-full font-medium"
|
||||
>
|
||||
{{ checkPrescriptionStatus(message.content.id) || statusInfo.text || '加载中' }}
|
||||
<!-- {{ statusInfo.text || '加载中' }}-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -315,7 +522,6 @@ const viewPrescription = (item) => {
|
||||
<!-- 通话消息 -->
|
||||
<div
|
||||
v-else-if="message.type === 'video-call' || message.type === 'voice-call'"
|
||||
"
|
||||
class="call-message"
|
||||
>
|
||||
<div class="call-info">
|
||||
@@ -622,6 +828,19 @@ v-else-if="message.type === 'video-call' || message.type === 'voice-call'"
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 挂号卡片样式 */
|
||||
.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;
|
||||
}
|
||||
|
||||
.message-bubble.sent .register-card {
|
||||
@apply bg-green-50/30 dark:bg-green-900/30 border-green-200/50 dark:border-green-700/70;
|
||||
}
|
||||
|
||||
.register-card:hover {
|
||||
@apply transform -translate-y-0.5;
|
||||
}
|
||||
|
||||
/* 处方卡片样式 - 使用TailwindCSS类替代 */
|
||||
.prescription-card {
|
||||
|
||||
@@ -262,8 +262,9 @@ const emit = defineEmits([
|
||||
// 开方功能触发函数
|
||||
const handleOpenPrescription = () => {
|
||||
// 获取当前会话的register_id,这里假设可以通过某种方式获取
|
||||
console.log(chatStore.currentFriend.register_id, 'sssssssssssssss')
|
||||
// 例如从聊天存储或props中获取
|
||||
const registerId = props.currentFriend?.register_id || 66;
|
||||
const registerId = chatStore.currentFriend?.register_id || 66;
|
||||
|
||||
if (registerId) {
|
||||
emit('openPrescription', registerId);
|
||||
|
||||
@@ -238,7 +238,7 @@ export const useChatStore = defineStore('chat', () => {
|
||||
id: message.id,
|
||||
type: getMessageType(message.message_type),
|
||||
content:
|
||||
message.message_type === 4
|
||||
message.message_type === 4 || message.message_type === 10
|
||||
? JSON.parse(message.message_content)
|
||||
: message.message_content,
|
||||
time: message.created_at_text,
|
||||
@@ -373,6 +373,8 @@ export const useChatStore = defineStore('chat', () => {
|
||||
'video-call',
|
||||
'audio-call',
|
||||
'file',
|
||||
'',
|
||||
'register',
|
||||
];
|
||||
return types[type] || 'text';
|
||||
};
|
||||
|
||||
@@ -36,3 +36,17 @@ export async function saveZSalePercentApi(z_sale_percent: number | string) {
|
||||
z_sale_percent,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 保存轮播图
|
||||
* @param data
|
||||
*/
|
||||
export async function saveNavUrlApi(data) {
|
||||
return requestClient.post<any>(`${prefix}upload-nav`, data);
|
||||
}
|
||||
/**
|
||||
* 删除轮播图
|
||||
* @param data
|
||||
*/
|
||||
export async function deleteNavApi(data) {
|
||||
return requestClient.post<any>(`${prefix}delete-nav`, data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { saveNavUrlApi } from '#/views/business/store/settings/api';
|
||||
|
||||
import { modalFormProps } from '../config/form';
|
||||
|
||||
const isUpdate = ref(false);
|
||||
const gridApi = ref();
|
||||
const getMyInfoApi = ref();
|
||||
|
||||
const [Form, formApi] = useVbenForm(modalFormProps);
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
fullscreenButton: false,
|
||||
draggable: true,
|
||||
onCancel() {
|
||||
modalApi.close();
|
||||
},
|
||||
onConfirm: async () => {
|
||||
formApi.validate().then(async (e: any) => {
|
||||
if (e.valid) {
|
||||
const values = await formApi.getValues();
|
||||
modalApi.setState({ loading: true, confirmLoading: true });
|
||||
const submitApi = saveNavUrlApi;
|
||||
submitApi(values)
|
||||
.then(() => {
|
||||
message.success('保存成功');
|
||||
gridApi.value?.reload();
|
||||
getMyInfoApi.value();
|
||||
modalApi.close();
|
||||
})
|
||||
.finally(() => {
|
||||
modalApi.setState({ loading: false, confirmLoading: false });
|
||||
});
|
||||
}
|
||||
});
|
||||
await formApi.validateAndSubmitForm();
|
||||
},
|
||||
onOpenChange(isOpen: boolean) {
|
||||
gridApi.value = isOpen ? modalApi.getData()?.gridApi : null;
|
||||
if (isOpen) {
|
||||
getMyInfoApi.value = isOpen ? modalApi.getData()?.getMyInfo : null;
|
||||
const { values, update } = modalApi.getData<Record<string, any>>();
|
||||
if (values) {
|
||||
isUpdate.value = update;
|
||||
formApi.setValues(values);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal
|
||||
:title="`${isUpdate === true ? '编辑' : '新增'}轮播图`"
|
||||
class="w-[30%]"
|
||||
>
|
||||
<Form />
|
||||
</Modal>
|
||||
</template>
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { VbenFormProps } from '#/adapter/form';
|
||||
|
||||
export const modalFormProps: VbenFormProps = {
|
||||
wrapperClass: 'grid-cols-12', // 24栅格,
|
||||
commonConfig: {
|
||||
formItemClass: 'col-span-12',
|
||||
// 所有表单项
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
},
|
||||
},
|
||||
// handleSubmit: onSubmit,
|
||||
layout: 'horizontal',
|
||||
schema: [
|
||||
{
|
||||
component: 'UploadImage',
|
||||
fieldName: 'url',
|
||||
label: '图片',
|
||||
rules: 'required',
|
||||
componentProps: {
|
||||
maxCount: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
showDefaultActions: false,
|
||||
};
|
||||
@@ -3,12 +3,14 @@ import { ref } from 'vue';
|
||||
|
||||
import { EllipsisText, Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { DeleteOutlined } from '@ant-design/icons-vue';
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
Image,
|
||||
InputNumber, message,
|
||||
InputNumber,
|
||||
message,
|
||||
notification,
|
||||
RadioButton,
|
||||
RadioGroup,
|
||||
@@ -19,14 +21,56 @@ import html2canvas from 'html2canvas';
|
||||
|
||||
import DoctorQrCodePreview from '#/components/modal/DoctorQrCodePreview.vue';
|
||||
import {
|
||||
deleteNavApi,
|
||||
getStoreInfoApi,
|
||||
saveZSalePercentApi,
|
||||
} from '#/views/business/store/settings/api';
|
||||
|
||||
import UploadModal from './components/uploadModal.vue';
|
||||
|
||||
// 定义类型
|
||||
interface TabBarItem {
|
||||
value: number;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface StoreInfo {
|
||||
name: string;
|
||||
star?: any;
|
||||
title: { name: string };
|
||||
contact: string;
|
||||
mobile: string;
|
||||
created_at: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
province: { name: string };
|
||||
city: { name: string };
|
||||
position: string;
|
||||
inquiry_count: number;
|
||||
doctor_count: number;
|
||||
inquiry_rate: string;
|
||||
z_sale_percent: number;
|
||||
qr_code: string;
|
||||
doctor_list: any[];
|
||||
nav: { id: number; pic: string }[];
|
||||
}
|
||||
|
||||
const [DoctorQrCodePreviewModal, DoctorQrCodePreviewModalApi] = useVbenModal({
|
||||
connectedComponent: DoctorQrCodePreview,
|
||||
});
|
||||
|
||||
const [UploadModals, UploadModalApi] = useVbenModal({
|
||||
connectedComponent: UploadModal,
|
||||
});
|
||||
|
||||
const openUpload = () => {
|
||||
UploadModalApi.setData({
|
||||
// doctorId,
|
||||
getMyInfo,
|
||||
});
|
||||
UploadModalApi.open();
|
||||
};
|
||||
|
||||
const openDoctorQrCode = (doctorId: number, isNotQr = false) => {
|
||||
if (isNotQr) return message.error('该医生暂时没有二维码!');
|
||||
DoctorQrCodePreviewModalApi.setData({
|
||||
@@ -37,41 +81,33 @@ const openDoctorQrCode = (doctorId: number, isNotQr = false) => {
|
||||
DoctorQrCodePreviewModalApi.open();
|
||||
};
|
||||
|
||||
// 映射数据(示例)
|
||||
// 映射数据
|
||||
const activeTabBar = ref(1);
|
||||
const tabBar = [
|
||||
{
|
||||
value: 1,
|
||||
label: '诊所资料',
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '商品价格',
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: '诊所二维码',
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
label: '我的医生团队',
|
||||
},
|
||||
const tabBar: TabBarItem[] = [
|
||||
{ value: 1, label: '诊所资料' },
|
||||
{ value: 2, label: '商品价格' },
|
||||
{ value: 3, label: '诊所二维码' },
|
||||
{ value: 4, label: '我的医生团队' },
|
||||
{ value: 5, label: '轮播图' },
|
||||
];
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateString) => {
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleDateString();
|
||||
};
|
||||
const data = ref();
|
||||
|
||||
const data = ref<null | StoreInfo>(null);
|
||||
|
||||
/**
|
||||
* 获取当前登录诊所信息
|
||||
*/
|
||||
const getMyInfo = () => {
|
||||
getStoreInfoApi({}).then((res) => {
|
||||
data.value = res;
|
||||
getStoreInfoApi({}).then((res: any) => {
|
||||
data.value = res as StoreInfo;
|
||||
});
|
||||
};
|
||||
getMyInfo();
|
||||
|
||||
/**
|
||||
* 医嘱列表
|
||||
*/
|
||||
@@ -87,8 +123,8 @@ const tabBarChange = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const qrCodeUrl = ref('');
|
||||
const htmlToImage = ref('');
|
||||
const qrCodeUrl = ref<HTMLElement | null>(null);
|
||||
const htmlToImage = ref<HTMLElement | null>(null);
|
||||
|
||||
/**
|
||||
* 下载二维码
|
||||
@@ -96,23 +132,28 @@ const htmlToImage = ref('');
|
||||
* @param isQr
|
||||
*/
|
||||
const downloadQRCode = async (name: string, isQr = false) => {
|
||||
if (!data.value) return;
|
||||
|
||||
const element = isQr ? qrCodeUrl.value : htmlToImage.value;
|
||||
if (!element) return;
|
||||
|
||||
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', `${data.value.name}${name}.png`); // 利用了a标签的download 来下载 canvas图片
|
||||
link.style.display = 'none'; // 将图片隐藏起来
|
||||
document.body.append(link); // 插入到其中
|
||||
const link = document.createElement('a');
|
||||
link.href = canvas.toDataURL();
|
||||
link.setAttribute('download', `${data.value!.name}${name}.png`);
|
||||
link.style.display = 'none';
|
||||
document.body.append(link);
|
||||
link.click();
|
||||
});
|
||||
};
|
||||
|
||||
const saveZSalePercent = () => {
|
||||
if (!data.value) return;
|
||||
|
||||
saveZSalePercentApi(data.value.z_sale_percent).then(() => {
|
||||
notification.success({
|
||||
message: '任务开始执行',
|
||||
@@ -120,11 +161,27 @@ const saveZSalePercent = () => {
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 删除轮播图项
|
||||
const deleteNavItem = (id: number) => {
|
||||
if (data.value) {
|
||||
deleteNavApi({
|
||||
id,
|
||||
}).then(() => {
|
||||
notification.success({
|
||||
message: '删除成功',
|
||||
duration: 2,
|
||||
});
|
||||
getMyInfo();
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page v-if="data" :title="`${data.name}的配置中心`" auto-content-height>
|
||||
<DoctorQrCodePreviewModal />
|
||||
<UploadModals />
|
||||
<div class="pb-2">
|
||||
<RadioGroup
|
||||
v-model:value="activeTabBar"
|
||||
@@ -287,10 +344,7 @@ const saveZSalePercent = () => {
|
||||
<div
|
||||
class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
<Card
|
||||
v-for="(doctor, index) in data.doctor_list"
|
||||
:key="index"
|
||||
>
|
||||
<Card v-for="(doctor, index) in data.doctor_list" :key="index">
|
||||
<!-- 医生头像和信息 -->
|
||||
<div class="mb-4 flex items-center">
|
||||
<Avatar
|
||||
@@ -340,7 +394,8 @@ const saveZSalePercent = () => {
|
||||
</div>
|
||||
|
||||
<!-- 二维码 -->
|
||||
<div class="border-t pt-4"
|
||||
<div
|
||||
class="border-t pt-4"
|
||||
@click="openDoctorQrCode(doctor.doctor.su_id, !doctor.qr_code)"
|
||||
>
|
||||
<p class="mb-2 text-sm text-gray-600">联系二维码:</p>
|
||||
@@ -385,6 +440,42 @@ const saveZSalePercent = () => {
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
<Card v-else-if="activeTabBar === 5" title="轮播图">
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<span>最多可添加5张轮播图</span>
|
||||
<Button v-if="data.nav.length < 5" type="primary" @click="openUpload">
|
||||
上传新图片
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap gap-4">
|
||||
<Card
|
||||
v-for="(item, index) in data.nav"
|
||||
:key="item.id"
|
||||
class="relative"
|
||||
style="width: 240px"
|
||||
>
|
||||
<div class="group relative">
|
||||
<Image :src="item.pic" class="h-40 w-full rounded object-cover" />
|
||||
<div
|
||||
class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 opacity-0 transition-opacity group-hover:opacity-100"
|
||||
>
|
||||
<Button
|
||||
class="shadow-lg"
|
||||
danger
|
||||
shape="circle"
|
||||
size="large"
|
||||
type="primary"
|
||||
@click.stop="deleteNavItem(item.id)"
|
||||
>
|
||||
<DeleteOutlined />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 text-center text-sm text-gray-500">点击图片删除</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
</Page>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@@ -438,4 +529,13 @@ const saveZSalePercent = () => {
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 轮播图卡片样式 */
|
||||
.card-wrapper {
|
||||
transition: all 0.3s ease;
|
||||
&:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -86,3 +86,11 @@ export async function importWarehouseDrugManagementStoreApi(data: Record<string,
|
||||
export async function importUpdatePriceApi(data: Record<string, any>) {
|
||||
return requestClient.upload(`${prefix}import-update-price`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步总仓库api
|
||||
* @param data
|
||||
*/
|
||||
export async function syncDrugApi(data: Record<string, any>) {
|
||||
return requestClient.get(`${prefix}sync-drug`, data);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { downloadByData } from '#/util/tool';
|
||||
|
||||
import {
|
||||
deleteWarehouseDrugManagementStore,
|
||||
exportWarehouseDrugManagementStoreApi,
|
||||
exportWarehouseDrugManagementStoreApi, syncDrugApi,
|
||||
updateWarehouseDrugManagementStoreStatusApi
|
||||
} from './api';
|
||||
import FormModalDemo from './components/modal.vue';
|
||||
@@ -93,6 +93,13 @@ const openExcelUploadModal = (type = 1) => {
|
||||
ExcelUploadModalApi.open();
|
||||
};
|
||||
|
||||
const syncDrugs = () => {
|
||||
syncDrugApi().then((res) => {
|
||||
message.success('同步成功!');
|
||||
gridApi.reload();
|
||||
})
|
||||
};
|
||||
|
||||
const updateStatus = (id) => {
|
||||
updateWarehouseDrugManagementStoreStatusApi(id).then(() => {
|
||||
message.success('修改成功!');
|
||||
@@ -116,6 +123,13 @@ const updateStatus = (id) => {
|
||||
// auth: ['超级西(中成)药', 'sys:user:save'],
|
||||
onClick: openExcelUploadModal.bind(null, 2),
|
||||
},
|
||||
{
|
||||
label: '更新总仓库商品(只更新未同步的商品)',
|
||||
type: 'primary',
|
||||
icon: 'ix:export-check',
|
||||
// auth: ['超级西(中成)药', 'sys:user:save'],
|
||||
onClick: syncDrugs,
|
||||
},
|
||||
]"
|
||||
:drop-down-actions="[
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { VbenFormProps } from '#/adapter/form';
|
||||
|
||||
import { addressOption } from '#/util/address.ts';
|
||||
|
||||
export const modalFormProps: VbenFormProps = {
|
||||
@@ -214,7 +215,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
hideLabel: true,
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
@@ -234,7 +235,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
@@ -250,7 +251,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
@@ -266,7 +267,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
@@ -282,7 +283,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
@@ -301,7 +302,7 @@ export const modalFormProps: VbenFormProps = {
|
||||
},
|
||||
dependencies: {
|
||||
show: (values) => {
|
||||
return values.id === null;
|
||||
return values.id == null;
|
||||
},
|
||||
triggerFields: ['id'],
|
||||
},
|
||||
|
||||
503
pnpm-lock.yaml
generated
503
pnpm-lock.yaml
generated
@@ -12,387 +12,51 @@ catalogs:
|
||||
'@changesets/cli':
|
||||
specifier: ^2.27.11
|
||||
version: 2.27.11
|
||||
'@changesets/git':
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2
|
||||
'@clack/prompts':
|
||||
specifier: ^0.9.0
|
||||
version: 0.9.0
|
||||
'@commitlint/cli':
|
||||
specifier: ^19.6.1
|
||||
version: 19.6.1
|
||||
'@commitlint/config-conventional':
|
||||
specifier: ^19.6.0
|
||||
version: 19.6.0
|
||||
'@eslint/js':
|
||||
specifier: ^9.17.0
|
||||
version: 9.17.0
|
||||
'@iconify/json':
|
||||
specifier: ^2.2.286
|
||||
version: 2.2.286
|
||||
'@iconify/tailwind':
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0
|
||||
'@iconify/vue':
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
'@intlify/core-base':
|
||||
specifier: ^10.0.5
|
||||
version: 10.0.5
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
'@jspm/generator':
|
||||
specifier: ^2.4.1
|
||||
version: 2.4.1
|
||||
'@manypkg/get-packages':
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@playwright/test':
|
||||
specifier: ^1.49.1
|
||||
version: 1.49.1
|
||||
'@pnpm/workspace.read-manifest':
|
||||
specifier: ^1000.0.1
|
||||
version: 1000.0.1
|
||||
'@stylistic/stylelint-plugin':
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1
|
||||
'@tailwindcss/nesting':
|
||||
specifier: 0.0.0-insiders.565cd3e
|
||||
version: 0.0.0-insiders.565cd3e
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.15
|
||||
version: 0.5.15
|
||||
'@tanstack/vue-query':
|
||||
specifier: ^5.62.8
|
||||
version: 5.62.8
|
||||
'@tanstack/vue-store':
|
||||
specifier: ^0.6.0
|
||||
version: 0.6.0
|
||||
'@types/archiver':
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
'@types/eslint':
|
||||
specifier: ^9.6.1
|
||||
version: 9.6.1
|
||||
'@types/html-minifier-terser':
|
||||
specifier: ^7.0.2
|
||||
version: 7.0.2
|
||||
'@types/lodash.clonedeep':
|
||||
specifier: ^4.5.9
|
||||
version: 4.5.9
|
||||
'@types/lodash.get':
|
||||
specifier: ^4.4.9
|
||||
version: 4.4.9
|
||||
'@types/lodash.isequal':
|
||||
specifier: ^4.5.8
|
||||
version: 4.5.8
|
||||
'@types/node':
|
||||
specifier: ^22.10.2
|
||||
version: 22.10.2
|
||||
'@types/nprogress':
|
||||
specifier: ^0.2.3
|
||||
version: 0.2.3
|
||||
'@types/postcss-import':
|
||||
specifier: ^14.0.3
|
||||
version: 14.0.3
|
||||
'@types/qrcode':
|
||||
specifier: ^1.5.5
|
||||
version: 1.5.5
|
||||
'@types/sortablejs':
|
||||
specifier: ^1.15.8
|
||||
version: 1.15.8
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^8.18.1
|
||||
version: 8.18.1
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^8.18.1
|
||||
version: 8.18.1
|
||||
'@vee-validate/zod':
|
||||
specifier: ^4.14.7
|
||||
version: 4.14.7
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
'@vitejs/plugin-vue-jsx':
|
||||
specifier: ^4.1.1
|
||||
version: 4.1.1
|
||||
'@vue/shared':
|
||||
specifier: ^3.5.13
|
||||
version: 3.5.13
|
||||
'@vue/test-utils':
|
||||
specifier: ^2.4.6
|
||||
version: 2.4.6
|
||||
'@vueuse/core':
|
||||
specifier: ^12.0.0
|
||||
version: 12.0.0
|
||||
'@vueuse/integrations':
|
||||
specifier: ^12.0.0
|
||||
version: 12.0.0
|
||||
ant-design-vue:
|
||||
specifier: ^4.2.6
|
||||
version: 4.2.6
|
||||
archiver:
|
||||
specifier: ^7.0.1
|
||||
version: 7.0.1
|
||||
autoprefixer:
|
||||
specifier: ^10.4.20
|
||||
version: 10.4.20
|
||||
axios:
|
||||
specifier: ^1.7.9
|
||||
version: 1.7.9
|
||||
axios-mock-adapter:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
cac:
|
||||
specifier: ^6.7.14
|
||||
version: 6.7.14
|
||||
chalk:
|
||||
specifier: ^5.4.0
|
||||
version: 5.4.0
|
||||
cheerio:
|
||||
specifier: 1.0.0
|
||||
version: 1.0.0
|
||||
circular-dependency-scanner:
|
||||
specifier: ^2.3.0
|
||||
version: 2.3.0
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
commitlint-plugin-function-rules:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
consola:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
cross-env:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
cspell:
|
||||
specifier: ^8.17.1
|
||||
version: 8.17.1
|
||||
cssnano:
|
||||
specifier: ^7.0.6
|
||||
version: 7.0.6
|
||||
cz-git:
|
||||
specifier: ^1.11.0
|
||||
version: 1.11.0
|
||||
czg:
|
||||
specifier: ^1.11.0
|
||||
version: 1.11.0
|
||||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
defu:
|
||||
specifier: ^6.1.4
|
||||
version: 6.1.4
|
||||
depcheck:
|
||||
specifier: ^1.4.7
|
||||
version: 1.4.7
|
||||
dotenv:
|
||||
specifier: ^16.4.7
|
||||
version: 16.4.7
|
||||
echarts:
|
||||
specifier: ^5.5.1
|
||||
version: 5.5.1
|
||||
eslint:
|
||||
specifier: ^9.17.0
|
||||
version: 9.17.0
|
||||
eslint-config-turbo:
|
||||
specifier: ^2.3.3
|
||||
version: 2.3.3
|
||||
eslint-plugin-command:
|
||||
specifier: ^0.2.7
|
||||
version: 0.2.7
|
||||
eslint-plugin-eslint-comments:
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0
|
||||
eslint-plugin-import-x:
|
||||
specifier: ^4.6.1
|
||||
version: 4.6.1
|
||||
eslint-plugin-jsdoc:
|
||||
specifier: ^50.6.1
|
||||
version: 50.6.1
|
||||
eslint-plugin-jsonc:
|
||||
specifier: ^2.18.2
|
||||
version: 2.18.2
|
||||
eslint-plugin-n:
|
||||
specifier: ^17.15.1
|
||||
version: 17.15.1
|
||||
eslint-plugin-no-only-tests:
|
||||
specifier: ^3.3.0
|
||||
version: 3.3.0
|
||||
eslint-plugin-perfectionist:
|
||||
specifier: ^3.9.1
|
||||
version: 3.9.1
|
||||
eslint-plugin-prettier:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
eslint-plugin-regexp:
|
||||
specifier: ^2.7.0
|
||||
version: 2.7.0
|
||||
eslint-plugin-unicorn:
|
||||
specifier: ^56.0.1
|
||||
version: 56.0.1
|
||||
eslint-plugin-unused-imports:
|
||||
specifier: ^4.1.4
|
||||
version: 4.1.4
|
||||
eslint-plugin-vitest:
|
||||
specifier: ^0.5.4
|
||||
version: 0.5.4
|
||||
eslint-plugin-vue:
|
||||
specifier: ^9.32.0
|
||||
version: 9.32.0
|
||||
execa:
|
||||
specifier: ^9.5.2
|
||||
version: 9.5.2
|
||||
find-up:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0
|
||||
get-port:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
globals:
|
||||
specifier: ^15.14.0
|
||||
version: 15.14.0
|
||||
happy-dom:
|
||||
specifier: ^15.11.7
|
||||
version: 15.11.7
|
||||
html-minifier-terser:
|
||||
specifier: ^7.2.0
|
||||
version: 7.2.0
|
||||
husky:
|
||||
specifier: ^9.1.7
|
||||
version: 9.1.7
|
||||
is-ci:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
jsonc-eslint-parser:
|
||||
specifier: ^2.4.0
|
||||
version: 2.4.0
|
||||
lint-staged:
|
||||
specifier: ^15.2.11
|
||||
version: 15.2.11
|
||||
lodash.clonedeep:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0
|
||||
lodash.get:
|
||||
specifier: ^4.4.2
|
||||
version: 4.4.2
|
||||
lodash.isequal:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0
|
||||
lucide-vue-next:
|
||||
specifier: ^0.469.0
|
||||
version: 0.469.0
|
||||
nitropack:
|
||||
specifier: ^2.10.4
|
||||
version: 2.10.4
|
||||
nprogress:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
ora:
|
||||
specifier: ^8.1.1
|
||||
version: 8.1.1
|
||||
pinia-plugin-persistedstate:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
pkg-types:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
playwright:
|
||||
specifier: ^1.49.1
|
||||
version: 1.49.1
|
||||
postcss:
|
||||
specifier: ^8.4.49
|
||||
version: 8.4.49
|
||||
postcss-antd-fixes:
|
||||
specifier: ^0.2.0
|
||||
version: 0.2.0
|
||||
postcss-html:
|
||||
specifier: ^1.7.0
|
||||
version: 1.7.0
|
||||
postcss-import:
|
||||
specifier: ^16.1.0
|
||||
version: 16.1.0
|
||||
postcss-preset-env:
|
||||
specifier: ^10.1.2
|
||||
version: 10.1.2
|
||||
postcss-scss:
|
||||
specifier: ^4.0.9
|
||||
version: 4.0.9
|
||||
prettier:
|
||||
specifier: ^3.4.2
|
||||
version: 3.4.2
|
||||
prettier-plugin-tailwindcss:
|
||||
specifier: ^0.6.9
|
||||
version: 0.6.9
|
||||
publint:
|
||||
specifier: ^0.2.12
|
||||
version: 0.2.12
|
||||
qrcode:
|
||||
specifier: ^1.5.4
|
||||
version: 1.5.4
|
||||
radix-vue:
|
||||
specifier: ^1.9.11
|
||||
version: 1.9.11
|
||||
resolve.exports:
|
||||
specifier: ^2.0.3
|
||||
version: 2.0.3
|
||||
rimraf:
|
||||
specifier: ^6.0.1
|
||||
version: 6.0.1
|
||||
rollup:
|
||||
specifier: ^4.28.1
|
||||
version: 4.28.1
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^5.12.0
|
||||
version: 5.12.0
|
||||
sass:
|
||||
specifier: 1.80.6
|
||||
version: 1.80.6
|
||||
sortablejs:
|
||||
specifier: ^1.15.6
|
||||
version: 1.15.6
|
||||
stylelint:
|
||||
specifier: ^16.12.0
|
||||
version: 16.12.0
|
||||
stylelint-config-recess-order:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
stylelint-config-recommended:
|
||||
specifier: ^14.0.1
|
||||
version: 14.0.1
|
||||
stylelint-config-recommended-scss:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
stylelint-config-recommended-vue:
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0
|
||||
stylelint-config-standard:
|
||||
specifier: ^36.0.1
|
||||
version: 36.0.1
|
||||
stylelint-order:
|
||||
specifier: ^6.0.4
|
||||
version: 6.0.4
|
||||
stylelint-prettier:
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
stylelint-scss:
|
||||
specifier: ^6.10.0
|
||||
version: 6.10.0
|
||||
tailwind-merge:
|
||||
specifier: ^2.5.5
|
||||
version: 2.5.5
|
||||
tailwindcss:
|
||||
specifier: ^3.4.17
|
||||
version: 3.4.17
|
||||
tailwindcss-animate:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7
|
||||
theme-colors:
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0
|
||||
turbo:
|
||||
specifier: ^2.3.3
|
||||
version: 2.3.3
|
||||
@@ -402,60 +66,15 @@ catalogs:
|
||||
unbuild:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
vee-validate:
|
||||
specifier: ^4.14.7
|
||||
version: 4.14.7
|
||||
vite:
|
||||
specifier: ^6.0.5
|
||||
version: 6.0.5
|
||||
vite-plugin-compression:
|
||||
specifier: ^0.5.1
|
||||
version: 0.5.1
|
||||
vite-plugin-dts:
|
||||
specifier: 4.2.1
|
||||
version: 4.2.1
|
||||
vite-plugin-html:
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.2
|
||||
vite-plugin-lazy-import:
|
||||
specifier: ^1.0.7
|
||||
version: 1.0.7
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.21.1
|
||||
version: 0.21.1
|
||||
vite-plugin-vue-devtools:
|
||||
specifier: ^7.6.8
|
||||
version: 7.6.8
|
||||
vitest:
|
||||
specifier: ^2.1.8
|
||||
version: 2.1.8
|
||||
vue-eslint-parser:
|
||||
specifier: ^9.4.3
|
||||
version: 9.4.3
|
||||
vue-i18n:
|
||||
specifier: ^10.0.5
|
||||
version: 10.0.5
|
||||
vue-router:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0
|
||||
vue-tsc:
|
||||
specifier: ^2.1.10
|
||||
version: 2.1.10
|
||||
vxe-pc-ui:
|
||||
specifier: ^4.3.40
|
||||
version: 4.3.40
|
||||
vxe-table:
|
||||
specifier: ^4.9.33
|
||||
version: 4.9.33
|
||||
watermark-js-plus:
|
||||
specifier: ^1.5.7
|
||||
version: 1.5.7
|
||||
zod:
|
||||
specifier: ^3.24.1
|
||||
version: 3.24.1
|
||||
zod-defaults:
|
||||
specifier: ^0.1.3
|
||||
version: 0.1.3
|
||||
|
||||
overrides:
|
||||
'@ast-grep/napi': ^0.31.1
|
||||
@@ -583,10 +202,10 @@ importers:
|
||||
version: 3.0.1(typescript@5.6.3)(vue-tsc@2.1.10(typescript@5.6.3))(vue@3.5.13(typescript@5.6.3))
|
||||
vite:
|
||||
specifier: 'catalog:'
|
||||
version: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)(yaml@2.6.1)
|
||||
version: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(terser@5.37.0)(yaml@2.6.1)
|
||||
vitest:
|
||||
specifier: 'catalog:'
|
||||
version: 2.1.8(@types/node@22.10.2)(happy-dom@15.11.7)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)
|
||||
version: 2.1.8(@types/node@22.10.2)(happy-dom@15.11.7)(less@4.2.1)(terser@5.37.0)
|
||||
vue:
|
||||
specifier: ^3.5.13
|
||||
version: 3.5.13(typescript@5.6.3)
|
||||
@@ -3266,8 +2885,8 @@ packages:
|
||||
resolution: {integrity: sha512-bmsP4L2HqBF6i6uaMqJMcFBONVjKt+siGluRq4Ca4C0q7W2eMaVZr8iCgF9dKbcVXutftkC7D6z2SaSMmLiDyA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@11.1.10':
|
||||
resolution: {integrity: sha512-6ZW/f3Zzjxfa1Wh0tYQI5pLKUtU+SY7l70pEG+0yd0zjcsYcK0EBt6Fz30Dy0tZhEqemziQQy2aNU3GJzyrMUA==}
|
||||
'@intlify/shared@11.1.11':
|
||||
resolution: {integrity: sha512-RIBFTIqxZSsxUqlcyoR7iiC632bq7kkOwYvZlvcVObHfrF4NhuKc4FKvu8iPCrEO+e3XsY7/UVpfgzg+M7ETzA==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@12.0.0-alpha.3':
|
||||
@@ -9899,7 +9518,7 @@ snapshots:
|
||||
'@babel/traverse': 7.26.4
|
||||
'@babel/types': 7.26.3
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.4.0(supports-color@9.4.0)
|
||||
debug: 4.4.0
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.3
|
||||
semver: 6.3.1
|
||||
@@ -10560,7 +10179,7 @@ snapshots:
|
||||
'@babel/parser': 7.26.3
|
||||
'@babel/template': 7.25.9
|
||||
'@babel/types': 7.26.3
|
||||
debug: 4.4.0(supports-color@9.4.0)
|
||||
debug: 4.4.0
|
||||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -11768,7 +11387,7 @@ snapshots:
|
||||
|
||||
'@intlify/shared@10.0.5': {}
|
||||
|
||||
'@intlify/shared@11.1.10': {}
|
||||
'@intlify/shared@11.1.11': {}
|
||||
|
||||
'@intlify/shared@12.0.0-alpha.3': {}
|
||||
|
||||
@@ -11776,8 +11395,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@2.4.2))
|
||||
'@intlify/bundle-utils': 10.0.0(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))
|
||||
'@intlify/shared': 11.1.10
|
||||
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.1.10)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||
'@intlify/shared': 11.1.11
|
||||
'@intlify/vue-i18n-extensions': 7.0.0(@intlify/shared@11.1.11)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))
|
||||
'@rollup/pluginutils': 5.1.4(rollup@4.28.1)
|
||||
'@typescript-eslint/scope-manager': 8.18.1
|
||||
'@typescript-eslint/typescript-estree': 8.18.1(typescript@5.7.2)
|
||||
@@ -11799,11 +11418,11 @@ snapshots:
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.1.10)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||
'@intlify/vue-i18n-extensions@7.0.0(@intlify/shared@11.1.11)(@vue/compiler-dom@3.5.13)(vue-i18n@10.0.5(vue@3.5.13(typescript@5.7.2)))(vue@3.5.13(typescript@5.7.2))':
|
||||
dependencies:
|
||||
'@babel/parser': 7.26.3
|
||||
optionalDependencies:
|
||||
'@intlify/shared': 11.1.10
|
||||
'@intlify/shared': 11.1.11
|
||||
'@vue/compiler-dom': 3.5.13
|
||||
vue: 3.5.13(typescript@5.7.2)
|
||||
vue-i18n: 10.0.5(vue@3.5.13(typescript@5.7.2))
|
||||
@@ -12787,7 +12406,7 @@ snapshots:
|
||||
'@babel/core': 7.26.0
|
||||
'@babel/plugin-transform-typescript': 7.26.3(@babel/core@7.26.0)
|
||||
'@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0)
|
||||
vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)(yaml@2.6.1)
|
||||
vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(terser@5.37.0)(yaml@2.6.1)
|
||||
vue: 3.5.13(typescript@5.6.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -12799,7 +12418,7 @@ snapshots:
|
||||
|
||||
'@vitejs/plugin-vue@5.2.1(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(terser@5.37.0)(yaml@2.6.1))(vue@3.5.13(typescript@5.6.3))':
|
||||
dependencies:
|
||||
vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)(yaml@2.6.1)
|
||||
vite: 6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(terser@5.37.0)(yaml@2.6.1)
|
||||
vue: 3.5.13(typescript@5.6.3)
|
||||
|
||||
'@vitest/expect@2.1.8':
|
||||
@@ -12816,6 +12435,15 @@ snapshots:
|
||||
magic-string: 0.30.17
|
||||
optionalDependencies:
|
||||
vite: 5.4.11(@types/node@22.10.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)
|
||||
optional: true
|
||||
|
||||
'@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0))':
|
||||
dependencies:
|
||||
'@vitest/spy': 2.1.8
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.17
|
||||
optionalDependencies:
|
||||
vite: 5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0)
|
||||
|
||||
'@vitest/pretty-format@2.1.8':
|
||||
dependencies:
|
||||
@@ -14089,6 +13717,10 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@4.4.0:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
debug@4.4.0(supports-color@9.4.0):
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
@@ -15766,7 +15398,7 @@ snapshots:
|
||||
dependencies:
|
||||
chalk: 5.3.0
|
||||
commander: 12.1.0
|
||||
debug: 4.4.0(supports-color@9.4.0)
|
||||
debug: 4.4.0
|
||||
execa: 8.0.1
|
||||
lilconfig: 3.1.3
|
||||
listr2: 8.2.5
|
||||
@@ -18515,6 +18147,25 @@ snapshots:
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
optional: true
|
||||
|
||||
vite-node@2.1.8(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.0
|
||||
es-module-lexer: 1.5.4
|
||||
pathe: 1.1.2
|
||||
vite: 5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
- lightningcss
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vite-plugin-compression@0.5.1(vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)(yaml@2.6.1)):
|
||||
dependencies:
|
||||
@@ -18636,6 +18287,18 @@ snapshots:
|
||||
less: 4.2.1
|
||||
sass: 1.80.6
|
||||
terser: 5.37.0
|
||||
optional: true
|
||||
|
||||
vite@5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0):
|
||||
dependencies:
|
||||
esbuild: 0.24.0
|
||||
postcss: 8.4.49
|
||||
rollup: 4.28.1
|
||||
optionalDependencies:
|
||||
'@types/node': 22.10.2
|
||||
fsevents: 2.3.3
|
||||
less: 4.2.1
|
||||
terser: 5.37.0
|
||||
|
||||
vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(sass@1.80.6)(terser@5.37.0)(yaml@2.6.1):
|
||||
dependencies:
|
||||
@@ -18651,6 +18314,19 @@ snapshots:
|
||||
terser: 5.37.0
|
||||
yaml: 2.6.1
|
||||
|
||||
vite@6.0.5(@types/node@22.10.2)(jiti@2.4.2)(less@4.2.1)(terser@5.37.0)(yaml@2.6.1):
|
||||
dependencies:
|
||||
esbuild: 0.24.0
|
||||
postcss: 8.4.49
|
||||
rollup: 4.28.1
|
||||
optionalDependencies:
|
||||
'@types/node': 22.10.2
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.4.2
|
||||
less: 4.2.1
|
||||
terser: 5.37.0
|
||||
yaml: 2.6.1
|
||||
|
||||
vitest@2.1.8(@types/node@22.10.2)(happy-dom@15.11.7)(less@4.2.1)(sass@1.80.6)(terser@5.37.0):
|
||||
dependencies:
|
||||
'@vitest/expect': 2.1.8
|
||||
@@ -18686,6 +18362,43 @@ snapshots:
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
optional: true
|
||||
|
||||
vitest@2.1.8(@types/node@22.10.2)(happy-dom@15.11.7)(less@4.2.1)(terser@5.37.0):
|
||||
dependencies:
|
||||
'@vitest/expect': 2.1.8
|
||||
'@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0))
|
||||
'@vitest/pretty-format': 2.1.8
|
||||
'@vitest/runner': 2.1.8
|
||||
'@vitest/snapshot': 2.1.8
|
||||
'@vitest/spy': 2.1.8
|
||||
'@vitest/utils': 2.1.8
|
||||
chai: 5.1.2
|
||||
debug: 4.4.0
|
||||
expect-type: 1.1.0
|
||||
magic-string: 0.30.17
|
||||
pathe: 1.1.2
|
||||
std-env: 3.8.0
|
||||
tinybench: 2.9.0
|
||||
tinyexec: 0.3.1
|
||||
tinypool: 1.0.2
|
||||
tinyrainbow: 1.2.0
|
||||
vite: 5.4.11(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0)
|
||||
vite-node: 2.1.8(@types/node@22.10.2)(less@4.2.1)(terser@5.37.0)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
'@types/node': 22.10.2
|
||||
happy-dom: 15.11.7
|
||||
transitivePeerDependencies:
|
||||
- less
|
||||
- lightningcss
|
||||
- msw
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
|
||||
vscode-languageserver-textdocument@1.0.12: {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user