school_file_web/src/views/resourceMgt/catalogResourceMgt/index.vue

584 lines
19 KiB
Vue

<template>
<el-row>
<el-col :span="5">
<div class="tree-container">
<div class="top">
<el-button type="" text="plain">全部专题资源</el-button>
<br>
<el-badge v-if="auditNum > 0" :value="auditNum" style="margin-left:10px;margin-top: 10px;">
<el-button v-hasPermi="['file:resource:awaitList']" :class="['btn-audit', isAudit && 'active']" type=""
text="plain" @click="handleAudit">待审核</el-button>
</el-badge>
<el-button v-else v-hasPermi="['file:resource:awaitList']" :class="['btn-audit', isAudit && 'active']" type=""
text="plain" @click="handleAudit">待审核</el-button>
<div class="tree-container-scroll">
<el-scrollbar>
<el-tree ref="treeRef" v-loading="treeLoading" :data="treeData" :props="defaultProps" default-expand-all
@node-click="handleNode" />
</el-scrollbar>
</div>
</div>
<div class="bottom" v-if="volume">
<span>资源空间:{{ volume.useVolumename }} / {{ volume.totalVolumeName }}</span>
<el-progress :percentage="volume.volumePercent" />
</div>
</div>
</el-col>
<el-col :span="19">
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="课件名称" prop="fileName">
<el-input v-model="queryParams.fileName" placeholder="请输入课件名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="格式" prop="fileSuffix">
<el-select v-model="queryParams.fileSuffix" placeholder="请选择" style="width: 240px"
@keyup.enter="handleQuery">
<el-option v-for="item in formatOptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="hover">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col v-if="isUpload" :span="1.5">
<el-button v-hasPermi="['file:resource:add']" type="primary" plain icon="Upload"
@click="handleFile">上传文件</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['file:resource:remove']" type="danger" plain icon="Delete" :disabled="multiple"
@click="handleDelete()">
删除
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar>
</el-row>
</template>
<el-table v-if="showTable" v-loading="loading" :data="ossList" :header-cell-class-name="handleHeaderClass"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="课件名" align="center" prop="fileName" width="240" />
<el-table-column label="课件格式" align="center" prop="fileSuffix" />
<el-table-column label="课件大小" align="center" prop="volume" />
<el-table-column label="创建人" align="center" prop="createBy" />
<el-table-column label="审核状态" align="center" prop="status">
<template #default="scope">
<el-tag v-if="scope.row.status == -1" type="warning">待审核</el-tag>
<el-tag v-if="scope.row.status == 0" type="success">审核不通过</el-tag>
<el-tag v-if="scope.row.status == 1" type="danger">审核通过</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="scope">
<span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="400">
<template #default="scope">
<span v-hasPermi="['file:resource:review']">
<el-tooltip v-if="isAudit" content="审核通过" placement="top">
<el-button link type="primary" icon="CopyDocument"
@click="handleAuditBtn(scope.row, 1)">审核通过</el-button>
</el-tooltip>
<el-tooltip v-if="isAudit" content="审核不通过" placement="top">
<el-button link type="primary" icon="DocumentCopy"
@click="handleAuditBtn(scope.row, 0)">审核不通过</el-button>
</el-tooltip>
</span>
<el-tooltip v-hasPermi="['file:resource:preview']" content="预览" placement="top">
<el-button link type="primary" icon="View" @click="handlePreview(scope.row)">预览</el-button>
</el-tooltip>
<el-tooltip v-hasPermi="['file:resource:download']" content="下载" placement="top">
<el-button link type="primary" icon="Download" @click="handleDownload(scope.row)">下载</el-button>
</el-tooltip>
<el-tooltip v-hasPermi="['file:resource:move']" v-if="isTree" content="移动" placement="top">
<el-button link type="primary" icon="CopyDocument" @click="handleMove(scope.row)">移动</el-button>
</el-tooltip>
<el-tooltip v-hasPermi="['file:resource:copy']" v-if="isTree" content="复制" placement="top">
<el-button link type="primary" icon="DocumentCopy" @click="handleCopy(scope.row)">复制</el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button v-hasPermi="['file:resource:remove']" link type="primary" icon="Delete"
@click="handleDelete(scope.row)">删除</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
:total="total" @pagination="getList" />
</el-card>
<!-- 添加或修改OSS对象存储对话框 -->
<el-dialog v-model="dialog.visible" :title="dialog.title" width="700px" append-to-body>
<el-form ref="ossFormRef" :model="form" :rules="rules">
<el-form-item prop="file">
<FileMd5Upload v-if="type === 0" v-model="form.file" @onFileName="handleFileName" />
<imageUpload v-if="type === 1" v-model="form.file" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="treeMoveDialog.visible" :title="treeMoveDialog.title" width="500px" append-to-body>
<el-form ref="treeMoveFormRef" :model="treeMoveForm" :rules="treeMoveRules">
<el-form-item label="移动至" prop="catalogId">
<el-tree-select v-model="treeMoveForm.catalogId" :data="treeData"
:props="{ value: 'catalogId', label: 'catalogName', children: 'children' }" value-key="catalogId"
placeholder="请选择" check-strictly />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitMoveForm">确 定</el-button>
<el-button @click="cancelMove">取 消</el-button>
</div>
</template>
</el-dialog>
<el-dialog v-model="treeCopyDialog.visible" :title="treeCopyDialog.title" width="500px" append-to-body>
<el-form ref="treeCopyFormRef" :model="treeCopyForm" :rules="treeCopyRules">
<el-form-item label="复制至" prop="catalogId">
<el-tree-select v-model="treeCopyForm.catalogId" :data="treeData"
:props="{ value: 'catalogId', label: 'catalogName', children: 'children' }" value-key="catalogId"
placeholder="请选择" check-strictly />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitCopyForm">确 定</el-button>
<el-button @click="cancelCopy">取 消</el-button>
</div>
</template>
</el-dialog>
</div>
</el-col>
</el-row>
</template>
<script setup name="Oss" lang="ts">
import { pageResource, awaitResourceList, awaitResourceCount, previewResource, delResource, addResource, reviewResource, copyResource, moveResource } from '@/api/system/oss';
import FileMd5Upload from '@/components/FileMd5Upload/index.vue';
import { listCatalogResource } from "@/api/resource/catalogResource";
import { CatalogTextbookVO } from '@/api/resource/catalogTextbook/types';
import { Base64 } from 'js-base64'
import { useVolume } from "@/composables/useVolume";
import auth from '@/plugins/auth';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { volume } = useVolume(1);
const formatOptions = [
{
value: '.doc',
label: 'doc',
},
{
value: '.docx',
label: 'docx',
},
{
value: '.xls',
label: 'xls',
},
{
value: '.xlsx',
label: 'xlsx',
},
{
value: '.ppt',
label: 'ppt',
},
{
value: '.pptx',
label: 'pptx',
},
{
value: '.pdf',
label: 'pdf',
},
{
value: '.txt',
label: 'txt',
}
]
const defaultProps = {
children: 'children',
label: 'catalogName',
}
const isUpload = ref(false)
const currentNode = ref<any>({})
const treeData = ref<CatalogTextbookVO[]>([])
const ossList = ref<any[]>([]);
const showTable = ref(true);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const type = ref(0);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const previewDialog = reactive<DialogOption>({
visible: false,
title: '文件预览'
});
const treeMoveDialog = reactive<DialogOption>({
visible: false,
title: '移动'
});
const treeMoveFormRef = ref()
const treeMoveForm = ref<any>({ id: '', catalogId: '' });
const treeMoveRules = ref({
catalogId: [{ required: true, message: '请选择', trigger: 'blur' }]
})
const treeCopyDialog = reactive<DialogOption>({
visible: false,
title: '复制'
});
const treeCopyFormRef = ref()
const treeCopyForm = ref<any>({ id: '', catalogId: '' });
const treeCopyRules = ref({
catalogId: [{ required: true, message: '请选择', trigger: 'blur' }]
})
const ossFormRef = ref<ElFormInstance>();
const queryFormRef = ref<ElFormInstance>();
const initFormData = {
file: undefined
};
const data = reactive<PageData<any, any>>({
form: { ...initFormData },
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
ossId: '',
fileName: '',
originalName: '',
fileSuffix: '',
createTime: '',
service: '',
catalogId: '',
},
rules: {
file: [{ required: true, message: '文件不能为空', trigger: 'blur' }]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询OSS对象存储列表 */
const getList = async () => {
loading.value = true;
let response
if (isAudit.value) {
response = await awaitResourceList(queryParams.value);
} else {
response = await pageResource(queryParams.value);
}
ossList.value = response.rows;
total.value = response.total;
loading.value = false;
showTable.value = true;
};
/** 取消按钮 */
function cancel() {
dialog.visible = false;
reset();
}
/** 表单重置 */
function reset() {
form.value = { ...initFormData };
ossFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
}
/** 重置按钮操作 */
function resetQuery() {
showTable.value = false;
queryFormRef.value?.resetFields();
handleQuery();
}
/** 选择条数 */
function handleSelectionChange(selection: any[]) {
ids.value = selection.map((item) => item.ossId);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 设置列的排序为我们自定义的排序 */
const handleHeaderClass = ({ column }: any): any => {
column.order = column.multiOrder;
};
const handleOrderChange = (prop: string, order: string) => {
let orderByArr = queryParams.value.orderByColumn ? queryParams.value.orderByColumn.split(',') : [];
let isAscArr = queryParams.value.isAsc ? queryParams.value.isAsc.split(',') : [];
let propIndex = orderByArr.indexOf(prop);
if (propIndex !== -1) {
if (order) {
//排序里已存在 只修改排序
isAscArr[propIndex] = order;
} else {
//如果order为null 则删除排序字段和属性
isAscArr.splice(propIndex, 1); //删除排序
orderByArr.splice(propIndex, 1); //删除属性
}
} else {
//排序里不存在则新增排序
orderByArr.push(prop);
isAscArr.push(order);
}
//合并排序
queryParams.value.orderByColumn = orderByArr.join(',');
queryParams.value.isAsc = isAscArr.join(',');
getList();
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
};
/** 文件按钮操作 */
const handleFile = () => {
reset();
type.value = 0;
dialog.visible = true;
dialog.title = '上传文件';
};
const fileName = ref('')
const handleFileName = (val) => {
fileName.value = val
}
/** 提交按钮 */
const submitForm = async () => {
const ossId = form.value.file
const catalogId = currentNode.value.catalogId
await addResource({ ossId, catalogId, fileName: fileName.value })
dialog.visible = false;
getList();
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
};
const submitMoveForm = () => {
treeMoveFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
treeMoveDialog.visible = false;
const res = await moveResource(treeMoveForm.value)
if (res.code === 200) {
proxy?.$modal.msgSuccess("移动成功")
await getList()
}
}
});
}
const cancelMove = () => {
treeMoveDialog.visible = false
}
const submitCopyForm = () => {
treeCopyFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
treeCopyDialog.visible = false
const res = await copyResource(treeCopyForm.value)
if (res.code === 200) {
proxy?.$modal.msgSuccess("复制成功")
await getList()
}
}
});
}
const cancelCopy = () => {
treeCopyDialog.visible = false
}
// 0审核不通过 1审核通过
const handleAuditBtn = async (row: any, status: number) => {
const id = row?.id
const fileName = row?.fileName
const title = status === 1 ? `是否审核通过${fileName}?` : `是否审核不通过${fileName}?`
await proxy?.$modal.confirm(title).finally(() => loading.value = false)
await reviewResource({ id, status })
proxy?.$modal.msgSuccess(status === 1 ? "审核通过" : '审核不通过');
await getList();
}
/** 下载按钮操作 */
const handleDownload = (row: any) => {
proxy?.download(`/file/resource/download/${row.id}`, {}, `${row.fileName}`);
};
const handleMove = async (row: any) => {
treeMoveDialog.visible = true
treeMoveForm.value.id = row.id
treeMoveForm.value.catalogId = currentNode.value.catalogId
}
const handleCopy = (row: any) => {
treeCopyDialog.visible = true
treeCopyForm.value.id = row.id
treeCopyForm.value.catalogId = currentNode.value.catalogId
}
/** 删除按钮操作 */
const handleDelete = async (row?: any) => {
const delIds = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除OSS对象存储编号为"' + delIds + '"的数据项?');
loading.value = true;
await delResource(delIds).finally(() => (loading.value = false));
await getList();
proxy?.$modal.msgSuccess('删除成功');
};
const isAudit = ref(false)
const isTree = ref(false)
const handleAudit = () => {
isAudit.value = true
isTree.value = false
getList()
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
}
const handleNode = (node: any) => {
console.log(node)
isAudit.value = false
isTree.value = true
isUpload.value = true
currentNode.value = node
queryParams.value.catalogId = node.catalogId
getList()
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
}
const preViewUrl = import.meta.env.VITE_APP_PREVIEW
const handlePreview = async (row: any) => {
const fileRes = await previewResource(row.id)
window.open(`${preViewUrl}?url=${encodeURIComponent(Base64.encode(fileRes.data))}`, '__blank')
}
const treeLoading = ref(false)
/** 查询目录-同步教材列表 */
const getlistCatalogResource = async () => {
treeLoading.value = true;
const res = await listCatalogResource();
const data = proxy?.handleTree<CatalogTextbookVO>(res.data, "catalogId", "parentId");
if (data) {
treeData.value = data;
treeLoading.value = false;
}
}
const auditNum = ref(0)
const awaitResourceCountData = async () => {
const res = await awaitResourceCount(queryParams.value)
auditNum.value = res.data
}
onMounted(() => {
getlistCatalogResource()
getList();
if (auth.hasPermi('file:resource:review')) {
awaitResourceCountData()
}
});
</script>
<style lang="scss" scoped>
.tree-container {
margin-top: 10px;
padding-top: 10px;
height: calc(100vh - 120px);
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid #ccc;
.top {
margin: 0 20px;
.tree-container-scroll {
height: calc(100vh - 300px);
}
}
.bottom {
text-align: center;
padding-left: 20px;
padding-right: 20px;
padding-bottom: 10px;
font-size: 18px;
}
.btn-audit {
text-indent: 1em;
}
.active {
background-color: #F5F7FA;
}
}
:deep(.docx-wrapper) {
background-color: #fff;
padding: 0;
}
</style>