fix(全局): 问题修复

This commit is contained in:
baiqi 2024-02-04 15:21:16 +08:00 committed by Craftsman
parent 830f4e4725
commit b2210479d8
26 changed files with 162 additions and 83 deletions

View File

@ -77,12 +77,12 @@
//
try {
const res = await getProjectInfo(appStore.currentProjectId);
if (res.deleted || !res.enable) {
if (res && (res.deleted || !res.enable)) {
//
router.push(NO_PROJECT_ROUTE_NAME);
return;
}
appStore.setCurrentMenuConfig(res.moduleIds);
appStore.setCurrentMenuConfig(res?.moduleIds || []);
} catch (err) {
appStore.setCurrentMenuConfig([]);
// eslint-disable-next-line no-console

View File

@ -24,7 +24,9 @@
<a-spin :loading="bottomLoading"></a-spin>
</div>
</div>
<a-empty v-if="isShow" :description="t('common.noData')" class="h-[200px] justify-center" />
<slot v-if="isShow" name="empty">
<a-empty :description="t('common.noData')" class="h-[200px] justify-center" />
</slot>
</div>
</template>

View File

@ -100,6 +100,13 @@
</template> -->
</MsAdvanceFilter>
<ms-base-table v-bind="propsRes" no-disable class="mt-[16px]" v-on="propsEvent">
<template #num="{ record }">
<a-tooltip :content="`${record.num}`">
<a-button type="text" class="px-0" @click="openDetail(record.id)">
<div class="one-line-text max-w-[168px]">{{ record.num }}</div>
</a-button>
</a-tooltip>
</template>
<template #caseLevel="{ record }">
<caseLevel :case-level="getCaseLevel(record)" />
</template>
@ -131,6 +138,7 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import { useVModel } from '@vueuse/core';
import { CustomTypeMaps, MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
@ -153,10 +161,12 @@
import type { CaseManagementTable } from '@/models/caseManagement/featureCase';
import type { CommonList, TableQueryParams } from '@/models/common';
import { ModuleTreeNode } from '@/models/projectManagement/file';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
import type { CaseLevel } from './types';
import { initGetModuleCountFunc, type RequestModuleEnum } from './utils';
const router = useRouter();
const appStore = useAppStore();
const { t } = useI18n();
@ -310,7 +320,8 @@
const columns: MsTableColumn = [
{
title: 'ID',
dataIndex: 'id',
dataIndex: 'num',
slotName: 'num',
sortIndex: 1,
showTooltip: true,
sortable: {
@ -347,8 +358,7 @@
},
{
title: 'caseManagement.featureCase.tableColumnCreateUser',
slotName: 'createUser',
dataIndex: 'createUser',
dataIndex: 'createUserName',
showInTable: true,
width: 300,
},
@ -554,6 +564,14 @@
return (record.customFields.find((item: any) => item.name === '用例等级')?.value as CaseLevel) || 'P1';
}
function openDetail(id: string) {
window.open(
`${window.location.origin}#${
router.resolve({ name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_DETAIL }).fullPath
}?id=${id}`
);
}
function cancel() {
innerVisible.value = false;
keyword.value = '';

View File

@ -267,7 +267,7 @@
/>
<a-divider margin="4px" />
<a-spin class="flex w-full" loading={orgListLoading.value}>
{orgList.value.length === 0 && orgKeyword.value !== '' ? (
{orgList.value.length === 0 ? (
<a-empty>{t('common.noData')}</a-empty>
) : (
<div class="switch-org-dropdown-list">
@ -387,25 +387,25 @@
const renderMenuItem = (element, icon) =>
element?.name === SettingRouteEnum.SETTING_ORGANIZATION ? (
orgTrigger(element, menuSwitchOrgVisible, () => (
<a-menu-item
key={element?.name}
v-slots={{ icon }}
onClick={() => goto(element)}
onMouseenter={() => {
if (xPack.value) {
// xpack
mouseEnterTimer = setTimeout(() => {
menuSwitchOrgVisible.value = true;
}, 500);
}
}}
onMouseleave={() => {
clearTimeout(mouseEnterTimer);
}}
>
<a-menu-item key={element?.name} v-slots={{ icon }} onClick={() => goto(element)}>
<div class="inline-flex w-[calc(100%-34px)] items-center justify-between !bg-transparent">
{t(element?.meta?.locale || '')}
<MsIcon type="icon-icon_switch_outlined1" class="text-[var(--color-text-4)]" />
<div
class="!bg-transparent"
onMouseenter={() => {
if (xPack.value) {
// xpack
mouseEnterTimer = setTimeout(() => {
menuSwitchOrgVisible.value = true;
}, 500);
}
}}
onMouseleave={() => {
clearTimeout(mouseEnterTimer);
}}
>
<MsIcon type="icon-icon_switch_outlined1" class="text-[var(--color-text-4)]" />
</div>
</div>
</a-menu-item>
))

View File

@ -448,7 +448,7 @@ export default defineComponent(
<a-select
ref={selectRef}
class="ms-select"
default-value={innerValue.value}
model-value={innerValue.value}
input-value={inputValue.value}
popup-visible={popupVisible.value}
placeholder={t(props.placeholder || '')}

View File

@ -83,21 +83,19 @@
}
const filterMenuTopRouter =
currentParent?.children
?.filter((item: any) => permission.accessRouter(item) && item.meta?.isTopMenu)
.filter((item: any) => {
currentParent?.children?.filter((item: any) => {
if (permission.accessRouter(item) && item.meta?.isTopMenu) {
if (item.name === RouteEnum.SETTING_SYSTEM_AUTHORIZED_MANAGEMENT) {
return appStore.packageType === 'enterprise';
}
return true;
}) || [];
}
return false;
}) || [];
appStore.setTopMenus(filterMenuTopRouter);
if (!newRoute.meta.isTopMenu) {
setCurrentTopMenu(filterMenuTopRouter[0].name as string);
} else {
setCurrentTopMenu(name as string);
}
setCurrentTopMenu(name as string);
return;
}
}

View File

@ -131,6 +131,7 @@
class="w-full"
show-time
format="YYYY-MM-DD HH:mm"
:separator="t('common.to')"
:disabled="!item.dataIndex"
/>
<MsCascader

View File

@ -235,7 +235,7 @@
@apply relative;
}
.ms-card-footer {
@apply fixed justify-between bg-white;
@apply fixed flex justify-between bg-white;
right: 16px;
bottom: 0;

View File

@ -5,6 +5,7 @@
:placeholder="t('ms.passwordInput.passwordPlaceholder')"
allow-clear
autocomplete="new-password"
:max-length="32"
@input="validatePsw"
@clear="validatePsw(innerPsw)"
/>

View File

@ -186,7 +186,7 @@
<template #empty>
<div class="w-full">
<slot name="empty">
<div class="flex h-[20px] flex-col items-center justify-center">
<div class="flex h-[40px] flex-col items-center justify-center">
<span class="text-[14px] text-[var(--color-text-4)]">{{ t('msTable.empty') }}</span>
</div>
</slot>
@ -676,4 +676,12 @@
color: var(--color-text-brand);
}
}
:deep(.arco-table-col-sorted) {
@apply bg-white;
}
:deep(.arco-table-cell-with-sorter) {
&:hover {
@apply bg-white;
}
}
</style>

View File

@ -10,7 +10,7 @@ export enum UploadAcceptEnum {
csv = '.csv',
zip = '.zip',
xmind = '.xmind',
image = '.jpg,.jpeg,.png,.svg,.webp,.gif,.bmp',
image = '.jpg,.jpeg,.png,.svg,.webp,.gif,.bmp,.ico',
jar = '.jar',
sketch = '.sketch',
none = 'none',

View File

@ -114,4 +114,5 @@ export default {
'common.importSuccess': 'Import successful',
'common.nameIsTooLang': 'The name exceeds 255 characters',
'common.validateSuccess': 'Validate success',
'common.to': 'To',
};

View File

@ -117,4 +117,5 @@ export default {
'common.importSuccess': '导入成功',
'common.nameIsTooLang': '名称超过255个字符',
'common.validateSuccess': '验证成功',
'common.to': '至',
};

View File

@ -113,6 +113,7 @@ export interface BatchReviewCaseParams extends BatchApiParams {
status: ReviewResult; // 评审结果
content: string; // 评论内容
notifier: string; // 评论@的人的Id, 多个以';'隔开
moduleIds: (string | number)[];
}
// 评审详情-批量修改评审人
export interface BatchChangeReviewerParams extends BatchApiParams {
@ -120,11 +121,13 @@ export interface BatchChangeReviewerParams extends BatchApiParams {
userId: string; // 用户id, 用来判断是否只看我的
reviewerId: string[]; // 评审人员id
append: boolean; // 是否追加
moduleIds: (string | number)[];
}
// 评审详情-批量取消关联用例
export interface BatchCancelReviewCaseParams extends BatchApiParams {
reviewId: string; // 评审id
userId: string; // 用户id, 用来判断是否只看我的
moduleIds: (string | number)[];
}
export interface ReviewDetailReviewersItem {
avatar: string;

View File

@ -11,7 +11,7 @@
@submit="confirmInvite"
>
<a-form-item field="name" class="hidden-item">
<a-input v-model="form.name" :placeholder="t('invite.namePlaceholder')" allow-clear />
<a-input v-model="form.name" :placeholder="t('invite.namePlaceholder')" :max-length="255" allow-clear />
</a-form-item>
<a-form-item field="password" class="hidden-item">
<MsPasswordInput v-model:password="form.password" />
@ -21,6 +21,7 @@
v-model="form.rePassword"
:placeholder="t('invite.repasswordPlaceholder')"
autocomplete="new-password"
:max-length="32"
allow-clear
/>
</a-form-item>

View File

@ -274,7 +274,7 @@
import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
import useFeatureCaseStore from '@/store/modules/case/featureCase';
import { downloadByteFile, getGenerateId, mapTree } from '@/utils';
import { downloadByteFile, getGenerateId } from '@/utils';
import type {
AssociatedList,
@ -285,7 +285,6 @@
} from '@/models/caseManagement/featureCase';
import type { TableQueryParams } from '@/models/common';
import { ModuleTreeNode } from '@/models/projectManagement/file';
import type { CustomField, DefinedFieldItem } from '@/models/setting/template';
import { convertToFile } from './utils';

View File

@ -99,13 +99,13 @@
<div class="case-detail-value">
<caseLevel :case-level="caseDetailLevel" />
</div>
<div class="case-detail-label">
<!-- <div class="case-detail-label">
{{ t('caseManagement.caseReview.caseVersion') }}
</div>
<div class="case-detail-value">
<MsIcon type="icon-icon_version" size="13" class="mr-[4px]" />
{{ caseDetail.versionName }}
</div>
</div> -->
<div class="case-detail-label">
{{ t('caseManagement.caseReview.reviewResult') }}
</div>
@ -254,6 +254,7 @@
* @description 功能测试-用例评审-用例详情
*/
import { useRoute, useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue';
import dayjs from 'dayjs';
import MSAvatar from '@/components/pure/ms-avatar/index.vue';
@ -275,7 +276,7 @@
getReviewDetail,
getReviewDetailCasePage,
} from '@/api/modules/case-management/caseReview';
import { getCaseDetail } from '@/api/modules/case-management/featureCase';
import { getCaseDetail, updateCaseRequest } from '@/api/modules/case-management/featureCase';
import { reviewDefaultDetail, reviewResultMap } from '@/config/caseManagement';
import { useI18n } from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
@ -501,9 +502,9 @@
function goCaseDetail() {
window.open(
`${window.location.origin}#${router.resolve({ name: CaseManagementRouteEnum.CASE_MANAGEMENT }).fullPath}?id=${
activeCaseId.value
}`
`${window.location.origin}#${
router.resolve({ name: CaseManagementRouteEnum.CASE_MANAGEMENT_CASE_DETAIL }).fullPath
}?id=${activeCaseId.value}`
);
}
@ -539,7 +540,11 @@
async function updateCase() {
try {
updateCaseLoading.value = true;
// await updateCaseRequest();
await updateCaseRequest(editCaseForm.value);
editCaseVisible.value = false;
Message.success(t('caseManagement.featureCase.editSuccess'));
loadCaseList();
loadCaseDetail();
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);

View File

@ -92,6 +92,7 @@
visible: boolean;
project: string;
reviewId?: string;
reviewers?: string[];
}>();
const emit = defineEmits<{
(e: 'update:visible', val: boolean): void;
@ -109,7 +110,7 @@
const innerProject = useVModel(props, 'project', emit);
const associateForm = ref({
reviewers: [] as string[],
reviewers: props.reviewers || ([] as string[]),
});
const associateFormRef = ref<FormInstance>();
@ -129,6 +130,7 @@
reviewerLoading.value = true;
const res = await getReviewUsers(appStore.currentProjectId, '');
reviewersOptions.value = res.map((e) => ({ label: e.name, value: e.id }));
associateForm.value.reviewers = props.reviewers || [];
} catch (error) {
// eslint-disable-next-line no-console
console.log(error);

View File

@ -543,6 +543,7 @@
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value.excludeIds,
condition: batchParams.value.condition,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
});
Message.success(t('common.updateSuccess'));
resetSelector();
@ -569,11 +570,12 @@
reviewPassRule: props.reviewPassRule,
status: 'RE_REVIEWED',
content: dialogForm.value.reason,
notifier: '', // TODO:
notifier: dialogForm.value.commentIds.join(';'),
selectIds: batchParams.value.selectIds,
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value.excludeIds,
condition: batchParams.value.condition,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
});
Message.success(t('common.updateSuccess'));
dialogVisible.value = false;
@ -603,6 +605,7 @@
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value.excludeIds,
condition: batchParams.value.condition,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
});
Message.success(t('common.updateSuccess'));
dialogVisible.value = false;
@ -635,6 +638,7 @@
selectAll: batchParams.value.selectAll,
excludeIds: batchParams.value.excludeIds,
condition: batchParams.value.condition,
moduleIds: props.activeFolder === 'all' ? [] : [props.activeFolder, ...props.offspringIds],
});
Message.success(t('caseManagement.caseReview.reviewSuccess'));
dialogVisible.value = false;
@ -784,6 +788,7 @@
defineExpose({
searchCase,
resetSelector,
});
await tableStore.initColumn(TableKeyEnum.CASE_MANAGEMENT_REVIEW_CASE, columns, 'drawer');

View File

@ -78,7 +78,7 @@
</div>
</template>
<MsSelect
v-model:modelValue="reviewForm.reviewers"
v-model:model-value="reviewForm.reviewers"
mode="static"
:placeholder="t('caseManagement.caseReview.reviewerPlaceholder')"
:options="reviewersOptions"
@ -105,6 +105,7 @@
v-model:model-value="reviewForm.cycle"
show-time
value-format="timestamp"
:separator="t('common.to')"
:time-picker-props="{
defaultValue: ['00:00:00', '00:00:00'],
}"

View File

@ -118,6 +118,7 @@
v-model:visible="associateDrawerVisible"
v-model:project="associateDrawerProject"
:review-id="reviewId"
:reviewers="reviewDetail.reviewers.map((e) => e.userId)"
@success="writeAssociateCases"
/>
<deleteReviewModal v-model:visible="deleteModalVisible" :record="reviewDetail" @success="handleDeleteSuccess" />
@ -220,17 +221,18 @@
get: () => [activeFolderId.value],
set: (val) => val,
});
const caseTableRef = ref<InstanceType<typeof CaseTable>>();
function handleFolderNodeSelect(ids: string[], _offspringIds: string[]) {
[activeFolderId.value] = ids;
offspringIds.value = [..._offspringIds];
caseTableRef.value?.resetSelector();
}
function initModulesCount(params: ReviewDetailCaseListQueryParams) {
getModuleCount(params);
}
const caseTableRef = ref<InstanceType<typeof CaseTable>>();
const associateDrawerVisible = ref(false);
const associateDrawerProject = ref(appStore.currentProjectId);

View File

@ -116,7 +116,7 @@
>
<MsButton class="!mr-0 ml-[8px]">{{ t('common.rename') }}</MsButton>
</popConfirm>
<template v-if="fileType === 'image'">
<template v-if="UploadAcceptEnum.image.includes(fileType)">
<a-divider
direction="vertical"
class="mx-[8px] min-h-[12px] rounded-[var(--border-radius-small)]"
@ -251,6 +251,7 @@
import { AssociationItem, FileDetail } from '@/models/projectManagement/file';
import { CaseManagementRouteEnum } from '@/enums/routeEnum';
import { UploadAcceptEnum } from '@/enums/uploadEnum';
const props = defineProps<{
visible: boolean;

View File

@ -119,6 +119,14 @@
@action-select="handleMoreActionSelect($event, item)"
/>
</template>
<template #empty>
<div class="flex w-full items-center justify-center p-[16px] text-[var(--color-text-4)]">
{{ t('project.fileManagement.tableNoFile') }}
<MsButton class="ml-[8px]" @click="handleAddClick">
{{ t('project.fileManagement.addFile') }}
</MsButton>
</div>
</template>
</MsCardList>
</a-spin>
</div>
@ -177,7 +185,13 @@
>
<template #tabExtra>
<div v-if="acceptType === 'jar'" class="flex items-center gap-[4px]">
<a-switch size="small" :disabled="fileList.length === 0" type="line" @change="enableAllJar"></a-switch>
<a-switch
v-model:model-value="allJarIsEnable"
size="small"
:disabled="fileList.length === 0"
type="line"
@change="enableAllJar"
></a-switch>
{{ t('project.fileManagement.enableAll') }}
<a-tooltip :content="t('project.fileManagement.uploadTip')">
<MsIcon type="icon-icon-maybe_outlined" class="cursor-pointer hover:text-[rgb(var(--primary-5))]" />
@ -522,6 +536,10 @@
slotName: 'name',
dataIndex: 'name',
fixed: 'left',
sortable: {
sortDirections: ['ascend', 'descend'],
sorter: true,
},
width: 270,
},
{
@ -996,6 +1014,7 @@
);
const uploadDrawerVisible = ref(false); // -
const allJarIsEnable = ref(false);
const fileList = ref<MsFileItem[]>(asyncTaskStore.uploadFileTask.fileList);
//
const noWaitingUpload = computed(
@ -1012,6 +1031,7 @@
if (isUploading.value || acceptType.value === type) return;
acceptType.value = type;
fileList.value = [];
allJarIsEnable.value = false;
}
/**
@ -1020,13 +1040,8 @@
*/
function handleFileChange(files: MsFileItem[]) {
fileList.value = files.map((e) => {
if (e.enable !== undefined) {
return e;
}
return {
...e,
enable: false, //
};
e.enable = acceptType.value === 'jar' ? allJarIsEnable.value : false; //
return e; // e
});
}

View File

@ -28,7 +28,6 @@
</div>
<a-range-picker
v-model:model-value="time"
show-time
:time-picker-props="{
defaultValue: ['00:00:00', '00:00:00'],
}"
@ -36,8 +35,11 @@
class="filter-item"
:allow-clear="false"
:disabled-input="false"
:separator="t('common.to')"
value-format="timestamp"
show-time
@select="selectTime"
@popup-visible-change="handleRangeVisibleChange"
>
<template #prefix>
{{ t('system.log.operateTime') }}
@ -230,16 +232,19 @@
label: t('system.log.organization'),
},
label: t('system.log.organization'),
children: res.organizationList.map((e) => ({
//
value: {
level: MENU_LEVEL[1],
value: e.id,
label: `${t('system.log.organization')} / ${e.name}`,
},
label: e.name,
isLeaf: true,
})),
children:
Array.isArray(res.organizationList) && res.organizationList.length > 0
? res.organizationList.map((e) => ({
//
value: {
level: MENU_LEVEL[1],
value: e.id,
label: `${t('system.log.organization')} / ${e.name}`,
},
label: e.name,
isLeaf: true,
}))
: undefined,
});
} else if (props.mode === MENU_LEVEL[1]) {
rangeOptions.value.push({
@ -258,16 +263,19 @@
label: t('system.log.project'),
},
label: t('system.log.project'),
children: res.projectList.map((e) => ({
//
value: {
level: MENU_LEVEL[2],
value: e.id,
label: `${t('system.log.project')} / ${e.name}`,
},
label: e.name,
isLeaf: true,
})),
children:
Array.isArray(res.projectList) && res.projectList.length > 0
? res.projectList.map((e) => ({
//
value: {
level: MENU_LEVEL[2],
value: e.id,
label: `${t('system.log.project')} / ${e.name}`,
},
label: e.name,
isLeaf: true,
}))
: undefined,
});
} catch (error) {
// eslint-disable-next-line no-console
@ -313,6 +321,12 @@
}
}
function handleRangeVisibleChange(val: boolean) {
if (!val) {
selectedTime.value = '';
}
}
const moduleOptions = ref<CascaderOption[]>([]);
const moduleLocaleMap = ref<Record<string, string>>({});
const { getPathMapByLevel, jumpRouteByMapKey } = usePathMap();
@ -454,6 +468,7 @@
title: 'system.log.operateName',
dataIndex: 'content',
slotName: 'content',
showTooltip: true,
width: 150,
},
{

View File

@ -1,6 +1,6 @@
export default {
'system.log.operator': 'Operator',
'system.log.operatorPlaceholder': 'Enter username/email to search',
'system.log.operatorPlaceholder': 'Please enter username/email to search',
'system.log.operateTime': 'Operation time',
'system.log.operateRange': 'Operating range',
'system.log.operateType': 'Operation type',

View File

@ -1,6 +1,6 @@
export default {
'system.log.operator': '操作人',
'system.log.operatorPlaceholder': '输入用户名/邮箱搜索',
'system.log.operatorPlaceholder': '输入用户名/邮箱搜索',
'system.log.operateTime': '操作时间',
'system.log.operateRange': '操作范围',
'system.log.operateType': '操作类型',