From 6ef1b14f735acdc3ff77a50da1bb09a5bb983dcc Mon Sep 17 00:00:00 2001 From: tj <1378534974@qq.com> Date: 星期三, 28 五月 2025 17:37:06 +0800 Subject: [PATCH] location,userinfo --- composables/useLocation.ts | 55 +++++ pages/home/home.vue | 20 - sub-pages/mine/settings.vue | 17 + pages/login/login.vue | 4 pages/home/home-main.vue | 7 pages.json | 4 composables/useNavigator.ts | 52 +++++ plugins/http.js | 6 components/footer/customer-footer.vue | 11 store/index.ts | 6 manifest.json | 16 + pages/home/community.vue | 275 ++++++++++++++++----------- package.json | 2 main.js | 13 - components/tabbar/top-tab-bar.vue | 2 sub-pages/mine/index.vue | 46 +++ store/user.ts | 13 + 17 files changed, 378 insertions(+), 171 deletions(-) diff --git a/components/footer/customer-footer.vue b/components/footer/customer-footer.vue index 423802c..f0a56cb 100644 --- a/components/footer/customer-footer.vue +++ b/components/footer/customer-footer.vue @@ -19,6 +19,8 @@ <script setup lang="ts"> import { ref, computed } from 'vue' +import { useNavigator } from '@/composables/useNavigator' +const { navigateTo, reLaunchTo} = useNavigator() interface TabItem { text: string @@ -57,9 +59,12 @@ }) function go(index: number, item: TabItem) { - uni.reLaunch({ - url: item.pagePath, - }) + // uni.reLaunch({ + // url: item.pagePath, + // }) + + reLaunchTo(item.pagePath) + } </script> diff --git a/components/tabbar/top-tab-bar.vue b/components/tabbar/top-tab-bar.vue index 82f73e1..014447a 100644 --- a/components/tabbar/top-tab-bar.vue +++ b/components/tabbar/top-tab-bar.vue @@ -16,7 +16,7 @@ <!-- 左侧图标 + 标题 --> <view class="left"> <up-icon name="/static/images/tabbar/line-Film.png" size="40rpx" color="#fff" /> - <text class="title">光影旅程</text> + <text class="title">影途</text> </view> <!-- 右侧按钮 --> diff --git a/composables/useLocation.ts b/composables/useLocation.ts new file mode 100644 index 0000000..cacb128 --- /dev/null +++ b/composables/useLocation.ts @@ -0,0 +1,55 @@ +import { ref } from 'vue' +import http from '@/plugins/http.js' +import { useUserStore } from '../store/user' + +const userStore = useUserStore() +export function useLocation() { + const latitude = ref<number | null>(null) + const longitude = ref<number | null>(null) + const error = ref<string | null>(null) + const address = ref<string | null>(null) + const province= ref<string | null>(null) + + const getLocation = () => { + uni.getLocation({ + type: 'wgs84', + geocode: true, + success: async (res:any) => { + latitude.value = res.latitude + longitude.value = res.longitude + const { + code,data + } = await http.request('get', '/api/pub/customer/home/address/parse', { + data: {}, + params: { + // https://apis.map.qq.com/ws/geocoder/v1/?location=39.984154,116.307490&key=[你的key]&get_poi=1 + location:`${res.latitude},${res.longitude}` + } + }) + + if (data && data.result && data.result.ad_info) { + address.value = data.result.address + province.value = data.result.ad_info.province + console.log("省的值",province.value ) + // 更新地址信息到缓存中 + userStore.updateAddress(data.result) + } + }, + fail: (err:any) => { + error.value = '获取位置失败:' + (err.errMsg || '未知错误') + }, + complete: function () { + console.log('getLocation 请求已完成'); + } + }) + } + + return { + latitude, + longitude, + address, + province, + error, + getLocation + } +} diff --git a/composables/useNavigator.ts b/composables/useNavigator.ts new file mode 100644 index 0000000..d2e5ad8 --- /dev/null +++ b/composables/useNavigator.ts @@ -0,0 +1,52 @@ +import { useUserStore } from '@/store/user' + +export const useNavigator = () => { + const userStore = useUserStore() + // 黑名单列表:未登录时禁止访问这些路径 + const loginRequiredRoutes = [ + '/sub-pages/mine/settings', + '/pages/settings/index', + '/sub-pages/mine/index', + ] + + const navigateTo = (url: string) => { + const isLogin = userStore.hasLogin + const noQueryUrl = url.split('?')[0] + + if (!isLogin && loginRequiredRoutes.includes(noQueryUrl)) { + uni.navigateTo({ + url: '/pages/login/login' + }) + return + } + + uni.navigateTo({ url }) + } + + const reLaunchTo = (url: string) => { + + const isLogin = userStore.hasLogin + const noQueryUrl = url.split('?')[0] + + if (!isLogin && loginRequiredRoutes.includes(noQueryUrl)) { + uni.navigateTo({ + url: '/pages/login/login' + }) + return + } + + uni.reLaunch({ url }) + } + + const toProtocol = (title: string) => { + uni.navigateTo({ + url: `/sub-pages/protocol/protocol?title=${encodeURIComponent(title)}` + }) + } + + return { + navigateTo, + reLaunchTo, + toProtocol + } +} diff --git a/main.js b/main.js index 226f769..25e2fac 100644 --- a/main.js +++ b/main.js @@ -6,18 +6,6 @@ import http from './plugins/http.js' // import store from './store/index.js' -// #ifndef VUE3 -import Vue from 'vue' -import './uni.promisify.adaptor' -Vue.config.productionTip = false -App.mpType = 'app' -const app = new Vue({ - ...App -}) -app.$mount() -// #endif - -// #ifdef VUE3 import { createSSRApp } from 'vue' @@ -99,4 +87,3 @@ app } } -// #endif \ No newline at end of file diff --git a/manifest.json b/manifest.json index 82d8aa6..3cc00b3 100644 --- a/manifest.json +++ b/manifest.json @@ -50,12 +50,22 @@ "quickapp" : {}, /* 小程序特有相关 */ "mp-weixin" : { - "appid" : "wx1441324401626290", - // "appid" : "wxede6e3ad8e89693a", + // "appid" : "wx1441324401626290", + "appid" : "wxf2e5534be77e3a80", "setting" : { - "urlCheck" : false + "urlCheck" : false, + "es6" : true, + "minified" : true }, "usingComponents" : true, + "permission" : { + "scope.userLocation" : { + "desc" : "获取当前位置功能" + } + }, + "requiredPrivateInfos" : [ "chooseLocation", "getLocation" ], + "plugins": {}, + "lazyCodeLoading": "requiredComponents", "mergeVirtualHostAttributes" : true }, "mp-alipay" : { diff --git a/package.json b/package.json index 7b5615c..2f686c9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "uni-app": { "scripts": { "film": { - "title": "光影", + "title": "影途", "BROWSER": "Chrome", "env": { "UNI_PLATFORM": "mp-weixin", diff --git a/pages.json b/pages.json index ab98945..b3ecbda 100644 --- a/pages.json +++ b/pages.json @@ -12,7 +12,7 @@ { "path": "pages/home/home", "style": { - "navigationBarTitleText": "片场", + "navigationBarTitleText": "影途", "enablePullDownRefresh": true, "onReachBottomDistance": 50 } @@ -118,7 +118,7 @@ ], "globalStyle": { "navigationBarTextStyle": "black", - "navigationBarTitleText": "片场", + "navigationBarTitleText": "影途", "navigationBarBackgroundColor": "#F8F8F8", "backgroundColor": "#F8F8F8" }, diff --git a/pages/home/community.vue b/pages/home/community.vue index ba2bb99..f1e4cb8 100644 --- a/pages/home/community.vue +++ b/pages/home/community.vue @@ -1,119 +1,168 @@ <template> - <view class="post-card"> - <!-- 用户信息 --> - <view class="user-info"> - <up-avatar :src="avatar" size="80rpx" shape="circle" /> - <view class="user-text"> - <text class="nickname">{{ nickname }}</text> - <text class="time">{{ time }}</text> - </view> + <view class="post-card"> + <!-- 用户信息 --> + <view class="user-info"> + <up-avatar :src="avatar" size="80rpx" shape="circle" /> + <view class="user-text"> + <text class="nickname">{{ nickname }}</text> + <text class="time">{{ time }}</text> </view> - - <view class="inner-content"> - <!-- 内容图片 --> - <image class="main-image" :src="image" mode="aspectFill" /> - - <!-- 描述内容 --> - <view class="description"> - {{ content }} + </view> + + <view class="inner-content"> + <!-- 内容图片 --> + <image class="main-image" :src="image" mode="aspectFill" /> + <!-- <image class="main-image" :src="image" mode="aspectFit" /> --> + <!-- <image class="main-image" :src="image" mode="scaleToFill" /> --> + <!-- <view class="main-image-wrapper" :style="{ backgroundImage: `url(${image})` }"></view> --> + <!-- 下面图片可以展示完全,但是拉伸变得模糊 --> + <!-- <image :src="image" class="main-image" ></image> --> + <!-- <up-image :show-loading="true" :src="image" width="100%" shape="square"></up-image> --> + <!-- 动态计算高度:能够展示完全,高度会拉伸很高 --> + <!-- <up-image v-if="imageHeight > 0" :src="image" width="100%" :height="imageHeight + 'px'" shape="square" + :show-loading="true" /> --> + <!-- 描述内容 --> + <view class="description"> + {{ content }} + </view> + + <!-- 底部操作栏 --> + <view class="footer"> + <view class="action"> + <up-icon name="heart-fill" size="30rpx" color="#fff" /> + <text class="count">{{ likeCount }}</text> </view> - - <!-- 底部操作栏 --> - <view class="footer"> - <view class="action"> - <up-icon name="heart-fill" size="30rpx" color="#fff" /> - <text class="count">{{ likeCount }}</text> - </view> - <view class="action"> - <up-icon name="chat-fill" size="30rpx" color="#fff" /> - <text class="count">{{ commentCount }}</text> - </view> - <view class="action"> - <up-icon name="share" size="30rpx" color="#fff" /> - </view> + <view class="action"> + <up-icon name="chat-fill" size="30rpx" color="#fff" /> + <text class="count">{{ commentCount }}</text> + </view> + <view class="action"> + <up-icon name="share" size="30rpx" color="#fff" /> </view> </view> </view> - </template> - - <script setup lang="ts"> - interface Props { - avatar?: string; - nickname?: string; - time?: string; - image?: string; - content?: string; - likeCount?: number | string; - commentCount?: number | string; - } - - const props = defineProps<Props>(); - </script> - - <style scoped lang="scss"> - .post-card { - background-color: #1e1e1e; - border-radius: 24rpx; - padding: 10rpx; - color: #fff; - font-size: 28rpx; - margin-top: 20rpx; - } - - .user-info { - margin: 20rpx 30rpx; - display: flex; - align-items: center; - } - - .user-text { - font-size: 24rpx; - margin-left: 16rpx; - } - - .nickname { - font-weight: bold; - display: block; - } - - .time { - font-size: 18rpx; - color: #aaa; - } - - .inner-content { - margin: 0 20rpx; - } - - .main-image { - width: 100%; - height: 250rpx; - border-radius: 24rpx; - } - - .description { - margin: 20rpx 0; - font-size: 24rpx; - font-weight: bold; - color: #ddd; - letter-spacing: 2rpx; - } - - .footer { - display: flex; - justify-content: space-between; - align-items: center; - } - - .action { - display: flex; - align-items: center; - } - - .count { - margin-left: 10rpx; - font-size: 26rpx; - color: #ccc; - } - </style> - \ No newline at end of file + </view> +</template> + +<script setup lang="ts"> +import { ref, watch,onMounted } from 'vue' +import { onReady } from '@dcloudio/uni-app' + +interface Props { + avatar?: string; + nickname?: string; + time?: string; + image?: string; + content?: string; + likeCount?: number | string; + commentCount?: number | string; +} + +const props = defineProps<Props>(); +const imageHeight = ref(0) + +const computeImageHeight = (src?: string) => { + if (!src) return + uni.getImageInfo({ + src, + success: (res) => { + const screenWidth = uni.getSystemSetting().windowWidth + imageHeight.value = screenWidth * (res.height / res.width) + }, + fail: () => { + console.warn('获取图片信息失败') + } + }) +} + +watch( + () => props.image, + (newImage) => { + if (!newImage) return + computeImageHeight(newImage) + }, + { immediate: true } +) + +onReady(() => { + computeImageHeight(props.image) +}) +</script> + +<style scoped lang="scss"> +.post-card { + background-color: #1e1e1e; + border-radius: 24rpx; + padding: 10rpx; + color: #fff; + font-size: 28rpx; + margin-top: 20rpx; +} + +.user-info { + margin: 20rpx 30rpx; + display: flex; + align-items: center; +} + +.user-text { + font-size: 24rpx; + margin-left: 16rpx; +} + +.nickname { + font-weight: bold; + display: block; +} + +.time { + font-size: 18rpx; + color: #aaa; +} + +.inner-content { + margin: 0 20rpx; +} + +.main-image { + width: 100%; + height: 250rpx; + border-radius: 24rpx; +} + +.description { + margin: 20rpx 0; + font-size: 24rpx; + font-weight: bold; + color: #ddd; + letter-spacing: 2rpx; +} + +.footer { + display: flex; + justify-content: space-between; + align-items: center; +} + +.action { + display: flex; + align-items: center; +} + +.count { + margin-left: 10rpx; + font-size: 26rpx; + color: #ccc; +} + +.main-image-wrapper { + width: 100%; + width: 500px; + height: 200px; + /* 你可以根据需求自适应设置 */ + background-size: contain; + /* 保证完整显示 */ + background-repeat: no-repeat; + background-position: center; +} +</style> \ No newline at end of file diff --git a/pages/home/home-main.vue b/pages/home/home-main.vue index 7c16251..3e545c6 100644 --- a/pages/home/home-main.vue +++ b/pages/home/home-main.vue @@ -1,6 +1,7 @@ <template> <view> - <view class="card" v-if="!showVideo"> + <!-- <view class="card" v-if="!showVideo"> --> + <view class="card"> <view class="main-title">每一帧画面,都藏着一个等待探索的世界</view> <view class="sub-title"> 从经典场景到幕后故事,开启你的专属影视朝圣之旅 @@ -39,7 +40,7 @@ </view> <!-- 视频播放区域 --> - <view v-else class="video-wrapper"> + <!-- <view v-else class="video-wrapper"> <video :src="currentVideo" controls @@ -47,7 +48,7 @@ @ended="onVideoEnd" style="width: 100%; height: 400rpx;" ></video> - </view> + </view> --> </view> </template> diff --git a/pages/home/home.vue b/pages/home/home.vue index 5288e11..012b8ac 100644 --- a/pages/home/home.vue +++ b/pages/home/home.vue @@ -43,11 +43,7 @@ <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> + <up-loadmore :status="communityStatus" :line="true" /> <view style="height: 300rpx;"></view> </view> @@ -57,7 +53,7 @@ <script setup lang="ts"> import { ref, computed, onMounted } from 'vue' -import { onShow, onPullDownRefresh,onReachBottom } from '@dcloudio/uni-app' +import { onShow, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app' import HomeMain from './home-main.vue' import TripCard from './trip-card.vue' @@ -146,18 +142,18 @@ // 内容精选 getContentSelected() // 光影社区 - communityPage.value=1 + communityPage.value = 1 getCommunitys() uni.stopPullDownRefresh() // 停止下拉刷新动画 }) -onReachBottom(()=>{ +onReachBottom(() => { console.log('用户触底了') getCommunitys() }) const getContentSelected = async () => { - tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20,1); + tripCardList.value = await getFilmWorks(FilmWorksCategory.CONTENT_SELECTED, 20, 1); } @@ -167,7 +163,7 @@ const getCommunitys = async () => { - if (communityStatus.value==='nomore') return + if (communityStatus.value === 'nomore') return communityStatus.value = 'loading' @@ -191,10 +187,10 @@ } } const getCommunitys_bak = async () => { - communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10,1); + communitys.value = await getFilmWorks(FilmWorksCategory.COMMUNITY, 10, 1); } // 内容精选 -const getFilmWorks = async (type: String, pageSize: Number,currentPage: Number) => { +const getFilmWorks = async (type: String, pageSize: Number, currentPage: Number) => { const { code, data } = await $http.request('get', '/api/filmWorks/list', { diff --git a/pages/login/login.vue b/pages/login/login.vue index a926a9a..1fae60e 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -6,7 +6,7 @@ </view> <view class="logo-container"> - <text class="app-name">光影</text> + <text class="app-name">影途</text> <text class="subtitle">登录后,体验更多功能</text> </view> @@ -148,7 +148,7 @@ } }) if (code == 0) { - debugger; + // 获取手机号码后,实现微信登录 const phoneNumber = data.phone_info.phoneNumber; const purePhoneNumber = data.phone_info.purePhoneNumber; diff --git a/plugins/http.js b/plugins/http.js index 9d895af..3ede604 100644 --- a/plugins/http.js +++ b/plugins/http.js @@ -114,12 +114,12 @@ // #ifdef PUB_CUSTOMER uni.reLaunch({ - url: '/pages/user/supplier-user' + url: '/pages/login/login' }) // #endif // #ifndef PUB_CUSTOMER uni.reLaunch({ - url: '/pages/login/supplier-login' + url: '/pages/login/login' }) // #endif reject({ @@ -165,7 +165,7 @@ // #endif // #ifndef PUB_CUSTOMER uni.reLaunch({ - url: '/pages/login/supplier-login' + url: '/pages/login/login' }) // #endif reject({ diff --git a/store/index.ts b/store/index.ts index 9ea779f..fd4b0e4 100644 --- a/store/index.ts +++ b/store/index.ts @@ -1,9 +1,9 @@ // 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 http from '@/plugins/http.js' +import storage from '@/plugins/storage' +import message from '@/plugins/message' import { WechatLoginData } from '@/types/index' diff --git a/store/user.ts b/store/user.ts index 61a39ea..57b723e 100644 --- a/store/user.ts +++ b/store/user.ts @@ -11,6 +11,7 @@ const hasLogin = ref(false) const isBind = ref(false) const userInfo = ref<any>(null) + const address = ref<any>(null) async function getCurrentInfo() { const currentInfo = await http.request('get', '/api/current/user', {}) @@ -75,14 +76,26 @@ hasLogin.value = false } } + + + function updateAddress(addressParam:any) { + + // 合并新信息到 userInfo 中 + console.log("addressParam",addressParam) + address.value = addressParam + // 如果你有持久化,这里也同步一下 + // storage.setItem('userInfo', userInfo.value) + } return { hasLogin, isBind, userInfo, + address, loginwx, getCurrentInfo, initLoginState, + updateAddress, } }) diff --git a/sub-pages/mine/index.vue b/sub-pages/mine/index.vue index fd50fa0..6a80c45 100644 --- a/sub-pages/mine/index.vue +++ b/sub-pages/mine/index.vue @@ -12,16 +12,18 @@ <view class="profile-content"> <view class="profile-header"> <view class="avatar-container"> - <image class="avatar" src="https://ai-public.mastergo.com/ai/img_res/e8ae645c666c247b895b488e60b048f5.jpg" - mode="aspectFill" /> + <image v-if="userStore.userInfo.customerDTO.cover" class="avatar" + :src="userStore.userInfo.customerDTO.cover" mode="aspectFill" /> + <image v-else class="avatar" + src="https://ai-public.mastergo.com/ai/img_res/e8ae645c666c247b895b488e60b048f5.jpg" mode="aspectFill" /> <view class="add-icon"> <up-icon name="plus" size="20rpx" color="#333" /> </view> </view> <view class="user-info"> - <view class="username">小红薯 6786F040</view> - <view class="user-id">小红书号:95619601810</view> - <view class="location">IP 属地:江苏</view> + <view class="username">影途 {{ userStore?.userInfo?.customerDTO?.name }}</view> + <view class="user-id">影途号:{{ userStore?.userInfo?.customerDTO?.id }}</view> + <view class="location">IP 属地:{{ userStore.address?.ad_info?.province }}</view> </view> </view> @@ -45,7 +47,7 @@ <view class="action-buttons"> <up-button text="编辑资料" size="mini" type="info" plain hairline :custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }" /> - <up-icon name="setting" size="40rpx" /> + <up-icon name="setting" size="40rpx" @click="gotoUrl('/sub-pages/mine/settings')" /> </view> </view> </view> @@ -84,8 +86,38 @@ </template> <script setup lang="ts"> -import { ref, computed } from 'vue'; +import { ref, computed, watch } from 'vue'; +import { onShow } from '@dcloudio/uni-app' import SettingPopup from '@/components/setting/setting-popup.vue'; +import { usePlatformLoginType } from '@/composables/usePlatformLoginType' +import { useUserStore } from '@/store/user' +import { useLocation } from '@/composables/useLocation' +import { useNavigator } from '@/composables/useNavigator' + +const { apitype } = usePlatformLoginType() +const userStore = useUserStore() +const { navigateTo } = useNavigator() +const {getLocation,province } = useLocation() + + +const gotoUrl = (url: string) => { + navigateTo(url) +} + +watch( + () => userStore.userInfo, // 监听 userInfo 这个响应式属性 + (newVal, oldVal) => { + console.log('userInfo 发生变化:', newVal) + }, + { deep: true } // 如果 userInfo 是对象,需要深度监听其属性变化 +) + +onShow(() => { + console.log('我的') + getLocation() +}); + + // 当前 tab 索引 const current = ref(0); diff --git a/sub-pages/mine/settings.vue b/sub-pages/mine/settings.vue index cacaa03..0770cc1 100644 --- a/sub-pages/mine/settings.vue +++ b/sub-pages/mine/settings.vue @@ -41,12 +41,12 @@ <!-- 法律文案 --> <view class="portotal-actions"> <view class="action-row"> - <up-text size="10" :bold="true" text="《个人信息收集清单》" color="#38516E" /> - <up-text size="10" :bold="true" text="《第三方信息共享清单》" color="#38516E" /> + <up-text size="10" :bold="true" text="《个人信息收集清单》" @click="toPortotalUni('个人信息收集清单')" color="#38516E" /> + <up-text size="10" :bold="true" text="《第三方信息共享清单》" @click="toPortotalUni('个人信息收集清单')" color="#38516E" /> </view> <view class="action-row"> - <up-text size="10" :bold="true" text="《用户服务协议》" color="#38516E" /> - <up-text size="10" :bold="true" text="《用户隐私政策》" color="#38516E" /> + <up-text size="10" :bold="true" text="《用户服务协议》" @click="toPortotalUni('用户协议')" color="#38516E" /> + <up-text size="10" :bold="true" text="《用户隐私政策》" @click="toPortotalUni('隐私政策')" color="#38516E" /> </view> </view> </view> @@ -54,6 +54,13 @@ <script setup lang="ts"> import { ref } from 'vue' + import { useNavigator } from '@/composables/useNavigator' + const { toProtocol } = useNavigator() + + +const toPortotalUni = (title:string) => { + toProtocol(title) +} // 菜单项类型定义 interface MenuItem { @@ -148,7 +155,7 @@ .portotal-actions { margin-top: 30rpx; - margin-bottom: 100rpx; + margin-bottom: 200rpx; display: flex; flex-direction: column; align-items: center; -- Gitblit v1.9.3