From fa74612c99459a8b4e94121d2d3bfcc42915208b Mon Sep 17 00:00:00 2001 From: tj <1378534974@qq.com> Date: 星期二, 27 五月 2025 16:08:20 +0800 Subject: [PATCH] loading,wechatLogin --- pages/home/home.vue | 67 +++++ pages/login/login.vue | 57 +++-- pages.json | 4 plugins/http.js | 8 App.vue | 8 store/index.js | 229 ---------------------- utils/time.ts | 29 ++ types/index.ts | 21 + store/index.ts | 69 ++++++ manifest.json | 4 main.js | 4 components/tabbar/top-tab-bar.vue | 12 store/index copy.js | 2 store/user.ts | 86 ++++++++ 14 files changed, 318 insertions(+), 282 deletions(-) diff --git a/App.vue b/App.vue index fa4780f..c6ce853 100644 --- a/App.vue +++ b/App.vue @@ -1,7 +1,12 @@ <script setup lang="ts"> import { onLaunch, onShow, onHide } from '@dcloudio/uni-app' - +import { useUserStore } from '@/store/user' +const userStore = useUserStore() onLaunch(async (options: any) => { + + // 初始化用户状态 + userStore.initLoginState() + const query = options.q ? decodeURIComponent(options.q) : '' const querydto: Record<string, string> = {} @@ -37,7 +42,6 @@ uni.getSystemSetting({ success: (e: any) => { - debugger; try { const custom = uni.getMenuButtonBoundingClientRect() uni.setStorageSync('StatusBar', e.statusBarHeight) diff --git a/components/tabbar/top-tab-bar.vue b/components/tabbar/top-tab-bar.vue index 0ba089b..82f73e1 100644 --- a/components/tabbar/top-tab-bar.vue +++ b/components/tabbar/top-tab-bar.vue @@ -21,7 +21,7 @@ <!-- 右侧按钮 --> <view class="right"> - <view class="login-view" @click="goLogin"> + <view class="login-view" @click="goLogin" v-if="!isLoggedIn"> <up-icon name="/static/images/tabbar/user.png" size="30rpx" /> <text class="login-text">登录</text> </view> @@ -33,10 +33,12 @@ </template> <script setup lang="ts"> -import { ref, onMounted } from 'vue' - -const CustomBar = ref<number>(uni.getStorageSync('CustomBar') || 0) -const StatusBar = ref<number>(uni.getStorageSync('StatusBar') || 0) +import { ref, onMounted ,computed} from 'vue' +import { useUserStore } from '@/store/user' +const userStore = useUserStore() +const isLoggedIn = computed(() => userStore.hasLogin) +console.log("登录状态") +console.log(isLoggedIn.value) // 可选:自动获取系统信息进行替代 onMounted(() => { diff --git a/main.js b/main.js index d2d448c..226f769 100644 --- a/main.js +++ b/main.js @@ -4,7 +4,7 @@ import { createPinia } from 'pinia' import message from './plugins/message' import http from './plugins/http.js' -import store from './store' +// import store from './store/index.js' // #ifndef VUE3 import Vue from 'vue' @@ -53,7 +53,7 @@ // 全局属性 app.config.globalProperties.$message = message app.config.globalProperties.$http = http - app.config.globalProperties.$store = store + // app.config.globalProperties.$store = store // uni.$u.setConfig({ // config: { diff --git a/manifest.json b/manifest.json index 54fb740..82d8aa6 100644 --- a/manifest.json +++ b/manifest.json @@ -50,8 +50,8 @@ "quickapp" : {}, /* 小程序特有相关 */ "mp-weixin" : { - // "appid" : "wx1441324401626290", - "appid" : "wxede6e3ad8e89693a", + "appid" : "wx1441324401626290", + // "appid" : "wxede6e3ad8e89693a", "setting" : { "urlCheck" : false }, diff --git a/pages.json b/pages.json index a092c37..ab98945 100644 --- a/pages.json +++ b/pages.json @@ -12,7 +12,9 @@ { "path": "pages/home/home", "style": { - "navigationBarTitleText": "片场" + "navigationBarTitleText": "片场", + "enablePullDownRefresh": true, + "onReachBottomDistance": 50 } }, { diff --git a/pages/home/home.vue b/pages/home/home.vue index a71e374..5288e11 100644 --- a/pages/home/home.vue +++ b/pages/home/home.vue @@ -43,7 +43,11 @@ <Community v-for="(item, index) in communitys" :key="index" :avatar="item.avatar" :nickname="item.nickname" :time="formatRelativeTime(item.createTime)" :image="item.coverUrl" :content="item.coverAlt" :likeCount="item.likeCount" :commentCount="item.commentCount" /> - + <view class="more"> + <!-- <view v-if="loadingCommunity">加载中...</view> + <view v-if="noMoreCommunity">没有更多了</view> --> + <up-loadmore :status="communityStatus" /> + </view> <view style="height: 300rpx;"></view> </view> @@ -53,7 +57,7 @@ <script setup lang="ts"> import { ref, computed, onMounted } from 'vue' -import { onShow } from '@dcloudio/uni-app' +import { onShow, onPullDownRefresh,onReachBottom } from '@dcloudio/uni-app' import HomeMain from './home-main.vue' import TripCard from './trip-card.vue' @@ -67,6 +71,7 @@ import { FilmWorks } from '@/types/index' import { formatRelativeTime } from '@/utils/time' import { FilmWorksCategory } from '@/enums/dict' + // 主题 const theme = ref('light') @@ -135,22 +140,68 @@ getCommunitys() }); -async function getContentSelected() { - tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20); - console.log('内容精选', tripCardList.value); + +onPullDownRefresh(async () => { + console.log('用户下拉刷新了') + // 内容精选 + getContentSelected() + // 光影社区 + communityPage.value=1 + getCommunitys() + uni.stopPullDownRefresh() // 停止下拉刷新动画 +}) + +onReachBottom(()=>{ + console.log('用户触底了') + getCommunitys() +}) + +const getContentSelected = async () => { + tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20,1); } -async function getCommunitys() { - communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10); + +const communityPage = ref(1) +const communitySize = 10 +const communityStatus = ref('loading') + + +const getCommunitys = async () => { + if (communityStatus.value==='nomore') return + + communityStatus.value = 'loading' + + const records = await getFilmWorks(FilmWorksCategory.COMMUNITY, communitySize, communityPage.value) + + if (records && records.length > 0) { + // 使用 Set 进行去重 + const existingIds = new Set(communitys.value.map(item => item.id)) + const uniqueRecords = records.filter(item => !existingIds.has(item.id)) + + communitys.value = [...communitys.value, ...uniqueRecords] + + // 如果返回的记录数少于请求的 size,说明没有更多数据 + if (records.length < communitySize) { + communityStatus.value = 'noMore' + } + + communityPage.value++ + } else { + communityStatus.value = 'noMore' + } +} +const getCommunitys_bak = async () => { + communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10,1); } // 内容精选 -const getFilmWorks = async (type: String, pageSize: Number) => { +const getFilmWorks = async (type: String, pageSize: Number,currentPage: Number) => { const { code, data } = await $http.request('get', '/api/filmWorks/list', { params: { classify: type, size: pageSize, + current: currentPage } }) if (code == 0) { diff --git a/pages/login/login.vue b/pages/login/login.vue index 7434365..a926a9a 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -50,8 +50,11 @@ import { onShow } from '@dcloudio/uni-app' import { useGlobal } from '@/composables/useGlobal' import { usePlatformLoginType } from '@/composables/usePlatformLoginType' +import { useUserStore } from '@/store/user' + const { apitype } = usePlatformLoginType() -const { $http, $message,$store } = useGlobal() +const { $http, $message, $store } = useGlobal() +const userStore = useUserStore() const isChecked = ref(false) const toggleCheck = () => { @@ -64,8 +67,29 @@ uni.showToast({ title: '请先同意协议', icon: 'none' }); return; } - // 微信登录逻辑 - uni.showToast({ title: '微信登录', icon: 'success' }); + // 微信登录 + uni.login({ + "provider": "weixin", + "onlyAuthorize": true, // 微信登录仅请求授权认证 + success: async function (event:any) { + const { code } = event + $message.showLoading(); + const resp = await userStore.loginwx({ code, phoneNumber: wxUser.value.phoneNumber, purePhoneNumber: wxUser.value.purePhoneNumber }) + if (resp && resp.data) { + // that.$forceUpdate() + uni.reLaunch({ + url: '/pages/home/home' + }) + } + $message.hideLoading(); + }, + fail: function (err:any) { + // 登录授权失败 + // err.code是错误码 + } + }) + + }; onShow(() => { @@ -77,13 +101,8 @@ "provider": "weixin", "onlyAuthorize": true, // 微信登录仅请求授权认证 success: async function (event: any) { - console.log("aaaa") - console.log(event) const { code } = event let openIdExistFlag = await getExistUserByOpenId(code); - console.log(openIdExistFlag) - console.log(wxUser.value) - }, fail: function (err: any) { // 登录授权失败 @@ -101,8 +120,6 @@ } }) if (code == 0) { - console.log("查看当前用户是否已经绑定过") - console.log(data) wxUser.value = data if (wxUser && wxUser.user) { return true @@ -113,16 +130,13 @@ } } -const handleGetPhoneNumber = async (e:any) => { +const handleGetPhoneNumber = async (e: any) => { + if (!isChecked.value) { $message.showToast('请同意用户协议') return } - debugger; - console.log(e) - console.log(e.detail.code) // 动态令牌 - console.log(e.detail.errMsg) // 回调信息(成功失败都会返回) - console.log(e.detail.errno) // 错误码(失败时返回) + if (e.detail.errMsg == 'getPhoneNumber:ok') { console.log('获取成功') const { @@ -134,13 +148,13 @@ } }) if (code == 0) { + debugger; // 获取手机号码后,实现微信登录 - console.log(data) const phoneNumber = data.phone_info.phoneNumber; const purePhoneNumber = data.phone_info.purePhoneNumber; wxUser.value.phoneNumber = phoneNumber wxUser.value.purePhoneNumber = purePhoneNumber - // that.handleWechatClick() + handleWechatClick() } else { } @@ -153,10 +167,11 @@ uni.login({ "provider": "weixin", "onlyAuthorize": true, // 微信登录仅请求授权认证 - success: async function (event) { + success: async function (event: any) { const { code } = event $message.showLoading(); - const resp = await $store.dispatch('loginwx', { code, phoneNumber: wxUser.phoneNumber, purePhoneNumber: wxUser.purePhoneNumber }) + console.log("获取到的微信用户信息是:", wxUser.value) + const resp = await userStore.loginwx({ code, phoneNumber: wxUser.value.phoneNumber, purePhoneNumber: wxUser.value.purePhoneNumber }) if (resp && resp.data) { // $forceUpdate() uni.reLaunch({ @@ -165,7 +180,7 @@ } $message.hideLoading(); }, - fail: function (err) { + fail: function (err: any) { // 登录授权失败 // err.code是错误码 } diff --git a/plugins/http.js b/plugins/http.js index 412254e..9d895af 100644 --- a/plugins/http.js +++ b/plugins/http.js @@ -1,7 +1,7 @@ import environments from '@/environments' import message from './message' import storage from './storage' -import store from '../store' +// import store from '../store' import utils from './util.js' let pre = 'api' @@ -107,7 +107,8 @@ console.log('resp', res) // storage.removeItem('token') // await store.dispatch('logout') - store.commit('updateLogin', false) + // TODO + // store.commit('updateLogin', false) await message.showToast('登录信息失效') @@ -152,7 +153,8 @@ console.log('401', res) // storage.removeItem('token') // await store.dispatch('logout') - store.commit('updateLogin', false) + // TODO + // store.commit('updateLogin', false) await message.showToast('登录信息失效') diff --git a/store/index copy.js b/store/index copy.js index 0cb7d8c..9ef1829 100644 --- a/store/index copy.js +++ b/store/index copy.js @@ -1,4 +1,4 @@ -import http from '../plugins/http' +import http from '../plugins/http.js' import storage from '../plugins/storage.js' import message from '../plugins/message.js' import Vue from 'vue' diff --git a/store/index.js b/store/index.js index 42843e1..e69de29 100644 --- a/store/index.js +++ b/store/index.js @@ -1,229 +0,0 @@ -// store/index.js -import { createStore } from 'vuex' -import http from '../plugins/http' -import storage from '../plugins/storage.js' -import message from '../plugins/message.js' - -const store = createStore({ - state() { - return { - hasLogin: false, - isUniverifyLogin: false, - loginProvider: '', - openid: null, - testvuex: false, - colorIndex: 0, - colorList: ['#FF0000', '#00FF00', '#0000FF'], - noMatchLeftWindow: true, - active: 'componentPage', - leftWinActive: '/pages/component/view/view', - activeOpen: '', - menu: [], - appMenu: [], - univerifyErrorMsg: '', - currentInfo: {}, - cache_address: {}, - sign: { - enterprise: 0, - info: 0, - flower: 0, - shopping: 0, - follow: 0, - delivery: 0, - order: 0, - shopnum: 0, - coupon: 0, - cache_topay: 0, - }, - cache: { - coupon: {}, - goods: [], - cache_coupon_select_cancel: 0, - }, - defaultaddress: {}, - addressDesc: '', - } - }, - mutations: { - updateLogin(state, provider) { - state.hasLogin = !!provider - if (!state.hasLogin) { - state.currentInfo = {} - storage.removeItem('token') - } - }, - login(state, provider) { - state.hasLogin = true - state.loginProvider = provider - }, - logout(state) { - state.hasLogin = false - state.openid = null - state.currentInfo = {} - state.appMenu = [] - storage.removeItem('token') - storage.removeItem('appMenu') - message.showToast('退出登录成功') - }, - setOpenid(state, openid) { - state.openid = openid - }, - setDefaultAddress(state, defaultaddress) { - state.defaultaddress = defaultaddress - }, - setAddressDesc(state, addressDesc) { - state.addressDesc = addressDesc - storage.setItem('defaultaddress', addressDesc || '') - }, - setTestTrue(state) { - state.testvuex = true - }, - setTestFalse(state) { - state.testvuex = false - }, - setColorIndex(state, index) { - state.colorIndex = index - }, - setActive(state, tabPage) { - state.active = tabPage - }, - setActiveOpen(state, activeOpen) { - state.activeOpen = activeOpen - }, - setMenu(state, menu) { - state.menu = menu - }, - setUniverifyLogin(state, payload) { - state.isUniverifyLogin = !!payload - }, - setUniverifyErrorMsg(state, payload = '') { - state.univerifyErrorMsg = payload - } - }, - getters: { - currentColor(state) { - return state.colorList[state.colorIndex] - } - }, - actions: { - async sign_add({ state }, key) { - state.sign[key] = 1 - }, - async sign_clear({ state }, key) { - state.sign[key] = 0 - }, - async cache_coupon_select({ state }, dto) { - state.cache.coupon = dto || {} - }, - async cache_coupon_select_cancel({ state }, val) { - state.cache.cache_coupon_select_cancel = val || 0 - }, - async cache_goods_select({ state }, goods) { - state.cache.goods = goods || [] - }, - async logout({ commit }) { - commit('logout') - }, - async getUserOpenId({ state, commit }) { - if (state.openid) return state.openid - return new Promise((resolve, reject) => { - uni.login({ - success(data) { - commit('login') - setTimeout(() => { - const openid = '123456789' - commit('setOpenid', openid) - resolve(openid) - }, 1000) - }, - fail(err) { - reject(err) - } - }) - }) - }, - async getCurrentInfo({ commit, state }) { - const currentInfo = await http.request('get', '/api/current/user', {}) - if (currentInfo && currentInfo.code === 0) { - state.currentInfo = currentInfo.data || {} - state.type = currentInfo.data.type || '' - state.spacecode = currentInfo.data.spacecode || '' - commit('updateLogin', true) - } else { - commit('updateLogin', false) - } - }, - async getSwitchSubAccount({ commit, state }, payload) { - const currentInfo = await http.request('get', '/api/supplierSub/getSwitchById', { - params: { - id: payload.id, - type: payload.type - } - }) - if (currentInfo && currentInfo.code === 0) { - state.currentInfo = currentInfo.data || {} - state.type = currentInfo.data.type || '' - state.spacecode = currentInfo.data.spacecode || '' - commit('updateLogin', true) - } else { - commit('updateLogin', false) - } - return currentInfo - }, - async getAppMenu({ state }) { - const menu = await http.request('get', '/api/app/menu/permission/menu', {}) - storage.setItem('appMenu', []) - if (menu && menu.code === 0) { - const appMenu = menu.data || [] - storage.setItem('appMenu', appMenu) - } - }, - async getAppMenuSupplier({ state }) { - const menu = await http.request('get', '/api/app/menu/supplier/permission/menu', {}) - storage.setItem('appMenu', []) - if (menu && menu.code === 0) { - const appMenu = menu.data || [] - storage.setItem('appMenu', appMenu) - } - }, - async getAppMenuPartner({ state }) { - const menu = await http.request('get', '/api/app/menu/partner/permission/menu', {}) - storage.setItem('appMenu', []) - if (menu && menu.code === 0) { - const appMenu = menu.data || [] - storage.setItem('appMenu', appMenu) - } - }, - async loginwx({ dispatch, state }, data) { - const resp = await http.request('post', '/api/login/wechat', { - data: { - code: data.code, - imgurl: data.imgurl || '', - nickname: data.nickname || '', - inviter: data.inviter || '', - phoneNumber: data.phoneNumber || '', - purePhoneNumber: data.purePhoneNumber || '', - } - }) - if (resp && resp.code === 0) { - state.isBind = true - storage.setItem('token', resp.data.access_token || '') - state.hasLogin = true - if (data.inviter) { - storage.removeItem('inviter') - storage.removeItem('inviterTime') - storage.removeItem('inviterName') - } - await dispatch('getCurrentInfo') - } else { - message.showToast('登录失败: ' + (resp && resp.msg)) - storage.removeItem('openid') - storage.removeItem('tel') - storage.removeItem('token') - } - return resp - } - } -}) - -export default store diff --git a/store/index.ts b/store/index.ts new file mode 100644 index 0000000..9ea779f --- /dev/null +++ b/store/index.ts @@ -0,0 +1,69 @@ +// stores/user.ts +import { defineStore } from 'pinia' +import { ref } from 'vue' +import http from '@/plugins/http.js' // 请替换成你实际的 http 封装路径 +import storage from '@/plugins/storage' // 同样替换为你的封装路径 +import message from '@/plugins/message' // 你使用的消息组件封装 +import { WechatLoginData } from '@/types/index' + + +export const useUserStore = defineStore('user', () => { + const hasLogin = ref(false) + const isBind = ref(false) + + async function getCurrentInfo() { + // 模拟请求用户信息 + console.log('获取当前用户信息') + // 这里你可以请求 /api/user/info 等接口获取用户数据 + } + + async function loginwx(data: WechatLoginData) { + const { + code, + imgurl = '', + nickname = '', + inviter = '', + phoneNumber = '', + purePhoneNumber = '' + } = data + + const resp = await http.request('post', '/api/login/wechat', { + data: { + code, + imgurl, + nickname, + inviter, + phoneNumber, + purePhoneNumber + } + }) + + if (resp && resp.code === 0) { + isBind.value = true + storage.setItem('token', resp.data.access_token || '') + hasLogin.value = true + + if (inviter) { + storage.removeItem('inviter') + storage.removeItem('inviterTime') + storage.removeItem('inviterName') + } + + await getCurrentInfo() + } else { + message.showToast('登录失败:' + (resp?.msg || '未知错误')) + storage.removeItem('openid') + storage.removeItem('tel') + storage.removeItem('token') + } + + return resp + } + + return { + hasLogin, + isBind, + loginwx, + getCurrentInfo + } +}) diff --git a/store/user.ts b/store/user.ts index c95eed2..61a39ea 100644 --- a/store/user.ts +++ b/store/user.ts @@ -1,6 +1,88 @@ +// stores/user.ts import { defineStore } from 'pinia' import { ref } from 'vue' +import http from '@/plugins/http.js' // 请替换成你实际的 http 封装路径 +import storage from '@/plugins/storage' // 同样替换为你的封装路径 +import message from '@/plugins/message' // 你使用的消息组件封装 +import { WechatLoginData } from '@/types/index' + export const useUserStore = defineStore('user', () => { - -}) \ No newline at end of file + const hasLogin = ref(false) + const isBind = ref(false) + const userInfo = ref<any>(null) + + async function getCurrentInfo() { + const currentInfo = await http.request('get', '/api/current/user', {}) + if (currentInfo && currentInfo.code == 0) { + console.log('当前用户信息', currentInfo) + userInfo.value = currentInfo.data // 赋值到 store + } else { + message.showToast('获取用户信息失败') + } + } + + async function loginwx(data: WechatLoginData) { + const { + code, + imgurl = '', + nickname = '', + inviter = '', + phoneNumber = '', + purePhoneNumber = '' + } = data + + const resp = await http.request('post', '/api/login/wechat', { + data: { + code, + imgurl, + nickname, + inviter, + phoneNumber, + purePhoneNumber + } + }) + + if (resp && resp.code === 0) { + + isBind.value = true + storage.setItem('token', resp.data.access_token || '') + hasLogin.value = true + await getCurrentInfo() + } else { + message.showToast('登录失败:' + (resp?.msg || '未知错误')) + storage.removeItem('openid') + storage.removeItem('tel') + storage.removeItem('token') + } + + return resp + } + + + function initLoginState() { + const token = storage.getItem('token') + if (token) { + hasLogin.value = true + + const savedUserInfo = storage.getItem('userInfo') + if (savedUserInfo) { + userInfo.value = savedUserInfo + } else { + getCurrentInfo() + } + } else { + hasLogin.value = false + } + } + + + return { + hasLogin, + isBind, + userInfo, + loginwx, + getCurrentInfo, + initLoginState, + } +}) diff --git a/types/index.ts b/types/index.ts index 3f1ff30..0aa5aff 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,9 +1,3 @@ -export interface ProtocolData { - id: number; - title: string; - content: string; -} - export interface WxUser { openId: String; sessionKey: String; @@ -13,6 +7,21 @@ purePhoneNumber: String; } +export interface WechatLoginData { + code: string + imgurl?: string + nickname?: string + inviter?: string + phoneNumber?: string + purePhoneNumber?: string +} + +export interface ProtocolData { + id: number; + title: string; + content: string; +} + export interface FilmWorks{ id?: number; diff --git a/utils/time.ts b/utils/time.ts index 8affc77..731a4a9 100644 --- a/utils/time.ts +++ b/utils/time.ts @@ -1,6 +1,35 @@ // utils/time.ts export function formatRelativeTime(inputTime: string | Date): string { + const now = new Date() + + // 如果是字符串格式,先进行兼容性处理 + let time: Date + if (typeof inputTime === 'string') { + // 替换中间的空格为 'T' 或替换 '-' 为 '/' + const compatibleStr = inputTime.replace(/-/g, '/') + time = new Date(compatibleStr) + } else { + time = inputTime + } + + const diffMs = now.getTime() - time.getTime() + + const minutes = Math.floor(diffMs / (1000 * 60)) + const hours = Math.floor(minutes / 60) + const days = Math.floor(hours / 24) + const months = Math.floor(days / 30) + const years = Math.floor(days / 365) + + if (years > 0) return `${years} 年前` + if (months > 0) return `${months} 个月前` + if (days > 0) return `${days} 天前` + if (hours > 0) return `${hours} 小时前` + if (minutes > 0) return `${minutes} 分钟前` + return '刚刚' +} + +export function formatRelativeTime2(inputTime: string | Date): string { const now = new Date() const time = typeof inputTime === 'string' ? new Date(inputTime) : inputTime const diffMs = now.getTime() - time.getTime() -- Gitblit v1.9.3