Commit 446a9198 by 姜雷

添加交互逻辑

parent f3f7f84b
...@@ -65,13 +65,28 @@ type ControllerParams = { ...@@ -65,13 +65,28 @@ type ControllerParams = {
customerId: number; customerId: number;
campusId: number; campusId: number;
}; };
type ControllerResponse = { type Balance = {
amount: number;
// allowEmptyValue: false
// 服务数量
serviceId: string;
// allowEmptyValue: false
// 服务id -1:授信额度;0:艾米;1:豆
serviceName: string;
// allowEmptyValue: false
// 服务名称
};
export type ControllerResponse = {
appointmentThresholdPrompt: string;
balances: Balance[];
beanAmount: number; beanAmount: number;
defaultType: ShowerUseType;
money: number; money: number;
thresholdPrompt: string; thresholdPrompt: string;
thresholdValue: number; thresholdValue: number;
useType: ShowerUseType; useType: ShowerUseType;
defaultType: ShowerUseType;
}; };
export const getShowerController = ( export const getShowerController = (
...@@ -81,3 +96,165 @@ export const getShowerController = ( ...@@ -81,3 +96,165 @@ export const getShowerController = (
url: '/dcxy/api/shower/controllerConfigs', url: '/dcxy/api/shower/controllerConfigs',
data: params, data: params,
}); });
type AppointDeviceParam = {
userId: number;
campusId: number;
location?: string;
pageNum?: number;
pageSize?: number;
};
export type AppointDeviceResponse = {
appointable: boolean;
// example: false
// allowEmptyValue: false
// 是否可预约
code: string;
// allowEmptyValue: false
// 设备编号
inPunishment: boolean;
// example: false
// allowEmptyValue: false
// 用户是在惩罚中
location: string;
// allowEmptyValue: false
// 设备位置
operationMode: number;
// allowEmptyValue: false
// 设备计费模式
};
export const getAppointmentDevice = (
params: AppointDeviceParam,
): Promise<ResponseDataEntity<{ list: AppointDeviceResponse[] }>> =>
showerFetch({
url: '/dcxy/api/shower/appointment/devices',
data: params,
});
type AppointingParams = {
account: string;
// allowEmptyValue: false
// 登录账号
deviceCode: string;
// allowEmptyValue: false
// 设备编号
phone: string;
// allowEmptyValue: false
// 手机号
userId: number;
// allowEmptyValue: false
// 用户ID
userName: string;
// allowEmptyValue: false
// 用户名称
};
export const appointingEquipment = (params: AppointingParams) =>
showerFetch({
url: '/dcxy/api/shower/appointment/appointing',
method: 'POST',
data: params,
});
type AppointmentRecordsParams = {
pageNum?: number;
// 当前页码
pageSize?: number;
// 页面大小
orderSort?: string;
// 排序
userId: number;
// 用户ID
appointTimeStart?: string;
// 预约时间区间上限
appointTimeEnd?: string;
// 预约时间区间下限
};
export type AppointmentRecordsResponse = {
appointTime: string;
// allowEmptyValue: false
// 预约时间
campusName: string;
// allowEmptyValue: false
// 所属区域
deviceCode: string;
// allowEmptyValue: false
// 设备编号
deviceLocation: string;
// allowEmptyValue: false
// 设备位置
expireTime: string;
// allowEmptyValue: false
// 到期时间
status: number;
// allowEmptyValue: false
// 状态: 0-预约中,1-预约成功,2-使用中,3-完成,4-预约失败,5-失效(逾期未使用)
used: boolean;
// example: false
// allowEmptyValue: false
// 是否使用
};
export const getAppointmentRecords = (
params: AppointmentRecordsParams,
): Promise<ResponseDataEntity<{ list: AppointmentRecordsResponse[] }>> =>
showerFetch({
url: '/dcxy/api/shower/appointment/appointRecords',
data: params,
});
type UserAppointableParams = {
userId: number;
campusId: number;
};
export type UserAppointableData = {
appointMode: number;
// allowEmptyValue: false
// 校验结果:0-校区未启用预约功能,1-校区未设置惩罚时长,2-用户未在惩罚中,3-用户在惩罚中
defaultType: number;
// allowEmptyValue: false
// 混合模式时的默认使用模式
duration: number;
// allowEmptyValue: false
// 预约有效时长
message: string;
// allowEmptyValue: false
// 被禁用时提示消息
punishment: number;
// allowEmptyValue: false
// 系统惩罚时长
useType: number;
// allowEmptyValue: false
// 使用模式: 1-蓝牙,2-预约,3-混合
userPunishment: number;
// allowEmptyValue: false
// 用户剩余惩罚时长
};
export const getUserAppointableData = (
params: UserAppointableParams,
): Promise<ResponseDataEntity<UserAppointableData>> =>
showerFetch({
url: `/dcxy/api/shower/appointment/user/${params.userId}/appointable/${
params.campusId
}`,
});
...@@ -24,7 +24,7 @@ class App extends Component { ...@@ -24,7 +24,7 @@ class App extends Component {
*/ */
config: Config = { config: Config = {
pages: [ pages: [
'pages/Shower/ShowerAppointment', // 'pages/Shower/ShowerAppointment',
'pages/index/index', 'pages/index/index',
'pages/Home/Home', 'pages/Home/Home',
'pages/Order/OrderPay/OrderPay', 'pages/Order/OrderPay/OrderPay',
...@@ -41,7 +41,7 @@ class App extends Component { ...@@ -41,7 +41,7 @@ class App extends Component {
'pages/Content/Content', 'pages/Content/Content',
'pages/WebPage/WebPage', 'pages/WebPage/WebPage',
'pages/Shower/Shower', 'pages/Shower/Shower',
// 'pages/Shower/ShowerAppointment', 'pages/Shower/ShowerAppointment',
'pages/WaterDispenser/WaterDispenser', 'pages/WaterDispenser/WaterDispenser',
'pages/Account/Account', 'pages/Account/Account',
], ],
......
import { useState, useCallback } from '@tarojs/taro';
import { BaseEventOrig } from '@tarojs/components/types/common';
function useInputValue(initialValue: string) {
let [value, setValue] = useState(initialValue);
let onChange = useCallback(function(
event: BaseEventOrig<{
value: string;
cursor: number;
keyCode: number;
}>,
) {
setValue(event.detail.value);
}, []);
return {
value,
onChange,
};
}
export default useInputValue;
...@@ -38,7 +38,12 @@ import MenuIconNormal from '@/components/MenuIcon/normal/MenuIconNormal'; ...@@ -38,7 +38,12 @@ import MenuIconNormal from '@/components/MenuIcon/normal/MenuIconNormal';
import MenuIconBlock from '@/components/MenuIcon/block/MenuIconBlock'; import MenuIconBlock from '@/components/MenuIcon/block/MenuIconBlock';
import MenuIconBig from '@/components/MenuIcon/big/MenuIconBig'; import MenuIconBig from '@/components/MenuIcon/big/MenuIconBig';
import { updateServiceList } from '@/store/rootReducers/service'; import { updateServiceList } from '@/store/rootReducers/service';
import { getShowerController, ShowerUseType } from '@/api/shower'; import {
getShowerController,
ShowerUseType,
ControllerResponse,
} from '@/api/shower';
import { updateShowerControlConfig } from '@/store/rootReducers/shower';
type PageStateProps = { type PageStateProps = {
userinfo: Customer; userinfo: Customer;
...@@ -47,6 +52,7 @@ type PageStateProps = { ...@@ -47,6 +52,7 @@ type PageStateProps = {
type PageDispatchProps = { type PageDispatchProps = {
updateUserInfo: (e: UserState) => void; updateUserInfo: (e: UserState) => void;
updateServiceList: (e: Service[]) => void; updateServiceList: (e: Service[]) => void;
updateShowerControlConfig: (e: ControllerResponse) => void;
}; };
type BeanAccount = { type BeanAccount = {
...@@ -78,6 +84,9 @@ interface Home { ...@@ -78,6 +84,9 @@ interface Home {
updateServiceList(entity: Service[]) { updateServiceList(entity: Service[]) {
dispatch(updateServiceList(entity)); dispatch(updateServiceList(entity));
}, },
updateShowerControlConfig(e: ControllerResponse) {
dispatch(updateShowerControlConfig(e));
},
}), }),
) )
class Home extends Component { class Home extends Component {
...@@ -191,6 +200,7 @@ class Home extends Component { ...@@ -191,6 +200,7 @@ class Home extends Component {
}) })
.then(res => { .then(res => {
let data = res.data; let data = res.data;
updateShowerControlConfig(res.data);
let type = let type =
data.useType === ShowerUseType.mix ? data.defaultType : data.useType; data.useType === ShowerUseType.mix ? data.defaultType : data.useType;
if (type === ShowerUseType.bluetooth) { if (type === ShowerUseType.bluetooth) {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
background: linear-gradient(180deg, #486dec, #b3b8fc); background: linear-gradient(180deg, #486dec, #b3b8fc);
.ShowerAppointment-Searchbox { .ShowerAppointment-Searchbox {
height: 100px; height: 100px;
margin: 0 40px 0; margin: 0 40px 28px;
background-color: #fff; background-color: #fff;
border-radius: 16px; border-radius: 16px;
display: flex; display: flex;
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
} }
} }
.ShowerAppointment-Account { .ShowerAppointment-Account {
margin: 28px 40px 34px; margin: 0 40px 34px;
color: #fff; color: #fff;
font-size: 28px; font-size: 28px;
display: flex; display: flex;
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
} }
} }
.ShowerAppointment-Content { .ShowerAppointment-Content {
box-sizing: border-box;
padding: 60px 40px; padding: 60px 40px;
background-color: #fff; background-color: #fff;
flex: 1; flex: 1;
...@@ -56,53 +57,9 @@ ...@@ -56,53 +57,9 @@
font-size: 24px; font-size: 24px;
color: #6180f4; color: #6180f4;
} }
.ShowerAppointment-Equipment-item {
position: relative;
font-size: 28px;
color: #333;
height: 158px;
background-color: #f7f8fe;
border-radius: 16px;
padding: 14px 0 0 32px;
margin-bottom: 20px;
&.disabled {
color: #999;
}
.ShowerAppointment-Equipment-row {
display: flex;
margin-bottom: 6px;
line-height: 44px;
.ShowerAppointment-Equipment-name {
margin-right: 32px;
}
.ShowerAppointment-Equipment-value {
width: 312px;
}
}
.ShowerAppointment-Equipment-appoint {
position: absolute;
top: 50px;
right: 0;
width: 136px;
height: 68px;
text-align: center;
line-height: 68px;
background-color: #e4f3da;
color: #6bb11a;
font-size: 32px;
font-weight: bold;
border-radius: 16px 0 0 16px;
}
.ShowerAppointment-Equipment-disabled {
position: absolute;
width: 40px;
height: 40px;
right: 46px;
top: 62px;
}
}
} }
.ShowerAppointment-AppointmentList { .ShowerAppointment-AppointmentList {
box-sizing: border-box;
flex: 1; flex: 1;
overflow-y: scroll; overflow-y: scroll;
padding: 10px 40px 20px; padding: 10px 40px 20px;
......
import './ShowerAppointment.scss'; import './ShowerAppointment.scss';
import { View, Input, Text, Image } from '@tarojs/components'; import { View, Input, Text, Image, ScrollView } from '@tarojs/components';
import DisabledIcon from '../../images/shower/ic_jinyuyue@2x.png'; import Taro, { useState, useReducer, useEffect } from '@tarojs/taro';
import { useState } from '@tarojs/taro';
import AppointermentCard from './components/AppointermentCard/AppointermentCard'; import AppointermentCard from './components/AppointermentCard/AppointermentCard';
import useInputValue from '@/hooks/useInputValue';
import {
getAppointmentDevice,
appointingEquipment,
ShowerUseType,
} from '@/api/shower';
import { useSelector } from '@tarojs/redux';
import { Customer } from '@/types/Customer/Customer';
import useDeviceList from './hooks/useDeviceList';
import AppointermentEquipment from './components/AppointermentEquipment/AppointermentEquipment';
import useAppointRecordsList from './hooks/useAppointRecordsList';
import useCheckAppointable from './hooks/useCheckAppointable';
import { ShowerState } from '@/store/rootReducers/shower';
function ShowerAppointment() { function ShowerAppointment() {
const [showState, setShowState] = useState(2); const userInfo = useSelector(
(state: { userinfo: Customer }) => state.userinfo,
);
const showerControlConfig = useSelector(
(state: { showerState: ShowerState }) => state.showerState,
);
const [showState, setShowState] = useState(1);
const search = useInputValue('');
const [searchString, setSearchString] = useState('');
const appointableData = useCheckAppointable(
userInfo.customerId,
userInfo.areaId,
);
const list = useDeviceList(
userInfo.areaId,
userInfo.customerId,
searchString,
);
const [records, resetRecordList, fetchMoreRecordList] = useAppointRecordsList(
userInfo.customerId,
);
const searchEquipment = () => {
setSearchString(search.value);
};
const appointingStart = (deviceCode: string) => {
// Taro.showModal({
// title: '',
// content: '',
// }).then(res => {
// if(res.confirm){
// }
// })
appointingEquipment({
account: userInfo.customerId.toString(),
phone: userInfo.customerPhone,
userId: userInfo.customerId,
userName: userInfo.customerName,
deviceCode: deviceCode,
})
.then(res => {
console.log(res);
Taro.showToast({
title: res.msg,
});
})
.catch(err => {
console.log(err);
});
};
const goBluetoothShower = () => {
Taro.navigateTo({
url: '/pages/Shower/Shower',
});
};
return ( return (
<View className='ShowerAppointment'> <View className='ShowerAppointment'>
{showState == 1 && ( {showState == 1 && (
<View className='ShowerAppointment-Searchbox'> <View className='ShowerAppointment-Searchbox'>
<Input placeholder='请输入要少选的设备位置' /> <Input
<Text className='ShowerAppointment-Searchbox-btn'>开始筛选</Text> placeholder='请输入要少选的设备位置'
value={search.value}
onInput={e => search.onChange(e)}
/>
<Text
className='ShowerAppointment-Searchbox-btn'
onClick={searchEquipment}>
开始筛选
</Text>
</View> </View>
)} )}
{showState == 1 && ( {showState == 1 && showerControlConfig.controllerConfigs.balances.length && (
<View className='ShowerAppointment-Account'> <View className='ShowerAppointment-Account'>
<View className='ShowerAppointment-Account-item'> {showerControlConfig.controllerConfigs.balances.map(item => (
<Text className='name'>艾米币</Text> <View className='ShowerAppointment-Account-item'>
<Text>10.00元</Text> <Text className='name'>{item.serviceName}</Text>
</View> <Text>{item.amount.toFixed(2)}</Text>
<View className='ShowerAppointment-Account-item'> </View>
<Text className='name'>吹风豆</Text> ))}
<Text>22.00元</Text>
</View>
</View> </View>
)} )}
{showState == 1 && ( {showState == 1 && (
<View className='ShowerAppointment-Content'> <View className='ShowerAppointment-Content'>
<View className='ShowerAppointment-Equipment-title'>设备列表</View> <View className='ShowerAppointment-Equipment-title'>设备列表</View>
<View className='ShowerAppointment-Equipment-info'> <View className='ShowerAppointment-Equipment-info'>
如预约未使用,将在12小时内无法再次预约 {appointableData.message}
</View>
<View className='ShowerAppointment-Equipment-item'>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text>
<Text className='ShowerAppointment-Equipment-value'>
AB000075
</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value'>
高新区天赋三街福年广场T2-1812
</Text>
</View>
<View className='ShowerAppointment-Equipment-appoint'>可预约</View>
</View>
<View className='ShowerAppointment-Equipment-item'>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text>
<Text className='ShowerAppointment-Equipment-value'>
AB000075
</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value'>
高新区天赋三街福年广场T2-1812
</Text>
</View>
<View className='ShowerAppointment-Equipment-appoint'>可预约</View>
</View>
<View className='ShowerAppointment-Equipment-item disabled'>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text>
<Text className='ShowerAppointment-Equipment-value'>
AB000075
</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value'>
高新区天赋三街福年广场T2-1812
</Text>
</View>
<Image
className='ShowerAppointment-Equipment-disabled'
src={DisabledIcon}
/>
</View>
<View className='ShowerAppointment-Equipment-item disabled'>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text>
<Text className='ShowerAppointment-Equipment-value'>
AB000075
</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value'>
高新区天赋三街福年广场T2-1812
</Text>
</View>
<Image
className='ShowerAppointment-Equipment-disabled'
src={DisabledIcon}
/>
</View> </View>
<View className='ShowerAppointment-Equipment-item disabled'> {list.map(item => (
<View className='ShowerAppointment-Equipment-row'> <AppointermentEquipment
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text> key={item.code}
<Text className='ShowerAppointment-Equipment-value'> data={item}
AB000075 appointingStart={appointingStart}
</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value'>
高新区天赋三街福年广场T2-1812
</Text>
</View>
<Image
className='ShowerAppointment-Equipment-disabled'
src={DisabledIcon}
/> />
</View> ))}
</View> </View>
)} )}
{showState == 1 && ( {showState == 1 &&
<View className='ShowerAppointment-ToggleBtn'>自助洗浴</View> showerControlConfig.controllerConfigs.useType === ShowerUseType.mix && (
)} <View
className='ShowerAppointment-ToggleBtn'
onClick={goBluetoothShower}>
自助洗浴
</View>
)}
{showState == 2 && ( {showState == 2 && (
<View className='ShowerAppointment-AppointmentList'> <ScrollView
<AppointermentCard disabled /> className='ShowerAppointment-AppointmentList'
<AppointermentCard /> scrollY
<AppointermentCard /> scrollWithAnimation
<AppointermentCard /> lowerThreshold={50}
</View> onScrollToLower={fetchMoreRecordList}>
{records.map(item => (
<AppointermentCard key={item.deviceCode} data={item} />
))}
</ScrollView>
)} )}
<View className='ShowerAppointment-Footer'> <View className='ShowerAppointment-Footer'>
...@@ -150,9 +158,13 @@ function ShowerAppointment() { ...@@ -150,9 +158,13 @@ function ShowerAppointment() {
</View> </View>
); );
} }
ShowerAppointment.onPullDownRefresh = () => {
console.log('in onPullDownRefresh');
};
ShowerAppointment.config = { ShowerAppointment.config = {
navigationBarBackgroundColor: '#486dec', navigationBarBackgroundColor: '#486dec',
navigationBarTitleText: '', navigationBarTitleText: '',
backgroundColor: '#486dec',
}; };
export default ShowerAppointment; export default ShowerAppointment;
...@@ -32,6 +32,9 @@ ...@@ -32,6 +32,9 @@
line-height: 36px; line-height: 36px;
font-size: 24px; font-size: 24px;
margin-bottom: 10px; margin-bottom: 10px;
&:last-child {
margin-bottom: 20px;
}
text:first-child { text:first-child {
margin-right: 16px; margin-right: 16px;
} }
......
import './AppointermentCard.scss'; import './AppointermentCard.scss';
import { View, Text, Image } from '@tarojs/components'; import { View, Text, Image } from '@tarojs/components';
import DisabledIcon from '../../../../images/shower/img_shixiao@2x.png'; import DisabledIcon from '../../../../images/shower/img_shixiao@2x.png';
import { AppointmentRecordsResponse } from '@/api/shower';
type PageOwnProps = { type PageOwnProps = {
disabled?: boolean; data: AppointmentRecordsResponse;
}; };
const AppointermentCard = (props: PageOwnProps) => { const AppointermentCard = (props: PageOwnProps) => {
const { data } = props;
return ( return (
<View className={`AppointermentCard ${props.disabled ? 'disabled' : ''}`}> <View
className={`AppointermentCard ${data.status === 5 ? 'disabled' : ''}`}>
<View className='AppointermentCard-Title'>我的预约</View> <View className='AppointermentCard-Title'>我的预约</View>
<View className='AppointermentCard-row'> <View className='AppointermentCard-row'>
<Text>设备编码:</Text> <Text>设备编码:</Text>
<Text>AB00075</Text> <Text>{data.deviceCode}</Text>
</View> </View>
<View className='AppointermentCard-row'> <View className='AppointermentCard-row'>
<Text>设备位置:</Text> <Text>设备位置:</Text>
<Text className='AppointermentCard-row-location'> <Text className='AppointermentCard-row-location'>
高新区天府三街福年广场T2-1812 {data.deviceLocation}
</Text> </Text>
</View> </View>
<View className='AppointermentCard-row'> <View className='AppointermentCard-row'>
<Text>预约生效时间:</Text> <Text>预约生效时间:</Text>
<Text>2019-7-9 18:09:30</Text> <Text>{data.appointTime ? data.appointTime : ''}</Text>
</View> </View>
<View className='AppointermentCard-Time'> <View className='AppointermentCard-Time'>
预约失效时间: 2019-7-9 20:03:20 <Text>预约失效时间:</Text>
<Text>2019-15-24 12:45:31</Text>
{/* <Text>{data.expireTime ? data.expireTime : ''}</Text> */}
</View> </View>
{props.disabled && <Image className='AppointermentCard-Dis-Icon' src={DisabledIcon} />} {data.status === 5 && (
<Image className='AppointermentCard-Dis-Icon' src={DisabledIcon} />
)}
</View> </View>
); );
}; };
......
.ShowerAppointment-Equipment {
position: relative;
font-size: 28px;
color: #333;
height: 158px;
background-color: #f7f8fe;
border-radius: 16px;
padding: 14px 0 0 32px;
margin-bottom: 20px;
&.disabled {
color: #999;
}
.ShowerAppointment-Equipment-row {
display: flex;
margin-bottom: 6px;
line-height: 44px;
.ShowerAppointment-Equipment-name {
margin-right: 32px;
}
.ShowerAppointment-Equipment-value {
width: 312px;
&.location {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
}
.ShowerAppointment-Equipment-appoint {
position: absolute;
top: 50px;
right: 0;
width: 136px;
height: 68px;
text-align: center;
line-height: 68px;
background-color: #e4f3da;
color: #6bb11a;
font-size: 32px;
font-weight: bold;
border-radius: 16px 0 0 16px;
}
.ShowerAppointment-Equipment-disabled {
position: absolute;
width: 40px;
height: 40px;
right: 46px;
top: 62px;
}
}
import './AppointermentEquipment.scss';
import { View, Text, Image } from '@tarojs/components';
import { AppointDeviceResponse } from '@/api/shower';
import DisabledIcon from '@/images/shower/ic_jinyuyue@2x.png';
type PageOwnProps = {
data: AppointDeviceResponse;
appointingStart: (deviceCode: string) => void;
};
const AppointermentEquipment = (props: PageOwnProps) => {
const { data, appointingStart } = props;
const clickHandle = () => {
appointingStart && appointingStart(data.code);
};
return (
<View
className={`ShowerAppointment-Equipment ${
data.appointable && !data.inPunishment ? '' : 'disabled'
}`}>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备编码</Text>
<Text className='ShowerAppointment-Equipment-value'>{data.code}</Text>
</View>
<View className='ShowerAppointment-Equipment-row'>
<Text className='ShowerAppointment-Equipment-name'>设备位置</Text>
<Text className='ShowerAppointment-Equipment-value location'>
{data.location}
</Text>
</View>
{data.appointable ? (
<View
className='ShowerAppointment-Equipment-appoint'
onClick={clickHandle}>
可预约
</View>
) : (
<Image
className='ShowerAppointment-Equipment-disabled'
src={DisabledIcon}
/>
)}
</View>
);
};
export default AppointermentEquipment;
import Taro, { useEffect, useState, useReducer } from '@tarojs/taro';
import {
getAppointmentRecords,
AppointmentRecordsResponse,
} from '@/api/shower';
import Actions from '@/types/Store/Actions';
const reducer = (state: AppointmentRecordsResponse[], action: Actions) => {
switch (action.type) {
case 'getRecordList':
return action.payload;
case 'appendRecordList':
return [...state, ...action.payload];
default:
return state;
}
};
const useAppointRecordsList = (
userId: number,
): [AppointmentRecordsResponse[], () => void, () => void] => {
const [pageNum, setPageNum] = useState(1);
const [list, dispatch] = useReducer(reducer, []);
const fetchList = (pageNum: number) => {
return getAppointmentRecords({
userId,
pageSize: 10,
pageNum,
});
};
const fetchMoreList = () => {
Taro.showLoading();
fetchList(pageNum + 1)
.then(res => {
Taro.hideLoading();
console.log(res);
let list = res.data.list;
if (list.length) {
setPageNum(pageNum + 1);
dispatch({ type: 'appendRecordList', payload: res.data.list });
}
})
.catch(err => {
console.log(err);
Taro.showToast({
title: err.msg || '网络错误',
icon: 'none',
});
});
};
const fetchNewList = () => {
Taro.showLoading();
fetchList(1)
.then(res => {
Taro.hideLoading();
console.log(res);
dispatch({ type: 'getRecordList', payload: res.data.list });
})
.catch(err => {
console.log(err);
Taro.showToast({
title: err.msg || '网络错误',
icon: 'none',
});
});
};
useEffect(() => {
fetchNewList();
}, [userId]);
return [list, fetchNewList, fetchMoreList];
};
export default useAppointRecordsList;
import { useEffect, useReducer } from '@tarojs/taro';
import { getUserAppointableData, UserAppointableData } from '@/api/shower';
import Actions from '@/types/Store/Actions';
const reducer = (state: UserAppointableData, action: Actions) => {
switch (action.type) {
case 'getAppointData':
return action.payload;
default:
return state;
}
};
const initState: UserAppointableData = {
appointMode: 0,
defaultType: 0,
duration: 0,
message: '',
punishment: 0,
useType: 0,
userPunishment: 0,
};
const useCheckAppointable = (
userId: number,
campusId: number,
): UserAppointableData => {
const [data, dispatch] = useReducer(reducer, initState);
useEffect(() => {
getUserAppointableData({
userId,
campusId,
})
.then(res => {
console.log(res);
dispatch({ type: 'getAppointData', payload: res.data });
})
.catch(err => {
console.log(err);
});
}, [userId, campusId]);
return data;
};
export default useCheckAppointable;
import Taro, { useReducer, useEffect } from '@tarojs/taro';
import Actions from '@/types/Store/Actions';
import { getAppointmentDevice, AppointDeviceResponse } from '@/api/shower';
const reducer = (state: AppointDeviceResponse[], action: Actions) => {
switch (action.type) {
case 'updateDeviceList':
return action.payload;
default:
return state;
}
};
const useDeviceList = (
campusId: number,
userId: number,
location: string,
): AppointDeviceResponse[] => {
const [list, dispatch] = useReducer(reducer, []);
// const fetchList = (pageNum: number) => {
// getAppointmentDevice({ location, campusId, userId, pageNum })
// .then(res => {
// Taro.hideLoading();
// dispatch({ type: 'updateDeviceList', payload: res.data.list });
// })
// .catch(err => {
// Taro.showToast({
// title: err.msg || '网络错误',
// icon: 'none',
// });
// });
// };
// const fetchNewList = () => {};
// const fetchMoreList = () => {};
useEffect(() => {
Taro.showLoading();
getAppointmentDevice(
location ? { location, campusId, userId } : { campusId, userId },
)
.then(res => {
Taro.hideLoading();
dispatch({ type: 'updateDeviceList', payload: res.data.list });
})
.catch(err => {
Taro.showToast({
title: err.msg || '网络错误',
icon: 'none',
});
});
}, [campusId, userId, location]);
return list;
};
export default useDeviceList;
...@@ -4,6 +4,7 @@ import OrderList from '../pages/Order/OrderList/store'; ...@@ -4,6 +4,7 @@ import OrderList from '../pages/Order/OrderList/store';
import ShowerReducer from '@/pages/Shower/store'; import ShowerReducer from '@/pages/Shower/store';
import serviceList from './rootReducers/service'; import serviceList from './rootReducers/service';
import orderState from './rootReducers/orderState'; import orderState from './rootReducers/orderState';
import showerState from './rootReducers/shower';
export default combineReducers({ export default combineReducers({
userinfo, userinfo,
...@@ -11,4 +12,5 @@ export default combineReducers({ ...@@ -11,4 +12,5 @@ export default combineReducers({
Shower: ShowerReducer, Shower: ShowerReducer,
serviceList, serviceList,
orderState, orderState,
showerState,
}); });
import Actions from '@/types/Store/Actions';
import { ControllerResponse } from '@/api/shower';
export type ShowerState = {
controllerConfigs: ControllerResponse;
};
const INITIAL_STATE = {
controllerConfigs: {
appointmentThresholdPrompt: '',
balances: [],
beanAmount: 0,
defaultType: 0,
money: 0,
thresholdPrompt: '',
thresholdValue: 0,
useType: 0,
},
};
export const updateShowerControlConfig = (
entity: ControllerResponse,
): Actions => ({
type: 'UPDATE_SHOWER_CONFIG',
payload: entity,
});
export default function shower(
state: ShowerState = INITIAL_STATE,
actions: Actions,
): ShowerState {
switch (actions.type) {
case 'UPDATE_SHOWER_CONFIG':
return {
...state,
controllerConfigs: actions.payload,
};
default:
return state;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment