33 Commits
Author SHA1 Message Date
Dawn1Ocean 04e616c477 fix: mainpage avatar & layout 2024-05-10 12:54:21 +08:00
Dawn1Ocean 3242b16e3d fix: ticketList service 2024-05-10 12:41:02 +08:00
Dawn1Ocean 6f960d46a8 fix: default dutyRecoverTime 2024-05-10 12:04:21 +08:00
Dawn1Ocean 669896d253 fix: alter message when inDutyCnt === 0 2024-05-10 11:27:32 +08:00
Dawn1Ocean fc9347e7c1 fix: changestatus 2024-05-10 11:14:23 +08:00
Dawn1Ocean 96dc81bd82 fix: dutyinfo display in mainpage 2024-05-10 10:42:44 +08:00
Dawn_Ocean 54d9dc45b4 fix: comment type 2024-05-09 17:39:41 +08:00
Dawn_Ocean 206eb49893 add member/checklogin in getInfo 2024-05-09 17:33:53 +08:00
Dawn_Ocean 590db1f3fd fix: add space in my continuing tickets; dutyinfo data process 2024-05-09 17:08:56 +08:00
Dawn_Ocean 5cc3387008 fix: get ticket id from url: string -> number 2024-05-09 16:50:17 +08:00
Dawn_Ocean fbe7b9d7de fix: dutyinfo when in duty 2024-04-24 00:19:46 +08:00
Dawn_Ocean 7e3ad80121 fix: memberDutyInfo api; dutyInfo card in MainPage 2024-04-23 17:10:22 +08:00
Dawn1Ocean 0dc87d06d6 fix: dutyinfo display; relaunch to Loading page 2024-04-23 15:59:22 +08:00
Dawn1Ocean 86398ff9a9 fix: request without token; request before getting id in detailframework 2024-04-23 10:17:02 +08:00
Dawn1Ocean 8b2ed25109 fix: request before getting token 2024-04-22 21:05:27 +08:00
Dawn1Ocean fb9f4b4342 small changes to test with ate 2024-04-21 23:06:06 +08:00
Dawn1Ocean 3313307e84 fix: wrong api & services 2024-04-12 01:51:22 +08:00
Dawn1Ocean b68e3db0a3 add conclusion page 2024-04-12 01:42:54 +08:00
Dawn1Ocean d7cdf46026 fix askleave locale & layout 2024-04-12 01:11:07 +08:00
Dawn1Ocean 6325147e81 refactor PicUploader from TicketDetail/Comment 2024-04-12 00:35:45 +08:00
Dawn1Ocean be687d0372 add entry for conclusion page 2024-04-11 19:34:05 +08:00
Dawn1Ocean 0351819fa2 add confirm modal in AskLeave 2024-04-11 17:01:08 +08:00
Dawn_Ocean a12c69cdc0 add entry for AskLeave 2024-04-11 16:14:01 +08:00
Dawn_Ocean 1702b5aa6a add AskLeave page 2024-04-11 15:26:11 +08:00
Dawn_Ocean 952a6caa24 add askleave api&service 2024-04-11 09:13:27 +08:00
Dawn_Ocean d1d01f0ad1 add pic upload service 2024-04-08 18:57:13 +08:00
Dawn_Ocean 51407930bb add pic uploader in ticketnote 2024-04-08 18:48:09 +08:00
Dawn_Ocean 097f6832e3 refactor: split ExpandItem from Mainpage 2024-04-08 15:55:01 +08:00
Dawn_Ocean 4d6eca0434 add pic preview in ticketnote 2024-04-08 15:42:02 +08:00
Dawn_Ocean ab52ffe7ae add pic display in ticketnote 2024-04-08 14:56:51 +08:00
Dawn_Ocean c487187451 change ticketinfo api 2024-04-08 14:20:21 +08:00
Dawn_Ocean 3fd0ebf9c8 refactor: split comment layout from ticketdetail 2024-04-08 14:10:26 +08:00
Dawn1Ocean 7a198cfe03 change /duty/info api 2024-04-07 12:29:07 +08:00
57 changed files with 1278 additions and 260 deletions
+2 -1
View File
@@ -1,3 +1,4 @@
# 配置文档参考 https://taro-docs.jd.com/docs/next/env-mode-config # 配置文档参考 https://taro-docs.jd.com/docs/next/env-mode-config
TARO_APP_ID="wx636eb7cf2b84f305" TARO_APP_ID="wx636eb7cf2b84f305"
TARO_APP_API="http://127.0.0.1:9527" TARO_APP_API="https://ate.zjueva.net"
# TARO_APP_API="http://127.0.0.1:9527"
+97 -8
View File
@@ -87,6 +87,23 @@ data:
} }
``` ```
#### 当前值班暂停
data:
```json
{
"isInDuty": false,
"inDutyCnt": 0,
"currentDuty": "off", // 'off' 代表当前值班暂停
"place": "",
"otherDutyStart": "",
"otherDutyEnd": "",
"offDutyReason": "考试周",
"dutyRecoverTime": "下周一"
}
```
## 账号登陆 ## 账号登陆
### 微信小程序登陆 `POST /login` OK ### 微信小程序登陆 `POST /login` OK
@@ -231,7 +248,15 @@ Request
{ {
"token": "token_test", "token": "token_test",
"id": "id", "id": "id",
"content" : "为什么 PD 不能充电呢?" "content": "为什么 PD 不能充电呢?",
}
```
Data
```json
{
"id": "id", // 返回的是评论的 id
} }
``` ```
@@ -344,7 +369,8 @@ data (same as oreo):
"op": "宇航员", "op": "宇航员",
"type": 0, "type": 0,
"content": "", "content": "",
"createdTime": "2024-03-07T19:52:48.523305" "createdTime": "2024-03-07T19:52:48.523305",
"pic": [], // 只有当 type = 1 (评论) 时 pic 才有可能非空
}, },
{ {
"avatar": "https://....jpg", "avatar": "https://....jpg",
@@ -352,7 +378,8 @@ data (same as oreo):
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "1", "content": "1",
"createdTime": "2024-03-07T19:58:27.838816" "createdTime": "2024-03-07T19:58:27.838816",
"pic": [], // 只有当 type = 1 (评论) 时 pic 才有可能非空
}, },
{ {
"avatar": "https://....jpg", "avatar": "https://....jpg",
@@ -360,7 +387,8 @@ data (same as oreo):
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "4", "content": "4",
"createdTime": "2024-03-07T20:28:12.070707" "createdTime": "2024-03-07T20:28:12.070707",
"pic": [], // 只有当 type = 1 (评论) 时 pic 才有可能非空
}, },
{ {
"avatar": "https://....jpg", "avatar": "https://....jpg",
@@ -368,7 +396,20 @@ data (same as oreo):
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "5", "content": "5",
"createdTime": "2024-03-07T20:30:15.770486" "createdTime": "2024-03-07T20:30:15.770486",
"pic": [], // 只有当 type = 1 (评论) 时 pic 才有可能非空
},
{
"avatar": "https://....jpg",
"id": 21374,
"op": "宇航员",
"type": 1,
"content": "清灰换硅脂",
"createdTime": "2024-03-07T20:30:15.780486",
"pic": [
"https://....jpg",
...
]
} }
], ],
"accessories": [2], "accessories": [2],
@@ -420,9 +461,14 @@ data:
```json ```json
{ {
"isInDuty": true, "isInDuty": true, // 指示成员其当前是否在值班
"inDutyCnt": 3, "inDutyCnt": 3,
"currentDuty": "2" "currentDuty": "others",
"place": "蓝田", // 只有当 currentDuty 为 others 时,place 才不为空
"otherDutyStart": "2024-03-07T11:52:48.523303", // Timestamp
"otherDutyEnd": "2024-03-07T13:52:48.523303",
"offDutyReason": "",
"dutyRecoverTime": ""
} }
``` ```
@@ -433,7 +479,50 @@ data:
```json ```json
{ {
"isInDuty": false, "isInDuty": false,
"offDutyReason": "学园维修", "inDutyCnt": 0,
"currentDuty": "off", // "0" => 正常值班下班,"others" => 其他值班下班,"off" => 值班暂停
"place": "", // 只有当 currentDuty 为 others 时,place 才不为空
"otherDutyStart": "",
"otherDutyEnd": "",
"offDutyReason": "期中考试周",
"dutyRecoverTime": "下周一" "dutyRecoverTime": "下周一"
} }
``` ```
### 成员请假 `POST /member/askleave`
Request
```json
{
"token": "token_test",
"week": "1",
"shift": "2",
"reason": "家庭原因",
"substitute": "晓洋" // 未找人代班则为空
}
```
### 值班总结上传 `POST /member/conclusion`
Request
```json
{
"token": "token_test",
"week": "2",
"shift": "3",
"conclusion": "周四第三班,一人请假,共收两台电脑,均劝退已取回。由上一班交接两台电脑,其中一台维修成功已取回,一台仍在维修。"
}
```
### 修改值班人数 `POST /member/dutycnt`
Request
```json
{
"token": "token_test",
"dutycnt": 5,
}
```
+26 -5
View File
@@ -59,7 +59,9 @@ export default {
}, },
'POST /tickets/addnote': { 'POST /tickets/addnote': {
success: true, success: true,
data: {}, data: {
id: 114,
},
}, },
'POST /tickets/create': { 'POST /tickets/create': {
success: true, success: true,
@@ -118,11 +120,18 @@ export default {
success: true, success: true,
data: { data: {
isInDuty: true, isInDuty: true,
inDutyCnt: 6, inDutyCnt: 3,
currentDuty: '3', currentDuty: 'others',
place: '204', otherDutyStart: '2024-03-07T09:30:48.523303',
otherDutyEnd: '2024-03-07T13:30:48.523303',
place: '蓝田',
offDutyReason: '',
dutyRecoverTime: '',
}, },
}, },
'POST /member/askleave': {
success: true,
},
'POST /login': { 'POST /login': {
success: true, success: true,
data: { data: {
@@ -132,7 +141,19 @@ export default {
'GET /checklogin': { 'GET /checklogin': {
success: true, success: true,
data: { data: {
islogin: false, islogin: true,
}, },
}, },
'POST /upload/pic': {
success: true,
},
'POST /member/conclusion': {
success: true,
data: {
id: 514,
},
},
'POST /member/dutycnt': {
success: true,
},
}; };
+21 -4
View File
@@ -17,7 +17,8 @@
"op": "宇航员", "op": "宇航员",
"type": 0, "type": 0,
"content": "", "content": "",
"createdTime": "2024-03-07T19:52:48.523305" "createdTime": "2024-03-07T19:52:48.523305",
"pic": []
}, },
{ {
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png", "avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
@@ -25,7 +26,8 @@
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "1", "content": "1",
"createdTime": "2024-03-07T19:58:27.838816" "createdTime": "2024-03-07T19:58:27.838816",
"pic": []
}, },
{ {
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png", "avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
@@ -33,7 +35,8 @@
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "4", "content": "4",
"createdTime": "2024-03-07T20:28:12.070707" "createdTime": "2024-03-07T20:28:12.070707",
"pic": []
}, },
{ {
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png", "avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
@@ -41,7 +44,21 @@
"op": "宇航员", "op": "宇航员",
"type": 2, "type": 2,
"content": "5", "content": "5",
"createdTime": "2024-03-07T20:30:15.770486" "createdTime": "2024-03-07T20:30:15.770486",
"pic": []
},
{
"avatar": "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png",
"id": 21374,
"op": "宇航员",
"type": 1,
"content": "清灰换硅脂",
"createdTime": "2024-03-07T20:30:15.780486",
"pic": [
"https://storage.360buyimg.com/mtd/home/111543234387022.jpg",
"https://storage.360buyimg.com/mtd/home/221543234387016.jpg",
"https://storage.360buyimg.com/mtd/home/331543234387025.jpg"
]
} }
], ],
"accessories": [2], "accessories": [2],
+1 -1
View File
@@ -9,7 +9,7 @@
"enhance": false, "enhance": false,
"compileHotReLoad": false, "compileHotReLoad": false,
"postcss": false, "postcss": false,
"minified": false, "minified": true,
"babelSetting": { "babelSetting": {
"ignore": [], "ignore": [],
"disablePlugins": [], "disablePlugins": [],
+1 -1
View File
@@ -3,7 +3,7 @@
"projectname": "EVA-Notify", "projectname": "EVA-Notify",
"setting": { "setting": {
"compileHotReLoad": true, "compileHotReLoad": true,
"urlCheck": false, "urlCheck": true,
"bigPackageSizeSupport": true "bigPackageSizeSupport": true
} }
} }
+3
View File
@@ -1,5 +1,6 @@
export default defineAppConfig({ export default defineAppConfig({
pages: [ pages: [
'pages/Loading/Loading',
'pages/index/index', 'pages/index/index',
'pages/repair/repair', 'pages/repair/repair',
'pages/user/user', 'pages/user/user',
@@ -10,6 +11,8 @@ export default defineAppConfig({
'pages/user/member/member', 'pages/user/member/member',
'pages/TicketDetail/TicketDetail', 'pages/TicketDetail/TicketDetail',
'pages/TicketList/TicketList', 'pages/TicketList/TicketList',
'pages/AskLeave/AskLeave',
'pages/Conclusion/Conclusion',
'pages/404/404', 'pages/404/404',
], ],
window: { window: {
@@ -160,12 +160,13 @@ export default class DetailFramework extends Component<
notelist: this.props.isInfoShow['notelist'] ? ( notelist: this.props.isInfoShow['notelist'] ? (
this.props.isInfoShow['showAllNotes'] ? ( this.props.isInfoShow['showAllNotes'] ? (
<View style={{ padding: '20rpx' }}> <View style={{ padding: '20rpx' }}>
<NoteList noteList={this.state.notes} /> <NoteList noteList={this.state.notes} showPic />
</View> </View>
) : ( ) : (
<View style={{ padding: '20rpx' }}> <View style={{ padding: '20rpx' }}>
<NoteList <NoteList
noteList={[this.state.notes[this.state.notes.length - 1]]} noteList={[this.state.notes[this.state.notes.length - 1]]}
showPic={false}
/> />
</View> </View>
) )
@@ -0,0 +1,3 @@
export default {
component: true,
};
+31
View File
@@ -0,0 +1,31 @@
import { View } from '@tarojs/components';
import { Component, ReactNode } from 'react';
import { AtAccordion } from 'taro-ui';
export class ExpandItem extends Component {
state = {
open: false,
};
props = {
title: '',
content: <View></View>,
};
handleClick(value: boolean) {
this.setState({ open: value });
}
render(): ReactNode {
return (
<View>
<AtAccordion
open={this.state.open}
onClick={this.handleClick.bind(this)}
title={this.props.title}
>
{this.props.content}
</AtAccordion>
</View>
);
}
}
+43 -5
View File
@@ -3,19 +3,23 @@ import { Component, ReactNode } from 'react';
import { TicketNote, StatusStr } from '@/pages/TicketDetail/TicketNote'; import { TicketNote, StatusStr } from '@/pages/TicketDetail/TicketNote';
import pt from '@/plain-text'; import pt from '@/plain-text';
import { timeFormat } from '@/utils'; import { timeFormat } from '@/utils';
import Taro from '@tarojs/taro';
import './NoteCard.scss'; import './NoteCard.scss';
interface NoteCardProps { interface NoteCardProps {
note: TicketNote; note: TicketNote;
showPic: boolean;
} }
export default class NoteCard extends Component<NoteCardProps, {}> { export default class NoteCard extends Component<NoteCardProps, {}> {
props: Readonly<NoteCardProps> = { props: Readonly<NoteCardProps> = {
note: new TicketNote(), note: new TicketNote(),
showPic: true,
}; };
render(): ReactNode { render(): ReactNode {
var message = ''; let message = '';
let pic: string[] = [];
const note = this.props.note; const note = this.props.note;
const td = pt.get().ticketDetail; const td = pt.get().ticketDetail;
const createMessage = td.comment.createTicketMessage; const createMessage = td.comment.createTicketMessage;
@@ -27,16 +31,47 @@ export default class NoteCard extends Component<NoteCardProps, {}> {
message = createMessage; message = createMessage;
break; break;
case 1: case 1:
message = note.content; message = pt.get().ticketDetail.comment.picked;
break; break;
case 2: case 2:
message = prefix + modifyMessage.get(note.content as StatusStr) || ''; message = prefix + modifyMessage.get(note.content as StatusStr) || '';
break; break;
case 3:
message = note.content;
pic = note.pic;
break;
} }
const showPicDetail = (url: string) => {
Taro.previewImage({
current: url,
urls: [url],
});
};
const notePicRenderer = (
<View>
<View className='at-row' style={{ marginLeft: '30rpx' }}>
{pic.map((url, idx) => (
<View className='at-col at-col-4' key={idx}>
<Image
style='width: 160rpx; height: 160rpx;'
src={url}
mode='aspectFit'
onClick={showPicDetail.bind(this, url)}
/>
</View>
))}
</View>
</View>
);
return ( return (
<View className='at-row at-row__align--center'> <View className='at-row at-row__align--start'>
<View className='at-col at-col-1 at-col--auto'> <View
className='at-col at-col-1 at-col--auto'
style={{ marginTop: '80rpx' }}
>
<Image <Image
style='width: 70rpx; height: 70rpx; border-radius: 35px;' style='width: 70rpx; height: 70rpx; border-radius: 35px;'
src={note.avatar} src={note.avatar}
@@ -55,7 +90,10 @@ export default class NoteCard extends Component<NoteCardProps, {}> {
<View className='at-article__info'> <View className='at-article__info'>
{note.createdTime.format(timeFormat)} {note.createdTime.format(timeFormat)}
</View> </View>
<View className='at-article__h3'>{message}</View> <View className='at-article__h3' style={{ marginBottom: '20rpx' }}>
{message}
</View>
{this.props.showPic ? notePicRenderer : null}
</View> </View>
</View> </View>
); );
+3 -1
View File
@@ -7,11 +7,13 @@ import pt from '@/plain-text';
interface NoteListProps { interface NoteListProps {
noteList: Array<TicketNote>; noteList: Array<TicketNote>;
showPic: boolean;
} }
export default class NoteList extends Component<NoteListProps, {}> { export default class NoteList extends Component<NoteListProps, {}> {
props: Readonly<NoteListProps> = { props: Readonly<NoteListProps> = {
noteList: [], noteList: [],
showPic: true,
}; };
render(): ReactNode { render(): ReactNode {
return ( return (
@@ -23,7 +25,7 @@ export default class NoteList extends Component<NoteListProps, {}> {
/> />
{this.props.noteList.map((note, idx) => ( {this.props.noteList.map((note, idx) => (
<View key={idx}> <View key={idx}>
<NoteCard note={note} /> <NoteCard note={note} showPic={this.props.showPic} />
</View> </View>
))} ))}
</View> </View>
@@ -0,0 +1,3 @@
export default {
component: true,
};
@@ -0,0 +1,66 @@
import { picUpload } from '@/service/picUpload';
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { Component, ReactNode } from 'react';
import { AtImagePicker } from 'taro-ui';
import { File } from 'taro-ui/types/image-picker';
const reLaunchInterval = 1000;
interface PicUploaderState {
files: File[];
}
interface PicUploaderProps {
source: string;
id: number;
superId?: number;
}
export default class PicUploader extends Component<
PicUploaderProps,
PicUploaderState
> {
state = {
files: [] as File[],
};
onUpload() {
if (this.state.files.length !== 0) {
for (let file of this.state.files) {
picUpload(this, file.url);
}
}
if (this.props.source == 'comment') {
setTimeout(() => {
Taro.reLaunch({
url: '/pages/TicketDetail/TicketDetail?id=' + this.props.superId,
});
}, reLaunchInterval);
} else if (this.props.source == 'conclusion') {
setTimeout(() => {
Taro.reLaunch({
url: '/pages/index/index',
});
}, reLaunchInterval);
}
}
handlePicChange(files: File[]) {
this.setState({
files: files,
});
return files;
}
render(): ReactNode {
return (
<View>
<AtImagePicker
showAddBtn={this.state.files.length !== 3}
count={3}
files={this.state.files}
sizeType={['compressed']}
onChange={this.handlePicChange.bind(this)}
/>
</View>
);
}
}
+3
View File
@@ -0,0 +1,3 @@
export default definePageConfig({
usingComponents: {},
});
View File
+187
View File
@@ -0,0 +1,187 @@
import {
AtTextarea,
AtButton,
AtForm,
AtMessage,
AtInput,
AtList,
AtListItem,
AtModal,
} from 'taro-ui';
import { Component, ReactNode } from 'react';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import { Picker, View } from '@tarojs/components';
import { askLeave } from '@/service/askleave';
import './AskLeave.scss';
const submitInterval = 5000;
export default class AskLeavePage extends Component {
state = {
isLoading: false,
isDisable: false,
showModal: false,
range: [pt.get().askLeave.shift.week, pt.get().askLeave.shift.shift],
shift: [0, 0],
reason: '',
substitute: '',
};
componentDidMount(): void {
Taro.setNavigationBarTitle({
title: pt.get().navBar.askLeave,
});
}
onShiftSelect(event) {
this.setState({
shift: event.detail.value,
});
console.log(event);
}
onModalClose() {
this.setState({
showModal: false,
});
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
onModalCancel() {
this.setState({
showModal: false,
});
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
onModalConfirm() {
this.setState({
showModal: false,
});
askLeave(this);
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
handleReasonChange(reason: string) {
this.setState({
reason,
});
}
handleSubstituteChange(substitute: string) {
this.setState({
substitute,
});
}
onSubmit() {
this.setState({
isDisable: true,
});
if (this.state.reason == '') {
Taro.atMessage({
message: pt.get().button.submitText.blank,
type: 'error',
});
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
return;
}
if (this.state.substitute == '') {
this.setState({
showModal: true,
});
return;
}
askLeave(this);
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
render(): ReactNode {
return (
<View style={{ marginTop: '30rpx', width: '94%', marginLeft: '3%' }}>
<AtMessage />
<AtModal
isOpened={this.state.showModal}
title={pt.get().askLeave.modal.title}
cancelText={pt.get().modal.cancel}
confirmText={pt.get().modal.confirm}
onClose={this.onModalClose.bind(this)}
onCancel={this.onModalCancel.bind(this)}
onConfirm={this.onModalConfirm.bind(this)}
content={pt.get().askLeave.modal.content}
/>
<AtForm onSubmit={this.onSubmit.bind(this)}>
<View style={{ width: '98%', marginLeft: '1%' }}>
<Picker
mode='multiSelector'
range={this.state.range}
onChange={this.onShiftSelect.bind(this)}
value={this.state.shift}
>
<AtList>
<AtListItem
title={pt.get().askLeave.shift.title}
extraText={
pt.get().askLeave.shift.week[this.state.shift[0]] +
pt.get().askLeave.shift.shift[this.state.shift[1]]
}
/>
</AtList>
</Picker>
</View>
<View
className='at-article__h3'
style={{ marginTop: '20rpx', marginBottom: '20rpx' }}
>
{pt.get().askLeave.reason.title}
</View>
<AtTextarea
value={this.state.reason}
onChange={this.handleReasonChange.bind(this)}
maxLength={200}
placeholder={pt.get().askLeave.reason.placeHolder}
/>
<AtInput
name='substitute'
title={pt.get().askLeave.substitute.title}
type='text'
placeholder={pt.get().askLeave.substitute.placeHolder}
value={this.state.substitute}
onChange={this.handleSubstituteChange.bind(this)}
/>
<View>
<AtButton
loading={this.state.isLoading}
formType='submit'
type='primary'
disabled={this.state.isDisable}
>
{pt.get().button.buttonText.submit}
</AtButton>
</View>
</AtForm>
</View>
);
}
}
@@ -0,0 +1,3 @@
export default definePageConfig({
usingComponents: {},
});
+129
View File
@@ -0,0 +1,129 @@
import {
AtTextarea,
AtButton,
AtForm,
AtMessage,
AtList,
AtListItem,
} from 'taro-ui';
import React, { Component, ReactNode } from 'react';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import { Picker, View } from '@tarojs/components';
import PicUploader from '@/components/PicUploader/PicUploader';
import { conclude } from '@/service/conclude';
import './Conclusion.scss';
const submitInterval = 5000;
export default class ConclusionPage extends Component {
state = {
isLoading: false,
isDisable: false,
conclusion: '',
conclusionId: 0,
range: [pt.get().askLeave.shift.week, pt.get().askLeave.shift.shift],
shift: [0, 0],
};
componentDidMount(): void {
Taro.setNavigationBarTitle({
title: pt.get().navBar.conclusion,
});
}
uploaderRef = React.createRef<PicUploader>();
handleConclusionChange(conclusion: string) {
this.setState({
conclusion,
});
}
onShiftSelect(event) {
this.setState({
shift: event.detail.value,
});
console.log(event);
}
onSubmit() {
this.setState({
isDisable: true,
});
if (this.state.conclusion == '') {
Taro.atMessage({
message: pt.get().button.submitText.blank,
type: 'error',
});
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
return;
}
conclude(this);
this.uploaderRef.current?.onUpload();
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
render(): ReactNode {
return (
<View style={{ marginTop: '30rpx', width: '94%', marginLeft: '3%' }}>
<AtMessage />
<AtForm onSubmit={this.onSubmit.bind(this)}>
<View style={{ width: '98%', marginLeft: '1%' }}>
<Picker
mode='multiSelector'
range={this.state.range}
onChange={this.onShiftSelect.bind(this)}
value={this.state.shift}
>
<AtList>
<AtListItem
title={pt.get().askLeave.shift.title}
extraText={
pt.get().askLeave.shift.week[this.state.shift[0]] +
pt.get().askLeave.shift.shift[this.state.shift[1]]
}
/>
</AtList>
</Picker>
</View>
<View
className='at-article__h3'
style={{ marginTop: '20rpx', marginBottom: '20rpx' }}
>
{pt.get().conclusion.title}
</View>
<AtTextarea
value={this.state.conclusion}
onChange={this.handleConclusionChange.bind(this)}
maxLength={200}
height={400}
placeholder={pt.get().conclusion.placeHolder}
/>
<PicUploader
ref={this.uploaderRef}
source='conclusion'
id={this.state.conclusionId}
/>
<View>
<AtButton
loading={this.state.isLoading}
formType='submit'
type='primary'
disabled={this.state.isDisable}
>
{pt.get().button.buttonText.submit}
</AtButton>
</View>
</AtForm>
</View>
);
}
}
+3
View File
@@ -0,0 +1,3 @@
export default definePageConfig({
usingComponents: {},
});
View File
+30
View File
@@ -0,0 +1,30 @@
import { AtActivityIndicator } from 'taro-ui';
import { Component, ReactNode } from 'react';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import { View } from '@tarojs/components';
import wechatUser from '@/wechat';
import './Loading.scss';
export default class LoadingPage extends Component {
componentDidMount(): void {
Taro.setNavigationBarTitle({
title: pt.get().navBar.loading,
});
if (wechatUser.getToken()) {
Taro.reLaunch({
url: '/pages/index/index',
});
}
}
render(): ReactNode {
return (
<View>
<AtActivityIndicator
mode='center'
content={pt.get().actIndicator.loading}
></AtActivityIndicator>
</View>
);
}
}
+101
View File
@@ -0,0 +1,101 @@
import { ExpandItem } from '@/components/ExpandItem/ExpandItem';
import PicUploader from '@/components/PicUploader/PicUploader';
import pt from '@/plain-text';
import { submitComment } from '@/service/submitComment';
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import React, { Component, ReactNode } from 'react';
import { AtButton, AtForm, AtTextarea } from 'taro-ui';
const submitInterval = 5000;
export interface commentData {
content: string;
id: number;
}
export class Comment extends Component {
state = {
isLoading: false,
isDisable: false,
comment: '',
commentId: 0,
};
uploaderRef = React.createRef<PicUploader>();
props = {
setFloatLayout: (_: boolean) => {},
id: 0,
didMount: false,
};
handleCommentChange(comment: string) {
this.setState({
comment: comment,
});
return comment;
}
onCommentSubmit() {
this.setState({
isDisable: true,
});
this.props.setFloatLayout(false);
if (this.state.comment == '') {
Taro.atMessage({
message: pt.get().button.submitText.blank,
type: 'error',
});
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
return;
}
submitComment(this);
this.uploaderRef.current?.onUpload();
setTimeout(() => {
this.setState({
isDisable: false,
});
}, submitInterval);
}
render(): ReactNode {
return this.props.didMount ? (
<AtForm onSubmit={this.onCommentSubmit.bind(this)}>
<AtTextarea
value={this.state.comment}
onChange={this.handleCommentChange.bind(this)}
maxLength={200}
height='400rpx'
placeholder={pt.get().ticketDetail.comment.placeholder}
/>
<ExpandItem
title={pt.get().ticketDetail.comment.uploadPic.title}
content={
<PicUploader
ref={this.uploaderRef}
source='comment'
superId={this.props.id}
id={this.state.commentId}
/>
}
/>
<AtButton
loading={this.state.isLoading}
disabled={this.state.isDisable}
formType='submit'
type='primary'
>
{pt.get().button.buttonText.submit}
</AtButton>
<View style={{ marginBottom: '20rpx' }}></View>
</AtForm>
) : (
<View></View>
);
}
}
+30 -62
View File
@@ -11,11 +11,9 @@ import {
AtForm, AtForm,
AtMessage, AtMessage,
AtModal, AtModal,
AtTextarea,
} from 'taro-ui'; } from 'taro-ui';
import DetailFramework from '@/components/DetailFramework/DetailFramework'; import DetailFramework from '@/components/DetailFramework/DetailFramework';
import PageFooter from '@/components/PageFooter/PageFooter'; import PageFooter from '@/components/PageFooter/PageFooter';
import { submitComment } from '@/service/submitComment';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import wechatUser from '@/wechat'; import wechatUser from '@/wechat';
import { addToOreo } from '@/service/addToOreo'; import { addToOreo } from '@/service/addToOreo';
@@ -24,6 +22,7 @@ import { retrieve } from '@/service/retrieve';
import { changeStatus } from '@/service/changeStatus'; import { changeStatus } from '@/service/changeStatus';
import { getDisable } from '@/service/getDisable'; import { getDisable } from '@/service/getDisable';
import { StatusStr } from './TicketNote'; import { StatusStr } from './TicketNote';
import { Comment } from './Comment';
const submitInterval = 5000; const submitInterval = 5000;
@@ -44,7 +43,6 @@ interface TicketDetailState {
status: boolean; status: boolean;
}; };
}; };
comment: string;
isLoading: { isLoading: {
oreo: boolean; oreo: boolean;
pick: boolean; pick: boolean;
@@ -52,6 +50,7 @@ interface TicketDetailState {
comment: boolean; comment: boolean;
status: boolean; status: boolean;
reminder: boolean; reminder: boolean;
framework: boolean;
}; };
isDisable: { isDisable: {
oreo: boolean; oreo: boolean;
@@ -89,7 +88,6 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
status: false, status: false,
}, },
}, },
comment: '',
isLoading: { isLoading: {
oreo: false, oreo: false,
pick: false, pick: false,
@@ -97,6 +95,7 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
comment: false, comment: false,
status: false, status: false,
reminder: false, reminder: false,
framework: true,
}, },
isDisable: { isDisable: {
oreo: false, oreo: false,
@@ -119,12 +118,18 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
componentDidMount(): void { componentDidMount(): void {
const { router } = getCurrentInstance(); const { router } = getCurrentInstance();
const id = router?.params.id as number; const id = Number(router?.params.id);
this.setState({ this.setState({
id: id, id: id,
isMember: wechatUser.getAccess(), isMember: wechatUser.getAccess(),
}); });
getDisable(this, id); getDisable(this, id);
this.setState({
isLoading: {
...this.state.isLoading,
framework: false,
},
});
} }
onAddToOreo(): void { onAddToOreo(): void {
@@ -338,7 +343,7 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
} }
handleStatusChange(status: number): void { handleStatusChange(status: number): void {
if (status == 3 || status == 5 || status == 7) { if (status >= 3 && status <= 7) {
this.setState({ this.setState({
isDisable: { isDisable: {
...this.state.isDisable, ...this.state.isDisable,
@@ -371,8 +376,10 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
status: false, status: false,
}, },
}, },
// eslint-disable-next-line react/no-unused-state
statusToBe: status,
}); });
changeStatus(this); changeStatus(this, status);
} }
setTimeout(() => { setTimeout(() => {
this.setState({ this.setState({
@@ -385,51 +392,16 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
return; return;
} }
handleCommentChange(comment: string) { setFloatLayout(show: boolean) {
this.setState({ this.setState({
comment: comment,
});
return comment;
}
onCommentSubmit() {
this.setState({
isDisable: {
...this.state.isDisable,
comment: true,
},
show: { show: {
...this.state.show, ...this.state.show,
layout: { layout: {
...this.state.show.layout, ...this.state.show.layout,
comment: false, comment: show,
}, },
}, },
}); });
if (this.state.comment == '') {
Taro.atMessage({
message: pt.get().button.submitText.blank,
type: 'error',
});
setTimeout(() => {
this.setState({
isDisable: {
...this.state.isDisable,
comment: false,
},
});
}, submitInterval);
return;
}
submitComment(this);
setTimeout(() => {
this.setState({
isDisable: {
...this.state.isDisable,
comment: false,
},
});
}, submitInterval);
} }
handleReminderChange(reminderList: Array<number>) { handleReminderChange(reminderList: Array<number>) {
@@ -457,7 +429,7 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
}, },
}, },
}); });
changeStatus(this); changeStatus(this, this.state.statusToBe);
} else { } else {
this.setState({ this.setState({
isDisable: { isDisable: {
@@ -639,6 +611,7 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
current: true, current: true,
notelist: true, notelist: true,
showAllNotes: true, showAllNotes: true,
pic: true,
}; };
return ( return (
@@ -676,18 +649,11 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
title={pt.get().ticketDetail.comment.title} title={pt.get().ticketDetail.comment.title}
onClose={this.handleCommentCancel.bind(this)} onClose={this.handleCommentCancel.bind(this)}
> >
<AtForm onSubmit={this.onCommentSubmit.bind(this)}> <Comment
<AtTextarea setFloatLayout={this.setFloatLayout.bind(this)}
value={this.state.comment} id={this.state.id}
onChange={this.handleCommentChange.bind(this)} didMount={this.state.show.layout.comment}
maxLength={200} />
height='400rpx'
placeholder={pt.get().ticketDetail.comment.placeholder}
/>
<AtButton formType='submit' type='primary'>
{pt.get().button.buttonText.submit}
</AtButton>
</AtForm>
</AtFloatLayout> </AtFloatLayout>
<AtFloatLayout <AtFloatLayout
isOpened={this.state.show.layout.reminder} isOpened={this.state.show.layout.reminder}
@@ -719,11 +685,13 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
> >
{sheetItemsRenderer} {sheetItemsRenderer}
</AtActionSheet> </AtActionSheet>
<DetailFramework {!this.state.isLoading.framework && (
middleButton={middleButton} <DetailFramework
id={this.state.id} middleButton={middleButton}
isInfoShow={isInfoShow} id={this.state.id}
/> isInfoShow={isInfoShow}
/>
)}
<PageFooter /> <PageFooter />
</View> </View>
); );
+2 -1
View File
@@ -16,9 +16,10 @@ export class TicketNote {
avatar: string; avatar: string;
id: number; id: number;
op: string; op: string;
type: 0 | 1 | 2; type: 0 | 1 | 2 | 3;
content: string; content: string;
createdTime: moment.Moment; createdTime: moment.Moment;
pic: string[];
} }
export class ShowElements { export class ShowElements {
+18 -12
View File
@@ -15,24 +15,24 @@ export class DutyData {
this.currentDuty = '1'; this.currentDuty = '1';
this.otherDutyStart = '2024-03-07T13:30:48.523303'; this.otherDutyStart = '2024-03-07T13:30:48.523303';
this.otherDutyEnd = '2024-03-07T16:00:48.523303'; this.otherDutyEnd = '2024-03-07T16:00:48.523303';
this.dutyRecoverTime = '明天 13:30'; this.dutyRecoverTime = '13:30';
this.place = '东三-204'; this.place = '东三-204';
} }
isInDuty: boolean; isInDuty: boolean;
inDutyCnt?: number; inDutyCnt: number;
currentDuty?: '0' | '1' | '2' | '3' | 'others'; currentDuty: 'off' | '0' | '1' | '2' | '3' | 'others';
otherDutyStart?: string; otherDutyStart: string;
otherDutyEnd?: string; otherDutyEnd: string;
offDutyReason?: string; offDutyReason: string;
dutyRecoverTime?: string; dutyRecoverTime: string;
place: string; place: string;
} }
class Card extends Component { class Card extends Component {
props = { props = {
isInDuty: false, isInDuty: false,
place: '东三-204', place: pt.get().common.place,
}; };
render(): ReactNode { render(): ReactNode {
const inDuty = this.props.isInDuty; const inDuty = this.props.isInDuty;
@@ -92,13 +92,13 @@ export class DutyInfo extends Component {
{ {
title: title:
data.currentDuty == '0' data.currentDuty == '0'
? pt.get().mainPage.normal.reason ? od.reason(pt.get().common.offDutyReason)
: od.reason(data.offDutyReason as string), : od.reason(data.offDutyReason as string),
}, },
{ {
title: title:
data.currentDuty == '0' data.currentDuty == '0'
? pt.get().mainPage.normal.recoverTime ? od.recoverTime(pt.get().common.dutyRecoverTime)
: od.recoverTime(data.dutyRecoverTime as string), : od.recoverTime(data.dutyRecoverTime as string),
}, },
]} ]}
@@ -122,9 +122,15 @@ export class DutyInfo extends Component {
moment(data.otherDutyStart).format('H:mm') + moment(data.otherDutyStart).format('H:mm') +
' - ' + ' - ' +
moment(data.otherDutyEnd).format('H:mm') moment(data.otherDutyEnd).format('H:mm')
: id.currentDutyText(data.currentDuty || '0'), : id.currentDutyText(data.currentDuty || 'off'),
},
{
title: id.inDutyCnt(
data.inDutyCnt === 0
? pt.get().common.zeroMemberOnDuty
: data.inDutyCnt.toString(),
),
}, },
{ title: id.inDutyCnt(data.inDutyCnt as number) },
]} ]}
/> />
</View> </View>
+25 -3
View File
@@ -1,24 +1,37 @@
import React from 'react'; import React from 'react';
import { View, Image } from '@tarojs/components'; import { View, Image } from '@tarojs/components';
import { AtButton } from 'taro-ui';
import pt from '@/plain-text'; import pt from '@/plain-text';
import wechatUser from '@/wechat'; import wechatUser from '@/wechat';
import Taro from '@tarojs/taro';
const logo = 'https://wiki.zjueva.net/images/evalogo_hd.png'; const logo = 'https://wiki.zjueva.net/images/evalogo_hd.png';
export default class TitleCard extends React.Component { export default class TitleCard extends React.Component {
onAskLeave() {
Taro.redirectTo({
url: '/pages/AskLeave/AskLeave',
});
}
render(): React.ReactNode { render(): React.ReactNode {
const mainPage = pt.get().mainPage; const mainPage = pt.get().mainPage;
const memberPage = pt.get().memberPage; const memberPage = pt.get().memberPage;
return ( return (
<View className='at-row at-row__align--center'> <View className='at-row at-row__align--center at-row__justify--start'>
<View className='at-col at-col-1 at-col--auto'> <View className='at-col at-col-1 at-col--auto'>
<Image <Image
style='width: 100rpx; height: 100rpx; margin-left: 30rpx;' style='width: 100rpx; height: 100rpx; margin-left: 30rpx; border-radius: 50rpx'
src={wechatUser.getAccess() ? wechatUser.getInfo().avatar : logo} src={wechatUser.getAccess() ? wechatUser.getInfo().avatar : logo}
mode='aspectFit' mode='aspectFit'
/> />
</View> </View>
<View className='page-title'> <View
className={
wechatUser.getAccess()
? 'at-col page-title at-col-1 at-col--auto'
: 'at-col page-title at-col-10 at-col--wrap'
}
>
<View className='at-article__h1' style={{ fontWeight: 'bold' }}> <View className='at-article__h1' style={{ fontWeight: 'bold' }}>
{wechatUser.getAccess() {wechatUser.getAccess()
? memberPage.titleLine.main.index + wechatUser.getInfo().name ? memberPage.titleLine.main.index + wechatUser.getInfo().name
@@ -30,6 +43,15 @@ export default class TitleCard extends React.Component {
: mainPage.titleLine.sub} : mainPage.titleLine.sub}
</View> </View>
</View> </View>
{wechatUser.getAccess() ? (
<View className='at-col at-col-1 at-col--auto'>
<AtButton type='secondary' onClick={this.onAskLeave}>
{pt.get().mainPage.askLeave}
</AtButton>
</View>
) : (
<View></View>
)}
</View> </View>
); );
} }
+54 -67
View File
@@ -3,7 +3,6 @@ import { Component, ReactNode } from 'react';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import { import {
AtCard, AtCard,
AtAccordion,
AtInputNumber, AtInputNumber,
AtButton, AtButton,
AtList, AtList,
@@ -23,6 +22,7 @@ import { getMemberDutyInfo } from '@/service/memberDutyInfo';
import { getUncompletedTicketList } from '@/service/uncompletedTicket'; import { getUncompletedTicketList } from '@/service/uncompletedTicket';
import { changeDutyCnt } from '@/service/changeDutyCount'; import { changeDutyCnt } from '@/service/changeDutyCount';
import { TicketListItem } from '@/components/TicketListItem/TicketListItem'; import { TicketListItem } from '@/components/TicketListItem/TicketListItem';
import { ExpandItem } from '@/components/ExpandItem/ExpandItem';
import './index.scss'; import './index.scss';
import TitleCard from './TitleCard'; import TitleCard from './TitleCard';
import { DutyInfo, DutyData } from './DutyInfo'; import { DutyInfo, DutyData } from './DutyInfo';
@@ -47,39 +47,10 @@ function mainPageCard(c: CardContent): JSX.Element {
); );
} }
class ExpandItem extends Component {
state = {
open: false,
};
props = {
title: '',
content: <View></View>,
};
handleClick(value: boolean) {
this.setState({ open: value });
}
render(): ReactNode {
return (
<View>
<AtAccordion
open={this.state.open}
onClick={this.handleClick.bind(this)}
title={this.props.title}
>
{this.props.content}
</AtAccordion>
</View>
);
}
}
interface MainPageState { interface MainPageState {
fixList: Array<TicketListItem>; fixList: Array<TicketListItem>;
rs: RequestState; rs: RequestState;
dutyData: DutyData; dutyData: DutyData;
inDutyCnt: number;
dutyInfoCard: CardContent; dutyInfoCard: CardContent;
stepInfoCard: CardContent; stepInfoCard: CardContent;
tipsInfoCard: CardContent; tipsInfoCard: CardContent;
@@ -90,7 +61,6 @@ interface MainPageState {
export default class MainPage extends Component<{}, MainPageState> { export default class MainPage extends Component<{}, MainPageState> {
state = { state = {
dutyData: new DutyData(), dutyData: new DutyData(),
inDutyCnt: 0,
dutyInfoCard: { dutyInfoCard: {
title: '', title: '',
note: '', note: '',
@@ -119,7 +89,6 @@ export default class MainPage extends Component<{}, MainPageState> {
const ptPage = wechatUser.getAccess() ? 'memberPage' : 'mainPage'; const ptPage = wechatUser.getAccess() ? 'memberPage' : 'mainPage';
this.setState({ this.setState({
dutyData: new DutyData(), dutyData: new DutyData(),
inDutyCnt: 0,
dutyInfoCard: { dutyInfoCard: {
title: pt.get()[ptPage].cardTitle.dutyInfo, title: pt.get()[ptPage].cardTitle.dutyInfo,
note: pt.get()[ptPage].cardTips.dutyInfo, note: pt.get()[ptPage].cardTips.dutyInfo,
@@ -158,7 +127,10 @@ export default class MainPage extends Component<{}, MainPageState> {
handleCnt(inDutyCnt: number) { handleCnt(inDutyCnt: number) {
this.setState({ this.setState({
inDutyCnt: inDutyCnt, dutyData: {
...this.state.dutyData,
inDutyCnt: inDutyCnt,
},
}); });
return inDutyCnt; return inDutyCnt;
} }
@@ -181,6 +153,12 @@ export default class MainPage extends Component<{}, MainPageState> {
}); });
} }
conclusionPage() {
Taro.navigateTo({
url: '/pages/Conclusion/Conclusion',
});
}
render(): ReactNode { render(): ReactNode {
const mainPage = pt.get().mainPage; const mainPage = pt.get().mainPage;
const memberPage = pt.get().memberPage; const memberPage = pt.get().memberPage;
@@ -213,44 +191,51 @@ export default class MainPage extends Component<{}, MainPageState> {
<ExpandItem <ExpandItem
title={memberPage.expandTitle.admin} title={memberPage.expandTitle.admin}
content={ content={
<View <View style={{ marginBottom: '40rpx' }}>
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '40rpx',
}}
>
<View
className='.at-article__h3'
style={{
marginTop: '40rpx',
}}
>
{pt.get().memberPage.dutyCount.text}
</View>
<View <View
style={{ style={{
marginTop: '40rpx', display: 'flex',
alignItems: 'center',
marginBottom: '40rpx',
}} }}
> >
<AtInputNumber <View
type='number' className='.at-article__h3'
min={0} style={{
max={10} marginTop: '40rpx',
step={1} }}
value={this.state.inDutyCnt}
onChange={this.handleCnt.bind(this)}
/>
</View>
<View style={{ marginLeft: 'auto', marginTop: '40rpx' }}>
<AtButton
type='secondary'
size='small'
loading={this.state.isLoading}
disabled={this.state.isDisable}
onClick={this.onChangeCnt.bind(this)}
> >
{pt.get().memberPage.dutyCount.button} {pt.get().memberPage.dutyCount.text}
</View>
<View
style={{
marginTop: '40rpx',
}}
>
<AtInputNumber
type='number'
min={0}
max={10}
step={1}
value={this.state.dutyData.inDutyCnt}
onChange={this.handleCnt.bind(this)}
/>
</View>
<View style={{ marginLeft: 'auto', marginTop: '40rpx' }}>
<AtButton
type='secondary'
size='small'
loading={this.state.isLoading}
disabled={this.state.isDisable}
onClick={this.onChangeCnt.bind(this)}
>
{pt.get().memberPage.dutyCount.button}
</AtButton>
</View>
</View>
<View>
<AtButton type='primary' onClick={this.conclusionPage}>
{pt.get().button.indexText.conclusion}
</AtButton> </AtButton>
</View> </View>
</View> </View>
@@ -270,7 +255,9 @@ export default class MainPage extends Component<{}, MainPageState> {
className='at-article__h3' className='at-article__h3'
style={{ marginBottom: '20rpx', fontWeight: 'bold' }} style={{ marginBottom: '20rpx', fontWeight: 'bold' }}
> >
{memberPage.ticketList.hint} {(this.state.fixList.length === 0
? memberPage.ticketList.nohint
: '') + memberPage.ticketList.hint}
</View> </View>
<AtList>{fixListRenderer}</AtList> <AtList>{fixListRenderer}</AtList>
<AtList> <AtList>
+24 -23
View File
@@ -194,29 +194,30 @@ export default class RepairPage extends Component<{}, RepairPageState> {
{pt.get().repairPage.currentTicket.hint} {pt.get().repairPage.currentTicket.hint}
</View> </View>
{this.state.currentTicketsIdName.map((pair, idx) => ( {this.state.currentTicketsIdName.map((pair, idx) => (
<AtCard <View key={idx} style={{ marginBottom: '20rpx' }}>
key={idx} <AtCard
title={pair.values().next().value} //pair.keys().next().value == ticket['device'] + ' ' + ticket['deviceModel'] title={pair.values().next().value} //pair.keys().next().value == ticket['device'] + ' ' + ticket['deviceModel']
extra={pt.get().repairPage.currentTicket.extra} extra={pt.get().repairPage.currentTicket.extra}
onClick={() => { onClick={() => {
Taro.navigateTo({ Taro.navigateTo({
url: url:
'/pages/TicketDetail/TicketDetail?id=' + '/pages/TicketDetail/TicketDetail?id=' +
pair.keys().next().value, pair.keys().next().value,
}); });
}} }}
note={ note={
pt.get().tips.tipsText[ pt.get().tips.tipsText[
randomInt(0, pt.get().tips.tipsText.length - 1) randomInt(0, pt.get().tips.tipsText.length - 1)
] ]
} }
> >
<DetailFramework <DetailFramework
id={pair.keys().next().value} //pair.keys().next().value == id id={pair.keys().next().value} //pair.keys().next().value == id
isInfoShow={isInfoShow} isInfoShow={isInfoShow}
middleButton={middleButton} middleButton={middleButton}
/> />
</AtCard> </AtCard>
</View>
))} ))}
</View> </View>
) : ( ) : (
+1 -2
View File
@@ -64,6 +64,7 @@ export default class ReportPage extends Component {
<AtMessage /> <AtMessage />
<AtTextarea <AtTextarea
value={this.state.report} value={this.state.report}
height={400}
onChange={this.handleChange.bind(this)} onChange={this.handleChange.bind(this)}
maxLength={200} maxLength={200}
placeholder={pt.get().reportPage.placeHolderText} placeholder={pt.get().reportPage.placeHolderText}
@@ -74,7 +75,6 @@ export default class ReportPage extends Component {
style={{ style={{
marginTop: '30rpx', marginTop: '30rpx',
marginRight: '10rpx', marginRight: '10rpx',
marginLeft: '10rpx',
width: '50%', width: '50%',
}} }}
> >
@@ -86,7 +86,6 @@ export default class ReportPage extends Component {
className='at-col' className='at-col'
style={{ style={{
marginTop: '30rpx', marginTop: '30rpx',
marginRight: '10rpx',
marginLeft: '10rpx', marginLeft: '10rpx',
width: '50%', width: '50%',
}} }}
+1 -1
View File
@@ -123,7 +123,7 @@ export default class UserPage extends Component {
className='at-row at-row__justify--center at-row__align--center' className='at-row at-row__justify--center at-row__align--center'
style='height:120rpx;color:#696969;' style='height:120rpx;color:#696969;'
> >
<Text style={{ fontSize: '32rpx' }}> EVA Eta v1.0.2</Text> <Text style={{ fontSize: '32rpx' }}> EVA Eta v1.1.0</Text>
</View> </View>
<AtList> <AtList>
<AtListItem <AtListItem
+60
View File
@@ -0,0 +1,60 @@
export interface AskLeaveText {
modal: {
title: string;
content: string;
};
shift: {
title: string;
week: string[];
shift: string[];
};
reason: {
title: string;
placeHolder: string;
};
substitute: {
title: string;
placeHolder: string;
};
}
export const askLeaveZhCn: AskLeaveText = {
modal: {
title: '确认无代班?',
content: '值班人数少于 4 时须填写代班人员。请假记录将会被上传保存!',
},
shift: {
title: '值班时间',
week: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
shift: ['第一班', '第二班', '第三班'],
},
reason: {
title: '请假原因',
placeHolder: '请在此说明请假原因',
},
substitute: {
title: '替班人员',
placeHolder: '人数少于 4 时必填!',
},
};
export const askLeaveEnUs: AskLeaveText = {
modal: {
title: 'Confirm no substitute?',
content:
'Must have substitute if members are less than 4! The ticket will be uploaded and saved!',
},
shift: {
title: 'Duty time',
week: ['Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.', 'Sun.'],
shift: ['1st Shift', '2nd Shift', '3rd Shift'],
},
reason: {
title: 'Reason',
placeHolder: 'Leave your reason for leaving here',
},
substitute: {
title: 'Substitute',
placeHolder: 'Must have if members are less than 4!',
},
};
+12
View File
@@ -13,6 +13,10 @@ export interface ButtonText {
memberText: { memberText: {
auth: string; auth: string;
}; };
indexText: {
conclusion: string;
askLeave: string;
};
loginText: { loginText: {
success: string; success: string;
error: string; error: string;
@@ -39,6 +43,10 @@ export const buttonZhCn: ButtonText = {
memberText: { memberText: {
auth: '协会统一身份认证登录', auth: '协会统一身份认证登录',
}, },
indexText: {
conclusion: '提交值班总结',
askLeave: '我要请假',
},
loginText: { loginText: {
success: '登录成功', success: '登录成功',
error: '登录失败', error: '登录失败',
@@ -65,6 +73,10 @@ export const buttonEnUs: ButtonText = {
memberText: { memberText: {
auth: 'EVA Auth Login Entry', auth: 'EVA Auth Login Entry',
}, },
indexText: {
conclusion: 'Submit Duty Conclusion',
askLeave: 'Ask for Leave',
},
loginText: { loginText: {
success: 'Login Success', success: 'Login Success',
error: 'Login Failed', error: 'Login Failed',
+16
View File
@@ -0,0 +1,16 @@
export interface ConclusionText {
title: string;
placeHolder: string;
}
export const conclusionTextZhCn: ConclusionText = {
title: '值班总结',
placeHolder:
'请在此填写完整的值班情况,包括:几人请假;收到几台电脑;后续的处理情况;上一班交接的电脑情况;下一班对接的电脑情况;另外,请拍照记录值班桌整理情况',
};
export const conclusionTextEnUs: ConclusionText = {
title: 'Duty Conclusion',
placeHolder:
'Please fill in the complete duty situation here, including: how many people were on leave; how many computers were received; how the follow-up was handled; how the computers were handed over by the previous shift; how the computers were docked by the next shift; Also, please take photos to document the organization of the duty desk',
};
+13 -15
View File
@@ -1,8 +1,6 @@
export interface MainPageText { export interface MainPageText {
normal: { askLeave: string;
recoverTime: string; conclusion: string;
reason: string;
};
titleLine: { titleLine: {
main: string; main: string;
sub: string; sub: string;
@@ -37,17 +35,15 @@ export interface MainPageText {
}; };
inDuty: { inDuty: {
title: string; title: string;
currentDutyText: (c: '0' | '1' | '2' | '3' | 'others') => string; currentDutyText: (c: 'off' | '0' | '1' | '2' | '3' | 'others') => string;
inDutyCnt: (n: number) => string; inDutyCnt: (n: string) => string;
}; };
}; };
} }
export const mainPageZhCn: MainPageText = { export const mainPageZhCn: MainPageText = {
normal: { askLeave: '我要请假',
recoverTime: '明天 13:30', conclusion: '提交值班总结',
reason: '正常下班',
},
titleLine: { titleLine: {
main: '您好,这里是E志者协会', main: '您好,这里是E志者协会',
sub: '维修请至【东三-204】实验室', sub: '维修请至【东三-204】实验室',
@@ -93,8 +89,10 @@ export const mainPageZhCn: MainPageText = {
title: '值班中', title: '值班中',
currentDutyText: (c) => { currentDutyText: (c) => {
switch (c) { switch (c) {
case 'off':
return '暂停值班';
case '0': case '0':
return '当前未值班'; return '休息中';
case '1': case '1':
return '第一班 13:30-16:00'; return '第一班 13:30-16:00';
case '2': case '2':
@@ -111,10 +109,8 @@ export const mainPageZhCn: MainPageText = {
}; };
export const mainPageEnUs: MainPageText = { export const mainPageEnUs: MainPageText = {
normal: { askLeave: 'Absence',
recoverTime: 'Tomorrow 13:30', conclusion: 'Submit Duty Conclusion',
reason: 'Normal shift',
},
titleLine: { titleLine: {
main: 'Hi! This is EVA.', main: 'Hi! This is EVA.',
sub: 'For maintenance, please go to [204 Lab, E3 building]', sub: 'For maintenance, please go to [204 Lab, E3 building]',
@@ -160,6 +156,8 @@ export const mainPageEnUs: MainPageText = {
title: 'On Duty', title: 'On Duty',
currentDutyText: (c) => { currentDutyText: (c) => {
switch (c) { switch (c) {
case 'off':
return 'Duty paused';
case '0': case '0':
return 'Normal Shift'; return 'Normal Shift';
case '1': case '1':
+3
View File
@@ -58,6 +58,7 @@ export interface MemberPageText {
stepList: Array<{ title: string }>; stepList: Array<{ title: string }>;
tipsList: Array<{ title: string }>; tipsList: Array<{ title: string }>;
ticketList: { ticketList: {
nohint: string;
hint: string; hint: string;
title: string; title: string;
note: string; note: string;
@@ -147,6 +148,7 @@ export const memberPageZhCn: MemberPageText = {
{ title: '螺丝上了吗?电源排线插了吗?' }, { title: '螺丝上了吗?电源排线插了吗?' },
], ],
ticketList: { ticketList: {
nohint: '暂无',
hint: '七日内未完成工单', hint: '七日内未完成工单',
title: '预填写工单列表', title: '预填写工单列表',
note: '在这里查看所有的预填写工单!', note: '在这里查看所有的预填写工单!',
@@ -241,6 +243,7 @@ export const memberPageEnUs: MemberPageText = {
{ title: 'Are the screws on? Is the power cable plugged in?' }, { title: 'Are the screws on? Is the power cable plugged in?' },
], ],
ticketList: { ticketList: {
nohint: 'N/A ',
hint: 'Uncompleted tickets in 7 days', hint: 'Uncompleted tickets in 7 days',
title: 'Pre-filling ticket list', title: 'Pre-filling ticket list',
note: 'Browse for all pre-filling tickets here!', note: 'Browse for all pre-filling tickets here!',
+9
View File
@@ -1,7 +1,10 @@
export interface NavBarTitle { export interface NavBarTitle {
notFound: string; notFound: string;
loading: string;
ticketDetail: string; ticketDetail: string;
ticketList: string; ticketList: string;
askLeave: string;
conclusion: string;
user: { user: {
myTicket: string; myTicket: string;
report: string; report: string;
@@ -14,8 +17,11 @@ export interface NavBarTitle {
export const navBarTitleZhCn: NavBarTitle = { export const navBarTitleZhCn: NavBarTitle = {
notFound: '连接失败', notFound: '连接失败',
loading: '加载中',
ticketDetail: '工单详情', ticketDetail: '工单详情',
ticketList: '所有工单', ticketList: '所有工单',
askLeave: '请假单填写',
conclusion: '值班总结',
user: { user: {
myTicket: '我的工单', myTicket: '我的工单',
report: '意见反馈', report: '意见反馈',
@@ -28,8 +34,11 @@ export const navBarTitleZhCn: NavBarTitle = {
export const navBarTitleEnUs: NavBarTitle = { export const navBarTitleEnUs: NavBarTitle = {
notFound: 'Failed', notFound: 'Failed',
loading: 'Loading',
ticketDetail: 'Ticket Detail', ticketDetail: 'Ticket Detail',
ticketList: 'All Tickets', ticketList: 'All Tickets',
askLeave: 'Ask for leave',
conclusion: 'Duty Conclusion',
user: { user: {
myTicket: 'My Tickets', myTicket: 'My Tickets',
report: 'Report', report: 'Report',
+12
View File
@@ -33,8 +33,12 @@ export interface TicketDetailText {
comment: { comment: {
title: string; title: string;
placeholder: string; placeholder: string;
picked: string;
createTicketMessage: string; createTicketMessage: string;
statusModifyPrefix: string; statusModifyPrefix: string;
uploadPic: {
title: string;
};
}; };
status: { status: {
title: string; title: string;
@@ -76,9 +80,13 @@ export const ticketDetailZhCn: TicketDetailText = {
}, },
comment: { comment: {
title: '添加评论', title: '添加评论',
picked: '认领了维修',
placeholder: '可以在这里交流机器情况、维修进度、提出问题~', placeholder: '可以在这里交流机器情况、维修进度、提出问题~',
createTicketMessage: '创建了维修', createTicketMessage: '创建了维修',
statusModifyPrefix: '将维修状态改为:', statusModifyPrefix: '将维修状态改为:',
uploadPic: {
title: '上传说明图片处',
},
}, },
reminder: { reminder: {
title: '注意事项!', title: '注意事项!',
@@ -128,10 +136,14 @@ export const ticketDetailEnUs: TicketDetailText = {
}, },
comment: { comment: {
title: 'Add comment', title: 'Add comment',
picked: 'Picked this ticket',
placeholder: placeholder:
'You can exchange information the device, the progress of repairs, and ask questions here.', 'You can exchange information the device, the progress of repairs, and ask questions here.',
createTicketMessage: 'Created ticket', createTicketMessage: 'Created ticket',
statusModifyPrefix: 'Modified repair status to: ', statusModifyPrefix: 'Modified repair status to: ',
uploadPic: {
title: 'Upload description images',
},
}, },
reminder: { reminder: {
title: 'Reminder', title: 'Reminder',
+17 -1
View File
@@ -1,17 +1,33 @@
import { Moment } from 'moment'; import moment, { Moment } from 'moment';
const dutyStart = moment().format('YYYY-MM-DD').toString() + ' 13:30:00';
export interface CommonText { export interface CommonText {
createdAtText(time: Moment): string; createdAtText(time: Moment): string;
offDutyReason: string;
place: string;
dutyRecoverTime: string;
zeroMemberOnDuty: string;
} }
export const commonTextZhCn: CommonText = { export const commonTextZhCn: CommonText = {
createdAtText(time: Moment): string { createdAtText(time: Moment): string {
return '创建于 ' + time.format('YYYY-MM-DD HH:mm'); return '创建于 ' + time.format('YYYY-MM-DD HH:mm');
}, },
offDutyReason: '正常值班下班',
place: '204',
dutyRecoverTime: moment().isBefore(dutyStart) ? '今天 13:30' : '明天 13:30',
zeroMemberOnDuty: '待更新',
}; };
export const commonTextEnUs: CommonText = { export const commonTextEnUs: CommonText = {
createdAtText(time: Moment): string { createdAtText(time: Moment): string {
return 'Created at ' + time.format('YYYY-MM-DD HH:mm'); return 'Created at ' + time.format('YYYY-MM-DD HH:mm');
}, },
offDutyReason: 'Normal Shift',
place: 'E3-204',
dutyRecoverTime: moment().isBefore(dutyStart)
? '13:30 Today'
: '13:30 Tomorrow',
zeroMemberOnDuty: 'Wait for update',
}; };
+12
View File
@@ -25,6 +25,12 @@ import {
actIndicatorZhCn, actIndicatorZhCn,
} from './ActIndicator'; } from './ActIndicator';
import { NotFoundText, notFound } from './404'; import { NotFoundText, notFound } from './404';
import { AskLeaveText, askLeaveEnUs, askLeaveZhCn } from './AskLeave';
import {
ConclusionText,
conclusionTextEnUs,
conclusionTextZhCn,
} from './Conclusion';
interface TextRecord { interface TextRecord {
common: CommonText; common: CommonText;
@@ -46,6 +52,8 @@ interface TextRecord {
toast: ToastText; toast: ToastText;
actIndicator: ActIndicatorText; actIndicator: ActIndicatorText;
notFound: NotFoundText; notFound: NotFoundText;
askLeave: AskLeaveText;
conclusion: ConclusionText;
} }
const textZhCn: TextRecord = { const textZhCn: TextRecord = {
@@ -68,6 +76,8 @@ const textZhCn: TextRecord = {
toast: toastZhCn, toast: toastZhCn,
actIndicator: actIndicatorZhCn, actIndicator: actIndicatorZhCn,
notFound: notFound, notFound: notFound,
askLeave: askLeaveZhCn,
conclusion: conclusionTextZhCn,
}; };
const textEnUs: TextRecord = { const textEnUs: TextRecord = {
@@ -90,6 +100,8 @@ const textEnUs: TextRecord = {
toast: toastEnUs, toast: toastEnUs,
actIndicator: actIndicatorEnUs, actIndicator: actIndicatorEnUs,
notFound: notFound, notFound: notFound,
askLeave: askLeaveEnUs,
conclusion: conclusionTextEnUs,
}; };
// type Lang = 'zh_CN' | 'en_US' | ...; // type Lang = 'zh_CN' | 'en_US' | ...;
+49
View File
@@ -0,0 +1,49 @@
import AskLeavePage from '@/pages/AskLeave/AskLeave';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import wechatUser from '@/wechat';
import { getUrl } from '.';
const reLaunchInterval = 1000;
export function askLeave(that: AskLeavePage) {
that.setState({
isLoading: true,
});
Taro.request({
url: getUrl('/member/askleave'),
method: 'POST',
data: {
token: wechatUser.getToken(),
week: (that.state.shift[0] + 1).toString(),
shift: (that.state.shift[1] + 1).toString(),
reason: that.state.reason,
substitute: that.state.substitute,
},
})
.then((res) => {
console.log(res.data);
that.setState({
isLoading: false,
});
Taro.atMessage({
message: pt.get().button.submitText.success,
type: 'success',
});
setTimeout(() => {
Taro.reLaunch({
url: '/pages/index/index',
});
}, reLaunchInterval);
})
.catch((err) => {
console.log(err.errMsg);
that.setState({
isLoading: false,
});
Taro.atMessage({
message: pt.get().button.submitText.error + err.errMsg,
type: 'error',
});
});
}
+2 -2
View File
@@ -11,11 +11,11 @@ export function changeDutyCnt(that: MainPage) {
isLoading: true, isLoading: true,
}); });
Taro.request({ Taro.request({
url: getUrl('/tickets/addtooreo'), url: getUrl('/member/dutycnt'),
method: 'POST', method: 'POST',
data: { data: {
token: wechatUser.getToken(), token: wechatUser.getToken(),
dutyCnt: that.state.inDutyCnt, dutyCnt: that.state.dutyData.inDutyCnt,
}, },
}) })
.then((res) => { .then((res) => {
+2 -2
View File
@@ -6,7 +6,7 @@ import { getUrl } from '.';
const reLaunchInterval = 1000; const reLaunchInterval = 1000;
export function changeStatus(that: TicketDetail) { export function changeStatus(that: TicketDetail, status: number) {
that.setState({ that.setState({
isLoading: { isLoading: {
...that.state.isLoading, ...that.state.isLoading,
@@ -19,7 +19,7 @@ export function changeStatus(that: TicketDetail) {
data: { data: {
token: wechatUser.getToken(), token: wechatUser.getToken(),
id: that.state.id, id: that.state.id,
status: that.state.statusToBe, status: status,
}, },
}) })
.then((res) => { .then((res) => {
+42
View File
@@ -0,0 +1,42 @@
import ConclusionPage from '@/pages/Conclusion/Conclusion';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import wechatUser from '@/wechat';
import { getUrl } from '.';
export function conclude(that: ConclusionPage) {
that.setState({
isLoading: true,
});
Taro.request({
url: getUrl('/member/conclusion'),
method: 'POST',
data: {
token: wechatUser.getToken(),
conclusion: that.state.conclusion,
week: (that.state.shift[0] + 1).toString(),
shift: (that.state.shift[1] + 1).toString(),
},
})
.then((res) => {
console.log(res.data);
that.setState({
isLoading: false,
conclusionId: res.data.data.id,
});
Taro.atMessage({
message: pt.get().button.submitText.success,
type: 'success',
});
})
.catch((err) => {
console.log(err.errMsg);
that.setState({
isLoading: false,
});
Taro.atMessage({
message: pt.get().button.submitText.error + err.errMsg,
type: 'error',
});
});
}
+30
View File
@@ -1,6 +1,7 @@
import MainPage from '@/pages/index'; import MainPage from '@/pages/index';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import wechatUser from '@/wechat'; import wechatUser from '@/wechat';
import pt from '@/plain-text';
import { getUrl } from '.'; import { getUrl } from '.';
export function getDutyInfo(that: MainPage) { export function getDutyInfo(that: MainPage) {
@@ -24,6 +25,31 @@ export function getDutyInfo(that: MainPage) {
rs: former.trans(true), rs: former.trans(true),
dutyData: data, dutyData: data,
}); });
if (!data.isInDuty) {
that.setState({
dutyData: {
...data,
offDutyReason: pt.get().common.offDutyReason,
},
});
if (data.currentDuty === '0') {
that.setState({
dutyData: {
...data,
place: pt.get().common.place,
offDutyReason: pt.get().common.offDutyReason,
dutyRecoverTime: pt.get().common.dutyRecoverTime,
},
});
}
} else {
that.setState({
dutyData: {
...data,
place: pt.get().common.place,
},
});
}
}) })
.catch((err) => { .catch((err) => {
console.log(err.errMsg); console.log(err.errMsg);
@@ -32,6 +58,10 @@ export function getDutyInfo(that: MainPage) {
rs: former.trans(false), rs: former.trans(false),
dutyData: { dutyData: {
isInDuty: false, isInDuty: false,
inDutyCnt: 0,
currentDuty: '0',
otherDutyStart: '',
otherDutyEnd: '',
offDutyReason: '获取失败!Network Error!', offDutyReason: '获取失败!Network Error!',
dutyRecoverTime: '获取失败!Network Error!', dutyRecoverTime: '获取失败!Network Error!',
place: '204', place: '204',
+1
View File
@@ -9,6 +9,7 @@ export function getDisable(that: TicketDetail, id: number) {
method: 'GET', method: 'GET',
data: { data: {
id: id, id: id,
token: wechatUser.getToken(),
}, },
}) })
.then((res) => { .then((res) => {
+1 -1
View File
@@ -6,7 +6,7 @@ import { getLocaleData } from './localeData';
export function getInfo() { export function getInfo() {
Taro.request({ Taro.request({
url: getUrl('/member/login'), url: getUrl('/member/checklogin'),
method: 'POST', method: 'POST',
data: { data: {
token: wechatUser.getToken(), token: wechatUser.getToken(),
+3
View File
@@ -21,6 +21,9 @@ export function loginAte() {
data: data.token, data: data.token,
}); });
wechatUser.setToken(data.token); wechatUser.setToken(data.token);
Taro.reLaunch({
url: '/pages/index/index',
});
getLocaleData(); getLocaleData();
}) })
.catch((err) => { .catch((err) => {
+19 -15
View File
@@ -1,6 +1,7 @@
import MainPage from '@/pages/index'; import MainPage from '@/pages/index';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import wechatUser from '@/wechat'; import wechatUser from '@/wechat';
import pt from '@/plain-text';
import { getUrl } from '.'; import { getUrl } from '.';
export function getMemberDutyInfo(that: MainPage) { export function getMemberDutyInfo(that: MainPage) {
@@ -13,25 +14,24 @@ export function getMemberDutyInfo(that: MainPage) {
}) })
.then((res) => { .then((res) => {
const data = res.data.data; const data = res.data.data;
if (data.isInDuty) { that.setState({
dutyData: data,
});
if (!data.isInDuty) {
that.setState({ that.setState({
dutyData: { dutyData: {
isInDuty: data.isInDuty, ...data,
inDutyCnt: data.inDutyCnt, offDutyReason: pt.get().common.offDutyReason,
currentDuty: data.currentDuty,
place: data.place,
},
inDutyCnt: data.inDutyCnt,
});
} else {
that.setState({
dutyData: {
isInDuty: data.isInDuty,
offDutyReason: data.offDutyReason,
dutyRecoverTime: data.dutyRecoverTime,
place: data.place,
}, },
}); });
if (data.currentDuty === '0') {
that.setState({
dutyData: {
...data,
place: pt.get().common.place,
},
});
}
} }
}) })
.catch((err) => { .catch((err) => {
@@ -39,6 +39,10 @@ export function getMemberDutyInfo(that: MainPage) {
that.setState({ that.setState({
dutyData: { dutyData: {
isInDuty: false, isInDuty: false,
inDutyCnt: 0,
currentDuty: '0',
otherDutyStart: '',
otherDutyEnd: '',
offDutyReason: '获取失败!Network Error!', offDutyReason: '获取失败!Network Error!',
dutyRecoverTime: '获取失败!Network Error!', dutyRecoverTime: '获取失败!Network Error!',
place: '204', place: '204',
+35
View File
@@ -0,0 +1,35 @@
import PicUploader from '@/components/PicUploader/PicUploader';
import Taro from '@tarojs/taro';
import pt from '@/plain-text';
import wechatUser from '@/wechat';
import { randomString } from '@/utils/random';
import { getUrl } from '.';
const randomLength = 8;
export function picUpload(that: PicUploader, file: string) {
Taro.uploadFile({
url: getUrl('/upload/pic'),
filePath: file,
name: randomString(randomLength),
formData: {
token: wechatUser.getToken(),
source: that.props.source,
id: that.props.id,
},
})
.then((res) => {
console.log(res.data);
Taro.atMessage({
message: pt.get().button.submitText.success,
type: 'success',
});
})
.catch((err) => {
console.log(err.errMsg);
Taro.atMessage({
message: pt.get().button.submitText.error + err.errMsg,
type: 'error',
});
});
}
+9 -23
View File
@@ -1,51 +1,37 @@
import TicketDetail from '@/pages/TicketDetail/TicketDetail'; import { Comment } from '@/pages/TicketDetail/Comment';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import pt from '@/plain-text'; import pt from '@/plain-text';
import wechatUser from '@/wechat'; import wechatUser from '@/wechat';
import { getUrl } from '.'; import { getUrl } from '.';
const reLaunchInterval = 1000; export function submitComment(that: Comment) {
export function submitComment(that: TicketDetail) {
that.setState({ that.setState({
isLoading: { isLoading: true,
...that.state.isLoading,
comment: true,
},
}); });
Taro.request({ Taro.request({
url: getUrl('/report'), url: getUrl('/tickets/addnote'),
method: 'POST', method: 'POST',
data: { data: {
token: wechatUser.getToken(), token: wechatUser.getToken(),
comment: that.state.comment, content: that.state.comment,
id: that.props.id,
}, },
}) })
.then((res) => { .then((res) => {
console.log(res.data); console.log(res.data);
that.setState({ that.setState({
isLoading: { isLoading: false,
...that.state.isLoading, commentId: res.data.data.id,
comment: false,
},
}); });
Taro.atMessage({ Taro.atMessage({
message: pt.get().button.submitText.success, message: pt.get().button.submitText.success,
type: 'success', type: 'success',
}); });
setTimeout(() => {
Taro.reLaunch({
url: '/pages/TicketDetail/TicketDetail?id=' + that.state.id,
});
}, reLaunchInterval);
}) })
.catch((err) => { .catch((err) => {
console.log(err.errMsg); console.log(err.errMsg);
that.setState({ that.setState({
isLoading: { isLoading: false,
...that.state.isLoading,
comment: false,
},
}); });
Taro.atMessage({ Taro.atMessage({
message: pt.get().button.submitText.error + err.errMsg, message: pt.get().button.submitText.error + err.errMsg,
+3 -3
View File
@@ -14,7 +14,7 @@ export function getTicketList(that: TicketListPage) {
token: wechatUser.getToken(), token: wechatUser.getToken(),
pageId: that.state.currentPage, pageId: that.state.currentPage,
count: that.state.pageSize, count: that.state.pageSize,
querytype: 0, queryType: 0,
}, },
}) })
.then((res) => { .then((res) => {
@@ -28,7 +28,7 @@ export function getTicketList(that: TicketListPage) {
} }
that.setState({ that.setState({
rs: former.trans(true), rs: former.trans(true),
fixList: data.data.map( fixList: data.list.map(
(item: { (item: {
id: number; id: number;
device: string; device: string;
@@ -67,7 +67,7 @@ export function searchTicketList(that: TicketListPage) {
pageId: that.state.currentPage, pageId: that.state.currentPage,
count: that.state.pageSize, count: that.state.pageSize,
value: that.state.search, value: that.state.search,
querytype: 0, queryType: 0,
}, },
}) })
.then((res) => { .then((res) => {
+4
View File
@@ -4,6 +4,7 @@ import Taro from '@tarojs/taro';
import moment from 'moment'; import moment from 'moment';
import { FixStatus } from '@/common'; import { FixStatus } from '@/common';
import pt from '@/plain-text'; import pt from '@/plain-text';
import wechatUser from '@/wechat';
import { getUrl } from '.'; import { getUrl } from '.';
const mapStatusStep: Map<FixStatus, 0 | 1 | 2 | 3> = new Map([ const mapStatusStep: Map<FixStatus, 0 | 1 | 2 | 3> = new Map([
@@ -23,6 +24,7 @@ export function getTicketInfo(that: DetailFramework, id: number) {
method: 'GET', method: 'GET',
data: { data: {
id: id, id: id,
token: wechatUser.getToken(),
}, },
}) })
.then((res) => { .then((res) => {
@@ -56,6 +58,7 @@ export function getTicketInfo(that: DetailFramework, id: number) {
type: 0 | 1 | 2; type: 0 | 1 | 2;
content: string; content: string;
createdTime: string; createdTime: string;
pic: string[];
}) => { }) => {
notes.push({ notes.push({
avatar: item.avatar, avatar: item.avatar,
@@ -64,6 +67,7 @@ export function getTicketInfo(that: DetailFramework, id: number) {
type: item.type, type: item.type,
content: item.content, content: item.content,
createdTime: moment(item.createdTime as string), createdTime: moment(item.createdTime as string),
pic: item.pic,
}); });
}, },
); );
+11
View File
@@ -1,3 +1,14 @@
export const randomInt = (floor: number, ceiling: number) => { export const randomInt = (floor: number, ceiling: number) => {
return Math.floor(Math.random() * (ceiling - floor + 1) + floor); return Math.floor(Math.random() * (ceiling - floor + 1) + floor);
}; };
export const randomString = (length: number) => {
const chars =
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const maxPos = chars.length;
let randomStr = '';
for (let i = 0; i < length; i++) {
randomStr += chars.charAt(Math.floor(Math.random() * maxPos));
}
return randomStr;
};