FileManage/web/src/views/special/document/index.vue
2025-02-13 09:10:39 +08:00

687 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts">
export default {
name: "document",//文档管理
};
</script>
<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
import { useAppStore } from '@/store/modules/app';
import { ElMessageBox, ElMessage } from "element-plus";
import Page from '@/components/Pagination/page.vue';
import { projectList, getNodesTree, addNodes, updateNodes, deleteNodesById, getFilesPage, addFiles, updateFiles, deleteFilesById, deleteFilesByIds } from "@/api/document";
import ZUpload from '@/components/file/ZUpload.vue'
import useFileUpload from "@/components/file/file/useFileUpload";
import useHeaderStorageList from "@/components/header/useHeaderStorageList";
const { openUploadDialog, openUploadFolderDialog, uploadProgressInfoStatistics } = useFileUpload();
const { currentStorageKey } = useHeaderStorageList();
onMounted(() => {
getProject()
});
//拖动条
const vMove = {
mounted(el: any) {
el.onmousedown = function (e: any) {
var init = e.clientX;
var parent: any = document.getElementById("silderLeft");
const initWidth: any = parent.offsetWidth;
document.onmousemove = function (e) {
var end = e.clientX;
var newWidth = end - init + initWidth;
parent.style.width = newWidth + "px";
};
document.onmouseup = function () {
document.onmousemove = document.onmouseup = null;
};
};
}
}
//左侧树的选择框
const projectId = ref()
const projectArr = ref([])
//获取所有项目
function getProject() {
projectList().then((res: any) => {
projectArr.value = res.data
projectId.value = projectArr.value[0].id
gettreedata()
})
}
//左侧树配置
const treedata = ref([])
const treeloading = ref(false)
const defaultProps = {
children: "children",
label: "nodeName"
};
const treeForm = ref({
projectId: '',
nodeName: '',
})
//获取树数据
function gettreedata() {
treeloading.value = true
treeForm.value.projectId = projectId.value
getNodesTree(treeForm.value).then((res: any) => {
treedata.value = res.data
treeloading.value = false
})
}
const pathid = ref()
function handleNodeClick(data: any, node: any) {
pathid.value = data.id
getdata()
}
//子项目配置
const frame = ref(false)
const title = ref()
const ruleFormRef = ref()
const projectForme: any = ref({
projectId: '',//所属项目id
parentId: "",//父节点id
nodeType: "",//节点类型
nodeName: "",//节点名称
})
//用户弹窗规则定义
const moderules = ref({
nodeName: [{ required: true, message: "请输入节点名称", trigger: "blur" }],
});
//新增子项目
function addSubItem(row: any) {
frame.value = true
projectForme.value = {
projectId: '',//所属项目id
parentId: "",//父节点id
nodeType: "",//节点类型
nodeName: "",//节点名称
}
projectForme.value.projectId = projectId.value
if (row.nodeType == '00') {
projectForme.value.parentId = '00'
} else {
projectForme.value.parentId = row.id
}
if (row.nodeType == '00') {
title.value = "添加子项目"
projectForme.value.nodeType = '01'
} else if (row.nodeType == '01') {
title.value = "添加课题"
projectForme.value.nodeType = '02'
} else if (row.nodeType == '02') {
title.value = "添加年度"
projectForme.value.nodeType = '03'
} else if (row.nodeType == '03') {
title.value = "添加主题"
projectForme.value.nodeType = '04'
}
}
//修改子项目
function editSubItem(row: any) {
if (row.nodeType == '01') {
title.value = "修改子项目"
} else if (row.nodeType == '02') {
title.value = "修改课题"
} else if (row.nodeType == '03') {
title.value = "修改年度"
} else if (row.nodeType == '04') {
title.value = "修改主题"
}
// title.value = "修改子项目"
frame.value = true
if (row.subRegions) {
delete row.subRegions
}
if (row.createTime) {
delete row.createTime
}
projectForme.value = JSON.parse(JSON.stringify(row))
}
//表单确定
async function submitForm(formEl: any) {
if (!formEl) return
await formEl.validate((valid: any, fields: any) => {
if (valid) {
if (projectForme.value.id) {
updateNodes(projectForme.value).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage.success("修改成功")
frame.value = false
}
})
} else {
addNodes(projectForme.value).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage.success("添加成功")
frame.value = false
}
})
}
}
})
}
//弹框关闭
function handleClose(formEl: any) {
// if (!formEl) return
// formEl.resetFields()
frame.value = false
}
//删除子节点
function delSubItem(row: any) {
ElMessageBox.confirm(
'您确定要删除该项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteNodesById({ id: row.id }).then((res: any) => {
if (res.code == 0) {
gettreedata()
ElMessage({
type: 'success',
message: '删除成功',
})
}
})
})
}
//表格数据配置
const queryParams: any = ref({
current: 1,
size: 20,
fileName: '',
startDate: '',
endDate: '',
keywords: '',
nodeId: '',//节点ID
projectId: '',//项目Id
});
const dataarr = ref([])
//定义表格数据
const tableData: any = ref([]);
const total = ref(0);
// 表格加载
const loading = ref(false)
//获取表格数据
function getdata() {
loading.value = true
console.log(dataarr.value)
if (dataarr.value && dataarr.value.length > 0) {
queryParams.value.startDate = dataarr.value[0]
queryParams.value.endDate = dataarr.value[1]
} else {
queryParams.value.startDate = ''
queryParams.value.endDate = ''
}
queryParams.value.nodeId = pathid.value
queryParams.value.projectId = projectId.value
getFilesPage(queryParams.value).then((res: any) => {
queryParams.value.current = res.data.current
queryParams.value.size = res.data.size
total.value = res.data.total
loading.value = false
tableData.value = res.data.records
})
}
//新增文件对象
const fileObj: any = ref({
projectId: '', //所属项目ID
nodeId: '', //节点ID
fileName: '', //文件名称
filePath: '', //文件对象存储路径
keywords: '', //关键字
description: '', //文件描述
fileSize: '', //M
})
//上传组件
const upfile = ref(false)
function openFile() {
localStorage.setItem('filepath', findPathById(treedata.value, pathid.value));
upfile.value = true
fileObj.value = {
projectId: '', //所属项目ID
nodeId: '', //节点ID
fileName: '', //文件名称
filePath: '', //文件对象存储路径
keywords: '', //关键字
description: '', //文件描述
fileSize: '', //M
}
}
//修改文件
function editfile(row: any) {
upfile.value = true
fileObj.value = JSON.parse(JSON.stringify(row))
}
function fileClose() {
upfile.value = false
}
//字节转mb
function bytesToMB(bytes: any) {
return bytes / Math.pow(1024, 2);
}
//上传确定
function submitfile() {
// console.log( )
if (fileObj.value.id) {
updateFiles(fileObj.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('修改成功')
getdata()
upfile.value = false
}
})
} else {
let fileArr = JSON.parse(localStorage.getItem('fileArr'))
let fileName = []
let fileSize = []
if (fileArr.length > 0) {
fileArr.forEach((item: any) => {
fileName.push(item.name)
fileSize.push(bytesToMB(item.size))
})
}
fileObj.value.projectId = projectId.value
fileObj.value.nodeId = pathid.value
fileObj.value.filePath = findPathById(treedata.value, pathid.value)
fileObj.value.fileName = fileName.join(',')
fileObj.value.fileSize = fileSize.join(',')
addFiles(fileObj.value).then((res: any) => {
if (res.code == 0) {
ElMessage.success('增加成功')
getdata()
upfile.value = false
}
})
}
}
//单个删除文件
function delfile(row: any) {
ElMessageBox.confirm(
'您确定要删除该文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteFilesById({ id: row.id }).then((res: any) => {
if (res.code == 0) {
getdata()
ElMessage({
type: 'success',
message: '删除成功',
})
}
})
})
}
//多个删除文件
//表格多选
const tableIdarr = ref([])
function handleSelectionChange(val: any) {
tableIdarr.value = val
}
//多选删除
function delprojectArr() {
const ids = []
tableIdarr.value.forEach((item: any) => {
ids.push(item.id)
})
ElMessageBox.confirm(
'您确定要删除这些项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteFilesByIds({ ids: ids.join(',') }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '删除成功',
})
getdata()
}
})
})
}
//下载
function xiafile(row: any) {
ElMessageBox.confirm(
'您确定要下载该文件吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
window.open(row.url);
})
}
//多选下载
function xiafilemony() {
ElMessageBox.confirm(
'您确定要下载这些项目吗?',
'警告',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
tableIdarr.value.forEach((item: any) => {
if(item.url){
downloadFileUseIframeMode(item.url);
}
})
})
}
/**
* 使用 iframe 模式下载文件
*
* @param url 下载文件 url
*/
const downloadFileUseIframeMode = (url:any) => {
const iframe:any = document.createElement("iframe");
iframe.style.display = "none"; // 防止影响页面
iframe.style.height = 0; // 防止影响页面
iframe.src = url;
document.body.appendChild(iframe);
setTimeout(()=>{
iframe.remove();
}, 5 * 60 * 1000);
}
function findPathById(array: any, targetId: any) {
// 辅助函数,用于递归查找路径
function recursiveSearch(items: any, target: any, path: any) {
for (let item of items) {
// 将当前对象的name添加到路径中
let newPath = [...path, item.nodeName];
// 检查当前对象的id是否匹配目标id
if (item.id === target) {
return newPath.join('/'); // 找到匹配项,返回路径字符串
}
// 如果没有找到匹配项继续检查children数组
if (item.children && item.children.length > 0) {
let result = recursiveSearch(item.children, target, newPath);
if (result) { // 如果在children中找到了匹配项返回结果
return result;
}
}
}
return null; // 如果没有找到匹配项返回null
}
// 从顶层数组开始搜索
let patharr = recursiveSearch(array, targetId, [])
return '/' + patharr; // 注意这里我们传入了一个空数组作为初始路径
}
</script>
<template>
<div class="faulttemplate-box">
<aside id="silderLeft">
<div>
<el-select v-model="projectId" placeholder="请选择项目" @change="gettreedata()">
<el-option v-for="item in projectArr" :key="item.id" :label="item.projectName" :value="item.id" />
</el-select>
<div class="tree_sou">
<el-input v-model="treeForm.nodeName" style="width:100%;margin:10px 9px 10px 0px;"
placeholder="节点名称" clearable />
<el-button type="primary" @click="gettreedata()">搜索</el-button>
<el-button type="primary" @click="addSubItem({ nodeType: '00' })">新增子项目</el-button>
</div>
<el-tree ref="treeRef" node-key="id" :data="treedata" :highlight-current="true" :props="defaultProps"
v-loading="treeloading" @node-click="handleNodeClick"
:class="useAppStore().size === 'default' ? 'silderLeft-large' : 'silderLeft-default'"
style="height: calc(100vh - 280px); overflow: auto;margin-top: 10px;">
<template #default="{ data }">
<span class="custom-tree-node">
<span>{{ data.nodeName }}</span>
<span class="img_tree">
<img src="@/assets/project/xiu.png" alt="" title="编辑" @click="editSubItem(data)">
<img src="@/assets/project/del.png" alt="" title="删除" @click="delSubItem(data)">
<img v-if="data.nodeType == '01'" src="@/assets/project/jia.png" alt="" title="添加课题"
@click="addSubItem(data)">
<img v-if="data.nodeType == '02'" src="@/assets/project/jia.png" alt="" title="添加年度"
@click="addSubItem(data)">
<img v-if="data.nodeType == '03'" src="@/assets/project/jia.png" alt="" title="添加主题"
@click="addSubItem(data)">
</span>
</span>
</template>
</el-tree>
</div>
<div class="moveBtn" v-move>
<div class="moveBtn-line"></div>
</div>
</aside>
<section class="silderRight">
<div class="sou_title">
<div class="sou_title_left">
<el-input style="margin-right: 10px ;" v-model="queryParams.fileName" clearable @change="getdata()"
placeholder="文件名称"></el-input>
<el-input style="margin-right: 10px ;" v-model="queryParams.keywords" clearable @change="getdata()"
placeholder="关键字"></el-input>
<el-date-picker v-model="dataarr" type="daterange" @change="getdata()"
style="width: 150%;margin-right: 10px ;" start-placeholder="开始时间" end-placeholder="结束时间"
format="YYYY-MM-DD" value-format="YYYY-MM-DD" range-separator="至" />
<el-button type="primary" @click="getdata()">搜索</el-button>
</div>
<div>
<!-- :disabled="pathid.value" -->
<el-button type="primary" :disabled="!pathid" @click="openFile">上传</el-button>
<el-button type="primary" @click="delprojectArr()" :disabled="tableIdarr.length == 0">删除</el-button>
<el-button type="primary" @click="xiafilemony()" :disabled="tableIdarr.length == 0">下载</el-button>
</div>
</div>
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange"
:header-cell-style="{ background: 'rgb(250 250 250)', height: '50px' }"
style="width: 100%; height: calc(100vh - 275px);margin-bottom: 20px;" border>
<el-table-column type="selection" width="40" />
<!-- <el-table-column type="index" label="序号" width="70" align="center"></el-table-column> -->
<el-table-column prop="fileName" label="文件名称"></el-table-column>
<el-table-column prop="keywords" label="关键字"></el-table-column>
<el-table-column prop="description" label="文件描述"></el-table-column>
<el-table-column prop="uploader" width="80" label="上传人"></el-table-column>
<el-table-column prop="uploadTime" width="170" label="上传时间"></el-table-column>
<el-table-column fixed="right" label="操作" width="80" align="center">
<template #default="scope">
<span
style="display: flex;display: -webkit-flex;justify-content: space-between;-webkit-justify-content: space-between; ">
<img src="@/assets/MenuIcon/lbcz_xg.png" alt="" @click="editfile(scope.row)" title="修改"
style="cursor: pointer;">
<img src="@/assets/MenuIcon/lbcz_sc.png" alt="" @click="delfile(scope.row)" title="删除"
style="cursor: pointer;">
<img src="@/assets/MenuIcon/xia1.png" alt="" @click="xiafile(scope.row)" title="下载"
style="cursor: pointer;">
</span>
</template>
</el-table-column>
</el-table>
<Page :total="total" v-model:size="queryParams.size" v-model:current="queryParams.current"
@pagination="getdata()">
</Page>
</section>
<el-dialog :title="title" v-model="frame" width="30%" :before-close="handleClose" top="30px" draggable
destroy-on-close>
<el-form ref="ruleFormRef" style="max-width: 600px" :model="projectForme" :rules="moderules"
label-width="auto" class="demo-ruleForm" status-icon>
<el-form-item label="节点名称" prop="nodeName">
<el-input v-model="projectForme.nodeName" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button>
<el-button @click="handleClose(ruleFormRef)">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog title="上传文件" v-model="upfile" width="35%" :before-close="fileClose" top="30px" draggable
destroy-on-close>
<el-form ref="ruleFormRef" style="max-width: 600px" :model="fileObj" :rules="moderules" label-width="auto"
class="demo-ruleForm" status-icon>
<el-form-item v-if="!fileObj.id" label="文件:" prop="taskCode">
<el-button @click="openUploadDialog" type="primary">上传文件</el-button>
<el-button @click="openUploadFolderDialog" type="primary">上传文件夹</el-button>
<ZUpload />
</el-form-item>
<el-form-item v-else label="文件名称:">
<el-input v-model="fileObj.fileName" />
</el-form-item>
<el-form-item label="关键字:" prop="taskName">
<el-input v-model="fileObj.keywords" />
</el-form-item>
<el-form-item label="描述:">
<el-input v-model="fileObj.description" :rows="2" type="textarea" />
</el-form-item>
<el-form-item>
<div style="width: 100%;display: flex;justify-content: end;">
<el-button type="primary" @click="submitfile">确定</el-button>
<el-button @click="fileClose">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<style scoped lang="scss">
.faulttemplate-box {
height: 100%;
display: flex;
display: -webkit-flex;
background-color: #f2f4f9;
}
#silderLeft {
width: 300px;
padding: 10px;
box-sizing: border-box;
background: #fff;
border-radius: 3px;
position: relative;
.tree_sou {
display: flex;
align-items: center;
justify-content: space-between;
}
&:hover {
.moveBtn {
opacity: 1;
}
}
}
/* 拖动条 */
.moveBtn {
height: 100%;
width: 15px;
padding: 0 6px;
opacity: 0;
position: absolute;
right: -15px;
top: 0;
}
.moveBtn-line {
width: 100%;
height: 100%;
cursor: col-resize;
user-select: none;
background-color: #60bfff;
}
.silderRight {
flex: 1;
width: 100%;
height: calc(100vh - 130px);
overflow: auto;
background-color: rgba(255, 255, 255, 1);
border-radius: 3px;
padding: 15px;
padding-bottom: 0px;
box-sizing: border-box;
margin-left: 15px;
.sou_title {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.sou_title_left {
width: 50%;
display: flex;
align-items: center;
justify-content: space-between;
}
}
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.img_tree {
display: flex;
width: 25%;
align-items: center;
justify-content: space-between;
img {
cursor: pointer;
}
}
}
</style>