diff --git a/src/components/custom/business-rich-text-view.vue b/src/components/custom/business-rich-text-view.vue index 5a7f9ff..4d4ab37 100644 --- a/src/components/custom/business-rich-text-view.vue +++ b/src/components/custom/business-rich-text-view.vue @@ -21,6 +21,7 @@ const isEmpty = computed(() => !safeHtml.value || safeHtml.value.replace(/<[^>]+ diff --git a/src/components/custom/business-user-picker.vue b/src/components/custom/business-user-picker.vue new file mode 100644 index 0000000..3faea0e --- /dev/null +++ b/src/components/custom/business-user-picker.vue @@ -0,0 +1,920 @@ + + + + + diff --git a/src/components/custom/business-user-picker/components/user-picker-trigger.vue b/src/components/custom/business-user-picker/components/user-picker-trigger.vue new file mode 100644 index 0000000..9e023e4 --- /dev/null +++ b/src/components/custom/business-user-picker/components/user-picker-trigger.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/src/components/custom/business-user-picker/composables/use-chain-source.ts b/src/components/custom/business-user-picker/composables/use-chain-source.ts new file mode 100644 index 0000000..635e79b --- /dev/null +++ b/src/components/custom/business-user-picker/composables/use-chain-source.ts @@ -0,0 +1,90 @@ +import { computed, ref } from 'vue'; +import { fetchGetUserManagementRelationTree } from '@/service/api'; +import type { TreeCheckState } from './use-dept-source'; + +type ChainNode = Api.SystemManage.UserManagementRelationTreeRespVO; + +export function useChainSource(selectedIds: () => Set, disabledUserIdSet: () => Set) { + const tree = ref([]); + const loading = ref(false); + let loaded = false; + + async function ensureLoaded() { + if (loaded) return; + loading.value = true; + try { + const { data } = await fetchGetUserManagementRelationTree({ fromUserIndex: false }); + tree.value = data ?? []; + loaded = true; + } finally { + loading.value = false; + } + } + + function nodeKey(node: ChainNode): string { + return node.id ?? `chain_${node.userId}`; + } + + function getNodeUserIds(node: ChainNode): string[] { + const ids = new Set([String(node.userId)]); + if (node.children) { + for (const c of node.children) { + for (const id of getNodeUserIds(c)) ids.add(id); + } + } + return [...ids]; + } + + function getNodeCheckState(node: ChainNode): TreeCheckState { + const ids = getNodeUserIds(node).filter(id => !disabledUserIdSet().has(id)); + if (!ids.length) return 'none'; + const sel = ids.filter(id => selectedIds().has(id)).length; + if (sel === 0) return 'none'; + if (sel === ids.length) return 'all'; + return 'partial'; + } + + function findNode(list: ChainNode[], key: string): ChainNode | null { + for (const n of list) { + if (nodeKey(n) === key) return n; + if (n.children) { + const r = findNode(n.children, key); + if (r) return r; + } + } + return null; + } + + function matchKeyword(node: ChainNode, kw: string): boolean { + if (!kw) return true; + if (node.userNickname.toLowerCase().includes(kw)) return true; + if (node.children) return node.children.some(c => matchKeyword(c, kw)); + return false; + } + + function filterByKeyword(kw: string) { + const lower = kw.trim().toLowerCase(); + if (!lower) return tree.value; + return tree.value.filter(n => matchKeyword(n, lower)); + } + + function getMetaText(node: ChainNode): string { + const total = getNodeUserIds(node).length; + return total > 1 ? `${total} 人` : ''; + } + + const treeProps = computed(() => ({ children: 'children', label: 'userNickname' }) as const); + + return { + tree, + loading, + treeProps, + ensureLoaded, + getNodeUserIds, + getNodeCheckState, + findNode, + filterByKeyword, + getMetaText, + nodeKey + }; +} diff --git a/src/components/custom/business-user-picker/composables/use-dept-source.ts b/src/components/custom/business-user-picker/composables/use-dept-source.ts new file mode 100644 index 0000000..ae7183e --- /dev/null +++ b/src/components/custom/business-user-picker/composables/use-dept-source.ts @@ -0,0 +1,99 @@ +import { computed, ref } from 'vue'; +import { fetchGetDeptSimpleList } from '@/service/api'; +import { buildMenuTree } from '@/views/system/shared/menu-tree'; + +export type TreeCheckState = 'none' | 'partial' | 'all'; + +export function useDeptSource( + userOptions: () => Api.SystemManage.UserSimple[], + selectedIds: () => Set, + disabledUserIdSet: () => Set +) { + const tree = ref([]); + const loading = ref(false); + let loaded = false; + + async function ensureLoaded() { + if (loaded) return; + loading.value = true; + try { + const { data } = await fetchGetDeptSimpleList(); + tree.value = data ? buildMenuTree(data) : []; + loaded = true; + } finally { + loading.value = false; + } + } + + function collectDeptIds(node: Api.SystemManage.DeptSimple): string[] { + const ids: string[] = [String(node.id)]; + if (node.children) { + for (const c of node.children) ids.push(...collectDeptIds(c)); + } + return ids; + } + + function getNodeUserIds(node: Api.SystemManage.DeptSimple): string[] { + const deptIds = new Set(collectDeptIds(node)); + return userOptions() + .filter(u => u.deptId !== null && u.deptId !== undefined && deptIds.has(String(u.deptId))) + .map(u => String(u.id)); + } + + function getNodeCheckState(node: Api.SystemManage.DeptSimple): TreeCheckState { + const ids = getNodeUserIds(node).filter(id => !disabledUserIdSet().has(id)); + if (!ids.length) return 'none'; + const sel = ids.filter(id => selectedIds().has(id)).length; + if (sel === 0) return 'none'; + if (sel === ids.length) return 'all'; + return 'partial'; + } + + function findNode(list: Api.SystemManage.DeptSimple[], key: string): Api.SystemManage.DeptSimple | null { + for (const n of list) { + if (String(n.id) === key) return n; + if (n.children) { + const r = findNode(n.children, key); + if (r) return r; + } + } + return null; + } + + function matchKeyword(node: Api.SystemManage.DeptSimple, kw: string): boolean { + if (!kw) return true; + if (node.name.toLowerCase().includes(kw)) return true; + if (node.children) return node.children.some(c => matchKeyword(c, kw)); + return false; + } + + function filterByKeyword(kw: string) { + const lower = kw.trim().toLowerCase(); + if (!lower) return tree.value; + return tree.value.filter(n => matchKeyword(n, lower)); + } + + function getMetaText(node: Api.SystemManage.DeptSimple): string { + const total = getNodeUserIds(node).length; + return total > 0 ? `${total} 人` : ''; + } + + function nodeKey(node: Api.SystemManage.DeptSimple): string { + return String(node.id); + } + + const treeProps = computed(() => ({ children: 'children', label: 'name' }) as const); + + return { + tree, + loading, + treeProps, + ensureLoaded, + getNodeUserIds, + getNodeCheckState, + findNode, + filterByKeyword, + getMetaText, + nodeKey + }; +} diff --git a/src/components/custom/business-user-picker/composables/use-picker-selection.ts b/src/components/custom/business-user-picker/composables/use-picker-selection.ts new file mode 100644 index 0000000..6b6c083 --- /dev/null +++ b/src/components/custom/business-user-picker/composables/use-picker-selection.ts @@ -0,0 +1,89 @@ +import { computed, ref } from 'vue'; + +export interface PickerSelectionOptions { + multiple: boolean; +} + +export function usePickerSelection(options: () => PickerSelectionOptions) { + const multiSet = ref>(new Set()); + const singleId = ref(null); + + const multiple = computed(() => options().multiple); + + function has(userId: string): boolean { + if (multiple.value) return multiSet.value.has(userId); + return singleId.value === userId; + } + + function toggle(userId: string) { + if (multiple.value) { + if (multiSet.value.has(userId)) multiSet.value.delete(userId); + else multiSet.value.add(userId); + multiSet.value = new Set(multiSet.value); + } else { + singleId.value = singleId.value === userId ? null : userId; + } + } + + function addMany(userIds: readonly string[]) { + if (!multiple.value) { + singleId.value = userIds[0] ?? singleId.value; + return; + } + for (const id of userIds) multiSet.value.add(id); + multiSet.value = new Set(multiSet.value); + } + + function removeMany(userIds: readonly string[]) { + if (!multiple.value) { + if (singleId.value && userIds.includes(singleId.value)) singleId.value = null; + return; + } + for (const id of userIds) multiSet.value.delete(id); + multiSet.value = new Set(multiSet.value); + } + + function clear(preserveIds?: readonly string[]) { + const keep = new Set((preserveIds ?? []).map(String)); + if (multiple.value) { + const next = new Set(); + for (const id of multiSet.value) { + if (keep.has(id)) next.add(id); + } + multiSet.value = next; + } else if (singleId.value && !keep.has(singleId.value)) singleId.value = null; + } + + function reset(initial: string | string[] | null | undefined) { + if (multiple.value) { + const ids = Array.isArray(initial) ? initial.map(String) : []; + multiSet.value = new Set(ids); + } else { + singleId.value = typeof initial === 'string' ? initial : null; + } + } + + const selectedIds = computed(() => { + if (multiple.value) return [...multiSet.value]; + return singleId.value ? [singleId.value] : []; + }); + + const size = computed(() => selectedIds.value.length); + + function commit(): string | string[] | null { + if (multiple.value) return [...multiSet.value]; + return singleId.value; + } + + return { + selectedIds, + size, + has, + toggle, + addMany, + removeMany, + clear, + reset, + commit + }; +} diff --git a/src/layouts/modules/global-header/components/notification-bell.vue b/src/layouts/modules/global-header/components/notification-bell.vue new file mode 100644 index 0000000..a28fc4a --- /dev/null +++ b/src/layouts/modules/global-header/components/notification-bell.vue @@ -0,0 +1,457 @@ + + + + + diff --git a/src/layouts/modules/global-header/index.vue b/src/layouts/modules/global-header/index.vue index 164daa0..071774b 100644 --- a/src/layouts/modules/global-header/index.vue +++ b/src/layouts/modules/global-header/index.vue @@ -7,6 +7,7 @@ import GlobalLogo from '../global-logo/index.vue'; import GlobalBreadcrumb from '../global-breadcrumb/index.vue'; import GlobalSearch from '../global-search/index.vue'; import ThemeButton from './components/theme-button.vue'; +import NotificationBell from './components/notification-bell.vue'; import UserAvatar from './components/user-avatar.vue'; defineOptions({ name: 'GlobalHeader' }); @@ -48,6 +49,7 @@ const { isFullscreen, toggle } = useFullscreen();
+ diff --git a/src/service/api/route.ts b/src/service/api/route.ts index d1f7f40..9952760 100644 --- a/src/service/api/route.ts +++ b/src/service/api/route.ts @@ -1,4 +1,3 @@ -import type { RouteMeta } from 'vue-router'; import type { ElegantConstRoute, LastLevelRouteKey } from '@elegant-router/types'; import { objectContextDomainConfigs } from '@/constants/object-context'; import { SYSTEM_SERVICE_PREFIX } from '@/constants/service'; diff --git a/src/typings/components.d.ts b/src/typings/components.d.ts index 093b12a..a9ae0ca 100644 --- a/src/typings/components.d.ts +++ b/src/typings/components.d.ts @@ -19,6 +19,7 @@ declare module 'vue' { BusinessFormSimpleDialog: typeof import('./../components/custom/business-form-simple-dialog.vue')['default'] BusinessRichTextEditor: typeof import('./../components/custom/business-rich-text-editor.vue')['default'] BusinessRichTextView: typeof import('./../components/custom/business-rich-text-view.vue')['default'] + BusinessUserPicker: typeof import('./../components/custom/business-user-picker.vue')['default'] BusinessUserSelect: typeof import('./../components/custom/business-user-select.vue')['default'] ButtonIcon: typeof import('./../components/custom/button-icon.vue')['default'] CountTo: typeof import('./../components/custom/count-to.vue')['default'] @@ -181,6 +182,7 @@ declare module 'vue' { TableSearchFields: typeof import('./../components/custom/table-search-fields.vue')['default'] TableSearchPanel: typeof import('./../components/custom/table-search-panel.vue')['default'] ThemeSchemaSwitch: typeof import('./../components/common/theme-schema-switch.vue')['default'] + UserPickerTrigger: typeof import('./../components/custom/business-user-picker/components/user-picker-trigger.vue')['default'] WaveBg: typeof import('./../components/custom/wave-bg.vue')['default'] WebSiteLink: typeof import('./../components/custom/web-site-link.vue')['default'] } diff --git a/src/views/personal-center/my-item/modules/personal-item-detail-dialog.vue b/src/views/personal-center/my-item/modules/personal-item-detail-dialog.vue index c2761bd..118d085 100644 --- a/src/views/personal-center/my-item/modules/personal-item-detail-dialog.vue +++ b/src/views/personal-center/my-item/modules/personal-item-detail-dialog.vue @@ -30,6 +30,7 @@ interface Props { } const props = withDefaults(defineProps(), { + rowData: null, defaultTab: 'worklog' }); diff --git a/src/views/product/list/modules/product-create-base-form.vue b/src/views/product/list/modules/product-create-base-form.vue index 1f5a340..5bf4c6b 100644 --- a/src/views/product/list/modules/product-create-base-form.vue +++ b/src/views/product/list/modules/product-create-base-form.vue @@ -2,7 +2,7 @@ import { computed } from 'vue'; import { RDMS_OBJECT_DIRECTION_DICT_CODE } from '@/constants/dict'; import { useForm, useFormRules } from '@/hooks/common/form'; -import BusinessUserSelect from '@/components/custom/business-user-select.vue'; +import BusinessUserPicker from '@/components/custom/business-user-picker.vue'; import DictSelect from '@/components/custom/dict-select.vue'; defineOptions({ name: 'ProductCreateBaseForm' }); @@ -72,9 +72,10 @@ defineExpose({ validate: runValidate }); - diff --git a/src/views/product/requirement/modules/module-tree-node.vue b/src/views/product/requirement/modules/module-tree-node.vue index dede9bd..b6381de 100644 --- a/src/views/product/requirement/modules/module-tree-node.vue +++ b/src/views/product/requirement/modules/module-tree-node.vue @@ -17,7 +17,14 @@ interface Props { } const props = withDefaults(defineProps(), { - level: 0 + level: 0, + selectedModuleId: undefined, + editingNodeId: undefined, + editingName: undefined, + addingChildParentId: undefined, + newChildModuleName: undefined, + rootModuleId: undefined, + moduleRequirementCountMap: undefined }); const emit = defineEmits([ diff --git a/src/views/product/requirement/modules/requirement-split-dialog.vue b/src/views/product/requirement/modules/requirement-split-dialog.vue index 968a857..d2582f9 100644 --- a/src/views/product/requirement/modules/requirement-split-dialog.vue +++ b/src/views/product/requirement/modules/requirement-split-dialog.vue @@ -1,7 +1,6 @@ - - - - diff --git a/src/views/workbench/modules/workbench-banner.vue b/src/views/workbench/modules/workbench-banner.vue index 1d783a8..ab2c402 100644 --- a/src/views/workbench/modules/workbench-banner.vue +++ b/src/views/workbench/modules/workbench-banner.vue @@ -1,273 +1,302 @@ diff --git a/src/views/workbench/modules/workbench-edit-overlay.vue b/src/views/workbench/modules/workbench-edit-overlay.vue index af7a08a..f2a9e24 100644 --- a/src/views/workbench/modules/workbench-edit-overlay.vue +++ b/src/views/workbench/modules/workbench-edit-overlay.vue @@ -8,6 +8,7 @@ const emit = defineEmits<{ (e: 'save'): void; (e: 'cancel'): void; (e: 'reset'): void; + (e: 'open-library'): void; }>(); @@ -18,6 +19,10 @@ const emit = defineEmits<{ 正在编辑布局——拖动模块换位 / 抽屉里把隐藏模块拖回来
+ + + 模块库 + 重置默认布局 取消 @@ -50,4 +55,7 @@ const emit = defineEmits<{ display: inline-flex; gap: 8px; } +.edit-overlay__btn-icon { + margin-right: 4px; +} diff --git a/src/views/workbench/modules/workbench-favorite.vue b/src/views/workbench/modules/workbench-favorite.vue deleted file mode 100644 index 20c6597..0000000 --- a/src/views/workbench/modules/workbench-favorite.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-mentions.vue b/src/views/workbench/modules/workbench-mentions.vue deleted file mode 100644 index a926e9f..0000000 --- a/src/views/workbench/modules/workbench-mentions.vue +++ /dev/null @@ -1,121 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-module-card.vue b/src/views/workbench/modules/workbench-module-card.vue index 6b91bda..75908e6 100644 --- a/src/views/workbench/modules/workbench-module-card.vue +++ b/src/views/workbench/modules/workbench-module-card.vue @@ -1,8 +1,12 @@ @@ -68,6 +86,18 @@ const categoryTagType: Record -import WorkbenchModuleCard from './workbench-module-card.vue'; - -defineOptions({ name: 'WorkbenchMyCompletionRate' }); - -interface Props { - editing?: boolean; - collapsed?: boolean; -} -withDefaults(defineProps(), { editing: false, collapsed: false }); -defineEmits<{ (e: 'hide'): void; (e: 'toggle-collapse'): void }>(); - -const rate = 72; // % -const teamAvg = 65; -const total = 25; -const completed = 18; -const onTime = 13; -const overdue = 5; -const diff = rate - teamAvg; - - - - - diff --git a/src/views/workbench/modules/workbench-my-execution.vue b/src/views/workbench/modules/workbench-my-execution.vue index b01044b..1bf0b2a 100644 --- a/src/views/workbench/modules/workbench-my-execution.vue +++ b/src/views/workbench/modules/workbench-my-execution.vue @@ -1,4 +1,12 @@ diff --git a/src/views/workbench/modules/workbench-my-requirement.vue b/src/views/workbench/modules/workbench-my-requirement.vue deleted file mode 100644 index f31b1b6..0000000 --- a/src/views/workbench/modules/workbench-my-requirement.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-my-task.vue b/src/views/workbench/modules/workbench-my-task.vue deleted file mode 100644 index ec99d4a..0000000 --- a/src/views/workbench/modules/workbench-my-task.vue +++ /dev/null @@ -1,107 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-my-week-worklog.vue b/src/views/workbench/modules/workbench-my-week-worklog.vue index d0f541d..cc38003 100644 --- a/src/views/workbench/modules/workbench-my-week-worklog.vue +++ b/src/views/workbench/modules/workbench-my-week-worklog.vue @@ -1,4 +1,18 @@ diff --git a/src/views/workbench/modules/workbench-notice-notification.vue b/src/views/workbench/modules/workbench-notice-notification.vue index 53e76bc..cd5c30d 100644 --- a/src/views/workbench/modules/workbench-notice-notification.vue +++ b/src/views/workbench/modules/workbench-notice-notification.vue @@ -1,4 +1,5 @@ @@ -65,50 +131,163 @@ const notifications: Row[] = [ diff --git a/src/views/workbench/modules/workbench-personal-item.vue b/src/views/workbench/modules/workbench-personal-item.vue deleted file mode 100644 index 1ce0e39..0000000 --- a/src/views/workbench/modules/workbench-personal-item.vue +++ /dev/null @@ -1,73 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-product-snapshot.vue b/src/views/workbench/modules/workbench-product-snapshot.vue index e5f09e1..ec9ae6e 100644 --- a/src/views/workbench/modules/workbench-product-snapshot.vue +++ b/src/views/workbench/modules/workbench-product-snapshot.vue @@ -77,7 +77,7 @@ function onChange(id: string) { @toggle-collapse="$emit('toggle-collapse')" >
- pin + 当前产品: diff --git a/src/views/workbench/modules/workbench-project-grid.vue b/src/views/workbench/modules/workbench-project-grid.vue index bc7a92b..1a8bd8f 100644 --- a/src/views/workbench/modules/workbench-project-grid.vue +++ b/src/views/workbench/modules/workbench-project-grid.vue @@ -1,8 +1,8 @@ - - - - diff --git a/src/views/workbench/modules/workbench-recent-visit.vue b/src/views/workbench/modules/workbench-recent-visit.vue deleted file mode 100644 index d64d75e..0000000 --- a/src/views/workbench/modules/workbench-recent-visit.vue +++ /dev/null @@ -1,81 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-risk-alert.vue b/src/views/workbench/modules/workbench-risk-alert.vue deleted file mode 100644 index 5d11f95..0000000 --- a/src/views/workbench/modules/workbench-risk-alert.vue +++ /dev/null @@ -1,124 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-shortcut-picker.vue b/src/views/workbench/modules/workbench-shortcut-picker.vue index 1b29e6f..75ff444 100644 --- a/src/views/workbench/modules/workbench-shortcut-picker.vue +++ b/src/views/workbench/modules/workbench-shortcut-picker.vue @@ -1,6 +1,8 @@ @@ -40,69 +38,243 @@ function level(n: number): 'ok' | 'warn' | 'over' { @hide="$emit('hide')" @toggle-collapse="$emit('toggle-collapse')" > -
    -
  • - {{ row.name }} -
    -
    +
    +
    + 高负载 + + {{ view.highCount }} + + +
    +
    + 中负载 + + {{ view.midCount }} + + +
    +
    + 临期 + 逾期 + + {{ view.urgentTotal }} + + +
    +
    + +
      +
    • + + {{ m.memberName }} +
      +
      + +
      + +
      + +{{ m.overflowExtra }}
      - - {{ row.inProgress }}{{ level(row.inProgress) === 'over' ? ' ⚠' : '' }} + + + {{ m.inProgress }} + 进行 + + + + + {{ m.urgent }} + 临期 + + + +
    -
    阈值 ≥6 高负载 · ≥4 中负载
    + +
    高 = 进行中 ≥ 6 或 临期+逾期 ≥ 2 · 中 = 进行中 ≥ 4 或 临期+逾期 ≥ 1
    diff --git a/src/views/workbench/modules/workbench-team-todo.vue b/src/views/workbench/modules/workbench-team-todo.vue deleted file mode 100644 index 5f07af9..0000000 --- a/src/views/workbench/modules/workbench-team-todo.vue +++ /dev/null @@ -1,182 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-team-worklog.vue b/src/views/workbench/modules/workbench-team-worklog.vue deleted file mode 100644 index e19294c..0000000 --- a/src/views/workbench/modules/workbench-team-worklog.vue +++ /dev/null @@ -1,112 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-ticket-sla.vue b/src/views/workbench/modules/workbench-ticket-sla.vue deleted file mode 100644 index 70673a1..0000000 --- a/src/views/workbench/modules/workbench-ticket-sla.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - - - diff --git a/src/views/workbench/modules/workbench-todo-panel.vue b/src/views/workbench/modules/workbench-todo-panel.vue index 641af6e..85ae25c 100644 --- a/src/views/workbench/modules/workbench-todo-panel.vue +++ b/src/views/workbench/modules/workbench-todo-panel.vue @@ -57,7 +57,7 @@ const mainTabs: Array<{ key: WorkbenchTodoMainTab; label: string }> = [ { key: 'task', label: '任务' }, { key: 'ticket', label: '工单' }, { key: 'personal', label: '个人事项' }, - { key: 'review', label: '待评审' } + { key: 'approval', label: '待审批' } ]; const deadlineFilters: Array<{ key: Exclude; label: string }> = [ @@ -85,7 +85,7 @@ const tabCounts = computed(() => { task: 0, ticket: 0, personal: 0, - review: 0 + approval: 0 }; allItems.value.forEach(item => { counts[item.category] += 1; @@ -99,7 +99,7 @@ const tabOverdueCount = computed(() => { task: 0, ticket: 0, personal: 0, - review: 0 + approval: 0 }; allItems.value.forEach(item => { if (!isWorkbenchTodoOverdue(item)) return; @@ -144,6 +144,7 @@ watch([activeTab, activeDeadlineFilter, activeSort], () => { function handleSelectTab(key: WorkbenchTodoMainTab) { if (activeTab.value === key) return; activeTab.value = key; + if (key === 'approval') activeDeadlineFilter.value = null; activeDeadlineFilter.value = null; if (key !== 'task' && activeSort.value === 'priority') { activeSort.value = 'deadline'; @@ -209,7 +210,7 @@ function getDeadlineToneClass(item: WorkbenchTodoItem) {
    -
    +
    +
    diff --git a/src/views/workbench/modules/workbench-worklog-reminder.vue b/src/views/workbench/modules/workbench-worklog-reminder.vue deleted file mode 100644 index 9bb4897..0000000 --- a/src/views/workbench/modules/workbench-worklog-reminder.vue +++ /dev/null @@ -1,111 +0,0 @@ - - - - -