feat(mobile-h5): add WeChat notify setup page with follow and bind steps
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
b79ff2d830
commit
df42730cc8
2 files changed
+310
No files matched your search
@@ -72,6 +72,14 @@
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/wechat-notify/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "开启微信通知",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/pdf-preview/index",
|
||||
"style": {
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
<template>
|
||||
<view class="notify-page">
|
||||
<view class="notify-body">
|
||||
<!-- 步骤 1:关注服务号 -->
|
||||
<view class="step-card" :class="{ 'is-done': step1Done }">
|
||||
<view class="step-hd">
|
||||
<view class="step-num">1</view>
|
||||
<view class="step-main">
|
||||
<view class="step-title">关注服务号</view>
|
||||
<view class="step-desc">
|
||||
关注后才能接收微信模板消息。可跳转服务号主页,或长按识别二维码。
|
||||
</view>
|
||||
</view>
|
||||
<text class="step-badge" :class="{ 'is-done': step1Done }">
|
||||
{{ step1Done ? '已完成' : '未完成' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="step-actions">
|
||||
<button class="btn btn-primary" @click="onFollow">
|
||||
{{ step1Done ? '重新打开关注页' : '去关注' }}
|
||||
</button>
|
||||
<view v-if="showQr && !step1Done" class="qr-box">
|
||||
<image
|
||||
class="qr-img"
|
||||
:src="mpQrcodeUrl"
|
||||
mode="aspectFit"
|
||||
show-menu-by-longpress
|
||||
/>
|
||||
<text class="qr-tip">长按识别关注</text>
|
||||
<button class="btn btn-ghost" @click="onConfirmFollowed">我已关注</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 步骤 2:绑定账号 -->
|
||||
<view class="step-card" :class="{ 'is-done': step2Done }">
|
||||
<view class="step-hd">
|
||||
<view class="step-num">2</view>
|
||||
<view class="step-main">
|
||||
<view class="step-title">绑定当前账号</view>
|
||||
<view class="step-desc">
|
||||
将服务号身份与系统账号关联,审批待办 / 抄送才能推送到你。
|
||||
</view>
|
||||
</view>
|
||||
<text class="step-badge" :class="{ 'is-done': step2Done }">
|
||||
{{ step2Done ? '已完成' : '未完成' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="step-actions">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="!step1Done || step2Done"
|
||||
@click="onBind"
|
||||
>
|
||||
{{
|
||||
step2Done
|
||||
? '已绑定'
|
||||
: step1Done
|
||||
? '去绑定'
|
||||
: '请先完成步骤 1'
|
||||
}}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
fetchMpBindStatus,
|
||||
getUser,
|
||||
forceRelogin,
|
||||
getToken
|
||||
} from '../../../utils/auth.js'
|
||||
import {
|
||||
isFollowConfirmed,
|
||||
setFollowConfirmed,
|
||||
resolveStepDone
|
||||
} from '../../../utils/mp-follow-confirm.js'
|
||||
import { MP_GH_USERNAME, MP_QRCODE_URL } from '../../../utils/config.js'
|
||||
|
||||
function currentUserId() {
|
||||
const u = getUser() || {}
|
||||
return u.id || u.userId || u.username || ''
|
||||
}
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
bound: false,
|
||||
followConfirmed: false,
|
||||
showQr: false,
|
||||
mpQrcodeUrl: MP_QRCODE_URL,
|
||||
step1Done: false,
|
||||
step2Done: false
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
if (!getToken()) {
|
||||
forceRelogin('请先登录')
|
||||
return
|
||||
}
|
||||
this.followConfirmed = isFollowConfirmed(currentUserId())
|
||||
this.refreshBind()
|
||||
},
|
||||
methods: {
|
||||
applySteps() {
|
||||
const r = resolveStepDone({
|
||||
bound: this.bound,
|
||||
followConfirmed: this.followConfirmed
|
||||
})
|
||||
this.step1Done = r.step1Done
|
||||
this.step2Done = r.step2Done
|
||||
},
|
||||
async refreshBind() {
|
||||
try {
|
||||
const res = await fetchMpBindStatus()
|
||||
this.bound = !!(res && res.bound)
|
||||
} catch (_) {
|
||||
this.bound = false
|
||||
}
|
||||
this.applySteps()
|
||||
},
|
||||
onFollow() {
|
||||
const username = (MP_GH_USERNAME || '').trim()
|
||||
const openProfile =
|
||||
typeof wx !== 'undefined' && typeof wx.openOfficialAccountProfile === 'function'
|
||||
if (openProfile && username) {
|
||||
wx.openOfficialAccountProfile({
|
||||
username,
|
||||
fail: () => {
|
||||
this.showQr = true
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
this.showQr = true
|
||||
},
|
||||
onConfirmFollowed() {
|
||||
setFollowConfirmed(currentUserId(), true)
|
||||
this.followConfirmed = true
|
||||
this.showQr = false
|
||||
this.applySteps()
|
||||
uni.showToast({ title: '已标记关注', icon: 'none' })
|
||||
},
|
||||
onBind() {
|
||||
if (!this.step1Done || this.step2Done) return
|
||||
uni.navigateTo({ url: '/pages/oa/mp-bind/index' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.notify-page {
|
||||
min-height: 100vh;
|
||||
background: #f5f8f7;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.notify-body {
|
||||
padding: 28rpx 24rpx 56rpx;
|
||||
}
|
||||
|
||||
.step-card {
|
||||
background: #fff;
|
||||
border: 1px solid #dcebe4;
|
||||
border-radius: 28rpx;
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
&.is-done {
|
||||
border-color: #b7ebcf;
|
||||
background: linear-gradient(180deg, #f6fffb 0%, #fff 60%);
|
||||
}
|
||||
}
|
||||
|
||||
.step-hd {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.step-num {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
background: #0a9f6d;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-card.is-done .step-num {
|
||||
background: #189b65;
|
||||
}
|
||||
|
||||
.step-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.step-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
line-height: 1.35;
|
||||
color: #1f2a26;
|
||||
}
|
||||
|
||||
.step-desc {
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6b7b74;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.step-badge {
|
||||
margin-left: auto;
|
||||
font-size: 22rpx;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #eef2f0;
|
||||
color: #6b7b74;
|
||||
flex-shrink: 0;
|
||||
line-height: 1.4;
|
||||
|
||||
&.is-done {
|
||||
background: #e9f9f2;
|
||||
color: #087f57;
|
||||
}
|
||||
}
|
||||
|
||||
.step-actions {
|
||||
margin-top: 24rpx;
|
||||
padding-left: 76rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
appearance: none;
|
||||
border: 0;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx 28rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
min-height: 80rpx;
|
||||
line-height: 1.3;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #0a9f6d;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
|
||||
&[disabled] {
|
||||
background: #a7d7c4;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
margin-top: 20rpx;
|
||||
background: #fff;
|
||||
color: #087f57;
|
||||
border: 1px solid #dcebe4;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.qr-box {
|
||||
margin-top: 20rpx;
|
||||
padding: 24rpx;
|
||||
border-radius: 24rpx;
|
||||
border: 1px dashed #a7f3d0;
|
||||
background: #f8fffb;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-img {
|
||||
display: block;
|
||||
width: 280rpx;
|
||||
height: 280rpx;
|
||||
margin: 0 auto;
|
||||
border-radius: 16rpx;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.qr-tip {
|
||||
display: block;
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6b7b74;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user