fix: lint

This commit is contained in:
xingyu4j
2026-06-26 18:33:45 +08:00
parent 8c085552f6
commit 68caa04209
41 changed files with 426 additions and 367 deletions

View File

@@ -91,8 +91,7 @@ const handleChange: NonNullable<CascaderProps['onChange']> = (value) => {
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
const areaId = typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
};

View File

@@ -97,11 +97,7 @@ onMounted(async () => {
>
<IconifyIcon icon="lucide:trash" />
</Button>
<Button
class="m-0 p-2"
type="text"
@click="handleButtonClick('more')"
>
<Button class="m-0 p-2" type="text" @click="handleButtonClick('more')">
<IconifyIcon icon="lucide:ellipsis-vertical" />
</Button>
</div>

View File

@@ -1,6 +1,5 @@
<!-- eslint-disable unicorn/no-nested-ternary -->
<!-- eslint-disable prettier/prettier -->
<script lang="ts" setup>
// oxlint-disable unicorn/no-nested-ternary
import { inject, nextTick, onBeforeUnmount, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui';

View File

@@ -205,7 +205,9 @@ const saveConfig = async () => {
(option) => option.key === configForm.value.calledProcessDefinitionKey,
);
currentNode.value.name = nodeName.value!;
if (nodeName.value) {
currentNode.value.name = nodeName.value;
}
if (currentNode.value.childProcessSetting) {
// 1. 是否异步
currentNode.value.childProcessSetting.async = configForm.value.async;
@@ -811,10 +813,7 @@ onMounted(async () => {
trigger: 'change',
}"
>
<InputNumber
v-model:value="multiInstanceSourceNumber"
:min="1"
/>
<InputNumber v-model:value="multiInstanceSourceNumber" :min="1" />
</FormItem>
<FormItem
v-if="

View File

@@ -157,7 +157,7 @@ function deleteHttpResponseSetting(
<IconifyIcon
class="size-4 cursor-pointer text-red-500"
icon="lucide:trash-2"
@click="deleteHttpResponseSetting(setting.response!, index)"
@click="deleteHttpResponseSetting(setting.response, index)"
/>
</div>
</Col>

View File

@@ -158,18 +158,20 @@ const formFieldOptions4Title = computed(() => {
};
});
// 固定添加发起人 ID 字段
cloneFormField.unshift({
label: '流程名称',
value: ProcessVariableEnum.PROCESS_DEFINITION_NAME,
});
cloneFormField.unshift({
label: '发起时间',
value: ProcessVariableEnum.START_TIME,
});
cloneFormField.unshift({
label: '发起人',
value: ProcessVariableEnum.START_USER_ID,
});
cloneFormField.unshift(
{
label: '发起人',
value: ProcessVariableEnum.START_USER_ID,
},
{
label: '发起时间',
value: ProcessVariableEnum.START_TIME,
},
{
label: '流程名称',
value: ProcessVariableEnum.PROCESS_DEFINITION_NAME,
},
);
return cloneFormField;
});
const formFieldOptions4Summary = computed(() => {

View File

@@ -112,11 +112,7 @@ defineExpose({ validate });
class="mb-5"
>
<Select v-model:value="modelData.formId" allow-clear>
<SelectOption
v-for="form in formList"
:key="form.id"
:value="form.id"
>
<SelectOption v-for="form in formList" :key="form.id" :value="form.id">
{{ form.name }}
</SelectOption>
</Select>

View File

@@ -142,7 +142,7 @@ function handleModelSort() {
modelList.value.splice(
newDraggableIndex ?? 0,
0,
modelList.value.splice(oldDraggableIndex ?? 0, 1)[0]!,
modelList.value.splice(oldDraggableIndex ?? 0, 1)[0],
);
}
},

View File

@@ -355,7 +355,8 @@ async function initNextAssigneesFormField() {
node.candidateStrategy) ||
// 情况二:当前节点是审批人自选
(isEmpty(node.candidateUsers) &&
BpmCandidateStrategyEnum.APPROVE_USER_SELECT === node.candidateStrategy)
BpmCandidateStrategyEnum.APPROVE_USER_SELECT ===
node.candidateStrategy)
) {
nextAssigneesActivityNode.value.push(node);
}
@@ -397,7 +398,10 @@ function validateNextAssignees() {
}
// 如果需要自选审批人,则校验每个节点是否都已配置审批人
for (const item of nextAssigneesActivityNode.value) {
if (isEmpty(item.candidateUsers) && isEmpty(approveReasonForm.nextAssignees[item.id])) {
if (
isEmpty(item.candidateUsers) &&
isEmpty(approveReasonForm.nextAssignees[item.id])
) {
message.warning('下一个节点的审批人不能为空!');
return false;
}
@@ -791,9 +795,7 @@ const imagePreviewUrl = ref('');
/** 判断文件是否为图片类型 */
function isImageUrl(url: string) {
return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(
url.split(/[?#]/)[0] || '',
);
return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(url.split(/[?#]/)[0] || '');
}
/** 处理文件预览 */

View File

@@ -425,71 +425,69 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
v-if="shouldShowReasonAndAttachment(task, activity.nodeType)"
class="mt-1 w-full rounded-md bg-gray-100 p-2 text-sm text-gray-500"
>
<div v-if="task.reason">审批意见:{{ task.reason }}</div>
<div
v-if="(task.attachments?.length || 0) > 0"
:class="{
'mt-2 border-t border-dashed border-gray-300 pt-2':
task.reason,
}"
>
<div class="mb-1 text-xs font-semibold text-gray-400">
附件列表:
</div>
<div class="flex flex-col gap-1.5">
<template
v-for="(
attachment, attachmentIndex
) in task.attachments"
:key="attachmentIndex"
>
<div class="flex items-center gap-2">
<IconifyIcon
:icon="
isImageAttachment(attachment)
? 'lucide:image'
: 'lucide:file-text'
"
class="text-gray-400"
/>
<Image
v-if="isImageAttachment(attachment)"
:width="32"
:height="32"
class="rounded border border-solid border-gray-200 object-cover"
:src="attachment"
:preview="{ src: attachment }"
/>
<a
v-else
:href="attachment"
target="_blank"
class="max-w-[240px] truncate text-blue-500 hover:text-blue-600 hover:underline"
:title="getAttachmentName(attachment)"
>
{{ getAttachmentName(attachment) }}
</a>
</div>
</template>
</div>
<div v-if="task.reason">审批意见:{{ task.reason }}</div>
<div
v-if="(task.attachments?.length || 0) > 0"
:class="{
'mt-2 border-t border-dashed border-gray-300 pt-2':
task.reason,
}"
>
<div class="mb-1 text-xs font-semibold text-gray-400">
附件列表:
</div>
<div class="flex flex-col gap-1.5">
<template
v-for="(attachment, attachmentIndex) in task.attachments"
:key="attachmentIndex"
>
<div class="flex items-center gap-2">
<IconifyIcon
:icon="
isImageAttachment(attachment)
? 'lucide:image'
: 'lucide:file-text'
"
class="text-gray-400"
/>
<Image
v-if="isImageAttachment(attachment)"
:width="32"
:height="32"
class="rounded border border-solid border-gray-200 object-cover"
:src="attachment"
:preview="{ src: attachment }"
/>
<a
v-else
:href="attachment"
target="_blank"
class="max-w-[240px] truncate text-blue-500 hover:text-blue-600 hover:underline"
:title="getAttachmentName(attachment)"
>
{{ getAttachmentName(attachment) }}
</a>
</div>
</template>
</div>
</div>
<div
v-if="
task.signPicUrl &&
activity.nodeType === BpmNodeTypeEnum.USER_TASK_NODE
"
class="mt-1 flex w-full items-center rounded-md bg-gray-100 p-2 text-sm text-gray-500"
>
签名:
<Image
class="ml-2"
:width="180"
:height="60"
:src="task.signPicUrl"
:preview="{ src: task.signPicUrl }"
/>
</div>
</div>
<div
v-if="
task.signPicUrl &&
activity.nodeType === BpmNodeTypeEnum.USER_TASK_NODE
"
class="mt-1 flex w-full items-center rounded-md bg-gray-100 p-2 text-sm text-gray-500"
>
签名:
<Image
class="ml-2"
:width="180"
:height="60"
:src="task.signPicUrl"
:preview="{ src: task.signPicUrl }"
/>
</div>
</div>
<!-- 情况二遍历每个审批节点下的【候选的】task 任务 -->

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup>
import type { CardTarget } from '../../../utils/message';
import type { Conversation, FriendLite } from '../../types';
import { computed, ref } from 'vue';
@@ -17,15 +18,14 @@ import {
} from '../../../utils/constants';
import { getConversationKey } from '../../../utils/conversation';
import { buildDefaultGroupName } from '../../../utils/group';
import { type CardTarget, serializeMessage } from '../../../utils/message';
import { serializeMessage } from '../../../utils/message';
import { getGroupDisplayName, isGroupQuit } from '../../../utils/user';
import { useMessageSender } from '../../composables/useMessageSender';
import { FacePicker } from '../../pages/conversation/components/input';
import { useConversationStore } from '../../store/conversationStore';
import { useFriendStore } from '../../store/friendStore';
import { useGroupStore } from '../../store/groupStore';
import { ConversationPickerPanel } from '../picker';
import { FriendPickerPanel } from '../picker';
import { ConversationPickerPanel, FriendPickerPanel } from '../picker';
defineOptions({ name: 'ImRecommendCardDialog' });

View File

@@ -1,29 +1,29 @@
<script lang="ts" setup>
import type { User } from '../../types'
import type { User } from '../../types';
import { computed } from 'vue'
import { computed } from 'vue';
import { Image } from 'ant-design-vue'
import { Image } from 'ant-design-vue';
import { ImFriendAddSource } from '../../../utils/constants'
import { getAvatarBgColor, getAvatarText } from '../../../utils/user'
import { useImUiStore } from '../../store/uiStore'
import { ImFriendAddSource } from '../../../utils/constants';
import { getAvatarBgColor, getAvatarText } from '../../../utils/user';
import { useImUiStore } from '../../store/uiStore';
defineOptions({ name: 'ImUserAvatar', inheritAttrs: false })
defineOptions({ name: 'ImUserAvatar', inheritAttrs: false });
const props = withDefaults(
defineProps<{
addSource?: number // 加好友来源;点头像弹 UserInfoCard 时透传给 FriendAddDialog默认 1=搜索)
addSourceExtra?: string // 加好友来源附加addSource=2群聊时传群名话术拼为「我是 XX 群的 YY」
clickable?: boolean // 是否点击弹出 UserInfoCard默认 true
id?: number | string // 用户 id传了才能点开名片
name?: string // 用户名(色卡文字 + 名片备用)
previewable?: boolean // 是否点头像直接放大预览;开启后忽略 clickable不再弹名片
previewZIndex?: number // 预览层 z-index放在高 z-index 弹层(如 UserInfoCard里时需手动抬高
radius?: string // 圆角,支持 CSS 长度;默认 15% 方块小圆角(参考微信)
size?: number // 尺寸px正方形优先于 width/height
url?: string // 头像图片 URL为空时走色卡文字
user?: User // 额外的用户信息,传了点击就不用现拉接口(弹名片用)
addSource?: number; // 加好友来源;点头像弹 UserInfoCard 时透传给 FriendAddDialog默认 1=搜索)
addSourceExtra?: string; // 加好友来源附加addSource=2群聊时传群名话术拼为「我是 XX 群的 YY」
clickable?: boolean; // 是否点击弹出 UserInfoCard默认 true
id?: number | string; // 用户 id传了才能点开名片
name?: string; // 用户名(色卡文字 + 名片备用)
previewable?: boolean; // 是否点头像直接放大预览;开启后忽略 clickable不再弹名片
previewZIndex?: number; // 预览层 z-index放在高 z-index 弹层(如 UserInfoCard里时需手动抬高
radius?: string; // 圆角,支持 CSS 长度;默认 15% 方块小圆角(参考微信)
size?: number; // 尺寸px正方形优先于 width/height
url?: string; // 头像图片 URL为空时走色卡文字
user?: User; // 额外的用户信息,传了点击就不用现拉接口(弹名片用)
}>(),
{
addSourceExtra: undefined,
@@ -36,60 +36,65 @@ const props = withDefaults(
size: 42,
url: undefined,
user: undefined,
addSource: ImFriendAddSource.SEARCH
}
)
addSource: ImFriendAddSource.SEARCH,
},
);
const uiStore = useImUiStore()
const uiStore = useImUiStore();
const imgStyle = computed(() => ({
width: `${props.size}px`,
height: `${props.size}px`,
borderRadius: props.radius
}))
borderRadius: props.radius,
}));
const textStyle = computed(() => ({
width: `${props.size}px`,
height: `${props.size}px`,
fontSize: `${Math.floor(props.size * (avatarText.value.length > 1 ? 0.34 : 0.42))}px`,
background: textColor.value,
borderRadius: props.radius
}))
borderRadius: props.radius,
}));
/** 色卡首字:中文取 1 个字、英文 / 拉丁取前 2 个字母 */
const avatarText = computed(() => getAvatarText(props.name))
const avatarText = computed(() => getAvatarText(props.name));
/** 色卡底色:按昵称 charCode 哈希取调色板色 */
const textColor = computed(() => getAvatarBgColor(props.name))
const textColor = computed(() => getAvatarBgColor(props.name));
/** 头像点击previewable 走 el-image 预览不弹名片;否则按 user / id 任一入参打开名片 */
function handleClick(e: MouseEvent) {
if (props.previewable) {
return
return;
}
if (!props.clickable) {
return
return;
}
// 情况一:有预传 user 信息:就直接用,省一次接口
if (props.user) {
uiStore.openUserInfoCardAtEvent(props.user, e, props.addSource, props.addSourceExtra)
return
uiStore.openUserInfoCardAtEvent(
props.user,
e,
props.addSource,
props.addSourceExtra,
);
return;
}
// 情况二:无预传 user 信息打开名片传最小必要信息id + 昵称 + 头像),位置在鼠标右侧
const numId = Number(props.id)
const numId = Number(props.id);
if (!numId || numId <= 0) {
return
return;
}
uiStore.openUserInfoCardAtEvent(
{
id: numId,
nickname: props.name,
avatar: props.url
avatar: props.url,
},
e,
props.addSource,
props.addSourceExtra
)
props.addSourceExtra,
);
}
</script>

View File

@@ -1,93 +1,95 @@
<script lang="ts" setup>
import { computed, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import type { UserInfoRelation } from './user-info.vue';
import { getCurrentUserId } from '#/views/im/utils/auth'
import { computed, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import { ImConversationType } from '../../../utils/constants'
import { getFriendDisplayName } from '../../../utils/user'
import { useConversationStore } from '../../store/conversationStore'
import { useFriendStore } from '../../store/friendStore'
import { useImUiStore } from '../../store/uiStore'
import UserInfo, { type UserInfoRelation } from './user-info.vue'
import { getCurrentUserId } from '#/views/im/utils/auth';
defineOptions({ name: 'ImUserInfoCard' })
import { ImConversationType } from '../../../utils/constants';
import { getFriendDisplayName } from '../../../utils/user';
import { useConversationStore } from '../../store/conversationStore';
import { useFriendStore } from '../../store/friendStore';
import { useImUiStore } from '../../store/uiStore';
import UserInfo from './user-info.vue';
const uiStore = useImUiStore()
const conversationStore = useConversationStore()
const friendStore = useFriendStore()
const router = useRouter()
defineOptions({ name: 'ImUserInfoCard' });
const card = computed(() => uiStore.userInfoCard)
const user = computed(() => card.value.user)
const uiStore = useImUiStore();
const conversationStore = useConversationStore();
const friendStore = useFriendStore();
const router = useRouter();
const card = computed(() => uiStore.userInfoCard);
const user = computed(() => card.value.user);
const isSelf = computed(() => {
const myId = getCurrentUserId()
return !!user.value?.id && user.value.id === myId
})
const myId = getCurrentUserId();
return !!user.value?.id && user.value.id === myId;
});
const isActiveFriend = computed(() => {
if (!user.value?.id || isSelf.value) {
return false
return false;
}
return friendStore.isActiveFriend(user.value.id)
})
return friendStore.isActiveFriend(user.value.id);
});
const relation = computed<UserInfoRelation>(() => {
if (!user.value) {
return 'readonly'
return 'readonly';
}
if (isSelf.value) {
return 'self'
return 'self';
}
if (isActiveFriend.value) {
return 'friend'
return 'friend';
}
return 'stranger'
})
return 'stranger';
});
const remark = computed(() => {
if (!isActiveFriend.value || !user.value?.id) {
return undefined
return undefined;
}
return friendStore.getFriend(user.value.id)?.displayName || ''
})
return friendStore.getFriend(user.value.id)?.displayName || '';
});
/** 关闭名片:点击遮罩 / Esc / UserInfo 抛上来的删除成功事件 */
function handleClose() {
uiStore.closeUserInfoCard()
uiStore.closeUserInfoCard();
}
/** 键盘事件Esc 键关闭名片 */
function handleKeydown(e: KeyboardEvent) {
if (e.key === 'Escape' && card.value.show) {
handleClose()
handleClose();
}
}
onMounted(() => window.addEventListener('keydown', handleKeydown))
onUnmounted(() => window.removeEventListener('keydown', handleKeydown))
onMounted(() => window.addEventListener('keydown', handleKeydown));
onUnmounted(() => window.removeEventListener('keydown', handleKeydown));
/** 发消息UserInfo 抛上来的"发消息",由本组件接力做 openConversation + 跳消息 Tab + 关浮层 */
function handleSendMessage() {
if (!user.value) {
return
return;
}
// 取 friendStore 里的最新备注 / 免打扰,避免新建会话用过期数据
const friend = friendStore.getFriend(user.value.id)
const friend = friendStore.getFriend(user.value.id);
const conversationName = friend
? getFriendDisplayName(friend)
: user.value.nickname || ''
: user.value.nickname || '';
conversationStore.openConversation(
user.value.id,
ImConversationType.PRIVATE,
conversationName,
user.value.avatar || '',
{ silent: !!friend?.silent }
)
{ silent: !!friend?.silent },
);
// 跳转会话 Tab如果不在的话并且不管当前路由是啥都先切到会话列表页
if (router.currentRoute.value.name !== 'ImHomeConversation') {
router.push({ name: 'ImHomeConversation' })
router.push({ name: 'ImHomeConversation' });
}
uiStore.closeUserInfoCard()
uiStore.closeUserInfoCard();
}
</script>
@@ -99,10 +101,14 @@ function handleSendMessage() {
- 关系态由 isSelf / isActiveFriend 派生 relation prop 透到 UserInfo删除 / 加好友 / 备注落库都在 UserInfo 内闭环
-->
<teleport to="body">
<div v-if="card.show" class="fixed inset-0 z-9998" @click.self="handleClose">
<div
v-if="card.show"
class="fixed inset-0 z-9998"
@click.self="handleClose"
>
<div
class="fixed w-80 p-4 bg-[var(--ant-color-bg-elevated)] rounded-md shadow-xl"
:style="{ left: `${card.position.x }px`, top: `${card.position.y }px` }"
:style="{ left: `${card.position.x}px`, top: `${card.position.y}px` }"
@click.stop
>
<UserInfo

View File

@@ -1,59 +1,68 @@
<script lang="ts" setup>
import type { User } from '../../types'
import type { User } from '../../types';
import { computed, h, nextTick, ref, watch } from 'vue'
import type { SystemUserApi } from '#/api/system/user';
import { confirm } from '@vben/common-ui'
import { DICT_TYPE } from '@vben/constants'
import { getDictLabel } from '@vben/hooks'
import { IconifyIcon as Icon } from '@vben/icons'
import { computed, h, nextTick, ref, watch } from 'vue';
import { Button, Checkbox, Dropdown, Input, Menu, message } from 'ant-design-vue'
import { confirm } from '@vben/common-ui';
import { DICT_TYPE } from '@vben/constants';
import { getDictLabel } from '@vben/hooks';
import { IconifyIcon as Icon } from '@vben/icons';
import { getSimpleUser, type SystemUserApi } from '#/api/system/user'
import { formatDate } from '#/views/im/utils/time'
import {
Button,
Checkbox,
Dropdown,
Input,
Menu,
message,
} from 'ant-design-vue';
import { ImFriendAddSource } from '../../../utils/constants'
import { toUserCardTarget } from '../../../utils/message'
import { getGenderColor, getGenderIcon } from '../../../utils/user'
import { useFriendStore } from '../../store/friendStore'
import { FriendAddDialog } from '../friend'
import RecommendCardDialog from './recommend-card-dialog.vue'
import UserAvatar from './user-avatar.vue'
import { getSimpleUser } from '#/api/system/user';
import { formatDate } from '#/views/im/utils/time';
defineOptions({ name: 'ImUserInfo' })
import { ImFriendAddSource } from '../../../utils/constants';
import { toUserCardTarget } from '../../../utils/message';
import { getGenderColor, getGenderIcon } from '../../../utils/user';
import { useFriendStore } from '../../store/friendStore';
import { FriendAddDialog } from '../friend';
import RecommendCardDialog from './recommend-card-dialog.vue';
import UserAvatar from './user-avatar.vue';
defineOptions({ name: 'ImUserInfo' });
const props = withDefaults(
defineProps<{
/** 加好友来源;默认 SEARCH参见 ImFriendAddSource */
addSource?: number
addSource?: number;
/** 来源附带信息addSource=GROUP群聊时传群名用于「我是 XX 群的 YY」预填话术 */
addSourceExtra?: string
addSourceExtra?: string;
/** 备注:仅 relation=friend 时有效;空串 → 显示"添加备注"占位 */
displayName?: string
displayName?: string;
/** UserAvatar 预览层 z-index放在高 z-index 浮层(如 UserInfoCard里需手动抬高 */
previewZIndex?: number
relation?: UserInfoRelation
previewZIndex?: number;
relation?: UserInfoRelation;
/** 起手用户:至少要有 id性别 / 部门由组件按 id 懒拉合并补齐 */
user: null | User
user: null | User;
}>(),
{
addSource: ImFriendAddSource.SEARCH,
addSourceExtra: '',
displayName: '',
previewZIndex: 2000,
relation: 'readonly'
}
)
relation: 'readonly',
},
);
const emit = defineEmits<{
/** 用户点"发消息":导航 / 关浮层等场景相关动作由父级承担(比如 UserInfoCard 要 close */
chat: [user: User]
chat: [user: User];
/** 删除联系人成功后通知父级confirm + 调 store 都在本组件内做完):父级关浮层 / 清选中等 */
deleted: [user: User]
deleted: [user: User];
/** 备注落库成功后通知父级,用于同步父级持有的本地 FriendLite / Friend 副本(如 contact 页的 selection */
saved: [value: string]
}>()
saved: [value: string];
}>();
/**
* 关系态:决定备注行 / 右上 "..." 菜单 / 底部动作区的内容
@@ -62,31 +71,35 @@ const emit = defineEmits<{
* - self: 单按钮"不能和自己聊天" disabled
* - readonly: 不渲染备注 / 菜单 / 动作区,仅展示头部信息
*/
export type UserInfoRelation = 'friend' | 'readonly' | 'self' | 'stranger'
export type UserInfoRelation = 'friend' | 'readonly' | 'self' | 'stranger';
const friendStore = useFriendStore()
const friendStore = useFriendStore();
const full = ref<null | User>(props.user) // 起手 user + getSimpleUser 合并后的完整对象(性别 / 部门补齐用)
const full = ref<null | User>(props.user); // 起手 user + getSimpleUser 合并后的完整对象(性别 / 部门补齐用)
/** 主标题:备注优先(好友场景),其次原昵称 */
const headerName = computed(() => props.displayName || full.value?.nickname || '')
const headerName = computed(
() => props.displayName || full.value?.nickname || '',
);
const deptText = computed(() => full.value?.deptName || '-')
const deptText = computed(() => full.value?.deptName || '-');
const genderIcon = computed(() => getGenderIcon(full.value?.sex))
const genderColor = computed(() => getGenderColor(full.value?.sex))
const genderIcon = computed(() => getGenderIcon(full.value?.sex));
const genderColor = computed(() => getGenderColor(full.value?.sex));
/** 好友关系记录:来源 / 添加时间 / 是否拉黑从这里取(仅 friend 态下才有意义) */
const friendInfo = computed(() =>
props.user?.id ? friendStore.getFriend(props.user.id) : undefined
)
props.user?.id ? friendStore.getFriend(props.user.id) : undefined,
);
/** 是否已拉黑:菜单项「加入黑名单 / 移出黑名单」按这个切换 */
const isBlocked = computed(() => !!friendInfo.value?.blocked)
const isBlocked = computed(() => !!friendInfo.value?.blocked);
const editingRemark = ref(false) // 备注内联编辑editingRemark 控制输入态user 切换时由下面的 watch 复位避免脏态泄漏
const remarkInput = ref('')
const remarkInputRef = ref<null | { focus: () => void; select?: () => void }>(null)
const editingRemark = ref(false); // 备注内联编辑editingRemark 控制输入态user 切换时由下面的 watch 复位避免脏态泄漏
const remarkInput = ref('');
const remarkInputRef = ref<null | { focus: () => void; select?: () => void }>(
null,
);
/**
* user.id 变化的统一处理:
@@ -97,30 +110,30 @@ const remarkInputRef = ref<null | { focus: () => void; select?: () => void }>(nu
watch(
() => props.user?.id,
async (id) => {
full.value = props.user
editingRemark.value = false
full.value = props.user;
editingRemark.value = false;
if (!id) {
return
return;
}
const data = (await getSimpleUser(id)) as User
const data = (await getSimpleUser(id)) as User;
if (props.user?.id !== id) {
return
return;
}
full.value = { ...props.user, ...data }
full.value = { ...props.user, ...data };
},
{ immediate: true }
)
{ immediate: true },
);
/** 备注行点击:进编辑态 + 把当前备注灌进输入框,下一帧把焦点 / 全选交给 el-input */
async function handleRowClick() {
if (editingRemark.value) {
return
return;
}
remarkInput.value = props.displayName || ''
editingRemark.value = true
await nextTick()
remarkInputRef.value?.focus()
remarkInputRef.value?.select?.()
remarkInput.value = props.displayName || '';
editingRemark.value = true;
await nextTick();
remarkInputRef.value?.focus();
remarkInputRef.value?.select?.();
}
/**
@@ -131,61 +144,61 @@ async function handleRowClick() {
*/
async function saveRemark() {
if (!editingRemark.value) {
return
return;
}
const userId = props.user?.id
const userId = props.user?.id;
if (!userId) {
editingRemark.value = false
return
editingRemark.value = false;
return;
}
const next = remarkInput.value.trim()
editingRemark.value = false
const next = remarkInput.value.trim();
editingRemark.value = false;
if (next === (props.displayName || '')) {
return
return;
}
await friendStore.setFriendDisplayName(userId, next)
message.success('已更新备注')
emit('saved', next)
await friendStore.setFriendDisplayName(userId, next);
message.success('已更新备注');
emit('saved', next);
}
function cancelEditRemark() {
editingRemark.value = false
editingRemark.value = false;
}
/** 发消息:导航 / 关浮层这些"业务侧"动作交给父级,本组件只负责通知 */
function handleChat() {
if (!props.user) {
return
return;
}
emit('chat', props.user)
emit('chat', props.user);
}
/** 占位提示:语音 / 视频聊天能力尚未接入,先以"开发中"友好提示 */
function handleComingSoon(featureName: string) {
message.info(`${featureName} 功能开发中`)
message.info(`${featureName} 功能开发中`);
}
// ==================== 添加好友 / 删除好友 ====================
const friendAddDialogRef = ref<InstanceType<typeof FriendAddDialog>>() // 加好友弹窗 refhandleAddFriend 调 open({ presetUser, addSource, addSourceExtra }) 触发
const friendAddDialogRef = ref<InstanceType<typeof FriendAddDialog>>(); // 加好友弹窗 refhandleAddFriend 调 open({ presetUser, addSource, addSourceExtra }) 触发
const recommendDialogRef = ref<InstanceType<typeof RecommendCardDialog>>() // 推荐名片弹窗 refhandleRecommend 调用 open({ target }) 打开
const recommendDialogRef = ref<InstanceType<typeof RecommendCardDialog>>(); // 推荐名片弹窗 refhandleRecommend 调用 open({ target }) 打开
/** 把他推荐给朋友:弹 RecommendCardDialog 选目标会话 */
function handleRecommend() {
if (!props.user?.id) {
return
return;
}
const target = toUserCardTarget(full.value)
const target = toUserCardTarget(full.value);
if (!target) {
return
return;
}
recommendDialogRef.value?.open({ target })
recommendDialogRef.value?.open({ target });
}
/** 加为好友:弹 FriendAddDialog带预填用户让用户填申请理由 + 备注后再发申请 */
function handleAddFriend() {
if (!props.user?.id) {
return
return;
}
const presetUser: SystemUserApi.UserSimple = {
id: props.user.id,
@@ -193,46 +206,49 @@ function handleAddFriend() {
avatar: props.user.avatar,
sex: props.user.sex,
deptId: props.user.deptId,
deptName: props.user.deptName
} as SystemUserApi.UserSimple
deptName: props.user.deptName,
} as SystemUserApi.UserSimple;
friendAddDialogRef.value?.open({
presetUser,
addSource: props.addSource,
addSourceExtra: props.addSourceExtra
})
addSourceExtra: props.addSourceExtra,
});
}
/** 加入黑名单confirm → friendStore.blockFriend后端 FRIEND_BLOCK 推到时由 dispatcher 同步多端 */
async function handleBlock() {
if (!props.user?.id) {
return
return;
}
const target = props.user
const target = props.user;
try {
await confirm(`确定将「${target.nickname || ''}」加入黑名单吗?`, '加入黑名单')
await confirm(
`确定将「${target.nickname || ''}」加入黑名单吗?`,
'加入黑名单',
);
} catch {
return
return;
}
await friendStore.blockFriend(target.id)
message.success('已加入黑名单')
await friendStore.blockFriend(target.id);
message.success('已加入黑名单');
}
/** 移出黑名单:操作温和不弹 confirm后端 FRIEND_UNBLOCK 推到时由 dispatcher 同步多端 */
async function handleUnblock() {
if (!props.user?.id) {
return
return;
}
await friendStore.unblockFriend(props.user.id)
message.success('已移出黑名单')
await friendStore.unblockFriend(props.user.id);
message.success('已移出黑名单');
}
/** 删除联系人:弹自定义确认(含「同时清空聊天记录」选项)→ friendStore.deleteFriend → 通知父级关浮层 / 清选中 */
async function handleDeleteFriend() {
if (!props.user?.id) {
return
return;
}
const target = props.user
const clearConversation = ref(true)
const target = props.user;
const clearConversation = ref(true);
try {
await confirm({
cancelText: '取消',
@@ -244,21 +260,21 @@ async function handleDeleteFriend() {
{
checked: clearConversation.value,
'onUpdate:checked': (value: boolean) => {
clearConversation.value = value
}
clearConversation.value = value;
},
},
() => '同时清空聊天记录'
)
() => '同时清空聊天记录',
),
]),
icon: 'warning',
title: '删除联系人'
})
title: '删除联系人',
});
} catch {
return
return;
}
await friendStore.deleteFriend(target.id, clearConversation.value)
message.success('已删除好友')
emit('deleted', target)
await friendStore.deleteFriend(target.id, clearConversation.value);
message.success('已删除好友');
emit('deleted', target);
}
</script>
@@ -297,19 +313,31 @@ async function handleDeleteFriend() {
class="flex-shrink-0"
/>
</div>
<div class="mt-2 space-y-1 text-13px text-[var(--ant-color-text-secondary)]">
<div
class="mt-2 space-y-1 text-13px text-[var(--ant-color-text-secondary)]"
>
<!-- 仅当备注已设时展示昵称副行未设置时主标题就是 nickname避免重复 -->
<div v-if="displayName" class="truncate">昵称{{ full?.nickname }}</div>
<div v-if="displayName" class="truncate">
昵称{{ full?.nickname }}
</div>
<div class="truncate">部门{{ deptText }}</div>
</div>
</div>
<!-- 右上 "..." 菜单 friend 态展示加入/移出黑名单 + 删除联系人 -->
<div v-if="relation === 'friend'" class="flex-shrink-0">
<Dropdown :trigger="['click']" placement="bottomRight" overlay-class-name="im-user-info__more-menu">
<Dropdown
:trigger="['click']"
placement="bottomRight"
overlay-class-name="im-user-info__more-menu"
>
<div
class="flex items-center justify-center w-7 h-7 rounded cursor-pointer hover:bg-[var(--ant-color-fill-secondary)]"
>
<Icon icon="ep:more-filled" :size="18" class="text-[var(--ant-color-text-secondary)]" />
<Icon
icon="ep:more-filled"
:size="18"
class="text-[var(--ant-color-text-secondary)]"
/>
</div>
<template #overlay>
<Menu>
@@ -317,9 +345,11 @@ async function handleDeleteFriend() {
<Menu.Item @click="handleRecommend">把他推荐给朋友</Menu.Item>
<!-- 拉黑 / 移出黑名单 friendInfo.blocked 切换文案 -->
<Menu.Item v-if="!isBlocked" divided @click="handleBlock">
加入黑名单
</Menu.Item>
<Menu.Item v-else divided @click="handleUnblock">移出黑名单</Menu.Item>
加入黑名单
</Menu.Item>
<Menu.Item v-else divided @click="handleUnblock">
移出黑名单
</Menu.Item>
<Menu.Item divided @click="handleDeleteFriend">
<span class="text-[var(--ant-color-error)]">删除联系人</span>
</Menu.Item>
@@ -341,7 +371,11 @@ async function handleDeleteFriend() {
"
@click="handleRowClick"
>
<span class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]">备注</span>
<span
class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]"
>
备注
</span>
<Input
v-if="editingRemark"
ref="remarkInputRef"
@@ -378,14 +412,30 @@ async function handleDeleteFriend() {
<!-- ==================== 更多信息来源 / 添加时间对齐微信朋友资料分块 ==================== -->
<template v-if="friendInfo?.addSource || friendInfo?.addTime">
<div class="my-4 h-px bg-[var(--ant-color-border-secondary)]"></div>
<div v-if="friendInfo?.addSource" class="flex gap-5 items-center px-1.5 py-1.5 text-sm">
<span class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]">来源</span>
<div
v-if="friendInfo?.addSource"
class="flex gap-5 items-center px-1.5 py-1.5 text-sm"
>
<span
class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]"
>
来源
</span>
<span class="flex-1 min-w-0 truncate text-[var(--ant-color-text)]">
{{ getDictLabel(DICT_TYPE.IM_FRIEND_ADD_SOURCE, friendInfo.addSource) }}
{{
getDictLabel(DICT_TYPE.IM_FRIEND_ADD_SOURCE, friendInfo.addSource)
}}
</span>
</div>
<div v-if="friendInfo?.addTime" class="flex gap-5 items-center px-1.5 py-1.5 text-sm">
<span class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]">添加时间</span>
<div
v-if="friendInfo?.addTime"
class="flex gap-5 items-center px-1.5 py-1.5 text-sm"
>
<span
class="flex-shrink-0 w-16 whitespace-nowrap text-[var(--ant-color-text-secondary)]"
>
添加时间
</span>
<span class="flex-1 min-w-0 truncate text-[var(--ant-color-text)]">
{{ formatDate(new Date(friendInfo.addTime), 'YYYY-MM-DD') }}
</span>

View File

@@ -104,7 +104,7 @@ function makeTemplate() {
const rule = ref('')
const option = ref('')
const init = () => {
rule.value = formCreate.parseJson('${formCreate.toJson(rule).replaceAll('\\', '\\\\')}')
rule.value = formCreate.parseJson('${formCreate.toJson(rule).replaceAll('\\', String.raw`\\`)}')
option.value = formCreate.parseJson('${JSON.stringify(opt, null, 2)}')
}
const onSubmit = (formData) => {

View File

@@ -79,7 +79,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
},
trigger: (values, formApi) => {
if (values.deviceId !== undefined) {
void formApi.setFieldValue('deviceId', undefined);
formApi.setFieldValue('deviceId', undefined);
}
},
},

View File

@@ -45,7 +45,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
productSpus.value = [];
@@ -54,7 +54,7 @@ watch(
// 只有商品发生变化时才重新查询
if (
productSpus.value.length === 0 ||
productSpus.value.some((spu) => !ids.includes(spu.id!))
productSpus.value.some((spu) => !ids.includes(spu.id))
) {
productSpus.value = await getSpuDetailList(ids);
}
@@ -88,7 +88,7 @@ function emitSpuChange() {
} else {
emit(
'update:modelValue',
productSpus.value.map((spu) => spu.id!),
productSpus.value.map((spu) => spu.id),
);
emit('change', productSpus.value);
}

View File

@@ -46,7 +46,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
activityList.value = [];
@@ -55,7 +55,7 @@ watch(
// 只有活动发生变化时才重新查询
if (
activityList.value.length === 0 ||
activityList.value.some((activity) => !ids.includes(activity.id!))
activityList.value.some((activity) => !ids.includes(activity.id))
) {
activityList.value = await getCombinationActivityListByIds(ids);
}
@@ -94,7 +94,7 @@ function emitActivityChange() {
} else {
emit(
'update:modelValue',
activityList.value.map((activity) => activity.id!),
activityList.value.map((activity) => activity.id),
);
emit('change', activityList.value);
}

View File

@@ -21,9 +21,10 @@ const spuList = ref<MallSpuApi.Spu[]>([]);
watch(
() => props.property.spuIds,
async () => {
spuList.value = props.property.spuIds.length > 0
? await getSpuDetailList(props.property.spuIds)
: [];
spuList.value =
props.property.spuIds.length > 0
? await getSpuDetailList(props.property.spuIds)
: [];
},
{
immediate: true,

View File

@@ -1,3 +1,4 @@
// oxlint-disable typescript/require-array-sort-compare
/** 坐标点 */
export interface Point {
x: number;

View File

@@ -45,7 +45,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
pointActivityList.value = [];
@@ -54,7 +54,7 @@ watch(
// 只有活动发生变化时才重新查询
if (
pointActivityList.value.length === 0 ||
pointActivityList.value.some((activity) => !ids.includes(activity.id!))
pointActivityList.value.some((activity) => !ids.includes(activity.id))
) {
pointActivityList.value = await getPointActivityListByIds(ids);
}
@@ -95,7 +95,7 @@ function emitActivityChange() {
} else {
emit(
'update:modelValue',
pointActivityList.value.map((activity) => activity.id!),
pointActivityList.value.map((activity) => activity.id),
);
emit('change', pointActivityList.value);
}

View File

@@ -45,7 +45,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
activityList.value = [];
@@ -54,7 +54,7 @@ watch(
// 只有活动发生变化时才重新查询
if (
activityList.value.length === 0 ||
activityList.value.some((activity) => !ids.includes(activity.id!))
activityList.value.some((activity) => !ids.includes(activity.id))
) {
activityList.value = await getSeckillActivityListByIds(ids as number[]);
}
@@ -93,7 +93,7 @@ function emitActivityChange() {
} else {
emit(
'update:modelValue',
activityList.value.map((activity) => activity.id!),
activityList.value.map((activity) => activity.id),
);
emit('change', activityList.value);
}

View File

@@ -57,7 +57,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区,避免旧库区条件残留
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -207,7 +207,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -225,7 +225,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库或库区切换时清空库位
trigger: (values, formApi) => {
if (values.areaId !== undefined) {
void formApi.setFieldValue('areaId', undefined);
formApi.setFieldValue('areaId', undefined);
}
},
},

View File

@@ -26,7 +26,9 @@ function normalizeTimestampPickerValue(value: any, valueFormat: unknown): any {
return value;
}
if (Array.isArray(value)) {
return value.map((item) => normalizeTimestampPickerValue(item, valueFormat));
return value.map((item) =>
normalizeTimestampPickerValue(item, valueFormat),
);
}
return typeof value === 'number' ? String(value) : value;
}

View File

@@ -91,8 +91,7 @@ const handleChange: NonNullable<CascaderProps['onChange']> = (value) => {
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
const areaId = typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
};

View File

@@ -1,6 +1,5 @@
<!-- eslint-disable unicorn/no-nested-ternary -->
<!-- eslint-disable prettier/prettier -->
<script lang="ts" setup>
// oxlint-disable unicorn/no-nested-ternary
import { inject, nextTick, onBeforeUnmount, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui';

View File

@@ -786,10 +786,7 @@ onMounted(async () => {
},
]"
>
<InputNumber
v-model:value="multiInstanceSourceNumber"
:min="1"
/>
<InputNumber v-model:value="multiInstanceSourceNumber" :min="1" />
</FormItem>
<FormItem
v-if="

View File

@@ -158,18 +158,20 @@ const formFieldOptions4Title = computed(() => {
};
});
// 固定添加发起人 ID 字段
cloneFormField.unshift({
label: '流程名称',
value: ProcessVariableEnum.PROCESS_DEFINITION_NAME,
});
cloneFormField.unshift({
label: '发起时间',
value: ProcessVariableEnum.START_TIME,
});
cloneFormField.unshift({
label: '发起人',
value: ProcessVariableEnum.START_USER_ID,
});
cloneFormField.unshift(
{
label: '发起人',
value: ProcessVariableEnum.START_USER_ID,
},
{
label: '发起时间',
value: ProcessVariableEnum.START_TIME,
},
{
label: '流程名称',
value: ProcessVariableEnum.PROCESS_DEFINITION_NAME,
},
);
return cloneFormField;
});
const formFieldOptions4Summary = computed(() => {

View File

@@ -336,7 +336,8 @@ async function initNextAssigneesFormField() {
node.candidateStrategy) ||
// 情况二:当前节点是审批人自选
(isEmpty(node.candidateUsers) &&
BpmCandidateStrategyEnum.APPROVE_USER_SELECT === node.candidateStrategy)
BpmCandidateStrategyEnum.APPROVE_USER_SELECT ===
node.candidateStrategy)
) {
nextAssigneesActivityNode.value.push(node);
}
@@ -378,7 +379,10 @@ function validateNextAssignees() {
}
// 如果需要自选审批人,则校验每个节点是否都已配置审批人
for (const item of nextAssigneesActivityNode.value) {
if (isEmpty(item.candidateUsers) && isEmpty(approveReasonForm.nextAssignees[item.id])) {
if (
isEmpty(item.candidateUsers) &&
isEmpty(approveReasonForm.nextAssignees[item.id])
) {
message.warning('下一个节点的审批人不能为空!');
return false;
}

View File

@@ -79,7 +79,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
},
trigger: (values, formApi) => {
if (values.deviceId !== undefined) {
void formApi.setFieldValue('deviceId', undefined);
formApi.setFieldValue('deviceId', undefined);
}
},
},

View File

@@ -45,7 +45,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
productSpus.value = [];
@@ -54,7 +54,7 @@ watch(
// 只有商品发生变化时才重新查询
if (
productSpus.value.length === 0 ||
productSpus.value.some((spu) => !ids.includes(spu.id!))
productSpus.value.some((spu) => !ids.includes(spu.id))
) {
productSpus.value = await getSpuDetailList(ids);
}
@@ -88,7 +88,7 @@ function emitSpuChange() {
} else {
emit(
'update:modelValue',
productSpus.value.map((spu) => spu.id!),
productSpus.value.map((spu) => spu.id),
);
emit('change', productSpus.value);
}

View File

@@ -46,7 +46,7 @@ const canAdd = computed(() => {
watch(
() => props.modelValue,
async (newValue) => {
// eslint-disable-next-line unicorn/no-nested-ternary
// oxlint-disable-next-line unicorn/no-nested-ternary
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
if (ids.length === 0) {
activityList.value = [];
@@ -55,7 +55,7 @@ watch(
// 只有活动发生变化时才重新查询
if (
activityList.value.length === 0 ||
activityList.value.some((activity) => !ids.includes(activity.id!))
activityList.value.some((activity) => !ids.includes(activity.id))
) {
activityList.value = await getCombinationActivityListByIds(ids);
}
@@ -94,7 +94,7 @@ function emitActivityChange() {
} else {
emit(
'update:modelValue',
activityList.value.map((activity) => activity.id!),
activityList.value.map((activity) => activity.id),
);
emit('change', activityList.value);
}

View File

@@ -187,7 +187,9 @@ function getTreeNode(slotProps: unknown) {
<FormItem
:label="getTreeNode(node).label"
:name="getTreeNode(node).prop"
:label-col="{ flex: getTreeNode(node).children ? '80px' : '58px' }"
:label-col="{
flex: getTreeNode(node).children ? '80px' : '58px',
}"
class="mb-0 w-full"
>
<Row>

View File

@@ -1,3 +1,4 @@
// oxlint-disable typescript/require-array-sort-compare
/** 坐标点 */
export interface Point {
x: number;

View File

@@ -57,7 +57,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区,避免旧库区条件残留
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -207,7 +207,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -225,7 +225,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库或库区切换时清空库位
trigger: (values, formApi) => {
if (values.areaId !== undefined) {
void formApi.setFieldValue('areaId', undefined);
formApi.setFieldValue('areaId', undefined);
}
},
},

View File

@@ -85,8 +85,7 @@ function handleChange(value?: CascaderValue | null) {
const path = Array.isArray(value[0]) ? value[0] : value;
const leafValue = path.at(-1);
const areaId =
typeof leafValue === 'number' ? leafValue : Number(leafValue);
const areaId = typeof leafValue === 'number' ? leafValue : Number(leafValue);
emit('update:modelValue', Number.isNaN(areaId) ? undefined : areaId);
}

View File

@@ -1,6 +1,5 @@
<!-- eslint-disable unicorn/no-nested-ternary -->
<!-- eslint-disable prettier/prettier -->
<script lang="ts" setup>
// oxlint-disable unicorn/no-nested-ternary
import { inject, nextTick, onBeforeUnmount, ref, watch } from 'vue';
import { useVbenModal } from '@vben/common-ui';

View File

@@ -700,7 +700,7 @@ onMounted(() => {
v-for="item in roleOptions"
:key="item.id"
:label="item.name"
:value="item.id!"
:value="item.id"
/>
</ElSelect>
</ElFormItem>
@@ -738,7 +738,7 @@ onMounted(() => {
v-for="item in postOptions"
:key="item.id"
:label="item.name"
:value="item.id!"
:value="item.id"
/>
</ElSelect>
</ElFormItem>
@@ -752,7 +752,7 @@ onMounted(() => {
v-for="item in userOptions"
:key="item.id"
:label="item.nickname"
:value="item.id!"
:value="item.id"
/>
</ElSelect>
</ElFormItem>
@@ -1035,7 +1035,7 @@ onMounted(() => {
v-for="item in userOptions"
:key="item.id"
:label="item.nickname"
:value="item.id!"
:value="item.id"
/>
</ElSelect>
</ElFormItem>

View File

@@ -79,7 +79,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
},
trigger: (values, formApi) => {
if (values.deviceId !== undefined) {
void formApi.setFieldValue('deviceId', undefined);
formApi.setFieldValue('deviceId', undefined);
}
},
},

View File

@@ -1,3 +1,4 @@
// oxlint-disable typescript/require-array-sort-compare
/** 坐标点 */
export interface Point {
x: number;

View File

@@ -57,7 +57,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区,避免旧库区条件残留
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -207,7 +207,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库切换时清空库区
trigger: (values, formApi) => {
if (values.locationId !== undefined) {
void formApi.setFieldValue('locationId', undefined);
formApi.setFieldValue('locationId', undefined);
}
},
},
@@ -225,7 +225,7 @@ export function useSelectGridFormSchema(): VbenFormSchema[] {
// 仓库或库区切换时清空库位
trigger: (values, formApi) => {
if (values.areaId !== undefined) {
void formApi.setFieldValue('areaId', undefined);
formApi.setFieldValue('areaId', undefined);
}
},
},