feat(系统设置): 添加项目管理员必填&用户选择器替换为MsSelect
This commit is contained in:
parent
5662e5abe7
commit
ed9b95eba1
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<MsUserSelector v-bind="$attrs" v-model="memberList" class="w-[262px]" />
|
<MsUserSelector v-bind="$attrs" v-model="memberList" class="min-w-[262px]" />
|
||||||
<a-button
|
<a-button
|
||||||
type="outline"
|
type="outline"
|
||||||
:disabled="!memberList.length"
|
:disabled="!memberList.length"
|
||||||
|
@ -22,12 +22,14 @@
|
||||||
>
|
>
|
||||||
{{ t('common.confirm') }}
|
{{ t('common.confirm') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<div
|
<a-button
|
||||||
class="ml-[8px] flex h-[24px] w-[48px] cursor-pointer items-center justify-center rounded-[4px] border border-[var(--color-text-input-border)] px-[11px] text-[12px] leading-[16px] text-[var(--color-text-1)] hover:bg-[rgb(var(--primary-1))]"
|
type="outline"
|
||||||
|
size="mini"
|
||||||
|
class="ml-[12px] !border-[var(--color-text-input-border)] !text-[var(--color-text-1)]"
|
||||||
@click="handleCancel"
|
@click="handleCancel"
|
||||||
>
|
>
|
||||||
{{ t('common.cancel') }}
|
{{ t('common.cancel') }}
|
||||||
</div>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,36 +1,35 @@
|
||||||
<template>
|
<template>
|
||||||
<a-select
|
<MsSelect
|
||||||
:model-value="currentValue"
|
v-model:model-value="currentValue"
|
||||||
:placeholder="t(props.placeholder || 'common.pleaseSelectMember')"
|
mode="remote"
|
||||||
|
:options="[]"
|
||||||
|
:placeholder="props.placeholder || 'common.pleaseSelectMember'"
|
||||||
multiple
|
multiple
|
||||||
:value-key="props.valueKey"
|
:value-key="props.valueKey"
|
||||||
:disabled="props.disabled"
|
:disabled="props.disabled"
|
||||||
|
:at-least-one="props.atLeastOne"
|
||||||
|
:label-key="props.firstLabelKey"
|
||||||
:filter-option="false"
|
:filter-option="false"
|
||||||
allow-clear
|
allow-clear
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@change="change"
|
:search-keys="[props.firstLabelKey, props.secondLabelKey]"
|
||||||
@search="debouncedSearch"
|
:remote-func="loadList"
|
||||||
|
:remote-extra-params="{ ...props.loadOptionParams, type: props.type }"
|
||||||
|
:option-label-render="optionLabelRender"
|
||||||
|
:should-calculate-max-tag="false"
|
||||||
>
|
>
|
||||||
<template #label="{ data }">
|
</MsSelect>
|
||||||
<span class="text-[var(--color-text-1)]"> {{ data.value.name }} </span>
|
|
||||||
</template>
|
|
||||||
<a-option v-for="data in allOptions" :key="data.id" :disabled="data.disabled" :value="data">
|
|
||||||
<span :class="data.disabled ? 'text-[var(--color-text-4)]' : 'text-[var(--color-text-1)]'">
|
|
||||||
{{ data.name }}
|
|
||||||
</span>
|
|
||||||
<span v-if="data.email" class="text-[var(--color-text-4)]"> {{ `(${data.email})` }} </span>
|
|
||||||
</a-option>
|
|
||||||
</a-select>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { SelectOptionData } from '@arco-design/web-vue';
|
||||||
import { debounce } from 'lodash-es';
|
|
||||||
|
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import MsSelect from '@/components/business/ms-select/index';
|
||||||
|
|
||||||
import initOptionsFunc, { UserRequestTypeEnum } from './utils';
|
import initOptionsFunc, { UserRequestTypeEnum } from './utils';
|
||||||
|
|
||||||
|
defineOptions({ name: 'MsUserSelector' });
|
||||||
|
|
||||||
export interface MsUserSelectorOption {
|
export interface MsUserSelectorOption {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -41,7 +40,6 @@
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
modelValue: string[] | string; // 选中的值
|
|
||||||
disabled?: boolean; // 是否禁用
|
disabled?: boolean; // 是否禁用
|
||||||
disabledKey?: string; // 禁用的key
|
disabledKey?: string; // 禁用的key
|
||||||
valueKey?: string; // value的key
|
valueKey?: string; // value的key
|
||||||
|
@ -50,6 +48,7 @@
|
||||||
secondLabelKey?: string; // 次要的字段key
|
secondLabelKey?: string; // 次要的字段key
|
||||||
loadOptionParams?: Record<string, any>; // 加载选项的参数
|
loadOptionParams?: Record<string, any>; // 加载选项的参数
|
||||||
type?: UserRequestTypeEnum; // 加载选项的类型
|
type?: UserRequestTypeEnum; // 加载选项的类型
|
||||||
|
atLeastOne?: boolean; // 是否至少选择一个
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
@ -58,27 +57,18 @@
|
||||||
firstLabelKey: 'name',
|
firstLabelKey: 'name',
|
||||||
secondLabelKey: 'email',
|
secondLabelKey: 'email',
|
||||||
type: UserRequestTypeEnum.SYSTEM_USER_GROUP,
|
type: UserRequestTypeEnum.SYSTEM_USER_GROUP,
|
||||||
|
atLeastOne: false,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const currentValue = defineModel<string[] | string>({ default: [] });
|
||||||
(e: 'update:modelValue', value: string[]): void;
|
|
||||||
(e: 'select', value: string[]): void;
|
|
||||||
}>();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const allOptions = ref<MsUserSelectorOption[]>([]);
|
|
||||||
const currentLoadParams = ref<Record<string, any>>(props.loadOptionParams || {});
|
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|
||||||
const currentValue = computed(() => {
|
const loadList = async (params: Record<string, any>) => {
|
||||||
return allOptions.value.filter((item) => props.modelValue.includes(item.id)) || [];
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadList = async () => {
|
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const list = (await initOptionsFunc(props.type, currentLoadParams.value || {})) || [];
|
const { type, keyword, ...rest } = params;
|
||||||
|
const list = (await initOptionsFunc(type, { keyword, ...rest })) || [];
|
||||||
const { firstLabelKey, secondLabelKey, disabledKey, valueKey } = props;
|
const { firstLabelKey, secondLabelKey, disabledKey, valueKey } = props;
|
||||||
list.forEach((item: MsUserSelectorOption) => {
|
list.forEach((item: MsUserSelectorOption) => {
|
||||||
if (firstLabelKey) {
|
if (firstLabelKey) {
|
||||||
|
@ -94,55 +84,16 @@
|
||||||
item.id = item[valueKey] as string;
|
item.id = item[valueKey] as string;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
allOptions.value = [...list];
|
return list;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(error);
|
console.log(error);
|
||||||
allOptions.value = [];
|
return [];
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const optionLabelRender = (option: SelectOptionData) => {
|
||||||
const debouncedSearch = async (value: string) => {
|
return `<span class='text-[var(--color-text-1)]'>${option.name}</span><span class='text-[var(--color-text-4)] ml-[4px]'>(${option.email})</span>`;
|
||||||
if (!value) {
|
|
||||||
currentLoadParams.value = {
|
|
||||||
...currentLoadParams.value,
|
|
||||||
keyword: value,
|
|
||||||
};
|
};
|
||||||
await loadList();
|
|
||||||
} else {
|
|
||||||
const fn = debounce(
|
|
||||||
() => {
|
|
||||||
currentLoadParams.value = {
|
|
||||||
...currentLoadParams.value,
|
|
||||||
keyword: value,
|
|
||||||
};
|
|
||||||
loadList();
|
|
||||||
},
|
|
||||||
300,
|
|
||||||
{ maxWait: 1000 }
|
|
||||||
);
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const change = (
|
|
||||||
value: string | number | boolean | Record<string, any> | (string | number | boolean | Record<string, any>)[]
|
|
||||||
) => {
|
|
||||||
const tmpArr = Array.isArray(value) ? value : [value];
|
|
||||||
const { valueKey } = props;
|
|
||||||
emit(
|
|
||||||
'update:modelValue',
|
|
||||||
tmpArr.map((item) => item[valueKey])
|
|
||||||
);
|
|
||||||
emit(
|
|
||||||
'select',
|
|
||||||
tmpArr.map((item) => item[valueKey])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(async () => {
|
|
||||||
await loadList();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -194,6 +194,10 @@
|
||||||
import { convertToFileByBug } from '@/views/bug-management/utils';
|
import { convertToFileByBug } from '@/views/bug-management/utils';
|
||||||
import { convertToFile } from '@/views/case-management/caseManagementFeature/components/utils';
|
import { convertToFile } from '@/views/case-management/caseManagementFeature/components/utils';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'BugDetailTab',
|
||||||
|
});
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -408,7 +412,7 @@
|
||||||
watch(
|
watch(
|
||||||
() => fileList.value,
|
() => fileList.value,
|
||||||
async (val) => {
|
async (val) => {
|
||||||
const isNewFiles = val.filter((item) => item.status === 'init').length;
|
const isNewFiles = val.filter((item) => item.status === 'init' || (!item.local && !item.associateId)).length;
|
||||||
if (val && isNewFiles) {
|
if (val && isNewFiles) {
|
||||||
startUpload();
|
startUpload();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,20 @@
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="userIds" :label="t('system.project.projectAdmin')">
|
<a-form-item
|
||||||
|
field="userIds"
|
||||||
|
asterisk-position="end"
|
||||||
|
:rules="[{ required: true, message: t('system.project.projectAdminIsNotNull') }]"
|
||||||
|
:label="t('system.project.projectAdmin')"
|
||||||
|
>
|
||||||
<MsUserSelector
|
<MsUserSelector
|
||||||
v-model="form.userIds"
|
v-model="form.userIds"
|
||||||
:type="UserRequestTypeEnum.ORGANIZATION_PROJECT_ADMIN"
|
:type="UserRequestTypeEnum.ORGANIZATION_PROJECT_ADMIN"
|
||||||
placeholder="system.project.projectAdminPlaceholder"
|
placeholder="system.project.pleaseSelectAdmin"
|
||||||
:load-option-params="{
|
:load-option-params="{
|
||||||
organizationId: currentOrgId,
|
organizationId: currentOrgId,
|
||||||
}"
|
}"
|
||||||
|
:at-least-one="true"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="module" :label="t('system.project.moduleSetting')">
|
<a-form-item field="module" :label="t('system.project.moduleSetting')">
|
||||||
|
@ -115,7 +121,7 @@
|
||||||
|
|
||||||
import { createOrUpdateProjectByOrg, getSystemOrgOption } from '@/api/modules/setting/organizationAndProject';
|
import { createOrUpdateProjectByOrg, getSystemOrgOption } from '@/api/modules/setting/organizationAndProject';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import { useAppStore } from '@/store';
|
import { useAppStore, useUserStore } from '@/store';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
import { CreateOrUpdateSystemProjectParams, SystemOrgOption } from '@/models/setting/system/orgAndProject';
|
import { CreateOrUpdateSystemProjectParams, SystemOrgOption } from '@/models/setting/system/orgAndProject';
|
||||||
|
@ -128,7 +134,6 @@
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean;
|
|
||||||
currentProject?: CreateOrUpdateSystemProjectParams;
|
currentProject?: CreateOrUpdateSystemProjectParams;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@ -137,6 +142,7 @@
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const isEdit = computed(() => !!(props.currentProject && props.currentProject.id));
|
const isEdit = computed(() => !!(props.currentProject && props.currentProject.id));
|
||||||
const affiliatedOrgOption = ref<SystemOrgOption[]>([]);
|
const affiliatedOrgOption = ref<SystemOrgOption[]>([]);
|
||||||
|
const userStore = useUserStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const currentOrgId = computed(() => appStore.currentOrgId);
|
const currentOrgId = computed(() => appStore.currentOrgId);
|
||||||
const licenseStore = useLicenseStore();
|
const licenseStore = useLicenseStore();
|
||||||
|
@ -180,20 +186,18 @@
|
||||||
moduleIds: allModuleIds,
|
moduleIds: allModuleIds,
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
const currentVisible = defineModel<boolean>('visible', {
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
const showPool = computed(() => showPoolModuleIds.some((item) => form.moduleIds?.includes(item)));
|
const showPool = computed(() => showPoolModuleIds.some((item) => form.moduleIds?.includes(item)));
|
||||||
|
|
||||||
const isXpack = computed(() => {
|
const isXpack = computed(() => {
|
||||||
return licenseStore.hasLicense();
|
return licenseStore.hasLicense();
|
||||||
});
|
});
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
currentVisible.value = props.visible;
|
|
||||||
});
|
|
||||||
|
|
||||||
const formReset = () => {
|
const formReset = () => {
|
||||||
form.name = '';
|
form.name = '';
|
||||||
form.userIds = [];
|
form.userIds = userStore.id ? [userStore.id] : [];
|
||||||
form.organizationId = currentOrgId.value;
|
form.organizationId = currentOrgId.value;
|
||||||
form.description = '';
|
form.description = '';
|
||||||
form.enable = true;
|
form.enable = true;
|
||||||
|
@ -252,8 +256,12 @@
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (isEdit.value && props.currentProject) {
|
initAffiliatedOrgOption();
|
||||||
|
if (props.currentProject?.id) {
|
||||||
|
// 编辑
|
||||||
|
if (props.currentProject) {
|
||||||
form.id = props.currentProject.id;
|
form.id = props.currentProject.id;
|
||||||
form.name = props.currentProject.name;
|
form.name = props.currentProject.name;
|
||||||
form.description = props.currentProject.description;
|
form.description = props.currentProject.description;
|
||||||
|
@ -263,11 +271,9 @@
|
||||||
form.moduleIds = props.currentProject.moduleIds;
|
form.moduleIds = props.currentProject.moduleIds;
|
||||||
form.resourcePoolIds = props.currentProject.resourcePoolIds;
|
form.resourcePoolIds = props.currentProject.resourcePoolIds;
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
onMounted(() => {
|
// 新建
|
||||||
initAffiliatedOrgOption();
|
|
||||||
});
|
|
||||||
onUnmounted(() => {
|
|
||||||
formReset();
|
formReset();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -50,11 +50,17 @@
|
||||||
>
|
>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="userIds" :label="t('system.project.projectAdmin')">
|
<a-form-item
|
||||||
|
field="userIds"
|
||||||
|
asterisk-position="end"
|
||||||
|
:rules="[{ required: true, message: t('system.project.projectAdminIsNotNull') }]"
|
||||||
|
:label="t('system.project.projectAdmin')"
|
||||||
|
>
|
||||||
<MsUserSelector
|
<MsUserSelector
|
||||||
v-model="form.userIds"
|
v-model="form.userIds"
|
||||||
:type="UserRequestTypeEnum.SYSTEM_PROJECT_ADMIN"
|
:type="UserRequestTypeEnum.SYSTEM_PROJECT_ADMIN"
|
||||||
placeholder="system.project.projectAdminPlaceholder"
|
placeholder="system.project.pleaseSelectAdmin"
|
||||||
|
:at-least-one="true"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item field="module" :label="t('system.project.moduleSetting')">
|
<a-form-item field="module" :label="t('system.project.moduleSetting')">
|
||||||
|
@ -99,7 +105,7 @@
|
||||||
{{ t('common.cancel') }}
|
{{ t('common.cancel') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="primary" :loading="loading" @click="handleBeforeOk">
|
<a-button type="primary" :loading="loading" @click="handleBeforeOk">
|
||||||
{{ isEdit ? t('common.confirm') : t('common.create') }}
|
{{ isEdit ? t('common.update') : t('common.create') }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -119,6 +125,7 @@
|
||||||
|
|
||||||
import { createOrUpdateProject, getSystemOrgOption } from '@/api/modules/setting/organizationAndProject';
|
import { createOrUpdateProject, getSystemOrgOption } from '@/api/modules/setting/organizationAndProject';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import useLicenseStore from '@/store/modules/setting/license';
|
import useLicenseStore from '@/store/modules/setting/license';
|
||||||
|
|
||||||
|
@ -127,9 +134,9 @@
|
||||||
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
import type { FormInstance, ValidatedError } from '@arco-design/web-vue';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
visible: boolean;
|
|
||||||
currentProject?: CreateOrUpdateSystemProjectParams;
|
currentProject?: CreateOrUpdateSystemProjectParams;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
@ -183,7 +190,9 @@
|
||||||
resourcePoolIds: [],
|
resourcePoolIds: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const currentVisible = ref(props.visible);
|
const currentVisible = defineModel<boolean>('visible', {
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
const showPool = computed(() => showPoolModuleIds.some((item) => form.moduleIds?.includes(item)));
|
const showPool = computed(() => showPoolModuleIds.some((item) => form.moduleIds?.includes(item)));
|
||||||
|
|
||||||
const isXpack = computed(() => {
|
const isXpack = computed(() => {
|
||||||
|
@ -192,7 +201,7 @@
|
||||||
|
|
||||||
const formReset = () => {
|
const formReset = () => {
|
||||||
form.name = '';
|
form.name = '';
|
||||||
form.userIds = [];
|
form.userIds = userStore.id ? [userStore.id] : [];
|
||||||
form.organizationId = '';
|
form.organizationId = '';
|
||||||
form.description = '';
|
form.description = '';
|
||||||
form.enable = true;
|
form.enable = true;
|
||||||
|
@ -256,6 +265,9 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
initAffiliatedOrgOption();
|
||||||
|
if (props.currentProject?.id) {
|
||||||
|
// 编辑
|
||||||
if (props.currentProject) {
|
if (props.currentProject) {
|
||||||
form.id = props.currentProject.id;
|
form.id = props.currentProject.id;
|
||||||
form.name = props.currentProject.name;
|
form.name = props.currentProject.name;
|
||||||
|
@ -266,16 +278,9 @@
|
||||||
form.moduleIds = props.currentProject.moduleIds;
|
form.moduleIds = props.currentProject.moduleIds;
|
||||||
form.resourcePoolIds = props.currentProject.resourcePoolIds;
|
form.resourcePoolIds = props.currentProject.resourcePoolIds;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(val) => {
|
|
||||||
currentVisible.value = val;
|
|
||||||
if (!val) {
|
|
||||||
formReset();
|
|
||||||
} else {
|
} else {
|
||||||
initAffiliatedOrgOption();
|
// 新建
|
||||||
|
formReset();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -79,4 +79,6 @@ export default {
|
||||||
'system.project.searchPlaceholder': 'Search by name or id',
|
'system.project.searchPlaceholder': 'Search by name or id',
|
||||||
'system.project.afterModule':
|
'system.project.afterModule':
|
||||||
'After the module is canceled, users will be unable to access the specified module, and existing data will remain intact',
|
'After the module is canceled, users will be unable to access the specified module, and existing data will remain intact',
|
||||||
|
'system.project.projectAdminIsNotNull': 'Project administrator cannot be empty',
|
||||||
|
'system.project.pleaseSelectAdmin': 'Please select project administrator',
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,4 +75,6 @@ export default {
|
||||||
'system.project.deleteTip': '删除后,系统会在 30天 后执行删除项目 (含项目下所有业务数据),请谨慎操作!',
|
'system.project.deleteTip': '删除后,系统会在 30天 后执行删除项目 (含项目下所有业务数据),请谨慎操作!',
|
||||||
'system.project.searchPlaceholder': '通过ID或项目名称搜索',
|
'system.project.searchPlaceholder': '通过ID或项目名称搜索',
|
||||||
'system.project.afterModule': '取消模块后用户将无法进入指定模块,已存在的数据会继续保留',
|
'system.project.afterModule': '取消模块后用户将无法进入指定模块,已存在的数据会继续保留',
|
||||||
|
'system.project.projectAdminIsNotNull': '项目管理员不能为空',
|
||||||
|
'system.project.pleaseSelectAdmin': '请选择项目管理员',
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue