ww664853070 2 years ago
parent
commit
0ceca51d5c
  1. 8
      api/Dockerfile
  2. 74
      api/app/lib/controllers/resourceRepository/index.js
  3. 10
      api/app/lib/routes/resourceRepository/index.js
  4. 18
      doc/scripts/3.2.0/schema/dept_training.sql
  5. 17
      doc/scripts/3.2.0/schema/personal_training_create.sql
  6. 29
      doc/scripts/PEP V3.2.0/schema/01 create_training_information.sql
  7. 11
      jenkinsfile_poms_api
  8. 11
      jenkinsfile_poms_web
  9. 21
      web/Dockerfile
  10. 13
      web/client/src/sections/humanAffairs/actions/resourceRepository.js
  11. 99
      web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx
  12. 6
      web/client/src/sections/humanAffairs/containers/departmentTrain/departmentTrainRecord.jsx
  13. 3
      web/client/src/sections/humanAffairs/containers/departmentTrain/editModal.js
  14. 2
      web/client/src/sections/humanAffairs/containers/departmentTrain/importModal.js
  15. 132
      web/client/src/sections/humanAffairs/containers/resourceRepository.jsx
  16. 4
      web/client/src/utils/webapi.js

8
api/Dockerfile

@ -25,12 +25,14 @@
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
MAINTAINER liuxinyi "liu.xinyi@free-sun.com.cn"
COPY . /var/app
WORKDIR /var/app
EXPOSE 8080
RUN npm cache clean -f && npm install --production --force --registry http://10.8.30.22:7000
CMD ["-u", "http://localhost:8088"]
RUN rm -rf package-lock.json
ENTRYPOINT [ "node", "server.js" ]
CMD [ "node", "server.js" ]

74
api/app/lib/controllers/resourceRepository/index.js

@ -6,7 +6,7 @@ async function getResourceClassify(ctx) {
const { models } = ctx.fs.dc;
let rlst = [];
rlst = [{
label: "公司培训资料", value: "company", key: "公司培训资料", operation: true, children: []
label: "公司培训资料", value: "company", key: "公司培训资料", operation: false, children: []
}, { label: "部门培训资料", value: 'dept', key: '部门培训资料', operation: false, children: [] }];
const findObj = { order: [["departmentName", "asc"]] }
const filterData = (arrayData, arrIndex, operation) => {
@ -147,6 +147,11 @@ async function getResourceFileList(ctx, next) {
findObj.where = where;
}
if ("公司培训资料" == type) {
if (findObj.where) {
findObj.where.fileName = { $not: null };
} else {
findObj.where = { fileName: { $not: null } };
}
rlst = await models.TrainingInformation.findAndCountAll(findObj);
} else {
rlst = await models.DeptTraining.findAndCountAll(findObj);
@ -163,6 +168,7 @@ async function getResourceFileList(ctx, next) {
}
}
async function postResourceClassify(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { departmentName, trainDate } = ctx.request.body;
@ -173,20 +179,78 @@ async function postResourceClassify(ctx) {
if (trainDate && '' != trainDate) {
where.trainDate = trainDate;
}
const oldData = await models.TrainingInformation.findOne(where);
const oldData = await models.TrainingInformation.findOne({ where });
if (oldData) {
ctx.throw("该文件夹已存在");
} else {
await models.TrainingInformation.create({
departmentName: departmentName,
trainDate: trainDate
}, { transaction })
}
}
await transaction.commit();
ctx.status = 204;
} catch (err) {
await transaction.rollback();
ctx.status = 400;
ctx.body = { message: err.message || '新增培训资源储备库文件夹失败' }
}
}
async function putResourceClassify(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
const { oldDepName, oldTrainDate, departmentName, trainDate } = ctx.request.body;
if (departmentName && '' != departmentName && oldDepName && '' != oldDepName) {
const where = { departmentName: oldDepName };
if (trainDate && '' != trainDate && oldTrainDate && '' != oldTrainDate) {
where.trainDate = oldTrainDate;
await models.TrainingInformation.update({ trainDate: trainDate }, { where, transaction });
//三级目录
} else {
//二级目录
await models.TrainingInformation.update({ departmentName: departmentName }, { where, transaction });
}
}
await transaction.commit();
ctx.status = 204;
} catch (err) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
await transaction.rollback();
ctx.status = 400;
ctx.body = { message: err.message || '查询培训资源储备库文件列表失败' }
ctx.body = { message: err.message || '编辑培训资源储备库文件夹失败' };
}
}
async function delResourceClassify(ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { departmentName, trainDate } = ctx.query;
const { models } = ctx.fs.dc;
if (departmentName && '' != departmentName) {
const where = { departmentName };
if (trainDate && '' != trainDate) {
where.trainDate = trainDate;
}
await models.TrainingInformation.destroy({ where, transaction });
}
await transaction.commit();
ctx.status = 204;
} catch (err) {
await transaction.rollback();
ctx.status = 400;
ctx.body = { message: err.message || '新增培训资源储备库文件夹失败' }
}
}
module.exports = {
getResourceClassify,
getResourceFileList,
postResourceClassify
postResourceClassify,
putResourceClassify,
delResourceClassify
}

10
api/app/lib/routes/resourceRepository/index.js

@ -9,4 +9,14 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/train/trainFiles/resourceRepository/fileList'] = { content: '查询培训资源储备库文件列表', visible: false };
router.get('/train/trainFiles/resourceRepository/fileList', resourceRepository.getResourceFileList);
app.fs.api.logAttr['POST/train/trainFiles/resourceRepository/classify'] = { content: '新增培训资源储备库文件夹', visible: true };
router.post('/train/trainFiles/resourceRepository/classify', resourceRepository.postResourceClassify);
app.fs.api.logAttr['PUT/train/trainFiles/resourceRepository/classify'] = { content: '编辑培训资源储备库文件夹', visible: true };
router.put('/train/trainFiles/resourceRepository/classify', resourceRepository.putResourceClassify);
app.fs.api.logAttr['DELETE/train/trainFiles/resourceRepository/classify'] = { content: '删除培训资源储备库文件夹', visible: true };
router.delete('/train/trainFiles/resourceRepository/classify', resourceRepository.delResourceClassify);
};

18
doc/scripts/3.2.0/schema/dept_training.sql

@ -0,0 +1,18 @@
CREATE TABLE PUBLIC.dept_training (
ID serial NOT NULL CONSTRAINT dept_training_pkey PRIMARY KEY,
departmentname VARCHAR ( 255 ) NOT NULL,
trainingtype VARCHAR ( 255 ) NOT NULL,
traindate TIMESTAMP NOT NULL,
traincontent VARCHAR ( 255 ) NOT NULL,
trainwho VARCHAR ( 255 ),
trainer VARCHAR ( 255 ),
trainmethod VARCHAR ( 255 ) NOT NULL,
appraisalmethod VARCHAR ( 255 ) NOT NULL,
traintime VARCHAR ( 255 ) NOT NULL,
attachpath VARCHAR ( 255 ),
origin VARCHAR ( 255 ),
filesize VARCHAR ( 255 ),
filename VARCHAR ( 255 ),
filetype VARCHAR ( 255 ),
updatedate TIMESTAMP WITH TIME ZONE
);

17
doc/scripts/3.2.0/schema/personal_training_create.sql

@ -0,0 +1,17 @@
CREATE TABLE personal_training (
ID serial PRIMARY KEY NOT NULL,
personalName VARCHAR ( 255 ) NOT NULL,-- 姓名
departmentName VARCHAR ( 255 ) NOT NULL,-- 部门名称
trainingType VARCHAR ( 255 ) NOT NULL,-- 培训类型
topic VARCHAR ( 255 ) NOT NULL,-- 课程主题
trainer VARCHAR ( 255 ) NOT NULL,-- 培训讲师
trainDate TIMESTAMP NOT NULL,-- 培训时间
trainTime VARCHAR ( 255 ) NOT NULL,-- 培训时长
trainMethod VARCHAR ( 255 ) NOT NULL,-- 培训方式
attendanceScore VARCHAR ( 255 ),-- 考勤分数
appraisalMethod VARCHAR ( 255 ) NOT NULL,-- 考核形式
appraisalScore VARCHAR ( 255 ),-- 考核分数
totalScore VARCHAR ( 255 ),-- 总分
origin VARCHAR ( 255 ) --
);

29
doc/scripts/PEP V3.2.0/schema/01 create_training_information.sql

@ -0,0 +1,29 @@
create table training_information
(
id serial not null
constraint training_information_record_pkey
primary key,
departmentname varchar(255) not null,
traindate varchar(255),
filetype varchar(255),
filename varchar(255),
filesize varchar(255),
updatedate timestamp,
attachpath varchar(255)
);
comment on table training_information is '公司培训资源库';
comment on column training_information.departmentname is '部门分类';
comment on column training_information.traindate is '时间(三级目录)';
comment on column training_information.filetype is '文件类型';
comment on column training_information.filename is '文件名';
comment on column training_information.filesize is '文件大小';
comment on column training_information.updatedate is '更新时间';
comment on column training_information.attachpath is '文件路径';

11
jenkinsfile_poms_api

@ -6,13 +6,12 @@ pipeline {
}
stages {
stage('Testing poms ......') {
stage('Testing hrm api......') {
steps {
sh 'switch-auth.sh anxinyun'
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}"
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./api'
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}'
buildName '#${BUILD_NUMBER} ~/pep/${JOB_NAME}:${IMAGE_VERSION}'
buildDescription 'harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}'
sh 'nerdctl build -t harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION} ./api'
sh 'nerdctl push harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}'
}
}
}

11
jenkinsfile_poms_web

@ -6,13 +6,12 @@ pipeline {
}
stages {
stage('Testing poms ......') {
stage('Testing hrm-web ......') {
steps {
sh 'switch-auth.sh anxinyun'
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}"
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./web'
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}'
buildName "#${BUILD_NUMBER} ~/pep/${JOB_NAME}:${IMAGE_VERSION}"
buildDescription "harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}"
sh 'nerdctl build -t harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION} ./web'
sh 'nerdctl push harbor.anxinyun.cn/pep/${JOB_NAME}:${IMAGE_VERSION}'
}
}
}

21
web/Dockerfile

@ -27,14 +27,19 @@
# 旧版本构建方式
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node:12-dev as builder
COPY . /var/app
WORKDIR /var/app
EXPOSE 8080
CMD ["-u", "http://localhost:8088"]
ENTRYPOINT [ "node", "server.js" ]
RUN npm config set registry=http://10.8.30.22:7000
RUN echo "{\"time\":\"$BUILD_TIMESTAMP\",\"build\": \"$BUILD_NUMBER\",\"revision\": \"$SVN_REVISION_1\",\"URL\":\"$SVN_URL_1\"}" > version.json
RUN npm cache clean -f
RUN npm install --registry http://10.8.30.22:7000
RUN npm run build
RUN rm -rf client/src
RUN rm -rf node_modules
RUN npm install --production --force --registry http://10.8.30.22:7000
FROM registry.cn-hangzhou.aliyuncs.com/fs-devops/node-16:7.22-06-20
COPY --from=builder --chown=node /var/app /home/node/app
WORKDIR /home/node/app
CMD ["node", "server.js"]

13
web/client/src/sections/humanAffairs/actions/resourceRepository.js

@ -32,8 +32,7 @@ export function postResourceClassify(data) {
data,
actionType: "POST_RESOURCE_CLASSIFY",
url: `${ApiTable.postResourceClassify}`,
msg: { option: "新增" },
reducer: { name: "" },
msg: { success: "新建成功" },
});
}
@ -45,20 +44,18 @@ export function putResourceClassify(data) {
data,
actionType: "PUT_RESOURCE_CLASSIFY",
url: `${ApiTable.putResourceClassify}`,
msg: { option: "修改" },
reducer: {},
msg: { option: "编辑" },
});
}
export function delResourceClassify(data) {
export function delResourceClassify(query) {
return (dispatch) =>
basicAction({
type: "del",
query: data,
query: query,
dispatch: dispatch,
actionType: "DEL_RESOURCE_CLASSIFY",
url: `${ApiTable.delResourceClassify}`,
msg: { option: "删除" }, //删除
reducer: {},
msg: { option: "删除" },
});
}

99
web/client/src/sections/humanAffairs/components/resourceRepository/folder-model.jsx

@ -0,0 +1,99 @@
import React, { useRef } from 'react';
import { Modal, Form, Button, Input } from '@douyinfe/semi-ui';
const FolderModal = (props) => {
const { modalData, oldData, onCancel, onOk } = props;
const { title, childFolder, departmentName, trainDate } = modalData;
const add = title.includes("新建");
const form = useRef();//
const validatName = (val) => {
if (val && '' == val.trim()) {
return '不可以为空';
} else
if (val.length > 20) {
return '最大20字符';
} else {
if (oldData.children) {
if (childFolder) {//
let deptChild = oldData.children.find(r => r.label == departmentName).children;
if (!add) {
deptChild = deptChild.filter(r => trainDate != r.label);
}
const old = deptChild.find(r => r.label == val.trim());
if (old) {
return ("该文件已存在");
} else {
return '';
}
} else { //
let deptData = oldData.children;
if (!add) {
deptData = deptData.filter(r => departmentName != r.label);
}
const old = deptData.find(r => r.label == val.trim());
if (old) {
return ("该文件已存在");
} else {
return '';
}
}
}
}
return '';
}
const handleOk = () => {
form.current.validate().then((values) => {
if (!add) {
values.oldDepName = departmentName;
values.oldTrainDate = trainDate;
}
onOk(add, values);
});
}
return (<Modal
title={`${title}文件夹`}
visible={true}
maskClosable={false}
onOk={handleOk}
onCancel={onCancel}>
<Form
getFormApi={(formApi) => (form.current = formApi)}
labelPosition={'left'}
labelAlign={'right'}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
{!childFolder && <Form.Input
field="name"
label="主文件夹"
initValue="公司档案"
disabled={true}
/>}
<Form.Input
field="departmentName"
label="二级文件夹"
initValue={departmentName}
disabled={childFolder}
validate={validatName}
trigger='blur'
rules={[{ required: true, message: "请输入二级文件夹" },
{ whitespace: true, message: '不允许输入空格' },
// { max: 20, message: "20" }
]}
/>
{childFolder &&
< Form.Input
field="trainDate"
label="子文件夹"
initValue={trainDate}
validate={validatName}
trigger='blur'
rules={[{ required: true, message: "请输入子文件夹" }]}
/>}
</Form>
</Modal >
)
}
export default FolderModal

6
web/client/src/sections/humanAffairs/containers/departmentTrain/departmentTrainRecord.jsx

@ -128,11 +128,7 @@ const DepartmentTrainRecord = (props) => {
render: (text, record) => {
if (record.origin === 'import')
return <div>
<span style={{ color: '#1890FF', cursor: 'pointer' }} onClick={() => onEdit(record)}>编辑</span>&nbsp;&nbsp;
{/* <Popconfirm
title='提示' content="确认删除该部门培训记录信息?" position='topLeft'
onConfirm={() => confirmDelete(record.id)} style={{ width: 330 }}
> <span style={{ color: '#1890FF', cursor: 'pointer' }}>删除</span></Popconfirm> */}
<span style={{ color: '#1890FF', cursor: 'pointer' }} onClick={() => onEdit(record)}>编辑</span>
</div>
else
return <span>-</span>

3
web/client/src/sections/humanAffairs/containers/departmentTrain/editModal.js

@ -82,7 +82,8 @@ const EditModal = (props) => {
return '';
}
};
//validate和validateContent写通用方法后,校验文本不提示了..奇怪
//validate和validateContent-暂不修改合并
const validateContent = (val, values) => {
if (!val) {
setValidateStatus('error');

2
web/client/src/sections/humanAffairs/containers/departmentTrain/importModal.js

@ -116,7 +116,7 @@ const ImportModal = props => {
<Form.Upload
label={'部门培训记录'} labelPosition='left'
action={'/'} accept={'.xlsx'}
maxSize={102400} limit={1}
maxSize={204800} limit={1}
onRemove={(currentFile, fileList, fileItem) => {
setMsg('');
setPostData([]);

132
web/client/src/sections/humanAffairs/containers/resourceRepository.jsx

@ -1,8 +1,9 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { Button, Col, Row, Input, Tree, Table, Space, Tooltip, Spin } from '@douyinfe/semi-ui';
import { Button, Col, Row, Input, Tree, Table, Space, Tooltip, Spin, Popconfirm } from '@douyinfe/semi-ui';
import { IconSearch, IconEditStroked, IconMinusCircleStroked, IconPlusCircleStroked } from '@douyinfe/semi-icons';
import { getResourceClassify, getResourceFileList } from '../actions/resourceRepository';
import { getResourceClassify, getResourceFileList, postResourceClassify, putResourceClassify, delResourceClassify } from '../actions/resourceRepository';
import FolderModal from '../components/resourceRepository/folder-model';
import '../style.less';
const ResourceRepository = (props) => {
@ -10,27 +11,12 @@ const ResourceRepository = (props) => {
const [treeData, setTreeData] = useState([]);
const [currentSelect, setCurrentSelect] = useState();
const [defaultExpandedKey, setDefaultExpandedKey] = useState();
const [modelVisiable, setModelVisiable] = useState(false);
const [modalData, setModalData] = useState();
const ref = useRef();
useEffect(() => {
dispatch(getResourceClassify()).then(res => {
const { success, payload } = res;
if (success) {
let defaultKey = "";
if (payload.data.length) {
if (payload.data[0].children && payload.data[0].children.length) {
defaultKey = payload.data[0].children[0].key;
setDefaultExpandedKey([payload.data[0].key, payload.data[0].children[0].key]);
} else {
defaultKey = payload.data[0].key;
setDefaultExpandedKey([payload.data[0].key]);
}
}
setCurrentSelect([defaultKey]);
setTreeData(payload.data);
getFile(defaultKey);
}
});
getClassify();
}, [])
const style = {
@ -60,21 +46,73 @@ const ResourceRepository = (props) => {
}
];
const renderLabel = (label, data) => (<div>
<Tooltip content={label}><span >{label.length > 8 ? label.substring(0, 8) + '...' : label}</span></Tooltip>
{true == data.operation ?
<span className='tree-icon'>
<IconEditStroked size='default' onClick={() => alert("bianji")} />
<IconMinusCircleStroked size='default' onClick={() => alert("sahnchu")} />
{data.children ? <IconPlusCircleStroked size='default' onClick={() => alert("+")} /> : ''}
</span>
: ''}
</div>
);
const renderLabel = (label, data) => {
const child = data.children ? true : false;
const key = data.key.split('/');
return (<div>
<Tooltip content={label}><span >{label.length > 8 ? label.substring(0, 8) + '...' : label}</span></Tooltip>
{true == data.operation ?
<span className='tree-icon'>
<IconEditStroked size='default' onClick={() => handleFolderClick(child ? '编辑' : '编辑子', !child, key[1], key[2] || undefined)} />
<Popconfirm
title="确定是否要删除?"
content="该文件夹下的所有子文件/附件将永久删除,请慎重!"
onConfirm={() => handleDel(data.key)}
// onCancel={onCancel}
>
<IconMinusCircleStroked size='default' />
</Popconfirm>
{child ?
<IconPlusCircleStroked
size='default'
onClick={() => handleFolderClick('新建子', true, label, undefined)}
/> : ''}
</span>
: ''}
</div>)
};
const handleFolderClick = (title, childFolder, departmentName, trainDate) => {
setModelVisiable(true);
setModalData({ title, childFolder, departmentName, trainDate });
}
const handleSelect = (e) => {
setCurrentSelect(e);
getFile(e);
}
const handleDataToSave = (add, body) => {
if (add) {
dispatch(postResourceClassify(body)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
} else {
dispatch(putResourceClassify(body)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
}
}
const handleDel = (key) => {
const arr = key.split('/');
const query = {
departmentName: arr[1]
}
if (arr.length == 3) {
query.trainDate = arr[2];
}
dispatch(delResourceClassify(query)).then(res => {
if (res.success) {
getClassify();
setModelVisiable(false);
}
});
}
const getFile = (e) => {
const arr = e.split("/");
const query = { type: arr[0] };
@ -82,6 +120,26 @@ const ResourceRepository = (props) => {
if (arr[2]) { query.trainDate = arr[2]; }
dispatch(getResourceFileList(query));
}
const getClassify = () => {
dispatch(getResourceClassify()).then(res => {
const { success, payload } = res;
if (success) {
let defaultKey = "";
if (payload.data.length) {
if (payload.data[0].children && payload.data[0].children.length) {
defaultKey = payload.data[0].children[0].key;
setDefaultExpandedKey([payload.data[0].key, payload.data[0].children[0].key]);
} else {
defaultKey = payload.data[0].key;
setDefaultExpandedKey([payload.data[0].key]);
}
}
setCurrentSelect([defaultKey]);
setTreeData(payload.data);
getFile(defaultKey);
}
});
}
return (
<>
@ -105,7 +163,7 @@ const ResourceRepository = (props) => {
<Row className='resourceRepository'>
{/* 左侧 */}
<Col className='left' span={6}>
<Button theme='solid' type='primary' >新建文件夹</Button>
<Button theme='solid' type='primary' onClick={() => handleFolderClick("新建", false)}>新建文件夹</Button>
<br />
<Input suffix={<IconSearch />} showClear onChange={v => ref.current.search(v)} placeholder="请输入"></Input>
<Tree
@ -129,7 +187,7 @@ const ResourceRepository = (props) => {
<Row type="flex" justify="space-around" align="middle">
<Col span={18}>
<Space>
<Button theme='solid' type='primary' >上传文件</Button>
{currentSelect && currentSelect.includes("部门培训资料") ? null : <Button theme='solid' type='primary' >上传文件</Button>}
<span className="path-lable"><strong>当前文件夹{currentSelect}</strong></span>
</Space>
</Col>
@ -145,6 +203,14 @@ const ResourceRepository = (props) => {
</Row>
</Spin>
</div>
{modelVisiable ?
<FolderModal
oldData={resourceClassify && resourceClassify.find(r => '公司培训资料' == r.label)}
modalData={modalData}
onOk={handleDataToSave}
onCancel={() => { setModelVisiable(false) }}
/> : null
}
</div>
</>
)

4
web/client/src/utils/webapi.js

@ -51,8 +51,8 @@ export const ApiTable = {
//-培训资料库
getResourceClassify: 'train/trainFiles/resourceRepository/classify',
postResourceClassify: 'train/trainFiles/resourceRepository/classify',
putResourceClassify: 'train/trainFiles/resourceRepository/classify/{id}',
delResourceClassify: 'train/trainFiles/resourceRepository/classify/{id}',
putResourceClassify: 'train/trainFiles/resourceRepository/classify',
delResourceClassify: 'train/trainFiles/resourceRepository/classify',
getResourceFileList: 'train/trainFiles/resourceRepository/fileList',
};

Loading…
Cancel
Save