@ledvance/group-ui-biz-bundle 1.0.90 → 1.0.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/modules/diyScene/DefaultScenes.ts +439 -0
- package/src/modules/diyScene/DiySceneActions.ts +206 -0
- package/src/modules/diyScene/DiySceneEditorPage.tsx +356 -0
- package/src/modules/diyScene/DiyScenePage.tsx +281 -0
- package/src/modules/diyScene/Router.ts +25 -0
- package/src/modules/energyConsumption/EnergyConsumptionActions.ts +134 -119
- package/src/modules/energyConsumption/EnergyConsumptionChart.tsx +30 -9
- package/src/modules/energyConsumption/component/DateSwitch.tsx +111 -0
- package/src/modules/energyConsumption/component/NewBarChart.tsx +16 -3
- package/src/modules/timeSchedule/Interface.ts +19 -10
- package/src/modules/timeSchedule/TimeScheduleActions.ts +7 -1
- package/src/modules/timeSchedule/TimeScheduleDetailPage.tsx +116 -26
- package/src/modules/timeSchedule/TimeSchedulePage.tsx +1 -0
- package/src/modules/timeSchedule/components/ManuaSettings.tsx +35 -3
- package/src/navigation/Routers.ts +3 -1
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import {useGroupEzvizConfig} from "@ledvance/base/src/models/modules/NativePropsSlice";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DpResultByMonthResData,
|
|
4
|
+
getDataWithSpecified,
|
|
5
|
+
getDpResultByHour,
|
|
6
|
+
getDpResultByMonth
|
|
7
|
+
} from "@ledvance/base/src/models/TuyaApi";
|
|
3
8
|
import {overDays} from "@ledvance/base/src/utils";
|
|
4
9
|
import {loopsText, monthFormat, monthFormatShort} from "@ledvance/base/src/utils/common";
|
|
5
10
|
import {DateType} from "@ledvance/group-ui-biz-bundle/src/modules/energyConsumption/co2Data";
|
|
@@ -9,150 +14,160 @@ import {isNumber} from "lodash";
|
|
|
9
14
|
import {EnergyData, UnitList} from "./component/EnergyModal";
|
|
10
15
|
|
|
11
16
|
interface LightConfig {
|
|
12
|
-
|
|
17
|
+
energyConsumption?: EnergyData
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
export const useEnergyConsumption = () =>{
|
|
16
|
-
|
|
20
|
+
export const useEnergyConsumption = () => {
|
|
21
|
+
return useGroupEzvizConfig<LightConfig, EnergyData>('energyConsumption', {unit: UnitList[0], price: ''})
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
export const unitDivision = (str: string) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
if (!str) {
|
|
26
|
+
return ['', '']
|
|
27
|
+
}
|
|
28
|
+
const strIndex = str.indexOf('(' || '(')
|
|
29
|
+
const unit = str.substring(strIndex)
|
|
30
|
+
const name = str.split(unit)[0]
|
|
31
|
+
return [name, unit]
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
export async function getElectricity(devIdGroup: string[], addEleDpCode: string, date: string, dateType: DateType): Promise<OverviewItem[]> {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
let res: OverviewItem[] = []
|
|
37
|
+
switch (dateType) {
|
|
38
|
+
case DateType.Year:
|
|
39
|
+
res = await getDpResultByYear(devIdGroup, addEleDpCode, date)
|
|
40
|
+
break
|
|
41
|
+
case DateType.Month:
|
|
42
|
+
res = await getDpResultByYearMonth(devIdGroup, addEleDpCode, date)
|
|
43
|
+
break
|
|
44
|
+
case DateType.Day:
|
|
45
|
+
res = await getDpResultByDate(devIdGroup, addEleDpCode, date);
|
|
46
|
+
break
|
|
47
|
+
}
|
|
48
|
+
return res
|
|
42
49
|
}
|
|
43
50
|
|
|
51
|
+
let dpResultByMonthCache: DpResultByMonthResData[] | undefined
|
|
44
52
|
const getDpResultByYear = async (devIdGroup: string[], addEleDpCode: string, dateStr: string): Promise<OverviewItem[]> => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const monthData = item.years[year];
|
|
55
|
-
if (monthData) {
|
|
56
|
-
Object.keys(monthData).forEach(month => {
|
|
57
|
-
if (mergedData[month] === undefined) {
|
|
58
|
-
mergedData[month] = 0
|
|
59
|
-
}
|
|
60
|
-
const monthNum = Number(monthData[month])
|
|
61
|
-
mergedData[month] += Number(isNumber(monthNum) ? monthNum : 0)
|
|
62
|
-
})
|
|
53
|
+
const year = dateStr;
|
|
54
|
+
let successGroup = dpResultByMonthCache;
|
|
55
|
+
if (!successGroup) {
|
|
56
|
+
const promiseGroup = devIdGroup.map(devId =>
|
|
57
|
+
getDpResultByMonth(devId, addEleDpCode, 'sum').catch(error => ({error}))
|
|
58
|
+
);
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
dpResultByMonthCache = (await Promise.all(promiseGroup)).filter(v => !v.error);
|
|
61
|
+
successGroup = dpResultByMonthCache
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return curMonthList.map(month => {
|
|
67
|
-
return {
|
|
68
|
-
key: `${monthFormat(month)} ${year}`,
|
|
69
|
-
value: (Number(mergedData[month]) || 0).toFixed(2),
|
|
70
|
-
headlineText: `${year}${month}`,
|
|
71
|
-
chartTitle: `${monthFormatShort(month)}\n${year}`
|
|
63
|
+
if (!successGroup) {
|
|
64
|
+
return []
|
|
72
65
|
}
|
|
73
|
-
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
const mergedData = {}
|
|
68
|
+
successGroup.forEach(item => {
|
|
69
|
+
const monthData = item.years[year];
|
|
70
|
+
if (monthData) {
|
|
71
|
+
Object.keys(monthData).forEach(month => {
|
|
72
|
+
if (mergedData[month] === undefined) {
|
|
73
|
+
mergedData[month] = 0
|
|
74
|
+
}
|
|
75
|
+
const monthNum = Number(monthData[month])
|
|
76
|
+
mergedData[month] += Number(isNumber(monthNum) ? monthNum : 0)
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
const curMonthList = Object.keys(mergedData).sort((a, b) => parseInt(b) - parseInt(a));
|
|
81
|
+
return curMonthList.map(month => {
|
|
82
|
+
return {
|
|
83
|
+
key: `${monthFormat(month)} ${year}`,
|
|
84
|
+
value: (Number(mergedData[month]) || 0).toFixed(2),
|
|
85
|
+
headlineText: `${year}${month}`,
|
|
86
|
+
chartTitle: `${monthFormatShort(month)}\n${year}`
|
|
87
|
+
}
|
|
88
|
+
})
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
|
|
77
92
|
const getDpResultByYearMonth = async (deviceIdGroup: string[], addEleDpCode: string, dateStr: string): Promise<OverviewItem[]> => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
const date = dayjs(dateStr)
|
|
94
|
+
const startDay = date.startOf('month').format('YYYYMMDD')
|
|
95
|
+
const endDay = date.endOf('month').format('YYYYMMDD')
|
|
96
|
+
const promiseGroup = deviceIdGroup.map(devId => getDataWithSpecified(devId, addEleDpCode, startDay, endDay, 'sum').catch(error => ({error})))
|
|
97
|
+
const res = await Promise.all(promiseGroup);
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
const successGroup: DpResultByDataWithSpecifiedResData[] = res.filter(v => !v.error);
|
|
100
|
+
const mergedData = {}
|
|
101
|
+
successGroup.forEach(item => {
|
|
102
|
+
if (item.result) {
|
|
103
|
+
Object.keys(item.result).forEach(day => {
|
|
104
|
+
if (mergedData[day] === undefined) {
|
|
105
|
+
mergedData[day] = 0
|
|
106
|
+
}
|
|
107
|
+
const dayNum = Number(item.result[day])
|
|
108
|
+
mergedData[day] += Number(isNumber(dayNum) ? dayNum : 0)
|
|
109
|
+
})
|
|
91
110
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// 提取年、月和日
|
|
99
|
-
const year = time.slice(0, 4);
|
|
100
|
-
const month = time.slice(4, 6);
|
|
101
|
-
const day = time.slice(6, 8);
|
|
111
|
+
})
|
|
112
|
+
return Object.keys(mergedData).filter(v => Number(mergedData[v]) > 0).map(time => {
|
|
113
|
+
// 提取年、月和日
|
|
114
|
+
const year = time.slice(0, 4);
|
|
115
|
+
const month = time.slice(4, 6);
|
|
116
|
+
const day = time.slice(6, 8);
|
|
102
117
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
// 格式化为 'YYYY/MM/DD' 格式
|
|
119
|
+
const formattedDate = `${year}/${month}/${day}`
|
|
120
|
+
const dateStr = `${day}/${month}/${year}`
|
|
121
|
+
const dateObj = dayjs(formattedDate, "YYYY/MM/DD");
|
|
122
|
+
const dayOfWeek = dateObj.day() % 7;
|
|
123
|
+
const key = `${dateStr} (${loopsText[dayOfWeek]})`
|
|
124
|
+
return {
|
|
125
|
+
key,
|
|
126
|
+
value: Number(mergedData[time] || 0).toFixed(2),
|
|
127
|
+
headlineText: formattedDate,
|
|
128
|
+
chartTitle: `${Number(key?.split('/')[0])}\n${loopsText[dayOfWeek]}`
|
|
129
|
+
}
|
|
130
|
+
})
|
|
116
131
|
}
|
|
117
132
|
|
|
118
133
|
|
|
119
134
|
const getDpResultByDate = async (deviceIdGroup: string[], addEleDpCode: string, date: string): Promise<OverviewItem[]> => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
const promiseGroup = deviceIdGroup.map(devId => getDpResultByHour(devId, addEleDpCode, date, 'sum').catch(error => ({error})))
|
|
125
|
-
const res = await Promise.all(promiseGroup);
|
|
126
|
-
// @ts-ignore
|
|
127
|
-
const successGroup: DpResultByDataWithSpecifiedResData[] = res.filter(v => !v.error);
|
|
128
|
-
const mergedData = {}
|
|
129
|
-
successGroup.forEach(item => {
|
|
130
|
-
if (item) {
|
|
131
|
-
Object.keys(item).forEach(day => {
|
|
132
|
-
if (mergedData[day] === undefined) {
|
|
133
|
-
mergedData[day] = 0
|
|
134
|
-
}
|
|
135
|
-
const dayNum = Number(item[day])
|
|
136
|
-
mergedData[day] += Number(isNumber(dayNum) ? dayNum : 0)
|
|
137
|
-
})
|
|
135
|
+
if (overDays(date, 7)) {
|
|
136
|
+
console.log("getDpResultByDate overDays true")
|
|
137
|
+
return []
|
|
138
138
|
}
|
|
139
|
-
|
|
139
|
+
const promiseGroup = deviceIdGroup.map(devId => getDpResultByHour(devId, addEleDpCode, date, 'sum').catch(error => ({error})))
|
|
140
|
+
const res = await Promise.all(promiseGroup);
|
|
141
|
+
// @ts-ignore
|
|
142
|
+
const successGroup: DpResultByDataWithSpecifiedResData[] = res.filter(v => !v.error);
|
|
143
|
+
const mergedData = {}
|
|
144
|
+
successGroup.forEach(item => {
|
|
145
|
+
if (item) {
|
|
146
|
+
Object.keys(item).forEach(day => {
|
|
147
|
+
if (mergedData[day] === undefined) {
|
|
148
|
+
mergedData[day] = 0
|
|
149
|
+
}
|
|
150
|
+
const dayNum = Number(item[day])
|
|
151
|
+
mergedData[day] += Number(isNumber(dayNum) ? dayNum : 0)
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
});
|
|
140
155
|
|
|
141
156
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
})
|
|
146
|
-
for (let i = 0; i <= 23; i++) {
|
|
147
|
-
const hourData = resData?.find(val => val?.key === i)
|
|
148
|
-
const hourKey = hourData?.key || i
|
|
149
|
-
const hourValue = Number(hourData?.value) || 0
|
|
150
|
-
list.push({
|
|
151
|
-
key: `${hourKey.toString().padStart(2, '0')}:00`,
|
|
152
|
-
value: hourValue,
|
|
153
|
-
chartTitle: `${hourKey}:00`,
|
|
154
|
-
headlineText: `${hourKey}:00`
|
|
157
|
+
const list: Array<OverviewItem> = []
|
|
158
|
+
const resData = Object.keys(mergedData)?.map(val => {
|
|
159
|
+
return {key: Number(val?.slice(8, 10)), value: Number(mergedData[val])}
|
|
155
160
|
})
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
for (let i = 0; i <= 23; i++) {
|
|
162
|
+
const hourData = resData?.find(val => val?.key === i)
|
|
163
|
+
const hourKey = hourData?.key || i
|
|
164
|
+
const hourValue = Number(hourData?.value) || 0
|
|
165
|
+
list.push({
|
|
166
|
+
key: `${hourKey.toString().padStart(2, '0')}:00`,
|
|
167
|
+
value: hourValue,
|
|
168
|
+
chartTitle: `${hourKey}:00`,
|
|
169
|
+
headlineText: `${hourKey}:00`
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
return list
|
|
158
173
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback } from "react";
|
|
2
|
-
import { Platform, View, StyleSheet, Image, Text} from "react-native";
|
|
2
|
+
import { Platform, View, StyleSheet, Image, Text, TouchableOpacity} from "react-native";
|
|
3
3
|
import { useRoute } from '@react-navigation/core'
|
|
4
4
|
import Page from "@ledvance/base/src/components/Page";
|
|
5
5
|
import res from "@ledvance/base/src/res";
|
|
@@ -18,6 +18,7 @@ import DateTypeItem from "@ledvance/group-ui-biz-bundle/src/modules/energyConsum
|
|
|
18
18
|
import DateSelectedItem from "@ledvance/group-ui-biz-bundle/src/modules/energyConsumption/component/DateSelectedItem";
|
|
19
19
|
import NewBarChart from "@ledvance/group-ui-biz-bundle/src/modules/energyConsumption/component/NewBarChart";
|
|
20
20
|
import { getElectricity } from "@ledvance/group-ui-biz-bundle/src/modules/energyConsumption/EnergyConsumptionActions";
|
|
21
|
+
import DateSwitch from "./component/DateSwitch";
|
|
21
22
|
|
|
22
23
|
const { convertX: cx, height, width } = Utils.RatioUtils
|
|
23
24
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -49,6 +50,14 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
|
49
50
|
listEmptyText: {
|
|
50
51
|
flex: 0
|
|
51
52
|
},
|
|
53
|
+
downloadIcon: {
|
|
54
|
+
width: cx(24),
|
|
55
|
+
height: cx(24),
|
|
56
|
+
tintColor: props.theme?.global.brand,
|
|
57
|
+
position: 'absolute',
|
|
58
|
+
right: 0,
|
|
59
|
+
top: cx(10)
|
|
60
|
+
}
|
|
52
61
|
});
|
|
53
62
|
|
|
54
63
|
const getDateType = useCallback((date: string) => {
|
|
@@ -87,7 +96,9 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
|
87
96
|
getElectricity(deviceIdGroup, addEleDpCode, state.date, state.dateType).then((res) => {
|
|
88
97
|
state.chartData = res;
|
|
89
98
|
state.loading = false;
|
|
90
|
-
})
|
|
99
|
+
}).catch(()=>{
|
|
100
|
+
state.loading = false;
|
|
101
|
+
});
|
|
91
102
|
}, [state.date]);
|
|
92
103
|
|
|
93
104
|
useUpdateEffect(() => {
|
|
@@ -127,7 +138,7 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
|
127
138
|
}, [state.dateType, state.headlineText]);
|
|
128
139
|
|
|
129
140
|
const getEmptyDataTip = useCallback(() => {
|
|
130
|
-
if (state.over365Days) {
|
|
141
|
+
if (state.over365Days && state.dateType !== DateType.Day) {
|
|
131
142
|
return I18n.getLang('energyconsumption_Daylimit')
|
|
132
143
|
}
|
|
133
144
|
if (state.dateType === DateType.Day && state.over7Days) {
|
|
@@ -139,16 +150,26 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
|
139
150
|
return (
|
|
140
151
|
<Page
|
|
141
152
|
backText={I18n.getLang('consumption_data_annual_bar_chart_system_back_text')}
|
|
142
|
-
headlineIcon={state.chartData?.length ? res.download_icon : undefined}
|
|
143
|
-
onHeadlineIconClick={() => {
|
|
144
|
-
exportFile(state.chartData,params.price,params.unit)
|
|
145
|
-
}}
|
|
146
153
|
showGreenery={false}
|
|
147
154
|
greeneryIcon={res.energy_consumption_greenery}
|
|
148
155
|
loading={state.loading}
|
|
149
156
|
headlineContent={
|
|
150
|
-
<View style={{
|
|
151
|
-
<
|
|
157
|
+
<View style={{width: '100%',flexDirection:'row'}}>
|
|
158
|
+
<DateSwitch
|
|
159
|
+
style={{flex: 1}}
|
|
160
|
+
date={state.date}
|
|
161
|
+
dateType={state.dateType}
|
|
162
|
+
headlineText={state.headlineText}
|
|
163
|
+
onDateChange={(date) => {
|
|
164
|
+
state.date = date;
|
|
165
|
+
}}/>
|
|
166
|
+
<TouchableOpacity onPress={() => {
|
|
167
|
+
exportFile(state.chartData, params.price, params.unit)
|
|
168
|
+
}}>
|
|
169
|
+
<Image
|
|
170
|
+
style={styles.downloadIcon}
|
|
171
|
+
source={state.chartData?.length ? res.download_icon : undefined}/>
|
|
172
|
+
</TouchableOpacity>
|
|
152
173
|
</View>
|
|
153
174
|
}
|
|
154
175
|
>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import ThemeType from "@ledvance/base/src/config/themeType";
|
|
2
|
+
import React, {PropsWithChildren, useCallback, useEffect} from "react";
|
|
3
|
+
import {Image, Text, TouchableOpacity, View, ViewProps} from "react-native";
|
|
4
|
+
import {Utils} from "tuya-panel-kit";
|
|
5
|
+
import {useReactive} from "ahooks";
|
|
6
|
+
import res from "@ledvance/base/src/res";
|
|
7
|
+
import dayjs from "dayjs";
|
|
8
|
+
import {DateType} from "../co2Data";
|
|
9
|
+
|
|
10
|
+
const cx = Utils.RatioUtils.convertX;
|
|
11
|
+
const {withTheme} = Utils.ThemeUtils
|
|
12
|
+
|
|
13
|
+
interface DateSwitchProps extends PropsWithChildren<ViewProps> {
|
|
14
|
+
theme?: ThemeType
|
|
15
|
+
headlineText: string,
|
|
16
|
+
date: string,
|
|
17
|
+
dateType: DateType,
|
|
18
|
+
onDateChange: (string) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default withTheme(function DateSwitch(props: DateSwitchProps) {
|
|
22
|
+
const {dateType, date, onDateChange, theme, headlineText} = props;
|
|
23
|
+
const state = useReactive({
|
|
24
|
+
date: date,
|
|
25
|
+
dateType: dateType,
|
|
26
|
+
headlineText: headlineText,
|
|
27
|
+
disableArrowLeft: false,
|
|
28
|
+
disableArrowRight: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
state.date = date;
|
|
33
|
+
state.headlineText = headlineText;
|
|
34
|
+
state.dateType = dateType;
|
|
35
|
+
const {canPreChangeDate, canNextChangeDate} = canPreOrNextChangeDate(dayjs(date));
|
|
36
|
+
state.disableArrowRight = !canNextChangeDate;
|
|
37
|
+
state.disableArrowLeft = !canPreChangeDate;
|
|
38
|
+
}, [date, headlineText, dateType]);
|
|
39
|
+
|
|
40
|
+
const canPreOrNextChangeDate = useCallback((datejs: dayjs.Dayjs) => {
|
|
41
|
+
const minDatejs = dayjs('2000-1-1');
|
|
42
|
+
const nowDatejs = dayjs();
|
|
43
|
+
const year = datejs.year();
|
|
44
|
+
const month = (datejs.month() + 1).toString().padStart(2, '0');
|
|
45
|
+
const day = datejs.date().toString().padStart(2, '0');
|
|
46
|
+
const dateType = state.dateType;
|
|
47
|
+
const dateUnit = dateType === DateType.Year ? 'year' : (dateType === DateType.Month ? 'month' : 'day');
|
|
48
|
+
let canPreChangeDate = datejs.isAfter(minDatejs, dateUnit);
|
|
49
|
+
let canNextChangeDate = datejs.isBefore(nowDatejs, dateUnit);
|
|
50
|
+
let date: string | undefined = undefined;
|
|
51
|
+
if (datejs >= minDatejs && datejs <= nowDatejs) {
|
|
52
|
+
switch (state.dateType) {
|
|
53
|
+
case DateType.Day:
|
|
54
|
+
date = `${year}${month}${day}`;
|
|
55
|
+
break
|
|
56
|
+
case DateType.Month:
|
|
57
|
+
date = `${year}${month}`;
|
|
58
|
+
break
|
|
59
|
+
case DateType.Year:
|
|
60
|
+
date = `${year}`;
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {date, canPreChangeDate, canNextChangeDate};
|
|
65
|
+
}, [state.dateType]);
|
|
66
|
+
|
|
67
|
+
const changeDate = useCallback((isNextDate: boolean) => {
|
|
68
|
+
const datejs = dayjs(state.date)
|
|
69
|
+
const dateType = state.dateType
|
|
70
|
+
const dateUnit = dateType === DateType.Year ? 'year' : (dateType === DateType.Month ? 'month' : 'day');
|
|
71
|
+
const newDatejs = datejs.add(isNextDate ? 1 : -1, dateUnit);
|
|
72
|
+
const {date, canPreChangeDate, canNextChangeDate} = canPreOrNextChangeDate(newDatejs);
|
|
73
|
+
state.disableArrowRight = !canNextChangeDate;
|
|
74
|
+
state.disableArrowLeft = !canPreChangeDate;
|
|
75
|
+
if (date) {
|
|
76
|
+
onDateChange(date);
|
|
77
|
+
}
|
|
78
|
+
}, [state.date, canPreOrNextChangeDate, state.disableArrowRight, state.disableArrowLeft, onDateChange]);
|
|
79
|
+
|
|
80
|
+
return (<View style={[props.style, {flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}]}>
|
|
81
|
+
<TouchableOpacity
|
|
82
|
+
disabled={state.disableArrowLeft}
|
|
83
|
+
onPress={() => {
|
|
84
|
+
changeDate(false);
|
|
85
|
+
}}>
|
|
86
|
+
<Image
|
|
87
|
+
source={res.arrow_left}
|
|
88
|
+
style={{tintColor: state.disableArrowLeft ? theme?.global.disabledFontColor : theme?.global.brand}}
|
|
89
|
+
height={cx(36)}
|
|
90
|
+
width={cx(36)}/>
|
|
91
|
+
</TouchableOpacity>
|
|
92
|
+
<Text style={{
|
|
93
|
+
fontSize: cx(24),
|
|
94
|
+
minWidth: cx(200),
|
|
95
|
+
textAlign: 'center',
|
|
96
|
+
color: theme?.global.brand,
|
|
97
|
+
fontFamily: 'helvetica_neue_lt_std_roman',
|
|
98
|
+
}}>{state.headlineText}</Text>
|
|
99
|
+
<TouchableOpacity
|
|
100
|
+
disabled={state.disableArrowRight}
|
|
101
|
+
onPress={() => {
|
|
102
|
+
changeDate(true);
|
|
103
|
+
}}>
|
|
104
|
+
<Image
|
|
105
|
+
source={res.arrow_right}
|
|
106
|
+
style={{tintColor: state.disableArrowRight ? theme?.global.disabledFontColor : theme?.global.brand}}
|
|
107
|
+
height={cx(36)}
|
|
108
|
+
width={cx(36)}/>
|
|
109
|
+
</TouchableOpacity>
|
|
110
|
+
</View>)
|
|
111
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {useRef} from 'react';
|
|
1
|
+
import React, {useMemo, useRef} from 'react';
|
|
2
2
|
import {View} from 'react-native';
|
|
3
3
|
import ECharts from '@ledvance/react-native-echarts-pro';
|
|
4
4
|
import I18n from "@ledvance/base/src/i18n";
|
|
@@ -29,7 +29,20 @@ const BarChartWithTouch = (props: BarChartProps) => {
|
|
|
29
29
|
const dataPriceY = data?.map(item => {
|
|
30
30
|
return ((isNaN(Number(item.value)) ? 0 : Number(item.value)) * price).toFixed(2);
|
|
31
31
|
});
|
|
32
|
-
const maxValue =
|
|
32
|
+
const maxValue = useMemo(() => {
|
|
33
|
+
let max = Math.max(...dataKwhY)
|
|
34
|
+
if (max < 0.1) {
|
|
35
|
+
max += 0.02
|
|
36
|
+
max = max - (max % 0.02)
|
|
37
|
+
} else if (max < 1) {
|
|
38
|
+
max += 0.2
|
|
39
|
+
max = max - (max % 0.2)
|
|
40
|
+
} else if (max < 10) {
|
|
41
|
+
max = Math.ceil(max) + 2
|
|
42
|
+
max = max - (max % 2)
|
|
43
|
+
}
|
|
44
|
+
return max
|
|
45
|
+
}, [dataKwhY]);
|
|
33
46
|
const option = {
|
|
34
47
|
tooltip: {
|
|
35
48
|
show: true,
|
|
@@ -57,7 +70,7 @@ const BarChartWithTouch = (props: BarChartProps) => {
|
|
|
57
70
|
yAxis: [{
|
|
58
71
|
type: 'value',
|
|
59
72
|
name: I18n.getLang('consumption_data_annual_bar_chart_text'),
|
|
60
|
-
max: Math.
|
|
73
|
+
max: Math.max(maxValue, 0.02),
|
|
61
74
|
min: 0,
|
|
62
75
|
position: 'left',
|
|
63
76
|
axisLabel: {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import I18n from "@ledvance/base/src/i18n";
|
|
2
|
+
import { AdjustType, DiySceneInfo } from "@ledvance/base/src/utils/interface";
|
|
3
|
+
import { MoodInfo, MoodUIInfo } from "../mood_new/Interface";
|
|
4
|
+
|
|
1
5
|
export interface IAddSingleTime {
|
|
2
6
|
bizId: string;
|
|
3
7
|
bizType?: string;
|
|
@@ -15,8 +19,6 @@ export interface IQueryTimerTasks {
|
|
|
15
19
|
category?: string;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
22
|
export interface IModifySingleTimer {
|
|
21
23
|
bizId: string;
|
|
22
24
|
bizType?: string;
|
|
@@ -40,10 +42,6 @@ export enum UVCFanMode {
|
|
|
40
42
|
Normal = 'normal'
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
import I18n from "@ledvance/base/src/i18n";
|
|
45
|
-
import { MoodInfo, MoodUIInfo } from "../mood_new/Interface";
|
|
46
|
-
|
|
47
45
|
export interface Timer {
|
|
48
46
|
status: number;
|
|
49
47
|
loops: string;
|
|
@@ -84,6 +82,7 @@ interface judgmentSupport {
|
|
|
84
82
|
isMixLight?: boolean;
|
|
85
83
|
isFanLight?: boolean;
|
|
86
84
|
isUVCFan?: boolean;
|
|
85
|
+
isMoodStrip?: boolean;
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
export interface ManualSettingProps extends judgmentSupport {
|
|
@@ -100,7 +99,8 @@ export enum DeviceType {
|
|
|
100
99
|
MixLight = 'mixLight',
|
|
101
100
|
StripLight = 'stripLight',
|
|
102
101
|
CeilingLight = 'ceilingLight',
|
|
103
|
-
FanLight = 'fanLight'
|
|
102
|
+
FanLight = 'fanLight',
|
|
103
|
+
MoodStrip = 'moodStrip',
|
|
104
104
|
}
|
|
105
105
|
// export type DeviceType = 'LightSource' | 'CeilingLight' | 'StringLight' | 'StripLight' | 'MixLight';
|
|
106
106
|
|
|
@@ -135,12 +135,17 @@ export interface FanLightData extends DeviceData {
|
|
|
135
135
|
disinfect: boolean
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
export interface MoodStripData extends DeviceData {
|
|
139
|
+
adjustType: AdjustType
|
|
140
|
+
}
|
|
141
|
+
|
|
138
142
|
export type ComponentConfig =
|
|
139
143
|
| { type: DeviceType.LightSource; deviceData: DeviceData }
|
|
140
144
|
| { type: DeviceType.MixLight; deviceData: MixLightData }
|
|
141
145
|
| { type: DeviceType.StripLight; deviceData: StripLightData }
|
|
142
146
|
| { type: DeviceType.CeilingLight; deviceData: CeilingLightData }
|
|
143
147
|
| { type: DeviceType.FanLight; deviceData: FanLightData }
|
|
148
|
+
| { type: DeviceType.MoodStrip; deviceData: MoodStripData}
|
|
144
149
|
|
|
145
150
|
export interface TimeScheduleDetailState {
|
|
146
151
|
timeSchedule: Timer;
|
|
@@ -152,15 +157,19 @@ export interface TimeScheduleDetailState {
|
|
|
152
157
|
loading: boolean;
|
|
153
158
|
moodLoading: boolean;
|
|
154
159
|
manualData: ComponentConfig;
|
|
155
|
-
mood?: MoodInfo;
|
|
156
|
-
moods: MoodUIInfo[];
|
|
160
|
+
mood?: MoodInfo | DiySceneInfo;
|
|
161
|
+
moods: MoodUIInfo[] | DiySceneInfo[];
|
|
162
|
+
filterMoods: MoodUIInfo[] | DiySceneInfo[];
|
|
163
|
+
staticTagChecked: boolean;
|
|
164
|
+
dynamicTagChecked: boolean;
|
|
165
|
+
diyTagChecked: boolean;
|
|
157
166
|
timerId: any;
|
|
158
167
|
moodName: string;
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
export interface DeviceStateType {
|
|
162
171
|
deviceData: ComponentConfig
|
|
163
|
-
mood?: MoodInfo
|
|
172
|
+
mood?: MoodInfo | DiySceneInfo
|
|
164
173
|
isManual: boolean
|
|
165
174
|
}
|
|
166
175
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { commonApi } from "@tuya/tuya-panel-api"
|
|
2
|
-
import { IAddSingleTime, IQueryTimerTasks, IModifySingleTimer, IModDeleteTaskByIds, UVCFanMode } from "
|
|
2
|
+
import { IAddSingleTime, IQueryTimerTasks, IModifySingleTimer, IModDeleteTaskByIds, UVCFanMode } from "./Interface"
|
|
3
3
|
import { flatMapDeep } from "lodash";
|
|
4
4
|
import I18n from "@ledvance/base/src/i18n";
|
|
5
5
|
import { ColorList } from '@ledvance/base/src/components/StripAdjustView';
|
|
6
6
|
import { parseJSON } from "@tuya/tuya-panel-lamp-sdk/lib/utils";
|
|
7
|
+
import { AdjustType } from "@ledvance/base/src/utils/interface";
|
|
7
8
|
|
|
8
9
|
export const defDeviceData = {
|
|
9
10
|
h: 0,
|
|
@@ -40,6 +41,11 @@ export const defFanLightDeviceData = {
|
|
|
40
41
|
disinfect: false
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
export const defMoodStripDeviceData = {
|
|
45
|
+
...defDeviceData,
|
|
46
|
+
adjustType: AdjustType.COLOUR
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
export const addTimeSchedule = async (props: IAddSingleTime) => {
|
|
44
50
|
try {
|
|
45
51
|
const res = await commonApi.timerApi.addSingleTimer({
|