Просмотр исходного кода

!1404 文件管理功能,通过权限进行附件私有化和公开管理
Merge pull request !1404 from Mr先生/next

zuohuaijun 1 год назад
Родитель
Сommit
0fcf0fce9c

+ 8 - 1
Admin.NET/Admin.NET.Core/Entity/SysFile.cs

@@ -12,7 +12,7 @@ namespace Admin.NET.Core;
 [SugarTable(null, "系统文件表")]
 [SysTable]
 [SugarIndex("index_{table}_F", nameof(FileName), OrderByType.Asc)]
-public partial class SysFile : EntityBase
+public partial class SysFile : EntityBaseData
 {
     /// <summary>
     /// 提供者
@@ -101,4 +101,11 @@ public partial class SysFile : EntityBase
     [SugarColumn(ColumnDescription = "文件类别", Length = 128)]
     [MaxLength(128)]
     public string? FileType { get; set; }
+
+    /// <summary>
+    /// 是否公开
+    /// 如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否公开", DefaultValue = "false")]
+    public bool IsPublic { get; set; } = false;
 }

+ 24 - 0
Admin.NET/Admin.NET.Core/Service/File/Dto/FileInput.cs

@@ -18,6 +18,12 @@ public class FileInput : BaseIdInput
     /// </summary>
     public string FileType { get; set; }
 
+    /// <summary>
+    /// 是否公开
+    /// 如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+    /// </summary>
+    public bool IsPublic { get; set; }
+
     /// <summary>
     /// 文件Url
     /// </summary>
@@ -72,6 +78,12 @@ public class UploadFileFromBase64Input
     /// 文件类型
     /// </summary>
     public string FileType { get; set; }
+
+    /// <summary>
+    /// 是否公开
+    /// 如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+    /// </summary>
+    public bool IsPublic { get; set; }
 }
 
 /// <summary>
@@ -90,6 +102,12 @@ public class FileUploadInput
     /// </summary>
     public string FileType { get; set; }
 
+    /// <summary>
+    /// 是否公开
+    /// 如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+    /// </summary>
+    public bool IsPublic { get; set; }
+
     /// <summary>
     /// 文件路径
     /// </summary>
@@ -168,6 +186,12 @@ public class FileOutput
     /// </summary>
     public string FileType { get; set; }
 
+    /// <summary>
+    /// 是否公开
+    /// 如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+    /// </summary>
+    public bool IsPublic { get; set; }
+
     /// <summary>
     /// 上传人
     /// </summary>

+ 17 - 11
Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs

@@ -44,12 +44,16 @@ public class SysFileService : IDynamicApiController, ITransient
     [DisplayName("获取文件分页列表")]
     public async Task<SqlSugarPagedList<SysFile>> Page(PageFileInput input)
     {
-        return await _sysFileRep.AsQueryable()
-            .WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
-            .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
-                        u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
-            .OrderBy(u => u.CreateTime, OrderByType.Desc)
-            .ToPagedListAsync(input.Page, input.PageSize);
+        //获取所有公开附件
+        var publicList = _sysFileRep.AsQueryable().ClearFilter().Where(u => u.IsPublic == true);
+        //获取私有附件
+        var privateList = _sysFileRep.AsQueryable().Where(u => u.IsPublic == false);
+        //合并公开和私有附件并分页
+        return await _sysFileRep.Context.UnionAll(publicList, privateList).WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
+             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
+                         u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)
+             .OrderBy(u => u.CreateTime, OrderByType.Desc)
+             .ToPagedListAsync(input.Page, input.PageSize);
     }
 
     /// <summary>
@@ -60,7 +64,7 @@ public class SysFileService : IDynamicApiController, ITransient
     [DisplayName("上传文件")]
     public async Task<SysFile> UploadFile([FromForm] FileUploadInput input)
     {
-        return await HandleUploadFile(input.File, input.Path, fileType: input.FileType);
+        return await HandleUploadFile(input.File, input.Path, fileType: input.FileType, isPublic: input.IsPublic);
     }
 
     /// <summary>
@@ -84,7 +88,7 @@ public class SysFileService : IDynamicApiController, ITransient
             Headers = new HeaderDictionary(),
             ContentType = input.ContentType
         };
-        return await UploadFile(new FileUploadInput { File = formFile, Path = input.Path, FileType = input.FileType });
+        return await UploadFile(new FileUploadInput { File = formFile, Path = input.Path, FileType = input.FileType, IsPublic = input.IsPublic });
     }
 
     /// <summary>
@@ -265,7 +269,7 @@ public class SysFileService : IDynamicApiController, ITransient
         var isExist = await _sysFileRep.IsAnyAsync(u => u.Id == input.Id);
         if (!isExist) throw Oops.Oh(ErrorCodeEnum.D8000);
 
-        await _sysFileRep.UpdateAsync(u => new SysFile() { FileName = input.FileName, FileType = input.FileType }, u => u.Id == input.Id);
+        await _sysFileRep.UpdateAsync(u => new SysFile() { FileName = input.FileName, FileType = input.FileType, IsPublic = input.IsPublic }, u => u.Id == input.Id);
     }
 
     /// <summary>
@@ -287,8 +291,9 @@ public class SysFileService : IDynamicApiController, ITransient
     /// <param name="savePath">路径</param>
     /// <param name="allowSuffix">允许格式:.jpg.png.gif.tif.bmp</param>
     /// <param name="fileType">类型</param>
+    /// <param name="isPublic">是否公开</param>
     /// <returns></returns>
-    private async Task<SysFile> HandleUploadFile(IFormFile file, string savePath, string allowSuffix = "", string fileType = "")
+    private async Task<SysFile> HandleUploadFile(IFormFile file, string savePath, string allowSuffix = "", string fileType = "", bool isPublic = false)
     {
         if (file == null) throw Oops.Oh(ErrorCodeEnum.D8000);
 
@@ -352,7 +357,8 @@ public class SysFileService : IDynamicApiController, ITransient
             SizeKb = sizeKb,
             FilePath = path,
             FileMd5 = fileMd5,
-            FileType = fileType
+            FileType = fileType,
+            IsPublic = isPublic,
         };
 
         var finalName = newFile.Id + suffix; // 文件最终名称

+ 30 - 14
Web/src/api-services/apis/sys-file-api.ts

@@ -183,11 +183,12 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
          * @param {number} id 主键Id
          * @param {string} [fileName] 文件名称
          * @param {string} [fileType] 文件类型
+         * @param {boolean} [isPublic] 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
          * @param {string} [url] 文件Url
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysFileFileGet: async (id: number, fileName?: string, fileType?: string, url?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysFileFileGet: async (id: number, fileName?: string, fileType?: string, isPublic?: boolean, url?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             // verify required parameter 'id' is not null or undefined
             if (id === null || id === undefined) {
                 throw new RequiredError('id','Required parameter id was null or undefined when calling apiSysFileFileGet.');
@@ -220,6 +221,10 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
                 localVarQueryParameter['FileType'] = fileType;
             }
 
+            if (isPublic !== undefined) {
+                localVarQueryParameter['IsPublic'] = isPublic;
+            }
+
             if (url !== undefined) {
                 localVarQueryParameter['Url'] = url;
             }
@@ -557,11 +562,12 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
          * @summary 上传文件 🔖
          * @param {Blob} [file] 
          * @param {string} [fileType] 
+         * @param {boolean} [isPublic] 
          * @param {string} [path] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysFileUploadFilePostForm: async (file?: Blob, fileType?: string, path?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysFileUploadFilePostForm: async (file?: Blob, fileType?: string, isPublic?: boolean, path?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             const localVarPath = `/api/sysFile/uploadFile`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@@ -592,6 +598,10 @@ export const SysFileApiAxiosParamCreator = function (configuration?: Configurati
                 localVarFormParams.append('FileType', fileType as any);
             }
 
+            if (isPublic !== undefined) { 
+                localVarFormParams.append('IsPublic', isPublic as any);
+            }
+
             if (path !== undefined) { 
                 localVarFormParams.append('Path', path as any);
             }
@@ -776,12 +786,13 @@ export const SysFileApiFp = function(configuration?: Configuration) {
          * @param {number} id 主键Id
          * @param {string} [fileName] 文件名称
          * @param {string} [fileType] 文件类型
+         * @param {boolean} [isPublic] 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
          * @param {string} [url] 文件Url
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, url?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysFile>>> {
-            const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileFileGet(id, fileName, fileType, url, options);
+        async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, isPublic?: boolean, url?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysFile>>> {
+            const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileFileGet(id, fileName, fileType, isPublic, url, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -879,12 +890,13 @@ export const SysFileApiFp = function(configuration?: Configuration) {
          * @summary 上传文件 🔖
          * @param {Blob} [file] 
          * @param {string} [fileType] 
+         * @param {boolean} [isPublic] 
          * @param {string} [path] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysFile>>> {
-            const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileUploadFilePostForm(file, fileType, path, options);
+        async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, isPublic?: boolean, path?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSysFile>>> {
+            const localVarAxiosArgs = await SysFileApiAxiosParamCreator(configuration).apiSysFileUploadFilePostForm(file, fileType, isPublic, path, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -963,12 +975,13 @@ export const SysFileApiFactory = function (configuration?: Configuration, basePa
          * @param {number} id 主键Id
          * @param {string} [fileName] 文件名称
          * @param {string} [fileType] 文件类型
+         * @param {boolean} [isPublic] 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
          * @param {string} [url] 文件Url
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, url?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysFile>> {
-            return SysFileApiFp(configuration).apiSysFileFileGet(id, fileName, fileType, url, options).then((request) => request(axios, basePath));
+        async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, isPublic?: boolean, url?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysFile>> {
+            return SysFileApiFp(configuration).apiSysFileFileGet(id, fileName, fileType, isPublic, url, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -1038,12 +1051,13 @@ export const SysFileApiFactory = function (configuration?: Configuration, basePa
          * @summary 上传文件 🔖
          * @param {Blob} [file] 
          * @param {string} [fileType] 
+         * @param {boolean} [isPublic] 
          * @param {string} [path] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysFile>> {
-            return SysFileApiFp(configuration).apiSysFileUploadFilePostForm(file, fileType, path, options).then((request) => request(axios, basePath));
+        async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, isPublic?: boolean, path?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSysFile>> {
+            return SysFileApiFp(configuration).apiSysFileUploadFilePostForm(file, fileType, isPublic, path, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -1114,13 +1128,14 @@ export class SysFileApi extends BaseAPI {
      * @param {number} id 主键Id
      * @param {string} [fileName] 文件名称
      * @param {string} [fileType] 文件类型
+     * @param {boolean} [isPublic] 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
      * @param {string} [url] 文件Url
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysFileApi
      */
-    public async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, url?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysFile>> {
-        return SysFileApiFp(this.configuration).apiSysFileFileGet(id, fileName, fileType, url, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysFileFileGet(id: number, fileName?: string, fileType?: string, isPublic?: boolean, url?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysFile>> {
+        return SysFileApiFp(this.configuration).apiSysFileFileGet(id, fileName, fileType, isPublic, url, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
@@ -1196,13 +1211,14 @@ export class SysFileApi extends BaseAPI {
      * @summary 上传文件 🔖
      * @param {Blob} [file] 
      * @param {string} [fileType] 
+     * @param {boolean} [isPublic] 
      * @param {string} [path] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysFileApi
      */
-    public async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, path?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysFile>> {
-        return SysFileApiFp(this.configuration).apiSysFileUploadFilePostForm(file, fileType, path, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysFileUploadFilePostForm(file?: Blob, fileType?: string, isPublic?: boolean, path?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSysFile>> {
+        return SysFileApiFp(this.configuration).apiSysFileUploadFilePostForm(file, fileType, isPublic, path, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 8 - 0
Web/src/api-services/models/file-input.ts

@@ -44,6 +44,14 @@ export interface FileInput {
      */
     fileType?: string | null;
 
+    /**
+     * 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+     *
+     * @type {boolean}
+     * @memberof FileInput
+     */
+    isPublic?: boolean;
+
     /**
      * 文件Url
      *

+ 8 - 0
Web/src/api-services/models/file-output.ts

@@ -76,6 +76,14 @@ export interface FileOutput {
      */
     fileType?: string | null;
 
+    /**
+     * 是否公开  如果设置true,所有人都可以查看,默认只有自己或有权限的人可以查看
+     *
+     * @type {boolean}
+     * @memberof FileOutput
+     */
+    isPublic?: boolean;
+
     /**
      * 上传人
      *

+ 9 - 1
Web/src/views/system/file/component/editSysfile.vue

@@ -1,6 +1,6 @@
 <template>
 	<div class="sys-file-container">
-		<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="500px">
+		<el-dialog v-model="state.isShowDialog" draggable overflow destroy-on-close width="500px">
 			<template #header>
 				<div style="color: #fff">
 					<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
@@ -24,6 +24,14 @@
 							</el-select>
 						</el-form-item>
 					</el-col>
+					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
+						<el-form-item label="是否公开">
+							<el-radio-group v-model="state.ruleForm.isPublic">
+								<el-radio :value="false">否</el-radio>
+								<el-radio :value="true">是</el-radio>
+							</el-radio-group>
+						</el-form-item>
+					</el-col>
 				</el-row>
 			</el-form>
 			<template #footer>

+ 14 - 2
Web/src/views/system/file/index.vue

@@ -53,6 +53,12 @@
 				<el-table-column prop="bucketName" label="存储位置" align="center" show-overflow-tooltip />
 				<el-table-column prop="id" label="存储标识" align="center" show-overflow-tooltip />
 				<el-table-column prop="fileType" label="文件类型" min-width="100" header-align="center" show-overflow-tooltip />
+				<el-table-column prop="isPublic" label="是否公开" min-width="100" header-align="center" show-overflow-tooltip >
+                    <template #default="scope">
+						<el-tag v-if="scope.row.isPublic === true" type="success">是</el-tag>
+							<el-tag v-else type="danger">否</el-tag>
+					</template>
+				</el-table-column>
 				<el-table-column type="relationName" label="关联对象名称" min-width="150" align="center" />
 				<el-table-column type="relationId" label="关联对象Id" align="center" />
 				<el-table-column type="belongId" label="所属Id" align="center" />
@@ -95,7 +101,11 @@
 					<el-option label="相关文件" value="相关文件" />
 					<el-option label="归档文件" value="归档文件" />
 				</el-select>
-
+                是否公开:
+				<el-radio-group  v-model="state.isPublic">
+					<el-radio :value="false">否</el-radio>
+					<el-radio :value="true">是</el-radio>
+				</el-radio-group>
 				<el-upload ref="uploadRef" drag :auto-upload="false" :limit="1" :file-list="state.fileList" action="" :on-change="handleChange" accept=".jpg,.png,.bmp,.gif,.txt,.pdf,.xlsx,.docx">
 					<el-icon class="el-icon--upload">
 						<ele-UploadFilled />
@@ -173,6 +183,7 @@ const state = reactive({
 	pdfUrl: '',
 	fileName: '',
 	fileType: '',
+    isPublic:false,
 	previewList: [] as string[],
 });
 
@@ -205,6 +216,7 @@ const resetQuery = () => {
 const openUploadDialog = () => {
 	state.fileList = [];
 	state.dialogUploadVisible = true;
+    state.isPublic=false;
 };
 
 // 通过onChanne方法获得文件列表
@@ -215,7 +227,7 @@ const handleChange = (file: any, fileList: []) => {
 // 上传
 const uploadFile = async () => {
 	if (state.fileList.length < 1) return;
-	await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, undefined);
+	await getAPI(SysFileApi).apiSysFileUploadFilePostForm(state.fileList[0].raw, state.fileType, state.isPublic, undefined);
 	handleQuery();
 	ElMessage.success('上传成功');
 	state.dialogUploadVisible = false;