feat(文件管理): 文件管理部分接口&部分组件调整&无权限登录无限重定向问题解决
This commit is contained in:
parent
1514ab80db
commit
eb9e4253e7
|
@ -129,11 +129,11 @@
|
||||||
// 当前查看的是否是总数据的第一条数据,用当前查看数据的下标是否等于0,且当前页码是否等于1
|
// 当前查看的是否是总数据的第一条数据,用当前查看数据的下标是否等于0,且当前页码是否等于1
|
||||||
const activeDetailIsFirst = computed(() => activeDetailIndex.value === 0 && props.pagination?.current === 1);
|
const activeDetailIsFirst = computed(() => activeDetailIndex.value === 0 && props.pagination?.current === 1);
|
||||||
const activeDetailIsLast = computed(
|
const activeDetailIsLast = computed(
|
||||||
// 当前查看的是否是总数据的最后一条数据,用当前页码*每页条数+当前查看的条数下标,是否等于总条数
|
// 当前查看的是否是总数据的最后一条数据,用(当前页码-1)*每页条数+当前查看的条数下标,是否等于总条数
|
||||||
() =>
|
() =>
|
||||||
activeDetailIndex.value === props.tableData.length - 1 &&
|
activeDetailIndex.value === props.tableData.length - 1 &&
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
props.pagination!.current * props.pagination!.pageSize + activeDetailIndex.value >=
|
(props.pagination!.current - 1) * props.pagination!.pageSize + (activeDetailIndex.value + 1) >=
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
props.pagination!.total
|
props.pagination!.total
|
||||||
);
|
);
|
||||||
|
@ -158,6 +158,7 @@
|
||||||
activeDetailId.value = props.tableData[activeDetailIndex.value - 1].id;
|
activeDetailId.value = props.tableData[activeDetailIndex.value - 1].id;
|
||||||
activeDetailIndex.value -= 1;
|
activeDetailIndex.value -= 1;
|
||||||
}
|
}
|
||||||
|
initDetail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,13 +182,16 @@
|
||||||
activeDetailId.value = props.tableData[activeDetailIndex.value + 1].id;
|
activeDetailId.value = props.tableData[activeDetailIndex.value + 1].id;
|
||||||
activeDetailIndex.value += 1;
|
activeDetailIndex.value += 1;
|
||||||
}
|
}
|
||||||
|
initDetail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => activeDetailId.value,
|
() => innerVisible.value,
|
||||||
() => {
|
(val) => {
|
||||||
initDetail();
|
if (val) {
|
||||||
|
initDetail();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="`ms-button ms-button-${props.type} ms-button--${props.status} ${
|
:class="`ms-button ms-button-${props.type} ms-button--${props.status} ${
|
||||||
props.disabled ? 'ms-button--disabled' : ''
|
props.disabled || props.loading ? 'ms-button--disabled' : ''
|
||||||
}`"
|
}`"
|
||||||
@click="clickHandler"
|
@click="clickHandler"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
|
<icon-loading v-if="props.loading" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
type?: 'text' | 'icon' | 'button';
|
type?: 'text' | 'icon' | 'button';
|
||||||
status?: 'primary' | 'danger' | 'secondary';
|
status?: 'primary' | 'danger' | 'secondary';
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
loading?: boolean;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
|
|
@ -22,11 +22,13 @@
|
||||||
<slot name="item-value" :item="item">
|
<slot name="item-value" :item="item">
|
||||||
<template v-if="item.isTag">
|
<template v-if="item.isTag">
|
||||||
<MsTag
|
<MsTag
|
||||||
v-for="tag of item.value"
|
v-for="tag of Array.isArray(item.value) ? item.value : [item.value]"
|
||||||
:key="`${tag}`"
|
:key="`${tag}`"
|
||||||
theme="outline"
|
theme="outline"
|
||||||
color="var(--color-text-n8)"
|
color="var(--color-text-n8)"
|
||||||
class="mb-[8px] mr-[8px] font-normal !text-[var(--color-text-1)]"
|
class="mb-[8px] mr-[8px] font-normal !text-[var(--color-text-1)]"
|
||||||
|
:closable="item.closable"
|
||||||
|
@close="emit('tagClose', tag, item)"
|
||||||
>
|
>
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</MsTag>
|
</MsTag>
|
||||||
|
@ -106,6 +108,7 @@
|
||||||
value: (string | number) | (string | number)[];
|
value: (string | number) | (string | number)[];
|
||||||
key?: string;
|
key?: string;
|
||||||
isTag?: boolean; // 是否标签
|
isTag?: boolean; // 是否标签
|
||||||
|
closable?: boolean; // 标签是否可关闭
|
||||||
showTagAdd?: boolean; // 是否显示添加标签
|
showTagAdd?: boolean; // 是否显示添加标签
|
||||||
isButton?: boolean;
|
isButton?: boolean;
|
||||||
showCopy?: boolean;
|
showCopy?: boolean;
|
||||||
|
@ -120,7 +123,7 @@
|
||||||
column?: number;
|
column?: number;
|
||||||
descriptions: Description[];
|
descriptions: Description[];
|
||||||
labelWidth?: string;
|
labelWidth?: string;
|
||||||
addTagFunc?: (val: string) => Promise<void>;
|
addTagFunc?: (val: string, item: Description) => Promise<void>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
column: 1,
|
column: 1,
|
||||||
|
@ -128,6 +131,7 @@
|
||||||
);
|
);
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'addTag', val: string): void;
|
(e: 'addTag', val: string): void;
|
||||||
|
(e: 'tagClose', tag: string | number, item: Description): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -163,6 +167,10 @@
|
||||||
* @param item 当前标签项
|
* @param item 当前标签项
|
||||||
*/
|
*/
|
||||||
async function handleAddTag(item: Description) {
|
async function handleAddTag(item: Description) {
|
||||||
|
if (addTagInput.value.trim() === '') {
|
||||||
|
showTagInput.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Array.isArray(item.value) && item.value.includes(addTagInput.value)) {
|
if (Array.isArray(item.value) && item.value.includes(addTagInput.value)) {
|
||||||
tagInputError.value = t('ms.description.addTagRepeat');
|
tagInputError.value = t('ms.description.addTagRepeat');
|
||||||
return;
|
return;
|
||||||
|
@ -171,7 +179,7 @@
|
||||||
try {
|
try {
|
||||||
tagInputLoading.value = true;
|
tagInputLoading.value = true;
|
||||||
if (props.addTagFunc && typeof props.addTagFunc === 'function') {
|
if (props.addTagFunc && typeof props.addTagFunc === 'function') {
|
||||||
await props.addTagFunc(addTagInput.value);
|
await props.addTagFunc(addTagInput.value, item);
|
||||||
if (Array.isArray(item.value)) {
|
if (Array.isArray(item.value)) {
|
||||||
item.value.push(addTagInput.value);
|
item.value.push(addTagInput.value);
|
||||||
} else {
|
} else {
|
||||||
|
@ -180,6 +188,7 @@
|
||||||
} else {
|
} else {
|
||||||
emit('addTag', addTagInput.value);
|
emit('addTag', addTagInput.value);
|
||||||
}
|
}
|
||||||
|
addTagInput.value = '';
|
||||||
showTagInput.value = false;
|
showTagInput.value = false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|
|
@ -3,17 +3,18 @@
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
:type="props.type"
|
:type="props.type"
|
||||||
defer
|
defer
|
||||||
|
:size="props.size"
|
||||||
:style="{
|
:style="{
|
||||||
...typeStyle,
|
...typeStyle,
|
||||||
'margin-right': tagMargin,
|
'margin-right': tagMargin,
|
||||||
'min-width': props.width && `${props.width}ch`,
|
'min-width': props.width && `${props.width}ch`,
|
||||||
'max-width: 144px': !props.width,
|
'max-width': '144px',
|
||||||
}"
|
}"
|
||||||
:size="props.size"
|
|
||||||
class="inline-block"
|
|
||||||
>
|
>
|
||||||
<slot name="icon"></slot>
|
<slot name="icon"></slot>
|
||||||
<slot></slot>
|
<div class="one-line-text">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ export interface FileDetail extends FileItem {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
moduleName: string; // 所属模块名
|
moduleName: string; // 所属模块名
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
|
storage?: string; // 存储方式
|
||||||
createUser: string;
|
createUser: string;
|
||||||
createTime: number;
|
createTime: number;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,7 @@ export interface UploadFileParams {
|
||||||
export interface UpdateFileParams {
|
export interface UpdateFileParams {
|
||||||
id: string;
|
id: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
tags?: string[];
|
tags?: (string | number)[];
|
||||||
description?: string;
|
description?: string;
|
||||||
moduleId?: string;
|
moduleId?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ function setupPageGuard(router: Router) {
|
||||||
}
|
}
|
||||||
switch (getRouteLevelByKey(to.name as PathMapRoute)) {
|
switch (getRouteLevelByKey(to.name as PathMapRoute)) {
|
||||||
case MENU_LEVEL[1]: // 组织级别的页面,需要给页面携带上组织 ID
|
case MENU_LEVEL[1]: // 组织级别的页面,需要给页面携带上组织 ID
|
||||||
if (!urlOrgId) {
|
if (urlOrgId === undefined) {
|
||||||
to.query = {
|
to.query = {
|
||||||
...to.query,
|
...to.query,
|
||||||
organizationId: appStore.currentOrgId,
|
organizationId: appStore.currentOrgId,
|
||||||
|
@ -38,7 +38,7 @@ function setupPageGuard(router: Router) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MENU_LEVEL[2]: // 项目级别的页面,需要给页面携带上组织 ID和项目 ID
|
case MENU_LEVEL[2]: // 项目级别的页面,需要给页面携带上组织 ID和项目 ID
|
||||||
if (!urlOrgId && !urlProjectId) {
|
if (urlOrgId === undefined && urlProjectId === undefined) {
|
||||||
to.query = {
|
to.query = {
|
||||||
...to.query,
|
...to.query,
|
||||||
organizationId: appStore.currentOrgId,
|
organizationId: appStore.currentOrgId,
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<template #titleRight="{ loading, detail }">
|
<template #titleRight="{ loading, detail }">
|
||||||
<a-switch
|
<a-switch
|
||||||
v-if="fileType === 'jar'"
|
v-if="fileType === 'jar'"
|
||||||
:default-checked="detail?.enable"
|
v-model:model-value="detail.enable"
|
||||||
:before-change="handleEnableIntercept"
|
:before-change="handleEnableIntercept"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -27,7 +27,8 @@
|
||||||
status="secondary"
|
status="secondary"
|
||||||
class="!rounded-[var(--border-radius-small)] !text-[var(--color-text-1)]"
|
class="!rounded-[var(--border-radius-small)] !text-[var(--color-text-1)]"
|
||||||
:disabled="loading"
|
:disabled="loading"
|
||||||
@click="handleDownload"
|
:loading="downLoading"
|
||||||
|
@click="handleDownload(detail)"
|
||||||
>
|
>
|
||||||
<MsIcon type="icon-icon_bottom-align_outlined" class="mr-[4px]" />
|
<MsIcon type="icon-icon_bottom-align_outlined" class="mr-[4px]" />
|
||||||
{{ t('project.fileManagement.download') }}
|
{{ t('project.fileManagement.download') }}
|
||||||
|
@ -71,6 +72,7 @@
|
||||||
:descriptions="fileDescriptions"
|
:descriptions="fileDescriptions"
|
||||||
:label-width="currentLocale === 'zh-CN' ? '80px' : '100px'"
|
:label-width="currentLocale === 'zh-CN' ? '80px' : '100px'"
|
||||||
:add-tag-func="addFileTag"
|
:add-tag-func="addFileTag"
|
||||||
|
@tag-close="handleFileTagClose"
|
||||||
>
|
>
|
||||||
<template #value="{ item }">
|
<template #value="{ item }">
|
||||||
<div class="flex flex-wrap items-center">
|
<div class="flex flex-wrap items-center">
|
||||||
|
@ -197,13 +199,20 @@
|
||||||
import MsThumbnailCard from '@/components/business/ms-thumbnail-card/index.vue';
|
import MsThumbnailCard from '@/components/business/ms-thumbnail-card/index.vue';
|
||||||
import popConfirm from './popConfirm.vue';
|
import popConfirm from './popConfirm.vue';
|
||||||
|
|
||||||
import { getFileDetail, reuploadFile, updateFile } from '@/api/modules/project-management/fileManagement';
|
import {
|
||||||
|
downloadFile,
|
||||||
|
getFileDetail,
|
||||||
|
reuploadFile,
|
||||||
|
toggleJarFileStatus,
|
||||||
|
updateFile,
|
||||||
|
} from '@/api/modules/project-management/fileManagement';
|
||||||
import { CompressImgUrl, OriginImgUrl } from '@/api/requrls/project-management/fileManagement';
|
import { CompressImgUrl, OriginImgUrl } from '@/api/requrls/project-management/fileManagement';
|
||||||
import { useI18n } from '@/hooks/useI18n';
|
import { useI18n } from '@/hooks/useI18n';
|
||||||
import useLocale from '@/locale/useLocale';
|
import useLocale from '@/locale/useLocale';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import { downloadUrlFile, formatFileSize } from '@/utils';
|
import { downloadByteFile, downloadUrlFile, formatFileSize } from '@/utils';
|
||||||
|
|
||||||
|
import { FileDetail } from '@/models/projectManagement/file';
|
||||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -241,22 +250,38 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
async function handleEnableIntercept(newValue: string | number | boolean) {
|
async function handleEnableIntercept(newValue: string | number | boolean) {
|
||||||
await new Promise((resolve) => {
|
try {
|
||||||
setTimeout(() => {
|
await toggleJarFileStatus(props.fileId, newValue as boolean);
|
||||||
resolve(true);
|
return true;
|
||||||
}, 1000);
|
} catch (error) {
|
||||||
});
|
// eslint-disable-next-line no-console
|
||||||
return true;
|
console.log(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDownload(detail: any) {
|
const downLoading = ref(false);
|
||||||
downloadUrlFile(detail.url, detail.name);
|
/**
|
||||||
|
* 下载单个文件
|
||||||
|
* @param record 表格数据项
|
||||||
|
*/
|
||||||
|
async function handleDownload(detail: FileDetail) {
|
||||||
|
try {
|
||||||
|
downLoading.value = true;
|
||||||
|
const res = await downloadFile(detail.id);
|
||||||
|
downloadByteFile(res, `${detail.name}.${detail.fileType}`);
|
||||||
|
} catch (error) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
downLoading.value = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileType = ref('unknown');
|
const fileType = ref('unknown');
|
||||||
const renameTitle = ref(''); // 重命名的文件名称
|
const renameTitle = ref(''); // 重命名的文件名称
|
||||||
|
|
||||||
function loadedFile(detail: any) {
|
function loadedFile(detail: FileDetail) {
|
||||||
if (detail.fileType) {
|
if (detail.fileType) {
|
||||||
fileType.value = getFileEnum(`/${detail.fileType.toLowerCase()}`);
|
fileType.value = getFileEnum(`/${detail.fileType.toLowerCase()}`);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +294,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('project.fileManagement.desc'),
|
label: t('project.fileManagement.desc'),
|
||||||
value: detail.desc,
|
value: detail.description,
|
||||||
key: 'desc',
|
key: 'desc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -291,9 +316,10 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: t('project.fileManagement.tag'),
|
label: t('project.fileManagement.tag'),
|
||||||
value: detail.tag,
|
value: detail.tags,
|
||||||
isTag: true,
|
isTag: true,
|
||||||
showTagAdd: true,
|
showTagAdd: true,
|
||||||
|
closable: true,
|
||||||
key: 'tag',
|
key: 'tag',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -306,18 +332,18 @@
|
||||||
3,
|
3,
|
||||||
0,
|
0,
|
||||||
...[
|
...[
|
||||||
{
|
// {
|
||||||
label: t('project.fileManagement.gitBranch'),
|
// label: t('project.fileManagement.gitBranch'),
|
||||||
value: detail.gitBranch,
|
// value: detail.gitBranch,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: t('project.fileManagement.gitPath'),
|
// label: t('project.fileManagement.gitPath'),
|
||||||
value: detail.gitPath,
|
// value: detail.gitPath,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: t('project.fileManagement.gitVersion'),
|
// label: t('project.fileManagement.gitVersion'),
|
||||||
value: detail.gitVersion,
|
// value: detail.gitVersion,
|
||||||
},
|
// },
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -359,10 +385,17 @@
|
||||||
|
|
||||||
const previewVisible = ref(false);
|
const previewVisible = ref(false);
|
||||||
|
|
||||||
async function addFileTag(val: string) {
|
async function addFileTag(val: string, item: Description) {
|
||||||
await updateFile({
|
await updateFile({
|
||||||
id: props.fileId,
|
id: props.fileId,
|
||||||
tags: [val],
|
tags: Array.isArray(item.value) ? [...item.value, val] : [item.value, val],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleFileTagClose(tag: string | number, item: Description) {
|
||||||
|
await updateFile({
|
||||||
|
id: props.fileId,
|
||||||
|
tags: Array.isArray(item.value) ? item.value.filter((e) => e !== tag) : [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -466,12 +466,21 @@
|
||||||
];
|
];
|
||||||
const tableStore = useTableStore();
|
const tableStore = useTableStore();
|
||||||
tableStore.initColumn(TableKeyEnum.FILE_MANAGEMENT_FILE, columns, 'drawer');
|
tableStore.initColumn(TableKeyEnum.FILE_MANAGEMENT_FILE, columns, 'drawer');
|
||||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getFileList, {
|
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(
|
||||||
tableKey: TableKeyEnum.FILE_MANAGEMENT_FILE,
|
getFileList,
|
||||||
showSetting: true,
|
{
|
||||||
selectable: true,
|
tableKey: TableKeyEnum.FILE_MANAGEMENT_FILE,
|
||||||
showSelectAll: true,
|
showSetting: true,
|
||||||
});
|
selectable: true,
|
||||||
|
showSelectAll: true,
|
||||||
|
},
|
||||||
|
(item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
tags: item.tags?.map((e: string) => ({ id: e, name: e })) || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
const moduleFileBatchActions = {
|
const moduleFileBatchActions = {
|
||||||
baseAction: [
|
baseAction: [
|
||||||
{
|
{
|
||||||
|
@ -653,7 +662,7 @@
|
||||||
try {
|
try {
|
||||||
batchMoveFileLoading.value = true;
|
batchMoveFileLoading.value = true;
|
||||||
await batchMoveFile({
|
await batchMoveFile({
|
||||||
selectIds: batchParams.value?.selectedIds || [activeFile.value?.id || ''],
|
selectIds: isBatchMove.value ? batchParams.value?.selectedIds || [] : [activeFile.value?.id || ''],
|
||||||
selectAll: !!batchParams.value?.selectAll,
|
selectAll: !!batchParams.value?.selectAll,
|
||||||
excludeIds: batchParams.value?.excludeIds || [],
|
excludeIds: batchParams.value?.excludeIds || [],
|
||||||
condition: { keyword: keyword.value, comebine: combine.value },
|
condition: { keyword: keyword.value, comebine: combine.value },
|
||||||
|
@ -834,6 +843,15 @@
|
||||||
activeFileIndex.value = index;
|
activeFileIndex.value = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => showDetailDrawer.value,
|
||||||
|
(val) => {
|
||||||
|
if (!val) {
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const uploadDrawerVisible = ref(false); // 模块-上传文件抽屉
|
const uploadDrawerVisible = ref(false); // 模块-上传文件抽屉
|
||||||
const fileList = ref<MsFileItem[]>(asyncTaskStore.uploadFileTask.fileList);
|
const fileList = ref<MsFileItem[]>(asyncTaskStore.uploadFileTask.fileList);
|
||||||
// 是否非上传中状态
|
// 是否非上传中状态
|
||||||
|
|
Loading…
Reference in New Issue