!376 fix: 修复 vben check:type 类型错误
Merge pull request !376 from 芋道源码/migration
This commit is contained in:
@@ -55,7 +55,7 @@ export function refuseFriendRequest(
|
||||
/** 查询「我相关」的好友申请列表(游标分页:传 maxId 加载更多) */
|
||||
export function getMyFriendRequestList(limit: number, maxId?: number) {
|
||||
const params: Record<string, number> = { limit };
|
||||
if (maxId !== null) {
|
||||
if (maxId != null) {
|
||||
params.maxId = maxId;
|
||||
}
|
||||
return requestClient.get<ImFriendRequestApi.FriendRequestRespVO[]>(
|
||||
|
||||
@@ -52,6 +52,7 @@ export namespace ThingModelApi {
|
||||
name?: string;
|
||||
required?: boolean;
|
||||
type?: string;
|
||||
dataType?: string;
|
||||
description?: string;
|
||||
outputParams?: Param[];
|
||||
method?: string;
|
||||
|
||||
@@ -395,15 +395,14 @@ const setEncoded = (type: string, data: string) => {
|
||||
};
|
||||
|
||||
// 加载本地文件
|
||||
const importLocalFile = () => {
|
||||
const importLocalFile = async () => {
|
||||
const file = refFile.value.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.text(file);
|
||||
reader.addEventListener('load', function () {
|
||||
const xmlStr = this.result;
|
||||
createNewDiagram(xmlStr);
|
||||
emit('save', xmlStr);
|
||||
});
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
const xmlStr = await file.text();
|
||||
createNewDiagram(xmlStr);
|
||||
emit('save', xmlStr);
|
||||
};
|
||||
/* ------------------------------------------------ refs methods ------------------------------------------------------ */
|
||||
const downloadProcessAsXml = () => {
|
||||
|
||||
@@ -264,7 +264,6 @@ watch(
|
||||
class="mr-2 mt-0.5"
|
||||
v-model:value="timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
@change="
|
||||
() => {
|
||||
updateTimeModdle();
|
||||
|
||||
@@ -239,9 +239,7 @@ const selectProcessListener = (listener: any) => {
|
||||
) ?? [];
|
||||
updateElementExtensions(
|
||||
bpmnElement,
|
||||
otherExtensionList.value
|
||||
? [...otherExtensionList.value, ...bpmnElementListeners.value]
|
||||
: undefined,
|
||||
[...otherExtensionList.value, ...bpmnElementListeners.value],
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -689,7 +689,6 @@ onMounted(async () => {
|
||||
class="w-24"
|
||||
v-model:value="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
|
||||
@@ -264,7 +264,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.roleIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -311,7 +311,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.postIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -331,7 +331,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.userIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -353,7 +353,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.userGroups"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -373,7 +373,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
label="表单内用户字段"
|
||||
name="formUser"
|
||||
>
|
||||
<Select v-model:value="configForm.formUser" clearable>
|
||||
<Select v-model:value="configForm.formUser" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in userFieldOnFormOptions"
|
||||
:key="idx"
|
||||
@@ -393,7 +393,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
label="表单内部门字段"
|
||||
name="formDept"
|
||||
>
|
||||
<Select v-model:value="configForm.formDept" clearable>
|
||||
<Select v-model:value="configForm.formDept" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in deptFieldOnFormOptions"
|
||||
:key="idx"
|
||||
@@ -419,7 +419,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
:label="deptLevelLabel!"
|
||||
name="deptLevel"
|
||||
>
|
||||
<Select v-model:value="configForm.deptLevel" clearable>
|
||||
<Select v-model:value="configForm.deptLevel" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, index) in MULTI_LEVEL_DEPT"
|
||||
:key="index"
|
||||
@@ -437,7 +437,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
label="流程表达式"
|
||||
name="expression"
|
||||
>
|
||||
<Textarea v-model:value="configForm.expression" clearable />
|
||||
<Textarea v-model:value="configForm.expression" allow-clear />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@@ -259,14 +259,14 @@ function updateFormFieldKey(
|
||||
) {
|
||||
if (!formSetting?.updateFormFields || !newKey) return;
|
||||
const value = formSetting.updateFormFields[oldKey];
|
||||
delete formSetting.updateFormFields.oldKey;
|
||||
delete formSetting.updateFormFields[oldKey];
|
||||
formSetting.updateFormFields[String(newKey)] = value;
|
||||
}
|
||||
|
||||
/** 删除修改字段设置项 */
|
||||
function deleteFormFieldSetting(formSetting: FormTriggerSetting, key: string) {
|
||||
if (!formSetting?.updateFormFields) return;
|
||||
delete formSetting.updateFormFields.key;
|
||||
delete formSetting.updateFormFields[key];
|
||||
}
|
||||
|
||||
/** 保存配置 */
|
||||
|
||||
@@ -698,7 +698,7 @@ onMounted(() => {
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.roleIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -745,7 +745,7 @@ onMounted(() => {
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.postIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -765,7 +765,7 @@ onMounted(() => {
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.userIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -787,7 +787,7 @@ onMounted(() => {
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.userGroups"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
@@ -807,7 +807,7 @@ onMounted(() => {
|
||||
label="表单内用户字段"
|
||||
name="formUser"
|
||||
>
|
||||
<Select v-model:value="configForm.formUser" clearable>
|
||||
<Select v-model:value="configForm.formUser" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in userFieldOnFormOptions"
|
||||
:key="idx"
|
||||
@@ -827,7 +827,7 @@ onMounted(() => {
|
||||
label="表单内部门字段"
|
||||
name="formDept"
|
||||
>
|
||||
<Select v-model:value="configForm.formDept" clearable>
|
||||
<Select v-model:value="configForm.formDept" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, idx) in deptFieldOnFormOptions"
|
||||
:key="idx"
|
||||
@@ -853,7 +853,7 @@ onMounted(() => {
|
||||
:label="deptLevelLabel!"
|
||||
name="deptLevel"
|
||||
>
|
||||
<Select v-model:value="configForm.deptLevel" clearable>
|
||||
<Select v-model:value="configForm.deptLevel" allow-clear>
|
||||
<SelectOption
|
||||
v-for="(item, index) in MULTI_LEVEL_DEPT"
|
||||
:key="index"
|
||||
@@ -944,7 +944,7 @@ onMounted(() => {
|
||||
label="驳回节点"
|
||||
name="returnNodeId"
|
||||
>
|
||||
<Select v-model:value="configForm.returnNodeId" clearable>
|
||||
<Select v-model:value="configForm.returnNodeId" allow-clear>
|
||||
<SelectOption
|
||||
v-for="item in returnTaskList"
|
||||
:key="item.id"
|
||||
@@ -1015,7 +1015,6 @@ onMounted(() => {
|
||||
class="mr-2 mt-0.5"
|
||||
v-model:value="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
@@ -1088,7 +1087,7 @@ onMounted(() => {
|
||||
>
|
||||
<Select
|
||||
v-model:value="configForm.assignEmptyHandlerUserIds"
|
||||
clearable
|
||||
allow-clear
|
||||
mode="multiple"
|
||||
>
|
||||
<SelectOption
|
||||
|
||||
@@ -139,11 +139,14 @@ function handleModelSort() {
|
||||
disabled: false,
|
||||
onEnd: ({ newDraggableIndex, oldDraggableIndex }) => {
|
||||
if (oldDraggableIndex !== newDraggableIndex) {
|
||||
modelList.value.splice(
|
||||
newDraggableIndex ?? 0,
|
||||
0,
|
||||
modelList.value.splice(oldDraggableIndex ?? 0, 1)[0],
|
||||
const [movedModel] = modelList.value.splice(
|
||||
oldDraggableIndex ?? 0,
|
||||
1,
|
||||
);
|
||||
if (!movedModel) {
|
||||
return;
|
||||
}
|
||||
modelList.value.splice(newDraggableIndex ?? 0, 0, movedModel);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
BpmFieldPermissionType,
|
||||
BpmModelFormType,
|
||||
BpmModelType,
|
||||
BpmProcessInstanceStatus,
|
||||
BpmTaskStatusEnum,
|
||||
DICT_TYPE,
|
||||
} from '@vben/constants';
|
||||
import {
|
||||
@@ -34,7 +34,7 @@ import { registerComponent } from '#/utils';
|
||||
|
||||
import ProcessInstanceBpmnViewer from './modules/bpm-viewer.vue';
|
||||
import ProcessInstanceOperationButton from './modules/operation-button.vue';
|
||||
import ProcessssPrint from './modules/process-print.vue';
|
||||
import ProcessPrint from './modules/process-print.vue';
|
||||
import ProcessInstanceSimpleViewer from './modules/simple-bpm-viewer.vue';
|
||||
import BpmProcessInstanceTaskList from './modules/task-list.vue';
|
||||
import ProcessInstanceTimeline from './modules/time-line.vue';
|
||||
@@ -61,10 +61,13 @@ const auditIconsMap: {
|
||||
| typeof SvgBpmRejectIcon
|
||||
| typeof SvgBpmRunningIcon;
|
||||
} = {
|
||||
[BpmProcessInstanceStatus.RUNNING]: SvgBpmRunningIcon,
|
||||
[BpmProcessInstanceStatus.APPROVE]: SvgBpmApproveIcon,
|
||||
[BpmProcessInstanceStatus.REJECT]: SvgBpmRejectIcon,
|
||||
[BpmProcessInstanceStatus.CANCEL]: SvgBpmCancelIcon,
|
||||
[BpmTaskStatusEnum.RUNNING]: SvgBpmRunningIcon,
|
||||
[BpmTaskStatusEnum.APPROVE]: SvgBpmApproveIcon,
|
||||
[BpmTaskStatusEnum.REJECT]: SvgBpmRejectIcon,
|
||||
[BpmTaskStatusEnum.CANCEL]: SvgBpmCancelIcon,
|
||||
[BpmTaskStatusEnum.APPROVING]: SvgBpmApproveIcon,
|
||||
[BpmTaskStatusEnum.RETURN]: SvgBpmRejectIcon,
|
||||
[BpmTaskStatusEnum.WAIT]: SvgBpmRunningIcon,
|
||||
};
|
||||
const activityNodes = ref<BpmProcessInstanceApi.ApprovalNodeInfo[]>([]); // 审批节点信息
|
||||
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||
@@ -189,7 +192,7 @@ const refresh = () => {
|
||||
};
|
||||
|
||||
const [PrintModal, printModalApi] = useVbenModal({
|
||||
connectedComponent: ProcessssPrint,
|
||||
connectedComponent: ProcessPrint,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ const recentForwardConversations = computed(() =>
|
||||
.map((key) => byKey.value.get(key))
|
||||
.filter(
|
||||
(c): c is Conversation =>
|
||||
c !== null && !hideSet.value.has(getConversationKey(c)),
|
||||
c != null && !hideSet.value.has(getConversationKey(c)),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -96,7 +96,7 @@ const selectedConversations = computed(() =>
|
||||
.map((key) => byKey.value.get(key))
|
||||
.filter(
|
||||
(conversation): conversation is Conversation =>
|
||||
conversation !== null &&
|
||||
conversation != null &&
|
||||
!hideSet.value.has(getConversationKey(conversation)),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Button, Input, message } from 'ant-design-vue';
|
||||
import { getCurrentUserId } from '#/views/im/utils/auth';
|
||||
|
||||
import { ImFriendRequestHandleResult } from '../../../utils/constants';
|
||||
import { UserAvatar } from '../../components/user';
|
||||
import { UserAvatar, UserInfo } from '../../components/user';
|
||||
import { useFriendStore } from '../../store/friendStore';
|
||||
|
||||
defineOptions({ name: 'ImContactFriendRequestDetail' });
|
||||
|
||||
@@ -95,12 +95,12 @@ const myId = computed(() => getCurrentUserId());
|
||||
/** 历史退群群:禁所有群操作入口(邀请 / 移出 / 改资料 / 禁言 / 审批 / 退出等),只保留展示;props.group 是 GroupLite 无 joinStatus,回 store 取全量 */
|
||||
const isQuitGroup = computed(() => {
|
||||
const id = props.group?.id;
|
||||
return id !== null && isGroupQuit(groupStore.getGroup(id));
|
||||
return id != null && isGroupQuit(groupStore.getGroup(id));
|
||||
});
|
||||
const isOwner = computed(
|
||||
() =>
|
||||
!isQuitGroup.value &&
|
||||
props.group !== null &&
|
||||
props.group != null &&
|
||||
props.group.ownerId === myId.value,
|
||||
);
|
||||
/** 当前用户在群里的角色(来自 props.members 的 me 行);用于判定是否可移出他人 */
|
||||
|
||||
@@ -86,7 +86,7 @@ const showSendName = computed(() => {
|
||||
return false;
|
||||
}
|
||||
const lastType = props.conversation.lastMessageType;
|
||||
return lastType !== null && isNormalMessage(lastType);
|
||||
return lastType != null && isNormalMessage(lastType);
|
||||
});
|
||||
|
||||
/** 列表展示文案:草稿优先(对齐微信 PC:有草稿时盖掉最后一条预览)→ 撤回实时算 → lastContent 兜底 */
|
||||
@@ -96,7 +96,7 @@ const lastContentDisplay = computed(() => {
|
||||
}
|
||||
if (
|
||||
props.conversation.lastMessageType === ImContentType.RECALL &&
|
||||
props.conversation.lastSenderId !== null
|
||||
props.conversation.lastSenderId != null
|
||||
) {
|
||||
return buildRecallTip(
|
||||
props.conversation.lastSenderId,
|
||||
|
||||
@@ -251,7 +251,7 @@ const redialRtcCall = inject(IM_RTC_REDIAL_KEY);
|
||||
/** 私聊 RTC_CALL_END 气泡点击:用同款 mediaType 重拨 */
|
||||
function handleRtcCallBubbleClick() {
|
||||
const mediaType = rtcCallEndPrivatePayload.value?.mediaType;
|
||||
if (mediaType === null) {
|
||||
if (mediaType == null) {
|
||||
return;
|
||||
}
|
||||
redialRtcCall?.(mediaType);
|
||||
|
||||
@@ -243,7 +243,7 @@ function handleConfirm() {
|
||||
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||
return;
|
||||
}
|
||||
emit('selected', multiple.value ? rows : [rows[0]]);
|
||||
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||
open.value = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ const showClear = computed(() => {
|
||||
props.allowClear &&
|
||||
!props.disabled &&
|
||||
hovering.value &&
|
||||
props.modelValue !== null
|
||||
props.modelValue != null
|
||||
);
|
||||
});
|
||||
|
||||
/** 根据编号查询群信息(用于编辑回显) */
|
||||
async function resolveItemById(id: number | undefined) {
|
||||
if (id === null) {
|
||||
if (id == null) {
|
||||
selectedItem.value = undefined;
|
||||
return;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ function handleClick(event: MouseEvent) {
|
||||
clearSelected();
|
||||
return;
|
||||
}
|
||||
dialogRef.value?.open(props.modelValue === null ? [] : [props.modelValue]);
|
||||
dialogRef.value?.open(props.modelValue == null ? [] : [props.modelValue]);
|
||||
}
|
||||
|
||||
/** 弹窗选中回调 */
|
||||
|
||||
@@ -55,7 +55,7 @@ export async function runIncrementalPull<T extends PullRecord>(
|
||||
const storedCursor = await getPullCursor(cursorKey);
|
||||
const highWater = { ...storedCursor };
|
||||
let cursor =
|
||||
storedCursor.lastUpdateTime === null
|
||||
storedCursor.lastUpdateTime == null
|
||||
? {}
|
||||
: {
|
||||
lastUpdateTime: Math.max(
|
||||
@@ -89,12 +89,12 @@ export async function runIncrementalPull<T extends PullRecord>(
|
||||
if (!last) {
|
||||
return;
|
||||
}
|
||||
if (last.updateTime === null) {
|
||||
if (last.updateTime == null) {
|
||||
return;
|
||||
}
|
||||
cursor = { lastUpdateTime: last.updateTime, lastId: last.id };
|
||||
if (
|
||||
highWater.lastUpdateTime === null ||
|
||||
highWater.lastUpdateTime == null ||
|
||||
cursor.lastUpdateTime > highWater.lastUpdateTime ||
|
||||
(cursor.lastUpdateTime === highWater.lastUpdateTime &&
|
||||
cursor.lastId > (highWater.lastId ?? 0))
|
||||
@@ -154,14 +154,14 @@ export async function runMinIdPull<T extends { id?: number }>(options: {
|
||||
// 本批最大消息 id 作为下次游标;无有效 id 则本批 apply 后停(无法继续翻页)
|
||||
const validIds = list
|
||||
.map((record) => record.id)
|
||||
.filter((id): id is number => id !== null);
|
||||
.filter((id): id is number => id != null);
|
||||
const nextMinId = validIds.length > 0 ? Math.max(...validIds) : undefined;
|
||||
// applyPage 返回 false:本页未落地(如入库失败),不推进游标并终止,避免漏消息
|
||||
if ((await applyPage(list, nextMinId)) === false) {
|
||||
return;
|
||||
}
|
||||
// 无有效 id,或游标没前进(后端契约是 id > minId,理论不会出现):停,防御死翻
|
||||
if (nextMinId === null || nextMinId <= minId) {
|
||||
if (nextMinId == null || nextMinId <= minId) {
|
||||
return;
|
||||
}
|
||||
minId = nextMinId;
|
||||
|
||||
@@ -228,7 +228,7 @@ onMounted(async () => {
|
||||
placeholder="请选择接收人"
|
||||
:disabled="!getIsOpen"
|
||||
>
|
||||
<Select.Option key="" value="" label="所有人">
|
||||
<Select.Option key="all" value="all" label="所有人">
|
||||
<div class="flex items-center">
|
||||
<Avatar size="small" class="mr-2">全</Avatar>
|
||||
<span>所有人</span>
|
||||
|
||||
@@ -45,8 +45,12 @@ const canAdd = computed(() => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
// oxlint-disable-next-line unicorn/no-nested-ternary
|
||||
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
|
||||
let ids: number[] = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
ids = newValue;
|
||||
} else if (newValue) {
|
||||
ids = [newValue];
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
productSpus.value = [];
|
||||
return;
|
||||
@@ -54,7 +58,7 @@ watch(
|
||||
// 只有商品发生变化时才重新查询
|
||||
if (
|
||||
productSpus.value.length === 0 ||
|
||||
productSpus.value.some((spu) => !ids.includes(spu.id))
|
||||
productSpus.value.some((spu) => spu.id == null || !ids.includes(spu.id))
|
||||
) {
|
||||
productSpus.value = await getSpuDetailList(ids);
|
||||
}
|
||||
|
||||
@@ -46,8 +46,12 @@ const canAdd = computed(() => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
// oxlint-disable-next-line unicorn/no-nested-ternary
|
||||
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
|
||||
let ids: number[] = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
ids = newValue;
|
||||
} else if (newValue) {
|
||||
ids = [newValue];
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
activityList.value = [];
|
||||
return;
|
||||
@@ -55,7 +59,9 @@ watch(
|
||||
// 只有活动发生变化时才重新查询
|
||||
if (
|
||||
activityList.value.length === 0 ||
|
||||
activityList.value.some((activity) => !ids.includes(activity.id))
|
||||
activityList.value.some(
|
||||
(activity) => activity.id == null || !ids.includes(activity.id),
|
||||
)
|
||||
) {
|
||||
activityList.value = await getCombinationActivityListByIds(ids);
|
||||
}
|
||||
|
||||
@@ -45,8 +45,12 @@ const canAdd = computed(() => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
// oxlint-disable-next-line unicorn/no-nested-ternary
|
||||
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
|
||||
let ids: number[] = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
ids = newValue;
|
||||
} else if (newValue) {
|
||||
ids = [newValue];
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
activityList.value = [];
|
||||
return;
|
||||
@@ -54,7 +58,9 @@ watch(
|
||||
// 只有活动发生变化时才重新查询
|
||||
if (
|
||||
activityList.value.length === 0 ||
|
||||
activityList.value.some((activity) => !ids.includes(activity.id))
|
||||
activityList.value.some(
|
||||
(activity) => activity.id == null || !ids.includes(activity.id),
|
||||
)
|
||||
) {
|
||||
activityList.value = await getSeckillActivityListByIds(ids as number[]);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ function getMultipleSelectedRows() {
|
||||
] as MesMdClientApi.Client[];
|
||||
records.forEach((row) => {
|
||||
const rowId = row.id;
|
||||
if (!rowId) {
|
||||
selectedMap.set(rowId as number, row);
|
||||
if (rowId !== undefined && rowId !== null) {
|
||||
selectedMap.set(rowId, row);
|
||||
}
|
||||
});
|
||||
return [...selectedMap.values()];
|
||||
|
||||
@@ -42,8 +42,8 @@ function getMultipleSelectedRows() {
|
||||
] as MesMdItemApi.Item[];
|
||||
records.forEach((row) => {
|
||||
const rowId = row.id;
|
||||
if (!rowId) {
|
||||
selectedMap.set(rowId as number, row);
|
||||
if (rowId !== undefined && rowId !== null) {
|
||||
selectedMap.set(rowId, row);
|
||||
}
|
||||
});
|
||||
return [...selectedMap.values()];
|
||||
|
||||
@@ -41,8 +41,8 @@ function getMultipleSelectedRows() {
|
||||
] as MesMdVendorApi.Vendor[];
|
||||
records.forEach((row) => {
|
||||
const rowId = row.id;
|
||||
if (!rowId) {
|
||||
selectedMap.set(rowId as number, row);
|
||||
if (rowId !== undefined && rowId !== null) {
|
||||
selectedMap.set(rowId, row);
|
||||
}
|
||||
});
|
||||
return [...selectedMap.values()];
|
||||
|
||||
@@ -36,8 +36,8 @@ function getMultipleSelectedRows() {
|
||||
] as MesTmToolApi.Tool[];
|
||||
records.forEach((row) => {
|
||||
const rowId = row.id;
|
||||
if (!rowId) {
|
||||
selectedMap.set(rowId as number, row);
|
||||
if (rowId !== undefined && rowId !== null) {
|
||||
selectedMap.set(rowId, row);
|
||||
}
|
||||
});
|
||||
return [...selectedMap.values()];
|
||||
|
||||
@@ -54,7 +54,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ function handleQualityStatusChange(value?: number) {
|
||||
emit('update:modelValue', undefined);
|
||||
emit('valueChange', {
|
||||
valueId: undefined,
|
||||
valueCode: value === null ? '' : String(value),
|
||||
valueCode: value === undefined || value === null ? '' : String(value),
|
||||
valueName: selected?.label || '',
|
||||
});
|
||||
}
|
||||
@@ -109,14 +109,15 @@ async function loadCascadeData() {
|
||||
: undefined;
|
||||
return;
|
||||
}
|
||||
if (!props.modelValue) {
|
||||
const valueId = props.modelValue;
|
||||
if (valueId === undefined || valueId === null) {
|
||||
return;
|
||||
}
|
||||
if (props.type === MesWmStockTakingParamTypeEnum.LOCATION) {
|
||||
const location = await getWarehouseLocation(props.modelValue);
|
||||
const location = await getWarehouseLocation(valueId);
|
||||
locationWarehouseId.value = location?.warehouseId;
|
||||
} else if (props.type === MesWmStockTakingParamTypeEnum.AREA) {
|
||||
const area = await getWarehouseArea(props.modelValue);
|
||||
const area = await getWarehouseArea(valueId);
|
||||
areaWarehouseId.value = area?.warehouseId;
|
||||
areaLocationId.value = area?.locationId;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
const props = defineProps<{ type: UploadType }>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
uploaded: [v: Promise<void>];
|
||||
uploaded: [];
|
||||
}>();
|
||||
|
||||
const accountId = inject<number>('accountId');
|
||||
|
||||
@@ -30,7 +30,7 @@ withDefaults(
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:open': [v: boolean];
|
||||
uploaded: [v: Promise<void>];
|
||||
uploaded: [];
|
||||
}>();
|
||||
|
||||
const accountId = inject<number>('accountId');
|
||||
|
||||
@@ -24,7 +24,7 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'delete', v: Promise<void>): void;
|
||||
(e: 'delete'): void;
|
||||
(e: 'update:modelValue', v: any): void;
|
||||
}>();
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getCheckOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getCheckOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断盘库单是否可修改 */
|
||||
|
||||
@@ -61,7 +61,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getMovementOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getMovementOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断移库单是否可修改 */
|
||||
|
||||
@@ -61,7 +61,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getReceiptOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getReceiptOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断入库单是否可修改 */
|
||||
|
||||
@@ -61,7 +61,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getShipmentOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getShipmentOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断出库单是否可修改 */
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"preview": "vite preview",
|
||||
"#typecheck": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vue-tsc --noEmit --skipLibCheck --incremental --tsBuildInfoFile node_modules/.cache/vue-tsc/tsconfig.tsbuildinfo"
|
||||
"typecheck": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vue-tsc --noEmit --skipLibCheck --incremental --tsBuildInfoFile node_modules/.cache/vue-tsc/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/*"
|
||||
|
||||
@@ -79,11 +79,11 @@ export namespace BpmProcessInstanceApi {
|
||||
export interface ApprovalTaskInfo {
|
||||
id: number;
|
||||
assigneeUser: User;
|
||||
attachments?: string[];
|
||||
ownerUser: User;
|
||||
reason: string;
|
||||
signPicUrl: string;
|
||||
status: number;
|
||||
attachments?: string[];
|
||||
}
|
||||
|
||||
/** 抄送流程实例 */
|
||||
|
||||
@@ -55,7 +55,7 @@ export function refuseFriendRequest(
|
||||
/** 查询「我相关」的好友申请列表(游标分页:传 maxId 加载更多) */
|
||||
export function getMyFriendRequestList(limit: number, maxId?: number) {
|
||||
const params: Record<string, number> = { limit };
|
||||
if (maxId !== null) {
|
||||
if (maxId != null) {
|
||||
params.maxId = maxId;
|
||||
}
|
||||
return requestClient.get<ImFriendRequestApi.FriendRequestRespVO[]>(
|
||||
|
||||
@@ -54,6 +54,7 @@ export namespace ThingModelApi {
|
||||
name?: string;
|
||||
required?: boolean;
|
||||
type?: string;
|
||||
dataType?: string;
|
||||
description?: string;
|
||||
outputParams?: Param[];
|
||||
method?: string;
|
||||
@@ -113,37 +114,41 @@ export namespace ThingModelApi {
|
||||
|
||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||
function buildRequiredNumberValidator(label: string) {
|
||||
return (_rule: any, value: any) => {
|
||||
return (_rule: any, value: any, callback: any) => {
|
||||
if (isEmpty(value)) {
|
||||
return Promise.reject(new Error(`${label}不能为空`));
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
}
|
||||
if (Number.isNaN(Number(value))) {
|
||||
return Promise.reject(new Error(`${label}必须是数字`));
|
||||
callback(new Error(`${label}必须是数字`));
|
||||
return;
|
||||
}
|
||||
return Promise.resolve();
|
||||
callback();
|
||||
};
|
||||
}
|
||||
|
||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||
export function buildIdentifierLikeNameValidator(label: string) {
|
||||
return (_rule: any, value: string) => {
|
||||
return (_rule: any, value: string, callback: any) => {
|
||||
if (isEmpty(value)) {
|
||||
return Promise.reject(new Error(`${label}不能为空`));
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||
return Promise.reject(
|
||||
new Error(`${label}必须以中文、英文字母或数字开头`),
|
||||
);
|
||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
||||
return;
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||
return Promise.reject(
|
||||
callback(
|
||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (value.length > 20) {
|
||||
return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
|
||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
||||
return;
|
||||
}
|
||||
return Promise.resolve();
|
||||
callback();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,7 +172,7 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
validator: (_rule: any, value: string) => {
|
||||
validator: (_rule: any, value: string, callback: any) => {
|
||||
const reservedKeywords = [
|
||||
'set',
|
||||
'get',
|
||||
@@ -178,16 +183,18 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
||||
'value',
|
||||
];
|
||||
if (reservedKeywords.includes(value)) {
|
||||
return Promise.reject(
|
||||
callback(
|
||||
new Error(
|
||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (/^\d+$/.test(value)) {
|
||||
return Promise.reject(new Error('标识符不能是纯数字'));
|
||||
callback(new Error('标识符不能是纯数字'));
|
||||
return;
|
||||
}
|
||||
return Promise.resolve();
|
||||
callback();
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
|
||||
@@ -395,15 +395,14 @@ const setEncoded = (type: string, data: string) => {
|
||||
};
|
||||
|
||||
// 加载本地文件
|
||||
const importLocalFile = () => {
|
||||
const importLocalFile = async () => {
|
||||
const file = refFile.value.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.text(file);
|
||||
reader.addEventListener('load', function () {
|
||||
const xmlStr = this.result;
|
||||
createNewDiagram(xmlStr);
|
||||
emit('save', xmlStr);
|
||||
});
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
const xmlStr = await file.text();
|
||||
createNewDiagram(xmlStr);
|
||||
emit('save', xmlStr);
|
||||
};
|
||||
/* ------------------------------------------------ refs methods ------------------------------------------------------ */
|
||||
const downloadProcessAsXml = () => {
|
||||
|
||||
@@ -263,7 +263,6 @@ watch(
|
||||
class="mr-2 mt-0.5"
|
||||
v-model:value="timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
@change="
|
||||
() => {
|
||||
updateTimeModdle();
|
||||
|
||||
@@ -231,9 +231,7 @@ const selectProcessListener = (listener: any) => {
|
||||
) ?? [];
|
||||
updateElementExtensions(
|
||||
bpmnElement,
|
||||
otherExtensionList.value
|
||||
? [...otherExtensionList.value, ...bpmnElementListeners.value]
|
||||
: undefined,
|
||||
[...otherExtensionList.value, ...bpmnElementListeners.value],
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -673,7 +673,6 @@ onMounted(async () => {
|
||||
class="w-24"
|
||||
v-model:value="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
|
||||
@@ -402,7 +402,7 @@ defineExpose({ showCopyTaskNodeConfig }); // 暴露方法给父组件
|
||||
label="流程表达式"
|
||||
name="expression"
|
||||
>
|
||||
<TextArea v-model:value="configForm.expression" clearable />
|
||||
<TextArea v-model:value="configForm.expression" allow-clear />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@@ -258,14 +258,14 @@ function updateFormFieldKey(
|
||||
) {
|
||||
if (!formSetting?.updateFormFields || !newKey) return;
|
||||
const value = formSetting.updateFormFields[oldKey];
|
||||
delete formSetting.updateFormFields.oldKey;
|
||||
delete formSetting.updateFormFields[oldKey];
|
||||
formSetting.updateFormFields[String(newKey)] = value;
|
||||
}
|
||||
|
||||
/** 删除修改字段设置项 */
|
||||
function deleteFormFieldSetting(formSetting: FormTriggerSetting, key: string) {
|
||||
if (!formSetting?.updateFormFields) return;
|
||||
delete formSetting.updateFormFields.key;
|
||||
delete formSetting.updateFormFields[key];
|
||||
}
|
||||
|
||||
/** 保存配置 */
|
||||
|
||||
@@ -980,7 +980,6 @@ onMounted(() => {
|
||||
class="mr-2 mt-0.5"
|
||||
v-model:value="configForm.timeDuration"
|
||||
:min="1"
|
||||
controls-position="right"
|
||||
/>
|
||||
</FormItem>
|
||||
</Col>
|
||||
|
||||
@@ -135,6 +135,7 @@ function openStartDeptSelect() {
|
||||
|
||||
/** 处理部门选择确认 */
|
||||
function handleDeptSelectConfirm(depts: SystemDeptApi.Dept[]) {
|
||||
selectedStartDepts.value = depts;
|
||||
modelData.value = {
|
||||
...modelData.value,
|
||||
startDeptIds: depts.map((d) => d.id),
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
BpmFieldPermissionType,
|
||||
BpmModelFormType,
|
||||
BpmModelType,
|
||||
BpmProcessInstanceStatus,
|
||||
BpmTaskStatusEnum,
|
||||
DICT_TYPE,
|
||||
} from '@vben/constants';
|
||||
import {
|
||||
@@ -34,7 +34,7 @@ import { registerComponent } from '#/utils';
|
||||
|
||||
import ProcessInstanceBpmnViewer from './modules/bpm-viewer.vue';
|
||||
import ProcessInstanceOperationButton from './modules/operation-button.vue';
|
||||
import ProcessssPrint from './modules/process-print.vue';
|
||||
import ProcessPrint from './modules/process-print.vue';
|
||||
import ProcessInstanceSimpleViewer from './modules/simple-bpm-viewer.vue';
|
||||
import BpmProcessInstanceTaskList from './modules/task-list.vue';
|
||||
import ProcessInstanceTimeline from './modules/time-line.vue';
|
||||
@@ -61,10 +61,13 @@ const auditIconsMap: {
|
||||
| typeof SvgBpmRejectIcon
|
||||
| typeof SvgBpmRunningIcon;
|
||||
} = {
|
||||
[BpmProcessInstanceStatus.RUNNING]: SvgBpmRunningIcon,
|
||||
[BpmProcessInstanceStatus.APPROVE]: SvgBpmApproveIcon,
|
||||
[BpmProcessInstanceStatus.REJECT]: SvgBpmRejectIcon,
|
||||
[BpmProcessInstanceStatus.CANCEL]: SvgBpmCancelIcon,
|
||||
[BpmTaskStatusEnum.RUNNING]: SvgBpmRunningIcon,
|
||||
[BpmTaskStatusEnum.APPROVE]: SvgBpmApproveIcon,
|
||||
[BpmTaskStatusEnum.REJECT]: SvgBpmRejectIcon,
|
||||
[BpmTaskStatusEnum.CANCEL]: SvgBpmCancelIcon,
|
||||
[BpmTaskStatusEnum.APPROVING]: SvgBpmApproveIcon,
|
||||
[BpmTaskStatusEnum.RETURN]: SvgBpmRejectIcon,
|
||||
[BpmTaskStatusEnum.WAIT]: SvgBpmRunningIcon,
|
||||
};
|
||||
const activityNodes = ref<BpmProcessInstanceApi.ApprovalNodeInfo[]>([]); // 审批节点信息
|
||||
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||
@@ -189,7 +192,7 @@ const refresh = () => {
|
||||
};
|
||||
|
||||
const [PrintModal, printModalApi] = useVbenModal({
|
||||
connectedComponent: ProcessssPrint,
|
||||
connectedComponent: ProcessPrint,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
|
||||
@@ -94,6 +94,24 @@ const popOverVisible: any = ref({
|
||||
deleteSign: false,
|
||||
}); // 气泡卡是否展示
|
||||
const returnList = ref([] as any); // 退回节点
|
||||
const APPROVAL_ATTACHMENT_FILE_TYPES = [
|
||||
'doc',
|
||||
'docx',
|
||||
'xls',
|
||||
'xlsx',
|
||||
'ppt',
|
||||
'pptx',
|
||||
'txt',
|
||||
'pdf',
|
||||
'jpg',
|
||||
'jpeg',
|
||||
'png',
|
||||
'gif',
|
||||
'bmp',
|
||||
'webp',
|
||||
];
|
||||
const APPROVAL_ATTACHMENT_FILE_SIZE = 5;
|
||||
const APPROVAL_ATTACHMENT_DIRECTORY = 'bpm/task-attachment';
|
||||
|
||||
/** 创建流程表达式 */
|
||||
function openSignatureModal() {
|
||||
@@ -901,8 +919,12 @@ defineExpose({ loadTodoTask });
|
||||
<FormItem label="上传附件/图片" name="attachments">
|
||||
<FileUpload
|
||||
v-model:value="approveReasonForm.attachments"
|
||||
:accept="APPROVAL_ATTACHMENT_FILE_TYPES"
|
||||
:directory="APPROVAL_ATTACHMENT_DIRECTORY"
|
||||
:max-number="10"
|
||||
:max-size="APPROVAL_ATTACHMENT_FILE_SIZE"
|
||||
:multiple="true"
|
||||
:show-description="true"
|
||||
:show-download-icon="false"
|
||||
help-text="支持多文件/图片上传"
|
||||
@preview="handleFilePreview"
|
||||
@@ -968,8 +990,12 @@ defineExpose({ loadTodoTask });
|
||||
<FormItem label="上传附件/图片" name="attachments">
|
||||
<FileUpload
|
||||
v-model:value="rejectReasonForm.attachments"
|
||||
:accept="APPROVAL_ATTACHMENT_FILE_TYPES"
|
||||
:directory="APPROVAL_ATTACHMENT_DIRECTORY"
|
||||
:max-number="10"
|
||||
:max-size="APPROVAL_ATTACHMENT_FILE_SIZE"
|
||||
:multiple="true"
|
||||
:show-description="true"
|
||||
help-text="支持多文件/图片上传"
|
||||
@preview="handleFilePreview"
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance';
|
||||
import type { SystemAreaApi } from '#/api/system/area';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, shallowRef } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
@@ -19,6 +19,7 @@ import { getAreaTree } from '#/api/system/area';
|
||||
import { getSimpleDeptList } from '#/api/system/dept';
|
||||
import { getSimpleUserList } from '#/api/system/user';
|
||||
import { decodeFields } from '#/components/form-create';
|
||||
import { registerComponent } from '#/utils';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -54,6 +55,7 @@ const userName = computed(() => userStore.userInfo?.nickname ?? '');
|
||||
const printTime = ref(formatDate(new Date(), 'YYYY-MM-DD HH:mm'));
|
||||
const formFields = ref<FormFieldItem[]>([]);
|
||||
const printDataMap = ref<Record<string, string>>({});
|
||||
const BusinessFormComponent = shallowRef<any>();
|
||||
|
||||
/** 打印配置 */
|
||||
const printObj = ref({
|
||||
@@ -93,6 +95,17 @@ async function fetchPrintData(id: string) {
|
||||
printTime.value = formatDate(new Date(), 'YYYY-MM-DD HH:mm');
|
||||
initPrintDataMap();
|
||||
await parseFormFields();
|
||||
initBusinessFormComponent();
|
||||
}
|
||||
|
||||
/** 初始化业务表单组件 */
|
||||
function initBusinessFormComponent() {
|
||||
const businessFormPath =
|
||||
printData.value?.processInstance.processDefinition?.formCustomViewPath ||
|
||||
'';
|
||||
BusinessFormComponent.value = businessFormPath
|
||||
? registerComponent(businessFormPath)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/** 解析表单字段 */
|
||||
@@ -595,6 +608,22 @@ function getPrintTemplateHTML() {
|
||||
<div v-html="item.html"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- 业务表单:独立成块渲染,不嵌入表格单元格,避免宽度与分页受限 -->
|
||||
<div
|
||||
v-if="BusinessFormComponent && formFields.length === 0"
|
||||
class="mt-3"
|
||||
>
|
||||
<component
|
||||
:is="BusinessFormComponent"
|
||||
:id="printData.processInstance.businessKey"
|
||||
:readonly="true"
|
||||
:print-mode="true"
|
||||
/>
|
||||
</div>
|
||||
<table class="mt-3 w-full border-collapse">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td
|
||||
class="w-full border border-black p-1.5 text-center"
|
||||
|
||||
@@ -206,7 +206,7 @@ function shouldShowCustomUserSelect(
|
||||
/** 判断是否需要显示审批意见和附件 */
|
||||
function shouldShowReasonAndAttachment(task: any, nodeType: BpmNodeTypeEnum) {
|
||||
return (
|
||||
(task.reason || task.attachments?.length > 0) &&
|
||||
Boolean(task.reason || task.attachments?.length > 0) &&
|
||||
[BpmNodeTypeEnum.START_USER_NODE, BpmNodeTypeEnum.USER_TASK_NODE].includes(
|
||||
nodeType,
|
||||
)
|
||||
@@ -214,11 +214,17 @@ function shouldShowReasonAndAttachment(task: any, nodeType: BpmNodeTypeEnum) {
|
||||
}
|
||||
|
||||
function getAttachmentName(url: string) {
|
||||
return decodeURIComponent(url.slice(url.lastIndexOf('/') + 1));
|
||||
const cleanUrl = url.split(/[?#]/)[0] || '';
|
||||
const fileName = cleanUrl.slice(cleanUrl.lastIndexOf('/') + 1);
|
||||
try {
|
||||
return decodeURIComponent(fileName);
|
||||
} catch {
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
|
||||
function isImageAttachment(url: string) {
|
||||
const ext = url.split('.').pop()?.toLowerCase();
|
||||
const ext = url.split(/[?#]/)[0]?.split('.').pop()?.toLowerCase();
|
||||
return ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'webp'].includes(ext || '');
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ import { useRoute, useRouter } from 'vue-router';
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useTabs } from '@vben/hooks';
|
||||
|
||||
import { Button, Card, TabPane, Tabs } from 'antdv-next';
|
||||
import { Card, TabPane, Tabs } from 'antdv-next';
|
||||
|
||||
import { getBusiness } from '#/api/crm/business';
|
||||
import { getOperateLogPage } from '#/api/crm/operateLog';
|
||||
import { BizTypeEnum } from '#/api/crm/permission';
|
||||
import { useDescription } from '#/components/description';
|
||||
import { OperateLog } from '#/components/operate-log';
|
||||
import { ACTION_ICON, TableAction } from '#/components/table-action';
|
||||
import { $t } from '#/locales';
|
||||
import { ContactDetailsList } from '#/views/crm/contact/components';
|
||||
import { ContractDetailsList } from '#/views/crm/contract/components';
|
||||
@@ -108,27 +109,36 @@ onMounted(() => {
|
||||
<TransferModal @success="getBusinessDetail" />
|
||||
<UpStatusModal @success="getBusinessDetail" />
|
||||
<template #extra>
|
||||
<div class="flex items-center gap-2">
|
||||
<Button
|
||||
v-if="permissionListRef?.validateWrite"
|
||||
type="primary"
|
||||
@click="handleEdit"
|
||||
>
|
||||
{{ $t('ui.actionTitle.edit') }}
|
||||
</Button>
|
||||
<Button
|
||||
v-if="permissionListRef?.validateWrite"
|
||||
@click="handleUpdateStatus"
|
||||
>
|
||||
变更商机状态
|
||||
</Button>
|
||||
<Button
|
||||
v-if="permissionListRef?.validateOwnerUser"
|
||||
@click="handleTransfer"
|
||||
>
|
||||
转移
|
||||
</Button>
|
||||
</div>
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
label: '返回',
|
||||
type: 'default',
|
||||
icon: 'lucide:arrow-left',
|
||||
onClick: handleBack,
|
||||
},
|
||||
{
|
||||
label: $t('ui.actionTitle.edit'),
|
||||
type: 'primary',
|
||||
icon: ACTION_ICON.EDIT,
|
||||
auth: ['crm:business:update'],
|
||||
ifShow: permissionListRef?.validateWrite,
|
||||
onClick: handleEdit,
|
||||
},
|
||||
{
|
||||
label: '变更商机状态',
|
||||
type: 'primary',
|
||||
ifShow: permissionListRef?.validateWrite,
|
||||
onClick: handleUpdateStatus,
|
||||
},
|
||||
{
|
||||
label: '转移',
|
||||
type: 'primary',
|
||||
ifShow: permissionListRef?.validateOwnerUser,
|
||||
onClick: handleTransfer,
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
<Card class="min-h-[10%]">
|
||||
<Descriptions :data="business" />
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
|
||||
export const schema: VbenFormSchema[] = [
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
@@ -14,17 +16,17 @@ export const schema: VbenFormSchema[] = [
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
component: 'Input',
|
||||
fieldName: 'notifyDays',
|
||||
componentProps: {
|
||||
placeholder: '请输入天数',
|
||||
class: '!w-full',
|
||||
min: 0,
|
||||
precision: 0,
|
||||
},
|
||||
renderComponentContent: () => ({
|
||||
addonBefore: () => '提前',
|
||||
addonAfter: () => '天提醒',
|
||||
}),
|
||||
rules: z.coerce.number().int().min(0, '天数不能小于 0'),
|
||||
dependencies: {
|
||||
triggerFields: ['notifyEnabled'],
|
||||
show: (values) => values.notifyEnabled,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
|
||||
export const schema: VbenFormSchema[] = [
|
||||
{
|
||||
component: 'RadioGroup',
|
||||
@@ -13,33 +15,33 @@ export const schema: VbenFormSchema[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
component: 'Input',
|
||||
fieldName: 'contactExpireDays',
|
||||
componentProps: {
|
||||
placeholder: '请输入天数',
|
||||
class: '!w-full',
|
||||
min: 0,
|
||||
precision: 0,
|
||||
},
|
||||
renderComponentContent: () => ({
|
||||
addonAfter: () => '天不跟进或',
|
||||
}),
|
||||
rules: z.coerce.number().int().min(0, '天数不能小于 0'),
|
||||
dependencies: {
|
||||
triggerFields: ['enabled'],
|
||||
show: (value) => value.enabled,
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
component: 'Input',
|
||||
fieldName: 'dealExpireDays',
|
||||
renderComponentContent: () => ({
|
||||
addonBefore: () => '或',
|
||||
addonAfter: () => '天未成交',
|
||||
}),
|
||||
componentProps: {
|
||||
placeholder: '请输入天数',
|
||||
class: '!w-full',
|
||||
min: 0,
|
||||
precision: 0,
|
||||
},
|
||||
rules: z.coerce.number().int().min(0, '天数不能小于 0'),
|
||||
dependencies: {
|
||||
triggerFields: ['enabled'],
|
||||
show: (value) => value.enabled,
|
||||
@@ -62,17 +64,17 @@ export const schema: VbenFormSchema[] = [
|
||||
defaultValue: false,
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
component: 'Input',
|
||||
fieldName: 'notifyDays',
|
||||
componentProps: {
|
||||
placeholder: '请输入天数',
|
||||
class: '!w-full',
|
||||
min: 0,
|
||||
precision: 0,
|
||||
},
|
||||
renderComponentContent: () => ({
|
||||
addonBefore: () => '提前',
|
||||
addonAfter: () => '天提醒',
|
||||
}),
|
||||
rules: z.coerce.number().int().min(0, '天数不能小于 0'),
|
||||
dependencies: {
|
||||
triggerFields: ['notifyEnabled'],
|
||||
show: (value) => value.enabled && value.notifyEnabled,
|
||||
|
||||
@@ -81,7 +81,7 @@ const recentForwardConversations = computed(() =>
|
||||
.map((key) => byKey.value.get(key))
|
||||
.filter(
|
||||
(c): c is Conversation =>
|
||||
c !== null && !hideSet.value.has(getConversationKey(c)),
|
||||
c != null && !hideSet.value.has(getConversationKey(c)),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -96,7 +96,7 @@ const selectedConversations = computed(() =>
|
||||
.map((key) => byKey.value.get(key))
|
||||
.filter(
|
||||
(conversation): conversation is Conversation =>
|
||||
conversation !== null &&
|
||||
conversation != null &&
|
||||
!hideSet.value.has(getConversationKey(conversation)),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -88,12 +88,12 @@ const myId = computed(() => getCurrentUserId());
|
||||
/** 历史退群群:禁所有群操作入口(邀请 / 移出 / 改资料 / 禁言 / 审批 / 退出等),只保留展示;props.group 是 GroupLite 无 joinStatus,回 store 取全量 */
|
||||
const isQuitGroup = computed(() => {
|
||||
const id = props.group?.id;
|
||||
return id !== null && isGroupQuit(groupStore.getGroup(id));
|
||||
return id != null && isGroupQuit(groupStore.getGroup(id));
|
||||
});
|
||||
const isOwner = computed(
|
||||
() =>
|
||||
!isQuitGroup.value &&
|
||||
props.group !== null &&
|
||||
props.group != null &&
|
||||
props.group.ownerId === myId.value,
|
||||
);
|
||||
/** 当前用户在群里的角色(来自 props.members 的 me 行);用于判定是否可移出他人 */
|
||||
|
||||
@@ -86,7 +86,7 @@ const showSendName = computed(() => {
|
||||
return false;
|
||||
}
|
||||
const lastType = props.conversation.lastMessageType;
|
||||
return lastType !== null && isNormalMessage(lastType);
|
||||
return lastType != null && isNormalMessage(lastType);
|
||||
});
|
||||
|
||||
/** 列表展示文案:草稿优先(对齐微信 PC:有草稿时盖掉最后一条预览)→ 撤回实时算 → lastContent 兜底 */
|
||||
@@ -96,7 +96,7 @@ const lastContentDisplay = computed(() => {
|
||||
}
|
||||
if (
|
||||
props.conversation.lastMessageType === ImContentType.RECALL &&
|
||||
props.conversation.lastSenderId !== null
|
||||
props.conversation.lastSenderId != null
|
||||
) {
|
||||
return buildRecallTip(
|
||||
props.conversation.lastSenderId,
|
||||
|
||||
@@ -251,7 +251,7 @@ const redialRtcCall = inject(IM_RTC_REDIAL_KEY);
|
||||
/** 私聊 RTC_CALL_END 气泡点击:用同款 mediaType 重拨 */
|
||||
function handleRtcCallBubbleClick() {
|
||||
const mediaType = rtcCallEndPrivatePayload.value?.mediaType;
|
||||
if (mediaType === null) {
|
||||
if (mediaType == null) {
|
||||
return;
|
||||
}
|
||||
redialRtcCall?.(mediaType);
|
||||
|
||||
@@ -243,7 +243,7 @@ function handleConfirm() {
|
||||
message.warning(multiple.value ? '请至少选择一条数据' : '请选择一条数据');
|
||||
return;
|
||||
}
|
||||
emit('selected', multiple.value ? rows : [rows[0]]);
|
||||
emit('selected', multiple.value ? rows : [rows[0]!]);
|
||||
open.value = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ const showClear = computed(() => {
|
||||
props.allowClear &&
|
||||
!props.disabled &&
|
||||
hovering.value &&
|
||||
props.modelValue !== null
|
||||
props.modelValue != null
|
||||
);
|
||||
});
|
||||
|
||||
/** 根据编号查询群信息(用于编辑回显) */
|
||||
async function resolveItemById(id: number | undefined) {
|
||||
if (id === null) {
|
||||
if (id == null) {
|
||||
selectedItem.value = undefined;
|
||||
return;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ function handleClick(event: MouseEvent) {
|
||||
clearSelected();
|
||||
return;
|
||||
}
|
||||
dialogRef.value?.open(props.modelValue === null ? [] : [props.modelValue]);
|
||||
dialogRef.value?.open(props.modelValue == null ? [] : [props.modelValue]);
|
||||
}
|
||||
|
||||
/** 弹窗选中回调 */
|
||||
|
||||
@@ -55,7 +55,7 @@ export async function runIncrementalPull<T extends PullRecord>(
|
||||
const storedCursor = await getPullCursor(cursorKey);
|
||||
const highWater = { ...storedCursor };
|
||||
let cursor =
|
||||
storedCursor.lastUpdateTime === null
|
||||
storedCursor.lastUpdateTime == null
|
||||
? {}
|
||||
: {
|
||||
lastUpdateTime: Math.max(
|
||||
@@ -89,12 +89,12 @@ export async function runIncrementalPull<T extends PullRecord>(
|
||||
if (!last) {
|
||||
return;
|
||||
}
|
||||
if (last.updateTime === null) {
|
||||
if (last.updateTime == null) {
|
||||
return;
|
||||
}
|
||||
cursor = { lastUpdateTime: last.updateTime, lastId: last.id };
|
||||
if (
|
||||
highWater.lastUpdateTime === null ||
|
||||
highWater.lastUpdateTime == null ||
|
||||
cursor.lastUpdateTime > highWater.lastUpdateTime ||
|
||||
(cursor.lastUpdateTime === highWater.lastUpdateTime &&
|
||||
cursor.lastId > (highWater.lastId ?? 0))
|
||||
@@ -154,14 +154,14 @@ export async function runMinIdPull<T extends { id?: number }>(options: {
|
||||
// 本批最大消息 id 作为下次游标;无有效 id 则本批 apply 后停(无法继续翻页)
|
||||
const validIds = list
|
||||
.map((record) => record.id)
|
||||
.filter((id): id is number => id !== null);
|
||||
.filter((id): id is number => id != null);
|
||||
const nextMinId = validIds.length > 0 ? Math.max(...validIds) : undefined;
|
||||
// applyPage 返回 false:本页未落地(如入库失败),不推进游标并终止,避免漏消息
|
||||
if ((await applyPage(list, nextMinId)) === false) {
|
||||
return;
|
||||
}
|
||||
// 无有效 id,或游标没前进(后端契约是 id > minId,理论不会出现):停,防御死翻
|
||||
if (nextMinId === null || nextMinId <= minId) {
|
||||
if (nextMinId == null || nextMinId <= minId) {
|
||||
return;
|
||||
}
|
||||
minId = nextMinId;
|
||||
|
||||
@@ -587,7 +587,7 @@ watch([activeTab, upstreamTab, downstreamTab], () => {
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'dataType'">
|
||||
{{ record.dataType ?? '-' }}
|
||||
{{ record.event?.dataType ?? '-' }}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'dataDefinition'">
|
||||
<DataDefinition :data="record" />
|
||||
|
||||
@@ -128,7 +128,7 @@ function validateStep(_rule: any, _value: any) {
|
||||
@change="unitChange"
|
||||
:options="[
|
||||
...unitOptions.map((item) => ({
|
||||
label: `{{ \`${item.label}-${item.value}\` }}`,
|
||||
label: `${item.label}-${item.value}`,
|
||||
value: `${item.label}-${item.value}`,
|
||||
})),
|
||||
]"
|
||||
|
||||
@@ -113,7 +113,7 @@ if (!props.isStructDataSpecs && !props.isParams) {
|
||||
@change="handleChange"
|
||||
:options="[
|
||||
...dataTypeOptions.map((option) => ({
|
||||
label: `{{ \`${option.value}(${option.label})\` }}`,
|
||||
label: `${option.value}(${option.label})`,
|
||||
value: option.value,
|
||||
})),
|
||||
]"
|
||||
|
||||
@@ -45,8 +45,12 @@ const canAdd = computed(() => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
// oxlint-disable-next-line unicorn/no-nested-ternary
|
||||
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
|
||||
let ids: number[] = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
ids = newValue;
|
||||
} else if (newValue) {
|
||||
ids = [newValue];
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
productSpus.value = [];
|
||||
return;
|
||||
@@ -54,7 +58,7 @@ watch(
|
||||
// 只有商品发生变化时才重新查询
|
||||
if (
|
||||
productSpus.value.length === 0 ||
|
||||
productSpus.value.some((spu) => !ids.includes(spu.id))
|
||||
productSpus.value.some((spu) => spu.id == null || !ids.includes(spu.id))
|
||||
) {
|
||||
productSpus.value = await getSpuDetailList(ids);
|
||||
}
|
||||
|
||||
@@ -46,8 +46,12 @@ const canAdd = computed(() => {
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
// oxlint-disable-next-line unicorn/no-nested-ternary
|
||||
const ids = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
|
||||
let ids: number[] = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
ids = newValue;
|
||||
} else if (newValue) {
|
||||
ids = [newValue];
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
activityList.value = [];
|
||||
return;
|
||||
@@ -55,7 +59,9 @@ watch(
|
||||
// 只有活动发生变化时才重新查询
|
||||
if (
|
||||
activityList.value.length === 0 ||
|
||||
activityList.value.some((activity) => !ids.includes(activity.id))
|
||||
activityList.value.some(
|
||||
(activity) => activity.id == null || !ids.includes(activity.id),
|
||||
)
|
||||
) {
|
||||
activityList.value = await getCombinationActivityListByIds(ids);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button } from 'antdv-next';
|
||||
|
||||
import { VerticalSpace } from '#/views/mall/promotion/components';
|
||||
import { VerticalButtonGroup } from '#/views/mall/promotion/components';
|
||||
|
||||
import { components } from './mobile';
|
||||
|
||||
@@ -108,7 +108,7 @@ const handleDeleteComponent = () => {
|
||||
class="component-toolbar"
|
||||
v-if="showToolbar && component.name && active"
|
||||
>
|
||||
<VerticalSpace size="small">
|
||||
<VerticalButtonGroup size="small">
|
||||
<Button
|
||||
:disabled="!canMoveUp"
|
||||
type="primary"
|
||||
@@ -163,7 +163,7 @@ const handleDeleteComponent = () => {
|
||||
>
|
||||
<IconifyIcon icon="lucide:trash-2" />
|
||||
</Button>
|
||||
</VerticalSpace>
|
||||
</VerticalButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -99,7 +99,7 @@ function calculateWidth() {
|
||||
:class="[
|
||||
{
|
||||
'w-full': property.layoutType !== 'oneColSmallImg',
|
||||
'w-[calc(100vh-140px-16px)]':
|
||||
'w-[calc(100%-140px-16px)]':
|
||||
property.layoutType === 'oneColSmallImg',
|
||||
},
|
||||
]"
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { cloneDeep, isEmpty, isString } from '@vben/utils';
|
||||
|
||||
import { Button, Card, Col, QRCode, Row, Tag, Tooltip } from 'antdv-next';
|
||||
import { Button, Card, Col, QRCode, Row, Space, Tag, Tooltip } from 'antdv-next';
|
||||
import draggable from 'vuedraggable';
|
||||
|
||||
import statusBarImg from '#/assets/imgs/diy/statusBar.png';
|
||||
|
||||
@@ -7,4 +7,4 @@ export { default as Draggable } from './draggable/index.vue';
|
||||
export { default as InputWithColor } from './input-with-color/index.vue';
|
||||
|
||||
export { default as MagicCubeEditor } from './magic-cube-editor/index.vue';
|
||||
export { default as VerticalSpace } from './vertical-button-group/index.vue';
|
||||
export { default as VerticalButtonGroup } from './vertical-button-group/index.vue';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { SpaceCompact } from 'antdv-next';
|
||||
import { Space, SpaceCompact } from 'antdv-next';
|
||||
|
||||
/**
|
||||
* 垂直按钮组
|
||||
* Ant Design Vue 的按钮组,通过 Space 实现垂直布局
|
||||
*/
|
||||
defineOptions({ name: 'VerticalSpace' });
|
||||
defineOptions({ name: 'VerticalButtonGroup' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -54,7 +54,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ const [DetailFormModal, detailFormModalApi] = useVbenModal({
|
||||
function handleRefresh() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
gridApi.query();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ defineProps<{
|
||||
<div v-else-if="item.event === 'location_select'">
|
||||
<Tag>选择地理位置</Tag>
|
||||
</div>
|
||||
<div v-else-if="item.event === 'SCAN'">
|
||||
<Tag>扫码</Tag>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Tag color="error">未知事件类型</Tag>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,16 @@ import { computed, ref } from 'vue';
|
||||
import { confirm } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Col, Input, Layout, Row, TextArea } from 'antdv-next';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Input,
|
||||
Layout,
|
||||
LayoutContent,
|
||||
LayoutSider,
|
||||
Row,
|
||||
TextArea,
|
||||
} from 'antdv-next';
|
||||
|
||||
import { createEmptyNewsItem } from '#/api/mp/draft';
|
||||
import { Tinymce as RichTextArea } from '#/components/tinymce';
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
const props = defineProps<{ type: UploadType }>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
uploaded: [v: Promise<void>];
|
||||
uploaded: [];
|
||||
}>();
|
||||
|
||||
const accountId = inject<number>('accountId');
|
||||
|
||||
@@ -32,7 +32,7 @@ withDefaults(
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:open': [v: boolean];
|
||||
uploaded: [v: Promise<void>];
|
||||
uploaded: [];
|
||||
}>();
|
||||
|
||||
const accountId = inject<number>('accountId');
|
||||
|
||||
@@ -16,7 +16,7 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'delete', v: Promise<void>): void;
|
||||
(e: 'delete'): void;
|
||||
(e: 'update:modelValue', v: any): void;
|
||||
}>();
|
||||
|
||||
|
||||
@@ -13,7 +13,15 @@ import {
|
||||
import { useTabs } from '@vben/hooks';
|
||||
import { fenToYuan, formatDate } from '@vben/utils';
|
||||
|
||||
import { Button, Card, Descriptions, Input, message, QRCode } from 'antdv-next';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
DescriptionsItem,
|
||||
Input,
|
||||
message,
|
||||
QRCode,
|
||||
} from 'antdv-next';
|
||||
|
||||
import { getOrder, submitOrder } from '#/api/pay/order';
|
||||
|
||||
@@ -205,6 +213,7 @@ function displayQrCode(channelCode: string, data: any) {
|
||||
url: data.displayContent,
|
||||
visible: true,
|
||||
};
|
||||
modalApi.open();
|
||||
}
|
||||
|
||||
/** 提交支付后(App) */
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import type { SystemDeptApi } from '#/api/system/dept';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { handleTree } from '@vben/utils';
|
||||
|
||||
import { Input, Spin, Tree } from 'antdv-next';
|
||||
|
||||
import { getSimpleDeptList } from '#/api/system/dept';
|
||||
|
||||
const emit = defineEmits(['select']);
|
||||
const deptList = ref<SystemDeptApi.Dept[]>([]); // 部门列表
|
||||
const deptTree = ref<any[]>([]); // 部门树
|
||||
const expandedKeys = ref<number[]>([]); // 展开的节点
|
||||
const loading = ref(false); // 加载状态
|
||||
const searchValue = ref(''); // 搜索值
|
||||
|
||||
/** 处理搜索逻辑 */
|
||||
function handleSearch(e: any) {
|
||||
const value = e.target.value;
|
||||
searchValue.value = value;
|
||||
const filteredList = value
|
||||
? deptList.value.filter((item) =>
|
||||
item.name.toLowerCase().includes(value.toLowerCase()),
|
||||
)
|
||||
: deptList.value;
|
||||
deptTree.value = handleTree(filteredList);
|
||||
// 展开所有节点
|
||||
expandedKeys.value = deptTree.value.map((node) => node.id!);
|
||||
}
|
||||
|
||||
/** 选中部门 */
|
||||
function handleSelect(selectedNodeKeys: any[], info: any) {
|
||||
const selectedKey = selectedNodeKeys[0] ?? info.node?.id ?? info.node?.key;
|
||||
const dept = info.selected
|
||||
? deptList.value.find((item) => String(item.id) === String(selectedKey))
|
||||
: undefined;
|
||||
emit('select', dept);
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const data = await getSimpleDeptList();
|
||||
deptList.value = data;
|
||||
deptTree.value = handleTree(data);
|
||||
} catch (error) {
|
||||
console.error('获取部门数据失败', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Input
|
||||
placeholder="搜索部门"
|
||||
allow-clear
|
||||
v-model:value="searchValue"
|
||||
@change="handleSearch"
|
||||
class="w-full"
|
||||
>
|
||||
<template #prefix>
|
||||
<IconifyIcon icon="lucide:search" class="size-4" />
|
||||
</template>
|
||||
</Input>
|
||||
<Spin :spinning="loading" :classes="{ root: 'w-full' }">
|
||||
<Tree
|
||||
@select="handleSelect"
|
||||
v-if="deptTree.length > 0"
|
||||
class="pt-2"
|
||||
:tree-data="deptTree"
|
||||
:default-expand-all="true"
|
||||
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
||||
/>
|
||||
<div v-else-if="!loading" class="py-4 text-center text-gray-500">
|
||||
暂无数据
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</template>
|
||||
@@ -68,7 +68,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getCheckOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getCheckOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断盘库单是否可修改 */
|
||||
|
||||
@@ -61,7 +61,7 @@ const [DetailModal, detailModalApi] = useVbenModal({
|
||||
function clearDetailMap() {
|
||||
for (const id of Object.keys(detailMap)) {
|
||||
const key = Number(id);
|
||||
delete detailMap.key;
|
||||
delete detailMap[key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,8 +107,11 @@ async function handleExpandChange(
|
||||
return;
|
||||
}
|
||||
const key = row.id;
|
||||
delete detailMap.key;
|
||||
detailMap[row.id!] = await getMovementOrderDetailListByOrderId(row.id!);
|
||||
if (key == null) {
|
||||
return;
|
||||
}
|
||||
delete detailMap[key];
|
||||
detailMap[key] = await getMovementOrderDetailListByOrderId(key);
|
||||
}
|
||||
|
||||
/** 判断移库单是否可修改 */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user