批量更新租户规则
This commit is contained in:
parent
108ec50978
commit
a5a02eb8c9
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -21,6 +21,7 @@ declare module 'vue' {
|
||||
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
|
||||
ElCard: typeof import('element-plus/es')['ElCard']
|
||||
ElCascader: typeof import('element-plus/es')['ElCascader']
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||
|
||||
@ -6,7 +6,7 @@ import { onMounted } from 'vue';
|
||||
const authStore = useAuthStore();
|
||||
|
||||
// 获取租户ID
|
||||
const tenantId = (authStore.user as any)?.tenant_id;
|
||||
const tenantId = (authStore.user as any)?.tid;
|
||||
|
||||
// 获取用户信息
|
||||
const userInfo = authStore.user;
|
||||
|
||||
@ -101,7 +101,7 @@ export function getEmployeeList(tenantId) {
|
||||
return request({
|
||||
url: '/admin/erp/getEmployee',
|
||||
method: 'get',
|
||||
params: { tenant_id: tenantId }
|
||||
params: { tid: tenantId }
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -144,6 +144,18 @@ export function deleteFile(id) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
* @param {number|string} id 文件ID
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function deleteFilePermanently(id) {
|
||||
return request({
|
||||
url: `/admin/deleteFilePermanently/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件
|
||||
* @param {number|string} id 文件ID
|
||||
@ -159,37 +171,41 @@ export function moveFile(id, cate) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传头像
|
||||
* @param {FormData} formData 文件数据
|
||||
* @param {Object} options 额外选项
|
||||
* @param {string} [options.cate]
|
||||
* 批量删除文件
|
||||
* @param {Array} ids 文件ID数组
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function uploadAvatar(formData, options = {}) {
|
||||
if (options.cate) {
|
||||
formData.append('cate', options.cate);
|
||||
}
|
||||
|
||||
export function batchDeleteFiles(ids) {
|
||||
return request({
|
||||
url: "/admin/uploadavatar",
|
||||
url: "/admin/batchDeleteFiles",
|
||||
method: "post",
|
||||
data: formData,
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data"
|
||||
}
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新头像
|
||||
* @param {number|string} id 文件ID
|
||||
* @param {Object} fileData 更新头像
|
||||
* 批量彻底删除文件
|
||||
* @param {Array} ids 文件ID数组
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function updateAvatar(id, fileData) {
|
||||
export function batchDeleteFilesPermanently(ids) {
|
||||
return request({
|
||||
url: `/admin/uploadavatar/${id}`,
|
||||
url: "/admin/batchDeleteFilesPermanently",
|
||||
method: "post",
|
||||
data: fileData,
|
||||
data: { ids },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量移动文件
|
||||
* @param {Array} ids 文件ID数组
|
||||
* @param {number} cate 目标分类ID
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function batchMoveFiles(ids, cate) {
|
||||
return request({
|
||||
url: "/admin/batchMoveFiles",
|
||||
method: "post",
|
||||
data: { ids, cate },
|
||||
});
|
||||
}
|
||||
@ -40,7 +40,7 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
account: userInfo.account || '',
|
||||
name: userInfo.name || '',
|
||||
group_id: userInfo.group_id || '',
|
||||
tenant_id: userInfo.tenant_id || '',
|
||||
tid: userInfo.tid || '',
|
||||
avatar: userInfo.avatar || ''
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,19 @@
|
||||
<template>
|
||||
<div class="category-manager">
|
||||
<!-- 页面头部 -->
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<h3>文章分类</h3>
|
||||
<p>共 {{ totalCount }} 个分类</p>
|
||||
</div>
|
||||
<div class="page-actions">
|
||||
<el-button type="primary" :icon="Plus" @click="handleAdd">
|
||||
新增分类
|
||||
</el-button>
|
||||
<el-button :icon="Refresh" @click="handleRefresh">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="category-list" v-loading="loading">
|
||||
<div v-if="filteredCategories.length === 0" class="empty-state">
|
||||
<el-empty description="暂无文章分类" />
|
||||
@ -55,6 +69,13 @@ const currentEdit = ref(null);
|
||||
const searchText = ref("");
|
||||
const categories = ref([]);
|
||||
|
||||
// 新增分类
|
||||
const addCategory = ref(null);
|
||||
const handleAdd = () => {
|
||||
addCategory.value = { parentId: 0 };
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
// 计算属性
|
||||
const totalCount = computed(() => categories.value.length);
|
||||
|
||||
@ -178,6 +199,8 @@ onMounted(() => {
|
||||
<style lang="less" scoped>
|
||||
.category-manager {
|
||||
min-height: 100vh;
|
||||
padding: 20px;
|
||||
background-color: var(--el-bg-color-page);
|
||||
|
||||
// 页面头部样式
|
||||
.page-header {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<div class="search-bar">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
placeholder="搜索文章标题/作者"
|
||||
placeholder="搜索文章标题"
|
||||
clearable
|
||||
@clear="handleSearch"
|
||||
>
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<template></template>
|
||||
<script setup lang="ts"></script>
|
||||
<style lang="less" scoped></style>
|
||||
@ -0,0 +1,3 @@
|
||||
<template></template>
|
||||
<script setup lang="ts"></script>
|
||||
<style lang="less" scoped></style>
|
||||
@ -79,7 +79,7 @@ const total = ref(0);
|
||||
const editRef = ref<any>(null);
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const tenantId = (authStore.user as any)?.tenant_id;
|
||||
const tenantId = (authStore.user as any)?.tid;
|
||||
|
||||
// console.log(tenantId);
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ const loading = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const isEdit = ref(false)
|
||||
const authStore = useAuthStore()
|
||||
const tenantId = (authStore.user as any)?.tenant_id
|
||||
const tenantId = (authStore.user as any)?.tid
|
||||
const leaderList = ref([])
|
||||
const formData = reactive({
|
||||
id: 0,
|
||||
@ -192,7 +192,7 @@ const handleSubmit = async () => {
|
||||
}
|
||||
})
|
||||
if (tenantId) {
|
||||
submitData.tenant_id = tenantId
|
||||
submitData.tid = tenantId
|
||||
}
|
||||
res = await editOrganization(formData.id, submitData)
|
||||
} else {
|
||||
@ -205,7 +205,7 @@ const handleSubmit = async () => {
|
||||
}
|
||||
})
|
||||
if (tenantId) {
|
||||
submitData.append('tenant_id', String(tenantId))
|
||||
submitData.append('tid', String(tenantId))
|
||||
}
|
||||
res = await createOrganization(submitData)
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ import { getOrganizationList, getOrganizationDetail, deleteOrganization } from '
|
||||
// 树形结构数据(与后台字段对应)
|
||||
interface TreeNode {
|
||||
id: number
|
||||
tenant_id?: number
|
||||
tid?: number
|
||||
org_name: string
|
||||
org_code?: string
|
||||
parent_id?: number
|
||||
@ -153,7 +153,7 @@ const buildTree = (list: any[]): TreeNode[] => {
|
||||
list.forEach(item => {
|
||||
const node: TreeNode = {
|
||||
id: item.id,
|
||||
tenant_id: item.tenant_id,
|
||||
tid: item.tid,
|
||||
org_name: item.org_name,
|
||||
org_code: item.org_code,
|
||||
parent_id: item.parent_id,
|
||||
@ -193,7 +193,7 @@ const loadOrganizationDetail = async (id: number) => {
|
||||
if (data) {
|
||||
selectedNode.value = {
|
||||
id: data.id,
|
||||
tenant_id: data.tenant_id,
|
||||
tid: data.tid,
|
||||
org_name: data.org_name,
|
||||
org_code: data.org_code,
|
||||
parent_id: data.parent_id,
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
详情
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.default !== 1 && row.default !== 2"
|
||||
v-if="userInfo?.id === 1"
|
||||
size="small"
|
||||
type="primary"
|
||||
link
|
||||
@ -66,7 +66,7 @@
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="row.id !== 1"
|
||||
v-if="userInfo?.id === 1"
|
||||
size="small"
|
||||
type="danger"
|
||||
link
|
||||
|
||||
@ -88,7 +88,7 @@ const submitForm = async () => {
|
||||
try {
|
||||
const submitData = {
|
||||
...formData,
|
||||
tenant_id: currentTenantId.value
|
||||
tid: currentTenantId.value
|
||||
};
|
||||
const res = await addUser(submitData);
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@
|
||||
const formRef = ref();
|
||||
|
||||
const formData = reactive({
|
||||
tenant_id: null,
|
||||
tid: null,
|
||||
type: '',
|
||||
file_url: '',
|
||||
expire_time: '',
|
||||
@ -89,7 +89,7 @@
|
||||
const open = (row: any) => {
|
||||
visible.value = true;
|
||||
tenantName.value = row.tenant_name;
|
||||
formData.tenant_id = row.id;
|
||||
formData.tid = row.id;
|
||||
|
||||
// 如果后端有资质详情接口,可以在此获取回显数据
|
||||
// fetchDetail(row.id);
|
||||
|
||||
@ -113,7 +113,7 @@ const fetchDomains = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 获取我的域名列表
|
||||
const res = await getMyDomains({ tid: authStore.user.tenant_id })
|
||||
const res = await getMyDomains({ tid: authStore.user.tid })
|
||||
if (res.code === 200) {
|
||||
tableData.value = res.data || []
|
||||
}
|
||||
@ -133,7 +133,7 @@ const handleSubmit = async () => {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const res = await applyTenantDomain({
|
||||
tenant_id: authStore.user.tenant_id,
|
||||
tid: authStore.user.tid,
|
||||
main_domain: form.main_domain,
|
||||
sub_domain: form.sub_domain
|
||||
})
|
||||
|
||||
@ -55,9 +55,9 @@
|
||||
<el-tag size="small">{{ row.dict_code }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="tenant_id" label="租户ID" width="100" align="center">
|
||||
<el-table-column prop="tid" label="租户ID" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.tenant_id || 0 }}</span>
|
||||
<span>{{ row.tid || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="parent_id" label="父级ID" width="100" align="center">
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
</div>
|
||||
<div class="group-count">{{ group.total }} 个文件</div>
|
||||
</div>
|
||||
<div class="group-actions" v-if="group.id !== 0 && group.id !== 999">
|
||||
<div class="group-actions" v-if="group.id !== 0">
|
||||
<div class="action-buttons" @click.stop>
|
||||
<el-button
|
||||
type="primary"
|
||||
@ -128,11 +128,46 @@
|
||||
>
|
||||
上传文件
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
:icon="FolderOpened"
|
||||
@click="handleBatchMove"
|
||||
:disabled="selectedFileIds.length === 0"
|
||||
>
|
||||
批量移动 ({{ selectedFileIds.length }})
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
@click="handleBatchDelete"
|
||||
:disabled="selectedFileIds.length === 0"
|
||||
>
|
||||
批量删除 ({{ selectedFileIds.length }})
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
@click="handleBatchDeletePermanently"
|
||||
:disabled="selectedFileIds.length === 0"
|
||||
>
|
||||
<el-icon><DeleteFilled /></el-icon>
|
||||
批量永久删除 ({{ selectedFileIds.length }})
|
||||
</el-button>
|
||||
<el-button
|
||||
type="info"
|
||||
@click="clearSelection"
|
||||
:disabled="selectedFileIds.length === 0"
|
||||
>
|
||||
取消选择
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件卡片网格 -->
|
||||
<div class="file-grid-container">
|
||||
<div class="file-grid-header" v-if="files.length > 0">
|
||||
<button class="allbtns" @click="toggleSelectAll">全选/反选</button>
|
||||
</div>
|
||||
<div
|
||||
v-loading="loading"
|
||||
class="file-grid"
|
||||
@ -142,14 +177,14 @@
|
||||
v-for="file in files"
|
||||
:key="file.id"
|
||||
shadow="hover"
|
||||
class="file-card"
|
||||
@click="handleFileClick(file)"
|
||||
:class="['file-card', { 'file-card-selected': selectedFileIds.includes(file.id) }]"
|
||||
@click="toggleFileSelection(file)"
|
||||
>
|
||||
<div class="file-checkbox">
|
||||
<el-checkbox :model-value="selectedFileIds.includes(file.id)" />
|
||||
</div>
|
||||
<div class="file-icon">
|
||||
<div
|
||||
v-if="isImage(file)"
|
||||
@click.stop="handleImagePreview(file)"
|
||||
>
|
||||
<div v-if="isImage(file)">
|
||||
<img
|
||||
:src="getFileUrl(file.url)"
|
||||
alt="file"
|
||||
@ -179,27 +214,46 @@
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="file-actions">
|
||||
<el-button
|
||||
v-if="isImage(file)"
|
||||
type="primary"
|
||||
link
|
||||
@click.stop="handleImagePreview(file)"
|
||||
title="预览"
|
||||
>
|
||||
<i class="fa-solid fa-eye"></i>
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click.stop="handleMoveClick(file)"
|
||||
title="移动"
|
||||
>
|
||||
移动
|
||||
<i class="fa-solid fa-arrows-up-down-left-right"></i>
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click.stop="handleDownload(file)"
|
||||
title="下载"
|
||||
>
|
||||
下载
|
||||
<i class="fa-solid fa-download"></i>
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
@click.stop="handleDelete(file)"
|
||||
title="删除"
|
||||
>
|
||||
删除
|
||||
<i class="fa-regular fa-trash-can"></i>
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
@click.stop="handlePermanentDelete(file)"
|
||||
title="彻底删除"
|
||||
>
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -211,7 +265,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<div class="pagination-container" v-if="total > 0">
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
@ -371,6 +425,33 @@
|
||||
@success="handleCreateCategorySuccess"
|
||||
@close="handleCreateCategoryClose"
|
||||
/>
|
||||
|
||||
<!-- 批量移动文件对话框 -->
|
||||
<el-dialog
|
||||
v-model="showBatchMoveDialog"
|
||||
title="批量移动文件"
|
||||
width="400px"
|
||||
>
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="目标分组">
|
||||
<el-select v-model="batchMoveTargetCate" placeholder="请选择目标分组">
|
||||
<el-option :value="0" label="未分类" />
|
||||
<el-option
|
||||
v-for="group in groups"
|
||||
:key="group.id"
|
||||
:value="group.id"
|
||||
:label="group.name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="showBatchMoveDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmBatchMove" :loading="batchMoveLoading">
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -391,6 +472,7 @@ import {
|
||||
Files,
|
||||
Download,
|
||||
Delete,
|
||||
DeleteFilled,
|
||||
Edit,
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
@ -404,7 +486,11 @@ import {
|
||||
createFileCate,
|
||||
renameFileCate,
|
||||
deleteFileCate,
|
||||
deleteFilePermanently,
|
||||
deleteFile,
|
||||
batchDeleteFiles,
|
||||
batchDeleteFilesPermanently,
|
||||
batchMoveFiles,
|
||||
} from "@/api/file";
|
||||
import UploadFile from "./components/uploadFile.vue";
|
||||
import MoveFile from "./components/moveFile.vue";
|
||||
@ -440,7 +526,7 @@ const loading = ref(false);
|
||||
|
||||
// 分页相关
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(24);
|
||||
const pageSize = ref(20);
|
||||
const total = ref(0);
|
||||
|
||||
// 上传对话框
|
||||
@ -450,6 +536,14 @@ const showUploadDialog = ref(false);
|
||||
const showMoveDialog = ref(false);
|
||||
const selectedFile = ref<FileItem | null>(null);
|
||||
|
||||
// 批量选择
|
||||
const selectedFileIds = ref<number[]>([]);
|
||||
|
||||
// 批量移动对话框
|
||||
const showBatchMoveDialog = ref(false);
|
||||
const batchMoveTargetCate = ref(0);
|
||||
const batchMoveLoading = ref(false);
|
||||
|
||||
// 图片预览
|
||||
const showImagePreview = ref(false);
|
||||
const previewImageUrl = ref("");
|
||||
@ -500,7 +594,7 @@ const getFileUrl = (url: string) => {
|
||||
return `${import.meta.env.VITE_API_BASE_URL}${url}`;
|
||||
};
|
||||
|
||||
//未分类分组(固定,不可编辑)
|
||||
// 未分类分组(固定,不可编辑)
|
||||
const uncategorizedGroup = ref<Group>({
|
||||
id: 0,
|
||||
name: "未分类",
|
||||
@ -508,17 +602,9 @@ const uncategorizedGroup = ref<Group>({
|
||||
description: "未分类的文件",
|
||||
});
|
||||
|
||||
// 头像分组(固定,不可编辑)
|
||||
const avatarGroup = ref<Group>({
|
||||
id: 999,
|
||||
name: "头像",
|
||||
total: 0,
|
||||
description: "用户头像",
|
||||
});
|
||||
|
||||
// 过滤后的分组列表(未分类组置顶)
|
||||
const filteredGroups = computed(() => {
|
||||
let result = [uncategorizedGroup.value, avatarGroup.value, ...groups.value];
|
||||
let result = [uncategorizedGroup.value, ...groups.value];
|
||||
|
||||
if (groupSearchQuery.value) {
|
||||
const query = groupSearchQuery.value.toLowerCase();
|
||||
@ -651,9 +737,6 @@ const loadFiles = async () => {
|
||||
if (selectedGroup.value.id === 0) {
|
||||
// 更新未分类组的文件数量
|
||||
uncategorizedGroup.value.total = res.data.total || 0;
|
||||
} else if (selectedGroup.value.id === 999) {
|
||||
// 更新头像组的文件数量
|
||||
avatarGroup.value.total = res.data.total || 0;
|
||||
} else {
|
||||
// 更新普通分组的文件数量
|
||||
const group = groups.value.find(
|
||||
@ -965,6 +1048,30 @@ function handleDelete(row) {
|
||||
});
|
||||
}
|
||||
|
||||
// 彻底删除文件
|
||||
function handlePermanentDelete(row) {
|
||||
ElMessageBox.confirm("确定要彻底删除文件吗?此操作不可恢复,服务器上的文件也会被删除!", "警告", {
|
||||
confirmButtonText: "确定删除",
|
||||
cancelButtonText: "取消",
|
||||
type: "error",
|
||||
}).then(() => {
|
||||
deleteFilePermanently(row.id).then((res) => {
|
||||
const resp =
|
||||
res && typeof res.code !== "undefined"
|
||||
? res
|
||||
: res && res.data
|
||||
? res.data
|
||||
: res;
|
||||
if (resp.code === 200) {
|
||||
ElMessage.success("彻底删除成功");
|
||||
loadFiles();
|
||||
} else {
|
||||
ElMessage.error((resp && resp.message) || "彻底删除失败");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const handleUpload = () => {
|
||||
if (!selectedGroup.value) {
|
||||
ElMessage.warning("请先选择一个分组");
|
||||
@ -979,6 +1086,158 @@ const handleUploadSuccess = () => {
|
||||
loadFiles();
|
||||
};
|
||||
|
||||
// 切换文件选择
|
||||
const toggleFileSelection = (file: FileItem) => {
|
||||
const index = selectedFileIds.value.indexOf(file.id);
|
||||
if (index > -1) {
|
||||
selectedFileIds.value.splice(index, 1);
|
||||
} else {
|
||||
selectedFileIds.value.push(file.id);
|
||||
}
|
||||
};
|
||||
|
||||
// 全选/反选切换
|
||||
const toggleSelectAll = () => {
|
||||
const allFileIds = files.value.map(file => file.id);
|
||||
const isAllSelected = allFileIds.length === selectedFileIds.value.length && allFileIds.length > 0;
|
||||
|
||||
if (isAllSelected) {
|
||||
selectedFileIds.value = [];
|
||||
} else {
|
||||
selectedFileIds.value = allFileIds;
|
||||
}
|
||||
};
|
||||
|
||||
// 清除选择
|
||||
const clearSelection = () => {
|
||||
selectedFileIds.value = [];
|
||||
};
|
||||
|
||||
// 批量移动
|
||||
const handleBatchMove = () => {
|
||||
if (selectedFileIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要移动的文件');
|
||||
return;
|
||||
}
|
||||
batchMoveTargetCate.value = 0;
|
||||
showBatchMoveDialog.value = true;
|
||||
};
|
||||
|
||||
// 确认批量移动
|
||||
const confirmBatchMove = async () => {
|
||||
if (selectedFileIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要移动的文件');
|
||||
return;
|
||||
}
|
||||
if (batchMoveTargetCate.value === null || batchMoveTargetCate.value === undefined) {
|
||||
ElMessage.warning('请选择目标分组');
|
||||
return;
|
||||
}
|
||||
|
||||
batchMoveLoading.value = true;
|
||||
try {
|
||||
const res = await batchMoveFiles(selectedFileIds.value, batchMoveTargetCate.value);
|
||||
const resp =
|
||||
res && typeof res.code !== 'undefined'
|
||||
? res
|
||||
: res && res.data
|
||||
? res.data
|
||||
: res;
|
||||
if (resp.code === 200) {
|
||||
ElMessage.success('批量移动成功');
|
||||
showBatchMoveDialog.value = false;
|
||||
clearSelection();
|
||||
loadFiles();
|
||||
getUserCateData();
|
||||
} else {
|
||||
ElMessage.error((resp && resp.message) || '批量移动失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量移动失败:', error);
|
||||
ElMessage.error('批量移动失败');
|
||||
} finally {
|
||||
batchMoveLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
const handleBatchDelete = () => {
|
||||
if (selectedFileIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要删除的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(
|
||||
`确定要删除选中的 ${selectedFileIds.value.length} 个文件吗?`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
).then(async () => {
|
||||
try {
|
||||
const res = await batchDeleteFiles(selectedFileIds.value);
|
||||
const resp =
|
||||
res && typeof res.code !== 'undefined'
|
||||
? res
|
||||
: res && res.data
|
||||
? res.data
|
||||
: res;
|
||||
if (resp.code === 200) {
|
||||
ElMessage.success('批量删除成功');
|
||||
clearSelection();
|
||||
loadFiles();
|
||||
getUserCateData();
|
||||
} else {
|
||||
ElMessage.error((resp && resp.message) || '批量删除失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量删除失败:', error);
|
||||
ElMessage.error('批量删除失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 批量永久删除
|
||||
const handleBatchDeletePermanently = () => {
|
||||
if (selectedFileIds.value.length === 0) {
|
||||
ElMessage.warning('请先选择要永久删除的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(
|
||||
`确定要永久删除选中的 ${selectedFileIds.value.length} 个文件吗?此操作不可恢复,服务器上的文件也会被删除!`,
|
||||
'危险操作',
|
||||
{
|
||||
confirmButtonText: '确定永久删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'error',
|
||||
}
|
||||
).then(async () => {
|
||||
try {
|
||||
const res = await batchDeleteFilesPermanently(selectedFileIds.value);
|
||||
const resp =
|
||||
res && typeof res.code !== 'undefined'
|
||||
? res
|
||||
: res && res.data
|
||||
? res.data
|
||||
: res;
|
||||
if (resp.code === 200) {
|
||||
ElMessage.success('批量永久删除成功');
|
||||
clearSelection();
|
||||
loadFiles();
|
||||
getUserCateData();
|
||||
} else {
|
||||
ElMessage.error((resp && resp.message) || '批量永久删除失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量永久删除失败:', error);
|
||||
ElMessage.error('批量永久删除失败');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
getUserCateData();
|
||||
@ -1111,9 +1370,23 @@ onMounted(() => {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.file-grid-header {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
.allbtns{
|
||||
color:#0081ff;
|
||||
|
||||
&:hover{
|
||||
color:#0088ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
grid-auto-rows: auto;
|
||||
align-items: start;
|
||||
gap: 16px;
|
||||
@ -1126,12 +1399,25 @@ onMounted(() => {
|
||||
// height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
&.file-card-selected {
|
||||
border: 2px solid var(--el-color-primary);
|
||||
box-shadow: 0 0 0 2px rgba(var(--el-color-primary-rgb), 0.2);
|
||||
}
|
||||
|
||||
.file-checkbox {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column prop="mid" label="MID" width="80" align="center" />
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="模块名称"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user