Compare commits
22
Commits
26776efbff
..
mgy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
166c8b6319 | ||
|
|
fbaedaad0e | ||
|
|
31a782daef | ||
|
|
31e48dafc8 | ||
|
|
31188c0bb0 | ||
|
|
57c0fed976 | ||
|
|
56174936d3 | ||
|
|
24817aea50 | ||
|
|
7316208b21 | ||
|
|
fb8b0ddc6e | ||
|
|
36bc6653e2 | ||
|
|
3187c7be28 | ||
|
|
7ee06b9901 | ||
|
|
787b52c096 | ||
|
|
3619ce3d1e | ||
|
|
c24a82d177 | ||
|
|
ec711daa0c | ||
|
|
d91ece0c54 | ||
|
|
1937fa4217 | ||
|
|
50e3f4a8f0 | ||
|
|
52a6968f4e | ||
|
|
385f77fb90 |
@@ -1,46 +1,60 @@
|
||||
# Getting Started with Create React App
|
||||
# Notify Admin
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
## 目标
|
||||
|
||||
## Available Scripts
|
||||
1. 微信小程序的信息管理页面
|
||||
2. 人资部后台(长期)
|
||||
|
||||
In the project directory, you can run:
|
||||
## 功能
|
||||
|
||||
### `npm start`
|
||||
### 主席团管理页面
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
1. 值班表导入、更新
|
||||
1. 值班表渲染
|
||||
2. 值班表在线更改、上传后端
|
||||
3. 值班表导出
|
||||
2. 成员权限管理
|
||||
1. 从 Auth 获取成员职位、部门
|
||||
2. 主席团成员:可更改所有信息
|
||||
3. 当班所有成员:可更改值班人数,可加入 Oreo,可更改状态
|
||||
4. 所有成员:可认领
|
||||
3. 特殊维修时间(如学园维修)、值班信息更新
|
||||
4. 日志
|
||||
1. 记录每一次操作、操作者
|
||||
5. 自动排班功能(Enhancement)
|
||||
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
### 值班组长管理页面
|
||||
|
||||
### `npm test`
|
||||
ps. 是微信小程序中小组管理页面的pc端替代
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
1. 值班组长上传本班相关信息
|
||||
2. 值班组长上传值班总结(Enhancement)
|
||||
|
||||
### `npm run build`
|
||||
## UI
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
### 仪表盘
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
1. 个人信息、职位
|
||||
2. 新系统中(未加入Oreo/预填写工单总数)统计
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
### 主席团管理页面
|
||||
|
||||
### `npm run eject`
|
||||
#### 值班表管理
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
1. 值班表渲染
|
||||
2. 值班表在线更改、上传后端
|
||||
1. 特殊时间值班表不上传
|
||||
3. 值班表导出
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
#### 特殊值班时间
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
1. (switch) 是否启用平常值班时间
|
||||
2. 若不在平常值班时间,选择录入不值班原因/特殊值班时间
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
### 值班组长管理页面(暂空)
|
||||
|
||||
## Learn More
|
||||
1. (Enhancement) 值班总结上传
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
### 日志(所有人可见)
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
1. 查询功能
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
# 接口文档
|
||||
|
||||
## 基本格式
|
||||
|
||||
### 成功响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"foo": "bar"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**NOTE:** 若无特殊说明,`POST`请求的响应`data`字段为空(`{}`),可以不用管。
|
||||
|
||||
### 失败响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"err": "some error"
|
||||
}
|
||||
```
|
||||
|
||||
### `GET`请求默认格式(若无特殊说明)
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "token_test"
|
||||
}
|
||||
```
|
||||
|
||||
## 主页面
|
||||
|
||||
### 统计数据 `GET /admin/stats`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"notInOreo": 114,
|
||||
"total": 514
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 当前值班信息 `GET /admin/duty/current`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"isInDuty": true,
|
||||
"currentDuty": "2",
|
||||
"inDutyCnt": 3,
|
||||
"otherDutyTime": "",
|
||||
"offDutyReason": "",
|
||||
"place": "204",
|
||||
"dutyRecoverTime": ""
|
||||
}
|
||||
```
|
||||
|
||||
## 主席团页面
|
||||
|
||||
### 值班表管理
|
||||
|
||||
#### 更新值班表 `POST /admin/sheet/create`
|
||||
|
||||
request:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "2024 春学期值班表",
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["马嘉祺", "丁程鑫", "宋亚轩"],
|
||||
"leader": "蔡徐坤"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["王俊凯", "易烊千玺", "王源"],
|
||||
"leader": "丁真珍珠"
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 更新值班表 `POST /admin/sheet/update`
|
||||
|
||||
request:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 114514,
|
||||
"name": "2024 春学期值班表",
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["马嘉祺", "丁程鑫", "宋亚轩"],
|
||||
"leader": "蔡徐坤"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["王俊凯", "易烊千玺", "王源"],
|
||||
"leader": "丁真珍珠"
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 获取当前值班表 `GET /admin/sheet/current`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "2024 春学期值班表",
|
||||
"id": 114514,
|
||||
"createdTime": "2024-03-07T19:52:48.523303",
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["马嘉祺", "丁程鑫", "宋亚轩"],
|
||||
"leader": "蔡徐坤"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["王俊凯", "易烊千玺", "王源"],
|
||||
"leader": "丁真珍珠"
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 获取所有值班表 `GET /admin/sheet/list`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"current": 114514,
|
||||
"list": [
|
||||
{
|
||||
"name": "2024 春学期值班表",
|
||||
"id": 114514,
|
||||
"createdTime": "2024-03-07T19:52:48.523303",
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["马嘉祺", "丁程鑫", "宋亚轩"],
|
||||
"leader": "蔡徐坤"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["王俊凯", "易烊千玺", "王源"],
|
||||
"leader": "丁真珍珠"
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 特殊值班
|
||||
|
||||
#### 获取当前值班情况 `GET /admin/duty/current`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"isInDuty": true,
|
||||
"currentDuty": "2",
|
||||
"inDutyCnt": 3,
|
||||
"otherDutyTime": "",
|
||||
"offDutyReason": "",
|
||||
"place": "",
|
||||
"dutyRecoverTime": "",
|
||||
},
|
||||
```
|
||||
|
||||
#### 更新当前值班情况 `POST /admin/duty/update`
|
||||
|
||||
无关项返回空字符串,后端手动校验
|
||||
|
||||
request:
|
||||
|
||||
```json
|
||||
{
|
||||
"isInDuty": true,
|
||||
"currentDuty": "2",
|
||||
"inDutyCnt": 3,
|
||||
"otherDutyTime": "",
|
||||
"offDutyReason": "",
|
||||
"place": "204",
|
||||
"dutyRecoverTime": "",
|
||||
},
|
||||
```
|
||||
|
||||
## 日志页面
|
||||
|
||||
### 获取日志列表 `GET /admin/loglist`
|
||||
|
||||
data:
|
||||
|
||||
```json
|
||||
{
|
||||
"op": "宇航员",
|
||||
"time": "2024-03-07T19:52:48.523303",
|
||||
"operation": 2,
|
||||
"target": 1,
|
||||
"prev": {
|
||||
"id": 114,
|
||||
"info": "马嘉祺"
|
||||
},
|
||||
"curr": {
|
||||
"id": 514,
|
||||
"info": "何君琳"
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
前端显示的信息:"{op} 于 {time} {operation} 了 {target}:{prev.info} -> {curr.info}"
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import sheetlist from './sheetlist.json';
|
||||
import sheet from './sheet.json';
|
||||
|
||||
const api = {
|
||||
'GET /admin/stats': {
|
||||
success: true,
|
||||
data: {
|
||||
notInOreo: 114,
|
||||
total: 514,
|
||||
},
|
||||
},
|
||||
'POST /admin/sheet/update': {
|
||||
success: true,
|
||||
data: {},
|
||||
},
|
||||
'POST /admin/sheet/create': {
|
||||
success: true,
|
||||
data: {},
|
||||
},
|
||||
'GET /admin/sheet/current': {
|
||||
success: true,
|
||||
data: sheet,
|
||||
},
|
||||
'GET /admin/sheet/list': {
|
||||
success: true,
|
||||
data: sheetlist,
|
||||
},
|
||||
'GET /admin/duty/current': {
|
||||
success: true,
|
||||
data: {
|
||||
isInDuty: true,
|
||||
currentDuty: '2',
|
||||
inDutyCnt: 3,
|
||||
otherDutyTime: '',
|
||||
offDutyReason: '',
|
||||
place: '204',
|
||||
dutyRecoverTime: '',
|
||||
},
|
||||
},
|
||||
'POST /admin/duty/update': {
|
||||
success: true,
|
||||
data: {},
|
||||
},
|
||||
'GET /admin/loglist': {
|
||||
success: true,
|
||||
data: {
|
||||
op: '宇航员',
|
||||
time: '2024-03-07T19:52:48.523303',
|
||||
operation: 2,
|
||||
target: 1,
|
||||
prev: {
|
||||
id: 114,
|
||||
info: '马嘉祺',
|
||||
},
|
||||
curr: {
|
||||
id: 514,
|
||||
info: '何君琳',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default api;
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"name": "2024 春学期值班表",
|
||||
"createdTime": "2024-03-07T19:52:48.523303",
|
||||
"id": 114,
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
{
|
||||
"current": 514,
|
||||
"list": [
|
||||
{
|
||||
"name": "2024 春学期值班表",
|
||||
"createdTime": "2024-03-07T19:52:48.523303",
|
||||
"id": 114,
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "2024 秋学期值班表",
|
||||
"createdTime": "2024-03-07T11:45:14.523303",
|
||||
"id": 514,
|
||||
"sheet": [
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 1,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 2,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 3,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 4,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 5,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 6,
|
||||
"shift": 3,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 1,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
},
|
||||
{
|
||||
"weekday": 7,
|
||||
"shift": 2,
|
||||
"workers": ["123423", "31424", "31242"],
|
||||
"leader": "3902487"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Generated
+1506
-9
File diff suppressed because it is too large
Load Diff
+5
-2
@@ -6,14 +6,18 @@
|
||||
"name": "EVA Tech"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^5.3.1",
|
||||
"@ant-design/pro-components": "^2.6.52",
|
||||
"@types/node": "^16.18.88",
|
||||
"@types/react": "^18.2.65",
|
||||
"@types/react-dom": "^18.2.21",
|
||||
"antd": "^5.15.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-scripts": "5.0.1",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
@@ -37,7 +41,6 @@
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"husky": "^9.0.11",
|
||||
"lint-staged": "^15.2.2",
|
||||
"sass": "^1.71.1",
|
||||
"stylelint": "^16.2.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
+3
-22
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
@@ -15,29 +15,10 @@
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>EVA Tea</title>
|
||||
</head>
|
||||
<body>
|
||||
<body style="margin: 0;">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
+144
-6
@@ -1,9 +1,147 @@
|
||||
function App() {
|
||||
return (
|
||||
<div>
|
||||
<p>Hello</p>
|
||||
</div>
|
||||
);
|
||||
import { FC } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
TeamOutlined,
|
||||
HomeOutlined,
|
||||
SmileOutlined,
|
||||
CrownOutlined,
|
||||
ClockCircleOutlined,
|
||||
ThunderboltOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { MenuProps } from 'antd';
|
||||
import { Breadcrumb, Layout, Menu, theme } from 'antd';
|
||||
import { AppRouter, routes, routeName } from './router';
|
||||
import PageFooter from './components/PageFooter';
|
||||
|
||||
const { Content, Sider } = Layout;
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
type KeyRouterMap = Map<React.Key, string>;
|
||||
|
||||
const keyRouterMap: KeyRouterMap = new Map();
|
||||
|
||||
function getItem(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon?: React.ReactNode,
|
||||
children?: MenuItem[],
|
||||
): MenuItem {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
} as MenuItem;
|
||||
}
|
||||
|
||||
function defMenu(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon: React.ReactNode,
|
||||
path: string,
|
||||
): MenuItem {
|
||||
keyRouterMap.set(key, path);
|
||||
return getItem(label, key, icon);
|
||||
}
|
||||
|
||||
function defRootMenu(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
icon: React.ReactNode,
|
||||
children: MenuItem[],
|
||||
): MenuItem {
|
||||
return getItem(label, key, icon, children);
|
||||
}
|
||||
|
||||
function defSubMenu(
|
||||
label: React.ReactNode,
|
||||
key: React.Key,
|
||||
path: string,
|
||||
): MenuItem {
|
||||
keyRouterMap.set(key, path);
|
||||
return getItem(label, key);
|
||||
}
|
||||
|
||||
const items: MenuItem[] = [
|
||||
defMenu('主页', 'mainpage', <SmileOutlined />, routes.main),
|
||||
defRootMenu('主席团管理', 'admin', <CrownOutlined />, [
|
||||
defSubMenu('排班表管理', 'dutytable', routes.admin.dutyTable),
|
||||
defSubMenu('值班信息管理', 'dutyinfo', routes.admin.dutyInfo),
|
||||
]),
|
||||
defRootMenu('值班组长', 'leader', <TeamOutlined />, [
|
||||
defSubMenu('值班总结', 'conclusion', routes.duty.conclusion),
|
||||
]),
|
||||
defMenu('日志', 'logspage', <ClockCircleOutlined />, routes.logs),
|
||||
defMenu('关于我们', 'aboutpage', <ThunderboltOutlined />, routes.about),
|
||||
];
|
||||
|
||||
interface BreadcrumbItem {
|
||||
href: string;
|
||||
title: JSX.Element;
|
||||
}
|
||||
|
||||
const AppLayout: FC<{ router: JSX.Element }> = (props) => {
|
||||
const { colorBgContainer, borderRadiusLG } = theme.getDesignToken();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const location = useLocation();
|
||||
const pathArray = location.pathname.split('/');
|
||||
const currentRouteItems: BreadcrumbItem[] = [
|
||||
{
|
||||
href: '/',
|
||||
title: <HomeOutlined />,
|
||||
},
|
||||
];
|
||||
|
||||
for (var i = 1; i < pathArray.length; i++) {
|
||||
currentRouteItems.push({
|
||||
href: '',
|
||||
title: <span>{routeName.get(pathArray[i])}</span>,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Sider>
|
||||
<div className='demo-logo-vertical' />
|
||||
<Menu
|
||||
theme='dark'
|
||||
defaultSelectedKeys={['1']}
|
||||
mode='inline'
|
||||
items={items}
|
||||
onClick={(info: { key: React.Key }) => {
|
||||
console.log('path', keyRouterMap.get(info.key));
|
||||
navigate(keyRouterMap.get(info.key) || '/');
|
||||
}}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Content style={{ margin: '0 16px' }}>
|
||||
<Breadcrumb style={{ margin: '16px 0' }} items={currentRouteItems} />
|
||||
<div
|
||||
style={{
|
||||
padding: 24,
|
||||
minHeight: 360,
|
||||
background: colorBgContainer,
|
||||
borderRadius: borderRadiusLG,
|
||||
}}
|
||||
>
|
||||
<div>{props.router}</div>
|
||||
</div>
|
||||
</Content>
|
||||
<PageFooter />
|
||||
</Layout>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
const App: FC = () => {
|
||||
return (
|
||||
<div className='app'>
|
||||
<AppLayout router={<AppRouter />} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { Layout } from 'antd';
|
||||
|
||||
const { Footer } = Layout;
|
||||
|
||||
const PageFooter: React.FC = () => {
|
||||
const startYear = 2024;
|
||||
const curYear = new Date().getFullYear();
|
||||
let yearStr = '';
|
||||
if (startYear === curYear) {
|
||||
yearStr = curYear.toString();
|
||||
} else {
|
||||
yearStr = startYear.toString() + ' - ' + curYear.toString();
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Footer style={{ textAlign: 'center', color: '#808080' }}>
|
||||
EVA Tea <br /> <br />
|
||||
© {yearStr} EVA Tech
|
||||
</Footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PageFooter;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Typography } from 'antd';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
const Todo: React.FC = () => {
|
||||
return (
|
||||
<div>
|
||||
<Title level={1}>施工中...</Title>
|
||||
<Text type={'secondary'}>{'// TODO'}</Text>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Todo;
|
||||
+3
-6
@@ -1,18 +1,15 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement,
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals(console.log);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,24 @@
|
||||
import { Button, Upload } from 'antd';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import { FC } from 'react';
|
||||
import { readExcelFile } from '../../utils/excel';
|
||||
|
||||
const DutyTablePage: FC = () => {
|
||||
return (
|
||||
<Upload
|
||||
name='file'
|
||||
action=''
|
||||
beforeUpload={(file) => {
|
||||
let data = readExcelFile(file, 0);
|
||||
data
|
||||
.then((d) => console.log('read data', d))
|
||||
.catch((e) => console.log('got error', e));
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传排班表文件</Button>
|
||||
</Upload>
|
||||
);
|
||||
};
|
||||
|
||||
export default DutyTablePage;
|
||||
@@ -0,0 +1,61 @@
|
||||
import { FC } from 'react';
|
||||
import { EllipsisOutlined } from '@ant-design/icons';
|
||||
import { ProList } from '@ant-design/pro-components';
|
||||
import { Progress, Tag } from 'antd';
|
||||
|
||||
const data = [
|
||||
'语雀的天空',
|
||||
'Ant Design',
|
||||
'蚂蚁金服体验科技',
|
||||
'TechUI',
|
||||
'TechUI 2.0',
|
||||
'Bigfish',
|
||||
'Umi',
|
||||
].map((item) => ({
|
||||
title: item,
|
||||
subTitle: <Tag color='#5BD8A6'>语雀专栏</Tag>,
|
||||
actions: [<EllipsisOutlined />],
|
||||
avatar:
|
||||
'https://gw.alipayobjects.com/zos/antfincdn/UCSiy1j6jx/xingzhuang.svg',
|
||||
content: (
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: 200,
|
||||
}}
|
||||
>
|
||||
<div>发布中</div>
|
||||
<Progress percent={80} />
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
|
||||
const LogsPage: FC = () => {
|
||||
return (
|
||||
<ProList<any>
|
||||
pagination={{
|
||||
defaultPageSize: 5,
|
||||
showSizeChanger: true,
|
||||
}}
|
||||
metas={{
|
||||
title: {},
|
||||
subTitle: {},
|
||||
type: {},
|
||||
avatar: {},
|
||||
content: {},
|
||||
actions: {},
|
||||
}}
|
||||
headerTitle='翻页'
|
||||
dataSource={data}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default LogsPage;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ReportHandler } from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import Todo from './components/Todo';
|
||||
import DutyTablePage from './pages/duty/DutyTable';
|
||||
import LogsPage from './pages/logs/Logs';
|
||||
|
||||
export const routes = {
|
||||
main: '/',
|
||||
about: '/about',
|
||||
admin: {
|
||||
dutyTable: '/admin/dutytable',
|
||||
userControl: '/admin/usercontrol',
|
||||
dutyInfo: '/admin/dutyinfo',
|
||||
},
|
||||
duty: {
|
||||
conclusion: '/duty/conclusion',
|
||||
},
|
||||
logs: '/logs',
|
||||
};
|
||||
|
||||
export const routeName = new Map<string, string>([
|
||||
['admin', '主席团管理'],
|
||||
['about', '关于我们'],
|
||||
['duty', '值班组长'],
|
||||
['dutytable', '排班表'],
|
||||
['dutyinfo', '值班信息'],
|
||||
['conclusion', '值班总结'],
|
||||
['logs', '日志'],
|
||||
]);
|
||||
|
||||
export const AppRouter: React.FC = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path={routes.main} element={<Todo />} />
|
||||
<Route path={routes.admin.dutyTable} element={<DutyTablePage />} />
|
||||
<Route path={routes.admin.userControl} element={<Todo />} />
|
||||
<Route path={routes.admin.dutyInfo} element={<Todo />} />
|
||||
<Route path={routes.duty.conclusion} element={<Todo />} />
|
||||
<Route path={routes.about} element={<Todo />} />
|
||||
<Route path={routes.logs} element={<LogsPage />} />
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { read as xlsxRead, utils as xlsxUtils } from 'xlsx';
|
||||
import { readFile } from './readfile';
|
||||
|
||||
export async function readExcelFile(file: File, sheetIndex: number) {
|
||||
let data = await readFile(file);
|
||||
let workbook = xlsxRead(data, { type: 'binary' });
|
||||
let worksheet = workbook.Sheets[workbook.SheetNames[sheetIndex]];
|
||||
data = xlsxUtils.sheet_to_json(worksheet);
|
||||
return data;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export function readFile(file: File) {
|
||||
return new Promise((resolve) => {
|
||||
let reader = new FileReader();
|
||||
reader.readAsBinaryString(file);
|
||||
reader.onload = (ev) => {
|
||||
resolve(ev.target?.result);
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user