gengx
This commit is contained in:
@@ -778,6 +778,7 @@ const showDatePicker = ref(false)
|
|||||||
const diagnosisId = ref(null)
|
const diagnosisId = ref(null)
|
||||||
const patientId = ref(null)
|
const patientId = ref(null)
|
||||||
const isAddMode = ref(false) // 新建模式
|
const isAddMode = ref(false) // 新建模式
|
||||||
|
const returnUrl = ref('') // 保存成功后跳回(如日常记录页)
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
@@ -1023,6 +1024,13 @@ const loadCardDetail = async () => {
|
|||||||
const options = currentPage.options || {}
|
const options = currentPage.options || {}
|
||||||
diagnosisId.value = options.id
|
diagnosisId.value = options.id
|
||||||
isAddMode.value = options.add === '1' || options.add === 1
|
isAddMode.value = options.add === '1' || options.add === 1
|
||||||
|
if (options.returnUrl) {
|
||||||
|
try {
|
||||||
|
returnUrl.value = decodeURIComponent(String(options.returnUrl))
|
||||||
|
} catch (e) {
|
||||||
|
returnUrl.value = String(options.returnUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const userData = uni.getStorageSync('userData')
|
const userData = uni.getStorageSync('userData')
|
||||||
patientId.value = userData?.diagnosis?.patient_id
|
patientId.value = userData?.diagnosis?.patient_id
|
||||||
@@ -1302,7 +1310,12 @@ const submitForm = async () => {
|
|||||||
}
|
}
|
||||||
uni.showToast({ title: isAddMode.value ? '创建成功' : '保存成功', icon: 'success' })
|
uni.showToast({ title: isAddMode.value ? '创建成功' : '保存成功', icon: 'success' })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.navigateBack()
|
const back = returnUrl.value
|
||||||
|
if (back && back.startsWith('/')) {
|
||||||
|
uni.redirectTo({ url: back })
|
||||||
|
} else {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
}, 1500)
|
}, 1500)
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: res.msg || '保存失败', icon: 'none' })
|
uni.showToast({ title: res.msg || '保存失败', icon: 'none' })
|
||||||
|
|||||||
@@ -212,7 +212,11 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<block v-if="!isInviteViewer">
|
<view v-if="authChecking && !isInviteViewer" class="page-gate-loading">
|
||||||
|
<text class="page-gate-loading-text">正在登录…</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<block v-if="!isInviteViewer && !authChecking">
|
||||||
<!-- 顶部 Hero(智能问候 + 今日状态)-->
|
<!-- 顶部 Hero(智能问候 + 今日状态)-->
|
||||||
<view class="hero">
|
<view class="hero">
|
||||||
<view class="hero-bg" />
|
<view class="hero-bg" />
|
||||||
@@ -1384,6 +1388,10 @@ const patientName = ref('')
|
|||||||
const age = ref(0)
|
const age = ref(0)
|
||||||
const gender = ref(0)
|
const gender = ref(0)
|
||||||
|
|
||||||
|
/** 登录 / 就诊卡门禁校验中(避免未登录时闪屏) */
|
||||||
|
const authChecking = ref(false)
|
||||||
|
let gateRedirected = false
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const cardsLoading = ref(false)
|
const cardsLoading = ref(false)
|
||||||
const cards = ref([])
|
const cards = ref([])
|
||||||
@@ -1767,10 +1775,104 @@ function getDayBpTrend(date) {
|
|||||||
return makeTrend(cur, prev.systolic, 0)
|
return makeTrend(cur, prev.systolic, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============ 登录 / 就诊卡门禁 ============
|
||||||
|
/** 进行中的登录任务(避免与 App.onLaunch 重复发起 mnpLogin,并保证业务接口在其之后) */
|
||||||
|
let authSessionPromise = null
|
||||||
|
|
||||||
|
function hasAuthToken() {
|
||||||
|
return !!String(uni.getStorageSync('token') || '').trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearAuthStorage() {
|
||||||
|
uni.removeStorageSync('token')
|
||||||
|
authSessionPromise = null
|
||||||
|
}
|
||||||
|
|
||||||
|
function wxLoginGetCode() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.login({
|
||||||
|
provider: 'weixin',
|
||||||
|
success: (res) => {
|
||||||
|
if (res && res.code) resolve(res.code)
|
||||||
|
else reject(new Error('微信登录未返回 code'))
|
||||||
|
},
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mnpLoginWithCode(code) {
|
||||||
|
const res = await proxy.apiUrl({
|
||||||
|
url: '/api/login/mnpLogin',
|
||||||
|
method: 'POST',
|
||||||
|
data: { code }
|
||||||
|
}, false)
|
||||||
|
if (res && res.code === 1 && res.data && res.data.token) {
|
||||||
|
uni.setStorageSync('token', res.data.token)
|
||||||
|
uni.setStorageSync('userData', res.data)
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
|
clearAuthStorage()
|
||||||
|
throw new Error(formatUserMessage(res?.msg, '登录失败'))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doWxLogin() {
|
||||||
|
const code = await wxLoginGetCode()
|
||||||
|
await mnpLoginWithCode(code)
|
||||||
|
return hasAuthToken()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 校验 token 有效;无效则清除并重新 mnpLogin(缺 token 时后端 code=0,不能当作已登录) */
|
||||||
|
async function verifyOrLogin() {
|
||||||
|
if (!hasAuthToken()) {
|
||||||
|
return doWxLogin()
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await proxy.apiUrl({ url: '/api/user/info', method: 'POST' }, false)
|
||||||
|
if (res && res.code === 1 && res.data) {
|
||||||
|
uni.setStorageSync('userData', res.data)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
/* 网络异常走重新登录 */
|
||||||
|
}
|
||||||
|
clearAuthStorage()
|
||||||
|
try {
|
||||||
|
return await doWxLogin()
|
||||||
|
} catch (e2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 登录完成后再调业务接口;并发调用共享同一 Promise */
|
||||||
|
async function ensureLoggedIn() {
|
||||||
|
if (authSessionPromise) {
|
||||||
|
return authSessionPromise
|
||||||
|
}
|
||||||
|
authSessionPromise = verifyOrLogin()
|
||||||
|
.then((ok) => {
|
||||||
|
if (!ok) authSessionPromise = null
|
||||||
|
return !!ok
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
authSessionPromise = null
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return authSessionPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectToCardEntry() {
|
||||||
|
if (gateRedirected) return
|
||||||
|
gateRedirected = true
|
||||||
|
const returnUrl = encodeURIComponent('/tongji/pages/index')
|
||||||
|
uni.redirectTo({
|
||||||
|
url: `/pages/Card/edit_card?add=1&returnUrl=${returnUrl}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ============ 就诊卡 ============
|
// ============ 就诊卡 ============
|
||||||
async function fetchCardList() {
|
async function fetchCardList() {
|
||||||
const token = uni.getStorageSync('token')
|
if (!hasAuthToken()) return []
|
||||||
if (!token) return
|
|
||||||
cardsLoading.value = true
|
cardsLoading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await proxy.apiUrl({
|
const res = await proxy.apiUrl({
|
||||||
@@ -1793,7 +1895,7 @@ async function fetchCardList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function applyCard(card) {
|
async function applyCard(card) {
|
||||||
if (!card) return
|
if (!card || !hasAuthToken()) return
|
||||||
diagnosisId.value = Number(card.id) || 0
|
diagnosisId.value = Number(card.id) || 0
|
||||||
patientId.value = Number(card.patient_id) || 0
|
patientId.value = Number(card.patient_id) || 0
|
||||||
patientName.value = card.patient_name || ''
|
patientName.value = card.patient_name || ''
|
||||||
@@ -1822,7 +1924,7 @@ async function onSelectCard(card) {
|
|||||||
|
|
||||||
// ============ 接口请求 ============
|
// ============ 接口请求 ============
|
||||||
async function fetchAll() {
|
async function fetchAll() {
|
||||||
if (!diagnosisId.value) return
|
if (!hasAuthToken() || !diagnosisId.value) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const { start, end } = currentRange.value
|
const { start, end } = currentRange.value
|
||||||
try {
|
try {
|
||||||
@@ -3095,24 +3197,33 @@ async function bootstrap(options) {
|
|||||||
options = options || {}
|
options = options || {}
|
||||||
const inviteCode = String(options.invite_code || '').trim()
|
const inviteCode = String(options.invite_code || '').trim()
|
||||||
if (options.from === 'share' && inviteCode) {
|
if (options.from === 'share' && inviteCode) {
|
||||||
|
authChecking.value = false
|
||||||
await bootstrapInviteViewer(inviteCode)
|
await bootstrapInviteViewer(inviteCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isInviteViewer.value = false
|
isInviteViewer.value = false
|
||||||
const passedDiagnosisId = Number(options.diagnosis_id || options.id || 0)
|
gateRedirected = false
|
||||||
diagnosisId.value = passedDiagnosisId
|
authChecking.value = true
|
||||||
patientId.value = Number(options.patient_id || 0)
|
|
||||||
if (options.patient_name) patientName.value = decodeURIComponent(options.patient_name)
|
|
||||||
if (options.age) age.value = Number(options.age) || 0
|
|
||||||
if (options.gender) gender.value = Number(options.gender) || 0
|
|
||||||
|
|
||||||
const token = uni.getStorageSync('token')
|
// 登录完成前不写 diagnosisId,避免模板/子流程提前打业务接口
|
||||||
if (!token) {
|
const passedDiagnosisId = Number(options.diagnosis_id || options.id || 0)
|
||||||
showUserToast('请先登录')
|
const passedPatientId = Number(options.patient_id || 0)
|
||||||
|
const passedPatientName = options.patient_name
|
||||||
|
? decodeURIComponent(String(options.patient_name))
|
||||||
|
: ''
|
||||||
|
const passedAge = Number(options.age) || 0
|
||||||
|
const passedGender = Number(options.gender) || 0
|
||||||
|
|
||||||
|
const loggedIn = await ensureLoggedIn()
|
||||||
|
if (!loggedIn || !hasAuthToken()) {
|
||||||
|
authChecking.value = false
|
||||||
|
showUserToast('登录失败,请稍后重试')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readUserContext()
|
||||||
|
|
||||||
const list = await fetchCardList()
|
const list = await fetchCardList()
|
||||||
|
|
||||||
if (Array.isArray(list) && list.length > 0) {
|
if (Array.isArray(list) && list.length > 0) {
|
||||||
@@ -3123,16 +3234,23 @@ async function bootstrap(options) {
|
|||||||
if (!target) target = list[0]
|
if (!target) target = list[0]
|
||||||
await applyCard(target)
|
await applyCard(target)
|
||||||
} else {
|
} else {
|
||||||
|
if (passedDiagnosisId) diagnosisId.value = passedDiagnosisId
|
||||||
|
if (passedPatientId) patientId.value = passedPatientId
|
||||||
|
if (passedPatientName) patientName.value = passedPatientName
|
||||||
|
if (passedAge) age.value = passedAge
|
||||||
|
if (passedGender) gender.value = passedGender
|
||||||
if (!diagnosisId.value || !patientId.value) {
|
if (!diagnosisId.value || !patientId.value) {
|
||||||
readUserContext()
|
readUserContext()
|
||||||
}
|
}
|
||||||
if (!diagnosisId.value) {
|
if (!diagnosisId.value) {
|
||||||
showUserToast('暂无就诊卡,请先创建')
|
authChecking.value = false
|
||||||
|
redirectToCardEntry()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchAll()
|
authChecking.value = false
|
||||||
|
await fetchAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
@@ -3152,6 +3270,7 @@ onShareAppMessage(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
if (authChecking.value || gateRedirected) return
|
||||||
if (!isInviteViewer.value && diagnosisId.value) {
|
if (!isInviteViewer.value && diagnosisId.value) {
|
||||||
loadFamilyLikeSummary()
|
loadFamilyLikeSummary()
|
||||||
}
|
}
|
||||||
@@ -3162,7 +3281,7 @@ onPullDownRefresh(async () => {
|
|||||||
if (isInviteViewer.value) {
|
if (isInviteViewer.value) {
|
||||||
const code = invitePreview.value.invite_code
|
const code = invitePreview.value.invite_code
|
||||||
if (code) await bootstrapInviteViewer(code)
|
if (code) await bootstrapInviteViewer(code)
|
||||||
} else {
|
} else if (await ensureLoggedIn()) {
|
||||||
await fetchAll()
|
await fetchAll()
|
||||||
}
|
}
|
||||||
uni.stopPullDownRefresh()
|
uni.stopPullDownRefresh()
|
||||||
@@ -3215,7 +3334,7 @@ function applyGamifyPayload(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function fetchGamifyState() {
|
async function fetchGamifyState() {
|
||||||
if (!diagnosisId.value) return
|
if (!hasAuthToken() || !diagnosisId.value) return
|
||||||
try {
|
try {
|
||||||
const res = await proxy.apiUrl({
|
const res = await proxy.apiUrl({
|
||||||
url: '/api/tcm/dailyGetGamify',
|
url: '/api/tcm/dailyGetGamify',
|
||||||
@@ -3725,7 +3844,7 @@ function closeWeeklyReport() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadFamilyLikeSummary() {
|
async function loadFamilyLikeSummary() {
|
||||||
if (!diagnosisId.value || isInviteViewer.value) return
|
if (!hasAuthToken() || !diagnosisId.value || isInviteViewer.value) return
|
||||||
const token = uni.getStorageSync('token')
|
const token = uni.getStorageSync('token')
|
||||||
if (!token) return
|
if (!token) return
|
||||||
try {
|
try {
|
||||||
@@ -3846,6 +3965,17 @@ async function onFamilyLike() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.page-gate-loading {
|
||||||
|
min-height: 60vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 80rpx 40rpx;
|
||||||
|
}
|
||||||
|
.page-gate-loading-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
.daily-page {
|
.daily-page {
|
||||||
/* Premium UI Color System & Variables - Teal-Emerald Healing Redesign */
|
/* Premium UI Color System & Variables - Teal-Emerald Healing Redesign */
|
||||||
--primary: #0d9488;
|
--primary: #0d9488;
|
||||||
|
|||||||
Reference in New Issue
Block a user