Compare commits

..

6 Commits

16 changed files with 262 additions and 58 deletions

1
src/common.ts 100644
View File

@ -0,0 +1 @@
export type FixStatus = 1 | 2 | 3 | 4 | 5;

View File

@ -0,0 +1,3 @@
export default {
component: true,
};

View File

@ -0,0 +1,49 @@
import { View } from '@tarojs/components';
import { Component, ReactNode } from 'react';
import { TicketNote, StatusStr } from '@/pages/TicketDetail/TicketNote';
import pt from '@/plain-text';
import { timeFormat } from '@/utils';
import { AtDivider } from 'taro-ui';
import './NoteCard.scss';
interface NoteCardProps {
note: TicketNote;
}
export default class NoteCard extends Component<NoteCardProps, {}> {
props: Readonly<NoteCardProps> = {
note: new TicketNote(),
};
render(): ReactNode {
var message = '';
const note = this.props.note;
const td = pt.get().ticketDetail;
const createMessage = td.createTicketMessage;
const modifyMessage = td.statusModifyMessage;
const prefix = td.statusModifyPrefix;
switch (note.type) {
case 0:
message = createMessage;
break;
case 1:
message = note.content;
break;
case 2:
message = prefix + modifyMessage.get(note.content as StatusStr) || '';
break;
}
return (
<View>
<View className='at-article__h2'>{note.op}</View>
<View className='at-article__info'>
{note.createdTime.format(timeFormat)}
</View>
<View className='at-article__p'>{message}</View>
<AtDivider />
</View>
);
}
}

View File

@ -0,0 +1,3 @@
export default {
component: true,
};

View File

@ -0,0 +1,25 @@
import { Component, ReactNode } from 'react';
import NoteCard from '@/components/NoteCard/NoteCard';
import { TicketNote } from '@/pages/TicketDetail/TicketNote';
import { View } from '@tarojs/components';
interface NoteListProps {
noteList: Array<TicketNote>;
}
export default class NoteList extends Component<NoteListProps, {}> {
props: Readonly<NoteListProps> = {
noteList: [],
};
render(): ReactNode {
return (
<View>
{this.props.noteList.map((note, idx) => (
<View key={idx}>
<NoteCard note={note} />
</View>
))}
</View>
);
}
}

View File

@ -3,39 +3,27 @@ import { View } from '@tarojs/components';
import { getCurrentInstance } from '@tarojs/runtime'; import { getCurrentInstance } from '@tarojs/runtime';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import pt from '@/plain-text'; import pt from '@/plain-text';
import { AtSteps } from 'taro-ui'; import { AtCard, AtSteps, AtButton } from 'taro-ui';
import moment from 'moment';
import { RequestState } from '@/service'; import { RequestState } from '@/service';
import { getTicketInfo } from '@/service/ticketsInfo'; import { getTicketInfo } from '@/service/ticketsInfo';
import { FixStatus } from '@/common';
import PageFooter from '@/components/PageFooter/PageFooter';
import NoteList from '@/components/NoteList/NoteList';
import { TicketNote, TicketInfo } from './TicketNote';
const mapStatusStep: Map<FixStatus, 0 | 1 | 2 | 3> = new Map([
[1, 0],
[2, 1],
[3, 2],
[4, 2],
[5, 3],
]);
interface StepItemData { interface StepItemData {
title: string; title: string;
} }
export class TicketInfo {
id: number;
type: 0 | 1;
device: string;
deviceModel: string;
description: string;
createdTime: moment.Moment;
status: 1 | 2 | 3 | 4 | 5;
}
export class TicketNote {
id: number;
op: string;
type: 0 | 1 | 2;
content: string;
createdTime: moment.Moment;
}
function renderNote(n: TicketNote): JSX.Element {
return <View>{n.id}</View>;
}
interface TicketDetailState { interface TicketDetailState {
id: number;
current: number; current: number;
items: Array<StepItemData>; items: Array<StepItemData>;
ticketInfo: TicketInfo; ticketInfo: TicketInfo;
@ -45,7 +33,6 @@ interface TicketDetailState {
export default class TicketDetail extends Component<{}, TicketDetailState> { export default class TicketDetail extends Component<{}, TicketDetailState> {
state = { state = {
id: 0,
current: 0, current: 0,
items: [], items: [],
ticketInfo: new TicketInfo(), ticketInfo: new TicketInfo(),
@ -62,11 +49,10 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
const id = router?.params.id as number; const id = router?.params.id as number;
const items = pt.get().ticketDetail.stepItems; const items = pt.get().ticketDetail.stepItems;
this.setState({ this.setState({
id: id,
items: items, items: items,
}); });
getTicketInfo(this); getTicketInfo(this, id);
} }
render(): ReactNode { render(): ReactNode {
@ -76,16 +62,58 @@ export default class TicketDetail extends Component<{}, TicketDetailState> {
return <View>Request failed</View>; return <View>Request failed</View>;
} }
const status = this.state.ticketInfo.status;
this.setState({
current: mapStatusStep.get(status) || 0,
});
return ( return (
<View> <View>
<View>{this.state.ticketInfo.deviceModel}</View> <View className='at-article__h1'>
{this.state.ticketInfo.device +
' ' +
this.state.ticketInfo.deviceModel}
</View>
<View className='at-article__info'>
{pt.get().common.createdAtText(this.state.ticketInfo.createdTime)}
</View>
<View style={{ marginTop: 10, marginBottom: 10 }}>
<AtCard title={pt.get().ticketDetail.descTitle}>
<View className='at-article__h3'>
{this.state.ticketInfo.description}
</View>
</AtCard>
</View>
<View style={{ padding: 10 }}>
<AtSteps <AtSteps
items={this.state.items} items={this.state.items}
current={this.state.current} current={this.state.current}
onChange={() => {}} onChange={() => {}}
/> />
<View>TicketDetail: {this.state.id}</View> </View>
<View>{this.state.notes.map(item => renderNote(item))}</View> <View
className='at-row'
style={{ paddingTop: 10, paddingBottom: 10, width: '100%' }}
>
<View
className='at-col'
style={{ marginLeft: 10, paddingRight: 5, width: '50%' }}
>
<AtButton type='primary'>{pt.get().ticketDetail.tookAway}</AtButton>
</View>
<View
className='at-col'
style={{ marginRight: 10, paddingLeft: 5, width: '50%' }}
>
<AtButton type='secondary'>
{pt.get().ticketDetail.addNote}
</AtButton>
</View>
</View>
<View style={{ padding: 10 }}>
<NoteList noteList={this.state.notes} />
</View>
<PageFooter />
</View> </View>
); );
} }

View File

@ -0,0 +1,21 @@
import { FixStatus } from '@/common';
export class TicketInfo {
id: number;
type: 0 | 1;
device: string;
deviceModel: string;
description: string;
createdTime: moment.Moment;
status: FixStatus;
}
export class TicketNote {
id: number;
op: string;
type: 0 | 1 | 2;
content: string;
createdTime: moment.Moment;
}
export type StatusStr = '1' | '2' | '3' | '4' | '5';

View File

@ -2,12 +2,37 @@ interface StepItem {
title: string; title: string;
} }
type StatusStr = '1' | '2' | '3' | '4' | '5';
export interface TicketDetailText { export interface TicketDetailText {
stepItems: Array<StepItem>; stepItems: Array<StepItem>;
createTicketMessage: string;
statusModifyPrefix: string;
statusModifyMessage: Map<StatusStr, string>;
descTitle: string;
tookAway: string;
addNote: string;
} }
export const ticketDetailZhCn: TicketDetailText = { export const ticketDetailZhCn: TicketDetailText = {
stepItems: [{ title: '创建成功' }, { title: '维修中' }, { title: '待取回' }], stepItems: [
{ title: '创建成功' },
{ title: '维修中' },
{ title: '待取回' },
{ title: '工单完成' },
],
createTicketMessage: '创建了维修',
statusModifyPrefix: '将维修状态更改为:',
statusModifyMessage: new Map<StatusStr, string>([
['1', '维修中'],
['2', '2(?)'],
['3', '3(?)'],
['4', '维修成功待取回'],
['5', '维修成功已取回'],
]),
descTitle: '问题描述',
tookAway: '已取回',
addNote: '添加评论',
}; };
export const ticketDetailEnUs: TicketDetailText = { export const ticketDetailEnUs: TicketDetailText = {
@ -15,5 +40,18 @@ export const ticketDetailEnUs: TicketDetailText = {
{ title: 'Ticket created' }, { title: 'Ticket created' },
{ title: 'Repairing' }, { title: 'Repairing' },
{ title: 'Take home' }, { title: 'Take home' },
{ title: 'Finished' },
], ],
createTicketMessage: 'Created ticket',
statusModifyPrefix: 'Modified repair status to: ',
statusModifyMessage: new Map<StatusStr, string>([
['1', 'Repairing'],
['2', '2(?)'],
['3', '3(?)'],
['4', 'Device to be taken home'],
['5', 'Ticket finished'],
]),
descTitle: 'Problem description',
tookAway: 'Already took home',
addNote: 'Add a comment',
}; };

View File

@ -0,0 +1,17 @@
import { Moment } from 'moment';
export interface CommonText {
createdAtText(time: Moment): string;
}
export const commonTextZhCn: CommonText = {
createdAtText(time: Moment): string {
return '创建于 ' + time.format('YYYY-MM-DD HH:mm');
},
};
export const commonTextEnUs: CommonText = {
createdAtText(time: Moment): string {
return 'Created at ' + time.format('YYYY-MM-DD HH:mm');
},
};

View File

@ -15,8 +15,10 @@ import {
ticketDetailEnUs, ticketDetailEnUs,
ticketDetailZhCn, ticketDetailZhCn,
} from './TicketDetail'; } from './TicketDetail';
import { CommonText, commonTextEnUs, commonTextZhCn } from './common';
interface TextRecord { interface TextRecord {
common: CommonText;
pageFooter: PageFooterText; pageFooter: PageFooterText;
mainPage: MainPageText; mainPage: MainPageText;
userPage: UserPageText; userPage: UserPageText;
@ -33,6 +35,7 @@ interface TextRecord {
} }
const textZhCn: TextRecord = { const textZhCn: TextRecord = {
common: commonTextZhCn,
pageFooter: pageFooterZhCn, pageFooter: pageFooterZhCn,
mainPage: mainPageZhCn, mainPage: mainPageZhCn,
userPage: userPageZhCn, userPage: userPageZhCn,
@ -49,6 +52,7 @@ const textZhCn: TextRecord = {
}; };
const textEnUs: TextRecord = { const textEnUs: TextRecord = {
common: commonTextEnUs,
pageFooter: pageFooterEnUs, pageFooter: pageFooterEnUs,
mainPage: mainPageEnUs, mainPage: mainPageEnUs,
userPage: userPageEnUs, userPage: userPageEnUs,

View File

@ -1,5 +1,15 @@
import process from 'process'; import process from 'process';
/**
* State machine for request
*
* @example
*
* let former = this.state.rs;
* this.setState({
* rs: former.trans(true),
* })
*/
export class RequestState { export class RequestState {
loading: boolean; loading: boolean;
success: boolean; success: boolean;
@ -7,6 +17,16 @@ export class RequestState {
this.loading = true; this.loading = true;
this.success = false; this.success = false;
} }
trans(success: boolean): RequestState {
if (this.loading) {
this.loading = false;
this.success = success;
} else {
console.error('calling trans on not loading state');
}
return this;
}
} }
/** /**

View File

@ -1,26 +1,22 @@
import TicketDetail, { import TicketDetail from '@/pages/TicketDetail/TicketDetail';
TicketInfo, import { TicketInfo, TicketNote } from '@/pages/TicketDetail/TicketNote';
TicketNote,
} from '@/pages/TicketDetail/TicketDetail';
import Taro from '@tarojs/taro'; import Taro from '@tarojs/taro';
import moment from 'moment'; import moment from 'moment';
import { getUrl } from '.'; import { getUrl } from '.';
export function getTicketInfo(that: TicketDetail) { export function getTicketInfo(that: TicketDetail, id: number) {
Taro.request({ Taro.request({
url: getUrl('/tickets/info'), url: getUrl('/tickets/info'),
method: 'GET', method: 'GET',
data: { data: {
id: that.state.id, id: id,
}, },
}) })
.then(res => { .then(res => {
let former = that.state.rs;
if (!res.data.success) { if (!res.data.success) {
that.setState({ that.setState({
rs: { rs: former.trans(false),
loading: false,
success: false,
},
}); });
} else { } else {
const data = res.data.data; const data = res.data.data;
@ -30,7 +26,7 @@ export function getTicketInfo(that: TicketDetail) {
device: data.device, device: data.device,
deviceModel: data.deviceModel, deviceModel: data.deviceModel,
description: data.description, description: data.description,
createdTime: moment(), createdTime: moment(data.createdTime as string),
status: data.status, status: data.status,
}; };
const notes: Array<TicketNote> = []; const notes: Array<TicketNote> = [];
@ -40,26 +36,21 @@ export function getTicketInfo(that: TicketDetail) {
op: item.op, op: item.op,
type: item.type, type: item.type,
content: item.content, content: item.content,
createdTime: moment(), createdTime: moment(item.createdTime as string),
}); });
}); });
that.setState({ that.setState({
ticketInfo: ticketDetail, ticketInfo: ticketDetail,
notes: notes, notes: notes,
rs: { rs: former.trans(true),
loading: false,
success: true,
},
}); });
} }
}) })
.catch(reason => { .catch(reason => {
let former = that.state.rs;
that.setState({ that.setState({
rs: { rs: former.trans(false),
loading: false,
success: false,
},
}); });
console.log(reason); console.error(reason);
}); });
} }

View File

@ -0,0 +1,3 @@
import * as Time from './time';
export const timeFormat = Time.timeFormat;

View File

@ -0,0 +1 @@
export const timeFormat = 'YYYY-MM-DD HH:mm';