feat(项目管理): 项目管理-菜单管理首页静态页面
This commit is contained in:
parent
58966bda2f
commit
05c863f62e
|
@ -0,0 +1,60 @@
|
|||
import MSR from '@/api/http/index';
|
||||
import * as Url from '@/api/requrls/project-management/menuManagement';
|
||||
import type { MenuTableListItem, MenuTableListParams } from '@/models/projectManagement/menuManagement';
|
||||
import { MenuEnum } from '@/enums/commonEnum';
|
||||
|
||||
import { TableQueryParams, CommonList } from '@/models/common';
|
||||
|
||||
const tableList: MenuTableListItem[] = [
|
||||
'workstation',
|
||||
'loadTest',
|
||||
'testPlan',
|
||||
'bugManagement',
|
||||
'caseManagement',
|
||||
'apiTest',
|
||||
'uiTest',
|
||||
].map((item, index) => {
|
||||
return { module: item, moduleEnable: index % 2 === 0 };
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function postTabletList(data: TableQueryParams) {
|
||||
// return MSR.post<CommonList<MenuTableListItem>>({ url: Url.getMenuListUrl, data });
|
||||
const result: CommonList<MenuTableListItem> = {
|
||||
list: tableList,
|
||||
total: tableList.length,
|
||||
pageSize: 10,
|
||||
current: 1,
|
||||
};
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
export function postUpdateMenu(data: MenuTableListParams) {
|
||||
let suffix = '';
|
||||
switch (data.type) {
|
||||
case MenuEnum.workstation:
|
||||
suffix = 'workstation';
|
||||
break;
|
||||
case MenuEnum.testPlan:
|
||||
suffix = 'test-plan';
|
||||
break;
|
||||
case MenuEnum.bugManagement:
|
||||
suffix = 'issue';
|
||||
break;
|
||||
case MenuEnum.caseManagement:
|
||||
suffix = 'case';
|
||||
break;
|
||||
case MenuEnum.apiTest:
|
||||
suffix = 'api';
|
||||
break;
|
||||
case MenuEnum.uiTest:
|
||||
suffix = 'uiTest';
|
||||
break;
|
||||
default:
|
||||
suffix = 'performance-test';
|
||||
break;
|
||||
}
|
||||
return MSR.post<string>({ url: `${Url.updateConfigByMenuTypeUrl}${suffix}`, data });
|
||||
}
|
||||
|
||||
export default {};
|
|
@ -0,0 +1,4 @@
|
|||
export const getConfigByMenuTypeUrl = '/project/application/';
|
||||
export const updateConfigByMenuTypeUrl = '/project/application/update/';
|
||||
// 获取表格最外层的数据
|
||||
export const getMenuListUrl = '/project/application/module-setting/';
|
|
@ -143,6 +143,10 @@
|
|||
</div>
|
||||
</slot>
|
||||
</template>
|
||||
<template #expand-icon="{ expanded }">
|
||||
<icon-down-circle v-if="expanded" />
|
||||
<icon-right-circle v-else />
|
||||
</template>
|
||||
</a-table>
|
||||
<div
|
||||
class="mt-[16px] flex h-[32px] w-[100%] min-w-[952px] flex-row flex-nowrap items-center justify-end px-0"
|
||||
|
|
|
@ -47,6 +47,7 @@ export interface MsTableProps<T> {
|
|||
rowKey: string; // 表格行的key rowId
|
||||
// 表格列 - 详见 TableColumn https://arco.design/web-vue/components/table-column;
|
||||
columns: MsTableColumnData[];
|
||||
showPagination?: boolean; // 是否显示分页
|
||||
size?: 'mini' | 'small' | 'default' | 'large'; // 表格尺寸
|
||||
scroll?: {
|
||||
x?: number | string;
|
||||
|
|
|
@ -8,6 +8,7 @@ import type { TableData } from '@arco-design/web-vue';
|
|||
import type { TableQueryParams, CommonList } from '@/models/common';
|
||||
import { SelectAllEnum } from '@/enums/tableEnum';
|
||||
import type { MsTableProps, MsTableDataItem, MsTableColumn, MsTableErrorStatus, SetPaginationPrams } from './type';
|
||||
import { set } from 'nprogress';
|
||||
|
||||
export interface Pagination {
|
||||
current: number;
|
||||
|
@ -151,52 +152,82 @@ export default function useTableProps<T>(
|
|||
|
||||
// 加载分页列表数据
|
||||
const loadList = async () => {
|
||||
const { current, pageSize } = propsRes.value.msPagination as Pagination;
|
||||
const { rowKey, selectorStatus, excludeKeys } = propsRes.value;
|
||||
setLoading(true);
|
||||
try {
|
||||
const data = await loadListFunc({
|
||||
current,
|
||||
pageSize,
|
||||
sort: sortItem.value,
|
||||
filter: filterItem.value,
|
||||
keyword: keyword.value,
|
||||
...loadListParams.value,
|
||||
});
|
||||
const tmpArr = data.list;
|
||||
(propsRes.value.data as MsTableDataItem<T>[]) = tmpArr.map((item) => {
|
||||
if (item.updateTime) {
|
||||
item.updateTime = dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (item.createTime) {
|
||||
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (dataTransform) {
|
||||
item = dataTransform(item);
|
||||
}
|
||||
if (selectorStatus === SelectAllEnum.ALL) {
|
||||
if (!excludeKeys.has(item[rowKey])) {
|
||||
setTableSelected(item[rowKey]);
|
||||
if (propsRes.value.showPagination) {
|
||||
const { current, pageSize } = propsRes.value.msPagination as Pagination;
|
||||
const { rowKey, selectorStatus, excludeKeys } = propsRes.value;
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await loadListFunc({
|
||||
current,
|
||||
pageSize,
|
||||
sort: sortItem.value,
|
||||
filter: filterItem.value,
|
||||
keyword: keyword.value,
|
||||
...loadListParams.value,
|
||||
});
|
||||
const tmpArr = data.list;
|
||||
(propsRes.value.data as MsTableDataItem<T>[]) = tmpArr.map((item) => {
|
||||
if (item.updateTime) {
|
||||
item.updateTime = dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (item.createTime) {
|
||||
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (dataTransform) {
|
||||
item = dataTransform(item);
|
||||
}
|
||||
if (selectorStatus === SelectAllEnum.ALL) {
|
||||
if (!excludeKeys.has(item[rowKey])) {
|
||||
setTableSelected(item[rowKey]);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
});
|
||||
if (data.total === 0) {
|
||||
setTableErrorStatus('empty');
|
||||
} else {
|
||||
setTableErrorStatus(false);
|
||||
}
|
||||
setPagination({ current: data.current, total: data.total });
|
||||
return data;
|
||||
} catch (err) {
|
||||
setTableErrorStatus('error');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
// debug 模式下打印属性
|
||||
if (propsRes.value.debug && import.meta.env.DEV) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('Table propsRes: ', propsRes.value);
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
if (data.total === 0) {
|
||||
setTableErrorStatus('empty');
|
||||
} else {
|
||||
setTableErrorStatus(false);
|
||||
}
|
||||
setPagination({ current: data.current, total: data.total });
|
||||
return data;
|
||||
} catch (err) {
|
||||
setTableErrorStatus('error');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
// debug 模式下打印属性
|
||||
if (propsRes.value.debug && import.meta.env.DEV) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('Table propsRes: ', propsRes.value);
|
||||
} else {
|
||||
// 没分页的情况下,直接调用loadListFunc
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await loadListFunc({ keyword: keyword.value, ...loadListParams.value });
|
||||
if (data.total === 0) {
|
||||
setTableErrorStatus('empty');
|
||||
return;
|
||||
}
|
||||
setTableErrorStatus(false);
|
||||
const tmpArr = data.list;
|
||||
(propsRes.value.data as MsTableDataItem<T>[]) = tmpArr.map((item) => {
|
||||
if (item.updateTime) {
|
||||
item.updateTime = dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (item.createTime) {
|
||||
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
if (dataTransform) {
|
||||
item = dataTransform(item);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return data;
|
||||
} catch (err) {
|
||||
setTableErrorStatus('error');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,4 +9,14 @@ export enum AuthScopeEnum {
|
|||
PROJECT = 'PROJECT',
|
||||
}
|
||||
|
||||
export enum MenuEnum {
|
||||
workstation = 'workstation',
|
||||
loadTest = 'loadTest',
|
||||
testPlan = 'testPlan',
|
||||
bugManagement = 'bugManagement',
|
||||
caseManagement = 'caseManagement',
|
||||
apiTest = 'apiTest',
|
||||
uiTest = 'uiTest',
|
||||
}
|
||||
|
||||
export default {};
|
||||
|
|
|
@ -9,9 +9,9 @@ export default interface CommonResponse<T> {
|
|||
// 表格查询
|
||||
export interface TableQueryParams {
|
||||
// 当前页
|
||||
current: number;
|
||||
current?: number;
|
||||
// 每页条数
|
||||
pageSize: number;
|
||||
pageSize?: number;
|
||||
// 排序仅针对单个字段
|
||||
sort?: object;
|
||||
// 排序仅针对单个字段
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import { MenuEnum } from '@/enums/commonEnum';
|
||||
|
||||
export interface MenuTableListItem {
|
||||
module: string;
|
||||
moduleEnable: boolean;
|
||||
moduleDesc?: string;
|
||||
}
|
||||
|
||||
export interface MenuTableListParams {
|
||||
projectId: string;
|
||||
type: MenuEnum;
|
||||
typeValue: boolean;
|
||||
}
|
|
@ -1,9 +1,110 @@
|
|||
<template>
|
||||
<div> 菜单管理 waiting for development</div>
|
||||
<div class="flex flex-row items-center">
|
||||
<div class="text-[var(--color-text-1)]"> {{ t('project.menu.management') }}</div>
|
||||
<a-tooltip :content="t('project.menu.manageTip')">
|
||||
<MsIcon class="ml-[4px] text-[rgb(var(--primary-5))]" type="icon-icon-maybe_outlined" />
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<MsBaseTable class="mt-[16px]" v-bind="propsRes" v-on="propsEvent">
|
||||
<template #module="{ record }">
|
||||
<MsIcon :type="getMenuIcon(record.module)" />
|
||||
<span class="ml-[4px]">{{ record.module }}</span>
|
||||
</template>
|
||||
<template #moduleEnable="{ record }">
|
||||
<a-switch v-model="record.moduleEnable" @change="handleMenuStatusChange(record)" />
|
||||
</template>
|
||||
</MsBaseTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
/**
|
||||
* @description 项目管理-项目与权限-菜单管理
|
||||
*/
|
||||
import { onMounted, computed } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||
import { postTabletList, postUpdateMenu } from '@/api/modules/project-management/menuManagement';
|
||||
import { useAppStore } from '@/store';
|
||||
import { MenuTableListItem } from '@/models/projectManagement/menuManagement';
|
||||
import { MenuEnum } from '@/enums/commonEnum';
|
||||
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const currentProjectId = computed(() => appStore.currentProjectId);
|
||||
const { t } = useI18n();
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: 'project.menu.name',
|
||||
dataIndex: 'module',
|
||||
slotName: 'module',
|
||||
},
|
||||
{
|
||||
title: 'project.menu.description',
|
||||
slotName: 'description',
|
||||
dataIndex: 'description',
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'common.operation',
|
||||
slotName: 'moduleEnable',
|
||||
dataIndex: 'moduleEnable',
|
||||
fixed: 'right',
|
||||
width: 150,
|
||||
},
|
||||
];
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(postTabletList, {
|
||||
showPagination: false,
|
||||
columns,
|
||||
selectable: false,
|
||||
scroll: { x: '100%' },
|
||||
noDisable: true,
|
||||
});
|
||||
|
||||
const getMenuIcon = (type: MenuEnum) => {
|
||||
switch (type) {
|
||||
case MenuEnum.workstation:
|
||||
return 'icon-icon_pc_filled';
|
||||
case MenuEnum.testPlan:
|
||||
return 'icon-icon_test_plan_filled';
|
||||
case MenuEnum.bugManagement:
|
||||
return 'icon-icon_defect';
|
||||
case MenuEnum.caseManagement:
|
||||
return 'icon_functional_testing';
|
||||
case MenuEnum.apiTest:
|
||||
return 'icon-icon_api-test-filled';
|
||||
case MenuEnum.uiTest:
|
||||
return 'icon-icon_ui-test-filled';
|
||||
default:
|
||||
return 'icon_performance-test-filled';
|
||||
}
|
||||
};
|
||||
|
||||
const handleMenuStatusChange = async (record: MenuTableListItem) => {
|
||||
try {
|
||||
await postUpdateMenu({
|
||||
projectId: currentProjectId.value,
|
||||
type: record.module as MenuEnum,
|
||||
typeValue: record.moduleEnable,
|
||||
});
|
||||
Message.success(t('common.operationSuccess'));
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
const fetchData = async () => {
|
||||
await loadList();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setLoadListParams({ projectId: currentProjectId.value });
|
||||
fetchData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
'project.menu.management': 'Add Member',
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
export default {
|
||||
'project.menu.management': '菜单管理',
|
||||
'project.menu.manageTip':
|
||||
'可根据使用场景配置各功能开关关闭后,将隐藏功能入口,成员无法访问该功能和数据;已产生的数据不够此规则影响;再次开启时,即恢复至关闭前状态',
|
||||
'project.menu.name': '菜单名称',
|
||||
'project.menu.description': '描述',
|
||||
};
|
|
@ -93,6 +93,9 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* @description 项目管理-项目与权限-用户组
|
||||
*/
|
||||
import { ref, onMounted, computed, provide } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
|
|
|
@ -56,6 +56,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* @description 系统设置-组织-项目
|
||||
*/
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useTable from '@/components/pure/ms-table/useTable';
|
||||
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
</div>
|
||||
</Transition>
|
||||
<Transition>
|
||||
<div class="usergroup-collapse" :style="leftCollapse ? 'left: 300px' : 'left: 0'" @click="handleCollapse">
|
||||
<div class="usergroup-collapse" :style="{ left: leftCollapse ? '300px' : '0' }" @click="handleCollapse">
|
||||
<icon-double-left v-if="leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
|
||||
<icon-double-right v-else class="text-[12px] text-[var(--color-text-brand)]" />
|
||||
</div>
|
||||
</Transition>
|
||||
<div class="w-[100%] p-[24px]">
|
||||
<div class="p-[24px]" :style="{ width: leftCollapse ? 'calc(100% - 300px)' : '100%' }">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<a-tooltip :content="currentUserGroupItem.name">
|
||||
<div class="one-line-text max-w-[300px]">{{ currentUserGroupItem.name }}</div>
|
||||
|
@ -57,6 +57,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* @description 系统设置-组织-用户组
|
||||
*/
|
||||
import { ref, computed, watchEffect, nextTick, provide, onMounted } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import UserGroupLeft from '@/components/business/ms-user-group-comp/msUserGroupLeft.vue';
|
||||
|
@ -171,6 +174,7 @@
|
|||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-right: 6px;
|
||||
width: 300px;
|
||||
min-width: 300px;
|
||||
height: 100%;
|
||||
border-right: 1px solid var(--color-border-1);
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* @description 系统设置-系统-组织与项目
|
||||
*/
|
||||
import { ref, watch, nextTick, onBeforeMount } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
|
|
|
@ -267,7 +267,7 @@
|
|||
slotName: 'action',
|
||||
dataIndex: 'operation',
|
||||
fixed: 'right',
|
||||
width: 110,
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
const tableStore = useTableStore();
|
||||
|
@ -280,6 +280,7 @@
|
|||
size: 'default',
|
||||
selectable: true,
|
||||
pageSimple: true,
|
||||
showSetting: true,
|
||||
},
|
||||
(record) => ({
|
||||
...record,
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
</div>
|
||||
</Transition>
|
||||
<Transition>
|
||||
<div class="usergroup-collapse" :style="leftCollapse ? 'left: 300px' : 'left: 0'" @click="handleCollapse">
|
||||
<div class="usergroup-collapse" :style="{ left: leftCollapse ? '300px' : '0' }" @click="handleCollapse">
|
||||
<icon-double-left v-if="leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
|
||||
<icon-double-right v-if="!leftCollapse" class="text-[12px] text-[var(--color-text-brand)]" />
|
||||
</div>
|
||||
</Transition>
|
||||
<div class="w-[100%] p-[24px]">
|
||||
<div class="p-[24px]" :style="{ width: leftCollapse ? 'calc(100% - 300px)' : '100%' }">
|
||||
<div class="flex flex-row items-center justify-between">
|
||||
<a-tooltip :content="currentUserGroupItem.name">
|
||||
<div class="one-line-text max-w-[300px]">{{ currentUserGroupItem.name }}</div>
|
||||
|
@ -57,6 +57,9 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
/**
|
||||
* @description 系统设置-系统-用户组
|
||||
*/
|
||||
import { ref, computed, watchEffect, nextTick, provide, onMounted } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import UserGroupLeft from '@/components/business/ms-user-group-comp/msUserGroupLeft.vue';
|
||||
|
@ -171,6 +174,7 @@
|
|||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-right: 6px;
|
||||
width: 300px;
|
||||
min-width: 300px;
|
||||
height: 100%;
|
||||
border-right: 1px solid var(--color-border-1);
|
||||
|
|
Loading…
Reference in New Issue