@ledvance/group-ui-biz-bundle 1.0.91 → 1.0.93
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/biorhythm/BiorhythmBean.ts +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/fixedTimeForPlug/FixedTimeForPlugPage.tsx +14 -0
- package/src/modules/fixedTimeForPlug/ItemCard.tsx +3 -2
- package/src/modules/fixedTimingForLight/FixedTimingForLightPage.tsx +14 -0
- package/src/modules/fixedTimingForLight/ItemCard.tsx +3 -2
- package/src/modules/flags/FlagActions.ts +3 -1
- package/src/modules/flags/FlagPage.tsx +4 -3
- package/src/modules/mood_new/Interface.ts +1 -0
- package/src/modules/mood_new/MoodActions.ts +12 -1
- package/src/modules/mood_new/MoodItem.tsx +2 -1
- package/src/modules/mood_new/MoodPage.tsx +34 -12
- package/src/modules/randomTimeForPlug/ItemCard.tsx +3 -2
- package/src/modules/randomTimeForPlug/RandomTimeForPlugPage.tsx +14 -0
- package/src/modules/randomTimingForLight/RandomTimingForLightPage.tsx +14 -0
- package/src/modules/sleepWakeUp/SleepWakeUpPage.tsx +34 -5
- 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/modules/timeSchedule/components/ScheduleCard.tsx +5 -6
- package/src/modules/timer/TimerAction.ts +1 -1
- 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: {
|
|
@@ -14,6 +14,7 @@ import {Utils} from "tuya-panel-kit";
|
|
|
14
14
|
import ItemCard from "./ItemCard";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
17
|
+
import { showDialog } from "@ledvance/base/src/utils/common";
|
|
17
18
|
|
|
18
19
|
const {convertX: cx, topBarHeight} = Utils.RatioUtils;
|
|
19
20
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -114,6 +115,19 @@ const FixedTimeForPlugPage = (props: { theme?: ThemeType}) => {
|
|
|
114
115
|
onPress={() => {
|
|
115
116
|
onAddOrEditItem('edit', item)
|
|
116
117
|
}}
|
|
118
|
+
onLongPress={async () =>{
|
|
119
|
+
showDialog({
|
|
120
|
+
method: 'confirm',
|
|
121
|
+
title: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_titel'),
|
|
122
|
+
subTitle: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_description'),
|
|
123
|
+
onConfirm: async (_, {close}) => {
|
|
124
|
+
close()
|
|
125
|
+
state.loading = true
|
|
126
|
+
await onPost('del', item)
|
|
127
|
+
state.loading = false
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
}}
|
|
117
131
|
/>
|
|
118
132
|
)}
|
|
119
133
|
keyExtractor={(item: any) => `${item?.index}`}
|
|
@@ -18,10 +18,11 @@ export interface ItemCardProps {
|
|
|
18
18
|
is24Hour?: boolean,
|
|
19
19
|
onSwitch: (enable: boolean) => void
|
|
20
20
|
onPress: () => void
|
|
21
|
+
onLongPress: () => void
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const ItemCard = (props: ItemCardProps) => {
|
|
24
|
-
const {item, is24Hour, onSwitch, onPress} = props
|
|
25
|
+
const {item, is24Hour, onSwitch, onPress, onLongPress} = props
|
|
25
26
|
// 判断是否关闭
|
|
26
27
|
const closed = getIsClosed(item)
|
|
27
28
|
|
|
@@ -50,7 +51,7 @@ const ItemCard = (props: ItemCardProps) => {
|
|
|
50
51
|
})
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
|
-
<Card style={styles.itemCard} onPress={onPress}>
|
|
54
|
+
<Card style={styles.itemCard} onPress={onPress} onLongPress={onLongPress}>
|
|
54
55
|
<Spacer height={cx(16)}/>
|
|
55
56
|
<View style={styles.switchLine}>
|
|
56
57
|
<Text style={styles.time}>
|
|
@@ -14,6 +14,7 @@ import ItemCard from "./ItemCard";
|
|
|
14
14
|
import {cloneDeep} from "lodash";
|
|
15
15
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
16
16
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
17
|
+
import { showDialog } from "@ledvance/base/src/utils/common";
|
|
17
18
|
|
|
18
19
|
const {convertX: cx, topBarHeight} = Utils.RatioUtils;
|
|
19
20
|
const { withTheme } = Utils.ThemeUtils
|
|
@@ -119,6 +120,19 @@ const FixedTimeForLightPage = (props: { theme?: ThemeType}) => {
|
|
|
119
120
|
onPress={() => {
|
|
120
121
|
onAddOrEditItem('edit', item)
|
|
121
122
|
}}
|
|
123
|
+
onLongPress={async () =>{
|
|
124
|
+
showDialog({
|
|
125
|
+
method: 'confirm',
|
|
126
|
+
title: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_titel'),
|
|
127
|
+
subTitle: I18n.getLang('cancel_dialog_delete_item_fixedtimecycle_description'),
|
|
128
|
+
onConfirm: async (_, {close}) => {
|
|
129
|
+
close()
|
|
130
|
+
state.loading = true
|
|
131
|
+
await onPost('del', item)
|
|
132
|
+
state.loading = false
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
}}
|
|
122
136
|
/>
|
|
123
137
|
)}
|
|
124
138
|
keyExtractor={(item: any) => `${item?.index}`}
|
|
@@ -18,10 +18,11 @@ export interface ItemCardProps {
|
|
|
18
18
|
is24Hour?: boolean,
|
|
19
19
|
onSwitch: (enable: boolean) => void
|
|
20
20
|
onPress: () => void
|
|
21
|
+
onLongPress: () => void
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const ItemCard = (props: ItemCardProps) => {
|
|
24
|
-
const {item, is24Hour, onSwitch, onPress} = props
|
|
25
|
+
const {item, is24Hour, onSwitch, onPress, onLongPress} = props
|
|
25
26
|
// 判断是否关闭
|
|
26
27
|
const closed = getIsClosed(item)
|
|
27
28
|
|
|
@@ -50,7 +51,7 @@ const ItemCard = (props: ItemCardProps) => {
|
|
|
50
51
|
})
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
|
-
<Card style={styles.itemCard} onPress={onPress}>
|
|
54
|
+
<Card style={styles.itemCard} onPress={onPress} onLongPress={onLongPress}>
|
|
54
55
|
<Spacer height={cx(16)}/>
|
|
55
56
|
<View style={styles.switchLine}>
|
|
56
57
|
<Text style={styles.time}>
|
|
@@ -71,7 +71,9 @@ export const useFlag: UseFlagType = (params) => {
|
|
|
71
71
|
const dps = {}
|
|
72
72
|
const { flag } = flagData
|
|
73
73
|
if (!(params.isStripLight || params.isCeilingLight)){
|
|
74
|
-
const
|
|
74
|
+
const cloneFlag = cloneDeep(flag)
|
|
75
|
+
cloneFlag.colors = cloneFlag.colors.reverse()
|
|
76
|
+
const moodDp = obj2Dp(cloneFlag, params)
|
|
75
77
|
if (params.isStringLight){
|
|
76
78
|
dps[getGlobalParamsDp('rgbic_linerlight_scene')] = moodDp
|
|
77
79
|
}else{
|
|
@@ -49,6 +49,7 @@ const FlagPage = (props: { theme?: ThemeType }) => {
|
|
|
49
49
|
const state = useReactive({
|
|
50
50
|
loading: false,
|
|
51
51
|
flags: cloneDeep(flags) as FlagUiInfo[],
|
|
52
|
+
filterFlags: cloneDeep(flags) as FlagUiInfo[],
|
|
52
53
|
searchText: ''
|
|
53
54
|
})
|
|
54
55
|
|
|
@@ -57,8 +58,8 @@ const FlagPage = (props: { theme?: ThemeType }) => {
|
|
|
57
58
|
}, [])
|
|
58
59
|
|
|
59
60
|
useUpdateEffect(() => {
|
|
60
|
-
state.
|
|
61
|
-
}, [state.searchText, flags])
|
|
61
|
+
state.filterFlags = state.searchText !== '' ? cloneDeep(state.flags).filter(flag => (flag.name ?? '').toLowerCase().includes(state.searchText.toLowerCase())) : cloneDeep(state.flags)
|
|
62
|
+
}, [state.searchText, state.flags])
|
|
62
63
|
|
|
63
64
|
const getRemoteFlagInfo = async (isRefresh?: boolean) => {
|
|
64
65
|
const defNum = uaGroupInfo.groupDevices.filter(device => !(def2Pids.includes(device.tyPid) || def3Pids.includes(device.tyPid))).length
|
|
@@ -177,7 +178,7 @@ const FlagPage = (props: { theme?: ThemeType }) => {
|
|
|
177
178
|
</TouchableOpacity>
|
|
178
179
|
</View>
|
|
179
180
|
<FlatList
|
|
180
|
-
data={state.
|
|
181
|
+
data={state.filterFlags}
|
|
181
182
|
renderItem={({ item }) => <FlagItem
|
|
182
183
|
enable={flagMode?.flagId === item.id && flagMode?.flagMode && switch_led}
|
|
183
184
|
title={item.name}
|