接入服务号模板推送通知
This commit is contained in:
@@ -9,6 +9,7 @@ export default defineAppConfig({
|
||||
"pages/sleep/index",
|
||||
"pages/sleep-schedule/index",
|
||||
"pages/family-invite/index",
|
||||
"pages/webview/index",
|
||||
],
|
||||
window: {
|
||||
backgroundTextStyle: "light",
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
startDeviceFirmwareUpdate,
|
||||
updateDeviceRole,
|
||||
} from '@/services/device'
|
||||
import { getWechatMpBindStatus, startWechatMpBind, WechatMpBindStatus } from '@/services/wechat-mp'
|
||||
import { useSystemBanner } from '@/components/system-banner/use-system-banner'
|
||||
import './index.scss'
|
||||
|
||||
@@ -104,6 +105,9 @@ export default function Sleep() {
|
||||
const [editingFamilyMember, setEditingFamilyMember] = useState<FamilyMember | null>(null)
|
||||
const [familyMemberDisplayName, setFamilyMemberDisplayName] = useState('')
|
||||
const [parentInfo, setParentInfo] = useState<Parent | null>(null)
|
||||
const [wechatMpStatus, setWechatMpStatus] = useState<WechatMpBindStatus | null>(null)
|
||||
const [isLoadingWechatMp, setIsLoadingWechatMp] = useState(false)
|
||||
const [isStartingWechatMpBind, setIsStartingWechatMpBind] = useState(false)
|
||||
const [isAuthorizingPhone, setIsAuthorizingPhone] = useState(false)
|
||||
const firmwareStatusPollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const firmwareStatusPollDeviceIdRef = useRef('')
|
||||
@@ -150,6 +154,7 @@ export default function Sleep() {
|
||||
void loadRoleData(nextBinding?.device_id)
|
||||
void loadFamilyData(nextBinding?.device_id)
|
||||
void loadCurrentDeviceCards(nextBinding?.device_id)
|
||||
void loadWechatMpStatus()
|
||||
} catch (error: any) {
|
||||
console.error('[manage] load failed:', error)
|
||||
Taro.showToast({
|
||||
@@ -161,6 +166,18 @@ export default function Sleep() {
|
||||
}
|
||||
}
|
||||
|
||||
const loadWechatMpStatus = async () => {
|
||||
setIsLoadingWechatMp(true)
|
||||
try {
|
||||
setWechatMpStatus(await getWechatMpBindStatus())
|
||||
} catch (error) {
|
||||
console.warn('[manage] wechat mp bind status load failed:', error)
|
||||
setWechatMpStatus(null)
|
||||
} finally {
|
||||
setIsLoadingWechatMp(false)
|
||||
}
|
||||
}
|
||||
|
||||
const loadCurrentParent = async (userId: number): Promise<Parent | null> => {
|
||||
try {
|
||||
return await getParent(userId)
|
||||
@@ -825,6 +842,41 @@ export default function Sleep() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleStartWechatMpBind = async () => {
|
||||
if (isStartingWechatMpBind) return
|
||||
|
||||
setIsStartingWechatMpBind(true)
|
||||
try {
|
||||
const result = await startWechatMpBind()
|
||||
const bindUrl = String(result.url || '').trim()
|
||||
if (!bindUrl) {
|
||||
throw new Error('未获取到服务号绑定链接')
|
||||
}
|
||||
Taro.navigateTo({
|
||||
url: `/pages/webview/index?url=${encodeURIComponent(bindUrl)}`,
|
||||
fail: () => {
|
||||
Taro.setClipboardData({
|
||||
data: bindUrl,
|
||||
success: () => {
|
||||
Taro.showModal({
|
||||
title: '服务号通知',
|
||||
content: '绑定链接已复制,请在微信里打开完成授权。',
|
||||
showCancel: false,
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error?.message || '服务号绑定失败',
|
||||
icon: 'none',
|
||||
})
|
||||
} finally {
|
||||
setIsStartingWechatMpBind(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleMenuClick = (item: MenuItem) => {
|
||||
if (item.disabled) return
|
||||
|
||||
@@ -878,6 +930,11 @@ export default function Sleep() {
|
||||
return
|
||||
}
|
||||
|
||||
if (item.name === '服务号通知') {
|
||||
handleStartWechatMpBind()
|
||||
return
|
||||
}
|
||||
|
||||
if (item.name === '解除设备绑定') {
|
||||
handleUnbind()
|
||||
}
|
||||
@@ -937,6 +994,13 @@ export default function Sleep() {
|
||||
: isLoadingFamily
|
||||
? '查询中'
|
||||
: `${familyInfo?.total || 1}/4 人`
|
||||
const wechatMpValue = isStartingWechatMpBind
|
||||
? '打开中'
|
||||
: isLoadingWechatMp
|
||||
? '查询中'
|
||||
: wechatMpStatus?.bound
|
||||
? '已开启'
|
||||
: '未绑定'
|
||||
const firmwareSubtitle = !binding?.device_id
|
||||
? '绑定设备后可查看系统版本'
|
||||
: isLoadingFirmware
|
||||
@@ -1018,6 +1082,14 @@ export default function Sleep() {
|
||||
arrow: true,
|
||||
disabled: !binding,
|
||||
},
|
||||
{
|
||||
icon: require('../../assets/tab-icons/rings.png'),
|
||||
iconBgClass: 'green',
|
||||
name: '服务号通知',
|
||||
value: wechatMpValue,
|
||||
arrow: true,
|
||||
disabled: isStartingWechatMpBind,
|
||||
},
|
||||
{
|
||||
icon: require('../../assets/tab-icons/broken-rings.png'),
|
||||
iconBgClass: 'red',
|
||||
|
||||
3
banban-mini/src/pages/webview/index.config.ts
Normal file
3
banban-mini/src/pages/webview/index.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '服务号通知',
|
||||
})
|
||||
21
banban-mini/src/pages/webview/index.scss
Normal file
21
banban-mini/src/pages/webview/index.scss
Normal file
@@ -0,0 +1,21 @@
|
||||
.webview-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
.webview-empty {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.webview-empty-text {
|
||||
font-size: 28px;
|
||||
line-height: 1.6;
|
||||
color: #6B7280;
|
||||
text-align: center;
|
||||
}
|
||||
23
banban-mini/src/pages/webview/index.tsx
Normal file
23
banban-mini/src/pages/webview/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Text, View, WebView } from '@tarojs/components'
|
||||
import { useRouter } from '@tarojs/taro'
|
||||
import './index.scss'
|
||||
|
||||
export default function WebviewPage() {
|
||||
const router = useRouter()
|
||||
const encodedUrl = String(router.params?.url || '').trim()
|
||||
const targetUrl = encodedUrl ? decodeURIComponent(encodedUrl) : ''
|
||||
|
||||
if (!targetUrl) {
|
||||
return (
|
||||
<View className='webview-empty'>
|
||||
<Text className='webview-empty-text'>链接无效</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='webview-page'>
|
||||
<WebView src={targetUrl} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
21
banban-mini/src/services/wechat-mp.ts
Normal file
21
banban-mini/src/services/wechat-mp.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { request } from './api'
|
||||
|
||||
export interface WechatMpBindStartResponse {
|
||||
url: string
|
||||
}
|
||||
|
||||
export interface WechatMpBindStatus {
|
||||
bound: boolean
|
||||
subscribed: boolean
|
||||
updated_at?: string | null
|
||||
}
|
||||
|
||||
export async function getWechatMpBindStatus(): Promise<WechatMpBindStatus> {
|
||||
return request<WechatMpBindStatus>('/banban/wechat-mp/bind/status')
|
||||
}
|
||||
|
||||
export async function startWechatMpBind(): Promise<WechatMpBindStartResponse> {
|
||||
return request<WechatMpBindStartResponse>('/banban/wechat-mp/bind/start', {
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user