feat(系统设置): 组织与项目静态页面
This commit is contained in:
parent
146ce20a59
commit
280ed916d6
|
@ -17,8 +17,8 @@ http{
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|
||||||
location ^~ /app/ {
|
location ^~ /front/ {
|
||||||
proxy_pass http://172.16.200.18:8081/app/;
|
proxy_pass http://172.16.200.18:8081/;
|
||||||
proxy_connect_timeout 2s;
|
proxy_connect_timeout 2s;
|
||||||
proxy_read_timeout 600s;
|
proxy_read_timeout 600s;
|
||||||
proxy_send_timeout 600s;
|
proxy_send_timeout 600s;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import MSR from '@/api/http/index';
|
||||||
|
import * as orgUrl from '@/api/requrls/setting/system/organizationAndProject';
|
||||||
|
import { TableQueryParams } from '@/models/common';
|
||||||
|
|
||||||
|
// 获取组织列表
|
||||||
|
export function postOrgTable(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: orgUrl.postOrgTableUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取项目列表
|
||||||
|
export function postProjectTable(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: orgUrl.postProjectTableUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据组织id获取项目列表
|
||||||
|
export function postProjectTableByOrgId(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: orgUrl.postProjectTableByOrgUrl, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据组织id获取用户列表
|
||||||
|
export function postUserTableByOrgId(data: TableQueryParams) {
|
||||||
|
return MSR.post({ url: orgUrl.postOrgMemberUrl, data });
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
// 修改组织
|
||||||
|
export const postModifyOrgUrl = '/system/organization/update';
|
||||||
|
// 获取系统下所有组织-下拉选项
|
||||||
|
export const postOrgOptionsUrl = '/system/organization/option/all';
|
||||||
|
// 获取系统下所有组织-Table
|
||||||
|
export const postOrgTableUrl = '/system/organization/list';
|
||||||
|
// 获取组织下所有项目-Table
|
||||||
|
export const postProjectTableByOrgUrl = '/system/organization/list-project';
|
||||||
|
// 获取组织成员
|
||||||
|
export const postOrgMemberUrl = '/system/organization/list-member';
|
||||||
|
// 添加组织
|
||||||
|
export const postAddOrgUrl = '/system/organization/add';
|
||||||
|
// 添加组织成员
|
||||||
|
export const postAddOrgMemberUrl = '/system/organization/member/add';
|
||||||
|
// 删除组织成员
|
||||||
|
export const getDeleteOrgMemberUrl = '/system/organization/remove-member/';
|
||||||
|
// 恢复组织
|
||||||
|
export const getRecoverOrgUrl = '/system/organization/recover/';
|
||||||
|
// 启用组织
|
||||||
|
export const getEnableOrgUrl = '/system/organization/enable/';
|
||||||
|
// 禁用组织
|
||||||
|
export const getDisableOrgUrl = '/system/organization/disable/';
|
||||||
|
// 删除组织
|
||||||
|
export const getDeleteOrgUrl = '/system/organization/delete/';
|
||||||
|
// 获取系统默认组织
|
||||||
|
export const getOrgDefaultUrl = '/system/organization/default';
|
||||||
|
|
||||||
|
// 项目
|
||||||
|
// 更新项目信息
|
||||||
|
export const postModifyProjectUrl = '/system/project/update';
|
||||||
|
// 获取项目列表
|
||||||
|
export const postProjectTableUrl = '/system/project/list';
|
||||||
|
// 获取项目成员
|
||||||
|
export const postProjectMemberUrl = '/system/project/member/list';
|
||||||
|
// 添加项目
|
||||||
|
export const postAddProjectUrl = '/system/project/add';
|
||||||
|
// 添加项目成员
|
||||||
|
export const postAddProjectMemberUrl = '/system/project/member/add';
|
||||||
|
// 撤销项目
|
||||||
|
export const getRevokeProjectUrl = '/system/project/revoke/';
|
||||||
|
// 移除项目成员
|
||||||
|
export const getDeleteProjectMemberUrl = '/system/project/remove-member/';
|
||||||
|
// 根据ID获取项目信息
|
||||||
|
export const getProjectInfoUrl = '/system/project/get/';
|
||||||
|
// 删除项目
|
||||||
|
export const getDeleteProjectUrl = '/system/project/delete/';
|
|
@ -0,0 +1,72 @@
|
||||||
|
<template>
|
||||||
|
<a-select
|
||||||
|
:value="value"
|
||||||
|
:disabled="props.disabled"
|
||||||
|
multiple
|
||||||
|
:virtual-list-props="{ height: 200 }"
|
||||||
|
:placeholder="props.placeholder ? t(props.placeholder) : t('common.pleaseSelect')"
|
||||||
|
:options="userOptions"
|
||||||
|
:field-names="fieldNames"
|
||||||
|
@search="handleSearch"
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<template #label="{ data }">
|
||||||
|
<span class="option-name"> {{ data.name }} </span>
|
||||||
|
</template>
|
||||||
|
<template #option="{ data }">
|
||||||
|
<span class="option-name"> {{ data.name }} </span>
|
||||||
|
<span class="option-email"> {{ `(${data.email})` }} </span>
|
||||||
|
</template>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { getUserList } from '@/api/modules/setting/usergroup';
|
||||||
|
|
||||||
|
export interface MsUserSelectorProps {
|
||||||
|
value: string[];
|
||||||
|
disabled?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserItem {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldNames = { value: 'id', label: 'name' };
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<MsUserSelectorProps>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:value', value: string[]): void;
|
||||||
|
}>();
|
||||||
|
const allOption = ref<UserItem[]>([]);
|
||||||
|
const userOptions = ref<UserItem[]>([]);
|
||||||
|
|
||||||
|
const initUserList = async () => {
|
||||||
|
const res = await getUserList();
|
||||||
|
allOption.value = res;
|
||||||
|
userOptions.value = res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = (value: string) => {
|
||||||
|
if (value) {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
userOptions.value = userOptions.value.filter((item) => item.name.includes(value));
|
||||||
|
}, 60);
|
||||||
|
} else {
|
||||||
|
userOptions.value = allOption.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (value: string | number | Record<string, any> | (string | number | Record<string, any>)[]) => {
|
||||||
|
emit('update:value', value as string[]);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initUserList();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -390,6 +390,8 @@ export default defineComponent({
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (props.total === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={cls.value}>
|
<div class={cls.value}>
|
||||||
{props.showTotal && (
|
{props.showTotal && (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="ms-base-tale">
|
<div class="ms-base-tale">
|
||||||
<select-all
|
<select-all
|
||||||
v-if="attrs.showSelectAll"
|
v-if="attrs.selectable && attrs.showSelectAll"
|
||||||
class="custom-action"
|
class="custom-action"
|
||||||
:total="selectTotal"
|
:total="selectTotal"
|
||||||
:current="selectCurrent"
|
:current="selectCurrent"
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
>
|
>
|
||||||
<template #columns>
|
<template #columns>
|
||||||
<a-table-column
|
<a-table-column
|
||||||
v-for="(item, idx) in columns"
|
v-for="(item, idx) in currentColumns"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
:width="item.width"
|
:width="item.width"
|
||||||
:align="item.align"
|
:align="item.align"
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
:tooltip="item.tooltip"
|
:tooltip="item.tooltip"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<div v-if="attrs.showSetting && idx === columns.length - 1" class="column-selector">
|
<div v-if="attrs.showSetting && idx === currentColumns.length - 1" class="column-selector">
|
||||||
<div class="title">{{ t(item.title as string) }}</div>
|
<div class="title">{{ t(item.title as string) }}</div>
|
||||||
<ColumnSelector :table-key="(attrs.tableKey as string)" @close="handleColumnSelectorClose" />
|
<ColumnSelector :table-key="(attrs.tableKey as string)" @close="handleColumnSelectorClose" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,14 +45,16 @@
|
||||||
<template #cell="{ column, record, rowIndex }">
|
<template #cell="{ column, record, rowIndex }">
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<template v-if="item.dataIndex === SpecialColumnEnum.ENABLE">
|
<template v-if="item.dataIndex === SpecialColumnEnum.ENABLE">
|
||||||
<div v-if="record.enable" class="flex items-center">
|
<slot name="enable" v-bind="{ record }">
|
||||||
<icon-check-circle-fill class="mr-[2px] text-[rgb(var(--success-6))]" />
|
<div v-if="record.enable" class="flex items-center">
|
||||||
{{ t('system.user.tableEnable') }}
|
<icon-check-circle-fill class="mr-[2px] text-[rgb(var(--success-6))]" />
|
||||||
</div>
|
{{ t('msTable.enable') }}
|
||||||
<div v-else class="flex items-center text-[var(--color-text-4)]">
|
</div>
|
||||||
<MsIcon type="icon-icon_disable" class="mr-[2px]" />
|
<div v-else class="flex items-center text-[var(--color-text-4)]">
|
||||||
{{ t('system.user.tableDisable') }}
|
<MsIcon type="icon-icon_disable" class="mr-[2px]" />
|
||||||
</div>
|
{{ t('msTable.disable') }}
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-input
|
<a-input
|
||||||
|
@ -124,12 +126,14 @@
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const columns = ref<MsTableColumn>([]);
|
const currentColumns = ref<MsTableColumn>([]);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
selectedKeys?: (string | number)[];
|
selectedKeys?: (string | number)[];
|
||||||
actionConfig?: BatchActionConfig;
|
actionConfig?: BatchActionConfig;
|
||||||
noDisable?: boolean;
|
noDisable?: boolean;
|
||||||
|
showSetting?: boolean;
|
||||||
|
columns: MsTableColumn;
|
||||||
}>();
|
}>();
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'selectedChange', value: (string | number)[]): void;
|
(e: 'selectedChange', value: (string | number)[]): void;
|
||||||
|
@ -160,7 +164,13 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const initColumn = () => {
|
const initColumn = () => {
|
||||||
columns.value = tableStore.getShowInTableColumns(attrs.tableKey as string);
|
let tmpArr: MsTableColumn = [];
|
||||||
|
if (props.showSetting) {
|
||||||
|
tmpArr = tableStore.getShowInTableColumns(attrs.tableKey as string);
|
||||||
|
} else {
|
||||||
|
tmpArr = props.columns;
|
||||||
|
}
|
||||||
|
currentColumns.value = tmpArr;
|
||||||
};
|
};
|
||||||
// 选择公共执行方法
|
// 选择公共执行方法
|
||||||
const selectionChange = (arr: (string | number)[], setCurrentSelect: boolean, isAll = false) => {
|
const selectionChange = (arr: (string | number)[], setCurrentSelect: boolean, isAll = false) => {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
</template>
|
</template>
|
||||||
<div v-if="props.actionConfig.moreAction" class="relative top-[2px] ml-3 inline-block">
|
<div v-if="props.actionConfig.moreAction" class="relative top-[2px] ml-3 inline-block">
|
||||||
<a-dropdown position="tr" @select="handleSelect">
|
<a-dropdown position="tr" @select="handleSelect">
|
||||||
<a-button type="outline"><a-icon-more /></a-button>
|
<a-button type="outline"><MsIcon type="icon-icon_more_outlined" /></a-button>
|
||||||
<template #content>
|
<template #content>
|
||||||
<template v-for="element in props.actionConfig.moreAction" :key="element.label">
|
<template v-for="element in props.actionConfig.moreAction" :key="element.label">
|
||||||
<a-divider v-if="element.isDivider" margin="0" />
|
<a-divider v-if="element.isDivider" margin="0" />
|
||||||
|
@ -34,6 +34,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { BatchActionConfig, BatchActionParams } from './type';
|
import { BatchActionConfig, BatchActionParams } from './type';
|
||||||
|
import MsIcon from '../ms-icon-font/index.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|
|
@ -2,6 +2,8 @@ export default {
|
||||||
msTable: {
|
msTable: {
|
||||||
current: 'Select Current Page',
|
current: 'Select Current Page',
|
||||||
all: 'Select All Pages',
|
all: 'Select All Pages',
|
||||||
|
enable: 'Enable',
|
||||||
|
disable: 'Disable',
|
||||||
batch: {
|
batch: {
|
||||||
title: '批量操作',
|
title: '批量操作',
|
||||||
selected: '已选择 {count} 项',
|
selected: '已选择 {count} 项',
|
||||||
|
|
|
@ -2,6 +2,8 @@ export default {
|
||||||
msTable: {
|
msTable: {
|
||||||
current: '全选当前页',
|
current: '全选当前页',
|
||||||
all: '全选所有页',
|
all: '全选所有页',
|
||||||
|
enable: '启用',
|
||||||
|
disable: '禁用',
|
||||||
batch: {
|
batch: {
|
||||||
title: '批量操作',
|
title: '批量操作',
|
||||||
selected: '已选择 {count} 项',
|
selected: '已选择 {count} 项',
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="ms-table-select-all items-center text-base">
|
<div class="ms-table-select-all items-center text-base">
|
||||||
<a-checkbox v-model="checked" class="text-base" :indeterminate="indeterminate" @change="handleCheckChange" />
|
<a-checkbox v-model="checked" class="text-base" :indeterminate="indeterminate" @change="handleCheckChange" />
|
||||||
<a-dropdown position="bl" @select="handleSelect">
|
<a-dropdown position="bl" @select="handleSelect">
|
||||||
<a-icon-down class="dropdown-icon ml-0.5" />
|
<MsIcon type="icon-icon_down_outlined" class="ml-0.5" />
|
||||||
<template #content>
|
<template #content>
|
||||||
<a-doption :value="SelectAllEnum.CURRENT">{{ t('msTable.current') }}</a-doption>
|
<a-doption :value="SelectAllEnum.CURRENT">{{ t('msTable.current') }}</a-doption>
|
||||||
<a-doption :value="SelectAllEnum.ALL">{{ t('msTable.all') }}</a-doption>
|
<a-doption :value="SelectAllEnum.ALL">{{ t('msTable.all') }}</a-doption>
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
import { ref, watchEffect } from 'vue';
|
import { ref, watchEffect } from 'vue';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { SelectAllEnum } from './type';
|
import { SelectAllEnum } from './type';
|
||||||
|
import MsIcon from '../ms-icon-font/index.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ export interface MsTableProps {
|
||||||
scroll?: {
|
scroll?: {
|
||||||
x?: number | string;
|
x?: number | string;
|
||||||
y?: number | string;
|
y?: number | string;
|
||||||
|
maxHeight?: number | string;
|
||||||
|
minWidth?: number | string;
|
||||||
};
|
};
|
||||||
// 表格是否可拖拽
|
// 表格是否可拖拽
|
||||||
enableDrag?: boolean;
|
enableDrag?: boolean;
|
||||||
|
@ -63,9 +65,9 @@ export interface MsTableProps {
|
||||||
pageSimple?: boolean;
|
pageSimple?: boolean;
|
||||||
// 编辑的key,默认为name
|
// 编辑的key,默认为name
|
||||||
editKey?: string;
|
editKey?: string;
|
||||||
[key: string]: any;
|
|
||||||
// 是否展示禁用的行
|
// 是否展示禁用的行
|
||||||
noDisable?: boolean;
|
noDisable?: boolean;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MsTableSelectAll {
|
export interface MsTableSelectAll {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default function useTableProps(
|
||||||
loadListFunc: (v: TableQueryParams) => Promise<any>,
|
loadListFunc: (v: TableQueryParams) => Promise<any>,
|
||||||
props?: Partial<MsTableProps>,
|
props?: Partial<MsTableProps>,
|
||||||
// 数据处理的回调函数
|
// 数据处理的回调函数
|
||||||
callBack?: (item: TableData) => TableData,
|
dataTransform?: (item: TableData) => TableData,
|
||||||
// 编辑操作的保存回调函数
|
// 编辑操作的保存回调函数
|
||||||
saveCallBack?: (item: TableData) => Promise<any>
|
saveCallBack?: (item: TableData) => Promise<any>
|
||||||
) {
|
) {
|
||||||
|
@ -35,7 +35,7 @@ export default function useTableProps(
|
||||||
bordered: true,
|
bordered: true,
|
||||||
showPagination: true,
|
showPagination: true,
|
||||||
size: 'small',
|
size: 'small',
|
||||||
scroll: { y: '860px', x: '1400px' },
|
scroll: { maxHeight: '600px', x: '1400px' },
|
||||||
checkable: true,
|
checkable: true,
|
||||||
loading: true,
|
loading: true,
|
||||||
data: [] as MsTableData,
|
data: [] as MsTableData,
|
||||||
|
@ -166,8 +166,8 @@ export default function useTableProps(
|
||||||
if (item.createTime) {
|
if (item.createTime) {
|
||||||
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
|
item.createTime = dayjs(item.createTime).format('YYYY-MM-DD HH:mm:ss');
|
||||||
}
|
}
|
||||||
if (callBack) {
|
if (dataTransform) {
|
||||||
item = callBack(item);
|
item = dataTransform(item);
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,4 +13,6 @@ export enum TableKeyEnum {
|
||||||
SYSTEM_RESOURCEPOOL = 'systemResourcePool',
|
SYSTEM_RESOURCEPOOL = 'systemResourcePool',
|
||||||
SYSTEM_AUTH = 'systemAuth',
|
SYSTEM_AUTH = 'systemAuth',
|
||||||
ORGANNATIONMEMBER = 'member',
|
ORGANNATIONMEMBER = 'member',
|
||||||
|
SYSTEM_ORGANIZATION = 'systemOrganization',
|
||||||
|
SYSTEM_PROJECT = 'systemProject',
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ Object.keys(_Vmodules).forEach((key) => {
|
||||||
if (!defaultModule) return;
|
if (!defaultModule) return;
|
||||||
result = { ...result, ...defaultModule };
|
result = { ...result, ...defaultModule };
|
||||||
});
|
});
|
||||||
|
console.log('result', result);
|
||||||
export default {
|
export default {
|
||||||
message: {
|
message: {
|
||||||
'menu.workplace': 'Workplace',
|
'menu.workplace': 'Workplace',
|
||||||
|
|
|
@ -42,6 +42,16 @@ const Setting: AppRouteRecordRaw = {
|
||||||
isTopMenu: true,
|
isTopMenu: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'organization-and-project',
|
||||||
|
name: 'settingSystemOrganization',
|
||||||
|
component: () => import('@/views/setting/system/organizationAndProject/index.vue'),
|
||||||
|
meta: {
|
||||||
|
locale: 'menu.settings.system.organizationAndProject',
|
||||||
|
roles: ['*'],
|
||||||
|
isTopMenu: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'resourcePool',
|
path: 'resourcePool',
|
||||||
name: 'settingSystemResourcePool',
|
name: 'settingSystemResourcePool',
|
||||||
|
|
|
@ -18,6 +18,14 @@ const msTableStore = defineStore('msTable', {
|
||||||
initColumn(tableKey: string, column: MsTableColumn, mode: TableOpenDetailMode) {
|
initColumn(tableKey: string, column: MsTableColumn, mode: TableOpenDetailMode) {
|
||||||
if (!this.selectorColumnMap.has(tableKey)) {
|
if (!this.selectorColumnMap.has(tableKey)) {
|
||||||
const tmpMap = this.selectorColumnMap;
|
const tmpMap = this.selectorColumnMap;
|
||||||
|
column.forEach((item) => {
|
||||||
|
if (item.showInTable === undefined) {
|
||||||
|
item.showInTable = true;
|
||||||
|
}
|
||||||
|
if (item.showDrag === undefined) {
|
||||||
|
item.showDrag = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
tmpMap.set(tableKey, { mode, column });
|
tmpMap.set(tableKey, { mode, column });
|
||||||
this.selectorColumnMap = tmpMap;
|
this.selectorColumnMap = tmpMap;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<template>
|
||||||
|
<a-modal
|
||||||
|
v-model:visible="currentVisible"
|
||||||
|
width="680px"
|
||||||
|
:ok-text="t('system.organization.create')"
|
||||||
|
unmount-on-close
|
||||||
|
:on-before-ok="handleBeforeOk"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title> {{ t('system.organization.createOrganization') }} </template>
|
||||||
|
<div class="form">
|
||||||
|
<a-form ref="formRef" :model="form" size="large" :style="{ width: '600px' }" layout="vertical">
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
required
|
||||||
|
:label="t('system.organization.organizationName')"
|
||||||
|
:rules="[
|
||||||
|
{ required: true, message: t('system.organization.organizationNameRequired') },
|
||||||
|
{ validator: validateName },
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<a-input v-model="form.name" :placeholder="t('system.organization.organizationNamePlaceholder')" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="name" :label="t('system.organization.organizationAdmin')">
|
||||||
|
<MsUserSelector v-model:value="form.admin" placeholder="system.organization.organizationAdminPlaceholder" />
|
||||||
|
</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-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { reactive, ref, watchEffect } from 'vue';
|
||||||
|
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
import MsUserSelector from '@/components/bussiness/ms-user-selector/index.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<{
|
||||||
|
visible: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
name: '',
|
||||||
|
admin: [],
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentVisible = ref(props.visible);
|
||||||
|
|
||||||
|
const validateName = (value: string, callback: (error?: string) => void) => {
|
||||||
|
if (value !== '') {
|
||||||
|
// const isExist = props.list.some((item) => item.name === value);
|
||||||
|
// if (isExist) {
|
||||||
|
// callback(t('system.organization.userGroupNameIsExist', { name: value }));
|
||||||
|
// }
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
currentVisible.value = props.visible;
|
||||||
|
});
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBeforeOk = () => {
|
||||||
|
formRef.value?.validate((errors: undefined | Record<string, ValidatedError>) => {
|
||||||
|
if (errors) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<MsDrawer
|
||||||
|
:width="680"
|
||||||
|
:visible="props.visible"
|
||||||
|
unmount-on-close
|
||||||
|
:footer="false"
|
||||||
|
:title="t('system.organization.projectName', { name: props.currentName })"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-row justify-end">
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('system.user.searchUser')"
|
||||||
|
class="w-[230px]"
|
||||||
|
@search="searchUser"
|
||||||
|
@press-enter="searchUser"
|
||||||
|
></a-input-search>
|
||||||
|
</div>
|
||||||
|
<ms-base-table v-bind="propsRes" v-on="propsEvent" />
|
||||||
|
</div>
|
||||||
|
</MsDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { postProjectTableByOrgId } from '@/api/modules/setting/system/organizationAndProject';
|
||||||
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { watch, ref } from 'vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
|
||||||
|
export interface projectDrawerProps {
|
||||||
|
visible: boolean;
|
||||||
|
organizationId: string;
|
||||||
|
currentName: string;
|
||||||
|
}
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<projectDrawerProps>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', v: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const keyword = ref('');
|
||||||
|
|
||||||
|
const projectColumn: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.organization.ID',
|
||||||
|
dataIndex: 'num',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.project.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.status',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.creator',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createTime',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(postProjectTableByOrgId, {
|
||||||
|
columns: projectColumn,
|
||||||
|
showSetting: false,
|
||||||
|
scroll: { y: 'auto', x: '600px' },
|
||||||
|
selectable: false,
|
||||||
|
noDisable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function searchUser() {
|
||||||
|
setKeyword(keyword.value);
|
||||||
|
await loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
await loadList();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.organizationId,
|
||||||
|
(organizationId) => {
|
||||||
|
setLoadListParams({ organizationId });
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
|
@ -0,0 +1,196 @@
|
||||||
|
<template>
|
||||||
|
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||||
|
<template #memberCount="{ record }">
|
||||||
|
<span class="primary-color" @click="showUserDrawer(record)">{{ record.memberCount }}</span>
|
||||||
|
</template>
|
||||||
|
<template #projectCount="{ record }">
|
||||||
|
<span class="primary-color" @click="showProjectDrawer(record)">{{ record.projectCount }}</span>
|
||||||
|
</template>
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<template v-if="!record.enable">
|
||||||
|
<MsButton @click="handleEnable(record)">{{ t('system.organization.enable') }}</MsButton>
|
||||||
|
<MsButton @click="handleDelete(record)">{{ t('system.organization.delete') }}</MsButton>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<MsButton @click="showOrganizationModal(record)">{{ t('system.organization.edit') }}</MsButton>
|
||||||
|
<MsButton @click="showAddUserModal(record)">{{ t('system.organization.addMember') }}</MsButton>
|
||||||
|
<MsButton @click="handleEnd(record)">{{ t('system.organization.end') }}</MsButton>
|
||||||
|
<MsTableMoreAction :list="tableActions" @select="handleMoreAction($event, record)"></MsTableMoreAction>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
|
<AddOrganizationModal :visible="userVisible" @cancel="handleAddUserModalCancel" />
|
||||||
|
<ProjectDrawer v-bind="currentProjectDrawer" @cancel="handleProjectDrawerCancel" />
|
||||||
|
<UserDrawer v-bind="currentUserDrawer" @cancel="handleUserDrawerCancel" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import { useTableStore } from '@/store';
|
||||||
|
import { ref, reactive, watchEffect } from 'vue';
|
||||||
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import { postOrgTable } from '@/api/modules/setting/system/organizationAndProject';
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import AddOrganizationModal from './addOrganizationModal.vue';
|
||||||
|
import ProjectDrawer from './projectDrawer.vue';
|
||||||
|
import { TableData } from '@arco-design/web-vue';
|
||||||
|
import UserDrawer from './userDrawer.vue';
|
||||||
|
|
||||||
|
export interface SystemOrganizationProps {
|
||||||
|
keyword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<SystemOrganizationProps>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const tableStore = useTableStore();
|
||||||
|
const userVisible = ref(false);
|
||||||
|
|
||||||
|
const currentProjectDrawer = reactive({
|
||||||
|
visible: false,
|
||||||
|
organizationId: '',
|
||||||
|
currentName: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentUserDrawer = reactive({
|
||||||
|
visible: false,
|
||||||
|
organizationId: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const tableActions: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.user.delete',
|
||||||
|
eventTag: 'delete',
|
||||||
|
danger: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMoreAction = (tag: string, record: any) => {
|
||||||
|
if (tag === 'delete') {
|
||||||
|
handleDelete(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnable = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnd = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showOrganizationModal = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showAddUserModal = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
userVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleProjectDrawerCancel = () => {
|
||||||
|
currentProjectDrawer.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showProjectDrawer = (record: TableData) => {
|
||||||
|
currentProjectDrawer.visible = true;
|
||||||
|
currentProjectDrawer.organizationId = record.id;
|
||||||
|
currentProjectDrawer.currentName = record.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showUserDrawer = (record: TableData) => {
|
||||||
|
currentUserDrawer.visible = true;
|
||||||
|
currentUserDrawer.organizationId = record.id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUserDrawerCancel = () => {
|
||||||
|
currentUserDrawer.visible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const organizationColumns: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.organization.ID',
|
||||||
|
dataIndex: 'num',
|
||||||
|
width: 100,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.member',
|
||||||
|
slotName: 'memberCount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.project',
|
||||||
|
slotName: 'projectCount',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.status',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.description',
|
||||||
|
dataIndex: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createUser',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createTime',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
width: 230,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 208,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
tableStore.initColumn(TableKeyEnum.SYSTEM_ORGANIZATION, organizationColumns, 'drawer');
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, loadList, setKeyword } = useTable(postOrgTable, {
|
||||||
|
tableKey: TableKeyEnum.SYSTEM_ORGANIZATION,
|
||||||
|
scroll: { y: 'auto', x: '1300px' },
|
||||||
|
selectable: false,
|
||||||
|
noDisable: false,
|
||||||
|
size: 'default',
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
await loadList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddUserModalCancel = () => {
|
||||||
|
userVisible.value = false;
|
||||||
|
};
|
||||||
|
watchEffect(() => {
|
||||||
|
setKeyword(props.keyword);
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.primary-color {
|
||||||
|
color: rgb(var(--primary-5));
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,137 @@
|
||||||
|
<template>
|
||||||
|
<MsBaseTable v-bind="propsRes" v-on="propsEvent">
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<template v-if="!record.enable">
|
||||||
|
<MsButton @click="handleEnable(record)">{{ t('system.organization.enable') }}</MsButton>
|
||||||
|
<MsButton @click="handleDelete(record)">{{ t('system.organization.delete') }}</MsButton>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<MsButton @click="showOrganizationModal(record)">{{ t('system.organization.edit') }}</MsButton>
|
||||||
|
<MsButton @click="showAddUserModal(record)">{{ t('system.organization.addUser') }}</MsButton>
|
||||||
|
<MsButton @click="handleEnd(record)">{{ t('system.organization.end') }}</MsButton>
|
||||||
|
<MsTableMoreAction :list="tableActions" @select="handleMoreAction($event, record)"></MsTableMoreAction>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</MsBaseTable>
|
||||||
|
<AddOrganizationModal :visible="userVisible" @cancel="handleAddUserModalCancel" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
import { useTableStore } from '@/store';
|
||||||
|
import { watchEffect, ref } from 'vue';
|
||||||
|
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||||
|
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||||
|
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||||
|
import { postUserByUserGroup } from '@/api/modules/setting/usergroup';
|
||||||
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import AddOrganizationModal from './addOrganizationModal.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const tableStore = useTableStore();
|
||||||
|
const userVisible = ref(false);
|
||||||
|
|
||||||
|
const tableActions: ActionsItem[] = [
|
||||||
|
{
|
||||||
|
label: 'system.user.delete',
|
||||||
|
eventTag: 'delete',
|
||||||
|
danger: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleDelete = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMoreAction = (tag: string, record: any) => {
|
||||||
|
if (tag === 'delete') {
|
||||||
|
handleDelete(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnable = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEnd = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showOrganizationModal = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showAddUserModal = (record: any) => {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(record);
|
||||||
|
userVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const projectColumn: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.organization.ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.member',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.project',
|
||||||
|
dataIndex: 'project',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.enabled',
|
||||||
|
dataIndex: 'enabled',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.description',
|
||||||
|
dataIndex: 'description',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createUser',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createTime',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
tableStore.initColumn(TableKeyEnum.SYSTEM_PROJECT, projectColumn, 'drawer');
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, loadList } = useTable(postUserByUserGroup, {
|
||||||
|
tableKey: TableKeyEnum.SYSTEM_PROJECT,
|
||||||
|
scroll: { y: 'auto', x: '600px' },
|
||||||
|
selectable: false,
|
||||||
|
noDisable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
await loadList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddUserModalCancel = () => {
|
||||||
|
userVisible.value = false;
|
||||||
|
};
|
||||||
|
watchEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,106 @@
|
||||||
|
<template>
|
||||||
|
<MsDrawer
|
||||||
|
:width="680"
|
||||||
|
:visible="props.visible"
|
||||||
|
unmount-on-close
|
||||||
|
:footer="false"
|
||||||
|
:title="t('system.organization.addMember')"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-row justify-between">
|
||||||
|
<a-button type="primary" @click="handleAddMember">
|
||||||
|
{{ t('system.organization.addMember') }}
|
||||||
|
</a-button>
|
||||||
|
<a-input-search
|
||||||
|
v-model:model-value="keyword"
|
||||||
|
:placeholder="t('system.user.searchUser')"
|
||||||
|
class="w-[230px]"
|
||||||
|
@search="searchUser"
|
||||||
|
@press-enter="searchUser"
|
||||||
|
></a-input-search>
|
||||||
|
</div>
|
||||||
|
<ms-base-table class="mt-[16px]" v-bind="propsRes" v-on="propsEvent" />
|
||||||
|
</div>
|
||||||
|
</MsDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { postUserTableByOrgId } from '@/api/modules/setting/system/organizationAndProject';
|
||||||
|
import { MsTableColumn } from '@/components/pure/ms-table/type';
|
||||||
|
import useTable from '@/components/pure/ms-table/useTable';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { watch, ref } from 'vue';
|
||||||
|
import MsDrawer from '@/components/pure/ms-drawer/index.vue';
|
||||||
|
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
|
||||||
|
|
||||||
|
export interface projectDrawerProps {
|
||||||
|
visible: boolean;
|
||||||
|
organizationId: string;
|
||||||
|
}
|
||||||
|
const { t } = useI18n();
|
||||||
|
const props = defineProps<projectDrawerProps>();
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update:visible', v: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const keyword = ref('');
|
||||||
|
|
||||||
|
const projectColumn: MsTableColumn = [
|
||||||
|
{
|
||||||
|
title: 'system.organization.ID',
|
||||||
|
dataIndex: 'num',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.project.name',
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.status',
|
||||||
|
dataIndex: 'enable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.creator',
|
||||||
|
dataIndex: 'createUser',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'system.organization.createTime',
|
||||||
|
dataIndex: 'createTime',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const { propsRes, propsEvent, loadList, setLoadListParams, setKeyword } = useTable(postUserTableByOrgId, {
|
||||||
|
columns: projectColumn,
|
||||||
|
showSetting: false,
|
||||||
|
scroll: { y: 'auto', x: '600px' },
|
||||||
|
selectable: false,
|
||||||
|
size: 'small',
|
||||||
|
noDisable: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function searchUser() {
|
||||||
|
setKeyword(keyword.value);
|
||||||
|
await loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('update:visible', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
await loadList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddMember = () => {
|
||||||
|
// TODO add member
|
||||||
|
emit('update:visible', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.organizationId,
|
||||||
|
(organizationId) => {
|
||||||
|
setLoadListParams({ organizationId });
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<MsCard simple>
|
||||||
|
<div class="mb-4 flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<a-button type="primary" @click="handleAddOrganization">{{
|
||||||
|
currentTable === 'organization'
|
||||||
|
? t('system.organization.createOrganization')
|
||||||
|
: t('system.organization.createProject')
|
||||||
|
}}</a-button>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a-input-search
|
||||||
|
:placeholder="t('system.user.searchUser')"
|
||||||
|
class="w-[230px]"
|
||||||
|
@change="handleKeywordChange"
|
||||||
|
@search="handleKeywordChange"
|
||||||
|
></a-input-search>
|
||||||
|
<a-radio-group v-model="currentTable" class="ml-[14px]" type="button">
|
||||||
|
<a-radio value="organization">{{
|
||||||
|
t('system.organization.organizationCount', { count: organizationCount })
|
||||||
|
}}</a-radio>
|
||||||
|
<a-radio value="project">{{ t('system.organization.projectCount', { count: projectCount }) }}</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<SystemOrganization v-if="currentTable === 'organization'" :keyword="currentKeyword" />
|
||||||
|
<SystemProject v-if="currentTable === 'project'" :keyword="currentKeyword" />
|
||||||
|
</div>
|
||||||
|
</MsCard>
|
||||||
|
<AddOrganizationModal :visible="organizationVisible" @cancel="handleAddOrganizationCancel" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||||
|
import AddOrganizationModal from './components/addOrganizationModal.vue';
|
||||||
|
import SystemOrganization from './components/systemOrganization.vue';
|
||||||
|
import SystemProject from './components/systemProject.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const currentTable = ref('organization');
|
||||||
|
const organizationVisible = ref(false);
|
||||||
|
const organizationCount = ref(0);
|
||||||
|
const projectCount = ref(0);
|
||||||
|
const currentKeyword = ref('');
|
||||||
|
|
||||||
|
const handleKeywordChange = (value: string) => {
|
||||||
|
currentKeyword.value = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddOrganization = () => {
|
||||||
|
organizationVisible.value = true;
|
||||||
|
};
|
||||||
|
const handleAddOrganizationCancel = () => {
|
||||||
|
organizationVisible.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,37 @@
|
||||||
|
export default {
|
||||||
|
'system.organization.create': 'Create',
|
||||||
|
'system.organization.cancel': 'Cancel',
|
||||||
|
'system.organization.add': 'Add',
|
||||||
|
'system.organization.delete': 'Delete',
|
||||||
|
'system.organization.edit': 'Edit',
|
||||||
|
'system.organization.save': 'Save',
|
||||||
|
'system.organization.end': 'End',
|
||||||
|
'system.organization.addMember': 'Add Member',
|
||||||
|
'system.organization.addMemberPlaceholder': 'Please select member',
|
||||||
|
'system.organization.addMemberRequired': 'Please select member',
|
||||||
|
'system.organization.searchPlaceholder': 'Please enter the organization name to query',
|
||||||
|
'system.organization.addOrganization': 'Add organization',
|
||||||
|
'system.organization.createOrganization': 'Create organization',
|
||||||
|
'system.organization.organizationName': 'Organization name',
|
||||||
|
'system.organization.organizationNamePlaceholder':
|
||||||
|
'Please enter the organization name, which cannot be duplicated with other organization names',
|
||||||
|
'system.organization.organizationNameRequired': 'Organization name cannot be empty',
|
||||||
|
'system.organization.organizationNameDuplicate': 'Already have {name} please change',
|
||||||
|
'system.organization.organizationAdmin': 'Organization administrator',
|
||||||
|
'system.organization.organizationAdminPlaceholder':
|
||||||
|
'The organization administrator defaults to the person who created the organization',
|
||||||
|
'system.organization.description': 'Description',
|
||||||
|
'system.organization.descriptionPlaceholder': 'Please describe the organization',
|
||||||
|
'system.organization.ID': 'ID',
|
||||||
|
'system.organization.name': 'Name',
|
||||||
|
'system.organization.member': 'Member',
|
||||||
|
'system.organization.project': 'Project',
|
||||||
|
'system.organization.status': 'Status',
|
||||||
|
'system.organization.creator': 'Creator',
|
||||||
|
'system.organization.createTime': 'Create Time',
|
||||||
|
'system.organization.operation': 'Operation',
|
||||||
|
'system.organization.organizationCount': 'Organization({count})',
|
||||||
|
'system.organization.projectCount': 'Project({count})',
|
||||||
|
'system.organization.projectName': 'Project({name})',
|
||||||
|
'system.project.name': 'Project name',
|
||||||
|
};
|
|
@ -0,0 +1,35 @@
|
||||||
|
export default {
|
||||||
|
'system.organization.create': '创建',
|
||||||
|
'system.organization.cancel': '取消',
|
||||||
|
'system.organization.add': '添加',
|
||||||
|
'system.organization.delete': '删除',
|
||||||
|
'system.organization.edit': '编辑',
|
||||||
|
'system.organization.save': '保存',
|
||||||
|
'system.organization.end': '结束',
|
||||||
|
'system.organization.addMember': '添加成员',
|
||||||
|
'system.organization.addMemberPlaceholder': '请选择成员',
|
||||||
|
'system.organization.addMemberRequired': '请选择成员',
|
||||||
|
'system.organization.searchPlaceholder': '请输入组织名称回车查询',
|
||||||
|
'system.organization.addOrganization': '添加组织',
|
||||||
|
'system.organization.createOrganization': '创建组织',
|
||||||
|
'system.organization.organizationName': '组织名称',
|
||||||
|
'system.organization.organizationNamePlaceholder': '请输入组织名称,不可与其他组织名称重复',
|
||||||
|
'system.organization.organizationNameRequired': '组织名称不能为空',
|
||||||
|
'system.organization.organizationNameDuplicate': '已有 {name} 请更改',
|
||||||
|
'system.organization.organizationAdmin': '组织管理员',
|
||||||
|
'system.organization.organizationAdminPlaceholder': '默认选择创建组织人为组织管理员',
|
||||||
|
'system.organization.description': '描述',
|
||||||
|
'system.organization.descriptionPlaceholder': '请对组织进行描述',
|
||||||
|
'system.organization.ID': 'ID',
|
||||||
|
'system.organization.name': '名称',
|
||||||
|
'system.organization.member': '成员',
|
||||||
|
'system.organization.project': '项目',
|
||||||
|
'system.organization.status': '状态',
|
||||||
|
'system.organization.creator': '创建人',
|
||||||
|
'system.organization.createTime': '创建时间',
|
||||||
|
'system.organization.operation': '操作',
|
||||||
|
'system.organization.organizationCount': '组织({count})',
|
||||||
|
'system.organization.projectCount': '项目({count})',
|
||||||
|
'system.organization.projectName': '项目({name})',
|
||||||
|
'system.project.name': '项目名称',
|
||||||
|
};
|
|
@ -16,23 +16,7 @@
|
||||||
:label="t('system.userGroup.user')"
|
:label="t('system.userGroup.user')"
|
||||||
:rules="[{ required: true, message: t('system.userGroup.pleaseSelectUser') }]"
|
:rules="[{ required: true, message: t('system.userGroup.pleaseSelectUser') }]"
|
||||||
>
|
>
|
||||||
<a-select
|
<ms-user-selector v-model:value="form.name" />
|
||||||
v-model="form.name"
|
|
||||||
multiple
|
|
||||||
:virtual-list-props="{ height: 200 }"
|
|
||||||
:placeholder="t('system.userGroup.pleaseSelectUser')"
|
|
||||||
:options="userOptions"
|
|
||||||
:field-names="fieldNames"
|
|
||||||
@search="handleSearch"
|
|
||||||
>
|
|
||||||
<template #label="{ data }">
|
|
||||||
<span class="option-name"> {{ data.name }} </span>
|
|
||||||
</template>
|
|
||||||
<template #option="{ data }">
|
|
||||||
<span class="option-name"> {{ data.name }} </span>
|
|
||||||
<span class="option-email"> {{ `(${data.email})` }} </span>
|
|
||||||
</template>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,6 +30,7 @@
|
||||||
import { useUserGroupStore } from '@/store';
|
import { useUserGroupStore } from '@/store';
|
||||||
import { getUserList, addUserToUserGroup } from '@/api/modules/setting/usergroup';
|
import { getUserList, addUserToUserGroup } from '@/api/modules/setting/usergroup';
|
||||||
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
import MsUserSelector from '@/components/bussiness/ms-user-selector/index.vue';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -59,8 +44,6 @@
|
||||||
(e: 'submit', value: string[]): void;
|
(e: 'submit', value: string[]): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const fieldNames = { value: 'id', label: 'name' };
|
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
const currentVisible = ref(props.visible);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
@ -102,18 +85,6 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearch = (value: string) => {
|
|
||||||
if (value) {
|
|
||||||
loading.value = true;
|
|
||||||
window.setTimeout(() => {
|
|
||||||
userOptions.value = userOptions.value.filter((item) => item.name.includes(value));
|
|
||||||
loading.value = false;
|
|
||||||
}, 60);
|
|
||||||
} else {
|
|
||||||
userOptions.value = allOption.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initUserList();
|
initUserList();
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="usergroup-auth-table">
|
<div class="usergroup-auth-table">
|
||||||
<a-table
|
<a-table
|
||||||
:span-method="dataSpanMethod"
|
:span-method="dataSpanMethod"
|
||||||
:scroll="{ y: '860px', x: '800px' }"
|
:scroll="{ y: '500px', x: '800px' }"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:bordered="{ wrapper: true, cell: true }"
|
:bordered="{ wrapper: true, cell: true }"
|
||||||
|
@ -286,6 +286,7 @@
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.usergroup-auth-table {
|
.usergroup-auth-table {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
min-height: calc(100vh - 230px);
|
||||||
:deep(.arco-table-container) {
|
:deep(.arco-table-container) {
|
||||||
border-top: 1px solid var(--color-text-n8) !important;
|
border-top: 1px solid var(--color-text-n8) !important;
|
||||||
border-right: 1px solid var(--color-text-n8) !important;
|
border-right: 1px solid var(--color-text-n8) !important;
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(postUserByUserGroup, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(postUserByUserGroup, {
|
||||||
tableKey: TableKeyEnum.USERGROUPUSER,
|
tableKey: TableKeyEnum.USERGROUPUSER,
|
||||||
scroll: { y: 'auto', x: '600px' },
|
scroll: { x: '600px' },
|
||||||
selectable: true,
|
selectable: true,
|
||||||
noDisable: true,
|
noDisable: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
<icon-double-right v-else class="icon" @click="collapse = true" />
|
<icon-double-right v-else class="icon" @click="collapse = true" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grow-1 w-[100%] overflow-x-scroll p-[24px]">
|
<div class="w-[100%] overflow-x-scroll p-[24px]">
|
||||||
<div class="grow-1 flex flex-row items-center justify-between">
|
<div class="flex flex-row items-center justify-between">
|
||||||
<div class="title">{{ store.userGroupInfo.currentName }}</div>
|
<div class="title">{{ store.userGroupInfo.currentName }}</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<a-input class="w-[240px]" :placeholder="t('system.userGroup.searchPlacehoder')">
|
<a-input class="w-[240px]" :placeholder="t('system.userGroup.searchPlacehoder')">
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
</a-radio-group>
|
</a-radio-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grow-1 mt-[16px]">
|
<div class="mt-[16px]">
|
||||||
<user-table v-if="currentTable === 'user'" />
|
<user-table v-if="currentTable === 'user'" />
|
||||||
<auth-table v-if="currentTable === 'auth'" />
|
<auth-table v-if="currentTable === 'auth'" />
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue