@ledvance/ui-biz-bundle 1.1.98 → 1.1.99
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/newModules/energyConsumption/EnergyConsumptionActions.ts +108 -3
- package/src/newModules/energyConsumption/EnergyConsumptionChart.tsx +151 -44
- package/src/newModules/energyConsumption/EnergyConsumptionDetail.tsx +29 -21
- package/src/newModules/energyConsumption/EnergyConsumptionPage.tsx +167 -161
- package/src/newModules/energyConsumption/co2Data.ts +6 -0
- package/src/newModules/energyConsumption/component/DateSelectedItem.tsx +168 -0
- package/src/newModules/energyConsumption/component/DateTypeItem.tsx +89 -0
- package/src/newModules/energyConsumption/component/NewBarChart.tsx +141 -0
package/package.json
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {useDp} from "@ledvance/base/src/models/modules/NativePropsSlice";
|
|
2
|
+
import {localeNumber, loopsText, monthFormat, monthFormatShort} from "@ledvance/base/src/utils/common";
|
|
3
3
|
import {EnergyData} from "./component/EnergyModal";
|
|
4
4
|
import {NativeApi} from "@ledvance/base/src/api/native";
|
|
5
|
+
import {getDataWithSpecified, getDpResultByHour, getDpResultByMonth} from "@ledvance/base/src/models/TuyaApi";
|
|
6
|
+
import {DateType} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
|
|
7
|
+
import {OverviewItem} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/EnergyConsumptionPage";
|
|
8
|
+
import {overDays} from "@ledvance/base/src/utils/index";
|
|
9
|
+
import dayjs from "dayjs";
|
|
10
|
+
import {isEmpty} from "lodash";
|
|
5
11
|
|
|
6
12
|
export function useElectricCurrent(dpCode: string): number {
|
|
7
13
|
const current = useDp<number, any>(dpCode)[0] || 0
|
|
@@ -18,6 +24,105 @@ export function usePower(dpCode: string): number {
|
|
|
18
24
|
return localeNumber(power, 1)
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
export async function updatePrice(devId: string, energyData: EnergyData){
|
|
27
|
+
export async function updatePrice(devId: string, energyData: EnergyData) {
|
|
22
28
|
return await NativeApi.putJson(devId, 'energiepreise', JSON.stringify(energyData))
|
|
23
29
|
}
|
|
30
|
+
|
|
31
|
+
export async function getElectricity(devId: string, addEleDpCode: string, date: string, dateType: DateType): Promise<OverviewItem[]> {
|
|
32
|
+
let res: OverviewItem[] = []
|
|
33
|
+
switch (dateType) {
|
|
34
|
+
case DateType.Year:
|
|
35
|
+
res = await getDpResultByYear(devId, addEleDpCode, date)
|
|
36
|
+
break
|
|
37
|
+
case DateType.Month:
|
|
38
|
+
res = await getDpResultByYearMonth(devId, addEleDpCode, date)
|
|
39
|
+
break
|
|
40
|
+
case DateType.Day:
|
|
41
|
+
res = await getDpResultByDate(devId, addEleDpCode, date);
|
|
42
|
+
break
|
|
43
|
+
}
|
|
44
|
+
return res
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const getDpResultByYear = async (devId: string, addEleDpCode: string, dateStr: string): Promise<OverviewItem[]> => {
|
|
48
|
+
const res = await getDpResultByMonth(devId, addEleDpCode, 'sum')
|
|
49
|
+
if (!isEmpty(res)) {
|
|
50
|
+
if (!isEmpty(res.years)) {
|
|
51
|
+
const year = dateStr;
|
|
52
|
+
const curMonth = res.years[year]
|
|
53
|
+
if (!curMonth){
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const curMonthList = Object.keys(curMonth).sort((a, b) => parseInt(b) - parseInt(a));
|
|
57
|
+
return curMonthList.map(month => {
|
|
58
|
+
return {
|
|
59
|
+
key: `${monthFormat(month)} ${year}`,
|
|
60
|
+
value: (Number(curMonth[month]) || 0).toFixed(2),
|
|
61
|
+
headlineText: `${year}${month}`,
|
|
62
|
+
chartTitle: `${monthFormatShort(month)}\n${year}`
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return []
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
const getDpResultByYearMonth = async (devId: string, addEleDpCode: string, dateStr: string): Promise<OverviewItem[]> => {
|
|
72
|
+
const date = dayjs(dateStr)
|
|
73
|
+
const startDay = date.startOf('month').format('YYYYMMDD')
|
|
74
|
+
const endDay = date.endOf('month').format('YYYYMMDD')
|
|
75
|
+
if (overDays(startDay, 365)) {
|
|
76
|
+
console.log("getDpResultByYearMonth overDays true")
|
|
77
|
+
return []
|
|
78
|
+
}
|
|
79
|
+
const res = await getDataWithSpecified(devId, addEleDpCode, startDay, endDay, 'sum')
|
|
80
|
+
if (!isEmpty(res) && res.result) {
|
|
81
|
+
const dayList = res.result
|
|
82
|
+
return Object.keys(dayList).filter(v => Number(dayList[v]) > 0).map(time => {
|
|
83
|
+
// 提取年、月和日
|
|
84
|
+
const year = time.slice(0, 4);
|
|
85
|
+
const month = time.slice(4, 6);
|
|
86
|
+
const day = time.slice(6, 8);
|
|
87
|
+
|
|
88
|
+
// 格式化为 'YYYY/MM/DD' 格式
|
|
89
|
+
const formattedDate = `${year}/${month}/${day}`
|
|
90
|
+
const dateStr = `${day}/${month}/${year}`
|
|
91
|
+
const dateObj = dayjs(formattedDate, "YYYY/MM/DD");
|
|
92
|
+
const dayOfWeek = dateObj.day() % 7;
|
|
93
|
+
const key = `${dateStr} (${loopsText[dayOfWeek]})`
|
|
94
|
+
return {
|
|
95
|
+
key,
|
|
96
|
+
value: Number(dayList[time] || 0).toFixed(2),
|
|
97
|
+
headlineText: formattedDate,
|
|
98
|
+
chartTitle: `${Number(key?.split('/')[0])}\n${loopsText[dayOfWeek]}`
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
return []
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
const getDpResultByDate = async (devId: string, addEleDpCode: string, date: string): Promise<OverviewItem[]> => {
|
|
107
|
+
if (overDays(date, 7)) {
|
|
108
|
+
console.log("getDpResultByDate overDays true")
|
|
109
|
+
return []
|
|
110
|
+
}
|
|
111
|
+
const res = await getDpResultByHour(devId, addEleDpCode, date, 'sum')
|
|
112
|
+
const list: Array<OverviewItem> = []
|
|
113
|
+
const resData = Object.keys(res)?.map(val => {
|
|
114
|
+
return {key: Number(val?.slice(8, 10)), value: Number(res[val])}
|
|
115
|
+
})
|
|
116
|
+
for (let i = 0; i <= 23; i++) {
|
|
117
|
+
const hourData = resData?.find(val => val?.key === i)
|
|
118
|
+
const hourKey = hourData?.key || i
|
|
119
|
+
const hourValue = Number(hourData?.value) || 0
|
|
120
|
+
list.push({
|
|
121
|
+
key: `${hourKey.toString().padStart(2, '0')}:00`,
|
|
122
|
+
value: hourValue,
|
|
123
|
+
chartTitle: `${hourKey}:00`,
|
|
124
|
+
headlineText: `${hourKey}:00`
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
return list
|
|
128
|
+
}
|
|
@@ -1,32 +1,44 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Platform,
|
|
3
|
-
import {
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import {Image, Platform, StyleSheet, View} from "react-native";
|
|
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";
|
|
6
6
|
import I18n from "@ledvance/base/src/i18n";
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import {Utils} from "tuya-panel-kit";
|
|
8
|
+
import NewBarChart from "./component/NewBarChart";
|
|
9
|
+
import {exportFile, loopsText, monthFormat} from "@ledvance/base/src/utils/common";
|
|
10
|
+
import {OverviewItem} from "./EnergyConsumptionPage";
|
|
11
11
|
import Spacer from "@ledvance/base/src/components/Spacer";
|
|
12
12
|
import InfoText from "@ledvance/base/src/components/InfoText";
|
|
13
|
+
import dayjs from "dayjs";
|
|
13
14
|
import ThemeType from '@ledvance/base/src/config/themeType'
|
|
15
|
+
import {overDays} from "@ledvance/base/src/utils/index";
|
|
16
|
+
import DateTypeItem from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/component/DateTypeItem";
|
|
17
|
+
import {DateType} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
|
|
18
|
+
import DateSelectedItem from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/component/DateSelectedItem";
|
|
19
|
+
import {useReactive, useUpdateEffect} from "ahooks";
|
|
20
|
+
import {getElectricity} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/EnergyConsumptionActions";
|
|
21
|
+
import {useDeviceId} from "@ledvance/base/src/models/modules/NativePropsSlice";
|
|
14
22
|
|
|
15
|
-
const {
|
|
16
|
-
const {
|
|
23
|
+
const {convertX: cx} = Utils.RatioUtils
|
|
24
|
+
const {withTheme} = Utils.ThemeUtils
|
|
17
25
|
|
|
18
26
|
export interface EnergyConsumptionChartProps {
|
|
19
27
|
addEleDpCode: string
|
|
20
28
|
headlineText: string
|
|
21
29
|
chartData: OverviewItem[],
|
|
22
30
|
over365Days?: boolean
|
|
23
|
-
over7Days?: boolean
|
|
31
|
+
over7Days?: boolean,
|
|
32
|
+
price: string,
|
|
33
|
+
unit: string,
|
|
34
|
+
date: string,
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
27
|
-
const
|
|
28
|
-
const computeNum = Platform.OS === 'ios' && 180 || 130
|
|
38
|
+
const devId = useDeviceId()
|
|
29
39
|
|
|
40
|
+
const params = useRoute().params as EnergyConsumptionChartProps
|
|
41
|
+
const {price, unit, date, addEleDpCode, over365Days, over7Days} = params;
|
|
30
42
|
const styles = StyleSheet.create({
|
|
31
43
|
listEmptyView: {
|
|
32
44
|
alignItems: 'center',
|
|
@@ -35,40 +47,135 @@ const EnergyConsumptionChart = (props: { theme?: ThemeType }) => {
|
|
|
35
47
|
width: cx(200),
|
|
36
48
|
height: cx(200),
|
|
37
49
|
},
|
|
38
|
-
|
|
50
|
+
listEmptyText: {
|
|
51
|
+
flex: 0
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const getDateType = useCallback((date: string) => {
|
|
56
|
+
const datejs = dayjs(date);
|
|
57
|
+
if (datejs.isValid()) {
|
|
58
|
+
if (datejs.format('YYYY') === date) {
|
|
59
|
+
return DateType.Year;
|
|
60
|
+
} else if (datejs.format('YYYYMM') === date) {
|
|
61
|
+
return DateType.Month;
|
|
62
|
+
} else if (datejs.format('YYYY/MM/DD') === date) {
|
|
63
|
+
return DateType.Day;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return DateType.Day;
|
|
67
|
+
}, [])
|
|
68
|
+
const dateType = getDateType(date);
|
|
69
|
+
const state = useReactive({
|
|
70
|
+
loading: false,
|
|
71
|
+
dateType: dateType,
|
|
72
|
+
date: date,
|
|
73
|
+
headlineText: dateType === DateType.Year ? date : params.headlineText,
|
|
74
|
+
chartData: params.chartData.filter((item) => {
|
|
75
|
+
return dateType !== DateType.Year || item.headlineText.startsWith(date)
|
|
76
|
+
}),
|
|
77
|
+
price: isNaN(Number(price)) ? 0 : Number(price),
|
|
78
|
+
over365Days: over365Days,
|
|
79
|
+
over7Days: over7Days,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
useUpdateEffect(() => {
|
|
83
|
+
state.over365Days = overDays(state.date, 365);
|
|
84
|
+
state.over7Days = overDays(state.date, 7);
|
|
85
|
+
state.loading = true;
|
|
86
|
+
getElectricity(devId, addEleDpCode, state.date, state.dateType).then((res) => {
|
|
87
|
+
state.chartData = res;
|
|
88
|
+
state.loading = false;
|
|
89
|
+
})
|
|
90
|
+
}, [state.date]);
|
|
91
|
+
|
|
92
|
+
const getEmptyDataTip = useCallback(() => {
|
|
93
|
+
if (state.over365Days) {
|
|
94
|
+
return I18n.getLang('energyconsumption_Daylimit')
|
|
95
|
+
}
|
|
96
|
+
if (state.dateType === DateType.Day && state.over7Days) {
|
|
97
|
+
return I18n.getLang('energyconsumption_hourlylimit')
|
|
98
|
+
}
|
|
99
|
+
return I18n.getLang('energyconsumption_emptydata')
|
|
100
|
+
}, [state.dateType, state.over365Days, state.over7Days]);
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
useUpdateEffect(() => {
|
|
104
|
+
const date = dayjs();
|
|
105
|
+
const year = date.year().toString();
|
|
106
|
+
const month = (date.month() + 1).toString().padStart(2, '0');
|
|
107
|
+
const day = date.date().toString().padStart(2, '0');
|
|
108
|
+
const dayOfWeek = date.day() % 7;
|
|
109
|
+
switch (state.dateType) {
|
|
110
|
+
case DateType.Year:
|
|
111
|
+
state.date = year;
|
|
112
|
+
state.headlineText = year;
|
|
113
|
+
break
|
|
114
|
+
case DateType.Month:
|
|
115
|
+
state.date = `${year}${month}`
|
|
116
|
+
state.headlineText = `${monthFormat(month)} ${year}`;
|
|
117
|
+
break
|
|
118
|
+
case DateType.Day:
|
|
119
|
+
state.date = `${year}${month}${day}`
|
|
120
|
+
state.headlineText = `${day}/${month}/${year}\n${loopsText[dayOfWeek]}`;
|
|
121
|
+
break
|
|
122
|
+
}
|
|
123
|
+
}, [state.dateType]);
|
|
39
124
|
|
|
40
125
|
return (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
126
|
+
<Page
|
|
127
|
+
backText={I18n.getLang('consumption_data_annual_bar_chart_system_back_text')}
|
|
128
|
+
headlineText={state.headlineText}
|
|
129
|
+
headlineIcon={state.chartData?.length ? res.download_icon : undefined}
|
|
130
|
+
onHeadlineIconClick={() => {
|
|
131
|
+
exportFile(state.chartData,params.price,params.unit)
|
|
132
|
+
}}
|
|
133
|
+
showGreenery={false}
|
|
134
|
+
loading={state.loading}
|
|
135
|
+
greeneryIcon={res.energy_consumption_greenery}
|
|
136
|
+
>
|
|
137
|
+
<View style={{marginHorizontal: cx(24)}}>
|
|
138
|
+
|
|
139
|
+
<View style={{flexDirection: 'row'}}>
|
|
140
|
+
<DateTypeItem
|
|
141
|
+
style={{flex: 1}}
|
|
142
|
+
dateType={state.dateType}
|
|
143
|
+
onDateTypeChange={(dateType) => {
|
|
144
|
+
state.dateType = dateType;
|
|
145
|
+
}}/>
|
|
146
|
+
<DateSelectedItem
|
|
147
|
+
style={{flex: 1, marginStart: cx(10),marginBottom:cx(15)}}
|
|
148
|
+
dateType={state.dateType}
|
|
149
|
+
date={state.date}
|
|
150
|
+
onDateChange={date => {
|
|
151
|
+
state.date = date;
|
|
152
|
+
}}
|
|
153
|
+
/>
|
|
154
|
+
|
|
155
|
+
</View>
|
|
156
|
+
{
|
|
157
|
+
(state.chartData.length <= 0) ? (
|
|
158
|
+
<View style={styles.listEmptyView}>
|
|
159
|
+
<Spacer height={cx(26)}/>
|
|
160
|
+
<Image
|
|
161
|
+
style={styles.listEmptyImage}
|
|
162
|
+
source={{uri: res.ldv_timer_empty}}/>
|
|
163
|
+
<Spacer height={cx(14)}/>
|
|
164
|
+
<InfoText
|
|
165
|
+
text={getEmptyDataTip()}
|
|
166
|
+
icon={res.ic_info}
|
|
167
|
+
textStyle={styles.listEmptyText}
|
|
168
|
+
contentColor={props.theme?.global.fontColor}
|
|
169
|
+
/>
|
|
170
|
+
</View>
|
|
171
|
+
) : (
|
|
172
|
+
state.chartData.length > 0 && !state.loading &&
|
|
173
|
+
<NewBarChart height={400} data={state.chartData} price={state.price}
|
|
174
|
+
unit={unit}/>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
</View>
|
|
178
|
+
</Page>
|
|
72
179
|
)
|
|
73
180
|
}
|
|
74
181
|
|
|
@@ -191,7 +191,7 @@ const EnergyConsumptionDetail = (props: {theme?: ThemeType}) => {
|
|
|
191
191
|
headlineText={params.curMonth.key}
|
|
192
192
|
headlineIcon={state.overviewList.length ? res.download_icon : undefined}
|
|
193
193
|
onHeadlineIconClick={() => {
|
|
194
|
-
exportFile(state.overviewList)
|
|
194
|
+
exportFile(state.overviewList, params.price, params.unit);
|
|
195
195
|
}}
|
|
196
196
|
showGreenery={false}
|
|
197
197
|
greeneryIcon={res.energy_consumption_greenery}
|
|
@@ -270,26 +270,34 @@ const EnergyConsumptionDetail = (props: {theme?: ThemeType}) => {
|
|
|
270
270
|
<Spacer height={cx(30)} />
|
|
271
271
|
{/* Annual overview */}
|
|
272
272
|
<OverView
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
273
|
+
style={{ marginHorizontal: cx(24) }}
|
|
274
|
+
headlineText={I18n.getLang('consumption_data_monthly_overview_field2_headline_text')}
|
|
275
|
+
headlineClick={() => {
|
|
276
|
+
navigation.navigate(ui_biz_routerKey.ui_biz_energy_consumption_chart, {
|
|
277
|
+
headlineText: params.curMonth.key,
|
|
278
|
+
chartData: state.overviewList,
|
|
279
|
+
over365Days: state.over365Days,
|
|
280
|
+
price:state.price,
|
|
281
|
+
unit:state.unit,
|
|
282
|
+
addEleDpCode:params.addEleDpCode,
|
|
283
|
+
date:params.curMonth.headlineText,
|
|
284
|
+
} as EnergyConsumptionChartProps)
|
|
285
|
+
}}
|
|
286
|
+
overviewItemClick={async (item) =>{
|
|
287
|
+
state.loading = true
|
|
288
|
+
const res = await getHourList(item)
|
|
289
|
+
state.loading = false
|
|
290
|
+
navigation.navigate(ui_biz_routerKey.ui_biz_energy_consumption_chart, {
|
|
291
|
+
headlineText: item.key,
|
|
292
|
+
chartData: res,
|
|
293
|
+
over7Days: state.over7Days,
|
|
294
|
+
price:state.price,
|
|
295
|
+
unit:state.unit,
|
|
296
|
+
addEleDpCode:params.addEleDpCode,
|
|
297
|
+
date:item.headlineText,
|
|
298
|
+
} as EnergyConsumptionChartProps)
|
|
299
|
+
}}
|
|
300
|
+
overViewList={state.overviewList}
|
|
293
301
|
/>
|
|
294
302
|
{/* modal */}
|
|
295
303
|
<EnergyPopup
|
|
@@ -120,6 +120,8 @@ const EnergyConsumptionPage = (props: {theme?: ThemeType}) => {
|
|
|
120
120
|
const v = JSON.parse(res.data)
|
|
121
121
|
state.price = v?.price
|
|
122
122
|
state.unit = v?.unit
|
|
123
|
+
} else {
|
|
124
|
+
state.price = '0'
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
|
|
@@ -209,185 +211,189 @@ const EnergyConsumptionPage = (props: {theme?: ThemeType}) => {
|
|
|
209
211
|
|
|
210
212
|
const ConsumedEnergyItem = (props: { value: number, unit: string }) => {
|
|
211
213
|
return (
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
214
|
+
<View style={styles.subContent}>
|
|
215
|
+
<Text style={styles.valueText}>{(props.value) || 0}</Text>
|
|
216
|
+
<Spacer height={cx(4)} />
|
|
217
|
+
<Text style={styles.titleText}>
|
|
218
|
+
{unitDivision(props.unit)[0]}
|
|
219
|
+
</Text>
|
|
220
|
+
<Text style={styles.titleText}>
|
|
221
|
+
{unitDivision(props.unit)[1]}
|
|
222
|
+
</Text>
|
|
223
|
+
</View>
|
|
222
224
|
)
|
|
223
225
|
}
|
|
224
226
|
|
|
225
227
|
return (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
<Spacer height={cx(15)} />
|
|
241
|
-
<View style={styles.showTip}>
|
|
242
|
-
<Text style={{ fontSize: cx(14) }}>{I18n.getLang(isSolarPlug ? 'generation_data_description_text' : 'consumption_data_description_text')}</Text>
|
|
243
|
-
</View>
|
|
244
|
-
<Spacer />
|
|
245
|
-
{/* Today */}
|
|
246
|
-
<Card
|
|
247
|
-
style={styles.cardContainer}
|
|
248
|
-
>
|
|
249
|
-
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field1_headline_text')}</Text>
|
|
250
|
-
<Spacer height={cx(15)} />
|
|
251
|
-
<View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
|
|
252
|
-
<Text style={[styles.consumptionNum, { fontSize: cx(38), marginRight: cx(8) }]}>{localeNumber(state.todayElectricity)}</Text>
|
|
253
|
-
<Text style={[styles.consumptionNum, { fontSize: cx(22), marginBottom: cx(4) }]}>kWh</Text>
|
|
254
|
-
</View>
|
|
255
|
-
<Spacer height={cx(10)} />
|
|
256
|
-
</Card>
|
|
257
|
-
<Spacer />
|
|
258
|
-
<Card
|
|
259
|
-
style={styles.cardContainer}
|
|
260
|
-
>
|
|
261
|
-
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field2_headline_text')}</Text>
|
|
262
|
-
<Spacer height={cx(15)} />
|
|
263
|
-
<View style={styles.consumedEnergyContent}>
|
|
264
|
-
<ConsumedEnergyItem
|
|
265
|
-
value={power}
|
|
266
|
-
unit={I18n.getLang('consumption_data_field2_value_text1')} />
|
|
267
|
-
<ConsumedEnergyItem
|
|
268
|
-
value={electric}
|
|
269
|
-
unit={I18n.getLang('consumption_data_field2_value_text2')} />
|
|
270
|
-
<ConsumedEnergyItem
|
|
271
|
-
value={voltage}
|
|
272
|
-
unit={I18n.getLang('consumption_data_field2_value_text3')} />
|
|
273
|
-
</View>
|
|
274
|
-
</Card>
|
|
275
|
-
<Spacer />
|
|
276
|
-
{/* 365 day */}
|
|
277
|
-
<Card
|
|
278
|
-
style={styles.cardContainer}
|
|
279
|
-
>
|
|
280
|
-
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field3_headline_text')}</Text>
|
|
228
|
+
<Page
|
|
229
|
+
style={{ position: 'relative' }}
|
|
230
|
+
backText={I18n.getLang(isSolarPlug ? 'sockets_headline_power' : 'consumption_data_annual_bar_chart_system_back_text')}
|
|
231
|
+
headlineText={I18n.getLang(isSolarPlug ? 'sockets_headline_power' : 'consumption_data_annual_bar_chart_system_back_text')}
|
|
232
|
+
headlineIcon={state.overviewList.length ? res.download_icon : undefined}
|
|
233
|
+
onHeadlineIconClick={() => {
|
|
234
|
+
exportFile(state.overviewList, state.price, state.unit);
|
|
235
|
+
}}
|
|
236
|
+
showGreenery={isSolarPlug}
|
|
237
|
+
greeneryIcon={res.energy_consumption_greenery}
|
|
238
|
+
>
|
|
239
|
+
<ScrollView nestedScrollEnabled={true}>
|
|
240
|
+
<View>
|
|
241
|
+
{/* tip */}
|
|
281
242
|
<Spacer height={cx(15)} />
|
|
282
|
-
<View style={
|
|
283
|
-
<Text style={
|
|
284
|
-
<Text style={[styles.consumptionNum, { fontSize: cx(22), marginBottom: cx(4) }]}>kWh</Text>
|
|
243
|
+
<View style={styles.showTip}>
|
|
244
|
+
<Text style={{ fontSize: cx(14) }}>{I18n.getLang(isSolarPlug ? 'generation_data_description_text' : 'consumption_data_description_text')}</Text>
|
|
285
245
|
</View>
|
|
286
246
|
<Spacer />
|
|
287
|
-
{/*
|
|
288
|
-
|
|
247
|
+
{/* Today */}
|
|
248
|
+
<Card
|
|
249
|
+
style={styles.cardContainer}
|
|
250
|
+
>
|
|
251
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field1_headline_text')}</Text>
|
|
252
|
+
<Spacer height={cx(15)} />
|
|
253
|
+
<View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
|
|
254
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(38), marginRight: cx(8) }]}>{localeNumber(state.todayElectricity)}</Text>
|
|
255
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(22), marginBottom: cx(4) }]}>kWh</Text>
|
|
256
|
+
</View>
|
|
257
|
+
<Spacer height={cx(10)} />
|
|
258
|
+
</Card>
|
|
259
|
+
<Spacer />
|
|
260
|
+
<Card
|
|
261
|
+
style={styles.cardContainer}
|
|
262
|
+
>
|
|
263
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field2_headline_text')}</Text>
|
|
264
|
+
<Spacer height={cx(15)} />
|
|
265
|
+
<View style={styles.consumedEnergyContent}>
|
|
266
|
+
<ConsumedEnergyItem
|
|
267
|
+
value={power}
|
|
268
|
+
unit={I18n.getLang('consumption_data_field2_value_text1')} />
|
|
269
|
+
<ConsumedEnergyItem
|
|
270
|
+
value={electric}
|
|
271
|
+
unit={I18n.getLang('consumption_data_field2_value_text2')} />
|
|
272
|
+
<ConsumedEnergyItem
|
|
273
|
+
value={voltage}
|
|
274
|
+
unit={I18n.getLang('consumption_data_field2_value_text3')} />
|
|
275
|
+
</View>
|
|
276
|
+
</Card>
|
|
277
|
+
<Spacer />
|
|
278
|
+
{/* 365 day */}
|
|
279
|
+
<Card
|
|
280
|
+
style={styles.cardContainer}
|
|
281
|
+
>
|
|
282
|
+
<Text style={styles.cardTitle}>{I18n.getLang('consumption_data_field3_headline_text')}</Text>
|
|
283
|
+
<Spacer height={cx(15)} />
|
|
284
|
+
<View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
|
|
285
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(38), marginRight: cx(8) }]}>{localeNumber(state.totalElectricity)}</Text>
|
|
286
|
+
<Text style={[styles.consumptionNum, { fontSize: cx(22), marginBottom: cx(4) }]}>kWh</Text>
|
|
287
|
+
</View>
|
|
288
|
+
<Spacer />
|
|
289
|
+
{/* CO2 */}
|
|
290
|
+
{isSolarPlug && <>
|
|
289
291
|
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
290
|
-
|
|
292
|
+
<View style={styles.priceBg}>
|
|
293
|
+
<Image
|
|
294
|
+
source={res.energy_consumption_cash}
|
|
295
|
+
resizeMode="contain"
|
|
296
|
+
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
|
|
297
|
+
/>
|
|
298
|
+
</View>
|
|
299
|
+
<View style={styles.priceNum}>
|
|
300
|
+
<View style={{ flexDirection: 'row' }}>
|
|
301
|
+
<Text style={{ color: props.theme?.global.secondFontColor, marginRight: cx(5) }}>{I18n.getLang('consumption_data_field3_co2_topic_text')}</Text>
|
|
302
|
+
<TouchableOpacity
|
|
303
|
+
onPress={() => {
|
|
304
|
+
state.showPopup = true
|
|
305
|
+
state.popupType = 'co2'
|
|
306
|
+
}}
|
|
307
|
+
>
|
|
291
308
|
<Image
|
|
292
|
-
source={res.
|
|
309
|
+
source={res.co2Icon}
|
|
293
310
|
resizeMode="contain"
|
|
294
311
|
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
|
|
295
312
|
/>
|
|
313
|
+
</TouchableOpacity>
|
|
296
314
|
</View>
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
<Text style={{ color: props.theme?.global.secondFontColor, marginRight: cx(5) }}>{I18n.getLang('consumption_data_field3_co2_topic_text')}</Text>
|
|
300
|
-
<TouchableOpacity
|
|
301
|
-
onPress={() => {
|
|
302
|
-
state.showPopup = true
|
|
303
|
-
state.popupType = 'co2'
|
|
304
|
-
}}
|
|
305
|
-
>
|
|
306
|
-
<Image
|
|
307
|
-
source={res.co2Icon}
|
|
308
|
-
resizeMode="contain"
|
|
309
|
-
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
|
|
310
|
-
/>
|
|
311
|
-
</TouchableOpacity>
|
|
312
|
-
</View>
|
|
313
|
-
<Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>{`${state.co2Saved} kg`}</Text>
|
|
314
|
-
</View>
|
|
315
|
+
<Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>{`${state.co2Saved} kg`}</Text>
|
|
316
|
+
</View>
|
|
315
317
|
</View>
|
|
316
318
|
<Spacer height={cx(10)} />
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
</View>
|
|
327
|
-
<View>
|
|
328
|
-
<View style={styles.priceNum}>
|
|
329
|
-
<Text style={{ color: props.theme?.global.secondFontColor }}>{I18n.getLang(isSolarPlug ? 'consumption_data_monthly_overview_field1_text2' : 'consumption_data_field3_value_text2')}</Text>
|
|
330
|
-
<Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>{state.price ? `${localeNumber(Number(state.price ) * Number(state.totalElectricity), 2)} ${state.unit}` : '-'}</Text>
|
|
319
|
+
</>}
|
|
320
|
+
{/* money */}
|
|
321
|
+
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
322
|
+
<View style={styles.priceBg}>
|
|
323
|
+
<Image
|
|
324
|
+
source={res.energy_consumption_cash}
|
|
325
|
+
resizeMode="contain"
|
|
326
|
+
style={{ height: cx(20), width: cx(20), tintColor: props.theme?.button.primary }}
|
|
327
|
+
/>
|
|
331
328
|
</View>
|
|
332
|
-
<
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
<View style={styles.priceButton}>
|
|
337
|
-
<Text style={{ color: props.theme?.button.fontColor }}>{I18n.getLang('consumption_data_field3_button_text')}</Text>
|
|
329
|
+
<View>
|
|
330
|
+
<View style={styles.priceNum}>
|
|
331
|
+
<Text style={{ color: props.theme?.global.secondFontColor }}>{I18n.getLang(isSolarPlug ? 'consumption_data_monthly_overview_field1_text2' : 'consumption_data_field3_value_text2')}</Text>
|
|
332
|
+
<Text style={{ color: props.theme?.global.fontColor, fontWeight: 'bold' }}>{state.price ? `${localeNumber(Number(state.price ) * Number(state.totalElectricity), 2)} ${state.unit}` : '-'}</Text>
|
|
338
333
|
</View>
|
|
339
|
-
|
|
334
|
+
<TouchableOpacity onPress={() => {
|
|
335
|
+
state.showPopup = true
|
|
336
|
+
state.popupType = 'money'
|
|
337
|
+
}}>
|
|
338
|
+
<View style={styles.priceButton}>
|
|
339
|
+
<Text style={{ color: props.theme?.button.fontColor }}>{I18n.getLang('consumption_data_field3_button_text')}</Text>
|
|
340
|
+
</View>
|
|
341
|
+
</TouchableOpacity>
|
|
342
|
+
</View>
|
|
340
343
|
</View>
|
|
341
|
-
</
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
344
|
+
</Card>
|
|
345
|
+
<Spacer height={cx(30)} />
|
|
346
|
+
{/* Annual overview */}
|
|
347
|
+
{!!state.price && <OverView
|
|
348
|
+
style={{marginHorizontal: cx(24)}}
|
|
349
|
+
headlineText={I18n.getLang('consumption_data_field4_headline_text')}
|
|
350
|
+
headlineClick={() => {
|
|
351
|
+
navigation.navigate(ui_biz_routerKey.ui_biz_energy_consumption_chart, {
|
|
352
|
+
headlineText: chartHeadline,
|
|
353
|
+
chartData: state.overviewList,
|
|
354
|
+
price: state.price,
|
|
355
|
+
unit: state.unit,
|
|
356
|
+
addEleDpCode: params.addEleDpCode,
|
|
357
|
+
date: (new Date()).getFullYear().toString(),
|
|
358
|
+
} as EnergyConsumptionChartProps)
|
|
359
|
+
}}
|
|
360
|
+
overviewItemClick={(item) => {
|
|
361
|
+
navigation.navigate(ui_biz_routerKey.ui_biz_energy_consumption_detail, {
|
|
362
|
+
addEleDpCode: params.addEleDpCode,
|
|
363
|
+
curMonth: item,
|
|
364
|
+
price: state.price,
|
|
365
|
+
unit: state.unit,
|
|
366
|
+
updateEnergyData
|
|
367
|
+
} as EnergyConsumptionDetailProps)
|
|
368
|
+
}}
|
|
369
|
+
overViewList={state.overviewList}
|
|
370
|
+
/>}
|
|
371
|
+
{/* modal */}
|
|
372
|
+
<EnergyPopup
|
|
373
|
+
visible={!!(state.popupType && state.showPopup)}
|
|
374
|
+
popupType={state.popupType || 'co2'}
|
|
375
|
+
title={state.popupType === 'co2' ? I18n.getLang('consumption_data_field3_co2_topic_text') : ''}
|
|
376
|
+
cancelText={state.popupType === 'co2' ? '' : I18n.getLang("auto_scan_system_cancel")}
|
|
377
|
+
confirmText={I18n.getLang(state.popupType === 'co2' ? 'home_screen_home_dialog_yes_con' : 'auto_scan_system_wifi_confirm')}
|
|
378
|
+
energyData={{ price: state.price, unit: state.unit }}
|
|
379
|
+
onConfirm={(energyData) => {
|
|
380
|
+
state.popupType = ''
|
|
381
|
+
state.showPopup = false
|
|
382
|
+
if(energyData){
|
|
383
|
+
updateEnergyData({
|
|
384
|
+
...energyData,
|
|
385
|
+
price: exchangeNumber(energyData.price)
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
}}
|
|
389
|
+
onCancel={() => {
|
|
390
|
+
state.popupType = ''
|
|
391
|
+
state.showPopup = false
|
|
392
|
+
}}
|
|
393
|
+
/>
|
|
394
|
+
</View>
|
|
395
|
+
</ScrollView>
|
|
396
|
+
</Page>
|
|
391
397
|
)
|
|
392
398
|
}
|
|
393
399
|
|
|
@@ -23653,3 +23653,9 @@ export const carbonDioxideEmission = (name, list) => {
|
|
|
23653
23653
|
const order = emissionData?.find(item => item.nation === nationCode)?.value
|
|
23654
23654
|
return order || emissionData?.find(item => item.nation === 'World')?.value
|
|
23655
23655
|
}
|
|
23656
|
+
|
|
23657
|
+
export enum DateType {
|
|
23658
|
+
Year = 'Year',
|
|
23659
|
+
Month = 'Month',
|
|
23660
|
+
Day = 'Day',
|
|
23661
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import ThemeType from "@ledvance/base/src/config/themeType";
|
|
2
|
+
import React, {PropsWithChildren, useCallback, useEffect} from "react";
|
|
3
|
+
import {StyleSheet, Text, TouchableOpacity, View, ViewProps} from "react-native";
|
|
4
|
+
import {DatePicker, Modal, Utils} from "tuya-panel-kit";
|
|
5
|
+
import {useReactive} from "ahooks";
|
|
6
|
+
import I18n from "@ledvance/base/src/i18n/index";
|
|
7
|
+
import dayjs from "dayjs";
|
|
8
|
+
import { DateType } from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
|
|
9
|
+
|
|
10
|
+
const {convertX: cx} = Utils.RatioUtils
|
|
11
|
+
const {withTheme} = Utils.ThemeUtils
|
|
12
|
+
|
|
13
|
+
interface DateSelectedItemProps extends PropsWithChildren<ViewProps> {
|
|
14
|
+
theme?: ThemeType
|
|
15
|
+
date: string,
|
|
16
|
+
dateType: DateType,
|
|
17
|
+
onDateChange: (string) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getModalMode = (dateType) => {
|
|
21
|
+
switch (dateType) {
|
|
22
|
+
case DateType.Year:
|
|
23
|
+
return 'year';
|
|
24
|
+
case DateType.Month:
|
|
25
|
+
return 'month';
|
|
26
|
+
case DateType.Day:
|
|
27
|
+
default:
|
|
28
|
+
return 'date';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getDateForDateType = (year, month, day, dateType: DateType) => {
|
|
33
|
+
const monthOfYear = month.toString().padStart(2, '0');
|
|
34
|
+
const dayOfMonth = day.toString().padStart(2, '0');
|
|
35
|
+
switch (dateType) {
|
|
36
|
+
case DateType.Year:
|
|
37
|
+
return `${year}`
|
|
38
|
+
case DateType.Month:
|
|
39
|
+
return `${year}${monthOfYear}`;
|
|
40
|
+
case DateType.Day:
|
|
41
|
+
return `${year}${monthOfYear}${dayOfMonth}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default withTheme(function DateSelectedItem(props: DateSelectedItemProps) {
|
|
46
|
+
const {dateType, date, onDateChange, theme} = props;
|
|
47
|
+
const state = useReactive({
|
|
48
|
+
showDateModal: false,
|
|
49
|
+
date: date,
|
|
50
|
+
selectedDate: date,
|
|
51
|
+
dateType: dateType,
|
|
52
|
+
modalMode: getModalMode(dateType),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const styles = StyleSheet.create({
|
|
56
|
+
root: {
|
|
57
|
+
width: '100%',
|
|
58
|
+
flexDirection: 'row',
|
|
59
|
+
borderRadius: cx(4),
|
|
60
|
+
backgroundColor: props.theme?.textInput.background,
|
|
61
|
+
alignItems: 'center',
|
|
62
|
+
height: cx(44),
|
|
63
|
+
borderBottomWidth: cx(1),
|
|
64
|
+
borderBottomColor: props.theme?.textInput.line,
|
|
65
|
+
},
|
|
66
|
+
date: {
|
|
67
|
+
fontSize: cx(16),
|
|
68
|
+
textAlign: 'center',
|
|
69
|
+
flex: 1,
|
|
70
|
+
color: props.theme?.textInput.fontColor,
|
|
71
|
+
fontFamily: 'helvetica_neue_lt_std_roman',
|
|
72
|
+
},
|
|
73
|
+
modalRoot: {paddingTop: cx(20), backgroundColor: theme?.popup.cellBg},
|
|
74
|
+
modalButtonParent: {flex: 1, height: cx(48)},
|
|
75
|
+
modalButton: {
|
|
76
|
+
height: '100%',
|
|
77
|
+
alignItems: 'center',
|
|
78
|
+
justifyContent: 'center'
|
|
79
|
+
},
|
|
80
|
+
modalConfirm: {
|
|
81
|
+
textAlign: 'center',
|
|
82
|
+
color: theme?.popup.confirmFontColor,
|
|
83
|
+
fontWeight: 'bold',
|
|
84
|
+
fontSize: cx(16)
|
|
85
|
+
},
|
|
86
|
+
modalCancel: {
|
|
87
|
+
textAlign: 'center',
|
|
88
|
+
color: theme?.popup.cancelFontColor,
|
|
89
|
+
fontSize: cx(16)
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
state.dateType = dateType;
|
|
95
|
+
const datejs = dayjs(date)
|
|
96
|
+
switch (dateType) {
|
|
97
|
+
case DateType.Year:
|
|
98
|
+
state.date = `${datejs.year()}`;
|
|
99
|
+
break
|
|
100
|
+
case DateType.Month:
|
|
101
|
+
state.date = `${datejs.month() + 1}/${datejs.year()}`;
|
|
102
|
+
break
|
|
103
|
+
case DateType.Day:
|
|
104
|
+
state.date = `${datejs.date()}/${datejs.month() + 1}/${datejs.year()}`;
|
|
105
|
+
}
|
|
106
|
+
state.modalMode = getModalMode(dateType);
|
|
107
|
+
}, [dateType, date]);
|
|
108
|
+
|
|
109
|
+
return (<View style={props.style}>
|
|
110
|
+
<TouchableOpacity
|
|
111
|
+
style={{width: '100%',}}
|
|
112
|
+
onPress={() => {
|
|
113
|
+
state.showDateModal = true;
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
<View style={styles.root}>
|
|
117
|
+
<Text style={styles.date}>{state.date}</Text>
|
|
118
|
+
</View>
|
|
119
|
+
</TouchableOpacity>
|
|
120
|
+
|
|
121
|
+
<Modal
|
|
122
|
+
visible={state.showDateModal}
|
|
123
|
+
onCancel={() => {
|
|
124
|
+
state.showDateModal = false;
|
|
125
|
+
}}>
|
|
126
|
+
<View style={styles.modalRoot}>
|
|
127
|
+
<DatePicker
|
|
128
|
+
defaultDate={dayjs(date).toDate()}
|
|
129
|
+
mode={state.modalMode}
|
|
130
|
+
dateSortKeys={['day', 'month', 'year']}
|
|
131
|
+
maxDate={new Date()}
|
|
132
|
+
style={{backgroundColor: theme?.popup.cellBg}}
|
|
133
|
+
pickerFontColor={theme?.global.fontColor}
|
|
134
|
+
onDateChange={date => {
|
|
135
|
+
if (date) {
|
|
136
|
+
state.selectedDate = getDateForDateType(
|
|
137
|
+
date.getFullYear(),
|
|
138
|
+
date.getMonth() + 1,
|
|
139
|
+
date.getDate(),
|
|
140
|
+
dateType,
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/>
|
|
146
|
+
<View style={{flexDirection: 'row'}}>
|
|
147
|
+
<TouchableOpacity style={styles.modalButtonParent} onPress={() => {
|
|
148
|
+
state.showDateModal = false;
|
|
149
|
+
}}>
|
|
150
|
+
<View style={styles.modalButton}>
|
|
151
|
+
<Text style={styles.modalCancel}>{I18n.getLang('auto_scan_system_cancel')}</Text>
|
|
152
|
+
</View>
|
|
153
|
+
</TouchableOpacity>
|
|
154
|
+
<TouchableOpacity style={styles.modalButtonParent} onPress={() => {
|
|
155
|
+
state.showDateModal = false;
|
|
156
|
+
onDateChange(state.selectedDate);
|
|
157
|
+
}}>
|
|
158
|
+
<View style={styles.modalButton}>
|
|
159
|
+
<Text style={styles.modalConfirm}>{I18n.getLang('auto_scan_system_wifi_confirm')}</Text>
|
|
160
|
+
</View>
|
|
161
|
+
</TouchableOpacity>
|
|
162
|
+
</View>
|
|
163
|
+
</View>
|
|
164
|
+
</Modal>
|
|
165
|
+
|
|
166
|
+
</View>)
|
|
167
|
+
})
|
|
168
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import ThemeType from "@ledvance/base/src/config/themeType";
|
|
2
|
+
import React, {PropsWithChildren} from "react";
|
|
3
|
+
import {Text, TouchableOpacity, View, ViewProps} from "react-native";
|
|
4
|
+
import {Modal, Utils} from "tuya-panel-kit";
|
|
5
|
+
import {useReactive, useUpdateEffect} from "ahooks";
|
|
6
|
+
import I18n from "@ledvance/base/src/i18n/index";
|
|
7
|
+
import {DateType} from "@ledvance/ui-biz-bundle/src/newModules/energyConsumption/co2Data";
|
|
8
|
+
|
|
9
|
+
const {convertX: cx} = Utils.RatioUtils
|
|
10
|
+
const {withTheme} = Utils.ThemeUtils
|
|
11
|
+
|
|
12
|
+
interface DateTypeItemProps extends PropsWithChildren<ViewProps> {
|
|
13
|
+
theme?: ThemeType
|
|
14
|
+
dateType: string,
|
|
15
|
+
onDateTypeChange: (dateType: DateType) => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default withTheme(function DateTypeItem(props: DateTypeItemProps) {
|
|
19
|
+
const {dateType} = props;
|
|
20
|
+
const state = useReactive({
|
|
21
|
+
showDateTypeModal: false,
|
|
22
|
+
dateType: dateType,
|
|
23
|
+
});
|
|
24
|
+
useUpdateEffect(() => {
|
|
25
|
+
state.dateType = dateType;
|
|
26
|
+
}, [dateType])
|
|
27
|
+
return (<View style={props.style}>
|
|
28
|
+
<TouchableOpacity
|
|
29
|
+
style={{width: '100%',}}
|
|
30
|
+
onPress={() => {
|
|
31
|
+
state.showDateTypeModal = true;
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
<View
|
|
35
|
+
style={{
|
|
36
|
+
width: '100%',
|
|
37
|
+
flexDirection: 'row',
|
|
38
|
+
borderRadius: cx(4),
|
|
39
|
+
backgroundColor: props.theme?.textInput.background,
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
height: cx(44),
|
|
42
|
+
borderBottomWidth: cx(1),
|
|
43
|
+
borderBottomColor: props.theme?.textInput.line,
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
<Text style={{
|
|
47
|
+
fontSize: cx(16),
|
|
48
|
+
textAlign: 'center',
|
|
49
|
+
flex: 1,
|
|
50
|
+
color: props.theme?.textInput.fontColor,
|
|
51
|
+
fontFamily: 'helvetica_neue_lt_std_roman',
|
|
52
|
+
}}>{state.dateType}</Text>
|
|
53
|
+
</View>
|
|
54
|
+
</TouchableOpacity>
|
|
55
|
+
|
|
56
|
+
<Modal.List
|
|
57
|
+
type={'radio'}
|
|
58
|
+
visible={state.showDateTypeModal}
|
|
59
|
+
value={state.dateType}
|
|
60
|
+
dataSource={[
|
|
61
|
+
{
|
|
62
|
+
title: I18n.getLang('day'),
|
|
63
|
+
key: DateType.Day,
|
|
64
|
+
value: DateType.Day,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: I18n.getLang('month'),
|
|
68
|
+
key: DateType.Month,
|
|
69
|
+
value: DateType.Month,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: I18n.getLang('year'),
|
|
73
|
+
key: DateType.Year,
|
|
74
|
+
value: DateType.Year,
|
|
75
|
+
}
|
|
76
|
+
]}
|
|
77
|
+
onCancel={() => {
|
|
78
|
+
state.showDateTypeModal = false;
|
|
79
|
+
}}
|
|
80
|
+
title={I18n.getLang('date_type')}
|
|
81
|
+
cancelText={I18n.getLang('auto_scan_system_cancel')}
|
|
82
|
+
confirmText={I18n.getLang('auto_scan_system_wifi_confirm')}
|
|
83
|
+
onConfirm={(item: DateType) => {
|
|
84
|
+
state.showDateTypeModal = false;
|
|
85
|
+
props.onDateTypeChange(item)
|
|
86
|
+
}}
|
|
87
|
+
/>
|
|
88
|
+
</View>)
|
|
89
|
+
})
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React, {useRef} from 'react';
|
|
2
|
+
import {View} from 'react-native';
|
|
3
|
+
import ECharts from '@ledvance/react-native-echarts-pro';
|
|
4
|
+
import I18n from "@ledvance/base/src/i18n";
|
|
5
|
+
import ThemeType from "@ledvance/base/src/config/themeType";
|
|
6
|
+
import {Utils} from "tuya-panel-kit";
|
|
7
|
+
import {OverviewItem} from "../EnergyConsumptionPage";
|
|
8
|
+
|
|
9
|
+
const {withTheme} = Utils.ThemeUtils
|
|
10
|
+
|
|
11
|
+
interface BarChartProps {
|
|
12
|
+
theme?: ThemeType
|
|
13
|
+
data: OverviewItem[],
|
|
14
|
+
price: number,
|
|
15
|
+
unit: string,
|
|
16
|
+
height: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const BarChartWithTouch = (props: BarChartProps) => {
|
|
20
|
+
const echarts = useRef();
|
|
21
|
+
const {data, height, price, unit, theme} = props;
|
|
22
|
+
const dataX = data?.map(item => {
|
|
23
|
+
return item.chartTitle;
|
|
24
|
+
});
|
|
25
|
+
const dataKwhY = data?.map(item => {
|
|
26
|
+
return Number(item.value);
|
|
27
|
+
});
|
|
28
|
+
const dataPriceY = data?.map(item => {
|
|
29
|
+
return ((isNaN(Number(item.value)) ? 0 : Number(item.value)) * price).toFixed(2);
|
|
30
|
+
});
|
|
31
|
+
const maxValue = Math.max(...dataKwhY);
|
|
32
|
+
const option = {
|
|
33
|
+
tooltip: {
|
|
34
|
+
show: true,
|
|
35
|
+
triggerOn: 'click',
|
|
36
|
+
trigger: 'axis',
|
|
37
|
+
},
|
|
38
|
+
legend: {
|
|
39
|
+
show: true,
|
|
40
|
+
data: ['kWh', unit],
|
|
41
|
+
textStyle: {
|
|
42
|
+
color: theme?.global.fontColor,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
xAxis: {
|
|
46
|
+
data: dataX,
|
|
47
|
+
axisTick: {
|
|
48
|
+
show: false,
|
|
49
|
+
},
|
|
50
|
+
axisLabel: {
|
|
51
|
+
show: true,
|
|
52
|
+
color: props.theme?.global.secondFontColor,
|
|
53
|
+
interval: 0,
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
yAxis: [{
|
|
57
|
+
type: 'value',
|
|
58
|
+
name: I18n.getLang('consumption_data_annual_bar_chart_text'),
|
|
59
|
+
max: Math.ceil(maxValue),
|
|
60
|
+
min: 0,
|
|
61
|
+
position: 'left',
|
|
62
|
+
axisLabel: {
|
|
63
|
+
formatter: function (value) {
|
|
64
|
+
return parseFloat(value).toFixed(2);
|
|
65
|
+
},
|
|
66
|
+
color:props.theme?.global.secondFontColor,
|
|
67
|
+
},
|
|
68
|
+
nameTextStyle: {
|
|
69
|
+
fontSize: 14,
|
|
70
|
+
color: props.theme?.global.secondFontColor,
|
|
71
|
+
},
|
|
72
|
+
}, {
|
|
73
|
+
type: 'value',
|
|
74
|
+
name: I18n.formatValue('format_unit', unit),
|
|
75
|
+
position: 'right',
|
|
76
|
+
alignTicks: true,
|
|
77
|
+
max: Math.ceil(price ? maxValue * price * 1.4 : 0),
|
|
78
|
+
min: 0,
|
|
79
|
+
minInterval: 1,
|
|
80
|
+
axisLabel: {
|
|
81
|
+
formatter: function (value) {
|
|
82
|
+
return parseFloat(value).toFixed(1);
|
|
83
|
+
},
|
|
84
|
+
color:props.theme?.global.secondFontColor,
|
|
85
|
+
},
|
|
86
|
+
nameTextStyle: {
|
|
87
|
+
fontSize: 14,
|
|
88
|
+
color: props.theme?.global.secondFontColor,
|
|
89
|
+
},
|
|
90
|
+
}],
|
|
91
|
+
series: [
|
|
92
|
+
{
|
|
93
|
+
name: 'kWh',
|
|
94
|
+
type: 'bar',
|
|
95
|
+
data: dataKwhY,
|
|
96
|
+
itemStyle: {
|
|
97
|
+
emphasis: {
|
|
98
|
+
color: '#FFC2A9', // Color when bar is clicked
|
|
99
|
+
},
|
|
100
|
+
color: '#FFC2A9',
|
|
101
|
+
borderRadius: 2,
|
|
102
|
+
},
|
|
103
|
+
barMaxWidth: 10,
|
|
104
|
+
select: {
|
|
105
|
+
itemStyle: {
|
|
106
|
+
borderColor: '#FFC2A9',
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
selectedMode: 'single',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: unit,
|
|
113
|
+
type: 'line',
|
|
114
|
+
data: dataPriceY,
|
|
115
|
+
yAxisIndex: 1,
|
|
116
|
+
smooth: true,
|
|
117
|
+
showSymbol: false,
|
|
118
|
+
color: '#F49431',
|
|
119
|
+
selectedMode: "single",
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
dataZoom: {
|
|
123
|
+
start: 0,
|
|
124
|
+
type: "inside",
|
|
125
|
+
maxValueSpan: 5,
|
|
126
|
+
zoomLock: true,
|
|
127
|
+
},
|
|
128
|
+
customMapData: {}
|
|
129
|
+
};
|
|
130
|
+
return (
|
|
131
|
+
<View style={{flex: 1}}>
|
|
132
|
+
<ECharts
|
|
133
|
+
option={option}
|
|
134
|
+
ref={echarts}
|
|
135
|
+
height={height}
|
|
136
|
+
/>
|
|
137
|
+
</View>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export default withTheme(BarChartWithTouch)
|