From bbccbe49be57c507cea6bf07a29421ef39b470eb Mon Sep 17 00:00:00 2001 From: baiqi Date: Thu, 28 Sep 2023 16:31:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B6=88=E6=81=AF=E7=AE=A1=E7=90=86):=20?= =?UTF-8?q?=20useSelect=E9=92=A9=E5=AD=90&=E6=B6=88=E6=81=AF=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=83=A8=E5=88=86=E9=A1=B5=E9=9D=A2&=E9=83=A8?= =?UTF-8?q?=E5=88=86=E7=BB=84=E4=BB=B6=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project-management/fileManagement.ts | 188 ++++++ .../project-management/messageManagement.ts | 153 +++++ .../project-management/messageManagement.ts | 6 + frontend/src/assets/style/arco-reset.less | 44 ++ .../business/ms-card-list/index.vue | 12 +- .../components/business/ms-cascader/index.vue | 70 +-- .../business/ms-form-item-sub/index.vue | 13 +- .../{ms-search-select => ms-select}/index.tsx | 146 ++++- .../src/components/pure/ms-button/index.vue | 2 +- .../src/components/pure/ms-button/not-mr.vue | 70 --- .../src/components/pure/ms-card/index.vue | 41 +- .../src/components/pure/ms-drawer/index.vue | 23 +- .../src/components/pure/ms-list/index.vue | 8 - .../src/components/pure/ms-timeline/index.vue | 6 - frontend/src/components/pure/navbar/index.vue | 2 +- frontend/src/config/pathMap.ts | 14 + frontend/src/enums/routeEnum.ts | 2 + frontend/src/hooks/useContainerShadow.ts | 13 +- frontend/src/hooks/useSelect.ts | 97 ++++ frontend/src/locale/en-US/common.ts | 3 + frontend/src/locale/en-US/index.ts | 2 + frontend/src/locale/zh-CN/common.ts | 3 + frontend/src/locale/zh-CN/index.ts | 2 + .../src/models/projectManagement/message.ts | 35 ++ .../routes/modules/projectManagement.ts | 32 + .../fileManagement/components/popConfirm.vue | 4 +- .../fileManagement/index.vue | 3 + .../src/views/project-management/index.vue | 3 - .../components/messageList.vue | 71 +++ .../components/robotList.vue | 547 ++++++++++++++++++ .../messageManagement/edit.vue | 11 + .../messageManagement/index.vue | 37 ++ .../messageManagement/locale/en-US.ts | 1 + .../messageManagement/locale/zh-CN.ts | 60 ++ .../userGroup/projectUserGroup.vue | 6 +- .../system/log/components/logCards.vue | 7 +- .../views/setting/system/log/locale/en-US.ts | 2 +- .../views/setting/system/log/locale/zh-CN.ts | 2 +- 38 files changed, 1515 insertions(+), 226 deletions(-) create mode 100644 frontend/src/api/modules/project-management/messageManagement.ts create mode 100644 frontend/src/api/requrls/project-management/messageManagement.ts rename frontend/src/components/business/{ms-search-select => ms-select}/index.tsx (52%) delete mode 100644 frontend/src/components/pure/ms-button/not-mr.vue create mode 100644 frontend/src/hooks/useSelect.ts create mode 100644 frontend/src/models/projectManagement/message.ts delete mode 100644 frontend/src/views/project-management/index.vue create mode 100644 frontend/src/views/project-management/messageManagement/components/messageList.vue create mode 100644 frontend/src/views/project-management/messageManagement/components/robotList.vue create mode 100644 frontend/src/views/project-management/messageManagement/edit.vue create mode 100644 frontend/src/views/project-management/messageManagement/index.vue create mode 100644 frontend/src/views/project-management/messageManagement/locale/en-US.ts create mode 100644 frontend/src/views/project-management/messageManagement/locale/zh-CN.ts diff --git a/frontend/src/api/modules/project-management/fileManagement.ts b/frontend/src/api/modules/project-management/fileManagement.ts index dff79b9c24..5a0de28774 100644 --- a/frontend/src/api/modules/project-management/fileManagement.ts +++ b/frontend/src/api/modules/project-management/fileManagement.ts @@ -570,6 +570,194 @@ const fileList = [ updateTime: 18975439859, createTime: 18975439859, }, + { + id: 100001, + name: 'JAR', + url: 'https://github.com/metersphere/metersphere/blob/v2.10/.gitignore', + type: 'JAR', + desc: 'fwihflhlofihlasjkhfdlkasjdhgaksuidhoasidoasidasopidapsoidaps', + storage: 'minio', + tag: ['dsadasd'], + size: '12MB', + enable: true, + fileVersion: 'v2.10', + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000002, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000003, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000004, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000005, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000006, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000007, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000008, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000009, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, + { + id: 1000010, + name: 'PNG', + url: 'http://localhost:5173/front/base-display/get/logo-platform', + type: 'PNG', + desc: 'sfakjdghkjrugheoirugkblasjblsdjkhflksdjfsldkjklnjkhkljds', + storage: 'github', + gitBranch: 'master', + gitVersion: 'v2.10', + gitPath: '/asdas/xas/xas/fd/f/', + tag: ['asfasdfas'], + size: '12MB', + enable: false, + fileModule: 'XXX', + creator: '创建人', + updater: '更新人', + updateTime: 18975439859, + createTime: 18975439859, + }, ]; // 获取文件列表 export function getFileList(data: TableQueryParams): Promise> { diff --git a/frontend/src/api/modules/project-management/messageManagement.ts b/frontend/src/api/modules/project-management/messageManagement.ts new file mode 100644 index 0000000000..0f5dc97b30 --- /dev/null +++ b/frontend/src/api/modules/project-management/messageManagement.ts @@ -0,0 +1,153 @@ +import MSR from '@/api/http/index'; +import { + RobotListUrl, + GetRobotUrl, + AddRobotUrl, + UpdateRobotUrl, + EnableRobotUrl, +} from '@/api/requrls/project-management/messageManagement'; + +import type { RobotItem, RobotAddParams, RobotEditParams } from '@/models/projectManagement/message'; +import type { TableQueryParams, CommonList } from '@/models/common'; + +const list = [ + { + id: '1', + name: '站内信', + description: '系统内置,在顶部导航栏显示消息通知', + platform: 'IN_SITE', + enable: true, + webhook: 'asdasdasfasfsaf', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + }, + { + id: '2', + name: '邮件', + description: '系统内置,以添加用户邮箱为通知方式', + platform: 'MAIL', + enable: false, + webhook: 'sdfsdfasfasf', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + }, + { + id: '3', + name: '飞书', + description: '', + platform: 'LARK', + enable: false, + webhook: 'asdfgasdgasfgasgas', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '4', + name: '钉钉', + description: '', + platform: 'DING_TALK', + enable: false, + webhook: 'asfgasfasdfa', + type: 'CUSTOM', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '44', + name: '钉钉', + description: '', + platform: 'DING_TALK', + enable: false, + webhook: 'asfgasfasdfa', + appKey: 'asfasfasfasfasf', + appSecret: 'asfasfasfasfasf', + type: 'ENTERPRISE', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '5', + name: '企业微信', + description: '', + platform: 'WE_COM', + enable: false, + webhook: 'vevbbt', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '5', + name: '自定义', + description: '', + platform: 'CUSTOM', + enable: false, + webhook: 'bytnm', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '5', + name: '自定义', + description: '', + platform: 'CUSTOM', + enable: false, + webhook: 'bytnm', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, + { + id: '5', + name: '自定义', + description: '', + platform: 'CUSTOM', + enable: false, + webhook: 'bytnm', + projectId: '1', + createTime: 1695721467045, + createUser: 'admin', + updateUser: 'bai', + updateTime: 1695721467045, + }, +]; + +export function getRobotList(projectId: string) { + // return MSR.post({ url: `${RobotListUrl}/${projectId}` }); + return Promise.resolve(list); +} + +export function getRobotDetail(robotId: string) { + // return MSR.get({ url: GetRobotUrl, params: robotId }); + return Promise.resolve(list.find((item) => item.id === robotId)); +} + +export function addRobot(data: RobotAddParams) { + return MSR.post({ url: AddRobotUrl, data }); +} + +export function updateRobot(data: RobotEditParams) { + return MSR.post({ url: UpdateRobotUrl, data }); +} + +export function toggleRobot(id: string) { + return MSR.get({ url: EnableRobotUrl, params: id }); +} diff --git a/frontend/src/api/requrls/project-management/messageManagement.ts b/frontend/src/api/requrls/project-management/messageManagement.ts new file mode 100644 index 0000000000..4818a66c0d --- /dev/null +++ b/frontend/src/api/requrls/project-management/messageManagement.ts @@ -0,0 +1,6 @@ +export const RobotListUrl = '/project/robot/list/page'; +export const UpdateRobotUrl = '/project/robot/update'; +export const AddRobotUrl = '/project/robot/add'; +export const GetRobotUrl = '/project/robot/get'; +export const EnableRobotUrl = '/project/robot/enable'; +export const DeleteRobotUrl = '/project/robot/delete'; diff --git a/frontend/src/assets/style/arco-reset.less b/frontend/src/assets/style/arco-reset.less index 8461dcfddf..3cb51e3a60 100644 --- a/frontend/src/assets/style/arco-reset.less +++ b/frontend/src/assets/style/arco-reset.less @@ -328,6 +328,16 @@ .arco-checkbox-icon { border: 1px solid var(--color-text-input-border); } + &:hover { + .arco-checkbox-icon-hover::before { + background-color: rgb(var(--primary-9)) !important; + } + } + .arco-checkbox-icon-hover { + &:hover::before { + background-color: rgb(var(--primary-9)) !important; + } + } } .arco-checkbox-indeterminate .arco-checkbox-icon { border-color: rgba(var(--primary-7)); @@ -407,8 +417,12 @@ .arco-dropdown, .arco-trigger-menu, .arco-select-dropdown { + padding: 6px; border: 0.5px solid var(--color-text-n8); box-shadow: 0 3px 14px 2px rgb(0 0 0 / 5%), 0 8px 10px 1px rgb(0 0 0 / 6%), 0 5px 5px -3px rgb(0 0 0 / 10%); + .arco-select-dropdown-header { + margin-bottom: 4px; + } .arco-dropdown-list, .arco-select-dropdown-list, .arco-trigger-menu-inner { @@ -427,6 +441,18 @@ background-color: rgb(var(--primary-1)); } } + .arco-select-option { + margin: 0; + .arco-select-option-checkbox { + padding-top: 3px; + padding-bottom: 3px; + &:hover { + .arco-checkbox-icon-hover::before { + background-color: rgb(var(--primary-9)) !important; + } + } + } + } .ms-dropdown-divider { margin: 6px 0; } @@ -442,6 +468,13 @@ } } } +.arco-select-dropdown-has-header { + padding-top: 6px !important; +} +.arco-select-dropdown-footer { + margin-top: 4px; + margin-bottom: 4px; +} .arco-dropdown-option-content { @apply flex items-center; @@ -742,3 +775,14 @@ white-space: nowrap; } } + +/** Alter **/ +.arco-alert-title { + font-size: 14px; + font-weight: 400; +} +.arco-alert-icon { + @apply flex; + + margin-top: 1px; +} diff --git a/frontend/src/components/business/ms-card-list/index.vue b/frontend/src/components/business/ms-card-list/index.vue index ab95fde2f2..e766ee07b4 100644 --- a/frontend/src/components/business/ms-card-list/index.vue +++ b/frontend/src/components/business/ms-card-list/index.vue @@ -66,16 +66,6 @@ } }); } - if (arr && arr.length > 0) { - nextTick(() => { - if (msCardListRef.value) { - // 为了在列表数据滚动加载时,能够正确判断是否滚动到底部,因为此时没有触发滚动事件,而在加载前触发了滚动到底部的判断 - const listContent = msCardListRef.value; - const { scrollTop, scrollHeight, clientHeight } = listContent; - isArrivedBottom.value = scrollHeight - clientHeight - scrollTop < props.shadowLimit; - } - }); - } } watch( @@ -219,7 +209,7 @@ @apply overflow-hidden; .ms-container--shadow(); .ms-card-list { - @apply grid overflow-auto; + @apply grid max-h-full overflow-auto; .ms-scroll-bar(); diff --git a/frontend/src/components/business/ms-cascader/index.vue b/frontend/src/components/business/ms-cascader/index.vue index 5d48aa5d52..383293d416 100644 --- a/frontend/src/components/business/ms-cascader/index.vue +++ b/frontend/src/components/business/ms-cascader/index.vue @@ -71,8 +71,8 @@ +@/hooks/useSelect diff --git a/frontend/src/components/business/ms-form-item-sub/index.vue b/frontend/src/components/business/ms-form-item-sub/index.vue index d6253411b3..e8999da8ca 100644 --- a/frontend/src/components/business/ms-form-item-sub/index.vue +++ b/frontend/src/components/business/ms-form-item-sub/index.vue @@ -1,5 +1,5 @@ @@ -17,12 +24,14 @@ defineProps<{ text: string; showFillIcon?: boolean; + icon?: string; + iconText?: string; }>(), { showFillIcon: true, } ); - const emit = defineEmits(['fill']); + const emit = defineEmits(['fill', 'iconClick']); function fillHeapByDefault() { emit('fill'); diff --git a/frontend/src/components/business/ms-search-select/index.tsx b/frontend/src/components/business/ms-select/index.tsx similarity index 52% rename from frontend/src/components/business/ms-search-select/index.tsx rename to frontend/src/components/business/ms-select/index.tsx index 2c0a0d8d63..aad948f055 100644 --- a/frontend/src/components/business/ms-search-select/index.tsx +++ b/frontend/src/components/business/ms-select/index.tsx @@ -1,6 +1,7 @@ -import { watch, ref, h, defineComponent, onBeforeMount } from 'vue'; +import { watch, ref, h, defineComponent, onBeforeMount, computed, Ref, Slot } from 'vue'; import { debounce } from 'lodash-es'; import { useI18n } from '@/hooks/useI18n'; +import useSelect from '@/hooks/useSelect'; import type { SelectOptionData } from '@arco-design/web-vue'; @@ -15,11 +16,14 @@ export type RemoteFieldsMap = { export interface MsSearchSelectProps { mode?: 'static' | 'remote'; // 静态模式,远程模式。默认为静态模式,需要传入 options 数据;远程模式需要传入请求函数 modelValue: ModelType; + allowSearch?: boolean; allowClear?: boolean; placeholder?: string; - prefix?: string; - searchKeys: string[]; // 需要搜索的 key 名,关键字会遍历这个 key 数组,然后取 item[key] 进行模糊匹配 + hasAllSelect?: boolean; // 是否有全选选项 + searchKeys?: string[]; // 需要搜索的 key 名,关键字会遍历这个 key 数组,然后取 item[key] 进行模糊匹配 + valueKey?: string; // 选项的 value 字段名,默认为 value options: SelectOptionData[]; + multiple?: boolean; // 是否多选 remoteFieldsMap?: RemoteFieldsMap; // 远程模式下的结果 key 映射,例如 { value: 'id' },表示远程请求时,会将返回结果的 id 赋值到 value 字段 remoteExtraParams?: Record; // 远程模式下的额外参数 remoteFunc?(params: Record): Promise; // 远程模式下的请求函数,返回一个 Promise @@ -27,13 +31,20 @@ export interface MsSearchSelectProps { optionTooltipContent?: (item: SelectOptionData) => string; // 自定义 option 的 tooltip 内容,返回一个字符串,默认使用 item.label } +export interface MsSearchSelectSlots { + prefix?: string; + header?: (() => JSX.Element) | Slot; + default?: () => JSX.Element[]; + footer?: Slot; +} + export default defineComponent( - (props: MsSearchSelectProps, { emit }) => { + (props: MsSearchSelectProps & MsSearchSelectSlots, { emit, slots }) => { const { t } = useI18n(); const innerValue = ref(props.modelValue); - const filterOptions = ref([]); - const remoteOriginOptions = ref([...props.options]); + const filterOptions = ref([]); // 实际渲染的 options,会根据搜索关键字进行过滤 + const remoteOriginOptions = ref([...props.options]); // 远程模式下的原始 options,接口返回的数据会存储在这里 watch( () => props.modelValue, (val) => { @@ -41,12 +52,14 @@ export default defineComponent( } ); - watch( - () => props.options, - (arr) => { - filterOptions.value = [...arr]; - } - ); + const selectRef = ref(); + + const { maxTagCount, getOptionComputedStyle, calculateMaxTag } = useSelect({ + selectRef, + selectVal: innerValue, + isCascade: true, + options: props.options, + }); const loading = ref(false); @@ -76,7 +89,11 @@ export default defineComponent( } if (val.trim() === '') { // 如果搜索关键字为空,则直接返回所有数据 - filterOptions.value = [...remoteOriginOptions.value]; + filterOptions.value = remoteOriginOptions.value.map((e) => ({ + ...e, + tooltipContent: typeof props.optionTooltipContent === 'function' ? props.optionTooltipContent(e) : e.label, + })); + calculateMaxTag(); return; } const highlightedKeyword = `${val}`; @@ -84,13 +101,15 @@ export default defineComponent( .map((e) => { const item = { ...e }; let hasMatch = false; - for (let i = 0; i < props.searchKeys.length; i++) { - // 遍历传入的搜索字段 - const key = props.searchKeys[i]; - if (e[key].includes(val)) { - // 是否匹配 - hasMatch = true; - item[key] = e[key].replace(new RegExp(val, 'gi'), highlightedKeyword); // 高亮关键字替换 + if (props.searchKeys) { + for (let i = 0; i < props.searchKeys.length; i++) { + // 遍历传入的搜索字段 + const key = props.searchKeys[i]; + if (e[key].includes(val)) { + // 是否匹配 + hasMatch = true; + item[key] = e[key].replace(new RegExp(val, 'gi'), highlightedKeyword); // 高亮关键字替换 + } } } if (hasMatch) { @@ -99,7 +118,9 @@ export default defineComponent( return null; }) .filter((e) => e) as SelectOptionData[]; + calculateMaxTag(); } catch (error) { + // eslint-disable-next-line no-console console.log(error); } finally { loading.value = false; @@ -111,31 +132,92 @@ export default defineComponent( ? h('div', { innerHTML: props.optionLabelRender(item) }) : item.label; + // 半选状态 + const indeterminate = computed(() => { + if (props.multiple && Array.isArray(innerValue.value)) { + return innerValue.value.length > 0 && innerValue.value.length < filterOptions.value.length; + } + return false; + }); + + const isSelectAll = computed({ + get: () => { + if (props.multiple && Array.isArray(innerValue.value)) { + return innerValue.value.length === filterOptions.value.length; + } + return false; + }, + set: (val) => val, + }); + function handleSelectAllChange(val: boolean) { + isSelectAll.value = val; + if (val) { + innerValue.value = filterOptions.value.map((item) => item[props.valueKey || 'value']); + emit('update:modelValue', innerValue.value); + } else { + innerValue.value = []; + emit('update:modelValue', []); + } + } + + const selectSlots = () => { + const _slots: MsSearchSelectSlots = { + default: () => + filterOptions.value.map((item) => ( + + +
+ {optionItemLabelRender(item)} +
+
+
+ )), + }; + if (props.hasAllSelect) { + _slots.header = () => ( +
+ + {t('common.allSelect')} + +
+ ); + } + if (slots.header) { + _slots.header = slots.header; + } + if (slots.footer) { + _slots.footer = slots.footer; + } + + return _slots; + }; + onBeforeMount(() => { handleUserSearch(''); }); return () => ( emit('update:modelValue', value)} onInputValueChange={debounce(handleUserSearch, 300)} > {{ prefix: () => t(props.prefix || ''), - default: () => - filterOptions.value.map((item) => ( - - - {optionItemLabelRender(item)} - - - )), + ...selectSlots(), }} ); @@ -145,16 +227,20 @@ export default defineComponent( props: [ 'mode', 'modelValue', + 'allowSearch', 'allowClear', 'placeholder', - 'prefix', 'searchKeys', + 'valueKey', 'options', 'optionLabelRender', 'remoteFieldsMap', 'remoteExtraParams', 'remoteFunc', 'optionTooltipContent', + 'prefix', + 'hasAllSelect', + 'multiple', ], emits: ['update:modelValue'], } diff --git a/frontend/src/components/pure/ms-button/index.vue b/frontend/src/components/pure/ms-button/index.vue index a5cde8116f..5b078fa297 100644 --- a/frontend/src/components/pure/ms-button/index.vue +++ b/frontend/src/components/pure/ms-button/index.vue @@ -39,7 +39,7 @@ } padding: 0 4px; - font-size: 1rem; + font-size: 14px; border-radius: var(--border-radius-mini); line-height: 22px; } diff --git a/frontend/src/components/pure/ms-button/not-mr.vue b/frontend/src/components/pure/ms-button/not-mr.vue deleted file mode 100644 index 297654cd35..0000000000 --- a/frontend/src/components/pure/ms-button/not-mr.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - - - diff --git a/frontend/src/components/pure/ms-card/index.vue b/frontend/src/components/pure/ms-card/index.vue index e72dd6e22b..4ea6d5a221 100644 --- a/frontend/src/components/pure/ms-card/index.vue +++ b/frontend/src/components/pure/ms-card/index.vue @@ -5,6 +5,7 @@ 'ms-card', 'relative', 'h-full', + props.isFullscreen ? 'ms-card--no-radius' : '', props.autoHeight ? '' : 'min-h-[500px]', props.noContentPadding ? 'ms-card--noContentPadding' : 'p-[24px]', ]" @@ -15,17 +16,8 @@
- -
+ +
@@ -72,10 +64,11 @@ specialHeight: number; // 特殊高度,例如某些页面有面包屑 hideBack: boolean; // 隐藏返回按钮 autoHeight: boolean; // 内容区域高度是否自适应 - otherWidth?: number; // 该宽度为卡片外部同级容器的宽度 - minWidth?: number; // 卡片最小宽度 + otherWidth: number; // 该宽度为卡片外部同级容器的宽度 + minWidth: number; // 卡片最小宽度 hasBreadcrumb: boolean; // 是否有面包屑,如果有面包屑,高度需要减去面包屑的高度 noContentPadding: boolean; // 内容区域是否有padding + isFullscreen?: boolean; // 是否全屏 handleBack: () => void; // 自定义返回按钮触发事件 }> >(), @@ -117,6 +110,23 @@ return 246 + _specialHeight; }); + const getComputedContentStyle = computed(() => { + if (props.isFullscreen) { + return { + overflow: 'auto', + width: 'calc(100vw - 58px)', + height: 'auto', + }; + } + return { + overflow: 'auto', + width: props.otherWidth + ? `calc(100vw - ${menuWidth.value}px - ${props.otherWidth}px)` + : `calc(100vw - ${menuWidth.value}px - 58px)`, + height: props.autoHeight ? 'auto' : `calc(100vh - ${cardOverHeight.value}px)`, + }; + }); + function back() { if (typeof props.handleBack === 'function') { props.handleBack(); @@ -128,7 +138,7 @@ diff --git a/frontend/src/components/pure/ms-drawer/index.vue b/frontend/src/components/pure/ms-drawer/index.vue index f2f6b6168e..a6859e940c 100644 --- a/frontend/src/components/pure/ms-drawer/index.vue +++ b/frontend/src/components/pure/ms-drawer/index.vue @@ -44,15 +44,20 @@ diff --git a/frontend/src/components/pure/ms-list/index.vue b/frontend/src/components/pure/ms-list/index.vue index a548a767b2..fa074023b6 100644 --- a/frontend/src/components/pure/ms-list/index.vue +++ b/frontend/src/components/pure/ms-list/index.vue @@ -154,14 +154,6 @@ initScrollListener(); }); } - if (props.data.length > 0) { - nextTick(() => { - // 为了在列表数据滚动加载时,能够正确判断是否滚动到底部,因为此时没有触发滚动事件,而在加载前触发了滚动到底部的判断 - const listContent = listRef.value?.$el.querySelector('.arco-list-content'); - const { scrollTop, scrollHeight, clientHeight } = listContent; - isArrivedBottom.value = scrollHeight - clientHeight - scrollTop < props.itemHeight; - }); - } }, { immediate: true, diff --git a/frontend/src/components/pure/ms-timeline/index.vue b/frontend/src/components/pure/ms-timeline/index.vue index b07e1c7a79..7b63eda995 100644 --- a/frontend/src/components/pure/ms-timeline/index.vue +++ b/frontend/src/components/pure/ms-timeline/index.vue @@ -84,12 +84,6 @@ listContent.addEventListener('scroll', listenScroll); }); } - nextTick(() => { - // 为了在列表数据滚动加载时,能够正确判断是否滚动到底部,因为此时没有触发滚动事件,而在加载前触发了滚动到底部的判断 - const listContent = listRef.value?.$el.querySelector('.arco-list-content'); - const { scrollTop, scrollHeight, clientHeight } = listContent; - isArrivedBottom.value = scrollHeight - clientHeight - scrollTop < 20; - }); }); function handleReachBottom() { diff --git a/frontend/src/components/pure/navbar/index.vue b/frontend/src/components/pure/navbar/index.vue index 40ff474ec7..857793b33e 100644 --- a/frontend/src/components/pure/navbar/index.vue +++ b/frontend/src/components/pure/navbar/index.vue @@ -2,7 +2,7 @@