feat(file): 添加文件管理功能和相关接口
- 新增文件上传、编辑、删除等基础功能 - 实现文件可见范围控制(公开/私有) - 添加与我相关的文件查询功能 - 集成用户选择组件用于设置文件可见用户 - 实现文件统计展示功能 - 完善文件操作权限验证机制 - 添加文件预览和下载功能 - 优化文件列表分页和搜索功能
This commit is contained in:
@@ -71,8 +71,9 @@ public class SysFileController extends BaseController {
|
||||
@Log(title = "文件主信息", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody SysFileBo bo) {
|
||||
return toAjax(iSysFileService.insertByBo(bo));
|
||||
public R<Long> add(@Validated(AddGroup.class) @RequestBody SysFileBo bo) {
|
||||
iSysFileService.insertByBo(bo);
|
||||
return R.ok(bo.getFileId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,4 +97,12 @@ public class SysFileController extends BaseController {
|
||||
@PathVariable Long[] fileIds) {
|
||||
return toAjax(iSysFileService.deleteWithValidByIds(Arrays.asList(fileIds), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询与我相关的文件(私有文件且当前用户在可见用户列表中)
|
||||
*/
|
||||
@GetMapping("/relatedToMe")
|
||||
public TableDataInfo<SysFileVo> relatedToMe(SysFileBo bo, PageQuery pageQuery) {
|
||||
return iSysFileService.queryPageListRelatedToMe(bo, pageQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,9 @@ public interface ISysFileService {
|
||||
* 校验并批量删除文件主信息信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 查询与我相关的文件(私有文件且当前用户在可见用户列表中)
|
||||
*/
|
||||
TableDataInfo<SysFileVo> queryPageListRelatedToMe(SysFileBo bo, PageQuery pageQuery);
|
||||
}
|
||||
|
||||
@@ -6,18 +6,22 @@ import com.klp.common.core.domain.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.klp.common.helper.LoginHelper;
|
||||
import com.klp.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.klp.system.domain.bo.SysFileBo;
|
||||
import com.klp.system.domain.vo.SysFileVo;
|
||||
import com.klp.system.domain.SysFile;
|
||||
import com.klp.system.domain.SysFileVisibleUser;
|
||||
import com.klp.system.mapper.SysFileMapper;
|
||||
import com.klp.system.mapper.SysFileVisibleUserMapper;
|
||||
import com.klp.system.service.ISysFileService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 文件主信息Service业务层处理
|
||||
@@ -30,6 +34,7 @@ import java.util.Collection;
|
||||
public class SysFileServiceImpl implements ISysFileService {
|
||||
|
||||
private final SysFileMapper baseMapper;
|
||||
private final SysFileVisibleUserMapper visibleUserMapper;
|
||||
|
||||
/**
|
||||
* 查询文件主信息
|
||||
@@ -69,6 +74,7 @@ public class SysFileServiceImpl implements ISysFileService {
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getDept()), SysFile::getDept, bo.getDept());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getFileType()), SysFile::getFileType, bo.getFileType());
|
||||
lqw.eq(bo.getScopeType() != null, SysFile::getScopeType, bo.getScopeType());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), SysFile::getCreateBy, bo.getCreateBy());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
@@ -96,6 +102,28 @@ public class SysFileServiceImpl implements ISysFileService {
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询与我相关的文件(私有文件且当前用户在可见用户列表中)
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<SysFileVo> queryPageListRelatedToMe(SysFileBo bo, PageQuery pageQuery) {
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
// 查询当前用户可见的私有文件ID列表
|
||||
LambdaQueryWrapper<SysFileVisibleUser> vuLqw = Wrappers.lambdaQuery();
|
||||
vuLqw.eq(SysFileVisibleUser::getUserId, currentUserId);
|
||||
List<SysFileVisibleUser> visibleList = visibleUserMapper.selectList(vuLqw);
|
||||
List<Long> fileIds = visibleList.stream().map(SysFileVisibleUser::getFileId).distinct().collect(Collectors.toList());
|
||||
|
||||
if (fileIds.isEmpty()) {
|
||||
return TableDataInfo.build(new Page<>());
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<SysFile> lqw = buildQueryWrapper(bo);
|
||||
lqw.in(SysFile::getFileId, fileIds);
|
||||
Page<SysFileVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
||||
return TableDataInfo.build(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
|
||||
99
klp-ui/src/api/system/file.js
Normal file
99
klp-ui/src/api/system/file.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询文件列表
|
||||
export function listFile(query) {
|
||||
return request({
|
||||
url: '/system/file/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询文件详细
|
||||
export function getFile(fileId) {
|
||||
return request({
|
||||
url: '/system/file/' + fileId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增文件
|
||||
export function addFile(data) {
|
||||
return request({
|
||||
url: '/system/file',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改文件
|
||||
export function updateFile(data) {
|
||||
return request({
|
||||
url: '/system/file',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除文件
|
||||
export function delFile(fileIds) {
|
||||
return request({
|
||||
url: '/system/file/' + fileIds,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 导出文件列表
|
||||
export function exportFile(query) {
|
||||
return request({
|
||||
url: '/system/file/export',
|
||||
method: 'post',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询与我相关的文件
|
||||
export function listRelatedToMe(query) {
|
||||
return request({
|
||||
url: '/system/file/relatedToMe',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// ============ 文件可见用户关联 ============
|
||||
|
||||
// 查询可见用户列表
|
||||
export function listVisibleUser(query) {
|
||||
return request({
|
||||
url: '/system/fileVisibleUser/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 新增可见用户关联
|
||||
export function addVisibleUser(data) {
|
||||
return request({
|
||||
url: '/system/fileVisibleUser',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除可见用户关联
|
||||
export function delVisibleUser(visibleIds) {
|
||||
return request({
|
||||
url: '/system/fileVisibleUser/' + visibleIds,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 按文件ID查询可见用户列表
|
||||
export function listVisibleUserByFileId(fileId) {
|
||||
return request({
|
||||
url: '/system/fileVisibleUser/list',
|
||||
method: 'get',
|
||||
params: { fileId: fileId }
|
||||
})
|
||||
}
|
||||
735
klp-ui/src/views/system/file/index.vue
Normal file
735
klp-ui/src/views/system/file/index.vue
Normal file
@@ -0,0 +1,735 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 统计卡片 -->
|
||||
<el-row :gutter="16" class="stat-row" v-if="activeTab === 'all'">
|
||||
<el-col :span="6">
|
||||
<div class="stat-card">
|
||||
<div class="stat-num">{{ stats.totalFiles }}</div>
|
||||
<div class="stat-label">文件总数</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="stat-card public">
|
||||
<div class="stat-num">{{ stats.publicFiles }}</div>
|
||||
<div class="stat-label">公开文件</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="stat-card private">
|
||||
<div class="stat-num">{{ stats.privateFiles }}</div>
|
||||
<div class="stat-label">私有文件</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="stat-card">
|
||||
<div class="stat-num">{{ stats.myFiles }}</div>
|
||||
<div class="stat-label">我上传的</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- Tab 切换 -->
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="所有文件" name="all"></el-tab-pane>
|
||||
<el-tab-pane label="我的文件" name="my"></el-tab-pane>
|
||||
<el-tab-pane label="共享文件" name="share"></el-tab-pane>
|
||||
<el-tab-pane label="与我相关" name="related"></el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
|
||||
<el-form-item label="文件名称" prop="fileName">
|
||||
<el-input
|
||||
v-model="queryParams.fileName"
|
||||
placeholder="请输入文件名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单编号" prop="orderNo">
|
||||
<el-input
|
||||
v-model="queryParams.orderNo"
|
||||
placeholder="请输入订单编号"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="dept">
|
||||
<el-input
|
||||
v-model="queryParams.dept"
|
||||
placeholder="请输入部门"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件类型" prop="fileType">
|
||||
<el-select
|
||||
v-model="queryParams.fileType"
|
||||
placeholder="请选择文件类型"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dict.type.sys_file_type"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="可见范围" prop="scopeType" v-if="activeTab !== 'share' && activeTab !== 'related'">
|
||||
<el-select
|
||||
v-model="queryParams.scopeType"
|
||||
placeholder="请选择可见范围"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option label="公开" :value="1" />
|
||||
<el-option label="私有" :value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传时间">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
style="width: 240px"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="['00:00:00', '23:59:59']"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5" v-if="activeTab === 'my' || activeTab === 'all'">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
>上传文件</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="activeTab === 'my' || activeTab === 'all'">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 文件列表表格 -->
|
||||
<KLPTable v-loading="loading" :data="fileList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" v-if="activeTab === 'my' || activeTab === 'all'" />
|
||||
<el-table-column label="文件名称" align="center" prop="fileName" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="handlePreview(scope.row)">{{ scope.row.fileName }}</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件类型" align="center" prop="fileType">
|
||||
<template slot-scope="scope">
|
||||
<dict-tag :options="dict.type.sys_file_type" :value="scope.row.fileType"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件大小" align="center" prop="fileSize">
|
||||
<template slot-scope="scope">
|
||||
{{ formatFileSize(scope.row.fileSize) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="订单编号" align="center" prop="orderNo" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="所属部门" align="center" prop="dept" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="可见范围" align="center" prop="scopeType">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.scopeType === 1 ? 'success' : 'warning'" size="small">
|
||||
{{ scope.row.scopeType === 1 ? '公开' : '私有' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传人" align="center" prop="createBy" />
|
||||
<el-table-column label="上传时间" align="center" prop="createTime" width="160">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" align="center" width="220" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-view"
|
||||
@click="handlePreview(scope.row)"
|
||||
>预览</el-button>
|
||||
<el-button
|
||||
v-if="canEdit(scope.row)"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
v-if="canEdit(scope.row)"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</KLPTable>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 上传/编辑对话框 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="open" width="650px" append-to-body @close="handleDialogClose">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="文件名称" prop="fileName">
|
||||
<el-input v-model="form.fileName" placeholder="请输入文件名称" :disabled="isEdit" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上传文件" v-if="!isEdit">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:file-list="uploadFileList"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:auto-upload="false"
|
||||
:limit="1"
|
||||
class="upload-demo"
|
||||
drag
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击选取</em></div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单编号" prop="orderNo">
|
||||
<el-input v-model="form.orderNo" placeholder="请输入订单编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="所属部门" prop="dept">
|
||||
<el-input v-model="form.dept" placeholder="请输入所属部门" />
|
||||
</el-form-item>
|
||||
<el-form-item label="文件类型" prop="fileType">
|
||||
<el-select v-model="form.fileType" placeholder="请选择文件类型" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in dict.type.sys_file_type"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="可见范围" prop="scopeType">
|
||||
<el-radio-group v-model="form.scopeType" @change="handleScopeChange">
|
||||
<el-radio :label="1">公开(所有人可见)</el-radio>
|
||||
<el-radio :label="2">私有(指定用户可见)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="可见用户" v-if="form.scopeType === 2">
|
||||
<user-select
|
||||
v-model="form.visibleUsers"
|
||||
:multiple="true"
|
||||
placeholder="请选择可见用户"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="3" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 文件预览对话框 -->
|
||||
<el-dialog :title="previewTitle" :visible.sync="previewVisible" width="80%" append-to-body>
|
||||
<div v-if="previewFile" class="file-preview-container">
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="文件名称">{{ previewFile.fileName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件类型">
|
||||
<dict-tag :options="dict.type.sys_file_type" :value="previewFile.fileType"/>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="文件大小">{{ formatFileSize(previewFile.fileSize) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="文件后缀">{{ previewFile.suffix }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单编号">{{ previewFile.orderNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属部门">{{ previewFile.dept || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="可见范围">
|
||||
<el-tag :type="previewFile.scopeType === 1 ? 'success' : 'warning'" size="small">
|
||||
{{ previewFile.scopeType === 1 ? '公开' : '私有' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="上传人">{{ previewFile.createBy }}</el-descriptions-item>
|
||||
<el-descriptions-item label="上传时间">{{ parseTime(previewFile.createTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="备注" :span="2">{{ previewFile.remark || '-' }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="previewFile.filePath" style="margin-top: 16px;">
|
||||
<el-button type="primary" size="small" @click="downloadFile(previewFile)">下载文件</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listFile, getFile, addFile, updateFile, delFile, exportFile, listVisibleUser, addVisibleUser, delVisibleUser, listVisibleUserByFileId, listRelatedToMe } from '@/api/system/file'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import UserSelect from '@/components/KLPService/UserSelect/index'
|
||||
|
||||
export default {
|
||||
name: 'SysFile',
|
||||
dicts: ['sys_file_type'],
|
||||
components: {
|
||||
UserSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 当前激活tab
|
||||
activeTab: 'all',
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 文件列表
|
||||
fileList: [],
|
||||
// 弹出层标题
|
||||
dialogTitle: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否编辑
|
||||
isEdit: false,
|
||||
// 日期范围
|
||||
dateRange: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
fileName: undefined,
|
||||
orderNo: undefined,
|
||||
dept: undefined,
|
||||
fileType: undefined,
|
||||
scopeType: undefined
|
||||
},
|
||||
// 表单
|
||||
form: {
|
||||
fileId: undefined,
|
||||
fileName: undefined,
|
||||
filePath: undefined,
|
||||
fileSize: undefined,
|
||||
suffix: undefined,
|
||||
orderNo: undefined,
|
||||
dept: undefined,
|
||||
fileType: undefined,
|
||||
scopeType: 1,
|
||||
visibleUsers: [],
|
||||
remark: undefined
|
||||
},
|
||||
// 可见用户原始数据(编辑时回显)
|
||||
originalVisibleUsers: [],
|
||||
// 表单校验
|
||||
rules: {
|
||||
fileName: [
|
||||
{ required: true, message: '文件名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
fileType: [
|
||||
{ required: true, message: '请选择文件类型', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
// 统计
|
||||
stats: {
|
||||
totalFiles: 0,
|
||||
publicFiles: 0,
|
||||
privateFiles: 0,
|
||||
myFiles: 0
|
||||
},
|
||||
// 上传相关
|
||||
uploadUrl: process.env.VUE_APP_BASE_API + '/system/oss/upload',
|
||||
uploadHeaders: {
|
||||
Authorization: 'Bearer ' + getToken()
|
||||
},
|
||||
uploadFileList: [],
|
||||
// 预览
|
||||
previewVisible: false,
|
||||
previewTitle: '',
|
||||
previewFile: null
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
/** 切换tab */
|
||||
handleTabClick(tab) {
|
||||
this.resetQuery()
|
||||
},
|
||||
/** 查询文件列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
const params = this.addDateRange(this.queryParams, this.dateRange)
|
||||
// 根据tab设置额外参数
|
||||
if (this.activeTab === 'my') {
|
||||
params.createBy = this.$store.getters.name
|
||||
} else if (this.activeTab === 'share') {
|
||||
params.scopeType = 1
|
||||
}
|
||||
|
||||
// 根据tab选择不同的API
|
||||
let request
|
||||
if (this.activeTab === 'related') {
|
||||
request = listRelatedToMe(params)
|
||||
} else {
|
||||
request = listFile(params)
|
||||
}
|
||||
|
||||
request.then(response => {
|
||||
this.fileList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
// 加载统计数据
|
||||
if (this.activeTab === 'all') {
|
||||
this.loadStats()
|
||||
}
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
/** 加载统计数据 */
|
||||
loadStats() {
|
||||
// 获取所有公开文件数量
|
||||
listFile({ pageNum: 1, pageSize: 1, scopeType: 1 }).then(r => { this.stats.publicFiles = r.total })
|
||||
// 获取所有私有文件数量
|
||||
listFile({ pageNum: 1, pageSize: 1, scopeType: 2 }).then(r => { this.stats.privateFiles = r.total })
|
||||
// 我上传的
|
||||
listFile({ pageNum: 1, pageSize: 1, createBy: this.$store.getters.name }).then(r => { this.stats.myFiles = r.total })
|
||||
// 总计
|
||||
listFile({ pageNum: 1, pageSize: 1 }).then(r => { this.stats.totalFiles = r.total })
|
||||
},
|
||||
/** 格式化文件大小 */
|
||||
formatFileSize(size) {
|
||||
if (!size) return '0 B'
|
||||
if (size < 1024) return size + ' B'
|
||||
if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB'
|
||||
return (size / 1024 / 1024).toFixed(2) + ' MB'
|
||||
},
|
||||
/** 是否可编辑 */
|
||||
canEdit(row) {
|
||||
if (this.activeTab === 'related') return false
|
||||
if (this.activeTab === 'share') return false
|
||||
// 我的文件tab 或 所有文件tab中属于当前用户的
|
||||
return row.createBy === this.$store.getters.name
|
||||
},
|
||||
/** 取消按钮 */
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
/** 对话框关闭回调 */
|
||||
handleDialogClose() {
|
||||
this.reset()
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
fileId: undefined,
|
||||
fileName: undefined,
|
||||
filePath: undefined,
|
||||
fileSize: undefined,
|
||||
suffix: undefined,
|
||||
orderNo: undefined,
|
||||
dept: undefined,
|
||||
fileType: undefined,
|
||||
scopeType: 1,
|
||||
visibleUsers: [],
|
||||
remark: undefined
|
||||
}
|
||||
this.uploadFileList = []
|
||||
this.originalVisibleUsers = []
|
||||
this.isEdit = false
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 可见范围切换 */
|
||||
handleScopeChange(val) {
|
||||
if (val === 1) {
|
||||
this.form.visibleUsers = []
|
||||
}
|
||||
},
|
||||
/** 搜索按钮 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮 */
|
||||
resetQuery() {
|
||||
this.dateRange = []
|
||||
this.resetForm('queryForm')
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
fileName: undefined,
|
||||
orderNo: undefined,
|
||||
dept: undefined,
|
||||
fileType: undefined,
|
||||
scopeType: undefined
|
||||
}
|
||||
this.handleQuery()
|
||||
},
|
||||
/** 多选框 */
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.fileId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增/上传 */
|
||||
handleAdd() {
|
||||
this.reset()
|
||||
this.isEdit = false
|
||||
this.open = true
|
||||
this.dialogTitle = '上传文件'
|
||||
},
|
||||
/** 修改 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
this.isEdit = true
|
||||
const fileId = row.fileId || this.ids[0]
|
||||
getFile(fileId).then(response => {
|
||||
const data = response.data
|
||||
this.form = {
|
||||
fileId: data.fileId,
|
||||
fileName: data.fileName,
|
||||
filePath: data.filePath,
|
||||
fileSize: data.fileSize,
|
||||
suffix: data.suffix,
|
||||
orderNo: data.orderNo,
|
||||
dept: data.dept,
|
||||
fileType: data.fileType,
|
||||
scopeType: data.scopeType,
|
||||
visibleUsers: [],
|
||||
remark: data.remark
|
||||
}
|
||||
// 如果是私有文件,加载可见用户
|
||||
if (data.scopeType === 2) {
|
||||
listVisibleUserByFileId(fileId).then(res => {
|
||||
const rows = res.rows || []
|
||||
this.form.visibleUsers = rows.map(r => r.userId)
|
||||
this.originalVisibleUsers = [...this.form.visibleUsers]
|
||||
})
|
||||
}
|
||||
this.open = true
|
||||
this.dialogTitle = '编辑文件'
|
||||
})
|
||||
},
|
||||
/** 上传前校验 */
|
||||
handleBeforeUpload(file) {
|
||||
// 自动设置文件名
|
||||
if (!this.form.fileName) {
|
||||
this.form.fileName = file.name
|
||||
}
|
||||
const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase()
|
||||
this.form.suffix = ext
|
||||
this.form.fileSize = file.size
|
||||
},
|
||||
/** 上传成功 */
|
||||
handleUploadSuccess(response, file, fileList) {
|
||||
if (response.code === 200) {
|
||||
this.form.filePath = response.data.url
|
||||
this.form.fileName = this.form.fileName || response.data.fileName
|
||||
this.$modal.msgSuccess('文件上传成功')
|
||||
// 自动提交表单
|
||||
this.doSubmit()
|
||||
} else {
|
||||
this.$modal.msgError(response.msg || '上传失败')
|
||||
}
|
||||
},
|
||||
/** 上传失败 */
|
||||
handleUploadError(err, file, fileList) {
|
||||
this.$modal.msgError('文件上传失败')
|
||||
},
|
||||
/** 提交表单 */
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.isEdit) {
|
||||
// 编辑模式直接提交
|
||||
this.doSubmit()
|
||||
} else {
|
||||
// 新增模式,先上传文件
|
||||
if (this.$refs.upload && this.$refs.upload.uploadFiles.length > 0) {
|
||||
this.$refs.upload.submit()
|
||||
} else {
|
||||
this.$modal.msgWarning('请选择要上传的文件')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 执行提交 */
|
||||
doSubmit() {
|
||||
const data = { ...this.form }
|
||||
const visibleUsers = data.visibleUsers
|
||||
delete data.visibleUsers
|
||||
|
||||
if (data.fileId) {
|
||||
// 编辑模式
|
||||
updateFile(data).then(response => {
|
||||
this.saveVisibleUsers(data.fileId, visibleUsers)
|
||||
this.$modal.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
}).catch(() => {})
|
||||
} else {
|
||||
// 新增模式
|
||||
addFile(data).then(response => {
|
||||
const newFileId = response.data
|
||||
if (newFileId && visibleUsers && visibleUsers.length > 0) {
|
||||
this.saveVisibleUsers(newFileId, visibleUsers)
|
||||
}
|
||||
this.$modal.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
}).catch(() => {})
|
||||
}
|
||||
},
|
||||
/** 保存可见用户 */
|
||||
saveVisibleUsers(fileId, visibleUsers) {
|
||||
if (!visibleUsers || visibleUsers.length === 0) {
|
||||
// 删除所有可见用户
|
||||
if (this.originalVisibleUsers.length > 0) {
|
||||
delVisibleUser(this.originalVisibleUsers.join(','))
|
||||
}
|
||||
return
|
||||
}
|
||||
// 新增的
|
||||
const toAdd = visibleUsers.filter(u => !this.originalVisibleUsers.includes(u))
|
||||
// 删除的
|
||||
const toDel = this.originalVisibleUsers.filter(u => !visibleUsers.includes(u))
|
||||
|
||||
// 删除
|
||||
if (toDel.length > 0) {
|
||||
// 需要先查出visibleId
|
||||
listVisibleUserByFileId(fileId).then(res => {
|
||||
const rows = res.rows || []
|
||||
const delIds = rows.filter(r => toDel.includes(r.userId)).map(r => r.visibleId)
|
||||
if (delIds.length > 0) {
|
||||
delVisibleUser(delIds.join(','))
|
||||
}
|
||||
})
|
||||
}
|
||||
// 新增
|
||||
toAdd.forEach(userId => {
|
||||
addVisibleUser({ fileId, userId })
|
||||
})
|
||||
},
|
||||
/** 删除 */
|
||||
handleDelete(row) {
|
||||
const fileIds = row.fileId || this.ids.join(',')
|
||||
this.$modal.confirm('是否确认删除所选文件?').then(() => {
|
||||
return delFile(fileIds)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.$modal.msgSuccess('删除成功')
|
||||
}).catch(() => {})
|
||||
},
|
||||
/** 导出 */
|
||||
handleExport() {
|
||||
this.download('system/file/export', {
|
||||
...this.queryParams
|
||||
}, `file_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
/** 预览 */
|
||||
handlePreview(row) {
|
||||
this.previewFile = row
|
||||
this.previewTitle = '文件详情 - ' + row.fileName
|
||||
this.previewVisible = true
|
||||
},
|
||||
/** 下载文件 */
|
||||
downloadFile(row) {
|
||||
if (row.filePath) {
|
||||
window.open(row.filePath, '_blank')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.stat-row {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
|
||||
.stat-card.public {
|
||||
border-left-color: #67c23a;
|
||||
}
|
||||
|
||||
.stat-card.private {
|
||||
border-left-color: #e6a23c;
|
||||
}
|
||||
|
||||
.stat-num {
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: #303133;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.file-preview-container {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.upload-demo {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user