@tuya-sat/sdf-main-sdk 0.0.1-beta.1
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/.vscode/settings.json +5 -0
- package/README.md +1 -0
- package/antd.less.overwrite.js +56 -0
- package/color.js +140 -0
- package/dark-variable.less +1449 -0
- package/package.json +74 -0
- package/scripts/gen-localize-file.mjs +56 -0
- package/src/App.less +156 -0
- package/src/App.tsx +87 -0
- package/src/api/index.ts +52 -0
- package/src/api/req.ts +23 -0
- package/src/api/res.ts +29 -0
- package/src/api/urls.ts +30 -0
- package/src/api/utils.ts +41 -0
- package/src/assets/imgs/404.svg +194 -0
- package/src/assets/imgs/reLogin.png +0 -0
- package/src/components/404/index.tsx +44 -0
- package/src/components/500/index.tsx +49 -0
- package/src/components/BCustomNav/index.module.less +17 -0
- package/src/components/BCustomNav/index.tsx +108 -0
- package/src/components/BForgot/index.module.less +5 -0
- package/src/components/BForgot/index.tsx +96 -0
- package/src/components/BHeaderUser/account.png +0 -0
- package/src/components/BHeaderUser/app-scan-en.png +0 -0
- package/src/components/BHeaderUser/app-scan-zh.png +0 -0
- package/src/components/BHeaderUser/app-scan.png +0 -0
- package/src/components/BHeaderUser/components/BSwitchLang/index.module.less +6 -0
- package/src/components/BHeaderUser/components/BSwitchLang/index.tsx +56 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/Content.tsx +199 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/index.module.less +11 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/Drawer/index.tsx +27 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/hooks.ts +104 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/index.module.less +70 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/index.tsx +184 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/table/index.tsx +184 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/table/read.tsx +67 -0
- package/src/components/BHeaderUser/components/Badge/components/Notice/tools/index.tsx +116 -0
- package/src/components/BHeaderUser/components/Badge/index.module.less +99 -0
- package/src/components/BHeaderUser/components/Badge/index.tsx +179 -0
- package/src/components/BHeaderUser/index.module.less +105 -0
- package/src/components/BHeaderUser/index.tsx +261 -0
- package/src/components/BHeaderUser/logout.tsx +26 -0
- package/src/components/BLayout/components/Header/index.module.less +27 -0
- package/src/components/BLayout/components/Header/index.tsx +36 -0
- package/src/components/BLayout/components/Layout/empty.tsx +35 -0
- package/src/components/BLayout/components/Layout/emptyPage.png +0 -0
- package/src/components/BLayout/components/Layout/index.tsx +72 -0
- package/src/components/BLayout/components/Logo.tsx +6 -0
- package/src/components/BLayout/components/Menu/collapse.tsx +41 -0
- package/src/components/BLayout/components/Menu/image/close.tsx +26 -0
- package/src/components/BLayout/components/Menu/image/closedefault.tsx +26 -0
- package/src/components/BLayout/components/Menu/image/open.tsx +38 -0
- package/src/components/BLayout/components/Menu/image/opendefault.tsx +38 -0
- package/src/components/BLayout/components/Menu/index.module.less +125 -0
- package/src/components/BLayout/components/Menu/index.tsx +244 -0
- package/src/components/BLayout/components/MenuIcon.module.less +5 -0
- package/src/components/BLayout/components/MenuIcon.tsx +46 -0
- package/src/components/BLayout/components/MultiSider/index.module.less +104 -0
- package/src/components/BLayout/components/MultiSider/index.tsx +172 -0
- package/src/components/BLayout/components/Sider/index.less +64 -0
- package/src/components/BLayout/components/Sider/index.module.less +17 -0
- package/src/components/BLayout/components/Sider/index.tsx +34 -0
- package/src/components/BLayout/index.tsx +78 -0
- package/src/components/BLayoutLogin/index.module.less +65 -0
- package/src/components/BLayoutLogin/index.tsx +68 -0
- package/src/components/BLayoutLogin/login.jpg +0 -0
- package/src/components/BLogin/component/Clause/index.module.less +25 -0
- package/src/components/BLogin/component/Clause/index.tsx +58 -0
- package/src/components/BLogin/component/ForgotBtn/index.module.less +9 -0
- package/src/components/BLogin/component/ForgotBtn/index.tsx +18 -0
- package/src/components/BLogin/component/Password/index.tsx +39 -0
- package/src/components/BLogin/component/SubmitBtn/index.tsx +30 -0
- package/src/components/BLogin/component/TenanSpace/index.tsx +28 -0
- package/src/components/BLogin/component/Title/index.module.less +6 -0
- package/src/components/BLogin/component/Title/index.tsx +12 -0
- package/src/components/BLogin/component/UserName/index.tsx +48 -0
- package/src/components/BLogin/component/VerifyCode/index.module.less +11 -0
- package/src/components/BLogin/component/VerifyCode/index.tsx +165 -0
- package/src/components/BLogin/index.module.less +31 -0
- package/src/components/BLogin/index.tsx +210 -0
- package/src/components/BRegister/components/TenantName/index.tsx +26 -0
- package/src/components/BRegister/index.module.less +5 -0
- package/src/components/BRegister/index.tsx +71 -0
- package/src/components/Back/index.tsx +25 -0
- package/src/components/IconFont/font.js +66 -0
- package/src/components/IconFont/index.tsx +18 -0
- package/src/components/MicroComponent/Header/index.module.less +7 -0
- package/src/components/MicroComponent/Header/index.tsx +220 -0
- package/src/components/PForgot/index.tsx +10 -0
- package/src/components/PLogin/index.tsx +12 -0
- package/src/components/PRegister/index.tsx +10 -0
- package/src/components/PSetting/index.module.less +53 -0
- package/src/components/PSetting/index.tsx +420 -0
- package/src/constant/chargeStatus.ts +6 -0
- package/src/constant/imgs.ts +6 -0
- package/src/constant/index.ts +293 -0
- package/src/dark-variable.less +1449 -0
- package/src/global.d.ts +54 -0
- package/src/hooks/index.ts +133 -0
- package/src/index.css +1493 -0
- package/src/index.tsx +105 -0
- package/src/lang/en.json +266 -0
- package/src/lang/index.ts +44 -0
- package/src/lang/utils.ts +285 -0
- package/src/lang/zh.json +270 -0
- package/src/micro-script/theme/index.ts +29 -0
- package/src/micro-script/theme/theme-css/static.js +73 -0
- package/src/micro-script/theme/theme-css/subscriber.ts +201 -0
- package/src/micro-script/theme/util/index.ts +58 -0
- package/src/mqtt/index.ts +121 -0
- package/src/pages/403.tsx +18 -0
- package/src/pages/404.tsx +17 -0
- package/src/pages/expiration.tsx +23 -0
- package/src/pages/forgot.tsx +9 -0
- package/src/pages/home/index.tsx +172 -0
- package/src/pages/home/setting/index.tsx +7 -0
- package/src/pages/index.ts +50 -0
- package/src/pages/login.tsx +46 -0
- package/src/pages/register.tsx +9 -0
- package/src/pages/relogin/index.module.less +0 -0
- package/src/pages/relogin/index.tsx +54 -0
- package/src/plugins/index.ts +11 -0
- package/src/public-path.js +8 -0
- package/src/qiankun/globalState.ts +6 -0
- package/src/qiankun/index.ts +174 -0
- package/src/qiankun/utils/index.ts +69 -0
- package/src/qiankun/xhook/index.ts +193 -0
- package/src/reportWebVitals.ts +15 -0
- package/src/sentry/index.ts +33 -0
- package/src/sky/index.ts +57 -0
- package/src/theme/custom-dark.less +64 -0
- package/src/theme/custom-light.less +48 -0
- package/src/theme/index.less +327 -0
- package/src/theme/variable.less +13 -0
- package/src/utils/checkPass.ts +21 -0
- package/src/utils/common.ts +195 -0
- package/src/utils/eventBus.ts +112 -0
- package/src/utils/gt.js +293 -0
- package/src/utils/index.ts +89 -0
- package/src/utils/theme/base.ts +110 -0
- package/src/utils/theme/changeCssVariable.ts +157 -0
- package/src/utils/theme/changeMenuCssVariable.ts +176 -0
- package/src/utils/theme/index.ts +85 -0
- package/src/utils/theme/store.ts +37 -0
- package/tsconfig.json +28 -0
- package/typings.d.ts +10 -0
- package/webpack.config.js +103 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Table, Typography } from 'antd';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { useSaasInfo } from '@/hooks';
|
|
5
|
+
import styles from '../index.module.less';
|
|
6
|
+
import Read from './read';
|
|
7
|
+
import { eventEmiter, eventNames } from '@/utils';
|
|
8
|
+
|
|
9
|
+
const { Text, Link } = Typography;
|
|
10
|
+
|
|
11
|
+
const NoticeTable = (props) => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const { saasIdInfoList } = useSaasInfo();
|
|
14
|
+
|
|
15
|
+
// 触发每条消息的已读
|
|
16
|
+
const {
|
|
17
|
+
selectedRowKeys,
|
|
18
|
+
setSelectedRowKeys,
|
|
19
|
+
loading,
|
|
20
|
+
list,
|
|
21
|
+
total,
|
|
22
|
+
pageSize,
|
|
23
|
+
current,
|
|
24
|
+
setCurrent,
|
|
25
|
+
setPageSize,
|
|
26
|
+
getData,
|
|
27
|
+
} = props;
|
|
28
|
+
|
|
29
|
+
const [dataList, setDataList] = useState(list);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setDataList(list);
|
|
32
|
+
}, [list]);
|
|
33
|
+
const columns = [
|
|
34
|
+
{
|
|
35
|
+
title: t('notice.table.column.content'),
|
|
36
|
+
dataIndex: 'message_content',
|
|
37
|
+
width: '40%',
|
|
38
|
+
render: (text, record) => {
|
|
39
|
+
if (
|
|
40
|
+
record.action_url &&
|
|
41
|
+
record.action_url.includes('tuyaSmart://microApp')
|
|
42
|
+
) {
|
|
43
|
+
const queryString = record.action_url.replace(
|
|
44
|
+
'tuyaSmart://microApp?',
|
|
45
|
+
''
|
|
46
|
+
);
|
|
47
|
+
const searchParams = new URLSearchParams(queryString);
|
|
48
|
+
const universal_id = searchParams.get('universalId');
|
|
49
|
+
const path = searchParams.get('path');
|
|
50
|
+
const query = searchParams.get('query');
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<Text
|
|
54
|
+
ellipsis={{ tooltip: record.message_content }}
|
|
55
|
+
style={{ color: 'var(--ant-primary-color)', cursor: 'pointer' }}
|
|
56
|
+
onClick={() => {
|
|
57
|
+
let pathUrl = '';
|
|
58
|
+
if (path) {
|
|
59
|
+
pathUrl = path;
|
|
60
|
+
if (atob(query)) {
|
|
61
|
+
pathUrl += `?${atob(query)}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const appId =
|
|
65
|
+
saasIdInfoList.find(
|
|
66
|
+
(item) => item.universal_id === universal_id
|
|
67
|
+
).oem_micro_app_id || '';
|
|
68
|
+
if (appId) {
|
|
69
|
+
window.open(
|
|
70
|
+
`${window.location.origin}/apps/${appId}${pathUrl}`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{record.message_content}
|
|
76
|
+
</Text>
|
|
77
|
+
);
|
|
78
|
+
} else {
|
|
79
|
+
return (
|
|
80
|
+
<Text ellipsis={{ tooltip: record.message_content }}>
|
|
81
|
+
{record.message_content}
|
|
82
|
+
</Text>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: t('notice.table.column.status'),
|
|
89
|
+
dataIndex: 'read_status',
|
|
90
|
+
render: (text) =>
|
|
91
|
+
text === '0'
|
|
92
|
+
? t('notice.table.render.status.unread')
|
|
93
|
+
: t('notice.table.render.status.read'),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
title: t('notice.table.column.type'),
|
|
97
|
+
dataIndex: 'message_type',
|
|
98
|
+
render: (text) =>
|
|
99
|
+
text === '1'
|
|
100
|
+
? t('notice.typeSelect.alert')
|
|
101
|
+
: t('notice.typeSelect.message'),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
title: t('notice.table.column.source'),
|
|
105
|
+
render: (text, record) => {
|
|
106
|
+
if (record.micro_universal_id) {
|
|
107
|
+
return (
|
|
108
|
+
<Link
|
|
109
|
+
onClick={() => {
|
|
110
|
+
const appId =
|
|
111
|
+
saasIdInfoList.find(
|
|
112
|
+
(item) => item.universal_id === record.micro_universal_id
|
|
113
|
+
).oem_micro_app_id || '';
|
|
114
|
+
appId && window.open(`${window.location.origin}/apps/${appId}`);
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{record.source_name}
|
|
118
|
+
</Link>
|
|
119
|
+
);
|
|
120
|
+
} else {
|
|
121
|
+
return <Text>{record.source_name}</Text>;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
title: t('notice.table.column.time'),
|
|
127
|
+
dataIndex: 'create_time',
|
|
128
|
+
width: '170px',
|
|
129
|
+
render: (text, record) => {
|
|
130
|
+
return rowKey === record.message_id ? (
|
|
131
|
+
<Read record={record} setDataList={setDataList} />
|
|
132
|
+
) : (
|
|
133
|
+
<Text className={styles.action}>{text}</Text>
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const rowSelection = {
|
|
140
|
+
selectedRowKeys,
|
|
141
|
+
onChange: (selectedRowKeys) => {
|
|
142
|
+
console.log('selectedRowKeys', selectedRowKeys.length);
|
|
143
|
+
setSelectedRowKeys(selectedRowKeys);
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
const [rowKey, setRowKey] = useState(null);
|
|
147
|
+
return (
|
|
148
|
+
<Table
|
|
149
|
+
rowKey="message_id"
|
|
150
|
+
rowSelection={rowSelection}
|
|
151
|
+
columns={columns}
|
|
152
|
+
dataSource={dataList}
|
|
153
|
+
sticky
|
|
154
|
+
loading={loading}
|
|
155
|
+
scroll={{ y: '560px' }}
|
|
156
|
+
onRow={(record) => {
|
|
157
|
+
return {
|
|
158
|
+
onMouseEnter: () => {
|
|
159
|
+
setRowKey(record.message_id);
|
|
160
|
+
}, // 鼠标移入行
|
|
161
|
+
onMouseLeave: () => {
|
|
162
|
+
setRowKey(null);
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}}
|
|
166
|
+
pagination={{
|
|
167
|
+
total,
|
|
168
|
+
current,
|
|
169
|
+
pageSize,
|
|
170
|
+
showSizeChanger: true,
|
|
171
|
+
showQuickJumper: true,
|
|
172
|
+
pageSizeOptions: ['10', '20', '40', '50'],
|
|
173
|
+
onChange: (current: number, pageSize: number) => {
|
|
174
|
+
setCurrent(current);
|
|
175
|
+
setPageSize(pageSize);
|
|
176
|
+
getData(pageSize, current);
|
|
177
|
+
eventEmiter.emit(eventNames.HIDE_MSG_TOOL);
|
|
178
|
+
},
|
|
179
|
+
}}
|
|
180
|
+
/>
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export default NoticeTable;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Typography, Divider, Popconfirm } from 'antd';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import styles from '../index.module.less';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { readStatus, noticeDelete } from '../hooks';
|
|
6
|
+
import EventBus from '@/utils/eventBus';
|
|
7
|
+
import { EVENT_NOTICE } from '@/constant';
|
|
8
|
+
|
|
9
|
+
const { Text, Link } = Typography;
|
|
10
|
+
const Read = ({ record, setDataList }) => {
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
|
|
13
|
+
const changItem = (read_status: string) => {
|
|
14
|
+
setDataList((prev) => {
|
|
15
|
+
const newList = prev.map((item) => {
|
|
16
|
+
if (item.message_id === record.message_id) {
|
|
17
|
+
item.read_status = read_status;
|
|
18
|
+
}
|
|
19
|
+
return item;
|
|
20
|
+
});
|
|
21
|
+
return newList;
|
|
22
|
+
});
|
|
23
|
+
setTimeout(() => {
|
|
24
|
+
EventBus.dispatchEvent(EVENT_NOTICE);
|
|
25
|
+
}, 500);
|
|
26
|
+
};
|
|
27
|
+
const markStatus = () => {
|
|
28
|
+
if (record.read_status == 0) {
|
|
29
|
+
readStatus('1', [record.message_id]).then(() => changItem('1'));
|
|
30
|
+
} else {
|
|
31
|
+
readStatus('0', [record.message_id]).then(() => changItem('0'));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const del = () => {
|
|
36
|
+
noticeDelete([record.message_id]).then(() => {
|
|
37
|
+
setDataList((prev) =>
|
|
38
|
+
prev.filter((item) => item.message_id !== record.message_id)
|
|
39
|
+
);
|
|
40
|
+
if (record.read_status == 0) {
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
EventBus.dispatchEvent(EVENT_NOTICE);
|
|
43
|
+
}, 500);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<Link className={styles.action} onClick={() => markStatus()}>
|
|
50
|
+
{record.read_status == 0
|
|
51
|
+
? t('notice.table.hover.read')
|
|
52
|
+
: t('notice.table.hover.unread')}
|
|
53
|
+
</Link>
|
|
54
|
+
<Divider type="vertical" />
|
|
55
|
+
<Popconfirm title={t('notice.table.delTip')} onConfirm={() => del()}>
|
|
56
|
+
<Text
|
|
57
|
+
className={cx(styles.action)}
|
|
58
|
+
style={{ cursor: 'pointer' }}
|
|
59
|
+
type="danger"
|
|
60
|
+
>
|
|
61
|
+
{t('notice.table.hover.del')}
|
|
62
|
+
</Text>
|
|
63
|
+
</Popconfirm>
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
export default Read;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { useCallback, useMemo, useEffect } from 'react';
|
|
2
|
+
import { Modal, Typography } from 'antd';
|
|
3
|
+
|
|
4
|
+
import eventBus from '@/utils/eventBus';
|
|
5
|
+
import { EVENT_NOTICE } from '@/constant';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { readStatus, noticeDelete, useReadCount } from '../hooks';
|
|
8
|
+
|
|
9
|
+
const { Link, Text } = Typography;
|
|
10
|
+
import styles from '../index.module.less';
|
|
11
|
+
import classnames from 'classnames';
|
|
12
|
+
import { eventEmiter, eventNames } from '@/utils';
|
|
13
|
+
|
|
14
|
+
interface Iprops {
|
|
15
|
+
pageSize: number;
|
|
16
|
+
selectedRowKeys: string[];
|
|
17
|
+
setSelectedRowKeys: (selectedRowKeys: string[]) => void;
|
|
18
|
+
getData: (page: number, pageSize: number) => void;
|
|
19
|
+
}
|
|
20
|
+
const Tools = ({
|
|
21
|
+
selectedRowKeys,
|
|
22
|
+
getData,
|
|
23
|
+
setSelectedRowKeys,
|
|
24
|
+
pageSize,
|
|
25
|
+
}: Iprops) => {
|
|
26
|
+
const { t } = useTranslation();
|
|
27
|
+
|
|
28
|
+
const [count] = useReadCount();
|
|
29
|
+
|
|
30
|
+
const resultBack = () => {
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
getData(pageSize, 1);
|
|
33
|
+
setSelectedRowKeys([]);
|
|
34
|
+
eventBus.dispatchEvent(EVENT_NOTICE);
|
|
35
|
+
}, 500);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
eventEmiter.addListener(eventNames.HIDE_MSG_TOOL, () => {
|
|
40
|
+
setSelectedRowKeys([]);
|
|
41
|
+
});
|
|
42
|
+
}, []);
|
|
43
|
+
|
|
44
|
+
const onDelete = useCallback(async () => {
|
|
45
|
+
const onOk = async () => {
|
|
46
|
+
const result = await noticeDelete(selectedRowKeys);
|
|
47
|
+
result && resultBack();
|
|
48
|
+
};
|
|
49
|
+
Modal.confirm({
|
|
50
|
+
title: t('notice.tools.popconfirm.title'),
|
|
51
|
+
content: t('notice.tools.popconfirm.content'),
|
|
52
|
+
okText: t('notice.tools.popconfirm.ok'),
|
|
53
|
+
onOk: () => onOk(),
|
|
54
|
+
cancelText: t('notice.tools.popconfirm.cancel'),
|
|
55
|
+
});
|
|
56
|
+
}, [getData, selectedRowKeys]);
|
|
57
|
+
|
|
58
|
+
const onReadStatus = useCallback(
|
|
59
|
+
async (type: string) => {
|
|
60
|
+
const result = await readStatus(type, selectedRowKeys);
|
|
61
|
+
result && resultBack();
|
|
62
|
+
},
|
|
63
|
+
[getData, selectedRowKeys]
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const selectNone = () => {
|
|
67
|
+
setSelectedRowKeys([]);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const checked = useMemo(() => {
|
|
71
|
+
return (
|
|
72
|
+
<div className={classnames(styles.checked, 'main-notice-tools-bg')}>
|
|
73
|
+
<div className={styles['checked-left']}>
|
|
74
|
+
<Text style={{ marginLeft: '16px' }}>
|
|
75
|
+
{t('notice.tools.itemsNums', {
|
|
76
|
+
num: selectedRowKeys.length,
|
|
77
|
+
})}
|
|
78
|
+
</Text>
|
|
79
|
+
|
|
80
|
+
<Link style={{ marginLeft: '16px' }} onClick={selectNone}>
|
|
81
|
+
{t('notice.tools.cancelSelect')}
|
|
82
|
+
</Link>
|
|
83
|
+
</div>
|
|
84
|
+
<div className={styles['checked-right']}>
|
|
85
|
+
<Link
|
|
86
|
+
style={{ marginRight: '16px' }}
|
|
87
|
+
onClick={() => onReadStatus('1')}
|
|
88
|
+
>
|
|
89
|
+
{t('notice.tools.pread')}
|
|
90
|
+
</Link>
|
|
91
|
+
<Link
|
|
92
|
+
style={{ marginRight: '16px' }}
|
|
93
|
+
onClick={() => onReadStatus('0')}
|
|
94
|
+
>
|
|
95
|
+
{t('notice.tools.punread')}
|
|
96
|
+
</Link>
|
|
97
|
+
<Text
|
|
98
|
+
style={{ marginRight: '16px', cursor: 'pointer' }}
|
|
99
|
+
type="danger"
|
|
100
|
+
onClick={() => onDelete()}
|
|
101
|
+
>
|
|
102
|
+
{t('notice.tools.pdelete')}
|
|
103
|
+
</Text>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
);
|
|
107
|
+
}, [onDelete, onReadStatus]);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<div className={styles.tools}>
|
|
111
|
+
{selectedRowKeys && selectedRowKeys.length > 0 && checked}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export default Tools;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// 单行
|
|
2
|
+
.single-warp() {
|
|
3
|
+
overflow: hidden;
|
|
4
|
+
text-overflow: ellipsis;
|
|
5
|
+
white-space: nowrap;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// 两行
|
|
9
|
+
.multi-warp {
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
text-overflow: ellipsis;
|
|
12
|
+
display: -webkit-box;
|
|
13
|
+
-webkit-line-clamp: 2;
|
|
14
|
+
-webkit-box-orient: vertical;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.resetPopover {
|
|
18
|
+
:global {
|
|
19
|
+
.main-popover-inner-content {
|
|
20
|
+
padding: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.main-list-header {
|
|
24
|
+
height: 32px;
|
|
25
|
+
line-height: 32px;
|
|
26
|
+
padding: 0;
|
|
27
|
+
font-weight: 500;
|
|
28
|
+
font-size: 14px;
|
|
29
|
+
padding-left: 20px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.main-spin-nested-loading {
|
|
33
|
+
padding: 0 20px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.main-list-item {
|
|
37
|
+
height: 79px;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.resetList {
|
|
43
|
+
:global {
|
|
44
|
+
.main-list-item-meta-title {
|
|
45
|
+
font-size: 12px;
|
|
46
|
+
.single-warp();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.main-list-item-meta-description {
|
|
50
|
+
font-size: 14px;
|
|
51
|
+
font-weight: 400;
|
|
52
|
+
.multi-warp();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.multiple {
|
|
58
|
+
:global {
|
|
59
|
+
.main-badge-multiple-words {
|
|
60
|
+
padding: 0 4px;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.iconMargin {
|
|
66
|
+
margin-right: 5px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.circle {
|
|
70
|
+
height: 24px;
|
|
71
|
+
.icon {
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
color: #555;
|
|
74
|
+
&:hover {
|
|
75
|
+
color: rgb(24, 144, 255);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.footer {
|
|
81
|
+
height: 18px;
|
|
82
|
+
display: flex;
|
|
83
|
+
align-self: center;
|
|
84
|
+
justify-content: center;
|
|
85
|
+
|
|
86
|
+
span {
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
font-weight: 400;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
line-height: 22px;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.wrap-badge {
|
|
95
|
+
height: 24px;
|
|
96
|
+
margin-left: 24px;
|
|
97
|
+
line-height: 24px;
|
|
98
|
+
margin-left: 24px;
|
|
99
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { Badge, List, Popover, Typography } from 'antd';
|
|
3
|
+
import cn from 'classnames';
|
|
4
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import IconFont from '@/components/IconFont';
|
|
7
|
+
import EventBus from '@/utils/eventBus';
|
|
8
|
+
import { useSaasInfo } from '@/hooks';
|
|
9
|
+
import { EVENT_NOTICE } from '@/constant';
|
|
10
|
+
import {
|
|
11
|
+
useReadCount,
|
|
12
|
+
useNoticeList,
|
|
13
|
+
Inotice,
|
|
14
|
+
} from '@/components/BHeaderUser/components/Badge/components/Notice/hooks';
|
|
15
|
+
|
|
16
|
+
import styles from './index.module.less';
|
|
17
|
+
|
|
18
|
+
const { Text } = Typography;
|
|
19
|
+
|
|
20
|
+
const Notice = () => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const { saasIdInfoList } = useSaasInfo();
|
|
23
|
+
|
|
24
|
+
const [count, getReadCount] = useReadCount();
|
|
25
|
+
|
|
26
|
+
const { list, getData } = useNoticeList('', '', '0', 10);
|
|
27
|
+
|
|
28
|
+
const [visible, setVisible] = useState(false);
|
|
29
|
+
|
|
30
|
+
const history = useHistory();
|
|
31
|
+
|
|
32
|
+
const { pathname } = useLocation();
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const cb = () => {
|
|
36
|
+
getReadCount();
|
|
37
|
+
getData(10, 1);
|
|
38
|
+
};
|
|
39
|
+
EventBus.addEventListener(EVENT_NOTICE, cb);
|
|
40
|
+
return () => {
|
|
41
|
+
EventBus.removeEventListener(EVENT_NOTICE, cb);
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
|
|
45
|
+
const jumpNotice = () => {
|
|
46
|
+
// 点击后关闭弹窗
|
|
47
|
+
setVisible(false);
|
|
48
|
+
if (pathname === '/application/notification') return;
|
|
49
|
+
|
|
50
|
+
if (pathname === '/application/setting') {
|
|
51
|
+
history.replace('/application/notification');
|
|
52
|
+
} else {
|
|
53
|
+
history.push('/application/notification');
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const onVisibleChange = (visible: boolean) => {
|
|
58
|
+
setVisible(visible);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const offset = (count: number): [number, number] => {
|
|
62
|
+
if (count <= 99 && count > 9) {
|
|
63
|
+
return [3, 0];
|
|
64
|
+
}
|
|
65
|
+
if (count > 99) {
|
|
66
|
+
return [8, 0];
|
|
67
|
+
}
|
|
68
|
+
return [-1, 0];
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const Desc = ({ record }) => {
|
|
72
|
+
if (
|
|
73
|
+
record.action_url &&
|
|
74
|
+
record.action_url.includes('tuyaSmart://microApp')
|
|
75
|
+
) {
|
|
76
|
+
const queryString = record.action_url.replace(
|
|
77
|
+
'tuyaSmart://microApp?',
|
|
78
|
+
''
|
|
79
|
+
);
|
|
80
|
+
const searchParams = new URLSearchParams(queryString);
|
|
81
|
+
const universal_id = searchParams.get('universalId');
|
|
82
|
+
const path = searchParams.get('path');
|
|
83
|
+
const query = searchParams.get('query');
|
|
84
|
+
return (
|
|
85
|
+
<Text
|
|
86
|
+
ellipsis
|
|
87
|
+
style={{ color: 'var(--ant-primary-color)', cursor: 'pointer' }}
|
|
88
|
+
onClick={() => {
|
|
89
|
+
let pathUrl = '';
|
|
90
|
+
if (path) {
|
|
91
|
+
pathUrl = path;
|
|
92
|
+
if (atob(query)) {
|
|
93
|
+
pathUrl += `?${atob(query)}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const appId =
|
|
97
|
+
saasIdInfoList.find((item) => item.universal_id === universal_id)
|
|
98
|
+
.oem_micro_app_id || '';
|
|
99
|
+
appId &&
|
|
100
|
+
window.open(`${window.location.origin}/apps/${appId}${pathUrl}`);
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
{record.message_content}
|
|
104
|
+
</Text>
|
|
105
|
+
);
|
|
106
|
+
} else {
|
|
107
|
+
return <Text ellipsis>{record.message_content}</Text>;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const content = (
|
|
112
|
+
<List
|
|
113
|
+
className={cn(styles.resetList, 'main-app-message')}
|
|
114
|
+
header={
|
|
115
|
+
<span className={'main-app-message-title'}>
|
|
116
|
+
{t('notice.badge.title')}
|
|
117
|
+
</span>
|
|
118
|
+
}
|
|
119
|
+
itemLayout="horizontal"
|
|
120
|
+
dataSource={(list || []).slice(0, 4)}
|
|
121
|
+
footer={
|
|
122
|
+
<div className={cn(styles.footer, 'main-app-message-footer')}>
|
|
123
|
+
<span onClick={() => jumpNotice()}>{t('notice.badge.message')}</span>
|
|
124
|
+
</div>
|
|
125
|
+
}
|
|
126
|
+
renderItem={(item: Inotice) => (
|
|
127
|
+
<List.Item>
|
|
128
|
+
<List.Item.Meta
|
|
129
|
+
title={
|
|
130
|
+
<>
|
|
131
|
+
【
|
|
132
|
+
{item.message_type === '1'
|
|
133
|
+
? t('notice.typeSelect.alert')
|
|
134
|
+
: t('notice.typeSelect.message')}
|
|
135
|
+
】{item.create_time}
|
|
136
|
+
</>
|
|
137
|
+
}
|
|
138
|
+
description={<Desc record={item} />}
|
|
139
|
+
/>
|
|
140
|
+
</List.Item>
|
|
141
|
+
)}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<Popover
|
|
147
|
+
content={content}
|
|
148
|
+
trigger="hover"
|
|
149
|
+
visible={visible}
|
|
150
|
+
mouseLeaveDelay={0.3}
|
|
151
|
+
arrowPointAtCenter
|
|
152
|
+
placement="bottomRight"
|
|
153
|
+
onVisibleChange={onVisibleChange}
|
|
154
|
+
overlayStyle={{ width: 400 }}
|
|
155
|
+
overlayClassName={styles.resetPopover}
|
|
156
|
+
>
|
|
157
|
+
<div className={styles['wrap-badge']}>
|
|
158
|
+
<Badge
|
|
159
|
+
count={count}
|
|
160
|
+
size="small"
|
|
161
|
+
className={cn(styles.circle, {
|
|
162
|
+
[styles.multiple]: count > 9,
|
|
163
|
+
[styles.iconMargin]: count > 99,
|
|
164
|
+
})}
|
|
165
|
+
offset={offset(count)}
|
|
166
|
+
>
|
|
167
|
+
<a onClick={() => jumpNotice()}>
|
|
168
|
+
<IconFont
|
|
169
|
+
type="icon-bell"
|
|
170
|
+
className={cn(styles.icon, 'main-nav-text-color')}
|
|
171
|
+
/>
|
|
172
|
+
</a>
|
|
173
|
+
</Badge>
|
|
174
|
+
</div>
|
|
175
|
+
</Popover>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export default Notice;
|