Browse Source

(*)培训资料库:左侧数据联动右侧

master
周沫沫历险记 2 years ago
parent
commit
9f5835230e
  1. 51
      api/app/lib/controllers/resourceRepository/index.js
  2. 0
      api/app/lib/models/training_information.js
  3. 3
      api/app/lib/routes/resourceRepository/index.js
  4. 14
      web/client/src/sections/humanAffairs/actions/resourceRepository.js
  5. 220
      web/client/src/sections/humanAffairs/containers/resourceRepository.jsx
  6. 1
      web/client/src/utils/webapi.js

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

@ -4,13 +4,7 @@ const moment = require('moment')
async function getResourceClassify(ctx) {
try {
const { models } = ctx.fs.dc;
// const { limit, offset } = ctx.query;
let rlst = [];
// const findObj = {}
// if (Number(limit) > 0 && Number(offset) >= 0) {
// findObj.limit = Number(limit);
// findObj.offset = Number(offset);
// }
rlst = [{
label: "公司培训资料", value: "company", key: "公司培训资料", operation: true, children: []
}, { label: "部门培训资料", value: 'dept', key: '部门培训资料', operation: false, children: [] }];
@ -99,17 +93,16 @@ async function getResourceClassify(ctx) {
}
}
}
const deptTraining = await models.DeptTraining.findAll({});
if (deptTraining.length) {
filterData(deptTraining, 1, false);
}
const trainingInformation = await models.TrainingInformation.findAll({});
if (trainingInformation.length) {
filterData(trainingInformation, 0, true);
}
ctx.status = 200;
ctx.body = rlst;
} catch (error) {
@ -119,9 +112,49 @@ async function getResourceClassify(ctx) {
message: '查询培训资源储备库分类目录失败'
}
}
}
async function getResourceFileList(ctx, next) {
try {
const { models } = ctx.fs.dc;
const { limit, offset, type, departmentName, trainDate } = ctx.query;
let rlst = [];
if (["公司培训资料", "部门培训资料"].includes(type)) {
const findObj = {
attributes: ["id", "fileType", "fileName", "fileSize", "updateDate", "attachPath"],
};
if (Number(limit) > 0 && Number(offset) >= 0) {
findObj.limit = Number(limit);
findObj.offset = Number(offset);
}
if (departmentName) {
const where = {
departmentName: departmentName
}
if (trainDate) {
//todo
// where.trainDate = trainDate
}
findObj.where = where;
}
if ("公司培训资料" == type) {
rlst = await models.TrainingInformation.findAndCountAll(findObj);
} else {
rlst = await models.DeptTraining.findAndCountAll(findObj);
}
} else {
ctx.throw("培训资料范围为公司或部门");
}
ctx.status = 200;
ctx.body = rlst;
} catch (err) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = { message: err.message || '查询培训资源储备库文件列表失败' }
}
}
module.exports = {
getResourceClassify
getResourceClassify,
getResourceFileList
}

0
api/app/lib/models/training_information_record.js → api/app/lib/models/training_information.js

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

@ -6,4 +6,7 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/train/trainFiles/resourceRepository/classify'] = { content: '查询培训资源储备库分类目录', visible: false };
router.get('/train/trainFiles/resourceRepository/classify', resourceRepository.getResourceClassify);
app.fs.api.logAttr['GET/train/trainFiles/resourceRepository/fileList'] = { content: '查询培训资源储备库文件列表', visible: false };
router.get('/train/trainFiles/resourceRepository/fileList', resourceRepository.getResourceFileList);
};

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

@ -1,8 +1,7 @@
'use strict';
import { ApiTable, basicAction } from '$utils'
export function getResourceClassify() {//查询籍贯列表
export function getResourceClassify() {
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
@ -13,6 +12,17 @@ export function getResourceClassify() {//查询籍贯列表
reducer: { name: "resourceClassify" },
});
}
export function getResourceFileList(query) {
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_RESOURCE_FILELIST",
query: query,
url: `${ApiTable.getResourceFileList}`,
msg: { option: "查询培训资源储备库文件列表" },
reducer: { name: "resourceFilelist" },
});
}
export function postResourceClassify(data) {
return (dispatch) =>

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

@ -1,21 +1,35 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { Button, Col, Row, Input, Tree, Table, Space, Tooltip } from '@douyinfe/semi-ui';
import { Button, Col, Row, Input, Tree, Table, Space, Tooltip, Spin } from '@douyinfe/semi-ui';
import { IconSearch, IconEditStroked, IconMinusCircleStroked, IconPlusCircleStroked } from '@douyinfe/semi-icons';
import { getResourceClassify } from '../actions/resourceRepository';
import '../style.less'
import { getResourceClassify, getResourceFileList } from '../actions/resourceRepository';
import '../style.less';
const ResourceRepository = (props) => {
const { dispatch, actions, clientHeight, resourceClassify } = props;
const { dispatch, clientHeight, resourceClassify, resourceFilelist, isRequesting } = props;
const [treeData, setTreeData] = useState([]);
const [currentSelect, setCurrentSelect] = useState();
const [defaultExpandedKey, setDefaultExpandedKey] = useState();
const ref = useRef();
useEffect(() => {
dispatch(getResourceClassify()).then(res => {
const { success, payload } = res;
if (success)
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);
}
});
}, [])
@ -27,117 +41,25 @@ const ResourceRepository = (props) => {
const columns = [
{
title: '文件类型',
dataIndex: 'name',
dataIndex: 'fileType',
},
{
title: '文件名称',
dataIndex: 'size',
dataIndex: 'fileName',
},
{
title: '大小',
dataIndex: 'owner',
dataIndex: 'fileSize',
},
{
title: '更新时间',
dataIndex: 'updateTime',
dataIndex: 'updateDate',
}, {
title: '操作',
dataIndex: 'action',
}
];
const data = [
// {
// key: '1',
// name: 'Semi Design 稿.fig',
// nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
// size: '2M',
// owner: '',
// updateTime: '2020-02-02 05:13',
// avatarBg: 'grey',
// },
// {
// key: '2',
// name: 'Semi Design 稿',
// nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
// size: '2M',
// owner: '',
// updateTime: '2020-01-17 05:31',
// avatarBg: 'red',
// },
// {
// key: '3',
// name: '',
// nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
// size: '34KB',
// owner: 'Zoey Edwards',
// updateTime: '2020-01-26 11:01',
// avatarBg: 'light-blue',
// },
{
key: '4',
name: 'Semi Design 设计稿.fig',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
size: '2M',
owner: '姜鹏志',
updateTime: '2020-02-02 05:13',
avatarBg: 'grey',
},
{
key: '5',
name: 'Semi Design 分享演示文稿',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
size: '2M',
owner: '郝宣',
updateTime: '2020-01-17 05:31',
avatarBg: 'red',
},
{
key: '6',
name: '设计文档',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
size: '34KB',
owner: 'Zoey Edwards',
updateTime: '2020-01-26 11:01',
avatarBg: 'light-blue',
},
{
key: '7',
name: 'Semi Design 设计稿.fig',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
size: '2M',
owner: '姜鹏志',
updateTime: '2020-02-02 05:13',
avatarBg: 'grey',
},
{
key: '8',
name: 'Semi Design 分享演示文稿',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
size: '2M',
owner: '郝宣',
updateTime: '2020-01-17 05:31',
avatarBg: 'red',
},
{
key: '9',
name: '设计文档',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
size: '34KB',
owner: 'Zoey Edwards',
updateTime: '2020-01-26 11:01',
avatarBg: 'light-blue',
},
{
key: '10',
name: '设计文档',
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
size: '34KB',
owner: 'Zoey Edwards',
updateTime: '2020-01-26 11:01',
avatarBg: 'light-blue',
}
];
const renderLabel = (label, data) => (<div>
<Tooltip content={label}><span >{label.length > 8 ? label.substring(0, 8) + '...' : label}</span></Tooltip>
{true == data.operation ?
@ -148,7 +70,17 @@ const ResourceRepository = (props) => {
</span>
: ''}
</div>
)
);
const handleSelect = (e) => {
getFile(e);
}
const getFile = (e) => {
const arr = e.split("/");
const query = { type: arr[0] };
if (arr[1]) { query.departmentName = arr[1]; }
if (arr[2]) { query.trainDate = arr[2]; }
dispatch(getResourceFileList(query));
}
return (
<>
@ -168,40 +100,48 @@ const ResourceRepository = (props) => {
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>RESOURCE REPOSITORY</div>
</div>
</div>
<Row className='resourceRepository'>
{/* 左侧 */}
<Col className='left' span={6}>
<Button theme='solid' type='primary' >新建文件夹</Button>
<br />
<Input suffix={<IconSearch />} showClear onChange={v => ref.current.search(v)} placeholder="请输入"></Input>
<Tree
ref={ref}
treeData={treeData}
defaultExpandAll
filterTreeNode
searchRender={false}
blockNode={false}
directory
style={style}
renderLabel={renderLabel}
/>
</Col>
{/* 右侧内容 */}
<Col span={18} className='right'>
<Row type="flex" justify="space-around" align="middle">
<Col span={18}>
<Space>
<Button theme='solid' type='primary' >上传文件</Button>
<span className="path-lable"><strong>当前文件夹公司培训资源/人力资源部2/2022-11</strong></span>
</Space>
</Col>
<Col span={6} >
<Input suffix={<IconSearch />} showClear placeholder="文件名称、更新时间"></Input>
</Col>
</Row>
<Table columns={columns} dataSource={data} pagination={false} />
</Col>
</Row>
<Spin spinning={isRequesting}>
<Row className='resourceRepository'>
{/* 左侧 */}
<Col className='left' span={6}>
<Button theme='solid' type='primary' >新建文件夹</Button>
<br />
<Input suffix={<IconSearch />} showClear onChange={v => ref.current.search(v)} placeholder="请输入"></Input>
<Tree
ref={ref}
defaultExpandAll={true}
treeData={treeData}
style={style}
expandedKeys={defaultExpandedKey}
filterTreeNode={true}
searchRender={false}
directory={true}
showFilteredOnly={true}
renderLabel={renderLabel}
onExpand={(e) => setDefaultExpandedKey(e)}
onSelect={handleSelect}
/>
</Col>
{/* 右侧内容 */}
<Col span={18} className='right'>
<Row type="flex" justify="space-around" align="middle">
<Col span={18}>
<Space>
<Button theme='solid' type='primary' >上传文件</Button>
<span className="path-lable"><strong>当前文件夹{currentSelect}</strong></span>
</Space>
</Col>
<Col span={6} >
<Input suffix={<IconSearch />} showClear placeholder="文件名称、更新时间"></Input>
</Col>
</Row>
<Table
columns={columns}
dataSource={resourceFilelist && resourceFilelist.rows || []}
pagination={false} />
</Col>
</Row>
</Spin>
</div>
</div>
</>
@ -209,12 +149,14 @@ const ResourceRepository = (props) => {
}
function mapStateToProps(state) {
const { auth, global, resourceClassify } = state;
const { auth, global, resourceClassify, resourceFilelist } = state;
return {
user: auth.user,
actions: global.actions,
clientHeight: global.clientHeight,
resourceClassify: resourceClassify.data || []
resourceClassify: resourceClassify.data || [],
resourceFilelist: resourceFilelist.data && resourceFilelist.data,
isRequesting: resourceClassify.isRequesting || resourceFilelist.isRequesting
};
}

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

@ -52,6 +52,7 @@ export const ApiTable = {
postResourceClassify: 'train/trainFiles/resourceRepository/classify',
putResourceClassify: 'train/trainFiles/resourceRepository/classify/{id}',
delResourceClassify: 'train/trainFiles/resourceRepository/classify/{id}',
getResourceFileList: 'train/trainFiles/resourceRepository/fileList',
};
export const RouteTable = {

Loading…
Cancel
Save