128 lines
4.0 KiB
TypeScript
128 lines
4.0 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react';
|
||
import { Button, Text, View } from '@tarojs/components';
|
||
import Taro from '@tarojs/taro';
|
||
import styles from './index.module.scss';
|
||
import {
|
||
SUBSCRIBE_TEMPLATES,
|
||
bindWechat,
|
||
getWechatBinding,
|
||
updateWechatSubscribe,
|
||
type WechatBinding,
|
||
} from '@/api/wechat';
|
||
|
||
const NotificationPage: React.FC = () => {
|
||
const [binding, setBinding] = useState<WechatBinding | null>(null);
|
||
const [loading, setLoading] = useState(false);
|
||
|
||
const refresh = useCallback(async () => {
|
||
const data = await getWechatBinding().catch(() => ({ bound: false } as WechatBinding));
|
||
setBinding(data);
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
refresh();
|
||
}, [refresh]);
|
||
|
||
const handleBind = async () => {
|
||
setLoading(true);
|
||
try {
|
||
const { code } = await Taro.login();
|
||
if (!code) throw new Error('获取登录 code 失败');
|
||
await bindWechat(code);
|
||
Taro.showToast({ title: '微信绑定成功', icon: 'success' });
|
||
refresh();
|
||
} catch (err) {
|
||
Taro.showToast({
|
||
title: err instanceof Error ? err.message : '绑定失败',
|
||
icon: 'none',
|
||
});
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleSubscribe = async () => {
|
||
const configured = SUBSCRIBE_TEMPLATES.filter((t) => t.id);
|
||
if (configured.length === 0) {
|
||
Taro.showModal({
|
||
title: '模板未配置',
|
||
content: '订阅消息模板 ID 尚未配置,申请模板后填入 miniapp/src/api/wechat.ts 即可启用。',
|
||
showCancel: false,
|
||
confirmText: '知道了',
|
||
});
|
||
return;
|
||
}
|
||
setLoading(true);
|
||
try {
|
||
const res = await Taro.requestSubscribeMessage({
|
||
tmplIds: configured.map((t) => t.id),
|
||
entityIds: configured.map((t) => t.id),
|
||
});
|
||
for (const t of configured) {
|
||
if (res[t.id] === 'accept') {
|
||
await updateWechatSubscribe(t.key, true);
|
||
}
|
||
}
|
||
Taro.showToast({ title: '订阅设置已更新', icon: 'success' });
|
||
refresh();
|
||
} catch (err) {
|
||
Taro.showToast({
|
||
title: err instanceof Error ? err.message : '订阅失败',
|
||
icon: 'none',
|
||
});
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<View className={styles.page}>
|
||
<View className={styles.card}>
|
||
<Text className={styles.cardTitle}>微信订阅消息</Text>
|
||
<Text className={styles.cardDesc}>
|
||
绑定微信后,巡检风险(黄/橙/红)和告警发生时可通过订阅消息提醒你。注意:微信一次性订阅消息每次触发都需重新授权。
|
||
</Text>
|
||
<View className={styles.statusRow}>
|
||
<Text className={styles.statusLabel}>绑定状态</Text>
|
||
<Text className={binding?.bound ? styles.statusOk : styles.statusNo}>
|
||
{binding?.bound ? '已绑定' : '未绑定'}
|
||
</Text>
|
||
</View>
|
||
{binding?.bound && binding.openId ? (
|
||
<Text className={styles.openId}>openid:{binding.openId}</Text>
|
||
) : null}
|
||
{binding?.bound && binding.authorized && binding.authorized.length > 0 ? (
|
||
<Text className={styles.openId}>已授权:{binding.authorized.join('、')}</Text>
|
||
) : null}
|
||
<Button
|
||
className={`${styles.btn} ${styles.btnPrimary}`}
|
||
loading={loading}
|
||
onClick={handleBind}
|
||
>
|
||
绑定微信
|
||
</Button>
|
||
<Button
|
||
className={`${styles.btn} ${styles.btnPrimary}`}
|
||
loading={loading}
|
||
onClick={handleSubscribe}
|
||
>
|
||
授权订阅
|
||
</Button>
|
||
</View>
|
||
<View className={styles.card}>
|
||
<Text className={styles.cardTitle}>可订阅场景</Text>
|
||
{SUBSCRIBE_TEMPLATES.map((t) => (
|
||
<View key={t.key} className={styles.tplRow}>
|
||
<Text className={styles.tplLabel}>{t.label}</Text>
|
||
<Text className={t.id ? styles.tplReady : styles.tplPending}>
|
||
{t.id ? '已配置' : '待配置模板 ID'}
|
||
</Text>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|
||
|
||
export default NotificationPage;
|