midway-fatcms 0.0.1-beta.70 → 0.0.1-beta.71

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,7 +111,7 @@ exports.default = (appInfo) => {
111
111
  fileSize: '20mb',
112
112
  limit: '20mb',
113
113
  // whitelist: string[],文件扩展名白名单
114
- whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.zip', '.xlsx', '.docx', '.pptx', '.txt', '.md', '.json', '.js', '.cjs', '.ejs', '.jsx', '.css', '.java', '.ts', '.tsx', '.less', '.scss', '.html', '.ttf', '.map', '.svg'],
114
+ whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.zip', '.rar', '.xlsx', '.docx', '.pptx', '.txt', '.md', '.json', '.js', '.cjs', '.ejs', '.jsx', '.css', '.java', '.ts', '.tsx', '.less', '.scss', '.html', '.ttf', '.map', '.svg'],
115
115
  // tmpdir: string,上传的文件临时存储路径
116
116
  tmpdir: (0, path_1.join)((0, os_1.tmpdir)(), 'fatcms-upload-files'),
117
117
  // cleanTimeout: number,上传的文件在临时目录中多久之后自动删除,默认为 5 分钟
@@ -25,4 +25,8 @@ export declare class FileController extends BaseApiController {
25
25
  * @param streaming 是否直接返回流,默认返回 302 跳转
26
26
  */
27
27
  downloadFile(byMethod: string, fileKey: string): Promise<void>;
28
+ /**
29
+ * 获取用户本人上传的文件列表
30
+ */
31
+ getCurrentUserFiles(): Promise<CommonResult>;
28
32
  }
@@ -80,12 +80,13 @@ let FileController = class FileController extends BaseApiController_1.BaseApiCon
80
80
  const isThumbnail = this.ctx.path.startsWith(`${FileCenterService_1.PATH_PREFIX}/get/thumbnail/`);
81
81
  const isPreview = this.ctx.path.startsWith(`${FileCenterService_1.PATH_PREFIX}/get/preview/`) || isTrue(preview);
82
82
  const isStreaming = isTrue(streaming);
83
- if (isThumbnail && (0, FileCenterService_1.isImageFile)(fileKey) && !process) {
83
+ const fileInfo = await this.fileCenterService.getFileInfo(fileKey);
84
+ if (isThumbnail && (0, FileCenterService_1.isImageFile)(fileKey, fileInfo.file_type) && !process) {
84
85
  // x-oss-process=image/resize,w_200,p_10/quality,q_60
85
86
  process = 'image/resize,w_200'; //图片缩略图(小图片)
86
87
  }
87
88
  const isOutByStreaming = isStreaming || isPreview || isThumbnail;
88
- const result = await this.fileCenterService.downloadFile(fileKey, isOutByStreaming, process);
89
+ const result = await this.fileCenterService.downloadFile(fileInfo, isOutByStreaming, process);
89
90
  if (isOutByStreaming) {
90
91
  // 移除这些属性
91
92
  const headers = _.omitBy(result.res.headers, (_v, key) => {
@@ -104,6 +105,14 @@ let FileController = class FileController extends BaseApiController_1.BaseApiCon
104
105
  this.ctx.redirect(result.downloadURL);
105
106
  }
106
107
  }
108
+ /**
109
+ * 获取用户本人上传的文件列表
110
+ */
111
+ async getCurrentUserFiles() {
112
+ let { file_category } = (this.ctx.query || {});
113
+ const res = await this.fileCenterService.getCurrentUserFiles(file_category);
114
+ return common_dto_1.CommonResult.successRes(res);
115
+ }
107
116
  };
108
117
  __decorate([
109
118
  (0, core_1.Inject)(),
@@ -139,6 +148,12 @@ __decorate([
139
148
  __metadata("design:paramtypes", [String, String]),
140
149
  __metadata("design:returntype", Promise)
141
150
  ], FileController.prototype, "downloadFile", null);
151
+ __decorate([
152
+ (0, core_1.Get)('/getCurrentUserFiles', { middleware: [(0, permission_middleware_1.checkLogin)()] }),
153
+ __metadata("design:type", Function),
154
+ __metadata("design:paramtypes", []),
155
+ __metadata("design:returntype", Promise)
156
+ ], FileController.prototype, "getCurrentUserFiles", null);
142
157
  FileController = __decorate([
143
158
  (0, core_1.Controller)(FileCenterService_1.PATH_PREFIX)
144
159
  ], FileController);
@@ -4,7 +4,7 @@ import { SqlCfgModel } from './SqlCfgModel';
4
4
  import { Transaction } from './Transaction';
5
5
  import { ColumnRelation, ICrudProCfg, ILogger, IVisitor } from '../interfaces';
6
6
  import { IExecuteContextFunc } from './ExecuteContextFunc';
7
- import { ResModelFlexible } from './ResModel';
7
+ import { ResModelFlexible, ResModelPageQuery } from './ResModel';
8
8
  declare class ExecuteContext {
9
9
  private transaction;
10
10
  private logger;
@@ -30,6 +30,7 @@ declare class ExecuteContext {
30
30
  getResRows(): any[];
31
31
  setResModelItem(resName: string, data: any): void;
32
32
  getResModelItem(resName: string): any;
33
+ getResModelForQueryPage(): ResModelPageQuery;
33
34
  getResModelItemLodash(resName: string): any;
34
35
  setCfgModel(cfgModel: RequestCfgModel): void;
35
36
  getCfgModel(): RequestCfgModel;
@@ -60,6 +60,14 @@ class ExecuteContext {
60
60
  getResModelItem(resName) {
61
61
  return this.resModel[resName];
62
62
  }
63
+ getResModelForQueryPage() {
64
+ const rows = this.resModel['rows'];
65
+ const total_count = this.resModel['total_count'];
66
+ return {
67
+ rows: rows || [],
68
+ total_count: total_count || 0
69
+ };
70
+ }
63
71
  getResModelItemLodash(resName) {
64
72
  return _.get(this.resModel, resName);
65
73
  }
@@ -10,7 +10,11 @@ interface ResModelStandard {
10
10
  insert_affected?: ResModelAffected;
11
11
  update_affected?: ResModelAffected;
12
12
  }
13
+ interface ResModelPageQuery {
14
+ rows: any[];
15
+ total_count: number;
16
+ }
13
17
  declare type ResModelFlexible = ResModelStandard & {
14
18
  [key: string]: any;
15
19
  };
16
- export { ResModelAffected, ResModelStandard, ResModelFlexible };
20
+ export { ResModelAffected, ResModelStandard, ResModelFlexible, ResModelPageQuery };
@@ -50,6 +50,12 @@ export declare enum UploadCategoryType {
50
50
  file = "file",
51
51
  assets = "assets"
52
52
  }
53
+ export declare enum FileCategoryType {
54
+ image = "image",
55
+ office = "office",
56
+ zip = "zip",
57
+ others = "others"
58
+ }
53
59
  export declare class PermFunc {
54
60
  funcCode: string;
55
61
  funcName: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CacheNameEnum = exports.StdCrudExportInputParamsAppType = exports.FILE_GET_TYPES = exports.CTX_WORKBENCH_CODE = exports.CTX_VISITOR_ACCOUNT_TYPE = exports.CTX_VISITOR_NICKNAME = exports.CTX_VISITOR_AVATAR = exports.CTX_VISITOR_ID = exports.PermRole = exports.PermFunc = exports.UploadCategoryType = exports.AccessType = void 0;
3
+ exports.CacheNameEnum = exports.StdCrudExportInputParamsAppType = exports.FILE_GET_TYPES = exports.CTX_WORKBENCH_CODE = exports.CTX_VISITOR_ACCOUNT_TYPE = exports.CTX_VISITOR_NICKNAME = exports.CTX_VISITOR_AVATAR = exports.CTX_VISITOR_ID = exports.PermRole = exports.PermFunc = exports.FileCategoryType = exports.UploadCategoryType = exports.AccessType = void 0;
4
4
  var AccessType;
5
5
  (function (AccessType) {
6
6
  AccessType["owner"] = "owner";
@@ -12,6 +12,13 @@ var UploadCategoryType;
12
12
  UploadCategoryType["file"] = "file";
13
13
  UploadCategoryType["assets"] = "assets";
14
14
  })(UploadCategoryType = exports.UploadCategoryType || (exports.UploadCategoryType = {}));
15
+ var FileCategoryType;
16
+ (function (FileCategoryType) {
17
+ FileCategoryType["image"] = "image";
18
+ FileCategoryType["office"] = "office";
19
+ FileCategoryType["zip"] = "zip";
20
+ FileCategoryType["others"] = "others";
21
+ })(FileCategoryType = exports.FileCategoryType || (exports.FileCategoryType = {}));
15
22
  class PermFunc {
16
23
  constructor(funcCode, funcName) {
17
24
  this.funcName = funcName;
@@ -1,7 +1,25 @@
1
1
  import { Context } from '@midwayjs/koa';
2
- import { AccessType, UploadCategoryType } from '../models/bizmodels';
2
+ import { AccessType, FileCategoryType, IEntityCommonInfo, UploadCategoryType } from '../models/bizmodels';
3
3
  import { BaseService } from './base/BaseService';
4
- export declare function isImageFile(fileKey: string): boolean;
4
+ import { ResModelPageQuery } from "../libs/crud-pro/models/ResModel";
5
+ export declare function isImageFile(fileKey: string, mimeType: string): boolean;
6
+ export declare function isOfficeFile(fileKey: string, mimeType: string): boolean;
7
+ export declare function isZipFile(fileKey: string, mimeType: string): boolean;
8
+ export declare function getFileCategory(fileKey: string, mimeType: string): FileCategoryType;
9
+ interface IFileInfo extends IEntityCommonInfo {
10
+ file_key: string;
11
+ file_name: string;
12
+ file_size: number;
13
+ file_type: string;
14
+ file_suffix: string;
15
+ file_desc: string;
16
+ storage_path: string;
17
+ storage_url: string;
18
+ storage_engine: string;
19
+ access_type: string;
20
+ referer: string;
21
+ file_category: string;
22
+ }
5
23
  interface IUploadFileToOSSOptions {
6
24
  uploadCategoryType: UploadCategoryType;
7
25
  uploadPath: string;
@@ -29,15 +47,18 @@ export declare class FileCenterService extends BaseService {
29
47
  mimeType: any;
30
48
  name: any;
31
49
  url: any;
50
+ file_category: FileCategoryType;
32
51
  }>;
33
52
  deleteFile(fileKey: string): Promise<import("../libs/crud-pro/models/ExecuteContext").ExecuteContext>;
34
53
  private headFile;
35
- downloadFile(fileKey: string, streaming: boolean, process: string): Promise<any>;
54
+ getFileInfo(fileKey: string): Promise<IFileInfo>;
55
+ downloadFile(fileInfo: IFileInfo, streaming: boolean, process: string): Promise<any>;
36
56
  /**
37
57
  * 检查用户下载权限
38
58
  * @param fileInfo
39
59
  * @private
40
60
  */
41
61
  private checkAuthUserDownloadFile;
62
+ getCurrentUserFiles(file_category: FileCategoryType): Promise<ResModelPageQuery>;
42
63
  }
43
64
  export {};
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.FileCenterService = exports.toDownloadPaths = exports.PATH_PREFIX = exports.isImageFile = void 0;
12
+ exports.FileCenterService = exports.toDownloadPaths = exports.PATH_PREFIX = exports.getFileCategory = exports.isZipFile = exports.isOfficeFile = exports.isImageFile = void 0;
13
13
  const core_1 = require("@midwayjs/core");
14
14
  const mime = require("mime-types");
15
15
  const md5 = require("md5");
@@ -76,18 +76,45 @@ function getAssetsContentType(filename) {
76
76
  return 'application/octet-stream';
77
77
  }
78
78
  // JPG、PNG、BMP、GIF、WebP、TIFF
79
- function isImageFile(fileKey) {
80
- const fileKey1 = fileKey.toLowerCase();
81
- const suffix = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tiff'];
82
- for (let i = 0; i < suffix.length; i++) {
83
- const suffix1 = suffix[i];
84
- if (fileKey1.endsWith(suffix1)) {
85
- return true;
86
- }
87
- }
88
- return false;
79
+ function isImageFile(fileKey, mimeType) {
80
+ if (typeof mimeType === 'string' && mimeType.startsWith('image/'))
81
+ return true;
82
+ const fileKey2 = fileKey.toLowerCase();
83
+ const suffixList = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tiff'];
84
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
89
85
  }
90
86
  exports.isImageFile = isImageFile;
87
+ function isOfficeFile(fileKey, mimeType) {
88
+ if (typeof mimeType === 'string' &&
89
+ (mimeType.startsWith('application/vnd.openxmlformats-officedocument') ||
90
+ mimeType.startsWith('application/msword') ||
91
+ mimeType.startsWith('application/vnd.ms-'))) {
92
+ return true;
93
+ }
94
+ const fileKey2 = fileKey.toLowerCase();
95
+ const suffixList = ['.docx', '.xlsx', '.pptx', '.doc', '.xls', '.ppt', '.pdf'];
96
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
97
+ }
98
+ exports.isOfficeFile = isOfficeFile;
99
+ function isZipFile(fileKey, mimeType) {
100
+ const suffixList = ['.zip', '.7z', '.rar'];
101
+ const fileKey2 = fileKey.toLowerCase();
102
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
103
+ }
104
+ exports.isZipFile = isZipFile;
105
+ function getFileCategory(fileKey, mimeType) {
106
+ if (isImageFile(fileKey, mimeType)) {
107
+ return bizmodels_1.FileCategoryType.image;
108
+ }
109
+ if (isOfficeFile(fileKey, mimeType)) {
110
+ return bizmodels_1.FileCategoryType.office;
111
+ }
112
+ if (isZipFile(fileKey, mimeType)) {
113
+ return bizmodels_1.FileCategoryType.zip;
114
+ }
115
+ return bizmodels_1.FileCategoryType.others;
116
+ }
117
+ exports.getFileCategory = getFileCategory;
91
118
  class FileDB {
92
119
  constructor(curdMixService) {
93
120
  this.curdMixService = curdMixService;
@@ -145,6 +172,17 @@ class FileDB {
145
172
  };
146
173
  return await this.curdMixService.executeCrudByCfg({ condition: { id } }, cfgModel);
147
174
  }
175
+ async getFilePage(reqModel) {
176
+ const { SystemDbName, SystemDbType } = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
177
+ const cfgModel = {
178
+ sqlTable: 'sys_file',
179
+ sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
180
+ sqlDatabase: SystemDbName,
181
+ sqlDbType: SystemDbType,
182
+ };
183
+ const res = await this.curdMixService.executeCrudByCfg(reqModel, cfgModel);
184
+ return res.getResModelForQueryPage();
185
+ }
148
186
  }
149
187
  exports.PATH_PREFIX = '/ns/gw/file';
150
188
  function toDownloadPaths(origin, fileKey) {
@@ -239,6 +277,7 @@ let FileCenterService = class FileCenterService extends BaseService_1.BaseServic
239
277
  access_type: accessType,
240
278
  referer: referer,
241
279
  upload_origin: uploadOrigin,
280
+ file_category: getFileCategory(fileKey, file.mimeType)
242
281
  };
243
282
  if (isAssets) {
244
283
  await this.fileBD.saveAssetsLog(saveInfo);
@@ -256,6 +295,7 @@ let FileCenterService = class FileCenterService extends BaseService_1.BaseServic
256
295
  mimeType: file.mimeType,
257
296
  name: result.name,
258
297
  url: result.url,
298
+ file_category: saveInfo.file_category,
259
299
  };
260
300
  }
261
301
  async deleteFile(fileKey) {
@@ -279,8 +319,10 @@ let FileCenterService = class FileCenterService extends BaseService_1.BaseServic
279
319
  return false;
280
320
  }
281
321
  }
282
- async downloadFile(fileKey, streaming, process) {
283
- const fileInfo = await this.fileBD.getFileInfo(fileKey);
322
+ async getFileInfo(fileKey) {
323
+ return await this.fileBD.getFileInfo(fileKey);
324
+ }
325
+ async downloadFile(fileInfo, streaming, process) {
284
326
  if (!fileInfo || fileInfo.status !== 1) {
285
327
  throw new devops_1.BizException('文件不存在');
286
328
  }
@@ -336,6 +378,35 @@ let FileCenterService = class FileCenterService extends BaseService_1.BaseServic
336
378
  }
337
379
  return 'OK';
338
380
  }
381
+ async getCurrentUserFiles(file_category) {
382
+ const userSession = this.ctx.userSession;
383
+ if (!userSession.isLogin()) {
384
+ throw new devops_1.BizException('您当前未登录,您没有访问此文件的权限');
385
+ }
386
+ const sessionInfo = this.ctx.userSession.getSessionInfo();
387
+ const condition = {
388
+ created_by: sessionInfo.accountId,
389
+ status: 1
390
+ };
391
+ if (file_category) {
392
+ condition.file_category = file_category;
393
+ }
394
+ return await this.fileBD.getFilePage({
395
+ condition: condition,
396
+ columns: [
397
+ 'id',
398
+ 'file_key',
399
+ 'file_name',
400
+ 'file_size',
401
+ 'file_type',
402
+ 'file_suffix',
403
+ 'storage_path',
404
+ 'storage_url',
405
+ 'file_category',
406
+ 'created_at'
407
+ ]
408
+ });
409
+ }
339
410
  };
340
411
  __decorate([
341
412
  (0, core_1.Inject)(),
@@ -2,7 +2,7 @@ import { SqlDbType } from '../../libs/crud-pro/models/keys';
2
2
  import { IRequestModel } from '../../libs/crud-pro/interfaces';
3
3
  import { IRequestCfgModel2 } from '../../models/bizmodels';
4
4
  import { CrudPro } from '../../libs/crud-pro/CrudPro';
5
- import { ResModelAffected, ResModelStandard } from '../../libs/crud-pro/models/ResModel';
5
+ import { ResModelAffected, ResModelPageQuery, ResModelStandard } from '../../libs/crud-pro/models/ResModel';
6
6
  export declare class CrudProQuick {
7
7
  private readonly curdPro;
8
8
  private readonly sqlDbType;
@@ -34,7 +34,7 @@ export declare class CrudProQuick {
34
34
  * @returns 返回多条数据对象组成的数组
35
35
  */
36
36
  getList(reqJson: IRequestModel, sqlTable?: string): Promise<any[]>;
37
- getListPage(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelStandard>;
37
+ getListPage(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelPageQuery>;
38
38
  getTotalCount(reqJson: IRequestModel, sqlTable?: string): Promise<number>;
39
39
  insertObject(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelAffected>;
40
40
  updateObject(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelAffected>;
@@ -91,7 +91,7 @@ class CrudProQuick {
91
91
  sqlSimpleName: keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
92
92
  };
93
93
  const res = await this.executeCrudByCfg(reqJson, cfgModel);
94
- return res.getResModel(); // 因为它有2个返回值
94
+ return res.getResModelForQueryPage();
95
95
  }
96
96
  async getTotalCount(reqJson, sqlTable) {
97
97
  const cfgModel = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midway-fatcms",
3
- "version": "0.0.1-beta.70",
3
+ "version": "0.0.1-beta.71",
4
4
  "description": "This is a midway component sample",
5
5
  "main": "dist/index.js",
6
6
  "typings": "index.d.ts",
@@ -122,7 +122,7 @@ export default (appInfo: any) => {
122
122
  fileSize: '20mb',
123
123
  limit: '20mb',
124
124
  // whitelist: string[],文件扩展名白名单
125
- whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.zip', '.xlsx', '.docx', '.pptx', '.txt', '.md', '.json', '.js', '.cjs', '.ejs', '.jsx', '.css', '.java', '.ts', '.tsx', '.less', '.scss', '.html', '.ttf', '.map', '.svg'],
125
+ whitelist: ['.jpg', '.jpeg', '.png', '.gif', '.pdf', '.zip', '.rar', '.xlsx', '.docx', '.pptx', '.txt', '.md', '.json', '.js', '.cjs', '.ejs', '.jsx', '.css', '.java', '.ts', '.tsx', '.less', '.scss', '.html', '.ttf', '.map', '.svg'],
126
126
  // tmpdir: string,上传的文件临时存储路径
127
127
  tmpdir: join(tmpdir(), 'fatcms-upload-files'),
128
128
  // cleanTimeout: number,上传的文件在临时目录中多久之后自动删除,默认为 5 分钟
@@ -94,14 +94,16 @@ export class FileController extends BaseApiController {
94
94
  const isPreview = this.ctx.path.startsWith(`${PATH_PREFIX}/get/preview/`) || isTrue(preview);
95
95
  const isStreaming = isTrue(streaming);
96
96
 
97
- if (isThumbnail && isImageFile(fileKey) && !process) {
97
+ const fileInfo = await this.fileCenterService.getFileInfo(fileKey);
98
+
99
+ if (isThumbnail && isImageFile(fileKey, fileInfo.file_type) && !process) {
98
100
  // x-oss-process=image/resize,w_200,p_10/quality,q_60
99
101
  process = 'image/resize,w_200'; //图片缩略图(小图片)
100
102
  }
101
103
 
102
104
  const isOutByStreaming = isStreaming || isPreview || isThumbnail;
103
105
 
104
- const result = await this.fileCenterService.downloadFile(fileKey, isOutByStreaming, process);
106
+ const result = await this.fileCenterService.downloadFile(fileInfo, isOutByStreaming, process);
105
107
 
106
108
  if (isOutByStreaming) {
107
109
  // 移除这些属性
@@ -120,4 +122,17 @@ export class FileController extends BaseApiController {
120
122
  this.ctx.redirect(result.downloadURL);
121
123
  }
122
124
  }
125
+
126
+
127
+ /**
128
+ * 获取用户本人上传的文件列表
129
+ */
130
+ @Get('/getCurrentUserFiles', { middleware: [checkLogin()] })
131
+ public async getCurrentUserFiles(): Promise<CommonResult> {
132
+ let { file_category } = (this.ctx.query || {}) as any;
133
+ const res = await this.fileCenterService.getCurrentUserFiles(file_category);
134
+ return CommonResult.successRes(res);
135
+ }
136
+
137
+
123
138
  }
@@ -7,7 +7,7 @@ import { Transaction } from './Transaction';
7
7
  import { ColumnRelation, ICrudProCfg, ILogger, IVisitor } from '../interfaces';
8
8
  import { IExecuteContextFunc } from './ExecuteContextFunc';
9
9
  import { defaultCrudProCfg } from '../defaultConfigs';
10
- import { ResModelFlexible } from './ResModel';
10
+ import {ResModelFlexible, ResModelPageQuery} from './ResModel';
11
11
 
12
12
  class ExecuteContext {
13
13
  // 运行前设置的
@@ -82,6 +82,15 @@ class ExecuteContext {
82
82
  return this.resModel[resName];
83
83
  }
84
84
 
85
+ getResModelForQueryPage(): ResModelPageQuery {
86
+ const rows = this.resModel['rows'];
87
+ const total_count = this.resModel['total_count'];
88
+ return {
89
+ rows: rows || [],
90
+ total_count: total_count || 0
91
+ }
92
+ }
93
+
85
94
  getResModelItemLodash(resName: string): any {
86
95
  return _.get(this.resModel, resName);
87
96
  }
@@ -12,8 +12,13 @@ interface ResModelStandard {
12
12
  update_affected?: ResModelAffected;
13
13
  }
14
14
 
15
+ interface ResModelPageQuery {
16
+ rows: any[];
17
+ total_count: number;
18
+ }
19
+
15
20
  type ResModelFlexible = ResModelStandard & {
16
21
  [key: string]: any;
17
22
  };
18
23
 
19
- export { ResModelAffected, ResModelStandard, ResModelFlexible };
24
+ export { ResModelAffected, ResModelStandard, ResModelFlexible, ResModelPageQuery };
@@ -59,6 +59,13 @@ export enum UploadCategoryType {
59
59
  assets = 'assets', // 前端资源文件
60
60
  }
61
61
 
62
+ export enum FileCategoryType {
63
+ image='image',
64
+ office='office',
65
+ zip='zip',
66
+ others='others',
67
+ }
68
+
62
69
  export class PermFunc {
63
70
  public funcCode: string;
64
71
  public funcName: string;
@@ -1,16 +1,17 @@
1
- import { Provide, Inject } from '@midwayjs/core';
2
- import { Context } from '@midwayjs/koa';
1
+ import {Inject, Provide} from '@midwayjs/core';
2
+ import {Context} from '@midwayjs/koa';
3
3
  import * as mime from 'mime-types';
4
4
  import * as md5 from 'md5';
5
5
  import * as fs from 'fs';
6
6
  import * as util from 'util';
7
- import { BizException } from '@/models/devops';
8
- import { CurdMixService } from './curd/CurdMixService';
9
- import { KeysOfSimpleSQL, KeysOfValidators } from '@/libs/crud-pro/models/keys';
10
- import { AccessType, IEntityCommonInfo, UploadCategoryType } from '@/models/bizmodels';
11
- import { IRequestCfgModel } from '@/libs/crud-pro/interfaces';
12
- import { BaseService } from './base/BaseService';
13
- import { GLOBAL_STATIC_CONFIG } from '@/libs/global-config/global-config';
7
+ import {BizException} from '@/models/devops';
8
+ import {CurdMixService} from './curd/CurdMixService';
9
+ import {KeysOfSimpleSQL, KeysOfValidators} from '@/libs/crud-pro/models/keys';
10
+ import {AccessType, FileCategoryType, IEntityCommonInfo, UploadCategoryType} from '@/models/bizmodels';
11
+ import {IRequestCfgModel, IRequestModel} from '@/libs/crud-pro/interfaces';
12
+ import {BaseService} from './base/BaseService';
13
+ import {GLOBAL_STATIC_CONFIG} from '@/libs/global-config/global-config';
14
+ import {ResModelPageQuery} from "@/libs/crud-pro/models/ResModel";
14
15
 
15
16
  function getSuffix(s: string): string {
16
17
  if (s) {
@@ -72,18 +73,47 @@ function getAssetsContentType(filename: string): string {
72
73
  }
73
74
 
74
75
  // JPG、PNG、BMP、GIF、WebP、TIFF
75
- export function isImageFile(fileKey: string) {
76
- const fileKey1 = fileKey.toLowerCase();
77
- const suffix = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tiff'];
78
- for (let i = 0; i < suffix.length; i++) {
79
- const suffix1 = suffix[i];
80
- if (fileKey1.endsWith(suffix1)) {
81
- return true;
82
- }
76
+ export function isImageFile(fileKey: string, mimeType: string) {
77
+ if (typeof mimeType === 'string' && mimeType.startsWith('image/')) return true;
78
+ const fileKey2= fileKey.toLowerCase();
79
+ const suffixList = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tiff'];
80
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
81
+ }
82
+
83
+ export function isOfficeFile(fileKey: string, mimeType: string) {
84
+ if (typeof mimeType === 'string' &&
85
+ (mimeType.startsWith('application/vnd.openxmlformats-officedocument') ||
86
+ mimeType.startsWith('application/msword') ||
87
+ mimeType.startsWith('application/vnd.ms-'))) {
88
+ return true;
89
+ }
90
+ const fileKey2= fileKey.toLowerCase();
91
+ const suffixList = ['.docx', '.xlsx', '.pptx', '.doc', '.xls', '.ppt', '.pdf'];
92
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
93
+ }
94
+
95
+ export function isZipFile(fileKey: string, mimeType: string) {
96
+ const suffixList = ['.zip', '.7z', '.rar'];
97
+ const fileKey2= fileKey.toLowerCase();
98
+ return suffixList.some(suffix => fileKey2.endsWith(suffix));
99
+ }
100
+
101
+
102
+
103
+ export function getFileCategory(fileKey: string, mimeType: string):FileCategoryType{
104
+ if (isImageFile(fileKey, mimeType)){
105
+ return FileCategoryType.image;
83
106
  }
84
- return false;
107
+ if (isOfficeFile(fileKey, mimeType)){
108
+ return FileCategoryType.office;
109
+ }
110
+ if (isZipFile(fileKey, mimeType)){
111
+ return FileCategoryType.zip;
112
+ }
113
+ return FileCategoryType.others;
85
114
  }
86
115
 
116
+
87
117
  interface IFileInfo extends IEntityCommonInfo {
88
118
  file_key: string;
89
119
  file_name: string;
@@ -96,6 +126,7 @@ interface IFileInfo extends IEntityCommonInfo {
96
126
  storage_engine: string;
97
127
  access_type: string;
98
128
  referer: string;
129
+ file_category: string;
99
130
  }
100
131
 
101
132
  class FileDB {
@@ -167,6 +198,21 @@ class FileDB {
167
198
  };
168
199
  return await this.curdMixService.executeCrudByCfg({ condition: { id } }, cfgModel);
169
200
  }
201
+
202
+
203
+ public async getFilePage(reqModel: IRequestModel): Promise<ResModelPageQuery> {
204
+ const { SystemDbName, SystemDbType } = GLOBAL_STATIC_CONFIG.getConfig();
205
+ const cfgModel: IRequestCfgModel = {
206
+ sqlTable: 'sys_file',
207
+ sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
208
+ sqlDatabase: SystemDbName,
209
+ sqlDbType: SystemDbType,
210
+ };
211
+ const res = await this.curdMixService.executeCrudByCfg(reqModel, cfgModel);
212
+ return res.getResModelForQueryPage();
213
+ }
214
+
215
+
170
216
  }
171
217
 
172
218
  interface IUploadFileToOSSOptions {
@@ -284,6 +330,7 @@ export class FileCenterService extends BaseService {
284
330
  access_type: accessType,
285
331
  referer: referer,
286
332
  upload_origin: uploadOrigin,
333
+ file_category: getFileCategory(fileKey, file.mimeType)
287
334
  };
288
335
 
289
336
  if (isAssets) {
@@ -302,6 +349,7 @@ export class FileCenterService extends BaseService {
302
349
  mimeType: file.mimeType,
303
350
  name: result.name,
304
351
  url: result.url,
352
+ file_category: saveInfo.file_category,
305
353
  };
306
354
  }
307
355
 
@@ -328,8 +376,12 @@ export class FileCenterService extends BaseService {
328
376
  }
329
377
  }
330
378
 
331
- public async downloadFile(fileKey: string, streaming: boolean, process: string): Promise<any> {
332
- const fileInfo = await this.fileBD.getFileInfo(fileKey);
379
+ public async getFileInfo(fileKey: string): Promise<IFileInfo> {
380
+ return await this.fileBD.getFileInfo(fileKey);
381
+ }
382
+
383
+ public async downloadFile(fileInfo: IFileInfo, streaming: boolean, process: string): Promise<any> {
384
+
333
385
  if (!fileInfo || fileInfo.status !== 1) {
334
386
  throw new BizException('文件不存在');
335
387
  }
@@ -392,4 +444,40 @@ export class FileCenterService extends BaseService {
392
444
 
393
445
  return 'OK';
394
446
  }
447
+
448
+
449
+ public async getCurrentUserFiles(file_category: FileCategoryType): Promise<ResModelPageQuery> {
450
+ const userSession = this.ctx.userSession;
451
+ if (!userSession.isLogin()) {
452
+ throw new BizException('您当前未登录,您没有访问此文件的权限');
453
+ }
454
+ const sessionInfo = this.ctx.userSession.getSessionInfo();
455
+
456
+ const condition: any = {
457
+ created_by: sessionInfo.accountId,
458
+ status: 1
459
+ };
460
+
461
+ if (file_category) {
462
+ condition.file_category = file_category
463
+ }
464
+
465
+ return await this.fileBD.getFilePage({
466
+ condition: condition,
467
+ columns: [
468
+ 'id',
469
+ 'file_key',
470
+ 'file_name',
471
+ 'file_size',
472
+ 'file_type',
473
+ 'file_suffix',
474
+ 'storage_path',
475
+ 'storage_url',
476
+ 'file_category',
477
+ 'created_at'
478
+ ]
479
+ });
480
+ }
481
+
482
+
395
483
  }
@@ -2,7 +2,7 @@ import { KeysOfSimpleSQL, SqlDbType } from '@/libs/crud-pro/models/keys';
2
2
  import { IRequestCfgModel, IRequestModel, ISqlCfgModel } from '@/libs/crud-pro/interfaces';
3
3
  import { IRequestCfgModel2 } from '@/models/bizmodels';
4
4
  import { CrudPro } from '@/libs/crud-pro/CrudPro';
5
- import { ResModelAffected, ResModelStandard } from '@/libs/crud-pro/models/ResModel';
5
+ import {ResModelAffected, ResModelPageQuery, ResModelStandard} from '@/libs/crud-pro/models/ResModel';
6
6
 
7
7
  const DEFAULT_MAX_LIMIT = 10 * 10000;
8
8
 
@@ -103,13 +103,13 @@ export class CrudProQuick {
103
103
  return res.getResRows();
104
104
  }
105
105
 
106
- public async getListPage(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelStandard> {
106
+ public async getListPage(reqJson: IRequestModel, sqlTable?: string): Promise<ResModelPageQuery> {
107
107
  const cfgModel: IRequestCfgModel = {
108
108
  sqlTable,
109
109
  sqlSimpleName: KeysOfSimpleSQL.SIMPLE_QUERY_PAGE,
110
110
  };
111
111
  const res = await this.executeCrudByCfg(reqJson, cfgModel);
112
- return res.getResModel(); // 因为它有2个返回值
112
+ return res.getResModelForQueryPage();
113
113
  }
114
114
 
115
115
  public async getTotalCount(reqJson: IRequestModel, sqlTable?: string): Promise<number> {