Merge branch 'develop'

# Conflicts:
#	pages/my/my.vue
This commit is contained in:
haomingming 2025-09-25 10:31:52 +08:00
commit 36cda41b14
17 changed files with 897 additions and 105 deletions

View File

@ -18,6 +18,7 @@ import { STORAGE_KEY } from "@/utils/im/constants";
import { isWxApp } from "@/utils/im/index"; import { isWxApp } from "@/utils/im/index";
/** 国际化*/ /** 国际化*/
import { setLanguage } from "@/utils/im/i18n"; import { setLanguage } from "@/utils/im/i18n";
import BASE_URL from "@/utils/config.js"
// #ifdef APP-PLUS // #ifdef APP-PLUS
/** 推送插件 */ /** 推送插件 */
@ -53,7 +54,7 @@ export default {
let storage_accid=''; let storage_accid='';
if (process.env.UNI_PLATFORM == "h5") { if (process.env.UNI_PLATFORM == "h5") {
if (window.location.href.indexOf('dev') > -1) { if (window.location.href.indexOf('dev') > -1) {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
@ -64,7 +65,7 @@ export default {
envVersion envVersion
} = uni.getAccountInfoSync().miniProgram; } = uni.getAccountInfoSync().miniProgram;
if (envVersion == "release") { if (envVersion == "release") {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
@ -76,7 +77,7 @@ export default {
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App'); storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} }
} }

20
api/my_api.js Normal file
View File

@ -0,0 +1,20 @@
import {request} from '@/utils/request.js'
const my_api = {
isBoundWechat() {
return request('/expertAPI/isBoundWechatByUuid', {}, 'post', true);
},
unBindWechat(data) {
return request('/expertAPI/delWechatExpert', data, 'post', true);
},
bindWechat(data) {
return request('/expertAPI/addWechatExpert', data, 'post', true);
},
expertWxLogin(data,header) {
return request('/expertAPI/wechatLogin', data, 'post', true,'application/json',header);
}
}
export default my_api;

View File

@ -18,7 +18,10 @@
}, },
"modules" : { "modules" : {
"OAuth" : {}, "OAuth" : {},
"Payment" : {} "Payment" : {},
"Share" : {},
"Webview-x5" : {},
"UIWebview" : {}
}, },
/* */ /* */
"distribute" : { "distribute" : {
@ -53,6 +56,7 @@
"oauth" : { "oauth" : {
"weixin" : { "weixin" : {
"appid" : "wxbf3658f5e674667c", "appid" : "wxbf3658f5e674667c",
"appsecret" : "c4505a04a9910c65efea8e11ffc93f92",
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/" "UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
} }
}, },
@ -62,8 +66,16 @@
"appid" : "wxbf3658f5e674667c", "appid" : "wxbf3658f5e674667c",
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/" "UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
} }
},
"ad" : {},
"share" : {
"weixin" : {
"appid" : "wxbf3658f5e674667c",
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
} }
}, },
"speech" : {}
},
"splashscreen" : { "splashscreen" : {
"androidStyle" : "common" "androidStyle" : "common"
}, },

View File

@ -67,6 +67,13 @@
"bounce": "none" "bounce": "none"
} }
} }
},
{
"path": "pages/webview/webview",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
} }
], ],
"subPackages": [ "subPackages": [
@ -1209,7 +1216,7 @@
"list": [ "list": [
{ {
"name": "", "name": "",
"path": "pages_app/videoDetail/videoDetail", "path": "pages/index/index",
"query": "" "query": ""
} }
] ]

View File

@ -637,7 +637,7 @@
// } // }
}; };
// tabbar //tabbar
const testTabbar = () => { const testTabbar = () => {
nextTick(() => { nextTick(() => {
if (tabbarRef.value) { if (tabbarRef.value) {
@ -648,9 +648,9 @@
tabbarRef.value.showRedDot(2); tabbarRef.value.showRedDot(2);
// 3 // 3
setTimeout(() => { // setTimeout(() => {
tabbarRef.value.hideRedDot(2); // tabbarRef.value.hideRedDot(2);
}, 3000); // }, 3000);
} }
}); });
}; };

View File

@ -9,7 +9,17 @@
:style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}"> :style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}">
<view class="user-info" @click="goToPage('myInfo')"> <view class="user-info" @click="goToPage('myInfo')">
<image class="avatar" :src="avatar" mode="aspectFill"></image> <image class="avatar" :src="avatar" mode="aspectFill"></image>
<view class="user-info-content">
<text class="username">{{username}}</text> <text class="username">{{username}}</text>
<scroll-view class="honor_box" scroll-x="true" show-scrollbar="false">
<view class="honor_wrap">
<view class="honor_item" v-for="item in honor_list" :key="item.id">
<image class="honor_image" src="/static/wdsc.png" mode="aspectFill"></image>
<text class="honor_text">{{ item.nick_name }}</text>
</view>
</view>
</scroll-view>
</view>
</view> </view>
<!-- 统计数据 --> <!-- 统计数据 -->
@ -27,9 +37,12 @@
<text class="stats-label">患者送花数</text> <text class="stats-label">患者送花数</text>
</view> </view>
<view class="divder"></view> <view class="divder"></view>
<view class="signbox"> <view class="signbox" v-if="sign_in == 0" @click="onSignClick">
<view class="sign">签到</view> <view class="sign">签到</view>
</view> </view>
<view class="signbox_1" v-else @click="goToPage('pointMall')">
<view class="sign">{{ formatToChineseUnit(totalPoints) }}</view>
</view>
</view> </view>
</view> </view>
@ -117,13 +130,15 @@
</up-scroll-list> </up-scroll-list>
</view> </view>
<!-- #ifdef APP -->
<!-- 常用操作 --> <!-- 常用操作 -->
<view class="section"> <view class="section">
<view class="section-title">常用操作</view> <view class="section-title">常用操作</view>
<view class="operation-grid"> <view class="operation-grid">
<view class="operation-item" @click="goToPage('wechatUnbind')"> <view class="operation-item" @click="goToPage('wechatUnbind')">
<up-image :src="wxjbImg" width="48rpx" height="48rpx"></up-image> <up-image :src="wxjbImg" width="48rpx" height="48rpx"></up-image>
<text>微信解绑</text> <text v-if="isBoundWechat">微信解绑</text>
<text v-else>微信绑定</text>
</view> </view>
<view class="operation-item" @click="goToPage('changePhone')"> <view class="operation-item" @click="goToPage('changePhone')">
<up-image :src="ghsjhImg" width="48rpx" height="48rpx"></up-image> <up-image :src="ghsjhImg" width="48rpx" height="48rpx"></up-image>
@ -135,10 +150,11 @@
</view> </view>
<view class="operation-item" @click="showVersion"> <view class="operation-item" @click="showVersion">
<up-image :src="versionImg" width="48rpx" height="48rpx"></up-image> <up-image :src="versionImg" width="48rpx" height="48rpx"></up-image>
<text>V4.1.4</text> <text>V{{version}}</text>
</view> </view>
</view> </view>
</view> </view>
<!-- #endif -->
<view class="setbox"> <view class="setbox">
<!-- 福利卡兑换 --> <!-- 福利卡兑换 -->
<view class="sectioncell benefit-section"> <view class="sectioncell benefit-section">
@ -209,6 +225,7 @@
import { import {
onShow onShow
} from "@dcloudio/uni-app"; } from "@dcloudio/uni-app";
import version from '@/utils/version.js'
import hzshImg from "@/static/hzsh.png" import hzshImg from "@/static/hzsh.png"
import hzfzImg from "@/static/hzfz.png" import hzfzImg from "@/static/hzfz.png"
import qfxxImg from "@/static/qfxz.png" import qfxxImg from "@/static/qfxz.png"
@ -236,6 +253,7 @@
import cyyhk from "@/static/cyhhk.png" import cyyhk from "@/static/cyhhk.png"
import settingImg from "@/static/setting.png" import settingImg from "@/static/setting.png"
import api from '@/api/api.js' import api from '@/api/api.js'
import my_api from '@/api/my_api.js'
import navTo from "@/utils/navTo" import navTo from "@/utils/navTo"
import linkUrl from "@/utils/docUrl" import linkUrl from "@/utils/docUrl"
// //
@ -248,7 +266,9 @@
const consultCount = ref(0) const consultCount = ref(0)
const flowerCount = ref(0) const flowerCount = ref(0)
const myInfoBackGround = ref('') const myInfoBackGround = ref('')
const totalPoints = ref(0)
const sign_in = ref(0)
const honor_list = ref([])
// storage // storage
const getUserInfoFromStorage = () => { const getUserInfoFromStorage = () => {
try { try {
@ -263,35 +283,79 @@
} }
} }
//
const onSignClick = async () => {
try {
//
const res = await api.addBonusPointsN({
score_type:1
});
if (res && res.code ==1) {
//
sign_in.value = 1;
uni.showToast({
title: '签到成功,获得'+res.bonuspoints+'积分',
icon: 'none'
});
} else {
uni.showToast({
title: res?.msg || '签到失败',
icon: 'none'
});
}
} catch (error) {
console.error('签到失败:', error);
uni.showToast({
title: '签到失败,请重试',
icon: 'none'
});
}
};
const fetchMyInfo = async () => { const fetchMyInfo = async () => {
try { try {
const res = await api.getMyInfo({}) const res = await api.getMyInfo({})
if (res && res.code === 200 && res.data) { if (res && res.code === 200 && res.data) {
const data = res.data const data = res.data
myInfoBackGround.value = data.myInfoBackGround; myInfoBackGround.value = data.myInfoBackGround;
followupCount.value = data.follow_patient_num || data.relationPatientNum || 0 followupCount.value = data.expert_apply_num || 0
consultCount.value = data.consult_total || data.consultCount || 0 consultCount.value = data.consult_total_num || 0
flowerCount.value = data.give_flower_num || data.flowerCount || 0 flowerCount.value = data.ping_flowewr_num || 0
totalPoints.value = data.total_points || 0
sign_in.value = data.sign_in || 0
honor_list.value = data.honor_list || []
} }
} catch (e) { } catch (e) {
console.error('获取我的信息失败', e) console.error('获取我的信息失败', e)
} }
} }
// /亿
const formatToChineseUnit = (value, fractionDigits = 1) => {
if (value == null || value === '' || isNaN(Number(value))) return value;
const num = Number(value);
const sign = num < 0 ? '-' : '';
const abs = Math.abs(num);
if (abs < 10000) {
return sign + String(abs);
}
if (abs < 100000000) {
const v = (abs / 10000).toFixed(fractionDigits);
return sign + (v.indexOf('.') > -1 ? v.replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1') : v) + '万';
}
const v = (abs / 100000000).toFixed(fractionDigits);
return sign + (v.indexOf('.') > -1 ? v.replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1') : v) + '亿';
}
// //
const toggleFontSize = () => { const toggleFontSize = () => {
isLargeFont.value = !isLargeFont.value; isLargeFont.value = !isLargeFont.value;
console.log('切换字体大小:', isLargeFont.value ? '大字版' : '普通版'); console.log('切换字体大小:', isLargeFont.value ? '大字版' : '普通版');
}; };
const checkin = () => {
console.log('签到');
uni.showToast({
title: '签到成功',
icon: 'none'
});
};
const goToPage = (page) => { const goToPage = (page) => {
console.log('跳转到页面:', page); console.log('跳转到页面:', page);
let url=""; let url="";
@ -333,6 +397,9 @@
case 'myPoints': case 'myPoints':
url="/pages_app/myPoint/myPoint" url="/pages_app/myPoint/myPoint"
break; break;
case 'pointMall':
url="/pages_goods/pointMall/pointMall"
break;
case 'myBenefits': case 'myBenefits':
url="/pages_app/myWelfare/myWelfare" url="/pages_app/myWelfare/myWelfare"
break; break;
@ -382,7 +449,7 @@
const showVersion = () => { const showVersion = () => {
uni.showModal({ uni.showModal({
title: '版本信息', title: '版本信息',
content: '当前版本V4.1.4', content: '当前版本V'+version,
showCancel: false showCancel: false
}); });
}; };
@ -411,10 +478,19 @@
}) })
} }
const getIsBoundWechat = async () => {
const res = await my_api.isBoundWechat()
console.log(res)
if (res.code === 200 && res.data) {
isBoundWechat.value = res.data
}
}
const isBoundWechat = ref(false)
onShow(() => { onShow(() => {
console.log('我的页面显示'); console.log('我的页面显示');
getUserInfoFromStorage() // storage getUserInfoFromStorage() // storage
fetchMyInfo() // API fetchMyInfo() // API
getIsBoundWechat()
}); });
</script> </script>
@ -468,11 +544,57 @@
} }
.user-info-content {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10rpx;
.username { .username {
color: $white; color: $white;
font-size: 36rpx; font-size: 36rpx;
font-weight: bold; font-weight: bold;
} }
.honor_box {
width: 500rpx;
/* 根据设计可调整宽度,使内容可横向滚动 */
white-space: nowrap;
}
.honor_wrap {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 10rpx;
}
.honor_item {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 10rpx;
flex: 0 0 auto;
padding: 6rpx 12rpx;
border: 2rpx solid rgba(255, 255, 255, 0.6);
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.08);
}
.honor_image {
width: 24rpx;
height: 24rpx;
}
.honor_text {
font-size: 24rpx;
color: $white;
}
}
}
} }
.stats-section { .stats-section {
@ -514,6 +636,26 @@
} }
} }
.signbox_1 {
position: absolute;
right: 0;
top: 54rpx;
width: 160rpx;
height: 56rpx;
display: flex;
align-items: center;
border: 1rpx solid #fc564a;
border-radius: 30rpx 0 0 30rpx;
background: #fff url("@/static/qd_bg.9.png")no-repeat 0 0;
background-size: 57rpx 56rpx;
.sign {
margin-left: 60rpx;
font-size: 28rpx;
color: #fc564a;
}
}
.stats-item { .stats-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -546,7 +688,6 @@
gap: 8rpx; gap: 8rpx;
font-size: 28rpx; font-size: 28rpx;
} }
}
// section // section
.section { .section {

18
pages/webview/webview.vue Normal file
View File

@ -0,0 +1,18 @@
<template>
<web-view :src="url"></web-view>
</template>
<script>
export default {
data() {
return {
url: ''
}
},
onLoad(item) {
// 使web-view
this.url = decodeURIComponent(item.url)
// console.log(this.url)
}
}
</script>

View File

@ -108,6 +108,10 @@
import checkImg from "@/static/login_new_unselect.png" import checkImg from "@/static/login_new_unselect.png"
import checkOnImg from "@/static/login_new_select.png" import checkOnImg from "@/static/login_new_select.png"
import api from "@/api/api.js" import api from "@/api/api.js"
import my_api from "@/api/my_api.js"
import BASE_URL from "@/utils/config.js"
import { createSignedPostData } from '@/utils/sign.js'
import navTo from "@/utils/navTo"
const customStyle = reactive({ const customStyle = reactive({
height: "100rpx", height: "100rpx",
@ -135,7 +139,7 @@
console.log('一键登录'); console.log('一键登录');
uni.showLoading({ uni.showLoading({
title: '登录中...' title: '登录中2...'
}); });
// //
@ -173,33 +177,89 @@
return; return;
} }
console.log('微信登录'); // #ifdef APP
wx.login({ uni.showToast({
success(res) { title: '微信登录 11',
if (res.code) { icon: 'none'
// res.code openId, sessionKey, unionId });
api.expertWxLogin(res.code).then((data) => { // #endif
console.log(data) uni.login({
if (data.data.openid) { provider: 'weixin',
if (process.env.NODE_ENV === 'development') { success: function (loginRes) {
uni.setStorageSync('DEV_APPID', data.data.openid); //
} else { uni.getUserInfo({
uni.setStorageSync('AUTH_APPID', data.data.openid); provider: 'weixin',
} success: async function(info) {
} // , info.authResult
// #ifdef APP
let openid = "" uni.showToast({
if (process.env.NODE_ENV === 'development') { title: info.userInfo.nickName,
openid = uni.getStorageSync('DEV_APPID'); icon: 'none'
} else { });
openid = uni.getStorageSync('AUTH_APPID'); // #endif
const wechat_user_info = {
openid:info.userInfo.openId,
unionid:info.userInfo.unionId,
nickname:info.userInfo.nickName,
} }
console.log("openid: ", openid) const { postData, sign } = await createSignedPostData({
wechat_user_info: JSON.stringify(wechat_user_info),
current_spec: "uniapp"
}) })
// #ifdef APP
uni.showToast({
title: sign,
icon: 'none'
});
// #endif
my_api.expertWxLogin(postData,{
sign:sign
}).then(res=>{
uni.showToast({
title: '登录成功',
icon: 'success'
})
if (BASE_URL.indexOf('dev') == -1) {
uni.setStorageSync('AUTH_TOKEN_App',res.data.access_token);
uni.setStorageSync('AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
} else { } else {
console.log('登录失败!' + res.errMsg); uni.setStorageSync('DEV_AUTH_TOKEN_App', res.data.access_token);
uni.setStorageSync('DEV_AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('DEV_AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
} }
//
navTo({
url: '/pages/index/index'
})
}).catch(err=>{
console.log(err)
uni.showToast({
title: res.data.msg || '登录失败',
icon: 'none'
})
})
}
})
},
fail: function (err) {
//
// err.code
console.log(err)
// #ifdef APP
uni.showToast({
title: err,
icon: 'none'
});
// #endif
} }
}); });

View File

@ -102,7 +102,10 @@
import eyeOpenImg from "@/static/eye_open.png" import eyeOpenImg from "@/static/eye_open.png"
import eyeCloseImg from "@/static/eye_close.png" import eyeCloseImg from "@/static/eye_close.png"
import api from "@/api/api.js" import api from "@/api/api.js"
import my_api from "@/api/my_api.js";
import BASE_URL from "@/utils/config.js"; import BASE_URL from "@/utils/config.js";
import { createSignedPostData } from '@/utils/sign.js'
import navTo from "@/utils/navTo"
const customStyle = reactive({ const customStyle = reactive({
height: "100rpx", height: "100rpx",
@ -284,11 +287,68 @@
return; return;
} }
console.log('微信登录'); console.log('微信登录 11');
uni.login({
provider: 'weixin',
success: function (loginRes) {
//
uni.getUserInfo({
provider: 'weixin',
success: async function(info) {
// , info.authResult
const wechat_user_info = {
openid:info.userInfo.openId,
unionid:info.userInfo.unionId,
nickname:info.userInfo.nickName,
}
const { postData, sign } = await createSignedPostData({
wechat_user_info: JSON.stringify(wechat_user_info),
current_spec: "uniapp"
})
my_api.expertWxLogin(postData,{
sign:sign
}).then(res=>{
uni.showToast({ uni.showToast({
title: '微信登录功能开发中', title: '登录成功',
icon: 'success'
})
if (BASE_URL.indexOf('dev') == -1) {
uni.setStorageSync('AUTH_TOKEN_App',res.data.access_token);
uni.setStorageSync('AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
} else {
uni.setStorageSync('DEV_AUTH_TOKEN_App', res.data.access_token);
uni.setStorageSync('DEV_AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('DEV_AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
}
//
navTo({
url: '/pages/index/index'
})
}).catch(err=>{
console.log(err)
uni.showToast({
title: res.data.msg || '登录失败',
icon: 'none' icon: 'none'
})
})
}
})
},
fail: function (err) {
//
// err.code
console.log(err)
}
}); });
}; };
// //

View File

@ -17,6 +17,7 @@
<!-- 设置选项列表 --> <!-- 设置选项列表 -->
<view class="settings-list"> <view class="settings-list">
<!-- #ifdef APP -->
<!-- 消息通知 --> <!-- 消息通知 -->
<view class="setting-item" @click="toggleNotification"> <view class="setting-item" @click="toggleNotification">
<text class="setting-text">消息通知</text> <text class="setting-text">消息通知</text>
@ -25,7 +26,7 @@
</view> </view>
</view> </view>
<!-- #endif -->
<!-- 修改登录密码 --> <!-- 修改登录密码 -->
<view class="setting-item" @click="goToChangePassword"> <view class="setting-item" @click="goToChangePassword">
<text class="setting-text">修改登录密码</text> <text class="setting-text">修改登录密码</text>
@ -37,27 +38,27 @@
<text class="setting-text">更换手机号</text> <text class="setting-text">更换手机号</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- #ifdef APP -->
<!-- 版本更新 --> <!-- 版本更新 -->
<view class="setting-item" @click="checkUpdate"> <view class="setting-item" @click="checkUpdate">
<text class="setting-text">版本更新</text> <text class="setting-text">版本更新</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- #endif -->
<!-- 关于肝胆相照 --> <!-- 关于肝胆相照 -->
<view class="setting-item" @click="goToAbout"> <view class="setting-item" @click="goToPage('https://doc.igandan.com/app/html/about/2017/about2.html')">
<text class="setting-text">关于肝胆相照</text> <text class="setting-text">关于肝胆相照</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- 分享肝胆相照APP --> <!-- 分享肝胆相照APP -->
<view class="setting-item" @click="shareApp"> <view class="setting-item" @click="shareToggle">
<text class="setting-text">分享肝胆相照APP</text> <text class="setting-text">分享肝胆相照APP</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- 肝胆相照直播群 --> <!-- 肝胆相照直播群 -->
<view class="setting-item" @click="goToLiveGroup"> <view class="setting-item" @click="goToPage('https://wx.igandan.com/qun/gdxzqun')">
<text class="setting-text">肝胆相照直播群</text> <text class="setting-text">肝胆相照直播群</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
@ -67,7 +68,7 @@
<text class="setting-text">微信关联</text> <text class="setting-text">微信关联</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- #ifdef APP -->
<!-- 清除缓存 --> <!-- 清除缓存 -->
<view class="setting-item" @click="clearCache"> <view class="setting-item" @click="clearCache">
<text class="setting-text">清除缓存</text> <text class="setting-text">清除缓存</text>
@ -76,7 +77,7 @@
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
</view> </view>
<!-- #endif -->
<!-- 意见反馈 --> <!-- 意见反馈 -->
<view class="setting-item" @click="goToFeedback"> <view class="setting-item" @click="goToFeedback">
<text class="setting-text">意见反馈</text> <text class="setting-text">意见反馈</text>
@ -90,13 +91,13 @@
</view> </view>
<!-- 注册协议 --> <!-- 注册协议 -->
<view class="setting-item" @click="goToAgreement"> <view class="setting-item" @click="goToPage('https://doc.igandan.com/app/integral/expert_zcxy.html')">
<text class="setting-text">注册协议</text> <text class="setting-text">注册协议</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
<!-- 隐私政策 --> <!-- 隐私政策 -->
<view class="setting-item" @click="goToPrivacy"> <view class="setting-item" @click="goToPage('https://doc.igandan.com/app/integral/permission_expert.html')">
<text class="setting-text">隐私政策</text> <text class="setting-text">隐私政策</text>
<uni-icons type="right" size="20" color="#999"></uni-icons> <uni-icons type="right" size="20" color="#999"></uni-icons>
</view> </view>
@ -106,13 +107,45 @@
<view class="logout-section"> <view class="logout-section">
<button class="logout-btn" @click="logout">退出登录</button> <button class="logout-btn" @click="logout">退出登录</button>
</view> </view>
<view>
<!-- 分享弹窗 -->
<uni-popup ref="shareRef" type="bottom" safeArea backgroundColor="#fff">
<view class="share-popup">
<view class="share-title">分享到</view>
<view class="share-content">
<view class="share-item" @click="shareToWechat">
<view class="share-icon wechat-icon">
<text class="share-icon-text"></text>
</view>
<text class="share-text">微信</text>
</view>
<view class="share-item" @click="shareToMoments">
<view class="share-icon moments-icon">
<text class="share-icon-text"></text>
</view>
<text class="share-text">朋友圈</text>
</view>
<view class="share-item" @click="shareToWeibo">
<view class="share-icon weibo-icon">
<text class="share-icon-text"></text>
</view>
<text class="share-text">新浪微博</text>
</view>
</view>
<view class="share-cancel" @click="closeShare">
<text>取消</text>
</view>
</view>
</uni-popup>
</view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
import { onShow } from "@dcloudio/uni-app"; import { onShow } from "@dcloudio/uni-app";
import navTo from "@/utils/navTo"
// //
const goBack = () => { const goBack = () => {
uni.navigateBack(); uni.navigateBack();
@ -127,6 +160,11 @@
}); });
}; };
const goToPage = (url) => {
uni.navigateTo({
url: '/pages/webview/webview?url=' + url
});
};
// //
const goToChangePassword = () => { const goToChangePassword = () => {
uni.navigateTo({ uni.navigateTo({
@ -157,13 +195,154 @@
}); });
}; };
const shareRef = ref()
// APP // APP
const shareApp = () => { const shareToggle = () => {
uni.showToast({ shareRef.value.open()
title: '分享APP', }
icon: 'none'
//
const closeShare = () => {
shareRef.value.close()
}
//
const shareToWechat = () => {
// #ifdef APP-PLUS
// 使
uni.share({
provider: "weixin",
scene: "WXSceneSession",
type: 1,
summary: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com",
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
}); });
}; // #endif
// #ifdef H5
// H5
if (navigator.share) {
navigator.share({
title: '肝胆相照APP',
text: '专业的医疗健康平台,快来下载体验吧!',
url: 'https://www.igandan.com'
}).then(() => {
uni.showToast({
title: '分享成功',
icon: 'success'
})
}).catch(() => {
uni.showToast({
title: '分享失败',
icon: 'none'
})
})
} else {
//
uni.setClipboardData({
data: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com',
success: () => {
uni.showToast({
title: '已复制到剪贴板',
icon: 'success'
})
}
})
}
// #endif
// #ifdef MP-WEIXIN
//
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
// #endif
closeShare()
}
//
const shareToMoments = () => {
// #ifdef APP-PLUS
uni.share({
provider: "weixin",
scene: "WXSceneTimeline",
type: 1,
summary: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com",
success: function (res) {
console.log("success:" + JSON.stringify(res));
},
fail: function (err) {
console.log("fail:" + JSON.stringify(err));
}
});
// #endif
// #ifdef H5
//
uni.setClipboardData({
data: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com',
success: () => {
uni.showToast({
title: '已复制到剪贴板,可分享到朋友圈',
icon: 'success'
})
}
})
// #endif
// #ifdef MP-WEIXIN
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
})
// #endif
closeShare()
}
//
const shareToWeibo = () => {
// #ifdef APP-PLUS
plus.share.sendWithSystem({
type: 'text',
content: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com'
}, () => {
uni.showToast({
title: '分享成功',
icon: 'success'
})
}, (err) => {
console.log('分享失败:', err)
uni.showToast({
title: '分享失败',
icon: 'none'
})
})
// #endif
// #ifdef H5
//
uni.setClipboardData({
data: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接https://www.igandan.com',
success: () => {
uni.showToast({
title: '已复制到剪贴板,可分享到微博',
icon: 'success'
})
}
})
// #endif
closeShare()
}
// //
const goToLiveGroup = () => { const goToLiveGroup = () => {
@ -247,7 +426,7 @@
<style scoped> <style scoped>
.content { .content {
background-color: #f5f5f5; background-color: #f5f5f5;
min-height: 100vh; /* min-height: 100vh; */
padding-bottom: 160rpx; /* 为固定的退出登录按钮留出空间 */ padding-bottom: 160rpx; /* 为固定的退出登录按钮留出空间 */
} }
@ -331,10 +510,10 @@
/* 退出登录按钮样式 */ /* 退出登录按钮样式 */
.logout-section { .logout-section {
position: fixed; /* position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0; */
padding: 30rpx; padding: 30rpx;
background-color: #fff; background-color: #fff;
border-top: 1rpx solid #e0e0e0; border-top: 1rpx solid #e0e0e0;
@ -357,4 +536,83 @@
.logout-btn:active { .logout-btn:active {
background-color: #fff0f0; background-color: #fff0f0;
} }
/* 分享弹窗样式 */
.share-popup {
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding: 40rpx 0 0;
}
.share-title {
text-align: center;
font-size: 32rpx;
color: #333;
margin-bottom: 40rpx;
font-weight: 500;
}
.share-content {
display: flex;
justify-content: space-around;
padding: 0 40rpx 40rpx;
}
.share-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.share-icon {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
}
.wechat-icon {
background-color: #07C160;
}
.moments-icon {
background-color: #07C160;
}
.weibo-icon {
background-color: #E6162D;
}
.qq-icon {
background-color: #12B7F5;
}
.share-icon-text {
font-size: 50rpx;
color: #fff;
font-weight: bold;
}
.share-text {
font-size: 24rpx;
color: #666;
}
.share-cancel {
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
border-top: 1rpx solid #f0f0f0;
font-size: 32rpx;
color: #333;
}
.share-cancel:active {
background-color: #f5f5f5;
}
</style> </style>

View File

@ -107,6 +107,11 @@
import pwdImg from "@/static/pwd.png" import pwdImg from "@/static/pwd.png"
import { Base64 } from 'js-base64'; import { Base64 } from 'js-base64';
import { md5 } from 'js-md5'; import { md5 } from 'js-md5';
import BASE_URL from "@/utils/config.js";
import my_api from "@/api/my_api.js";
import { createSignedPostData } from '@/utils/sign.js'
import navTo from "@/utils/navTo"
const customStyle = reactive({ const customStyle = reactive({
height: "100rpx", height: "100rpx",
fontSize: "36rpx", fontSize: "36rpx",
@ -388,8 +393,8 @@
} }
}; };
// //
const onWechatLogin = () => { const onWechatLogin = () => {
if (!isAgreed.value) { if (!isAgreed.value) {
uni.showToast({ uni.showToast({
title: '请先同意相关协议', title: '请先同意相关协议',
@ -398,11 +403,68 @@
return; return;
} }
console.log('微信登录'); console.log('微信登录 11');
uni.login({
provider: 'weixin',
success: function (loginRes) {
//
uni.getUserInfo({
provider: 'weixin',
success: async function(info) {
// , info.authResult
const wechat_user_info = {
openid:info.userInfo.openId,
unionid:info.userInfo.unionId,
nickname:info.userInfo.nickName,
}
const { postData, sign } = await createSignedPostData({
wechat_user_info: JSON.stringify(wechat_user_info),
current_spec: "uniapp"
})
my_api.expertWxLogin(postData,{
sign:sign
}).then(res=>{
uni.showToast({ uni.showToast({
title: '微信登录功能开发中', title: '登录成功',
icon: 'success'
})
if (BASE_URL.indexOf('dev') == -1) {
uni.setStorageSync('AUTH_TOKEN_App',res.data.access_token);
uni.setStorageSync('AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
} else {
uni.setStorageSync('DEV_AUTH_TOKEN_App', res.data.access_token);
uni.setStorageSync('DEV_AUTH_YX_ACCID_App', res.data.YX_accid);
uni.setStorageSync('DEV_AUTH_YX_TOKEN_App', res.data.YX_token);
uni.setStorageSync('userInfo', res.data);
}
//
navTo({
url: '/pages/index/index'
})
}).catch(err=>{
console.log(err)
uni.showToast({
title: res.data.msg || '登录失败',
icon: 'none' icon: 'none'
})
})
}
})
},
fail: function (err) {
//
// err.code
console.log(err)
}
}); });
}; };
// //

View File

@ -13,7 +13,19 @@
></uni-nav-bar> ></uni-nav-bar>
<!-- 微信卡片 --> <!-- 微信卡片 -->
<view class="card"> <view class="card" v-if="isBoundWechat">
<view class="wx-left">
<up-image :src="wxIcon" width="120rpx" height="120rpx" mode="aspectFill"></up-image>
</view>
<view class="wx-center">
<view class="wx-title">微信</view>
<view class="wx-sub">{{ nickname }}</view>
</view>
<view class="wx-right">
<button class="bind-btn" @click="onUnBind">解绑</button>
</view>
</view>
<view class="card" v-else>
<view class="wx-left"> <view class="wx-left">
<up-image :src="wxIcon" width="120rpx" height="120rpx" mode="aspectFill"></up-image> <up-image :src="wxIcon" width="120rpx" height="120rpx" mode="aspectFill"></up-image>
</view> </view>
@ -41,15 +53,106 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
import {onShow} from "@dcloudio/uni-app";
import wxIcon from '@/static/wechat.png'; import wxIcon from '@/static/wechat.png';
import my_api from '@/api/my_api.js'
const isBoundWechat = ref(false)
const unionid = ref('')
const openid = ref('')
const nickname = ref('')
const goBack = () => { const goBack = () => {
uni.navigateBack(); uni.navigateBack();
}; };
const onBind = () => { const onBind = () => {
uni.showToast({ title: '去绑定', icon: 'none' }); uni.login({
}; provider: 'weixin',
success: function (loginRes) {
//
uni.getUserInfo({
provider: 'weixin',
success: function(info) {
// , info.authResult
console.log(info.userInfo)
my_api.bindWechat({openid:info.userInfo.openId,unionid:info.userInfo.unionId,nickname:info.userInfo.nickName}).then(res=>{
console.log("111: ",res)
if (res.code === 200 || res.code === '200') {
uni.showToast({
title: '绑定成功',
icon: 'success'
})
isBoundWechat.value = true
unionid.value = info.userInfo.unionId
openid.value = info.userInfo.openId
nickname.value = info.userInfo.nickName
}else{
uni.showToast({
title: res.msg || '绑定失败',
icon: 'none'
})
}
}).catch(err=>{
console.log(err)
uni.showToast({
title: '绑定失败',
icon: 'none'
})
})
}
})
},
fail: function (err) {
//
// err.code
console.log(err)
}
});
}
const getIsBoundWechat = async () => {
const res = await my_api.isBoundWechat()
console.log(res)
if (res.code === 200 || res.code === '200') {
isBoundWechat.value = res.isBound == 1
unionid.value = res.unionid
openid.value = res.openid
nickname.value = res.nickname
}
}
const onUnBind = async () => {
uni.showModal({
title: '解绑微信',
content: '确定要解绑微信吗?',
success: (res) => {
if (res.confirm) {
my_api.unBindWechat({"unionid":unionid.value}).then(res=>{
console.log(res)
if (res.code === 200 || res.code === '200') {
uni.showToast({
title: '解绑成功',
icon: 'success'
})
isBoundWechat.value = false
}
else{
uni.showToast({
title: res.msg || '解绑失败',
icon: 'none'
})
}
getIsBoundWechat()
})
}
}
});
}
onShow(() => {
getIsBoundWechat()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -17,7 +17,7 @@ const imLogin = async ()=>{
let storage_accid=''; let storage_accid='';
if (process.env.UNI_PLATFORM == "h5") { if (process.env.UNI_PLATFORM == "h5") {
if (window.location.href.indexOf('dev') > -1) { if (window.location.href.indexOf('dev') > -1) {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
@ -28,7 +28,7 @@ const imLogin = async ()=>{
envVersion envVersion
} = uni.getAccountInfoSync().miniProgram; } = uni.getAccountInfoSync().miniProgram;
if (envVersion == "release") { if (envVersion == "release") {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
@ -40,7 +40,7 @@ const imLogin = async ()=>{
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App'); storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
} else { } else {
storage_accid=uni.getetStorageSync('AUTH_YX_ACCID_App'); storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App'); storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
} }
} }

View File

@ -1,4 +1,4 @@
let client_type='' let client_type='A'
// #ifdef MP-WEIXIN // #ifdef MP-WEIXIN
client_type="M" client_type="M"

View File

@ -46,7 +46,7 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
} }
let defaultData={} let defaultData={}
let freeList=['/manager/getSystemTimeStamp','/expertAPI/smsLogin','/login/mobile','/expertAPI/login','/expertAPI/index'] let freeList=['/manager/getSystemTimeStamp','/expertAPI/smsLogin','/login/mobile','/expertAPI/login','/expertAPI/index','/expertAPI/wechatLogin']
let postData={ let postData={
...data ...data
} }
@ -119,6 +119,7 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
}else if (res.data.code == 401 || res.data.code == 403 || res.data.code == }else if (res.data.code == 401 || res.data.code == 403 || res.data.code ==
405 || res.data.code == 406 || res.data.code == 37006) { 405 || res.data.code == 406 || res.data.code == 37006) {
uni.hideLoading();
uni.redirectTo({ uni.redirectTo({
url: '/pages_app/login/login' url: '/pages_app/login/login'
}); });

49
utils/sign.js Normal file
View File

@ -0,0 +1,49 @@
import api from '@/api/api.js'
import sortObj from '@/utils/sort'
import version from '@/utils/version.js'
import client_type from '@/utils/client_type.js'
import { Base64 } from 'js-base64'
import { md5 } from 'js-md5'
function formatString(obj) {
let concatenated = ''
for (const key in obj) {
if (concatenated) {
concatenated += key + obj[key]
} else {
concatenated = key + obj[key]
}
}
return concatenated
}
function toBase64Url(str) {
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
}
export async function createSignedPostData(extraData = {}) {
try {
const res = await api.getTimeStamp()
const timestamp = res.data.timestamp.toString()
const basePayload = {
version: version,
user_uuid: '',
client_type: client_type,
timestamp: timestamp
}
const postData = { ...basePayload, ...extraData }
const sorted = sortObj(postData)
const str1 = formatString(sorted).replace(' ', '')
const str2 = str1 + md5(timestamp)
const str3 = md5(str2)
const sign = toBase64Url(Base64.encode(str3))
return { postData, sign }
} catch (err) {
console.log(err)
return { postData: {}, sign: '' }
}
}
export default { createSignedPostData }