fix(系统设置): 项目组&组织&项目&权限 bug 修改

This commit is contained in:
RubyLiu 2024-01-31 16:48:15 +08:00 committed by 刘瑞斌
parent e34be8e23d
commit 254b29f373
20 changed files with 103 additions and 69 deletions

View File

@ -23,7 +23,7 @@
import { setFavicon, watchStyle, watchTheme } from '@/utils/theme';
import { getPublicKeyRequest } from './api/modules/user';
import { WorkbenchRouteEnum } from './enums/routeEnum';
import { getFirstRouteNameByPermission } from './utils/permission';
import enUS from '@arco-design/web-vue/es/locale/lang/en-us';
import zhCN from '@arco-design/web-vue/es/locale/lang/zh-cn';
@ -91,7 +91,8 @@
}
if (isLoginPage && isLogin) {
//
router.push(WorkbenchRouteEnum.WORKBENCH);
const currentRouteName = getFirstRouteNameByPermission(router.getRoutes());
router.push({ name: currentRouteName });
}
};
//

View File

@ -36,13 +36,13 @@
{{ t('system.userGroup.systemUserGroup') }}
</div>
</div>
<MsMoreAction
<icon-plus-circle-fill
v-permission="['SYSTEM_USER_ROLE:READ+ADD']"
:list="createSystemUGActionItem"
@select="handleCreateUG(AuthScopeEnum.SYSTEM)"
>
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
class="cursor-pointer text-[rgb(var(--primary-7))]"
size="20"
@click="handleCreateUG(AuthScopeEnum.SYSTEM)"
/>
</div>
</CreateUserGroupPopup>
<Transition>
@ -123,13 +123,13 @@
{{ t('system.userGroup.orgUserGroup') }}
</div>
</div>
<MsMoreAction
<icon-plus-circle-fill
v-permission="['ORGANIZATION_USER_ROLE:READ+ADD']"
:list="createOrgUGActionItem"
@select="orgUserGroupVisible = true"
>
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
class="cursor-pointer text-[rgb(var(--primary-7))]"
size="20"
@click="orgUserGroupVisible = true"
/>
</div>
</CreateUserGroupPopup>
<Transition>
@ -211,13 +211,13 @@
{{ t('system.userGroup.projectUserGroup') }}
</div>
</div>
<MsMoreAction
<icon-plus-circle-fill
v-permission="['PROJECT_GROUP:READ+ADD']"
:list="createProjectUGActionItem"
@select="projectUserGroupVisible = true"
>
<icon-plus-circle-fill class="cursor-pointer text-[rgb(var(--primary-7))]" size="20" />
</MsMoreAction>
class="cursor-pointer text-[rgb(var(--primary-7))]"
size="20"
@click="projectUserGroupVisible = true"
/>
</div>
</CreateUserGroupPopup>
<Transition>
@ -353,32 +353,8 @@
return userGroupList.value.filter((ele) => ele.type === AuthScopeEnum.PROJECT);
});
const createSystemUGActionItem: ActionsItem[] = [
{ label: 'system.userGroup.addSysUserGroup', eventTag: 'createUserGroup' },
];
const createOrgUGActionItem: ActionsItem[] = [
{ label: 'system.userGroup.addOrgUserGroup', eventTag: 'createUserGroup' },
];
const createProjectUGActionItem: ActionsItem[] = [
{ label: 'system.userGroup.addProjectUserGroup', eventTag: 'createUserGroup' },
];
const addMemberActionItem: ActionsItem[] = [{ label: 'system.userGroup.addMember', eventTag: 'addMember' }];
const moreAction: ActionsItem[] = [
{
label: 'system.userGroup.rename',
danger: false,
eventTag: 'rename',
},
{
isDivider: true,
},
{
label: 'system.userGroup.delete',
danger: true,
eventTag: 'delete',
},
];
const systemMoreAction: ActionsItem[] = [
{
label: 'system.userGroup.rename',

View File

@ -5,7 +5,7 @@
</template>
<template v-if="hasAnyPermission(props.updatePermission || [])" #action="{ record }">
<MsRemoveButton
:title="t('system.userGroup.removeName', { name: record.name })"
:title="t('system.userGroup.removeName', { name: characterLimit(record.name) })"
:sub-title-tip="t('system.userGroup.removeTip')"
@ok="handleRemove(record)"
/>
@ -32,6 +32,7 @@
} from '@/api/modules/setting/usergroup';
import { useI18n } from '@/hooks/useI18n';
import { useAppStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { CurrentUserGroupItem, UserTableItem } from '@/models/setting/usergroup';

View File

@ -430,6 +430,9 @@
editActiveKey.value = '';
currentEditValue.value = '';
} else {
if (!record[dataIndex]) {
return;
}
// Enter
emit('rowNameChange', record, (v: boolean) => {
if (!v) {

View File

@ -82,6 +82,7 @@ export default function useTableStore() {
// 初始化过了,但是可能有新变动,如列的顺序,列的显示隐藏,列的拖拽
column = columnsTransform(column);
const { columnBackup: oldColumn } = selectorColumnMap[tableKey];
// 比较页面上定义的 column 和 浏览器备份的column 是否相同
const isEqual = isArraysEqualWithOrder<MsTableColumnData>(oldColumn, column);
if (!isEqual) {
// 如果不相等说明有变动将新的column存入indexDB
@ -129,7 +130,7 @@ export default function useTableStore() {
selectorColumnMap[key] = {
mode,
column: JSON.parse(JSON.stringify(columns)),
columnBackup: JSON.parse(JSON.stringify(columns)),
columnBackup: selectorColumnMap[key].columnBackup,
};
await localforage.setItem('selectorColumnMap', selectorColumnMap);
} catch (e) {

View File

@ -1,7 +1,7 @@
import { WorkbenchRouteEnum } from '@/enums/routeEnum';
// import { WorkbenchRouteEnum } from '@/enums/routeEnum';
import { DEFAULT_LAYOUT } from '../base';
import type { AppRouteRecordRaw } from '../types';
// import { DEFAULT_LAYOUT } from '../base';
// import type { AppRouteRecordRaw } from '../types';
// const Workbench: AppRouteRecordRaw = {
// path: '/workbench',
@ -28,3 +28,4 @@ import type { AppRouteRecordRaw } from '../types';
// };
// export default Workbench;
export default {};

View File

@ -135,6 +135,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useAppStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { CurrentUserGroupItem, UserGroupItem } from '@/models/setting/usergroup';
@ -245,7 +246,7 @@
const handleDelete = (record: UserGroupItem) => {
openDeleteModal({
title: t('project.userGroup.deleteName', { name: record.name }),
title: t('project.userGroup.deleteName', { name: characterLimit(record.name) }),
content: t('project.userGroup.deleteTip'),
onBeforeOk: async () => {
try {

View File

@ -32,7 +32,7 @@
</template>
<template #operation="{ record }">
<MsRemoveButton
:title="t('system.organization.removeName', { name: record.name })"
:title="t('system.organization.removeName', { name: characterLimit(record.name) })"
:sub-title-tip="t('system.organization.removeTip')"
@ok="handleRemove(record)"
/>
@ -61,6 +61,7 @@
import { deleteUserFromUserGroup, postUserByUserGroup } from '@/api/modules/project-management/usergroup';
import { useI18n } from '@/hooks/useI18n';
import { characterLimit } from '@/utils';
export interface projectDrawerProps {
visible: boolean;
@ -155,6 +156,7 @@
(visible) => {
currentVisible.value = visible;
if (visible) {
setKeyword(keyword.value);
fetchData();
}
}

View File

@ -23,6 +23,8 @@ export default {
'system.organization.organizationAdminPlaceholder':
'The organization administrator defaults to the person who created the organization',
'system.organization.description': 'Description',
'system.project.affiliatedOrgExtra':
'After selecting an organization, prompt the user to confirm the selected organization. After the project is successfully created, the organization cannot be changed',
'system.organization.descriptionPlaceholder': 'Please describe the organization',
'system.organization.ID': 'ID',
'system.organization.name': 'Name',

View File

@ -21,7 +21,8 @@ export default {
'system.organization.organizationAdmin': '组织管理员',
'system.organization.organizationAdminPlaceholder': '默认选择创建组织人为组织管理员',
'system.organization.description': '描述',
'system.organization.descriptionPlaceholder': '请对组织进行描述',
'system.organization.descriptionPlaceholder': '请对该组织进行描述',
'system.project.affiliatedOrgExtra': '选择组织后提示用户确认所选组织,项目创建成功后组织不可变更',
'system.organization.ID': 'ID',
'system.organization.name': '名称',
'system.organization.member': '成员',

View File

@ -112,6 +112,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useAppStore, useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { UserItem } from '@/models/setting/log';
@ -251,7 +252,7 @@
const handleDelete = (record: TableData) => {
openDeleteModal({
title: t('system.organization.deleteName', { name: record.name }),
title: t('system.organization.deleteName', { name: characterLimit(record.name) }),
content: t('system.organization.deleteTip'),
onBeforeOk: async () => {
try {

View File

@ -25,7 +25,11 @@
:label="t('system.organization.organizationName')"
:rules="[{ required: true, message: t('system.organization.organizationNameRequired') }]"
>
<a-input v-model="form.name" :placeholder="t('system.organization.organizationNamePlaceholder')" />
<a-input
v-model="form.name"
allow-clear
:placeholder="t('system.organization.organizationNamePlaceholder')"
/>
</a-form-item>
<a-form-item field="name" :label="t('system.organization.organizationAdmin')">
<MsUserSelector
@ -35,7 +39,13 @@
/>
</a-form-item>
<a-form-item field="description" :label="t('system.organization.description')">
<a-input v-model="form.description" :placeholder="t('system.organization.descriptionPlaceholder')" />
<a-textarea
v-model="form.description"
allow-clear
:placeholder="t('system.organization.descriptionPlaceholder')"
:auto-size="{ minRows: 1 }"
style="resize: vertical"
/>
</a-form-item>
</a-form>
</div>

View File

@ -41,6 +41,7 @@
:options="affiliatedOrgOption"
:placeholder="t('system.project.affiliatedOrgPlaceholder')"
:field-names="{ label: 'name', value: 'id' }"
:extra="t('system.project.affiliatedOrgExtra')"
>
</a-select>
</a-form-item>

View File

@ -20,7 +20,14 @@
@press-enter="searchUser"
></a-input-search>
</div>
<ms-base-table v-bind="propsRes" v-on="propsEvent" />
<ms-base-table v-bind="propsRes" v-on="propsEvent">
<template #num="{ record }">
<a-tooltip v-if="!record.enable" position="tl" :content="t('system.organization.projectIsDisabled')">
<div>{{ record.num }}</div>
</a-tooltip>
<span v-else>{{ record.num }}</span>
</template>
</ms-base-table>
</div>
</ms-drawer>
</template>
@ -54,6 +61,7 @@
{
title: 'system.organization.ID',
dataIndex: 'num',
slotName: 'num',
},
{
title: 'system.project.name',
@ -62,6 +70,7 @@
{
title: 'system.organization.status',
dataIndex: 'enable',
disableTitle: 'common.end',
},
{
title: 'system.organization.creator',
@ -70,6 +79,11 @@
{
title: 'system.organization.createTime',
dataIndex: 'createTime',
width: 180,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
},
];

View File

@ -4,7 +4,9 @@
<a-tooltip background-color="#FFFFFF">
<template #content>
<span>
<span class="text-[var(--color-text-1)]">{{ t('system.organization.revokeDeleteToolTip') }}</span>
<span class="text-[var(--color-text-1)]">{{
t('system.organization.revokeDeleteToolTip', { count: record.remainDayCount })
}}</span>
<MsButton
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+RECOVER']"
class="ml-[8px]"
@ -87,7 +89,7 @@
<UserDrawer v-bind="currentUserDrawer" @request-fetch-data="fetchData" @cancel="handleUserDrawerCancel" />
</template>
<script lang="ts" setup>
<script lang="ts" setup async>
import { reactive, ref } from 'vue';
import { Message, TableData } from '@arco-design/web-vue';
@ -114,6 +116,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { CreateOrUpdateSystemOrgParams, OrgProjectTableItem } from '@/models/setting/system/orgAndProject';
@ -183,6 +186,10 @@
title: 'system.organization.createTime',
dataIndex: 'createTime',
width: 180,
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
},
{
title: hasOperationPermission.value ? 'system.organization.operation' : '',
@ -243,7 +250,7 @@
const handleDelete = (record: TableData) => {
openDeleteModal({
title: t('system.organization.deleteName', { name: record.name }),
title: t('system.organization.deleteName', { name: characterLimit(record.name) }),
content: t('system.organization.deleteTip'),
onBeforeOk: async () => {
try {

View File

@ -4,7 +4,9 @@
<a-tooltip background-color="#FFFFFF">
<template #content>
<span>
<span class="text-[var(--color-text-1)]">{{ t('system.project.revokeDeleteToolTip') }}</span>
<span class="text-[var(--color-text-1)]">{{
t('system.project.revokeDeleteToolTip', { count: record.remainDayCount })
}}</span>
<MsButton
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+RECOVER']"
class="ml-[8px]"
@ -104,6 +106,7 @@
import { useI18n } from '@/hooks/useI18n';
import useModal from '@/hooks/useModal';
import { useTableStore } from '@/store';
import { characterLimit } from '@/utils';
import { hasAnyPermission } from '@/utils/permission';
import { UserItem } from '@/models/setting/log';
@ -234,7 +237,7 @@
const handleDelete = (record: TableData) => {
openDeleteModal({
title: t('system.organization.deleteName', { name: record.name }),
title: t('system.organization.deleteName', { name: characterLimit(record.name) }),
content: t('system.organization.deleteTip'),
onBeforeOk: async () => {
try {

View File

@ -16,7 +16,7 @@
</a-button>
<a-input-search
v-model:model-value="keyword"
:placeholder="t('system.user.searchUser')"
:placeholder="t('system.organization.searchUserPlaceholder')"
class="w-[230px]"
allow-clear
@search="searchUser"

View File

@ -3,6 +3,7 @@
<div class="mb-4 flex items-center justify-between">
<div>
<a-button
v-if="currentTable !== 'organization' || licenseStore.hasLicense()"
v-permission="['SYSTEM_ORGANIZATION_PROJECT:READ+ADD']"
type="primary"
@click="handleAddOrganization"
@ -16,7 +17,7 @@
<div class="flex items-center">
<a-input-search
v-model="keyword"
:placeholder="t('system.user.searchUser')"
:placeholder="t('system.organization.searchIndexPlaceholder')"
class="w-[240px]"
allow-clear
@press-enter="handleEnter"
@ -53,6 +54,7 @@
import { getOrgAndProjectCount } from '@/api/modules/setting/organizationAndProject';
import { useI18n } from '@/hooks/useI18n';
import useLicenseStore from '@/store/modules/setting/license';
const { t } = useI18n();
const currentTable = ref('organization');
@ -64,6 +66,7 @@
const orgTableRef = ref();
const projectTableRef = ref();
const projectVisible = ref(false);
const licenseStore = useLicenseStore();
//
const initOrgAndProjectCount = async () => {

View File

@ -44,7 +44,7 @@ export default {
'system.organization.deleteName': 'Are you sure to delete {name}',
'system.organization.deleteTip':
'Delete the organization and delete the project data under that organization together. Please be cautious!',
'system.organization.revokeDeleteToolTip': 'The organization will be deleted automatically after 30 days',
'system.organization.revokeDeleteToolTip': 'The organization will be deleted automatically after {count} days',
'system.organization.createOrganizationSuccess': 'Create organization success',
'system.organization.enableTitle': 'Start organization',
'system.organization.endTitle': 'Close organization',
@ -55,6 +55,8 @@ export default {
'system.organization.updateOrganizationSuccess': 'Update organization success',
'system.organization.createProject': 'Create project',
'system.organization.subordinateOrg': 'Subordinate organization',
'system.organization.searchUserPlaceholder': 'Search by name/email/phone number',
'system.organization.searchIndexPlaceholder': 'Search by name/id',
'system.project.revokeDeleteTitle': 'Confirm revoke {name} ?',
'system.project.enableTitle': 'Start project',
'system.project.endTitle': 'Close project',
@ -72,6 +74,7 @@ export default {
'system.project.projectNameRequired': 'Project name cannot be empty',
'system.project.createTip': 'After the project is enabled, it will be displayed in the project switching list',
'system.project.affiliatedOrgRequired': 'Affiliated organization cannot be empty',
'system.project.revokeDeleteToolTip': 'The project will be deleted automatically after 30 days',
'system.project.revokeDeleteToolTip': 'The project will be deleted automatically after {count} days',
'system.project.removeTip': "Remove it, and you'll lose access to the project.",
'system.organization.projectIsDisabled': 'The project has ended and can be opened in the project list.',
};

View File

@ -22,7 +22,7 @@ export default {
'system.organization.organizationAdmin': '组织管理员',
'system.organization.organizationAdminPlaceholder': '默认选择创建组织人为组织管理员',
'system.organization.description': '描述',
'system.organization.descriptionPlaceholder': '请对组织进行描述',
'system.organization.descriptionPlaceholder': '请对组织进行描述',
'system.organization.ID': 'ID',
'system.organization.name': '名称',
'system.organization.member': '成员',
@ -41,7 +41,7 @@ export default {
'system.organization.addSuccess': '添加成功',
'system.organization.deleteName': '确认删除 {name} 这个组织吗',
'system.organization.deleteTip': '删除组织同时将该组织下的项目数据一起删除,请谨慎操作!',
'system.organization.revokeDeleteToolTip': '该组织将与 30 天后自动删除',
'system.organization.revokeDeleteToolTip': '该组织将与 {count} 天后自动删除',
'system.organization.createOrganizationSuccess': '创建组织成功',
'system.organization.enableTitle': '开启组织',
'system.organization.endTitle': '关闭组织',
@ -51,6 +51,8 @@ export default {
'system.organization.updateOrganizationSuccess': '更新组织成功',
'system.organization.createProject': '创建项目',
'system.organization.subordinateOrg': '所属组织',
'system.organization.searchIndexPlaceholder': '通过ID或名称搜索',
'system.organization.searchUserPlaceholder': '通过名称/邮箱/手机号搜索',
'system.project.revokeDeleteTitle': '确认恢复 {name} 这个项目吗?',
'system.project.enableTitle': '开启项目',
'system.project.endTitle': '关闭项目',
@ -67,6 +69,7 @@ export default {
'system.project.projectNameRequired': '项目名称不能为空',
'system.project.createTip': '项目启用后,将展示在项目切换列表',
'system.project.affiliatedOrgRequired': '所属组织不能为空',
'system.project.revokeDeleteToolTip': '该项目将于30 天后自动删除',
'system.project.revokeDeleteToolTip': '该项目将于 {count} 天后自动删除',
'system.project.removeTip': '移除后,将失去项目权限',
'system.organization.projectIsDisabled': '项目已结束,可在 项目列表 开启',
};