fix:合并冲突
commit
51bfeed463
|
|
@ -75,7 +75,7 @@ defineExpose({
|
|||
<div class="inline-block text-center" :style="getStyle">
|
||||
<!-- 图片包装器 -->
|
||||
<div
|
||||
class="bg-card group relative cursor-pointer overflow-hidden rounded-full border border-gray-200"
|
||||
class="group relative cursor-pointer overflow-hidden rounded-full border border-gray-200 bg-card"
|
||||
:style="getImageWrapperStyle"
|
||||
@click="openModal"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -302,9 +302,9 @@ function getValue() {
|
|||
class="mt-2 flex flex-wrap items-center"
|
||||
>
|
||||
请上传不超过
|
||||
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
|
||||
<div class="mx-1 font-bold text-primary">{{ maxSize }}MB</div>
|
||||
的
|
||||
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
|
||||
<div class="mx-1 font-bold text-primary">{{ accept.join('/') }}</div>
|
||||
格式文件
|
||||
</div>
|
||||
</Upload>
|
||||
|
|
|
|||
|
|
@ -312,9 +312,9 @@ function getValue() {
|
|||
class="mt-2 flex flex-wrap items-center text-sm"
|
||||
>
|
||||
请上传不超过
|
||||
<div class="text-primary mx-1 font-bold">{{ maxSize }}MB</div>
|
||||
<div class="mx-1 font-bold text-primary">{{ maxSize }}MB</div>
|
||||
的
|
||||
<div class="text-primary mx-1 font-bold">{{ accept.join('/') }}</div>
|
||||
<div class="mx-1 font-bold text-primary">{{ accept.join('/') }}</div>
|
||||
格式文件
|
||||
</div>
|
||||
<Modal
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"register": "Register",
|
||||
"codeLogin": "Code Login",
|
||||
"qrcodeLogin": "Qr Code Login",
|
||||
"forgetPassword": "Forget Password"
|
||||
"forgetPassword": "Forget Password",
|
||||
"profile": "Profile"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"register": "注册",
|
||||
"codeLogin": "验证码登录",
|
||||
"qrcodeLogin": "二维码登录",
|
||||
"forgetPassword": "忘记密码"
|
||||
"forgetPassword": "忘记密码",
|
||||
"profile": "个人中心"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "概览",
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export const useMallKefuStore = defineStore('mall-kefu', {
|
|||
},
|
||||
conversationSort() {
|
||||
// 按置顶属性和最后消息时间排序
|
||||
this.conversationList.sort((a, b) => {
|
||||
this.conversationList.toSorted((a, b) => {
|
||||
// 按照置顶排序,置顶的会在前面
|
||||
if (a.adminPinned !== b.adminPinned) {
|
||||
return a.adminPinned ? -1 : 1;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
<script setup lang="ts">
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { SystemUserProfileApi } from '#/api/system/user/profile';
|
||||
|
||||
import { computed, ref, watch } from 'vue';
|
||||
|
||||
import { ProfileBaseSetting, z } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { updateUserProfile } from '#/api/system/user/profile';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const props = defineProps<{
|
||||
profile?: SystemUserProfileApi.UserProfileRespVO;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'success'): void;
|
||||
}>();
|
||||
|
||||
const profileBaseSettingRef = ref();
|
||||
|
||||
const formSchema = computed((): VbenFormSchema[] => {
|
||||
return [
|
||||
{
|
||||
label: '用户昵称',
|
||||
fieldName: 'nickname',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户昵称',
|
||||
},
|
||||
rules: 'required',
|
||||
},
|
||||
{
|
||||
label: '用户手机',
|
||||
fieldName: 'mobile',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户手机',
|
||||
},
|
||||
rules: z.string(),
|
||||
},
|
||||
{
|
||||
label: '用户邮箱',
|
||||
fieldName: 'email',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入用户邮箱',
|
||||
},
|
||||
rules: z.string().email('请输入正确的邮箱'),
|
||||
},
|
||||
{
|
||||
label: '用户性别',
|
||||
fieldName: 'sex',
|
||||
component: 'RadioGroup',
|
||||
componentProps: {
|
||||
options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'),
|
||||
buttonStyle: 'solid',
|
||||
optionType: 'button',
|
||||
},
|
||||
rules: z.number(),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
async function handleSubmit(values: Recordable<any>) {
|
||||
try {
|
||||
profileBaseSettingRef.value.getFormApi().setLoading(true);
|
||||
// 提交表单
|
||||
await updateUserProfile(values as SystemUserProfileApi.UpdateProfileReqVO);
|
||||
// 关闭并提示
|
||||
emit('success');
|
||||
message.success($t('ui.actionMessage.operationSuccess'));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
profileBaseSettingRef.value.getFormApi().setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
/** 监听 profile 变化 */
|
||||
watch(
|
||||
() => props.profile,
|
||||
(newProfile) => {
|
||||
if (newProfile) {
|
||||
profileBaseSettingRef.value.getFormApi().setValues(newProfile);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<ProfileBaseSetting
|
||||
ref="profileBaseSettingRef"
|
||||
:form-schema="formSchema"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { ProfileNotificationSetting } from '@vben/common-ui';
|
||||
|
||||
const formSchema = computed(() => {
|
||||
return [
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'accountPassword',
|
||||
label: '账户密码',
|
||||
description: '其他用户的消息将以站内信的形式通知',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'systemMessage',
|
||||
label: '系统消息',
|
||||
description: '系统消息将以站内信的形式通知',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'todoTask',
|
||||
label: '待办任务',
|
||||
description: '待办任务将以站内信的形式通知',
|
||||
},
|
||||
];
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<ProfileNotificationSetting :form-schema="formSchema" />
|
||||
</template>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<script setup lang="ts">
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { ProfilePasswordSetting, z } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const profilePasswordSettingRef = ref();
|
||||
|
||||
const formSchema = computed((): VbenFormSchema[] => {
|
||||
return [
|
||||
{
|
||||
fieldName: 'oldPassword',
|
||||
label: '旧密码',
|
||||
component: 'VbenInputPassword',
|
||||
componentProps: {
|
||||
placeholder: '请输入旧密码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'newPassword',
|
||||
label: '新密码',
|
||||
component: 'VbenInputPassword',
|
||||
componentProps: {
|
||||
passwordStrength: true,
|
||||
placeholder: '请输入新密码',
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldName: 'confirmPassword',
|
||||
label: '确认密码',
|
||||
component: 'VbenInputPassword',
|
||||
componentProps: {
|
||||
passwordStrength: true,
|
||||
placeholder: '请再次输入新密码',
|
||||
},
|
||||
dependencies: {
|
||||
rules(values) {
|
||||
const { newPassword } = values;
|
||||
return z
|
||||
.string({ required_error: '请再次输入新密码' })
|
||||
.min(1, { message: '请再次输入新密码' })
|
||||
.refine((value) => value === newPassword, {
|
||||
message: '两次输入的密码不一致',
|
||||
});
|
||||
},
|
||||
triggerFields: ['newPassword'],
|
||||
},
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
function handleSubmit() {
|
||||
message.success('密码修改成功');
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<ProfilePasswordSetting
|
||||
ref="profilePasswordSettingRef"
|
||||
class="w-1/3"
|
||||
:form-schema="formSchema"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { ProfileSecuritySetting } from '@vben/common-ui';
|
||||
|
||||
const formSchema = computed(() => {
|
||||
return [
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'accountPassword',
|
||||
label: '账户密码',
|
||||
description: '当前密码强度:强',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'securityPhone',
|
||||
label: '密保手机',
|
||||
description: '已绑定手机:138****8293',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'securityQuestion',
|
||||
label: '密保问题',
|
||||
description: '未设置密保问题,密保问题可有效保护账户安全',
|
||||
},
|
||||
{
|
||||
value: true,
|
||||
fieldName: 'securityEmail',
|
||||
label: '备用邮箱',
|
||||
description: '已绑定邮箱:ant***sign.com',
|
||||
},
|
||||
{
|
||||
value: false,
|
||||
fieldName: 'securityMfa',
|
||||
label: 'MFA 设备',
|
||||
description: '未绑定 MFA 设备,绑定后,可以进行二次确认',
|
||||
},
|
||||
];
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<ProfileSecuritySetting :form-schema="formSchema" />
|
||||
</template>
|
||||
|
|
@ -403,8 +403,8 @@ async function doSendMessageStream(userMessage: AiChatMessageApi.ChatMessage) {
|
|||
const lastMessage =
|
||||
activeMessageList.value[activeMessageList.value.length - 1];
|
||||
// 累加推理内容
|
||||
lastMessage.reasoningContent =
|
||||
(lastMessage.reasoningContent || '') +
|
||||
lastMessage!.reasoningContent =
|
||||
(lastMessage!.reasoningContent || '') +
|
||||
data.receive.reasoningContent;
|
||||
}
|
||||
|
||||
|
|
@ -552,9 +552,9 @@ onMounted(async () => {
|
|||
/>
|
||||
|
||||
<!-- 右侧:详情部分 -->
|
||||
<Layout class="bg-card mx-4">
|
||||
<Layout class="mx-4 bg-card">
|
||||
<Layout.Header
|
||||
class="!bg-card border-border flex !h-12 items-center justify-between border-b !px-4"
|
||||
class="flex !h-12 items-center justify-between border-b border-border !bg-card !px-4"
|
||||
>
|
||||
<div class="text-lg font-bold">
|
||||
{{ activeConversation?.title ? activeConversation?.title : '对话' }}
|
||||
|
|
@ -613,9 +613,9 @@ onMounted(async () => {
|
|||
</div>
|
||||
</Layout.Content>
|
||||
|
||||
<Layout.Footer class="!bg-card flex flex-col !p-0">
|
||||
<Layout.Footer class="flex flex-col !bg-card !p-0">
|
||||
<form
|
||||
class="border-border mx-4 mb-8 mt-2 flex flex-col rounded-xl border p-2"
|
||||
class="mx-4 mb-8 mt-2 flex flex-col rounded-xl border border-border p-2"
|
||||
>
|
||||
<textarea
|
||||
class="box-border h-24 resize-none overflow-auto rounded-md p-2 focus:outline-none"
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ async function getChatConversationList() {
|
|||
// 1.1 获取 对话数据
|
||||
conversationList.value = await getChatConversationMyList();
|
||||
// 1.2 排序
|
||||
conversationList.value.sort((a, b) => {
|
||||
conversationList.value.toSorted((a, b) => {
|
||||
return Number(b.createTime) - Number(a.createTime);
|
||||
});
|
||||
// 1.3 没有任何对话情况
|
||||
|
|
@ -414,7 +414,7 @@ onMounted(async () => {
|
|||
|
||||
<!-- 左底部:工具栏 -->
|
||||
<div
|
||||
class="bg-card absolute bottom-1 left-0 right-0 mb-4 flex items-center justify-between px-5 leading-9 text-gray-400 shadow-sm"
|
||||
class="absolute bottom-1 left-0 right-0 mb-4 flex items-center justify-between bg-card px-5 leading-9 text-gray-400 shadow-sm"
|
||||
>
|
||||
<div
|
||||
class="flex cursor-pointer items-center text-gray-400"
|
||||
|
|
|
|||
|
|
@ -138,14 +138,14 @@ async function uploadFile(fileItem: FileItem) {
|
|||
fileItem.progress = 100;
|
||||
|
||||
// 调试日志
|
||||
console.log('上传响应:', response);
|
||||
console.warn('上传响应:', response);
|
||||
|
||||
// 兼容不同的返回格式:{ url: '...' } 或 { data: '...' } 或直接是字符串
|
||||
const fileUrl =
|
||||
(response as any)?.url || (response as any)?.data || response;
|
||||
fileItem.url = fileUrl;
|
||||
|
||||
console.log('提取的文件 URL:', fileUrl);
|
||||
console.warn('提取的文件 URL:', fileUrl);
|
||||
|
||||
// 只有当 URL 有效时才添加到列表
|
||||
if (fileUrl && typeof fileUrl === 'string') {
|
||||
|
|
@ -242,7 +242,7 @@ onUnmounted(() => {
|
|||
<!-- Hover 显示的文件列表 -->
|
||||
<div
|
||||
v-if="hasFiles && showTooltip"
|
||||
class="animate-in fade-in slide-in-from-bottom-1 absolute bottom-[calc(100%+8px)] left-1/2 z-[1000] min-w-[240px] max-w-[320px] -translate-x-1/2 rounded-lg border border-gray-200 bg-white p-2 shadow-lg duration-200"
|
||||
class="absolute bottom-[calc(100%+8px)] left-1/2 z-[1000] min-w-[240px] max-w-[320px] -translate-x-1/2 rounded-lg border border-gray-200 bg-white p-2 shadow-lg duration-200 animate-in fade-in slide-in-from-bottom-1"
|
||||
@mouseenter="showTooltipHandler"
|
||||
@mouseleave="hideTooltipHandler"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ function handleClick(doc: any) {
|
|||
<div
|
||||
v-for="(doc, index) in documentList"
|
||||
:key="index"
|
||||
class="bg-card cursor-pointer rounded-lg p-2 px-3 transition-all hover:bg-blue-50"
|
||||
class="cursor-pointer rounded-lg bg-card p-2 px-3 transition-all hover:bg-blue-50"
|
||||
@click="handleClick(doc)"
|
||||
>
|
||||
<div class="mb-1 text-sm text-gray-600">
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ onMounted(async () => {
|
|||
<!-- 回到底部按钮 -->
|
||||
<div
|
||||
v-if="isScrolling"
|
||||
class="z-1000 absolute bottom-0 right-1/2"
|
||||
class="absolute bottom-0 right-1/2 z-1000"
|
||||
@click="handleGoBottom"
|
||||
>
|
||||
<Button shape="circle">
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ async function handleTabsScroll() {
|
|||
<Menu.Item @click="handleMoreClick(['edit', role])">
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon icon="lucide:edit" color="#787878" />
|
||||
<span class="text-primary ml-2">编辑</span>
|
||||
<span class="ml-2 text-primary">编辑</span>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
|
|
|
|||
|
|
@ -176,12 +176,12 @@ onMounted(async () => {
|
|||
<template>
|
||||
<Drawer>
|
||||
<Layout
|
||||
class="bg-card absolute inset-0 flex h-full w-full flex-col overflow-hidden"
|
||||
class="absolute inset-0 flex h-full w-full flex-col overflow-hidden bg-card"
|
||||
>
|
||||
<FormModal @success="handlerAddRoleSuccess" />
|
||||
|
||||
<Layout.Content class="relative m-0 flex-1 overflow-hidden p-0">
|
||||
<div class="z-100 absolute right-0 top--1 mr-5 mt-5">
|
||||
<div class="absolute right-0 top--1 z-100 mr-5 mt-5">
|
||||
<!-- 搜索输入框 -->
|
||||
<Input.Search
|
||||
:loading="loading"
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ onMounted(async () => {
|
|||
<template>
|
||||
<Page auto-content-height>
|
||||
<div class="absolute inset-0 m-4 flex h-full w-full flex-row">
|
||||
<div class="bg-card left-0 mr-4 flex w-96 flex-col rounded-lg p-4">
|
||||
<div class="left-0 mr-4 flex w-96 flex-col rounded-lg bg-card p-4">
|
||||
<div class="flex justify-center">
|
||||
<Segmented
|
||||
v-model:value="selectPlatform"
|
||||
|
|
@ -123,7 +123,7 @@ onMounted(async () => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-card flex-1">
|
||||
<div class="flex-1 bg-card">
|
||||
<ImageList ref="imageListRef" @on-regeneration="handleRegeneration" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ defineExpose({ settingValues });
|
|||
@click="handleSizeClick(imageSize)"
|
||||
>
|
||||
<div
|
||||
class="bg-card flex h-12 w-12 flex-col items-center justify-center rounded-lg border p-0"
|
||||
class="flex h-12 w-12 flex-col items-center justify-center rounded-lg border bg-card p-0"
|
||||
:class="[
|
||||
selectSize === imageSize.key ? 'border-blue-500' : 'border-white',
|
||||
]"
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ onUnmounted(async () => {
|
|||
</div>
|
||||
|
||||
<div
|
||||
class="bg-card sticky bottom-0 z-50 flex h-16 items-center justify-center shadow-sm"
|
||||
class="sticky bottom-0 z-50 flex h-16 items-center justify-center bg-card shadow-sm"
|
||||
>
|
||||
<Pagination
|
||||
:total="pageTotal"
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ defineExpose({ settingValues });
|
|||
@click="handleSizeClick(imageSize)"
|
||||
>
|
||||
<div
|
||||
class="bg-card flex h-12 w-12 items-center justify-center rounded-lg border p-0"
|
||||
class="flex h-12 w-12 items-center justify-center rounded-lg border bg-card p-0"
|
||||
:class="[
|
||||
selectSize === imageSize.key ? 'border-blue-500' : 'border-white',
|
||||
]"
|
||||
|
|
|
|||
|
|
@ -56,12 +56,12 @@ onMounted(async () => {
|
|||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<div
|
||||
class="bg-card grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2.5 shadow-sm"
|
||||
class="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-2.5 bg-card shadow-sm"
|
||||
>
|
||||
<div
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
class="bg-card relative cursor-pointer overflow-hidden transition-transform duration-300 hover:scale-105"
|
||||
class="relative cursor-pointer overflow-hidden bg-card transition-transform duration-300 hover:scale-105"
|
||||
>
|
||||
<Image
|
||||
:src="item.picUrl"
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ onMounted(async () => {
|
|||
<div class="mx-auto">
|
||||
<!-- 头部导航栏 -->
|
||||
<div
|
||||
class="bg-card absolute left-0 right-0 top-0 z-10 flex h-12 items-center border-b px-4"
|
||||
class="absolute left-0 right-0 top-0 z-10 flex h-12 items-center border-b bg-card px-4"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ onMounted(async () => {
|
|||
分片-{{ index + 1 }} · {{ segment.contentLength || 0 }} 字符数 ·
|
||||
{{ segment.tokens || 0 }} Token
|
||||
</div>
|
||||
<div class="bg-card rounded-md p-2">
|
||||
<div class="rounded-md bg-card p-2">
|
||||
{{ segment.content }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ defineExpose({
|
|||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="bg-card flex w-80 flex-col rounded-lg p-5">
|
||||
<h3 class="text-primary h-7 w-full text-center text-xl leading-7">
|
||||
<div class="flex w-80 flex-col rounded-lg bg-card p-5">
|
||||
<h3 class="h-7 w-full text-center text-xl leading-7 text-primary">
|
||||
思维导图创作中心
|
||||
</h3>
|
||||
<div class="mt-4 flex-grow overflow-y-auto">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
getChatRole,
|
||||
updateChatRole,
|
||||
} from '#/api/ai/model/chatRole';
|
||||
import {} from '#/api/bpm/model';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useFormSchema } from '../data';
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import { message } from 'ant-design-vue';
|
|||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { createModel, getModel, updateModel } from '#/api/ai/model/model';
|
||||
import {} from '#/api/bpm/model';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
import { useFormSchema } from '../data';
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ function audioTimeUpdate(args: any) {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="b-1 b-l-none h-18 bg-card flex items-center justify-between border border-solid border-rose-100 px-2"
|
||||
class="b-1 b-l-none h-18 flex items-center justify-between border border-solid border-rose-100 bg-card px-2"
|
||||
>
|
||||
<!-- 歌曲信息 -->
|
||||
<div class="flex gap-2.5">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const currentSong = ref({}); // 当前音乐
|
|||
const mySongList = ref<Recordable<any>[]>([]);
|
||||
const squareSongList = ref<Recordable<any>[]>([]);
|
||||
|
||||
function generateMusic(formData: Recordable<any>) {
|
||||
function generateMusic(_formData: Recordable<any>) {
|
||||
loading.value = true;
|
||||
setTimeout(() => {
|
||||
mySongList.value = Array.from({ length: 20 }, (_, index) => {
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ onBeforeUnmount(() => {
|
|||
<div class="mx-auto">
|
||||
<!-- 头部导航栏 -->
|
||||
<div
|
||||
class="bg-card absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b px-5"
|
||||
class="absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b bg-card px-5"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ defineExpose({ validate });
|
|||
</fieldset>
|
||||
|
||||
<fieldset
|
||||
class="bg-card m-0 mt-10 rounded-lg border border-gray-200 px-3 py-4"
|
||||
class="m-0 mt-10 rounded-lg border border-gray-200 bg-card px-3 py-4"
|
||||
>
|
||||
<legend class="ml-2 px-2.5 text-base font-semibold text-gray-600">
|
||||
<h3>运行结果</h3>
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ function handleSubmit() {
|
|||
<span>{{ label }}</span>
|
||||
<span
|
||||
v-if="hint"
|
||||
class="text-primary-500 flex cursor-pointer select-none items-center text-xs"
|
||||
class="flex cursor-pointer select-none items-center text-xs text-primary-500"
|
||||
@click="hintClick"
|
||||
>
|
||||
<IconifyIcon icon="lucide:circle-help" />
|
||||
|
|
@ -145,14 +145,14 @@ function handleSubmit() {
|
|||
</h3>
|
||||
</DefineLabel>
|
||||
<div class="flex flex-col" v-bind="$attrs">
|
||||
<div class="bg-card flex w-full justify-center pt-2">
|
||||
<div class="bg-card z-10 w-72 rounded-full p-1">
|
||||
<div class="flex w-full justify-center bg-card pt-2">
|
||||
<div class="z-10 w-72 rounded-full bg-card p-1">
|
||||
<div
|
||||
:class="
|
||||
selectedTab === AiWriteTypeEnum.REPLY &&
|
||||
'after:translate-x-[100%] after:transform'
|
||||
"
|
||||
class="after:bg-card relative flex items-center after:absolute after:left-0 after:top-0 after:block after:h-7 after:w-1/2 after:rounded-full after:transition-transform after:content-['']"
|
||||
class="relative flex items-center after:absolute after:left-0 after:top-0 after:block after:h-7 after:w-1/2 after:rounded-full after:bg-card after:transition-transform after:content-['']"
|
||||
>
|
||||
<ReuseTab
|
||||
v-for="tab in tabs"
|
||||
|
|
@ -166,7 +166,7 @@ function handleSubmit() {
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="bg-card box-border h-full w-96 flex-grow overflow-y-auto px-7 pb-2 lg:block"
|
||||
class="box-border h-full w-96 flex-grow overflow-y-auto bg-card px-7 pb-2 lg:block"
|
||||
>
|
||||
<div>
|
||||
<template v-if="selectedTab === AiWriteTypeEnum.WRITING">
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ watch(copied, (val) => {
|
|||
class="hide-scroll-bar box-border h-full overflow-y-auto"
|
||||
>
|
||||
<div
|
||||
class="bg-card relative box-border min-h-full w-full flex-grow p-2 sm:p-5"
|
||||
class="relative box-border min-h-full w-full flex-grow bg-card p-2 sm:p-5"
|
||||
>
|
||||
<Button
|
||||
v-show="isWriting"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const emits = defineEmits<{
|
|||
<span
|
||||
v-for="tag in props.tags"
|
||||
:key="tag.value"
|
||||
class="bg-card border-card-100 mb-2 cursor-pointer rounded border-2 border-solid px-1 text-xs leading-6"
|
||||
class="border-card-100 mb-2 cursor-pointer rounded border-2 border-solid bg-card px-1 text-xs leading-6"
|
||||
:class="
|
||||
modelValue === tag.value && '!border-primary-500 !text-primary-500'
|
||||
"
|
||||
|
|
|
|||
|
|
@ -62,16 +62,16 @@ const resetElement = () => {
|
|||
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] });
|
||||
|
||||
// 是否开启自定义用户任务超时处理
|
||||
boundaryEventType.value = elExtensionElements.value.values?.filter(
|
||||
boundaryEventType.value = elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:BoundaryEventType`,
|
||||
)?.[0];
|
||||
);
|
||||
if (boundaryEventType.value && boundaryEventType.value.value === 1) {
|
||||
timeoutHandlerEnable.value = true;
|
||||
configExtensions.value.push(boundaryEventType.value);
|
||||
}
|
||||
|
||||
// 执行动作
|
||||
timeoutHandlerType.value = elExtensionElements.value.values?.filter(
|
||||
timeoutHandlerType.value = elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:TimeoutHandlerType`,
|
||||
)?.[0];
|
||||
if (timeoutHandlerType.value) {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 审批类型
|
||||
approveType.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:ApproveType`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:ApproveType`, {
|
||||
|
|
@ -121,7 +121,7 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 审批人与提交人为同一人时
|
||||
assignStartUserHandlerTypeEl.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:AssignStartUserHandlerType`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:AssignStartUserHandlerType`, {
|
||||
|
|
@ -131,13 +131,13 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 审批人拒绝时
|
||||
rejectHandlerTypeEl.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:RejectHandlerType`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:RejectHandlerType`, { value: 1 });
|
||||
rejectHandlerType.value = rejectHandlerTypeEl.value.value;
|
||||
returnNodeIdEl.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:RejectReturnTaskId`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:RejectReturnTaskId`, {
|
||||
|
|
@ -147,7 +147,7 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 审批人为空时
|
||||
assignEmptyHandlerTypeEl.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:AssignEmptyHandlerType`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:AssignEmptyHandlerType`, {
|
||||
|
|
@ -155,7 +155,7 @@ const resetCustomConfigList = () => {
|
|||
});
|
||||
assignEmptyHandlerType.value = assignEmptyHandlerTypeEl.value.value;
|
||||
assignEmptyUserIdsEl.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:AssignEmptyUserIds`,
|
||||
)?.[0] ||
|
||||
bpmnInstances().moddle.create(`${prefix}:AssignEmptyUserIds`, {
|
||||
|
|
@ -172,7 +172,7 @@ const resetCustomConfigList = () => {
|
|||
});
|
||||
|
||||
// 操作按钮
|
||||
buttonsSettingEl.value = elExtensionElements.value.values?.filter(
|
||||
buttonsSettingEl.value = elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:ButtonsSetting`,
|
||||
);
|
||||
if (buttonsSettingEl.value.length === 0) {
|
||||
|
|
@ -189,7 +189,7 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 字段权限
|
||||
if (formType.value === BpmModelFormType.NORMAL) {
|
||||
const fieldsPermissionList = elExtensionElements.value.values?.filter(
|
||||
const fieldsPermissionList = elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:FieldsPermission`,
|
||||
);
|
||||
fieldsPermissionEl.value = [];
|
||||
|
|
@ -206,21 +206,21 @@ const resetCustomConfigList = () => {
|
|||
|
||||
// 是否需要签名
|
||||
signEnable.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:SignEnable`,
|
||||
)?.[0] ||
|
||||
) ||
|
||||
bpmnInstances().moddle.create(`${prefix}:SignEnable`, { value: false });
|
||||
|
||||
// 审批意见
|
||||
reasonRequire.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:ReasonRequire`,
|
||||
)?.[0] ||
|
||||
) ||
|
||||
bpmnInstances().moddle.create(`${prefix}:ReasonRequire`, { value: false });
|
||||
|
||||
// 保留剩余扩展元素,便于后面更新该元素对应属性
|
||||
otherExtensions.value =
|
||||
elExtensionElements.value.values?.filter(
|
||||
elExtensionElements.value.values?.find(
|
||||
(ex: any) =>
|
||||
ex.$type !== `${prefix}:AssignStartUserHandlerType` &&
|
||||
ex.$type !== `${prefix}:RejectHandlerType` &&
|
||||
|
|
|
|||
|
|
@ -118,10 +118,10 @@ const resetTaskForm = () => {
|
|||
const extensionElements =
|
||||
businessObject?.extensionElements ??
|
||||
bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] });
|
||||
userTaskForm.value.candidateStrategy = extensionElements.values?.filter(
|
||||
userTaskForm.value.candidateStrategy = extensionElements.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:CandidateStrategy`,
|
||||
)?.[0]?.value;
|
||||
const candidateParamStr = extensionElements.values?.filter(
|
||||
const candidateParamStr = extensionElements.values?.find(
|
||||
(ex: any) => ex.$type === `${prefix}:CandidateParam`,
|
||||
)?.[0]?.value;
|
||||
if (candidateParamStr && candidateParamStr.length > 0) {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ function setDuration(type, val) {
|
|||
// 组装ISO 8601字符串
|
||||
let d = isoDuration.value;
|
||||
if (d.includes(type)) {
|
||||
d = d.replace(new RegExp(`\\d+${type}`), val + type);
|
||||
d = d.replace(new RegExp(String.raw`\d+${type}`), val + type);
|
||||
} else {
|
||||
d += val + type;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,10 +82,12 @@ export function updateElementExtensions(element, extensionList) {
|
|||
}
|
||||
|
||||
// 创建一个id
|
||||
export function uuid(length = 8, chars?) {
|
||||
export function uuid(
|
||||
length = 8,
|
||||
charsString = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
) {
|
||||
let result = '';
|
||||
const charsString =
|
||||
chars || '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
for (let i = length; i > 0; --i) {
|
||||
result += charsString[Math.floor(Math.random() * charsString.length)];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ onMounted(() => {
|
|||
</script>
|
||||
<template>
|
||||
<div class="simple-process-model-container">
|
||||
<div class="bg-card absolute right-0 top-0">
|
||||
<div class="absolute right-0 top-0 bg-card">
|
||||
<Row type="flex" justify="end">
|
||||
<ButtonGroup key="scale-control">
|
||||
<Button v-if="!readonly" @click="exportJson">
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ onBeforeUnmount(() => {
|
|||
<div class="mx-auto">
|
||||
<!-- 头部导航栏 -->
|
||||
<div
|
||||
class="bg-card absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b px-5"
|
||||
class="absolute inset-x-0 top-0 z-10 flex h-12 items-center border-b bg-card px-5"
|
||||
>
|
||||
<!-- 左侧标题 -->
|
||||
<div class="flex w-48 items-center overflow-hidden">
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ onMounted(async () => {
|
|||
<span class="text-gray-500">编号:{{ id || '-' }}</span>
|
||||
<IconifyIcon
|
||||
icon="lucide:printer"
|
||||
class="hover:text-primary cursor-pointer"
|
||||
class="cursor-pointer hover:text-primary"
|
||||
@click="handlePrint"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -54,7 +54,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -102,7 +102,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -150,7 +150,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -198,7 +198,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -246,7 +246,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -294,7 +294,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
@ -342,7 +342,7 @@ export function getChartOptions(activeTabName: any, res: any): any {
|
|||
return {
|
||||
dataset: {
|
||||
dimensions: ['nickname', 'count'],
|
||||
source: cloneDeep(res).reverse(),
|
||||
source: cloneDeep(res).toReversed(),
|
||||
},
|
||||
grid: {
|
||||
left: 20,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ onMounted(() => {
|
|||
{ name: '定制', value: 310 },
|
||||
{ name: '技术支持', value: 274 },
|
||||
{ name: '远程', value: 400 },
|
||||
].sort((a, b) => {
|
||||
].toSorted((a, b) => {
|
||||
return a.value - b.value;
|
||||
}),
|
||||
name: '商业占比',
|
||||
|
|
|
|||
|
|
@ -249,9 +249,9 @@ defineExpose({ validate });
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>
|
||||
合计付款:{{ erpPriceInputFormatter(summaries.totalPrice) }}
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ function handleOpenSaleOut() {
|
|||
|
||||
function handleAddSaleOut(rows: ErpSaleOutApi.SaleOut[]) {
|
||||
rows.forEach((row) => {
|
||||
// TODO 芋艿
|
||||
const newItem: ErpFinanceReceiptApi.FinanceReceiptItem = {
|
||||
bizId: row.id,
|
||||
bizType: ErpBizType.SALE_OUT,
|
||||
|
|
@ -153,6 +154,7 @@ function handleOpenSaleReturn() {
|
|||
}
|
||||
|
||||
function handleAddSaleReturn(rows: ErpSaleReturnApi.SaleReturn[]) {
|
||||
// TODO 芋艿
|
||||
rows.forEach((row) => {
|
||||
const newItem: ErpFinanceReceiptApi.FinanceReceiptItem = {
|
||||
bizId: row.id,
|
||||
|
|
@ -249,9 +251,9 @@ defineExpose({ validate });
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>
|
||||
合计收款:{{ erpPriceInputFormatter(summaries.totalPrice) }}
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ async function handleWarehouseChange(row: ErpPurchaseInApi.PurchaseInItem) {
|
|||
|
||||
/** 处理行数据变更 */
|
||||
function handleRowChange(row: any) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index === -1) {
|
||||
tableData.value.push(row);
|
||||
|
|
@ -273,9 +274,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpPurchaseOrderApi.PurchaseOrderItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -285,9 +286,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ watch(
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpPurchaseReturnApi.PurchaseReturnItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -153,6 +154,7 @@ async function handleWarehouseChange(
|
|||
|
||||
/** 处理行数据变更 */
|
||||
function handleRowChange(row: any) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index === -1) {
|
||||
tableData.value.push(row);
|
||||
|
|
@ -275,9 +277,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpSaleOrderApi.SaleOrderItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -285,9 +286,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ watch(
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpSaleOutApi.SaleOutItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -273,9 +274,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ watch(
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpSaleReturnApi.SaleReturnItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -273,9 +274,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpStockCheckApi.StockCheckItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -280,9 +281,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ function handleAdd() {
|
|||
totalPrice: undefined,
|
||||
remark: undefined,
|
||||
};
|
||||
// TODO 芋艿
|
||||
tableData.value.push(newRow);
|
||||
// 通知父组件更新
|
||||
emit('update:items', [...tableData.value]);
|
||||
|
|
@ -105,6 +106,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpStockInApi.StockInItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -269,9 +271,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpStockMoveApi.StockMoveItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -290,9 +291,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ function handleAdd() {
|
|||
|
||||
/** 处理删除 */
|
||||
function handleDelete(row: ErpStockOutApi.StockOutItem) {
|
||||
// TODO 芋艿
|
||||
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
|
|
@ -267,9 +268,9 @@ onMounted(async () => {
|
|||
</template>
|
||||
|
||||
<template #bottom>
|
||||
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="mt-2 rounded border border-border bg-muted p-2">
|
||||
<div class="flex justify-between text-sm text-muted-foreground">
|
||||
<span class="font-medium text-foreground">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ getDetail();
|
|||
|
||||
<template>
|
||||
<Page auto-content-height v-loading="loading">
|
||||
<div class="bg-card flex h-[95%] flex-col rounded-md p-4">
|
||||
<div class="flex h-[95%] flex-col rounded-md bg-card p-4">
|
||||
<Steps
|
||||
type="navigation"
|
||||
v-model:current="currentStep"
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ const { status, data, send, close, open } = useWebSocket(server.value, {
|
|||
const messageList = ref(
|
||||
[] as { text: string; time: number; type?: string; userId?: string }[],
|
||||
); // 消息列表
|
||||
const messageReverseList = computed(() => [...messageList.value].reverse());
|
||||
const messageReverseList = computed(() => [...messageList.value].toReversed());
|
||||
watchEffect(() => {
|
||||
if (!data.value) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ onMounted(async () => {
|
|||
<!-- 所属产品列 -->
|
||||
<template #product="{ row }">
|
||||
<a
|
||||
class="text-primary cursor-pointer"
|
||||
class="cursor-pointer text-primary"
|
||||
@click="openProductDetail(row.productId)"
|
||||
>
|
||||
{{ products.find((p: any) => p.id === row.productId)?.name || '-' }}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ function handleAuthInfoDialogClose() {
|
|||
<Card class="h-full">
|
||||
<template #title>
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon icon="ep:info-filled" class="text-primary mr-2" />
|
||||
<IconifyIcon icon="ep:info-filled" class="mr-2 text-primary" />
|
||||
<span>设备信息</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -141,7 +141,7 @@ function handleAuthInfoDialogClose() {
|
|||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<IconifyIcon icon="ep:location" class="text-primary mr-2" />
|
||||
<IconifyIcon icon="ep:location" class="mr-2 text-primary" />
|
||||
<span>设备位置</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -553,17 +553,17 @@ defineExpose({ open }); // 提供 open 方法,用于打开弹窗
|
|||
|
||||
.toolbar-wrapper {
|
||||
padding: 16px;
|
||||
background-color: hsl(var(--card) / 0.9);
|
||||
background-color: hsl(var(--card) / 90%);
|
||||
border: 1px solid hsl(var(--border) / 60%);
|
||||
border-radius: 8px;
|
||||
border: 1px solid hsl(var(--border) / 0.6);
|
||||
}
|
||||
|
||||
.chart-container,
|
||||
.table-container {
|
||||
padding: 16px;
|
||||
background-color: hsl(var(--card));
|
||||
border: 1px solid hsl(var(--border) / 60%);
|
||||
border-radius: 8px;
|
||||
border: 1px solid hsl(var(--border) / 0.6);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ import {
|
|||
|
||||
import { getLatestDeviceProperties } from '#/api/iot/device/device';
|
||||
|
||||
import DeviceDetailsThingModelPropertyHistory
|
||||
from './device-details-thing-model-property-history.vue';
|
||||
import DeviceDetailsThingModelPropertyHistory from './device-details-thing-model-property-history.vue';
|
||||
|
||||
const props = defineProps<{ deviceId: number }>();
|
||||
|
||||
|
|
@ -168,13 +167,13 @@ onMounted(() => {
|
|||
>
|
||||
<!-- 添加渐变背景层 -->
|
||||
<div
|
||||
class="from-muted pointer-events-none absolute left-0 right-0 top-0 h-12 bg-gradient-to-b to-transparent"
|
||||
class="pointer-events-none absolute left-0 right-0 top-0 h-12 bg-gradient-to-b from-muted to-transparent"
|
||||
></div>
|
||||
<div class="relative p-4">
|
||||
<!-- 标题区域 -->
|
||||
<div class="mb-3 flex items-center">
|
||||
<div class="mr-2.5 flex items-center">
|
||||
<IconifyIcon icon="ep:cpu" class="text-primary text-lg" />
|
||||
<IconifyIcon icon="ep:cpu" class="text-lg text-primary" />
|
||||
</div>
|
||||
<div class="flex-1 text-base font-bold">{{ item.name }}</div>
|
||||
<!-- 标识符 -->
|
||||
|
|
@ -198,7 +197,7 @@ onMounted(() => {
|
|||
>
|
||||
<IconifyIcon
|
||||
icon="ep:data-line"
|
||||
class="text-primary text-lg"
|
||||
class="text-lg text-primary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -206,14 +205,14 @@ onMounted(() => {
|
|||
<!-- 信息区域 -->
|
||||
<div class="text-sm">
|
||||
<div class="mb-2.5 last:mb-0">
|
||||
<span class="text-muted-foreground mr-2.5">属性值</span>
|
||||
<span class="text-foreground font-bold">
|
||||
<span class="mr-2.5 text-muted-foreground">属性值</span>
|
||||
<span class="font-bold text-foreground">
|
||||
{{ formatValueWithUnit(item) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mb-2.5 last:mb-0">
|
||||
<span class="text-muted-foreground mr-2.5">更新时间</span>
|
||||
<span class="text-foreground text-sm">
|
||||
<span class="mr-2.5 text-muted-foreground">更新时间</span>
|
||||
<span class="text-sm text-foreground">
|
||||
{{ item.updateTime ? formatDate(item.updateTime) : '-' }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ function getDeviceTypeColor(deviceType: number) {
|
|||
}
|
||||
|
||||
// 获取设备状态信息
|
||||
function getStatusInfo(state: number | string | null | undefined) {
|
||||
function getStatusInfo(state: null | number | string | undefined) {
|
||||
const parsedState = Number(state);
|
||||
const hasNumericState = Number.isFinite(parsedState);
|
||||
const fallback = hasNumericState
|
||||
|
|
@ -396,21 +396,21 @@ defineExpose({
|
|||
.device-card {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: hsl(var(--card) / 0.95);
|
||||
border: 1px solid hsl(var(--border) / 0.6);
|
||||
background: hsl(var(--card) / 95%);
|
||||
border: 1px solid hsl(var(--border) / 60%);
|
||||
border-radius: 8px;
|
||||
box-shadow:
|
||||
0 1px 2px 0 hsl(var(--foreground) / 0.04),
|
||||
0 1px 6px -1px hsl(var(--foreground) / 0.05),
|
||||
0 2px 4px 0 hsl(var(--foreground) / 0.05);
|
||||
0 1px 2px 0 hsl(var(--foreground) / 4%),
|
||||
0 1px 6px -1px hsl(var(--foreground) / 5%),
|
||||
0 2px 4px 0 hsl(var(--foreground) / 5%);
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
&:hover {
|
||||
border-color: hsl(var(--border));
|
||||
box-shadow:
|
||||
0 1px 2px -2px hsl(var(--foreground) / 0.12),
|
||||
0 3px 6px 0 hsl(var(--foreground) / 0.1),
|
||||
0 5px 12px 4px hsl(var(--foreground) / 0.08);
|
||||
0 1px 2px -2px hsl(var(--foreground) / 12%),
|
||||
0 3px 6px 0 hsl(var(--foreground) / 10%),
|
||||
0 5px 12px 4px hsl(var(--foreground) / 8%);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
|
|
@ -473,7 +473,7 @@ defineExpose({
|
|||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
color: hsl(var(--foreground) / 0.9);
|
||||
color: hsl(var(--foreground) / 90%);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
|
@ -496,7 +496,7 @@ defineExpose({
|
|||
.label {
|
||||
flex-shrink: 0;
|
||||
font-size: 13px;
|
||||
color: hsl(var(--foreground) / 0.6);
|
||||
color: hsl(var(--foreground) / 60%);
|
||||
}
|
||||
|
||||
.value {
|
||||
|
|
@ -505,7 +505,7 @@ defineExpose({
|
|||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 13px;
|
||||
color: hsl(var(--foreground) / 0.85);
|
||||
color: hsl(var(--foreground) / 85%);
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
|
||||
|
|
@ -515,7 +515,7 @@ defineExpose({
|
|||
transition: color 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: hsl(var(--primary) / 0.85);
|
||||
color: hsl(var(--primary) / 85%);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -524,7 +524,7 @@ defineExpose({
|
|||
'SF Mono', Monaco, Inconsolata, 'Fira Code', Consolas, monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: hsl(var(--foreground) / 0.6);
|
||||
color: hsl(var(--foreground) / 60%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -537,7 +537,7 @@ defineExpose({
|
|||
display: flex;
|
||||
gap: 8px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid hsl(var(--border) / 0.4);
|
||||
border-top: 1px solid hsl(var(--border) / 40%);
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
|
|
@ -561,8 +561,8 @@ defineExpose({
|
|||
|
||||
&.btn-edit {
|
||||
color: hsl(var(--primary));
|
||||
background: hsl(var(--primary) / 0.12);
|
||||
border-color: hsl(var(--primary) / 0.25);
|
||||
background: hsl(var(--primary) / 12%);
|
||||
border-color: hsl(var(--primary) / 25%);
|
||||
|
||||
&:hover {
|
||||
color: hsl(var(--primary-foreground));
|
||||
|
|
@ -573,8 +573,8 @@ defineExpose({
|
|||
|
||||
&.btn-view {
|
||||
color: hsl(var(--warning));
|
||||
background: hsl(var(--warning) / 0.12);
|
||||
border-color: hsl(var(--warning) / 0.25);
|
||||
background: hsl(var(--warning) / 12%);
|
||||
border-color: hsl(var(--warning) / 25%);
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
|
|
@ -590,11 +590,7 @@ defineExpose({
|
|||
hsl(var(--accent)) 40%,
|
||||
hsl(var(--card)) 60%
|
||||
);
|
||||
border-color: color-mix(
|
||||
in srgb,
|
||||
hsl(var(--accent)) 55%,
|
||||
transparent
|
||||
);
|
||||
border-color: color-mix(in srgb, hsl(var(--accent)) 55%, transparent);
|
||||
|
||||
&:hover {
|
||||
color: hsl(var(--accent-foreground));
|
||||
|
|
@ -607,8 +603,8 @@ defineExpose({
|
|||
flex: 0 0 32px;
|
||||
padding: 4px;
|
||||
color: hsl(var(--destructive));
|
||||
background: hsl(var(--destructive) / 0.12);
|
||||
border-color: hsl(var(--destructive) / 0.3);
|
||||
background: hsl(var(--destructive) / 12%);
|
||||
border-color: hsl(var(--destructive) / 30%);
|
||||
|
||||
&:hover {
|
||||
color: hsl(var(--destructive-foreground));
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ async function handleDownloadTemplate() {
|
|||
<Modal :title="getTitle" class="w-1/3">
|
||||
<Form class="mx-4" />
|
||||
<div class="mx-4 mt-4 text-center">
|
||||
<a class="text-primary cursor-pointer" @click="handleDownloadTemplate">
|
||||
<a class="cursor-pointer text-primary" @click="handleDownloadTemplate">
|
||||
下载导入模板
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import {ComparisonCard, Page} from '@vben/common-ui';
|
||||
// TODO @芋艿
|
||||
import type { StatsData } from './data';
|
||||
|
||||
import {Col, Row} from 'ant-design-vue';
|
||||
import {onMounted, ref} from 'vue';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import {getStatisticsSummary} from '#/api/iot/statistics';
|
||||
import { ComparisonCard, Page } from '@vben/common-ui';
|
||||
|
||||
import {defaultStatsData, type StatsData} from './data';
|
||||
import { Col, Row } from 'ant-design-vue';
|
||||
|
||||
import { getStatisticsSummary } from '#/api/iot/statistics';
|
||||
|
||||
import { defaultStatsData } from './data';
|
||||
import DeviceCountCard from './modules/device-count-card.vue';
|
||||
import DeviceStateCountCard from './modules/device-state-count-card.vue';
|
||||
import MessageTrendCard from './modules/message-trend-card.vue';
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ onMounted(() => {
|
|||
<span class="text-base font-medium text-gray-600">消息量统计</span>
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="whitespace-nowrap text-sm text-gray-500"
|
||||
>时间范围</span
|
||||
>
|
||||
<span class="whitespace-nowrap text-sm text-gray-500">
|
||||
时间范围
|
||||
</span>
|
||||
<ShortcutDateRangePicker @change="handleDateRangeChange" />
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
|
|
@ -178,4 +178,4 @@ onMounted(() => {
|
|||
<EchartsUI ref="messageChartRef" class="h-[300px] w-full" />
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -123,13 +123,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||
>
|
||||
<IconifyIcon
|
||||
icon="ant-design:download-outlined"
|
||||
class="text-primary shrink-0 align-middle text-base"
|
||||
class="shrink-0 align-middle text-base text-primary"
|
||||
/>
|
||||
<a
|
||||
:href="row.fileUrl"
|
||||
target="_blank"
|
||||
download
|
||||
class="text-primary cursor-pointer align-middle hover:underline"
|
||||
class="cursor-pointer align-middle text-primary hover:underline"
|
||||
>
|
||||
下载固件
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
export {default as HttpConfigForm} from './http-config-form.vue';
|
||||
export {default as KafkaMqConfigForm} from './kafka-mq-config-form.vue';
|
||||
export {default as MqttConfigForm} from './mqtt-config-form.vue';
|
||||
export {default as RabbitMqConfigForm} from './rabbit-mq-config-form.vue';
|
||||
export {default as RedisStreamConfigForm} from './redis-stream-config-form.vue';
|
||||
export {default as RocketMqConfigForm} from './rocket-mq-config-form.vue';
|
||||
export { default as HttpConfigForm } from './http-config-form.vue';
|
||||
export { default as KafkaMqConfigForm } from './kafka-mq-config-form.vue';
|
||||
export { default as MqttConfigForm } from './mqtt-config-form.vue';
|
||||
export { default as RabbitMqConfigForm } from './rabbit-mq-config-form.vue';
|
||||
export { default as RedisStreamConfigForm } from './redis-stream-config-form.vue';
|
||||
export { default as RocketMqConfigForm } from './rocket-mq-config-form.vue';
|
||||
|
|
|
|||
|
|
@ -135,7 +135,8 @@ function handleDeviceChange(_: any) {
|
|||
|
||||
/**
|
||||
* 处理属性变化事件
|
||||
* @param propertyInfo 属性信息对象
|
||||
* @param propertyInfo.config 属性配置
|
||||
* @param propertyInfo.type 属性类型
|
||||
*/
|
||||
function handlePropertyChange(propertyInfo: { config: any; type: string }) {
|
||||
propertyType.value = propertyInfo.type;
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ watch(
|
|||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
class="w-full"
|
||||
/>
|
||||
<div v-else class="text-secondary text-sm">无需设置时间值</div>
|
||||
<div v-else class="text-sm text-secondary">无需设置时间值</div>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
|
||||
|
|
|
|||
|
|
@ -365,10 +365,10 @@ function handlePropertyChange(propertyInfo: any) {
|
|||
|
||||
<!-- 其他触发类型的提示 -->
|
||||
<div v-else class="py-5 text-center">
|
||||
<p class="text-secondary mb-1 text-sm">
|
||||
<p class="mb-1 text-sm text-secondary">
|
||||
当前触发事件类型:{{ getTriggerTypeLabel(triggerType) }}
|
||||
</p>
|
||||
<p class="text-secondary text-xs">此触发类型暂不需要配置额外条件</p>
|
||||
<p class="text-xs text-secondary">此触发类型暂不需要配置额外条件</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -108,18 +108,18 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
|||
>
|
||||
<!-- 条件配置 -->
|
||||
<div
|
||||
class="rounded-3px border-border bg-fill-color-blank border shadow-sm"
|
||||
class="rounded-3px bg-fill-color-blank border border-border shadow-sm"
|
||||
>
|
||||
<div
|
||||
class="rounded-t-1 border-border bg-fill-color-blank flex items-center justify-between border-b p-3"
|
||||
class="rounded-t-1 bg-fill-color-blank flex items-center justify-between border-b border-border p-3"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="bg-primary flex size-5 items-center justify-center rounded-full text-xs font-bold text-white"
|
||||
class="flex size-5 items-center justify-center rounded-full bg-primary text-xs font-bold text-white"
|
||||
>
|
||||
{{ conditionIndex + 1 }}
|
||||
</div>
|
||||
<span class="text-primary text-base font-bold">
|
||||
<span class="text-base font-bold text-primary">
|
||||
条件 {{ conditionIndex + 1 }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -159,7 +159,7 @@ function updateCondition(index: number, condition: TriggerCondition) {
|
|||
<IconifyIcon icon="lucide:plus" />
|
||||
继续添加条件
|
||||
</Button>
|
||||
<span class="text-secondary mt-2 block text-xs">
|
||||
<span class="mt-2 block text-xs text-secondary">
|
||||
最多可添加 {{ maxConditions }} 个条件
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -451,8 +451,8 @@ watch(
|
|||
<!-- 弹出层内容 -->
|
||||
<div class="json-params-detail-content">
|
||||
<div class="mb-4 flex items-center gap-2">
|
||||
<IconifyIcon :icon="titleIcon" class="text-primary text-lg" />
|
||||
<span class="text-primary text-base font-bold">
|
||||
<IconifyIcon :icon="titleIcon" class="text-lg text-primary" />
|
||||
<span class="text-base font-bold text-primary">
|
||||
{{ title }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -463,9 +463,9 @@ watch(
|
|||
<div class="mb-2 flex items-center gap-2">
|
||||
<IconifyIcon
|
||||
:icon="paramsIcon"
|
||||
class="text-primary text-base"
|
||||
class="text-base text-primary"
|
||||
/>
|
||||
<span class="text-primary text-base font-bold">
|
||||
<span class="text-base font-bold text-primary">
|
||||
{{ paramsLabel }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -473,10 +473,10 @@ watch(
|
|||
<div
|
||||
v-for="param in paramsList"
|
||||
:key="param.identifier"
|
||||
class="bg-card flex items-center justify-between rounded-lg p-2"
|
||||
class="flex items-center justify-between rounded-lg bg-card p-2"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<div class="text-primary text-base font-bold">
|
||||
<div class="text-base font-bold text-primary">
|
||||
{{ param.name }}
|
||||
<Tag
|
||||
v-if="param.required"
|
||||
|
|
@ -487,7 +487,7 @@ watch(
|
|||
{{ JSON_PARAMS_INPUT_CONSTANTS.REQUIRED_TAG }}
|
||||
</Tag>
|
||||
</div>
|
||||
<div class="text-secondary text-xs">
|
||||
<div class="text-xs text-secondary">
|
||||
{{ param.identifier }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -495,7 +495,7 @@ watch(
|
|||
<Tag :type="getParamTypeTag(param.dataType)" size="small">
|
||||
{{ getParamTypeName(param.dataType) }}
|
||||
</Tag>
|
||||
<span class="text-secondary text-xs">
|
||||
<span class="text-xs text-secondary">
|
||||
{{ getExampleValue(param) }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -503,11 +503,11 @@ watch(
|
|||
</div>
|
||||
|
||||
<div class="ml-6 mt-3">
|
||||
<div class="text-secondary mb-1 text-xs">
|
||||
<div class="mb-1 text-xs text-secondary">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.COMPLETE_JSON_FORMAT }}
|
||||
</div>
|
||||
<pre
|
||||
class="bg-card border-l-3px border-primary text-primary overflow-x-auto rounded-lg p-3 text-sm"
|
||||
class="border-l-3px overflow-x-auto rounded-lg border-primary bg-card p-3 text-sm text-primary"
|
||||
>
|
||||
<code>{{ generateExampleJson() }}</code>
|
||||
</pre>
|
||||
|
|
@ -517,7 +517,7 @@ watch(
|
|||
<!-- 无参数提示 -->
|
||||
<div v-else>
|
||||
<div class="py-4 text-center">
|
||||
<p class="text-secondary text-sm">
|
||||
<p class="text-sm text-secondary">
|
||||
{{ emptyMessage }}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -550,7 +550,7 @@ watch(
|
|||
|
||||
<!-- 快速填充按钮 -->
|
||||
<div v-if="paramsList.length > 0" class="flex items-center gap-2">
|
||||
<span class="text-secondary text-xs">
|
||||
<span class="text-xs text-secondary">
|
||||
{{ JSON_PARAMS_INPUT_CONSTANTS.QUICK_FILL_LABEL }}
|
||||
</span>
|
||||
<Button size="small" type="primary" plain @click="fillExampleJson">
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ watch(
|
|||
class="min-w-0 flex-1"
|
||||
style="width: auto !important"
|
||||
/>
|
||||
<span class="text-secondary whitespace-nowrap text-xs"> 至 </span>
|
||||
<span class="whitespace-nowrap text-xs text-secondary"> 至 </span>
|
||||
<Input
|
||||
v-model="rangeEnd"
|
||||
:type="getInputType()"
|
||||
|
|
@ -231,7 +231,7 @@ watch(
|
|||
v-if="listPreview.length > 0"
|
||||
class="mt-2 flex flex-wrap items-center gap-1"
|
||||
>
|
||||
<span class="text-secondary text-xs"> 解析结果: </span>
|
||||
<span class="text-xs text-secondary"> 解析结果: </span>
|
||||
<Tag
|
||||
v-for="(item, index) in listPreview"
|
||||
:key="index"
|
||||
|
|
@ -282,7 +282,7 @@ watch(
|
|||
:content="`单位:${propertyConfig.unit}`"
|
||||
placement="top"
|
||||
>
|
||||
<span class="text-secondary px-1 text-xs">
|
||||
<span class="px-1 text-xs text-secondary">
|
||||
{{ propertyConfig.unit }}
|
||||
</span>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ function onActionTypeChange(action: Action, type: any) {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="border-primary rounded-lg border" shadow="never">
|
||||
<Card class="rounded-lg border border-primary" shadow="never">
|
||||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="gap-8px flex items-center">
|
||||
|
|
@ -275,14 +275,14 @@ function onActionTypeChange(action: Action, type: any) {
|
|||
action.type ===
|
||||
IotRuleSceneActionTypeEnum.ALERT_TRIGGER.toString()
|
||||
"
|
||||
class="border-border bg-fill-color-blank rounded-lg border p-4"
|
||||
class="bg-fill-color-blank rounded-lg border border-border p-4"
|
||||
>
|
||||
<div class="mb-2 flex items-center gap-2">
|
||||
<IconifyIcon icon="ep:warning" class="text-warning text-base" />
|
||||
<span class="font-600 text-primary text-sm">触发告警</span>
|
||||
<IconifyIcon icon="ep:warning" class="text-base text-warning" />
|
||||
<span class="font-600 text-sm text-primary">触发告警</span>
|
||||
<Tag size="small" type="warning">自动执行</Tag>
|
||||
</div>
|
||||
<div class="text-secondary text-xs leading-relaxed">
|
||||
<div class="text-xs leading-relaxed text-secondary">
|
||||
当触发条件满足时,系统将自动发送告警通知,可在菜单 [告警中心 ->
|
||||
告警配置] 管理。
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import { IconifyIcon } from '@vben/icons';
|
|||
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Card, Col, Form, Input, Radio, Row } from 'ant-design-vue';
|
||||
import { DictTag } from "#/components/dict-tag";
|
||||
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
|
||||
/** 基础信息配置组件 */
|
||||
defineOptions({ name: 'BasicInfoSection' });
|
||||
|
|
@ -26,7 +27,7 @@ const formData = useVModel(props, 'modelValue', emit); // 表单数据
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="rounded-8px mb-10px border-primary border" shadow="never">
|
||||
<Card class="rounded-8px mb-10px border border-primary" shadow="never">
|
||||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="gap-8px flex items-center">
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ onMounted(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="rounded-8px mb-10px border-primary border" shadow="never">
|
||||
<Card class="rounded-8px mb-10px border border-primary" shadow="never">
|
||||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="gap-8px flex items-center">
|
||||
|
|
@ -201,7 +201,7 @@ onMounted(() => {
|
|||
class="gap-16px flex flex-col"
|
||||
>
|
||||
<div
|
||||
class="gap-8px p-12px px-16px rounded-6px border-primary bg-background flex items-center border"
|
||||
class="gap-8px p-12px px-16px rounded-6px flex items-center border border-primary bg-background"
|
||||
>
|
||||
<IconifyIcon
|
||||
icon="lucide:timer"
|
||||
|
|
@ -214,7 +214,7 @@ onMounted(() => {
|
|||
|
||||
<!-- CRON 表达式配置 -->
|
||||
<div
|
||||
class="p-16px rounded-6px border-primary bg-background border"
|
||||
class="p-16px rounded-6px border border-primary bg-background"
|
||||
>
|
||||
<Form.Item label="CRON表达式" required>
|
||||
<CronTab
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ watch(
|
|||
{{ operator.label }}
|
||||
</div>
|
||||
<div
|
||||
class="text-12px px-6px py-2px rounded-4px bg-primary-light-9 text-primary font-mono"
|
||||
class="text-12px px-6px py-2px rounded-4px bg-primary-light-9 font-mono text-primary"
|
||||
>
|
||||
{{ operator.symbol }}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { DICT_TYPE } from '@vben/constants';
|
|||
import { Select } from 'ant-design-vue';
|
||||
|
||||
import { getSimpleProductList } from '#/api/iot/product/product';
|
||||
import { DictTag } from "#/components/dict-tag";
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
|
||||
/** 产品选择器组件 */
|
||||
defineOptions({ name: 'ProductSelector' });
|
||||
|
|
@ -78,7 +78,7 @@ onMounted(() => {
|
|||
{{ product.productKey }}
|
||||
</div>
|
||||
</div>
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" />
|
||||
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="product.status" />
|
||||
</div>
|
||||
</Select.Option>
|
||||
</Select>
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ const emit = defineEmits<{
|
|||
(e: 'change', value: { config: any; type: string }): void;
|
||||
}>();
|
||||
|
||||
// TODO 芋艿
|
||||
/** 属性选择器内部使用的统一数据结构 */
|
||||
interface PropertySelectorItem {
|
||||
identifier: string;
|
||||
|
|
@ -296,7 +297,7 @@ watch(
|
|||
:value="property.identifier"
|
||||
>
|
||||
<div class="py-2px flex w-full items-center justify-between">
|
||||
<span class="text-14px font-500 text-primary flex-1 truncate">
|
||||
<span class="text-14px font-500 flex-1 truncate text-primary">
|
||||
{{ property.name }}
|
||||
</span>
|
||||
<Tag
|
||||
|
|
@ -351,10 +352,10 @@ watch(
|
|||
|
||||
<div class="space-y-8px ml-24px">
|
||||
<div class="gap-8px flex items-start">
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
标识符:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ selectedProperty.identifier }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -363,28 +364,28 @@ watch(
|
|||
v-if="selectedProperty.description"
|
||||
class="gap-8px flex items-start"
|
||||
>
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
描述:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ selectedProperty.description }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedProperty.unit" class="gap-8px flex items-start">
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
单位:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ selectedProperty.unit }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedProperty.range" class="gap-8px flex items-start">
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
取值范围:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ selectedProperty.range }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -397,10 +398,10 @@ watch(
|
|||
"
|
||||
class="gap-8px flex items-start"
|
||||
>
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
访问模式:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ getAccessModeLabel(selectedProperty.accessMode) }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -412,10 +413,10 @@ watch(
|
|||
"
|
||||
class="gap-8px flex items-start"
|
||||
>
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
事件类型:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ getEventTypeLabel(selectedProperty.eventType) }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -427,10 +428,10 @@ watch(
|
|||
"
|
||||
class="gap-8px flex items-start"
|
||||
>
|
||||
<span class="text-12px min-w-60px text-secondary flex-shrink-0">
|
||||
<span class="text-12px min-w-60px flex-shrink-0 text-secondary">
|
||||
调用类型:
|
||||
</span>
|
||||
<span class="text-12px text-primary flex-1">
|
||||
<span class="text-12px flex-1 text-primary">
|
||||
{{ getThingModelServiceCallTypeLabel(selectedProperty.callType) }}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export {default as ThingModelArrayDataSpecs} from './thing-model-array-data-specs.vue';
|
||||
export {default as ThingModelEnumDataSpecs} from './thing-model-enum-data-specs.vue';
|
||||
export {default as ThingModelNumberDataSpecs} from './thing-model-number-data-specs.vue';
|
||||
export {default as ThingModelStructDataSpecs} from './thing-model-struct-data-specs.vue';
|
||||
export { default as ThingModelArrayDataSpecs } from './thing-model-array-data-specs.vue';
|
||||
export { default as ThingModelEnumDataSpecs } from './thing-model-enum-data-specs.vue';
|
||||
export { default as ThingModelNumberDataSpecs } from './thing-model-number-data-specs.vue';
|
||||
export { default as ThingModelStructDataSpecs } from './thing-model-struct-data-specs.vue';
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ function emitSpuChange() {
|
|||
<!-- 添加商品按钮 -->
|
||||
<Tooltip v-if="canAdd" title="选择商品">
|
||||
<div
|
||||
class="hover:border-primary hover:bg-primary/5 flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors"
|
||||
class="flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors hover:border-primary hover:bg-primary/5"
|
||||
@click="handleOpenSpuSelect"
|
||||
>
|
||||
<!-- TODO @AI:还是使用 IconifyIcon:使用自己的 + 图标 -->
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ function validateSku() {
|
|||
/**
|
||||
* 选择时触发
|
||||
*
|
||||
* @param records 传递过来的选中的 sku 是一个数组
|
||||
* @param {object} param0 参数对象
|
||||
* @param {MallSpuApi.Sku[]} param0.records 传递过来的选中的 sku 是一个数组
|
||||
*/
|
||||
function handleSelectionChange({ records }: { records: MallSpuApi.Sku[] }) {
|
||||
emit('selectionChange', records);
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ function emitActivityChange() {
|
|||
>
|
||||
<Tooltip :title="activity.name">
|
||||
<div class="relative h-full w-full">
|
||||
<!-- TODO @芋艿 -->
|
||||
<Image
|
||||
:src="activity.picUrl"
|
||||
class="h-full w-full rounded-lg object-cover"
|
||||
|
|
@ -128,7 +129,7 @@ function emitActivityChange() {
|
|||
<!-- 添加活动按钮 -->
|
||||
<Tooltip v-if="canAdd" title="选择活动">
|
||||
<div
|
||||
class="hover:border-primary hover:bg-primary/5 flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors"
|
||||
class="flex h-[60px] w-[60px] cursor-pointer items-center justify-center rounded-lg border-2 border-dashed transition-colors hover:border-primary hover:bg-primary/5"
|
||||
@click="handleOpenActivitySelect"
|
||||
>
|
||||
<PlusOutlined class="text-xl text-gray-400" />
|
||||
|
|
|
|||
|
|
@ -99,8 +99,8 @@ function handleAppLinkSelected(appLink: AppLink) {
|
|||
/**
|
||||
* 处理右侧链接列表滚动
|
||||
*
|
||||
* @param {object} param0 滚动事件参数
|
||||
* @param {number} param0.scrollTop 滚动条的位置
|
||||
* @param {Event} event 滚动事件
|
||||
* @param {number} event.target.scrollTop 滚动条的位置
|
||||
*/
|
||||
function handleScroll(event: Event) {
|
||||
const scrollTop = (event.target as HTMLDivElement).scrollTop;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ defineProps<{ property: ImageBarProperty }>();
|
|||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="bg-card flex h-12 items-center justify-center"
|
||||
class="flex h-12 items-center justify-center bg-card"
|
||||
v-if="!property.imgUrl"
|
||||
>
|
||||
<IconifyIcon icon="lucide:image" class="text-3xl text-gray-600" />
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ function calculateWidth() {
|
|||
ref="containerRef"
|
||||
>
|
||||
<div
|
||||
class="bg-card relative box-content flex flex-row flex-wrap overflow-hidden"
|
||||
class="relative box-content flex flex-row flex-wrap overflow-hidden bg-card"
|
||||
:style="{
|
||||
...calculateSpace(index),
|
||||
...calculateWidth(),
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ function calculateWidth() {
|
|||
borderBottomLeftRadius: `${property.borderRadiusBottom}px`,
|
||||
borderBottomRightRadius: `${property.borderRadiusBottom}px`,
|
||||
}"
|
||||
class="bg-card relative box-content flex flex-row flex-wrap overflow-hidden"
|
||||
class="relative box-content flex flex-row flex-wrap overflow-hidden bg-card"
|
||||
>
|
||||
<!-- 角标 -->
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ function calculateWidth() {
|
|||
ref="containerRef"
|
||||
>
|
||||
<div
|
||||
class="bg-card relative box-content flex flex-row flex-wrap overflow-hidden"
|
||||
class="relative box-content flex flex-row flex-wrap overflow-hidden bg-card"
|
||||
:style="{
|
||||
...calculateSpace(index),
|
||||
...calculateWidth(),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ defineProps<{ property: UserCardProperty }>();
|
|||
</div>
|
||||
<IconifyIcon icon="tdesign:qrcode" :size="20" />
|
||||
</div>
|
||||
<div class="bg-card flex items-center justify-between px-5 py-2 text-xs">
|
||||
<div class="flex items-center justify-between bg-card px-5 py-2 text-xs">
|
||||
<span class="text-orange-500">点击绑定手机号</span>
|
||||
<span class="rounded-lg bg-orange-500 px-2 py-1 text-white">
|
||||
去绑定
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ onMounted(() => {
|
|||
<template>
|
||||
<Page auto-content-height>
|
||||
<!-- 顶部:工具栏 -->
|
||||
<Row class="bg-card flex max-h-12 rounded-lg">
|
||||
<Row class="flex max-h-12 rounded-lg bg-card">
|
||||
<!-- 左侧操作区 -->
|
||||
<Col :span="8">
|
||||
<slot name="toolBarLeft"></slot>
|
||||
|
|
@ -350,7 +350,7 @@ onMounted(() => {
|
|||
<!-- 手机顶部 -->
|
||||
<div class="mx-auto flex w-96 flex-col">
|
||||
<!-- 手机顶部状态栏 -->
|
||||
<img alt="" class="bg-card h-6" :src="statusBarImg" />
|
||||
<img alt="" class="h-6 bg-card" :src="statusBarImg" />
|
||||
<!-- 手机顶部导航栏 -->
|
||||
<ComponentContainer
|
||||
v-if="showNavigationBar"
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ const handleDelete = function (index: number) {
|
|||
<div class="mb-1 flex flex-col gap-1 rounded border border-gray-200 p-2">
|
||||
<!-- 操作按钮区 -->
|
||||
<div
|
||||
class="bg-secondary -m-2 mb-1 flex flex-row items-center justify-between rounded-t p-2"
|
||||
class="-m-2 mb-1 flex flex-row items-center justify-between rounded-t bg-secondary p-2"
|
||||
>
|
||||
<Tooltip title="拖动排序">
|
||||
<IconifyIcon
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ function eachCube(callback: (x: number, y: number, cube: Cube) => void) {
|
|||
<td
|
||||
v-for="(cube, col) in rowCubes"
|
||||
:key="col"
|
||||
class="active:bg-primary-200 hover:bg-primary-100 box-border cursor-pointer border text-center align-middle"
|
||||
class="box-border cursor-pointer border text-center align-middle hover:bg-primary-100 active:bg-primary-200"
|
||||
:class="[{ active: cube.active }]"
|
||||
:style="{
|
||||
width: `${cubeSize}px`,
|
||||
|
|
@ -219,7 +219,7 @@ function eachCube(callback: (x: number, y: number, cube: Cube) => void) {
|
|||
<div
|
||||
v-for="(hotArea, index) in hotAreas"
|
||||
:key="index"
|
||||
class="bg-primary-200 border-primary absolute box-border flex items-center justify-center border"
|
||||
class="absolute box-border flex items-center justify-center border border-primary bg-primary-200"
|
||||
:style="{
|
||||
top: `${cubeSize * hotArea.top}px`,
|
||||
left: `${cubeSize * hotArea.left}px`,
|
||||
|
|
@ -232,12 +232,12 @@ function eachCube(callback: (x: number, y: number, cube: Cube) => void) {
|
|||
<!-- 右上角热区删除按钮 -->
|
||||
<div
|
||||
v-if="selectedHotAreaIndex === index && hotArea.width && hotArea.height"
|
||||
class="bg-card absolute -right-2 -top-2 z-[1] size-6 h-4 w-4 items-center rounded-lg"
|
||||
class="absolute -right-2 -top-2 z-[1] size-6 h-4 w-4 items-center rounded-lg bg-card"
|
||||
@click="handleDeleteHotArea(index)"
|
||||
>
|
||||
<IconifyIcon
|
||||
icon="lucide:x"
|
||||
class="bg-primary inset-0 items-center text-white"
|
||||
class="inset-0 items-center bg-primary text-white"
|
||||
/>
|
||||
</div>
|
||||
<span v-if="hotArea.width">
|
||||
|
|
|
|||
|
|
@ -57,10 +57,10 @@ export function isContains(hotArea: Rect, point: Point): boolean {
|
|||
*/
|
||||
export function createRect(a: Point, b: Point): Rect {
|
||||
// 计算矩形的范围
|
||||
let [left, left2] = [a.x, b.x].sort();
|
||||
let [left, left2] = [a.x, b.x].toSorted();
|
||||
left = left ?? 0;
|
||||
left2 = left2 ?? 0;
|
||||
let [top, top2] = [a.y, b.y].sort();
|
||||
let [top, top2] = [a.y, b.y].toSorted();
|
||||
top = top ?? 0;
|
||||
top2 = top2 ?? 0;
|
||||
const right = left2 + 1;
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ onBeforeUnmount(() => {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="bg-background flex flex-shrink-0 flex-col border-r border-gray-200 p-4"
|
||||
class="flex flex-shrink-0 flex-col border-r border-gray-200 bg-background p-4"
|
||||
>
|
||||
<div class="flex h-12 w-full flex-row items-center justify-between">
|
||||
<span class="text-lg font-bold">会话记录</span>
|
||||
|
|
@ -213,7 +213,7 @@ onBeforeUnmount(() => {
|
|||
<ul
|
||||
v-show="showRightMenu"
|
||||
:style="rightMenuStyle"
|
||||
class="bg-background absolute z-[9999] m-0 w-32 list-none rounded-xl p-1 shadow-md"
|
||||
class="absolute z-[9999] m-0 w-32 list-none rounded-xl bg-background p-1 shadow-md"
|
||||
>
|
||||
<li
|
||||
v-show="!rightClickConversation.adminPinned"
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ function pushMessage(message: any) {
|
|||
/** 按照时间倒序,获取消息列表 */
|
||||
const getMessageList0 = computed(() => {
|
||||
// 使用展开运算符创建新数组,避免直接修改原数组
|
||||
return [...messageList.value].sort(
|
||||
return [...messageList.value].toSorted(
|
||||
(a: any, b: any) => a.createTime - b.createTime,
|
||||
);
|
||||
});
|
||||
|
|
@ -261,7 +261,7 @@ function showTime(item: MallKefuMessageApi.Message, index: number) {
|
|||
<template>
|
||||
<div
|
||||
v-if="showMessageList()"
|
||||
class="bg-background flex h-full flex-auto flex-col p-4"
|
||||
class="flex h-full flex-auto flex-col bg-background p-4"
|
||||
>
|
||||
<div class="flex h-full flex-auto flex-shrink-0 flex-col">
|
||||
<div class="flex h-12 w-full flex-row items-center justify-between">
|
||||
|
|
@ -415,7 +415,7 @@ function showTime(item: MallKefuMessageApi.Message, index: number) {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="bg-background relative">
|
||||
<div v-else class="relative bg-background">
|
||||
<Empty description="请选择左侧的一个会话后开始" class="mt-[20%]" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ function formatOrderStatus(order: any) {
|
|||
<div class="flex flex-row text-sm">
|
||||
<div>订单号:</div>
|
||||
<span
|
||||
class="text-primary cursor-pointer hover:underline"
|
||||
class="cursor-pointer text-primary hover:underline"
|
||||
@click="openDetail(getMessageContent.id)"
|
||||
>
|
||||
{{ getMessageContent.no }}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ function handleSelect(item: Emoji) {
|
|||
v-for="(item, index) in emojiList"
|
||||
:key="index"
|
||||
:title="item.name"
|
||||
class="w-1/10 border-primary m-2 flex cursor-pointer items-center justify-center border border-solid p-2"
|
||||
class="w-1/10 m-2 flex cursor-pointer items-center justify-center border border-solid border-primary p-2"
|
||||
@click="handleSelect(item)"
|
||||
>
|
||||
<img :src="item.url" class="size-4" />
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ import { getRangePickerDefaultProps } from '#/utils';
|
|||
|
||||
/** 关联数据 */
|
||||
const userStore = useUserStore();
|
||||
const pickUpStoreList = ref<MallDeliveryPickUpStoreApi.DeliveryPickUpStore[]>([]);
|
||||
const pickUpStoreList = ref<MallDeliveryPickUpStoreApi.DeliveryPickUpStore[]>(
|
||||
[],
|
||||
);
|
||||
getSimpleDeliveryPickUpStoreList().then((res) => {
|
||||
pickUpStoreList.value = res;
|
||||
// 移除自己无法核销的门店
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ const [Modal, modalApi] = useVbenModal({
|
|||
return;
|
||||
}
|
||||
// 加载数据
|
||||
const data = modalApi.getData<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>();
|
||||
const data =
|
||||
modalApi.getData<MallDeliveryPickUpStoreApi.DeliveryPickUpStore>();
|
||||
if (!data || !data.id) {
|
||||
// 初始化地图
|
||||
await initTencentLbsMap();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue