tj
2025-05-28 6ef1b14f735acdc3ff77a50da1bb09a5bb983dcc
location,userinfo
已修改15个文件
已添加2个文件
549 ■■■■■ 文件已修改
components/footer/customer-footer.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/tabbar/top-tab-bar.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
composables/useLocation.ts 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
composables/useNavigator.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manifest.json 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/community.vue 275 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home-main.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/home/home.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/login/login.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
plugins/http.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
store/index.ts 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
store/user.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sub-pages/mine/index.vue 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sub-pages/mine/settings.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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>
        <!-- 右侧按钮 -->
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
  }
}
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
    }
}
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
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" : {
package.json
@@ -2,7 +2,7 @@
  "uni-app": {
    "scripts": {
      "film": {
        "title": "光影",
        "title": "影途",
        "BROWSER": "Chrome",
        "env": {
          "UNI_PLATFORM": "mp-weixin",
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"
    },
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>
  </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>
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>
  
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', {
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;
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({
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'
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,
    }
})
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);
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;