|
|
@@ -23,6 +23,131 @@ module.exports = app => {
|
|
|
if (!ctx.subProject.lock_file) throw '请先锁定,再管理分类数据';
|
|
|
}
|
|
|
|
|
|
+ isAdmin(ctx) {
|
|
|
+ return Number(ctx.session.sessionUser.is_admin) === 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ hasFilePermission(ctx, permissionKey) {
|
|
|
+ if (this.isAdmin(ctx)) return true;
|
|
|
+ const permission = ctx.service.subProjPermission.PermissionConst.file[permissionKey];
|
|
|
+ const filePermission = ctx.subProject.permission.file_permission || [];
|
|
|
+ return permission && filePermission.indexOf(permission.value) >= 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ hasFileConfigPermission(ctx) {
|
|
|
+ return this.hasFilePermission(ctx, 'manage_dir') || this.hasFilePermission(ctx, 'auth_user');
|
|
|
+ }
|
|
|
+
|
|
|
+ applyFileConfigViewPermission(ctx, permissionMap) {
|
|
|
+ if (!this.hasFileConfigPermission(ctx)) return permissionMap;
|
|
|
+ Object.keys(permissionMap || {}).forEach(filingId => {
|
|
|
+ permissionMap[filingId].can_view = 1;
|
|
|
+ });
|
|
|
+ return permissionMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ checkFilePermission(ctx, permissionKey) {
|
|
|
+ if (!this.hasFilePermission(ctx, permissionKey)) throw '您无权进行该操作';
|
|
|
+ }
|
|
|
+
|
|
|
+ hasLegacyFilePermission(ctx, value) {
|
|
|
+ if (this.isAdmin(ctx)) return true;
|
|
|
+ return (ctx.subProject.permission.file_permission || []).indexOf(value) >= 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ async getProjectFiling(ctx, filingId) {
|
|
|
+ const filing = await ctx.service.filing.getDataById(filingId);
|
|
|
+ if (!filing || filing.is_deleted || filing.spid !== ctx.subProject.id) throw '分类不存在';
|
|
|
+ return filing;
|
|
|
+ }
|
|
|
+
|
|
|
+ async fillFilingAddUserNames(ctx, filingList) {
|
|
|
+ const rows = filingList || [];
|
|
|
+ const userIds = this.app._.uniq(rows.map(x => Number(x.create_uid)).filter(x => x > 0));
|
|
|
+ const users = userIds.length > 0 ? await ctx.service.projectAccount.getAllDataByCondition({
|
|
|
+ columns: ['id', 'name'],
|
|
|
+ where: { id: userIds },
|
|
|
+ }) : [];
|
|
|
+ const userNameMap = {};
|
|
|
+ users.forEach(user => { userNameMap[Number(user.id)] = user.name || ''; });
|
|
|
+ rows.forEach(filing => {
|
|
|
+ filing.add_user = userNameMap[Number(filing.create_uid)] || '';
|
|
|
+ });
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ async fillFilingPermissionCreatorNames(ctx, filingList, permissionRows) {
|
|
|
+ const rows = filingList || [];
|
|
|
+ const exactPermissionRows = (permissionRows || []).filter(permission => {
|
|
|
+ return permission.filing_id && Number(permission.create_uid) > 0;
|
|
|
+ });
|
|
|
+ const creatorIds = this.app._.uniq(exactPermissionRows
|
|
|
+ .map(permission => Number(permission.create_uid)).filter(uid => uid > 0));
|
|
|
+ const creators = creatorIds.length > 0 ? await ctx.service.projectAccount.getAllDataByCondition({
|
|
|
+ columns: ['id', 'name'],
|
|
|
+ where: { id: creatorIds },
|
|
|
+ }) : [];
|
|
|
+ const creatorNameMap = {};
|
|
|
+ creators.forEach(creator => { creatorNameMap[Number(creator.id)] = creator.name || ''; });
|
|
|
+ rows.forEach(filing => {
|
|
|
+ const creatorNames = this.app._.uniq(exactPermissionRows.filter(permission => {
|
|
|
+ return String(permission.filing_id) === String(filing.id);
|
|
|
+ }).map(permission => creatorNameMap[Number(permission.create_uid)]).filter(Boolean));
|
|
|
+ if (creatorNames.length > 0) filing.add_user = creatorNames.join('、');
|
|
|
+ });
|
|
|
+ return rows;
|
|
|
+ }
|
|
|
+
|
|
|
+ async checkFilingView(ctx, filing) {
|
|
|
+ const permission = await ctx.service.subProjectFilingPermission.getResolvedPermission(
|
|
|
+ ctx.subProject.id,
|
|
|
+ ctx.session.sessionUser.accountId,
|
|
|
+ filing.id,
|
|
|
+ filing.filing_type,
|
|
|
+ ctx.subProject.permission.file_permission,
|
|
|
+ ctx.subProject.permission.filing_type,
|
|
|
+ this.isAdmin(ctx)
|
|
|
+ );
|
|
|
+ if (this.hasFileConfigPermission(ctx)) permission.can_view = 1;
|
|
|
+ if (!permission.can_view) throw '您无权查看该资料目录';
|
|
|
+ return permission;
|
|
|
+ }
|
|
|
+
|
|
|
+ async getFilingOperationPermission(ctx, filing) {
|
|
|
+ return await this.checkFilingView(ctx, filing);
|
|
|
+ }
|
|
|
+
|
|
|
+ async checkFilingOperation(ctx, filing, permissionField) {
|
|
|
+ const permission = await this.getFilingOperationPermission(ctx, filing);
|
|
|
+ if (!permission[permissionField]) throw '您无权进行该操作';
|
|
|
+ return permission;
|
|
|
+ }
|
|
|
+
|
|
|
+ async getFilingFromDirectoryData(ctx, data) {
|
|
|
+ const filingId = data.id || data.tree_pre_id || (data.tree_pid && data.tree_pid !== '-1' ? data.tree_pid : '');
|
|
|
+ if (!filingId) throw '请先选择资料类别';
|
|
|
+ return await this.getProjectFiling(ctx, filingId);
|
|
|
+ }
|
|
|
+
|
|
|
+ filterVisibleFiling(filingList, permissionMap) {
|
|
|
+ const filingMap = {};
|
|
|
+ (filingList || []).forEach(filing => { filingMap[String(filing.id)] = filing; });
|
|
|
+ const visibleIds = new Set();
|
|
|
+ (filingList || []).forEach(filing => {
|
|
|
+ const permission = permissionMap[filing.id];
|
|
|
+ if (!permission || !permission.can_view) return;
|
|
|
+ let current = filing;
|
|
|
+ while (current) {
|
|
|
+ const currentId = String(current.id);
|
|
|
+ if (visibleIds.has(currentId)) break;
|
|
|
+ visibleIds.add(currentId);
|
|
|
+ if (current.tree_pid === '-1' || current.tree_pid === -1) break;
|
|
|
+ current = filingMap[String(current.tree_pid)];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return (filingList || []).filter(filing => visibleIds.has(String(filing.id)));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 概算投资
|
|
|
*
|
|
|
@@ -54,14 +179,15 @@ module.exports = app => {
|
|
|
|
|
|
async file(ctx) {
|
|
|
try {
|
|
|
+ if (!this.hasLegacyFilePermission(ctx, 1)) throw '您无权查看旧版资料管理';
|
|
|
const renderData = {
|
|
|
jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.file.file),
|
|
|
};
|
|
|
renderData.filing = await ctx.service.filing.getValidFiling(ctx.params.id, ctx.subProject.permission.filing_type);
|
|
|
renderData.categoryData = await ctx.service.category.getAllCategory(ctx.subProject);
|
|
|
- renderData.canFiling = ctx.subProject.permission.file_permission.indexOf(ctx.service.subProjPermission.PermissionConst.file.filing.value) >= 0;
|
|
|
- renderData.canUpload = ctx.subProject.permission.file_permission.indexOf(ctx.service.subProjPermission.PermissionConst.file.upload.value) >= 0;
|
|
|
- renderData.canEdit = ctx.subProject.permission.file_permission.indexOf(ctx.service.subProjPermission.PermissionConst.file.editfile.value) >= 0;
|
|
|
+ renderData.canFiling = !ctx.subProject.lock_file && this.hasLegacyFilePermission(ctx, 3);
|
|
|
+ renderData.canUpload = !ctx.subProject.lock_file && this.hasLegacyFilePermission(ctx, 2);
|
|
|
+ renderData.canEdit = !ctx.subProject.lock_file && this.hasLegacyFilePermission(ctx, 4);
|
|
|
renderData.fileReferenceList = await ctx.service.subProject.getFileReference(ctx.subProject, ctx.service.subProject.FileReferenceType.file);
|
|
|
await this.layout('file/file.ejs', renderData, 'file/file_modal.ejs');
|
|
|
} catch (err) {
|
|
|
@@ -69,6 +195,399 @@ module.exports = app => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * SpreadJS 替代 zTree 展示资料分类树 Demo
|
|
|
+ *
|
|
|
+ * @param {Object} ctx - egg context
|
|
|
+ */
|
|
|
+ async fileSjsDemo(ctx) {
|
|
|
+ try {
|
|
|
+ const renderData = {
|
|
|
+ jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.file.sjs_demo),
|
|
|
+ };
|
|
|
+ renderData.filing = await ctx.service.filing.getValidFiling(ctx.params.id, ctx.subProject.permission.filing_type);
|
|
|
+ renderData.categoryData = await ctx.service.category.getAllCategory(ctx.subProject);
|
|
|
+ // 根据 lock_file 判断是否可编辑
|
|
|
+ const canEdit = !ctx.subProject.lock_file;
|
|
|
+ renderData.canFiling = canEdit;
|
|
|
+ renderData.canUpload = canEdit;
|
|
|
+ renderData.canEdit = canEdit;
|
|
|
+ renderData.fileReferenceList = await ctx.service.subProject.getFileReference(ctx.subProject, ctx.service.subProject.FileReferenceType.file);
|
|
|
+ await this.layout('file/file_sjs_demo.ejs', renderData);
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 资料管理 SpreadJS 版本
|
|
|
+ * 使用 SpreadJS 替代 zTree 展示文件分类树
|
|
|
+ *
|
|
|
+ * @param {Object} ctx - egg context
|
|
|
+ */
|
|
|
+ async filesjs(ctx) {
|
|
|
+ try {
|
|
|
+ const renderData = {
|
|
|
+ jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.file.filesjs),
|
|
|
+ };
|
|
|
+ const allFiling = await ctx.service.filing.getValidFiling(ctx.params.id, 'all');
|
|
|
+ const canManageDir = this.hasFilePermission(ctx, 'manage_dir');
|
|
|
+ renderData.categoryData = await ctx.service.category.getAllCategory(ctx.subProject);
|
|
|
+ renderData.filingPermissionMap = await ctx.service.subProjectFilingPermission.getPermissionMap(
|
|
|
+ ctx.subProject.id,
|
|
|
+ ctx.session.sessionUser.accountId,
|
|
|
+ allFiling,
|
|
|
+ ctx.subProject.permission.filing_type,
|
|
|
+ ctx.subProject.permission.file_permission,
|
|
|
+ this.isAdmin(ctx)
|
|
|
+ );
|
|
|
+ this.applyFileConfigViewPermission(ctx, renderData.filingPermissionMap);
|
|
|
+ renderData.filing = this.filterVisibleFiling(allFiling, renderData.filingPermissionMap);
|
|
|
+ // 共用 file_modal.ejs 需要渲染全部弹窗,实际显示与操作由 filingPermissionMap 控制。
|
|
|
+ renderData.canFiling = true;
|
|
|
+ renderData.canUpload = true;
|
|
|
+ renderData.canEdit = false;
|
|
|
+ renderData.canManageDir = this.hasFileConfigPermission(ctx);
|
|
|
+ renderData.needFilingInitialization = canManageDir && allFiling.length === 0;
|
|
|
+ renderData.filingInitializationTemplates = [];
|
|
|
+ renderData.filingInitializationProjects = [];
|
|
|
+ if (renderData.needFilingInitialization) {
|
|
|
+ renderData.filingInitializationTemplates = await ctx.service.filingTemplateList.getAllDataByCondition({
|
|
|
+ columns: ['id', 'name'],
|
|
|
+ where: { ft_type: ctx.service.filingTemplateList.FtType.org },
|
|
|
+ orders: [['create_time', 'asc']],
|
|
|
+ });
|
|
|
+ renderData.filingInitializationProjects = await ctx.service.subProject.getManageDirProjects(
|
|
|
+ ctx.session.sessionProject.id,
|
|
|
+ ctx.session.sessionUser.accountId,
|
|
|
+ this.isAdmin(ctx),
|
|
|
+ ctx.subProject.id
|
|
|
+ );
|
|
|
+ }
|
|
|
+ renderData.fileReferenceList = await ctx.service.subProject.getFileReference(ctx.subProject, ctx.service.subProject.FileReferenceType.file);
|
|
|
+ await this.layout('file/filesjs.ejs', renderData, 'file/file_modal.ejs');
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async initializeFiling(ctx) {
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'manage_dir');
|
|
|
+ const data = JSON.parse(ctx.request.body.data);
|
|
|
+ if (!data || !data.init_type) throw '请选择初始化方式';
|
|
|
+ if (data.init_type === 'template') throw '模板库初始化功能暂未开放';
|
|
|
+
|
|
|
+ let sourceData = [];
|
|
|
+ if (data.init_type === 'project') {
|
|
|
+ if (!data.source_spid) throw '请选择来源项目';
|
|
|
+ const sourceProjects = await ctx.service.subProject.getManageDirProjects(
|
|
|
+ ctx.session.sessionProject.id,
|
|
|
+ ctx.session.sessionUser.accountId,
|
|
|
+ this.isAdmin(ctx),
|
|
|
+ ctx.subProject.id
|
|
|
+ );
|
|
|
+ const sourceProject = sourceProjects.find(project => {
|
|
|
+ return String(project.id) === String(data.source_spid);
|
|
|
+ });
|
|
|
+ if (!sourceProject) throw '来源项目不存在或您没有管理目录权限';
|
|
|
+ sourceData = await ctx.service.filing.getValidFiling(sourceProject.id, 'all');
|
|
|
+ }
|
|
|
+ const result = await ctx.service.filing.initializeDirectory(
|
|
|
+ ctx.subProject.id,
|
|
|
+ data.init_type,
|
|
|
+ sourceData,
|
|
|
+ ctx.session.sessionUser.accountId
|
|
|
+ );
|
|
|
+ ctx.body = { err: 0, msg: '', data: result };
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.ajaxErrorBody(err, '初始化资料目录失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async configDir(ctx) {
|
|
|
+ try {
|
|
|
+ const canManageDir = this.hasFilePermission(ctx, 'manage_dir');
|
|
|
+ const canAuthUser = this.hasFilePermission(ctx, 'auth_user');
|
|
|
+ if (!canManageDir && !canAuthUser) throw '您无权查看配置目录';
|
|
|
+ const renderData = {
|
|
|
+ jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.file.config_dir),
|
|
|
+ };
|
|
|
+ renderData.canManageDir = canManageDir;
|
|
|
+ renderData.canAuthUser = canAuthUser;
|
|
|
+ renderData.filing = await ctx.service.filing.getValidFiling(ctx.params.id, 'all');
|
|
|
+ await this.fillFilingAddUserNames(ctx, renderData.filing);
|
|
|
+ renderData.permissionData = renderData.canAuthUser ? await ctx.service.subProjPermission.getPermission(ctx.params.id) : [];
|
|
|
+ renderData.filingPermissionData = renderData.canAuthUser
|
|
|
+ ? await ctx.service.subProjectFilingPermission.getConfigPermissionRows(ctx.params.id, renderData.filing) : [];
|
|
|
+ if (renderData.canAuthUser) {
|
|
|
+ await this.fillFilingPermissionCreatorNames(
|
|
|
+ ctx, renderData.filing, renderData.filingPermissionData
|
|
|
+ );
|
|
|
+ }
|
|
|
+ renderData.accountList = renderData.canAuthUser
|
|
|
+ ? await ctx.service.subProjDataRange.getSelectableAccounts(ctx.subProject, 'file') : [];
|
|
|
+ await this.layout('file/config_dir.ejs', renderData);
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.session.postError = err.toString();
|
|
|
+ ctx.redirect(this.menu.menu.dashboard.url);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async configDirLock(ctx) {
|
|
|
+ const redirectUrl = `/sp/${ctx.subProject.id}/config-dir`;
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'manage_dir');
|
|
|
+ const lock = Number(ctx.request.body.lock);
|
|
|
+ if (lock !== 0 && lock !== 1) throw '锁定状态参数错误';
|
|
|
+ await ctx.service.subProject.save({ id: ctx.subProject.id, lock_file: lock });
|
|
|
+ ctx.redirect(redirectUrl);
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.postError(err, '资料管理锁定状态修改失败');
|
|
|
+ ctx.redirect(redirectUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async configDirUpdate(ctx) {
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'manage_dir');
|
|
|
+ this.checkLock(ctx);
|
|
|
+ const data = JSON.parse(ctx.request.body.data);
|
|
|
+ const result = await this.updateFiling(ctx, data);
|
|
|
+ if (result && result.create) await this.fillFilingAddUserNames(ctx, result.create);
|
|
|
+ ctx.body = { err: 0, msg: '', data: result };
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.ajaxErrorBody(err, '修改失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async getFilingNodePermission(ctx) {
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'auth_user');
|
|
|
+ const filingId = ctx.request.body.filing_id;
|
|
|
+ const filing = await this.getProjectFiling(ctx, filingId);
|
|
|
+ const selectableAccounts = await ctx.service.subProjDataRange.getSelectableAccounts(ctx.subProject, 'file');
|
|
|
+ const projectAccounts = await ctx.service.subProjPermission.getPermission(ctx.subProject.id);
|
|
|
+ const permissionRows = await ctx.service.subProjectFilingPermission.getConfigPermissionRows(
|
|
|
+ ctx.subProject.id, [filing]
|
|
|
+ );
|
|
|
+ const authorizedIds = permissionRows.filter(row => {
|
|
|
+ return String(row.filing_id || '') === String(filing.id);
|
|
|
+ }).map(row => Number(row.uid));
|
|
|
+ const accountMap = {};
|
|
|
+ projectAccounts.forEach(permission => {
|
|
|
+ const userId = Number(permission.uid);
|
|
|
+ accountMap[userId] = {
|
|
|
+ id: userId,
|
|
|
+ name: permission.name,
|
|
|
+ company: permission.company,
|
|
|
+ role: permission.role,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ selectableAccounts.forEach(account => {
|
|
|
+ accountMap[Number(account.id)] = account;
|
|
|
+ });
|
|
|
+ const authorizedUsers = authorizedIds.map(uid => accountMap[uid]).filter(Boolean).map(account => {
|
|
|
+ return {
|
|
|
+ id: Number(account.id),
|
|
|
+ name: account.name,
|
|
|
+ company: account.company,
|
|
|
+ role: account.role,
|
|
|
+ };
|
|
|
+ }).filter((account, index, list) => {
|
|
|
+ return list.findIndex(item => Number(item.id) === Number(account.id)) === index;
|
|
|
+ });
|
|
|
+ /*
|
|
|
+ * 下拉选择仍只使用数据范围内账号;这里额外合并项目账号,
|
|
|
+ * 是为了让已经存在的旧授权不会因数据范围调整而从弹窗消失。
|
|
|
+ */
|
|
|
+ const selectableIds = selectableAccounts.map(account => Number(account.id));
|
|
|
+ authorizedUsers.forEach(account => {
|
|
|
+ account.selectable = selectableIds.indexOf(Number(account.id)) >= 0;
|
|
|
+ });
|
|
|
+ ctx.body = { err: 0, msg: '', data: authorizedUsers };
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.ajaxErrorBody(err, '获取授权用户失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async saveFilingNodePermission(ctx) {
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'auth_user');
|
|
|
+ this.checkLock(ctx);
|
|
|
+ const data = JSON.parse(ctx.request.body.data);
|
|
|
+ if (!data || !data.filing_id) throw '请选择需要授权的资料目录';
|
|
|
+ if (!(data.user_permissions instanceof Array)) throw '授权用户权限格式错误';
|
|
|
+ if (data.user_permissions.find(x => !x || typeof x !== 'object')) throw '授权用户权限格式错误';
|
|
|
+ const filing = await this.getProjectFiling(ctx, data.filing_id);
|
|
|
+ const allFiling = await ctx.service.filing.getValidFiling(ctx.subProject.id, 'all');
|
|
|
+ const filingMap = {};
|
|
|
+ allFiling.forEach(item => { filingMap[String(item.id)] = item; });
|
|
|
+ const ancestorIds = [];
|
|
|
+ let parentId = String(filing.tree_pid);
|
|
|
+ while (parentId !== '-1') {
|
|
|
+ const parent = filingMap[parentId];
|
|
|
+ if (!parent) break;
|
|
|
+ ancestorIds.push(String(parent.id));
|
|
|
+ parentId = String(parent.tree_pid);
|
|
|
+ }
|
|
|
+ if (ancestorIds.length > 0) {
|
|
|
+ const ancestorPermissionRows = await ctx.service.subProjectFilingPermission.getAllDataByCondition({
|
|
|
+ columns: ['filing_id'],
|
|
|
+ where: { spid: ctx.subProject.id, filing_id: ancestorIds },
|
|
|
+ limit: 1,
|
|
|
+ });
|
|
|
+ if (ancestorPermissionRows.length > 0) throw '父级目录已授权,当前目录不能单独授权';
|
|
|
+ }
|
|
|
+ const userPermissions = data.user_permissions;
|
|
|
+ const requestedUserIds = userPermissions.map(x => Number(x.uid !== undefined ? x.uid : x.id));
|
|
|
+ if (requestedUserIds.find(uid => !Number.isInteger(uid) || uid <= 0)) throw '授权用户数据错误';
|
|
|
+ if (new Set(requestedUserIds).size !== requestedUserIds.length) throw '授权用户数据重复';
|
|
|
+ const selectableAccounts = await ctx.service.subProjDataRange.getSelectableAccounts(ctx.subProject, 'file');
|
|
|
+ const selectableIds = selectableAccounts.map(account => Number(account.id));
|
|
|
+ const currentPermissionRows = await ctx.service.subProjectFilingPermission.getConfigPermissionRows(
|
|
|
+ ctx.subProject.id, [filing]
|
|
|
+ );
|
|
|
+ const currentUserIds = currentPermissionRows.filter(row => {
|
|
|
+ return String(row.filing_id || '') === String(filing.id);
|
|
|
+ }).map(row => Number(row.uid));
|
|
|
+ const invalidUserId = requestedUserIds.find(uid => {
|
|
|
+ return selectableIds.indexOf(uid) < 0 && currentUserIds.indexOf(uid) < 0;
|
|
|
+ });
|
|
|
+ if (invalidUserId) throw '选择的用户超出资料管理数据范围';
|
|
|
+ const result = await ctx.service.subProjectFilingPermission.savePermissionsToSubtree(
|
|
|
+ ctx.subProject,
|
|
|
+ filing,
|
|
|
+ allFiling,
|
|
|
+ userPermissions,
|
|
|
+ ctx.session.sessionUser.accountId
|
|
|
+ );
|
|
|
+ const savedPermissionRows = await ctx.service.subProjectFilingPermission.getRows(ctx.subProject.id);
|
|
|
+ await this.fillFilingAddUserNames(ctx, result.filings);
|
|
|
+ await this.fillFilingPermissionCreatorNames(ctx, result.filings, savedPermissionRows);
|
|
|
+ ctx.body = {
|
|
|
+ err: 0,
|
|
|
+ msg: '',
|
|
|
+ data: {
|
|
|
+ permissions: result.permissions,
|
|
|
+ filings: result.filings.map(item => ({
|
|
|
+ id: item.id,
|
|
|
+ add_user: item.add_user || '',
|
|
|
+ })),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.ajaxErrorBody(err, '保存授权用户失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async addFilingNodePermissions(ctx) {
|
|
|
+ await this._saveFilingNodePermissionsToOther(ctx, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ async coverFilingNodePermissions(ctx) {
|
|
|
+ await this._saveFilingNodePermissionsToOther(ctx, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ async _saveFilingNodePermissionsToOther(ctx, replaceExisting) {
|
|
|
+ try {
|
|
|
+ this.checkFilePermission(ctx, 'auth_user');
|
|
|
+ this.checkLock(ctx);
|
|
|
+ const data = JSON.parse(ctx.request.body.data);
|
|
|
+ if (!data || !data.source_filing_id) throw '请选择来源资料目录';
|
|
|
+ if (!(data.target_filing_ids instanceof Array) || data.target_filing_ids.length === 0) {
|
|
|
+ throw '请选择目标资料目录';
|
|
|
+ }
|
|
|
+ if (data.target_filing_ids.length > 500) throw '一次最多选择500个目标资料目录';
|
|
|
+ if (!(data.user_permissions instanceof Array) || data.user_permissions.length === 0) {
|
|
|
+ throw '请选择需要添加的授权用户';
|
|
|
+ }
|
|
|
+ if (data.user_permissions.find(x => !x || typeof x !== 'object')) {
|
|
|
+ throw '授权用户权限格式错误';
|
|
|
+ }
|
|
|
+
|
|
|
+ const sourceFiling = await this.getProjectFiling(ctx, data.source_filing_id);
|
|
|
+ const targetFilingIds = data.target_filing_ids.map(id => String(id || '').trim());
|
|
|
+ if (targetFilingIds.find(id => !id)) throw '目标资料目录数据错误';
|
|
|
+ if (new Set(targetFilingIds).size !== targetFilingIds.length) throw '目标资料目录重复';
|
|
|
+ if (targetFilingIds.indexOf(String(sourceFiling.id)) >= 0) throw '当前目录不能作为目标目录';
|
|
|
+
|
|
|
+ const targetFilingRows = await ctx.service.filing.getAllDataByCondition({
|
|
|
+ where: {
|
|
|
+ id: targetFilingIds,
|
|
|
+ spid: ctx.subProject.id,
|
|
|
+ is_deleted: 0,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const targetFilingMap = {};
|
|
|
+ targetFilingRows.forEach(filing => { targetFilingMap[String(filing.id)] = filing; });
|
|
|
+ if (targetFilingIds.find(filingId => !targetFilingMap[filingId])) throw '目标资料目录不存在';
|
|
|
+ const targetFilings = targetFilingIds.map(filingId => targetFilingMap[filingId]);
|
|
|
+
|
|
|
+ const userPermissions = data.user_permissions;
|
|
|
+ const requestedUserIds = userPermissions.map(x => Number(x.uid !== undefined ? x.uid : x.id));
|
|
|
+ if (requestedUserIds.find(uid => !Number.isInteger(uid) || uid <= 0)) throw '授权用户数据错误';
|
|
|
+ if (new Set(requestedUserIds).size !== requestedUserIds.length) throw '授权用户数据重复';
|
|
|
+
|
|
|
+ const selectableAccounts = await ctx.service.subProjDataRange.getSelectableAccounts(ctx.subProject, 'file');
|
|
|
+ const selectableIds = selectableAccounts.map(account => Number(account.id));
|
|
|
+ const sourcePermissionRows = await ctx.service.subProjectFilingPermission.getConfigPermissionRows(
|
|
|
+ ctx.subProject.id, [sourceFiling]
|
|
|
+ );
|
|
|
+ const sourceUserIds = sourcePermissionRows.filter(row => {
|
|
|
+ return String(row.filing_id || '') === String(sourceFiling.id);
|
|
|
+ }).map(row => Number(row.uid));
|
|
|
+ const invalidUserId = requestedUserIds.find(uid => {
|
|
|
+ return selectableIds.indexOf(uid) < 0 && sourceUserIds.indexOf(uid) < 0;
|
|
|
+ });
|
|
|
+ if (invalidUserId) throw '选择的用户超出资料管理数据范围';
|
|
|
+
|
|
|
+ const permissionService = ctx.service.subProjectFilingPermission;
|
|
|
+ if (replaceExisting) {
|
|
|
+ await permissionService.coverPermissionsToFilings(
|
|
|
+ ctx.subProject,
|
|
|
+ targetFilings,
|
|
|
+ userPermissions,
|
|
|
+ ctx.session.sessionUser.accountId
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ await permissionService.addPermissionsToFilings(
|
|
|
+ ctx.subProject,
|
|
|
+ targetFilings,
|
|
|
+ userPermissions,
|
|
|
+ ctx.session.sessionUser.accountId
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const savedPermissionRows = await ctx.service.subProjectFilingPermission.getRows(ctx.subProject.id);
|
|
|
+ const targetPermissionRows = await ctx.service.subProjectFilingPermission.getConfigPermissionRows(
|
|
|
+ ctx.subProject.id, targetFilings
|
|
|
+ );
|
|
|
+ await this.fillFilingAddUserNames(ctx, targetFilings);
|
|
|
+ await this.fillFilingPermissionCreatorNames(ctx, targetFilings, savedPermissionRows);
|
|
|
+ ctx.body = {
|
|
|
+ err: 0,
|
|
|
+ msg: '',
|
|
|
+ data: {
|
|
|
+ permissions: targetPermissionRows,
|
|
|
+ filings: targetFilings.map(filing => ({
|
|
|
+ id: filing.id,
|
|
|
+ add_user: filing.add_user || '',
|
|
|
+ })),
|
|
|
+ },
|
|
|
+ };
|
|
|
+ } catch (err) {
|
|
|
+ ctx.log(err);
|
|
|
+ ctx.ajaxErrorBody(err, replaceExisting ? '覆盖授权用户至其他目录失败' : '添加授权用户至其他目录失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
async getFilingTypePermission(ctx) {
|
|
|
try {
|
|
|
if (ctx.subProject.project_id !== this.ctx.session.sessionProject.id) throw '您无权操作该数据';
|
|
|
@@ -95,6 +614,8 @@ module.exports = app => {
|
|
|
try {
|
|
|
this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
+ const filing = await this.getFilingFromDirectoryData(ctx, data);
|
|
|
+ await this.checkFilingOperation(ctx, filing, 'can_edit_dir');
|
|
|
const result = await ctx.service.filing.add(data);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (err) {
|
|
|
@@ -106,6 +627,8 @@ module.exports = app => {
|
|
|
try {
|
|
|
this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
+ const filing = await this.getFilingFromDirectoryData(ctx, data);
|
|
|
+ await this.checkFilingOperation(ctx, filing, 'can_edit_dir');
|
|
|
const result = await ctx.service.filing.del(data);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (err) {
|
|
|
@@ -117,6 +640,8 @@ module.exports = app => {
|
|
|
try {
|
|
|
this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
+ const filing = await this.getFilingFromDirectoryData(ctx, data);
|
|
|
+ await this.checkFilingOperation(ctx, filing, 'can_edit_dir');
|
|
|
const result = await ctx.service.filing.save(data);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (err) {
|
|
|
@@ -130,6 +655,8 @@ module.exports = app => {
|
|
|
this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.id || !(data.tree_order >= 0)) throw '数据错误';
|
|
|
+ const filing = await this.getFilingFromDirectoryData(ctx, data);
|
|
|
+ await this.checkFilingOperation(ctx, filing, 'can_edit_dir');
|
|
|
const result = await ctx.service.filing.move(data);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (err) {
|
|
|
@@ -141,6 +668,8 @@ module.exports = app => {
|
|
|
async loadFile(ctx) {
|
|
|
try {
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
+ const filing = await this.getProjectFiling(ctx, data.filing_id);
|
|
|
+ await this.checkFilingView(ctx, filing);
|
|
|
const order = data.order.split('|');
|
|
|
if (order.length !== 2) throw '加载文件错误';
|
|
|
if (order[0] !== 'filename' && order[0] !== 'create_time') throw '加载文件错误';
|
|
|
@@ -159,10 +688,9 @@ module.exports = app => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- async checkCanUpload(ctx) {
|
|
|
- if (ctx.subProject.permission.file_permission.indexOf(ctx.service.subProjPermission.PermissionConst.file.upload.value) < 0) {
|
|
|
- throw '您无权上传、导入、删除文件';
|
|
|
- }
|
|
|
+ async checkCanUpload(ctx, filing) {
|
|
|
+ this.checkUnlock(ctx);
|
|
|
+ await this.checkFilingOperation(ctx, filing, 'can_upload');
|
|
|
}
|
|
|
|
|
|
async checkFiling(filing) {
|
|
|
@@ -174,6 +702,8 @@ module.exports = app => {
|
|
|
try{
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.filing_id || !data.files) throw '缺少参数';
|
|
|
+ const filing = await this.getProjectFiling(ctx, data.filing_id);
|
|
|
+ await this.checkCanUpload(ctx, filing);
|
|
|
const result = await ctx.service.file.checkFiles(data.filing_id, data.files);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch(error) {
|
|
|
@@ -185,16 +715,14 @@ module.exports = app => {
|
|
|
async uploadFile(ctx){
|
|
|
let stream;
|
|
|
try {
|
|
|
- await this.checkCanUpload(ctx);
|
|
|
-
|
|
|
const parts = ctx.multipart({ autoFields: true });
|
|
|
|
|
|
let index = 0;
|
|
|
const create_time = Date.parse(new Date()) / 1000;
|
|
|
- let stream = await parts();
|
|
|
+ stream = await parts();
|
|
|
const user = await ctx. service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
|
|
|
- const filing = await ctx.service.filing.getDataById(parts.field.filing_id);
|
|
|
- if (!filing || filing.is_deleted) throw '分类不存在,请刷新页面后重试';
|
|
|
+ const filing = await this.getProjectFiling(ctx, parts.field.filing_id);
|
|
|
+ await this.checkCanUpload(ctx, filing);
|
|
|
await this.checkFiling(filing);
|
|
|
|
|
|
const uploadfiles = [];
|
|
|
@@ -234,6 +762,7 @@ module.exports = app => {
|
|
|
}
|
|
|
async delFile(ctx) {
|
|
|
try{
|
|
|
+ this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.del) throw '缺少参数';
|
|
|
const result = await ctx.service.file.delFiles(data.del);
|
|
|
@@ -245,6 +774,7 @@ module.exports = app => {
|
|
|
}
|
|
|
async saveFile(ctx) {
|
|
|
try {
|
|
|
+ this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.id) throw '缺少参数';
|
|
|
const result = await ctx.service.file.saveFile(data.id, data.filename);
|
|
|
@@ -254,10 +784,25 @@ module.exports = app => {
|
|
|
ctx.ajaxErrorBody(error, '编辑附件失败');
|
|
|
}
|
|
|
}
|
|
|
+ async lockFile(ctx) {
|
|
|
+ try {
|
|
|
+ this.checkUnlock(ctx);
|
|
|
+ const data = JSON.parse(ctx.request.body.data);
|
|
|
+ if (!data || !data.id) throw '缺少参数';
|
|
|
+ const result = await ctx.service.file.setLocked(data.id, data.is_locked);
|
|
|
+ ctx.body = { err: 0, msg: '', data: result };
|
|
|
+ } catch (error) {
|
|
|
+ this.log(error);
|
|
|
+ ctx.ajaxErrorBody(error, '修改文件锁定状态失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
async moveFile(ctx) {
|
|
|
try {
|
|
|
+ this.checkUnlock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.id || !data.filingId) throw '缺少参数';
|
|
|
+ const targetFiling = await this.getProjectFiling(ctx, data.filingId);
|
|
|
+ await this.checkFilingOperation(ctx, targetFiling, 'can_upload');
|
|
|
const result = await ctx.service.file.moveFile(data.id, data.filingId);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (error) {
|
|
|
@@ -267,11 +812,10 @@ module.exports = app => {
|
|
|
}
|
|
|
async uploadBigFile(ctx) {
|
|
|
try {
|
|
|
- await this.checkCanUpload(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
if (!data.type || !data.filing_id || !data.fileInfo) throw '缺少参数';
|
|
|
- const filing = await ctx.service.filing.getDataById(data.filing_id);
|
|
|
- if (!filing || filing.is_deleted) throw '分类不存在,请刷新页面后重试';
|
|
|
+ const filing = await this.getProjectFiling(ctx, data.filing_id);
|
|
|
+ await this.checkCanUpload(ctx, filing);
|
|
|
|
|
|
let result;
|
|
|
const fileInfo = path.parse(data.fileInfo.filename);
|
|
|
@@ -443,8 +987,8 @@ module.exports = app => {
|
|
|
if (!data.filing_id || !data.files) throw '缺少参数';
|
|
|
|
|
|
const user = await ctx. service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
|
|
|
- const filing = await ctx.service.filing.getDataById(data.filing_id);
|
|
|
- if (!filing || filing.is_deleted) throw '分类不存在,请刷新页面后重试';
|
|
|
+ const filing = await this.getProjectFiling(ctx, data.filing_id);
|
|
|
+ await this.checkCanUpload(ctx, filing);
|
|
|
await this.checkFiling(filing);
|
|
|
|
|
|
const result = await ctx.service.file.relaFiles(filing, data.files, user);
|
|
|
@@ -549,10 +1093,36 @@ module.exports = app => {
|
|
|
try {
|
|
|
const limit = 1000;
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
- if (!data.filing_type || !data.keyword) throw '数据错误';
|
|
|
+ if (!data.keyword) throw '数据错误';
|
|
|
+ if (data.filing_id instanceof Array) {
|
|
|
+ const filingIds = this.app._.uniq(data.filing_id.map(id => String(id || '')).filter(Boolean));
|
|
|
+ if (filingIds.length === 0) throw '数据错误';
|
|
|
+ const filings = await ctx.service.filing.getAllDataByCondition({
|
|
|
+ where: { id: filingIds, spid: ctx.subProject.id, is_deleted: 0 },
|
|
|
+ });
|
|
|
+ const permissionMap = await ctx.service.subProjectFilingPermission.getPermissionMap(
|
|
|
+ ctx.subProject.id,
|
|
|
+ ctx.session.sessionUser.accountId,
|
|
|
+ filings,
|
|
|
+ ctx.subProject.permission.filing_type,
|
|
|
+ ctx.subProject.permission.file_permission,
|
|
|
+ this.isAdmin(ctx)
|
|
|
+ );
|
|
|
+ this.applyFileConfigViewPermission(ctx, permissionMap);
|
|
|
+ const validFilingIds = filings.filter(filing => {
|
|
|
+ return permissionMap[filing.id] && permissionMap[filing.id].can_view;
|
|
|
+ }).map(filing => filing.id);
|
|
|
+ const result = await ctx.service.file.searchByFilingIds(validFilingIds, data.keyword, limit);
|
|
|
+ ctx.body = { err: 0, msg: '', data: { list: result, limit } };
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!data.filing_type) throw '数据错误';
|
|
|
const validFilingType = [];
|
|
|
for (const f of data.filing_type) {
|
|
|
- if (ctx.subProject.permission.filing_type === 'all' || ctx.subProject.permission.filing_type.indexOf(f) >= 0) validFilingType.push(f);
|
|
|
+ const filingType = Number(f);
|
|
|
+ if (!Number.isInteger(filingType) || filingType <= 0) continue;
|
|
|
+ if (ctx.subProject.permission.filing_type === 'all' ||
|
|
|
+ ctx.subProject.permission.filing_type.indexOf(filingType) >= 0) validFilingType.push(filingType);
|
|
|
}
|
|
|
const result = await ctx.service.file.search(validFilingType, data.keyword, limit);
|
|
|
ctx.body = { err: 0, msg: '', data: { list: result, limit } };
|
|
|
@@ -599,28 +1169,34 @@ module.exports = app => {
|
|
|
try {
|
|
|
this.checkLock(ctx);
|
|
|
const data = JSON.parse(ctx.request.body.data);
|
|
|
- if (!data.updateType) throw '数据错误';
|
|
|
- let result;
|
|
|
- const updateData = JSON.parse(JSON.stringify(data));
|
|
|
- delete updateData.updateType;
|
|
|
- if (data.updateType === 'add') {
|
|
|
- result = await ctx.service.filing.add(updateData);
|
|
|
- } else if (data.updateType === 'del') {
|
|
|
- result = await ctx.service.filing.del(updateData);
|
|
|
- } else if (data.updateType === 'save') {
|
|
|
- result = await ctx.service.filing.save(updateData);
|
|
|
- } else if (data.updateType === 'move') {
|
|
|
- if (!data.id || !(data.tree_order >= 0)) throw '数据错误';
|
|
|
- result = await ctx.service.filing.move(updateData);
|
|
|
- } else if (data.updateType === 'multi' ) {
|
|
|
- result = await ctx.service.filing.multiUpdate(ctx.subProject.id, data.data);
|
|
|
- }
|
|
|
+ const result = await this.updateFiling(ctx, data);
|
|
|
ctx.body = { err: 0, msg: '', data: result };
|
|
|
} catch (err) {
|
|
|
ctx.log(err);
|
|
|
ctx.ajaxErrorBody(err, '修改失败');
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ async updateFiling(ctx, data) {
|
|
|
+ if (!data.updateType) throw '数据错误';
|
|
|
+ const updateData = JSON.parse(JSON.stringify(data));
|
|
|
+ delete updateData.updateType;
|
|
|
+ if (data.updateType === 'add') {
|
|
|
+ return await ctx.service.filing.add(updateData);
|
|
|
+ } else if (data.updateType === 'del') {
|
|
|
+ return await ctx.service.filing.del(updateData);
|
|
|
+ } else if (data.updateType === 'save') {
|
|
|
+ return await ctx.service.filing.save(updateData);
|
|
|
+ } else if (data.updateType === 'edit') {
|
|
|
+ return await ctx.service.filing.editDirectory(updateData);
|
|
|
+ } else if (data.updateType === 'move') {
|
|
|
+ if (!data.id || !(data.tree_order >= 0)) throw '数据错误';
|
|
|
+ return await ctx.service.filing.move(updateData);
|
|
|
+ } else if (data.updateType === 'multi') {
|
|
|
+ return await ctx.service.filing.multiUpdate(ctx.subProject.id, data.data);
|
|
|
+ }
|
|
|
+ throw '未知的修改类型';
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return FileController;
|