Jelajahi Sumber

微信授权登录

Xiao_123 1 bulan lalu
induk
melakukan
0cfe23d27c

+ 13 - 0
api/common.js

@@ -1,5 +1,18 @@
 import request from "@/utils/request"
 
+// 微信用户注册
+export const weChatRegister = (data) => {
+  return request({
+    url: '/api/parse/wechat-register',
+    method: "POST",
+    data,
+    custom: {
+      showLoading: false,
+      showError: true
+    }
+  })
+}
+
 // 刷新令牌
 export const refreshToken = (refreshToken) => {
   return request({

+ 27 - 1
api/drawLots.js

@@ -1,6 +1,6 @@
 import request from "@/utils/request"
 
-// 获取日历
+// 获取黄历信息
 export const getDrawLots = (params) => {
 	return request({
 		url: '/api/parse/get-calendar-info',
@@ -11,4 +11,30 @@ export const getDrawLots = (params) => {
 			auth: false
 		}
 	})
+}
+
+// 获取手账记录
+export const getCalendarRecord = (params) => {
+	return request({
+		url: '/api/parse/get-calendar-record',
+		method: 'GET',
+		params,
+		custom: {
+			showLoading: false,
+			auth: false
+		}
+	})
+}
+
+// 保存手账记录
+export const saveCalendarRecord = (data) => {
+	return request({
+		url: '/api/parse/save-calendar-record',
+		method: 'POST',
+		data,
+		custom: {
+			showLoading: false,
+			auth: false
+		}
+	})
 }

+ 8 - 4
components/uni-calendar/components/uni-calendar/uni-calendar-item.vue

@@ -20,7 +20,7 @@
 
 			<text class="uni-calendar-item__weeks-box-text" :class="{
 				'uni-calendar-item--isDay-text': weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay && !weeks.extraInfo?.color,
 				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay && !weeks.extraInfo?.color,
 				'uni-calendar-item--before-checked':weeks.beforeMultiple,
 				'uni-calendar-item--multiple': weeks.multiple,
@@ -39,7 +39,7 @@
 
 			<text v-if="lunar" class="uni-calendar-item__weeks-lunar-text" :class="{
 				'uni-calendar-item--isDay-text':weeks.isDay,
-				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay && !weeks.extraInfo?.color,
 				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay && !weeks.extraInfo?.color,
 				'uni-calendar-item--before-checked':weeks.beforeMultiple,
 				'uni-calendar-item--multiple': weeks.multiple,
@@ -59,8 +59,12 @@
 				}">{{weeks.extraInfo.info}}</text> -->
 		</view>
 		
-		<view v-if="weeks.extraInfo && weeks.extraInfo.url" style="text-align: center; margin-top: 10px;">
-			<image :src="weeks.extraInfo.url" style="width: 20px; height: 20px;" @click="handleClickImg(weeks)" />
+		<view v-if="weeks.extraInfo" style="text-align: center; margin-top: 10px;">
+			<image
+				src="https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png"
+				style="width: 20px; height: 20px;"
+				@click="handleClickImg(weeks)"
+			/>
 		</view>
 	</view>
 

+ 15 - 15
layout/components/authModal/login/index.vue

@@ -10,7 +10,7 @@
             class="send-button MiSans-Medium"
             @click="showProtocolToast"
             >
-            手机号快捷登录
+            微信授权注册/登录
           </button>
           <button 
           v-else
@@ -20,7 +20,7 @@
             open-type="getPhoneNumber"
             @getphonenumber="getPhoneNumber"
             >
-            手机号快捷登录
+            微信授权注册/登录
           </button>
         </view>
 
@@ -44,11 +44,11 @@
 
 <script setup>
 import { ref } from 'vue'
-import { userStore } from '@/store/user'
+import { weChatRegister } from '@/api/common'
+import { closeAuthModal } from '@/hooks/useModal'
 
-const useUserStore = userStore()
 const phoneNumberLoading = ref(false)
-const protocol = ref(false)
+const protocol = ref(true)
 
 const changeType = ref('login')
 
@@ -64,7 +64,7 @@ const showProtocolToast = () => {
   uni.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
 }
 
-// 微信登录
+// 微信登录/注册
 const getPhoneNumber = async (e) => {
   if (e?.detail?.errMsg !== 'getPhoneNumber:ok') {
     uni.showToast({ title: '微信登录失败', icon: 'none' })
@@ -74,16 +74,16 @@ const getPhoneNumber = async (e) => {
   phoneNumberLoading.value = true
 
   wx.login({
-    success: async (result) => {
-      console.log(result, '微信登录返回res', e)
-      const wxLoginCode = result?.code || ''
-      const query = {
-        loginCode: wxLoginCode,
-        phoneCode: e.detail.code,
-        state: e.detail.encryptedData,
+    success: async (res) => {
+      try {
+        const { result } = await weChatRegister({ wechat_code: res?.code })
+        console.log(result, '用户注册返回结果')
+        uni.setStorageSync('wechat_user', result)
+        uni.$emit && uni.$emit('auth:login', result)
+        closeAuthModal()
+      } finally {
+        phoneNumberLoading.value = false
       }
-      // await useUserStore.handleSmsLogin(query, current.value)
-      phoneNumberLoading.value = false
     },
     fail:(res)=> { 
       phoneNumberLoading.value = false

+ 103 - 88
pages/drawLots/index.vue

@@ -1,30 +1,41 @@
 <template>
   <layout-page>
 		<view style="position: relative;">
+			<!-- 日历 -->
 			<Calendar
+				:date="date"
 				class="uni-calendar--hook"
 				:selected="selected"
 				:lunar="true"
 				:range="false"
 				:showMonth="true"
 				@change="handleChange"
+				@monthSwitch="handleMonthSwitch"
 			/>
 
-			<view class="journal" v-if="journalData && Object.keys(journalData).length > 0">
+			<button 
+        size="default" 
+        class="send-button" 
+        @click="handleClear"
+       >
+				清除缓存
+				</button>
+
+			<!-- 手账 -->
+			<view class="journal" v-if="calendarRecord && calendarRecord.length > 0">
 				<view class="title">手账</view>
-				<uni-card @tap="handleUpdateJournal(journalData.id, journalData.description)">
-					<view class="d-flex align-center">
-						<view class="line"></view>
-						<view class="date">{{ journalData.date }}</view>
-					</view>
-					<view class="description ss-m-t-15">{{ journalData.description }}</view>
+				<uni-card v-for="(val, index) in calendarRecord" :key="index" @tap="handleUpdateJournal(val)">
+					<uni-section :title="val.date" type="line"></uni-section>
+					<view class="description ss-m-t-15">{{ val.notes }}</view>
 				</uni-card>
 			</view>
 
+			<!-- 添加手账 -->
 			<view class="add-btn" @tap="handleAddJournal">
 				<uni-icons type="plusempty" size="30" color="#fff"></uni-icons>
 			</view>
 
+			<!-- 黄历弹窗 -->
 			<uni-popup ref="popupRef" type="dialog">
 				<view class="popupContent">
 					<view class="content-box">
@@ -57,7 +68,7 @@
 									<view class="label">五行</view>
 									<view class="value">{{ calendarInfo.wuxing }}</view>
 								</view>
-								<view style="border-top: 1px solid #c2a08c; height: 1px; width: 100%;"></view>
+								<view class="border"></view>
 								<view class="padding">
 									<view class="label">吉神</view>
 									<view class="value">{{ calendarInfo.jishen }}</view>
@@ -74,7 +85,7 @@
 									<view class="label">冲煞</view>
 									<view class="value">{{ calendarInfo.chongsha }}</view>
 								</view>
-								<view style="border-top: 1px solid #c2a08c; height: 1px; width: 100%;"></view>
+								<view class="border"></view>
 								<view class="padding">
 									<view class="label">凶神</view>
 									<view class="value">{{ calendarInfo.xiongshen }}</view>
@@ -93,26 +104,21 @@
 </template>
 
 <script setup>
-import { onLoad } from '@dcloudio/uni-app'
-import { ref } from 'vue'
-import Calendar from '@/components/uni-calendar/components/uni-calendar/uni-calendar.vue'
-import { getDrawLots } from '@/api/drawLots.js'
-import layoutPage from '@/layout'
-import { showAuthModal, closeAuthModal } from '@/hooks/useModal'
-
-const colorDict = {
-	'白': '#FAFAFA',
-	'黑': '#212121',
-	'绿': '#43A047',
-	'红': '#F44336',
-	'黄': '#FDD835'
-}
+	import { onLoad, onShow } from '@dcloudio/uni-app'
+	import { ref } from 'vue'
+	import Calendar from '@/components/uni-calendar/components/uni-calendar/uni-calendar.vue'
+	import { getDrawLots } from '@/api/drawLots.js'
+	import layoutPage from '@/layout'
+	import { showAuthModal } from '@/hooks/useModal'
+	import { getCalendarRecord } from '@/api/drawLots.js'
 
-const journalData = ref({
-	id: 1,
-	date: '2025-08-27',
-	description: '南京金陵酒店管理有限公司隶属于金陵饭店集团酒店业务板块,成立于2004年,已成为品牌化、连锁化、规模化发展的酒店管理专业机构。着力打造多层级品牌体系,构建涵盖高中端精品商务酒店、休闲度假酒店、主题文化酒店、智能公寓酒店等多样化产品线。公司秉承金陵饭店“细意浓情”服务理念,融合国际标准、传承中国文化、深耕本土特色,依托总部强大的支撑体系,为在管运营酒店赋能,为业主提供超值服务。“金陵”相继摘取中国质量奖——“全国质量工作先进单位标兵”,荣膺中国质量领域政府性荣誉——首届“中国质量奖”提名奖,十度蝉联世界品牌实验室评定的全球服务业奖项——“五星钻石奖”,位列中国饭店集团前30强,保持全国国有高星级酒店集团前三甲。国家旅游局在《饭店星评标准访查示范》中,将金陵饭店的管理模式和服务标准作为五星级酒店示范样板并拍摄成教学片,向全国酒店业推广。'
-})
+	const colorDict = {
+		'白': '#FAFAFA',
+		'黑': '#212121',
+		'绿': '#43A047',
+		'红': '#F44336',
+		'黄': '#FDD835'
+	}
 
 	function getDate(date, AddDayCount = 0) {
 		if (!date) {
@@ -122,9 +128,9 @@ const journalData = ref({
 			date = date.replace(/-/g, '/')
 		}
 		const dd = new Date(date)
-
+		
 		dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
-
+		
 		const y = dd.getFullYear()
 		const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
 		const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
@@ -136,58 +142,49 @@ const journalData = ref({
 			day: dd.getDay()
 		}
 	}
-
+	
+	const date = ref(getDate(new Date()).fullDate)
+	// 设置日期选中内容
 	const selected = ref([])
-	const setSelectedDates = () => {
-		selected.value = [ 
-			{
-				date: getDate(new Date(),-20).fullDate,
-				color: '#d3e3fd',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			},
-			{
-				date: getDate(new Date(),-16).fullDate,
-				color: '#f8bbd0',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			},
-			{
-				date: getDate(new Date(),-12).fullDate,
-				color: '#3bb19b',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			},
-			{
-				date: getDate(new Date(),-7).fullDate,
-				color: '#facd89',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			},
-			{
-				date: getDate(new Date(),-3).fullDate,
-				color: '#d7ccc8',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			},
-			{
-				date: getDate(new Date(),-2).fullDate,
-				color: '#c5cae9',
-				url: 'https://menduner.citupro.com:3443/dev/2dbc20a5db2122e399b491638889ba9f8aea4e1c7a44463ee0df40b25f85b8cc.png'
-			}
-		]
-	}
 
+	// 登录信息
+	const userInfo = ref(uni.getStorageSync('wechat_user') || {})
 	onLoad(() => {
-		// showAuthModal()
-		// closeAuthModal()
+		if (!userInfo.value || !userInfo.value?.openid) return showAuthModal()
+		getCalendarData(date.value.slice(0, 7), 'onLoad')
+	})
 
-		// 设置选中项
-		setTimeout(() => {
-			setSelectedDates()
-		}, 2000)
+	onShow(() => {
+		// 刷新一次本地登录信息,防止 onLoad 时未拿到最新登录态
+		const latestUser = uni.getStorageSync('wechat_user')
+		if (latestUser?.openid && latestUser?.openid !== userInfo.value?.openid) {
+			userInfo.value = latestUser
+		}
+		if (userInfo.value?.openid) getCalendarData(date.value.slice(0, 7), 'onShow')
 	})
 
+	// 监听登录成功事件,立刻刷新数据
+	uni.$off && uni.$off('auth:login')
+	uni.$on && uni.$on('auth:login', (user) => {
+		userInfo.value = user || uni.getStorageSync('wechat_user')
+		if (userInfo.value?.openid) {
+			getCalendarData(date.value.slice(0, 7), 'event:auth:login')
+		}
+	})
 
+	const handleClear = () => {
+		selected.value = []
+		calendarRecord.value = []
+		userInfo.value = {}
+		uni.clearStorageSync()
+		showAuthModal()
+	}
+	
+	// 点击日期查看黄历信息
 	const popupRef = ref()
-
 	const calendarInfo = ref({})
 	const handleChange = async (e) => {
+		date.value = e.fulldate
 		if (e.isBackToday) return // 点击左上角“今日”按钮不弹窗
 
 		try {
@@ -201,6 +198,25 @@ const journalData = ref({
 		}
 	}
 
+	// 获取手账记录
+	const calendarRecord = ref([])
+	const getCalendarData = async (month_key, type) => {
+		console.log(type, '获取手账记录类型')
+		try {
+			const { result } = await getCalendarRecord({ month_key, openid: userInfo.value.openid })
+			calendarRecord.value = result?.calendar_content || []
+			selected.value = calendarRecord.value?.length ? calendarRecord.value.map((item) => {
+				return { date: item.date, color: '#f8bbd0' }
+			}) : []
+		} catch {}
+	}
+
+	// 切换月份
+	const handleMonthSwitch = (e) => {
+		console.log(e, '切换月份')
+		getCalendarData(`${e.year}-${e.month < 10 ? '0' + e.month : e.month}`, 'monthSwitch')
+	}
+
 	const handleClose = () => {
 		popupRef.value.close()
 		calendarInfo.value = {}
@@ -208,15 +224,21 @@ const journalData = ref({
 
 	// 添加手账
 	const handleAddJournal = () => {
+		let url = `/pages/drawLots/journal?date=${date.value}`
+		const index = calendarRecord.value.findIndex((item) => item.date === date.value)
+		if (index > -1) {
+			uni.showToast({ title: '手账已存在,可进行编辑', icon: 'none' })
+			url += `&notes=${calendarRecord.value[index].notes}`
+		}
 		uni.navigateTo({
-			url: '/pages/drawLots/journal'
+			url
 		})
 	}
 
 	// 更新手账
-	const handleUpdateJournal = (id, text) => {
+	const handleUpdateJournal = (val) => {
 		uni.navigateTo({
-			url: `/pages/drawLots/journal?id=${id}&text=${text}`
+			url: `/pages/drawLots/journal?date=${val.date}&notes=${val.notes}`
 		})
 	}
 </script>
@@ -234,25 +256,13 @@ $size: 25px;
 	margin-top: 30rpx;
 	padding-bottom: 100px;
 	.title {
-		// color: #2979ff;
 		color: #999;
 		margin: 0 30px;
 	}
-	.date {
-		font-size: 17px;
-		font-weight: bold;
-	}
-	.line {
-		width: 5px;
-		height: 15px;
-		border-radius: 4px;
-		background-color: #2979ff;
-		margin-right: 10px;
-	}
 	.description {
 		display: -webkit-box;
 		-webkit-box-orient: vertical;
-		-webkit-line-clamp: 6;
+		-webkit-line-clamp: 2;
 		overflow: hidden;
 	}
 }
@@ -331,6 +341,11 @@ $size: 25px;
 			.padding {
 				padding: 10px;
 			}
+			.border {
+				border-top: 1px solid #c2a08c;
+				height: 1px;
+				width: 100%;
+			}
 		}
 	}
 	.luckyColor {

+ 81 - 6
pages/drawLots/journal.vue

@@ -1,10 +1,13 @@
 <template>
   <view class="ss-p-x-30 ss-p-y-30">
+		<view class="ss-m-b-30">
+      <uni-easyinput v-model="date" type="text" disabled />
+    </view>
 		<uni-easyinput type="textarea" v-model="journal" clearable maxlength="500" autoHeight placeholder="请输入要记录的内容" />
     <view style="text-align: end;" class="ss-m-t-10 color-999">{{ journal?.length || 0 }}/500</view>
 		<view class="f-horizon-center">
       <button
-				v-if="editId"
+				v-if="isEdit"
 				size="default"
 				class="delete-button commonBtnStyle" 
 				:disabled="deleteDisabled"
@@ -12,7 +15,7 @@
 			>删 除</button>
       <button 
         size="default" 
-        :class="{'save-button': editId, 'commonBtnStyle': editId, 'send-button': !editId}" 
+        :class="{'save-button': isEdit, 'commonBtnStyle': isEdit, 'send-button': !isEdit}" 
         @click="handleSubmit"
         :disabled="disabled"
        >保 存</button>
@@ -23,20 +26,92 @@
 <script setup>
 import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
+import { getCalendarRecord, saveCalendarRecord } from '@/api/drawLots.js'
 
-const editId = ref(null)
+const isEdit = ref(false)
+const date = ref(null)
 const journal = ref(null)
 const disabled = ref(false)
 const deleteDisabled = ref(false)
+const userInfo = ref(uni.getStorageSync('wechat_user'))
+
+// 获取手账记录
+const calendarRecord = ref([])
+const getCalendarData = async (month_key) => {
+	try {
+		const { result } = await getCalendarRecord({ month_key, openid: userInfo.value.openid })
+		calendarRecord.value = result?.calendar_content || []
+	} catch {}
+}
 
 onLoad((options) => {
-  editId.value = options?.id || null
-  journal.value = options?.text || null
+  date.value = options?.date || null
+  journal.value = options?.notes || null
+  isEdit.value = options?.notes ? true : false
+
+  getCalendarData(options?.date.slice(0, 7))
 })
 
-const handleDelete = () => {}
+// 删除
+const handleDelete = async () => {
+  const index = calendarRecord.value.findIndex((item) => item.date === date.value)
+  if (index === -1) return uni.showToast({ title: '删除失败,当前数据不存在', icon: 'none', duration: 2000 })
+  calendarRecord.value.splice(index, 1)
+  deleteDisabled.value = true
+  disabled.value = true
 
+  try {
+    await saveCalendarRecord({ openid: userInfo.value.openid, month_key: date.value.slice(0, 7), calendar_content: calendarRecord.value })
+    uni.showToast({ title: '删除成功', icon: 'none', duration: 2000 })
+    setTimeout(() => {
+			uni.navigateBack({
+				delta: 1
+			})
+			disabled.value = false
+      deleteDisabled.value = false
+		}, 1000)
+  } catch {
+    deleteDisabled.value = false
+    disabled.value = false
+  }
+}
+
+// 保存
 const handleSubmit = async () => {
+  if (!journal.value) return uni.showToast({ title: '请输入要记录的内容', icon: 'none', duration: 2000 })
+  disabled.value = true
+
+  let list = []
+  if (!calendarRecord.value.length) {
+    list = [{ date: date.value, events: [], notes: journal.value }]
+  } else {
+    const index = calendarRecord.value.findIndex((item) => item.date === date.value)
+    if (index > -1) {
+      calendarRecord.value[index].notes = journal.value
+    } else {
+      calendarRecord.value.push({ date: date.value, events: [], notes: journal.value })
+    }
+    list = calendarRecord.value
+  }
+  const params = {
+    openid: userInfo.value.openid,
+    month_key: date.value.slice(0, 7),
+    calendar_content: list
+  }
+
+  console.log(params, 'params')
+  try {
+    await saveCalendarRecord(params)
+    uni.showToast({ title: '保存成功', icon: 'none', duration: 2000 })
+    setTimeout(() => {
+			uni.navigateBack({
+				delta: 1
+			})
+			disabled.value = false
+		}, 1000)
+  } catch {
+    disabled.value = false
+  }
 }
 </script>
 

+ 8 - 0
static/style/index.css

@@ -9192,3 +9192,11 @@
 .uni-select__input-box {
   width: 100%;
 }
+
+.uni-card {
+  border-radius: 10px !important;
+}
+
+.uni-section .uni-section-header {
+  padding: 0 !important;
+}

File diff ditekan karena terlalu besar
+ 0 - 0
static/style/index.min.css


+ 8 - 0
static/style/index.scss

@@ -553,4 +553,12 @@
 
 .uni-select__input-box {
 	width: 100%;
+}
+
+.uni-card {
+  border-radius: 10px !important;
+}
+
+.uni-section .uni-section-header {
+  padding: 0 !important;
 }

+ 7 - 5
utils/request.js

@@ -167,8 +167,9 @@ http.interceptors.response.use(
 		return Promise.resolve(response.data);
 	},
 	(error) => {
-		const useUserStore = userStore()
-		const isLogin = useUserStore.isLogin;
+		console.log(error, '响应拦截器error')
+		// const useUserStore = userStore()
+		// const isLogin = useUserStore.isLogin;
 		let errorMessage = '网络请求出错';
 		if (error !== undefined) {
 			switch (error.statusCode) {
@@ -176,7 +177,8 @@ http.interceptors.response.use(
 					errorMessage = '请求错误';
 					break;
 				case 401:
-          errorMessage = isLogin ? '您的登陆已过期' : '请先登录';
+					errorMessage = '请先登录'
+          // errorMessage = isLogin ? '您的登陆已过期' : '请先登录';
           // 正常情况下,后端不会返回 401 错误,所以这里不处理 handleAuthorized
           break;
 				case 403:
@@ -223,7 +225,7 @@ http.interceptors.response.use(
 		if (error && error.config) {
 			if (error.config.custom.showError === false) {
 				uni.showToast({
-					title: error.data?.msg || errorMessage,
+					title: error.data?.error || errorMessage,
 					icon: 'none',
 					duration: 2000,
 					mask: true,
@@ -232,7 +234,7 @@ http.interceptors.response.use(
 			error.config.custom.showLoading && closeLoading();
 		}
 
-		return false;
+		return Promise.reject(error.data)
 	},
 );
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini