| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <script setup lang="ts">
- import { onLoad } from '@dcloudio/uni-app';
- import { ref } from 'vue';
- import globalConfig from '@/config/global';
- import * as ww from '@wecom/jssdk';
- import {
- checkExternalUserInGroup,
- getCachedWecomVisitorProfile,
- syncExternalVisitorProfile,
- } from '@/api/wecom';
- import type { WecomVisitorProfile } from '@/api/wecom/types';
- const AUTH_PAGE = '/pages/index/index'
- const getCodeFromLocation = () => {
- if (typeof window === 'undefined') return ''
- const searchParams = new URLSearchParams(window.location.search)
- return searchParams.get('code') || ''
- }
- const stripOAuthCodeFromUrl = () => {
- if (typeof window === 'undefined') return
- const url = new URL(window.location.href)
- const hadOAuthParams = url.searchParams.has('code') || url.searchParams.has('state')
- if (!hadOAuthParams) return
- url.searchParams.delete('code')
- url.searchParams.delete('state')
- const nextSearch = url.searchParams.toString()
- const next = `${url.pathname}${nextSearch ? `?${nextSearch}` : ''}${url.hash}`
- window.history.replaceState({}, '', next)
- }
- const externalUserid = ref('');
- const unionidValue = ref('');
- const ownerId = ref('');
- const internalUserGetPopupVisible = ref(false);
- const internalUserGetJsonText = ref('');
- const applyVisitorFromSyncResult = (result: Awaited<ReturnType<typeof syncExternalVisitorProfile>>) => {
- externalUserid.value = result.externalUserId
- unionidValue.value = result.profile?.unionid || ''
- }
- const applyVisitorFromCachedProfile = (profile: WecomVisitorProfile) => {
- externalUserid.value = profile.externalUserId || ''
- unionidValue.value = profile.unionid || ''
- }
- const resolveExternalChatId = () =>
- new Promise<string>((resolve, reject) => {
- ww.register({
- corpId: globalConfig.corpid,
- agentId: globalConfig.agentId,
- jsApiList: ['getCurExternalChat'],
- });
- ww.getCurExternalChat({
- success(res) {
- if (res?.chatId) {
- resolve(res.chatId);
- return;
- }
- reject(new Error('chatId missing'));
- },
- fail(err) {
- reject(err);
- },
- });
- });
- const tryPrefetchOwnerInBackground = async () => {
- if (!unionidValue.value) return
- try {
- const chatId = await resolveExternalChatId();
- const outcome = await checkExternalUserInGroup(chatId, unionidValue.value);
- ownerId.value = outcome.ownerUserId;
- } catch {
- ownerId.value = '';
- }
- };
- const bootstrapWithCode = async (code: string) => {
- const result = await syncExternalVisitorProfile(code)
- if (!result.profile) {
- throw new Error('identity incomplete')
- }
- applyVisitorFromSyncResult(result)
- if (result.internalUserRaw) {
- internalUserGetJsonText.value = JSON.stringify(result.internalUserRaw, null, 2)
- internalUserGetPopupVisible.value = true
- }
- }
- const cacheLooksUsable = (cached: WecomVisitorProfile | null): cached is WecomVisitorProfile =>
- !!cached &&
- !!(cached.name || cached.mobile || cached.internalUserid || cached.externalUserId || cached.unionid)
- const goReauthorize = () => {
- uni.reLaunch({ url: AUTH_PAGE })
- }
- onLoad(async (option) => {
- const code = (option && option.code) || getCodeFromLocation()
- if (code) {
- try {
- await bootstrapWithCode(code)
- void tryPrefetchOwnerInBackground()
- } catch {
- const cached = getCachedWecomVisitorProfile()
- if (cacheLooksUsable(cached)) {
- applyVisitorFromCachedProfile(cached)
- void tryPrefetchOwnerInBackground()
- } else {
- goReauthorize()
- }
- } finally {
- stripOAuthCodeFromUrl()
- }
- return
- }
- const cached = getCachedWecomVisitorProfile()
- if (cacheLooksUsable(cached)) {
- applyVisitorFromCachedProfile(cached)
- void tryPrefetchOwnerInBackground()
- return
- }
- goReauthorize()
- })
- const getQuestionPage = () => {
- const ownerQuery = ownerId.value ? `?owner=${encodeURIComponent(ownerId.value)}` : ''
- uni.navigateTo({
- url: `/subPages/pages/reportProblems/index${ownerQuery}`
- })
- }
- </script>
- <template>
- <view class="box">
- <img class="box_bg_top" src="@/assets/bg_top.png" alt="" srcset="">
- <view class="container">
- <div class="shadow question-box" @click="getQuestionPage">
- <img class="box_img" src="@/assets/1.png" alt="" srcset="">
- <div class="box_title">问题上报</div>
- </div>
- <navigator url="/subPages/pages/reportServer/index" class="shadow">
- <img class="box_img" src="@/assets/2.png" alt="" srcset="">
- <div class="box_title">服务事项</div>
- </navigator>
- <navigator url="/subPages/pages/questions/index" class="shadow">
- <img class="box_img" src="@/assets/3.png" alt="" srcset="">
- <div class="box_title">问答库</div>
- </navigator>
- </view>
- <img class="box_bg_bottom" src="@/assets/bg_bottom.png" alt="" srcset="">
- <van-popup v-model:show="internalUserGetPopupVisible" round closeable class="user-get-popup">
- <view class="user-get-popup__header">getuserdetail 返回</view>
- <scroll-view scroll-y class="user-get-popup__content">
- <text selectable class="user-get-popup__json">{{ internalUserGetJsonText }}</text>
- </scroll-view>
- </van-popup>
- </view>
- </template>
- <style lang="scss" scoped>
- .box{
- position: relative;
- width: 100%;
- height: 100vh;
- background: #f6f6f6;
- &_bg_top{
- width: 100%;
- position: absolute;
- top: 0;
- }
- &_bg_bottom{
- position: absolute;
- bottom: 0;
- width: 100%;
- }
- &_title{
- font-size: 16px;
- font-weight: bold;
- color: #333;
- text-align: center;
- }
- &_img{
- width: 88px;
- height: 88px;
- }
- }
- .container {
- padding: 5%;
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 20px;
- position: absolute;
- top: 130px;
- z-index: 1;
- }
- .container uni-navigator {
- border-radius: 8px;
- padding: 5%;
- height: 0;
- padding-bottom: 100%;
- position: relative;
- display: flex;
- justify-content: center;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- background: #fff;
- }
- .container uni-navigator::before {
- content: "";
- display: block;
- padding-top: 90%;
- }
- .container uni-navigator-content {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .question-box {
- border-radius: 8px;
- padding: 5%;
- height: 0;
- padding-bottom: 100%;
- position: relative;
- display: flex;
- justify-content: center;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- background: #fff;
- flex-wrap: wrap;
- .box_title {
- width: 100%;
- }
- }
- .user-get-popup {
- width: 88vw;
- max-height: 75vh;
- padding: 20px 16px 16px;
- box-sizing: border-box;
- &__header {
- margin-bottom: 12px;
- padding-right: 24px;
- font-size: 16px;
- font-weight: 600;
- color: #333;
- }
- &__content {
- max-height: 60vh;
- background: #f7f8fa;
- border-radius: 8px;
- padding: 12px;
- box-sizing: border-box;
- }
- &__json {
- display: block;
- white-space: pre-wrap;
- word-break: break-all;
- font-size: 12px;
- line-height: 1.6;
- color: #333;
- }
- }
- </style>
|