Browse Source

Merge pull request 'fox' (#5) from fox into master

Reviewed-on: http://175.178.51.79:3000/Augcl/studytour-front/pulls/5
master
Fox 4 months ago
parent
commit
447ce43077
69 changed files with 1244 additions and 1691 deletions
  1. +1
    -1
      App.vue
  2. +6
    -2
      api/api.js
  3. +5
    -0
      api/model/activity.js
  4. +34
    -0
      api/model/bind.js
  5. +5
    -0
      api/model/comment.js
  6. +29
    -0
      api/model/coupon.js
  7. +8
    -0
      api/model/experience.js
  8. +8
    -2
      api/model/login.js
  9. +18
    -0
      api/model/notice.js
  10. +8
    -0
      api/model/order.js
  11. +1
    -1
      api/model/partner.js
  12. +3
    -3
      components/growing/recordsView.vue
  13. +35
    -26
      components/growing/userCard.vue
  14. +15
    -46
      components/home/pictureLiveView.vue
  15. +1
    -1
      components/home/productView.vue
  16. +9
    -4
      components/partner/posterPopup.vue
  17. +3
    -0
      components/product/productCard.vue
  18. +1
    -1
      config.js
  19. +68
    -17
      pages.json
  20. +10
    -64
      pages/index/category.vue
  21. +12
    -22
      pages/index/center.vue
  22. +35
    -36
      pages/index/growing.vue
  23. +4
    -1
      pages/index/index.vue
  24. +5
    -0
      pages/index/partner.vue
  25. +2
    -4
      pages_order/auth/wxLogin.vue
  26. +20
    -20
      pages_order/auth/wxUserInfo.vue
  27. +8
    -12
      pages_order/center/orderCard.vue
  28. +26
    -10
      pages_order/comment/commentCard.vue
  29. +79
    -31
      pages_order/comment/commentPopup.vue
  30. +2
    -14
      pages_order/comment/commentRecords.vue
  31. +43
    -12
      pages_order/comment/commentRecordsOfProduct.vue
  32. +81
    -76
      pages_order/comment/recordFormPopup.vue
  33. +2
    -0
      pages_order/components/reloateProjectPopup.vue
  34. +4
    -3
      pages_order/coupon/couponList/couponCard.vue
  35. +2
    -38
      pages_order/coupon/couponList/index.vue
  36. +3
    -3
      pages_order/coupon/couponSelect/couponCard.vue
  37. +2
    -38
      pages_order/coupon/couponSelect/index.vue
  38. +16
    -0
      pages_order/growing/activity/index.vue
  39. +20
    -18
      pages_order/live/formPopup.vue
  40. +30
    -77
      pages_order/live/index.vue
  41. +21
    -62
      pages_order/live/list.vue
  42. +15
    -7
      pages_order/member/memberApplyCard.vue
  43. +11
    -9
      pages_order/member/memberBind.vue
  44. +1
    -1
      pages_order/member/memberCard.vue
  45. +9
    -54
      pages_order/member/memberList.vue
  46. +3
    -43
      pages_order/member/switch.vue
  47. +10
    -7
      pages_order/message/card.vue
  48. +15
    -5
      pages_order/message/index.vue
  49. +1
    -2
      pages_order/message/list.vue
  50. +2
    -15
      pages_order/order/components/orderInfoView.vue
  51. +24
    -8
      pages_order/order/components/productCard.vue
  52. +75
    -114
      pages_order/order/orderConfirm/index.vue
  53. +54
    -61
      pages_order/order/orderConfirm/infoPopup.vue
  54. +14
    -8
      pages_order/order/orderConfirm/memberCard.vue
  55. +34
    -96
      pages_order/order/orderConfirm/peopleNumberInput.vue
  56. +2
    -3
      pages_order/order/orderConfirm/timeOptionsSelect.vue
  57. +44
    -157
      pages_order/order/orderDetail/index.vue
  58. +11
    -12
      pages_order/order/orderList/index.vue
  59. +27
    -30
      pages_order/order/orderList/orderCard.vue
  60. +87
    -133
      pages_order/order/orderPay/index.vue
  61. +3
    -3
      pages_order/partner/apply.vue
  62. +5
    -97
      pages_order/partner/team.vue
  63. +13
    -10
      pages_order/partner/withdraw.vue
  64. +5
    -5
      pages_order/product/commentList.vue
  65. +17
    -85
      pages_order/product/productDetail.vue
  66. +14
    -9
      pages_order/traveler/travelerCard.vue
  67. +2
    -4
      pages_order/traveler/travelerList.vue
  68. +24
    -43
      pages_order/traveler/travelerPopup.vue
  69. +37
    -25
      store/store.js

+ 1
- 1
App.vue View File

@ -3,7 +3,7 @@
onLaunch: function() {
},
onShow: function() {
// this.$store.commit('initConfig')
this.$store.commit('initConfig')
},
onHide: function() {
}


+ 6
- 2
api/api.js View File

@ -5,7 +5,7 @@ import utils from '../utils/utils.js'
let limit = {}
let debounce = {}
const models = ['login', 'index', 'image', 'activity', 'order', 'comment', 'experience', 'partner', 'info']
const models = ['login', 'index', 'image', 'activity', 'coupon', 'order', 'comment', 'bind', 'experience', 'partner', 'info', 'notice']
const config = {
// 示例
@ -14,7 +14,11 @@ const config = {
// limit : 1000
// },
getConfig : {url : '/config_common/getConfig', method : 'GET', limit : 500},
getConfig : {url : '/config/queryConfigList', method : 'GET', limit : 500},
queryConfigByParamCode : {url : '/config/queryConfigByParamCode', method : 'GET'},
queryPeriodList : {url : '/config/queryPeriodList', method : 'GET'},
queryCommentOptionList : {url : '/config/queryCommentOptionList', method : 'GET'},
queryExperienceQuestionList : {url : '/config/queryExperienceQuestionList', method : 'GET'},
}


+ 5
- 0
api/model/activity.js View File

@ -1,6 +1,11 @@
// 研学活动相关接口
const api = {
// 系统配置-查询研学活动分类列表
queryCategoryList: {
url: '/config/queryCategoryList',
method: 'GET',
},
// 首页&分类-查询研学活动列表
queryActivityList: {
url: '/activity/queryActivityList',


+ 34
- 0
api/model/bind.js View File

@ -0,0 +1,34 @@
// 成员管理相关接口
const api = {
// 成员管理-查询绑定成员列表
queryBindList: {
url: '/bind/queryBindList',
method: 'GET',
auth: true,
},
// 成员管理-查询绑定人信息
queryBindUser: {
url: '/bind/queryBindUser',
method: 'GET',
auth: true,
},
// 成员管理-绑定申请
addBind: {
url: '/bind/addBind',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
// 成员管理-审批绑定申请
updateBind: {
url: '/bind/updateBind',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
}
export default api

+ 5
- 0
api/model/comment.js View File

@ -1,6 +1,11 @@
// 评论相关接口
const api = {
// 我的评论-查询评价列表
queryCommentList: {
url: '/comment/queryCommentList',
method: 'GET',
},
// 我的评论-查询我的评价列表
queryMyCommentList: {
url: '/comment/queryMyCommentList',


+ 29
- 0
api/model/coupon.js View File

@ -0,0 +1,29 @@
// 优惠券相关接口
const api = {
// 优惠券-我的优惠券列表
queryCouponList: {
url: '/coupon/queryCouponList',
method: 'GET',
auth: true,
},
// 优惠券-根据id查看优惠券详情
queryCouponById: {
url: '/coupon/queryCouponById',
method: 'GET',
},
// 优惠券-查看可领取的优惠券
queryFetchCouponList: { // todo: check use in where?
url: '/coupon/queryFetchCouponList',
method: 'GET',
auth: true,
},
// 优惠券-领取优惠券
fetchCoupon: { // todo: check use in where?
url: '/coupon/fetchCoupon',
method: 'POST',
auth: true,
},
}
export default api

+ 8
- 0
api/model/experience.js View File

@ -11,6 +11,14 @@ const api = {
url: '/experience/queryExperienceById',
method: 'GET',
},
// 成长档案-新增成长档案
addExperience: {
url: '/experience/addExperience',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
}
export default api

+ 8
- 2
api/model/login.js View File

@ -18,7 +18,7 @@ const api = {
},
// 修改个人信息接口
updateInfo: {
url: '/info_common/updateInfo',
url: '/userInfo/updateUser',
method: 'POST',
auth: true,
limit : 500,
@ -26,7 +26,13 @@ const api = {
},
// 获取个人信息
getInfo: {
url: '/info_common/getInfo',
url: '/userInfo/queryUser',
method: 'GET',
auth: true,
},
// 获取个人基础数据
queryUserCenterData: {
url: '/userInfo/queryUserCenterData',
method: 'GET',
auth: true,
},


+ 18
- 0
api/model/notice.js View File

@ -0,0 +1,18 @@
// 开营通知相关接口
const api = {
// 开营通知-查询开营通知列表
queryNoticeList: {
url: '/notice/queryNoticeList',
method: 'GET',
auth: true,
},
// 开营通知-查询开营通知详情
queryNoticeById: {
url: '/notice/queryNoticeById',
method: 'GET',
auth: true,
},
}
export default api

+ 8
- 0
api/model/order.js View File

@ -19,6 +19,14 @@ const api = {
limit : 500,
showLoading : true,
},
// 我的订单-修改订单
updateOrder: {
url: '/order/updateOrder',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
// 我的订单-支付订单
payOrder: {
url: '/order/payOrder',


+ 1
- 1
api/model/partner.js View File

@ -31,7 +31,7 @@ const api = {
method: 'GET',
},
// 我的团队-获取间推用户列表
queryDirectList: {
queryIndirectList: {
url: '/partner/queryIndirectList',
method: 'GET',
},


+ 3
- 3
components/growing/recordsView.vue View File

@ -11,14 +11,14 @@
</view>
</template>
<template #title>
<view class="title" @click="onClickActivity(record.id)">{{ record.createTime }}</view>
<view class="title" @click="onClickActivity(record.id)">{{ $dayjs(record.createTime).format('YYYY-MM-DD') }}</view>
</template>
<template #desc>
<view class="content" @click="onClickActivity(record.id)">
<view class="desc">{{ record.name }}</view>
<view class="desc">{{ record.activityTitle || record.activityId_dictText || '' }}</view>
<view class="image">
<view class="image-item" v-for="(image, imgIdx) in record.image" :key="imgIdx">
<image class="img" :src="image" mode="scaleToFill"></image>
<image class="img" :src="image" mode="aspectFill"></image>
</view>
</view>
</view>


+ 35
- 26
components/growing/userCard.vue View File

@ -10,27 +10,27 @@
</view>
<view class="flex">
<button class="btn btn-switch" @click="onSwitch">切换</button>
<button class="btn btn-add" @click="onAdd">新增记录</button>
<!-- <button class="btn btn-add" @click="onAdd">新增记录</button> -->
</view>
</view>
<view class="card-content">
<view class="flex info">
<view class="avatar">
<image class="img" src="@/pages_order/static/temp-30.png" mode="scaleToFill"></image>
<image class="img" :src="memberInfo.headImage" mode="scaleToFill"></image>
<view :class="['tag', `tag-0`]">学生</view>
</view>
<view class="flex summary">
<view class="flex flex-column summary-item name">
<view class="summary-item-content">战斗世界</view>
<view class="summary-item-label">ID5625354</view>
<view class="summary-item-content">{{ memberInfo.nickName }}</view>
<view class="summary-item-label">{{ `ID:${memberInfo.id}` }}</view>
</view>
<view class="flex flex-column summary-item" @click="jumpToAchievement">
<view class="summary-item-content">8</view>
<view class="summary-item-label">成就</view>
<view class="summary-item-label nowrap">成就</view>
</view>
<view class="flex flex-column summary-item">
<view class="summary-item-content">68</view>
<view class="summary-item-label">足迹</view>
<view class="summary-item-label nowrap">足迹</view>
</view>
</view>
</view>
@ -49,31 +49,36 @@
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
import { mapState } from 'vuex'
},
methods: {
getData() {
// todo
export default {
data() {
return {
}
},
onAdd() {
this.$emit('addRecord')
onLoad() {
},
onSwitch() {
this.$emit('switchMember')
computed: {
...mapState(['memberInfo']),
},
jumpToAchievement() {
uni.navigateTo({
url: '/pages_order/growing/achievement/index'
})
methods: {
getData() {
// todo
},
onAdd() {
this.$emit('addRecord')
},
onSwitch() {
this.$emit('switchMember')
},
jumpToAchievement() {
uni.navigateTo({
url: '/pages_order/growing/achievement/index'
})
},
},
},
}
}
</script>
<style scoped lang="scss">
@ -199,4 +204,8 @@ export default {
}
}
.nowrap {
white-space: nowrap;
}
</style>

+ 15
- 46
components/home/pictureLiveView.vue View File

@ -27,7 +27,7 @@
<swiper-item v-for="item in list" :key="item.id" style="display: inline-block;">
<view class="swiper-item">
<view class="swiper-item-content" @click="jumpToLive(item.id)">
<image class="live-item-bg" :src="item.image" mode="aspectFill"></image>
<image class="live-item-bg" :src="item.url" mode="aspectFill"></image>
<view class="live-item-info">
<view class="text-ellipsis live-item-info-title">{{ item.title }}</view>
<view class="live-item-info-time">{{ item.createTime }}</view>
@ -52,57 +52,26 @@
},
methods: {
async getData() {
this.list = [
{
id: '001',
image: '/static/image/temp-15.png',
title: '苕溪露营漂流',
createTime: '2025-04-18',
},
{
id: '002',
image: '/static/image/temp-15.png',
title: '科技奇遇记',
createTime: '2025-04-18',
},
{
id: '003',
image: '/static/image/temp-15.png',
title: '满陇桂雨',
createTime: '2025-04-18',
},
{
id: '004',
image: '/static/image/temp-15.png',
title: '跟着皇帝游江南',
createTime: '2025-04-18',
},
{
id: '005',
image: '/static/image/temp-15.png',
title: '苕溪露营漂流',
createTime: '2025-04-18',
},
{
id: '006',
image: '/static/image/temp-15.png',
title: '科技奇遇记',
createTime: '2025-04-18',
},
]
return
// todo: check
try {
this.list = await this.$fetch('queryImageList', { pageNo: 1, pageSize: 8 })
this.list = (await this.$fetch('queryImageList', { pageNo: 1, pageSize: 8 }))?.records?.map(item => {
const { id, image, activityId_dictText, createTime } = item
const images = image?.split?.(',') || []
return {
id,
url: images?.[0],
images,
title: activityId_dictText,
createTime: this.$dayjs(createTime).format('YYYY-MM-DD'),
}
})
} catch (err) {
}
},
jumpToLive(id) {
this.$store.commit('setLiveInfo', this.list.find(item => item.id === id))
this.$utils.navigateTo(`/pages_order/live/index?id=${id}`)
},
showAll() {


+ 1
- 1
components/home/productView.vue View File

@ -73,7 +73,7 @@
// todo: fetch
this.tabs = [
{ name: '全部' },
{ id: '1962342791093227522', name: '研学活动一', disabled: true, },
// { id: '1962342791093227522', name: '', disabled: true, },
]
},
onClickTab(e) {


+ 9
- 4
components/partner/posterPopup.vue View File

@ -21,6 +21,8 @@
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
@ -30,6 +32,9 @@
retry: 10,
}
},
computed: {
...mapState(['userInfo', 'configList']),
},
async onLoad() {
},
methods: {
@ -45,6 +50,7 @@
this.wxCodeImage = 'https://uploadfile.bizhizu.cn/up/e3/64/e0/e364e0f7f6af11f11abdafc22d17b15c.jpg'
return
try {
const path = `pages/index/index?userId=${this.userInfo.id}`
this.wxCodeImage = (await this.$fetch('getInviteCode', { path }))?.url
} catch (err) {
@ -119,8 +125,7 @@
return new Promise(resolve => {
//
const avatarImage = canvas.createImage()
// todo: fetch
avatarImage.src = 'https://i1.hdslb.com/bfs/archive/c0101b4ce06e6bdda803728408e79c8f8b8d0725.jpg'
avatarImage.src = this.userInfo.headImage
avatarImage.onload = () => {
console.log('avatarImage onload')
@ -253,8 +258,8 @@
ctx.restore();
ctx.save()
let text = '战斗世界'
let maxWidth = 220 * Ratio / dpr
let text = this.userInfo.nickName
let maxWidth = 560 * Ratio / dpr
let lineHeight = 17 * Ratio / dpr
x = 100 * Ratio / dpr
y = 474 * Ratio / dpr


+ 3
- 0
components/product/productCard.vue View File

@ -218,11 +218,13 @@
justify-content: flex-start;
align-items: baseline;
column-gap: 12rpx;
flex-wrap: wrap;
&-val {
font-size: 24rpx;
font-weight: 500;
color: #FF4800;
white-space: nowrap;
.highlight {
font-size: 32rpx;
@ -249,6 +251,7 @@
color: #FFFFFF;
background: #00A9FF;
border-radius: 24rpx;
white-space: nowrap;
}
&.small {


+ 1
- 1
config.js View File

@ -14,7 +14,7 @@ const type = 'prod'
// 环境配置
const config = {
dev : {
baseUrl : 'http://www.gcosc.fun:82',
baseUrl : 'http://augcl.natapp1.cc/studytour-admin/studytour',
},
prod : {
baseUrl : 'https://www.hongyujiaoyu.com/studytour-admin/studytour',


+ 68
- 17
pages.json View File

@ -56,19 +56,28 @@
"path": "auth/loginAndRegisterAndForgetPassword"
},
{
"path": "product/search"
"path": "product/search",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "product/productDetail"
},
{
"path": "product/collectList"
"path": "product/collectList",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "order/orderConfirm/index"
},
{
"path": "order/orderPay/index"
"path": "order/orderPay/index",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "order/orderDetail/index",
@ -83,28 +92,49 @@
}
},
{
"path": "traveler/travelerList"
"path": "traveler/travelerList",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "coupon/couponSelect/index"
"path": "coupon/couponSelect/index",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "coupon/couponList/index"
"path": "coupon/couponList/index",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "comment/commentRecordsOfProduct"
"path": "comment/commentRecordsOfProduct",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "comment/commentRecords"
"path": "comment/commentRecords",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "growing/activity/search"
"path": "growing/activity/search",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "growing/activity/index"
},
{
"path": "growing/activity/markList"
"path": "growing/activity/markList",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "growing/activity/applyEmail"
@ -113,19 +143,34 @@
"path": "growing/achievement/index"
},
{
"path": "member/memberList"
"path": "member/memberList",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "member/memberBind"
"path": "member/memberBind",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "member/switch"
"path": "member/switch",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "live/list"
"path": "live/list",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "live/index"
"path": "live/index",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "partner/apply"
@ -137,13 +182,19 @@
"path": "partner/withdraw"
},
{
"path": "article/search"
"path": "article/search",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "article/index"
},
{
"path": "message/list"
"path": "message/list",
"style": {
"enablePullDownRefresh": true
}
},
{
"path": "message/index"


+ 10
- 64
pages/index/category.vue View File

@ -204,6 +204,9 @@
}
},
async onLoad({ categoryId }) {
if(uni.getStorageSync('token')){
this.$store.commit('getUserInfo')
}
await Promise.allSettled([this.fetchCategoryList(), this.fetchFilters()])
console.log('categoryList', this.categoryList)
@ -222,6 +225,13 @@
},
methods: {
async fetchCategoryList() {
try {
this.categoryList = (await this.$fetch('queryCategoryList', { pageSize: 1000 }))?.records?.map(item => ({ id: item.id, name: item.title, children: [] }))
} catch(err) {
this.categoryList = []
}
return
this.categoryList = [
{
"key": "1962345168240185345",
@ -363,12 +373,6 @@
}
})
return
try {
this.categoryList = (await this.$fetch('getCategoryList', { pageSize: 1000 }))?.records?.map(item => ({ id: item.id, name: item.name, children: [] }))
} catch(err) {
this.categoryList = []
}
},
async fetchFilters() {
@ -499,69 +503,11 @@
// todo: fetch
},
async queryProductList(categoryId) {
try {
return (await this.$fetch('queryActivityList', { ...this.queryParams, categoryId }))?.records || []
} catch (err) {
return []
}
return [
{
id: '001',
image: '/static/image/temp-20.png',
title: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
{
id: '002',
image: '/static/image/temp-20.png',
title: '坝上双草原6日|乌兰布统+锡林郭勒+长城',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
{
id: '003',
image: '/static/image/temp-20.png',
title: '牛湖线探秘 | 清远牛湖线徒步,探秘天坑与大草原',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
{
id: '004',
image: '/static/image/temp-20.png',
title: '低海拔藏区草原,汉藏文化大穿越',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
{
id: '005',
image: '/static/image/temp-20.png',
title: '新丝路到敦煌7日 | 甘青轻松穿越,沙漠+草原',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
{
id: '006',
image: '/static/image/temp-20.png',
title: '呼伦贝尔6/8日|经典or环线双套餐可选',
tagList: ['国内游','7-9天','12岁+'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
},
]
},
async initList() {
console.log('queryParams', this.queryParams)


+ 12
- 22
pages/index/center.vue View File

@ -9,18 +9,18 @@
<view class="flex user">
<!-- 用户信息 -->
<template v-if="isLogin">
<view class="user-avatar">
<!-- todo: check key -->
<image class="user-avatar-img" src="@/pages_order/static/temp-30.png" mode="scaleToFill"></image>
<view class="user-avatar" v-if="userInfo.headImage">
<image class="user-avatar-img" :src="userInfo.headImage" mode="scaleToFill"></image>
</view>
<view class="user-avatar is-default" v-else>
<image class="user-avatar-img" src="@/pages_order/static/center/avatar-default.png" mode="scaleToFill"></image>
</view>
<view class="user-info">
<!-- todo: check key -->
<view class="flex user-info-name">
<view class="highligt">战斗世界</view>
<view class="light">ID5625354</view>
<view class="highligt" v-if="userInfo.nickName">{{ userInfo.nickName || '' }}</view>
<view class="light">{{ `ID:${userInfo.id}` }}</view>
</view>
<!-- todo: check key -->
<view class="user-info-desc">手机号19989674531</view>
<view class="user-info-desc" v-if="userInfo.phone">{{ `手机号${userInfo.phone}` }}</view>
</view>
</template>
<template v-else>
@ -44,7 +44,7 @@
</view>
<!-- 订单信息 -->
<order-card :statistics="statistics"></order-card>
<order-card></order-card>
<!-- 用户菜单 -->
<view class="card">
@ -112,7 +112,6 @@
},
data() {
return {
statistics: {},
list1: [
{ id: '001', label: '我的收藏', icon: '/pages_order/static/center/icon-collect.png', path: '/pages_order/product/collectList' },
{ id: '004', label: '学员管理', icon: '/pages_order/static/center/icon-student.png', path: `/pages_order/member/memberList` },
@ -129,15 +128,13 @@
computed: {
...mapState(['userInfo', 'configList']),
isLogin() {
// todo: delete
return true
return this.userInfo && this.userInfo.id
}
},
onShow() {
if(uni.getStorageSync('token')){
this.$store.commit('getUserInfo')
this.fetchOrderStatistics()
this.$store.commit('getUserCenterData')
}
},
methods: {
@ -156,14 +153,6 @@
break
}
},
async fetchOrderStatistics() {
return
try {
this.statistics = await this.$fetch('getOrderStatistics', { id: '' })
} catch (err) {
}
},
jumpToBindMember() {
this.$utils.navigateTo('/pages_order/member/memberBind')
},
@ -239,7 +228,8 @@
&-name {
justify-content: flex-start;
column-gap: 16rpx;
flex-wrap: wrap;
gap: 16rpx;
font-family: PingFang SC;
color: #FFFFFF;


+ 35
- 36
pages/index/growing.vue View File

@ -60,48 +60,47 @@
return {
keyword: '',
isFocusSearch: false,
// todo
mixinsListApi: '',
queryParams: {
pageNo: 1,
pageSize: 10,
userId: '',
},
}
},
computed: {
...mapState(['memberInfo']),
mixinsListApi() {
return 'queryExperienceList'
// todo
return this.queryParams.userId ? 'queryExperienceList' : ''
},
},
onLoad() {
if(uni.getStorageSync('token')){
this.$store.commit('getUserInfo')
}
},
onShow() {
// todo: set queryParams.userId by memberInfo
if (!this.memberInfo && this.userInfo.id) {
this.$store.commit('setMemberInfo', this.userInfo)
}
// this.queryParams.userId = this.memberInfo.id
// this.getData()
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
name: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
image: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
],
createTime: '2025-07-12',
},
{
id: '002',
name: '仙踪新昌·韩妃江古道|邂逅“江南小桂林”',
image: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
],
createTime: '2025-06-18',
},
{
id: '003',
name: '山水石窟·大佛寺|江南佛窟造像,新昌山水轻徒',
image: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
],
createTime: '2025-06-15',
},
]
getDataThen(records) {
this.list = records.map(item => {
const { id, name, image, createTime } = item
return {
id,
// todo: check key
name,
image: image?.split?.(',') || [],
createTime
}
})
},
search() {
console.log('search', this.keyword)


+ 4
- 1
pages/index/index.vue View File

@ -103,6 +103,9 @@
}
},
onLoad() {
if(uni.getStorageSync('token')){
this.$store.commit('getUserInfo')
}
},
computed: {
searchStyle() {
@ -155,7 +158,7 @@
top: 0;
left: 0;
width: 100%;
padding: 100rpx 32rpx calc(120rpx + env(safe-area-inset-bottom) + 100rpx) 32rpx;
padding: 100rpx 32rpx calc(120rpx + env(safe-area-inset-bottom) + 32rpx) 32rpx;
box-sizing: border-box;
}


+ 5
- 0
pages/index/partner.vue View File

@ -112,6 +112,11 @@
mixinsListApi: '',
}
},
onLoad() {
if(uni.getStorageSync('token')){
this.$store.commit('getUserInfo')
}
},
onShow() {
// todo: refresh is partner?
},


+ 2
- 4
pages_order/auth/wxLogin.vue View File

@ -3,10 +3,8 @@
<view class="flex flex-column content">
<!-- todo: check key -->
<image class="logo" src="@/pages_order/static/temp-29.png" mode="widthFix"></image>
<!-- todo: check key -->
<view class="name">鸿宇研学生</view>
<image class="logo" :src="configList.config_logo" mode="widthFix"></image>
<view class="name">{{ configList.app_name }}</view>
<button class="btn btn-login flex" @click="wxLogin" > </button>


+ 20
- 20
pages_order/auth/wxUserInfo.vue View File

@ -15,14 +15,14 @@
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="name" :customStyle="formItemStyle">
<uv-form-item prop="nickName" :customStyle="formItemStyle">
<view class="form-item-label">昵称</view>
<view class="form-item-content input">
<input
type="nickname"
placeholder="请输入"
placeholderStyle="color: #C6C6C6; font-size: 32rpx; font-weight: 400;"
v-model="form.name"
v-model="form.nickName"
/>
</view>
</uv-form-item>
@ -45,12 +45,12 @@
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="phone" :customStyle="formItemStyle">
<uv-form-item prop="headImage" :customStyle="formItemStyle">
<view class="form-item-label">头像</view>
<view class="form-item-content input">
<button class="btn btn-avatar" :plain="true" :hairline="false" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
<view v-if="form.avatar" class="avatar">
<image class="img" :src="form.avatar" mode="aspectFill"></image>
<view v-if="form.headImage" class="avatar">
<image class="img" :src="form.headImage" mode="aspectFill"></image>
<view class="flex mask">
<image class="icon" src="@/pages_order/static/icon-change.png" mode="widthFix" />
</view>
@ -93,12 +93,12 @@
data() {
return {
form: {
name: null,
nickName: null,
phone: null,
avatar: null,
headImage: null,
},
rules: {
'name': {
'nickName': {
type: 'string',
required: true,
message: '请输入昵称',
@ -108,9 +108,9 @@
required: true,
message: '请输入手机号',
},
'avatar': {
type: 'array',
required: true,
'headImage': {
type: 'string',
required: false,
message: '请选择头像',
},
},
@ -123,15 +123,15 @@
onLoad(arg) {
this.mode = arg.mode
this.form.name = this.userInfo.name || ''
this.form.nickName = this.userInfo.nickName || ''
this.form.phone = this.userInfo.phone || ''
this.form.avatar = this.userInfo.avatar || ''
this.form.headImage = this.userInfo.headImage || ''
},
methods: {
onChooseAvatar(res) {
this.$Oss.ossUpload(res.target.avatarUrl)
.then(url => {
this.form.avatar = url
this.form.headImage = url
})
},
getPhone(e){
@ -141,7 +141,8 @@
if(res.code == 200){
if(res.success){
this.form.phone = res.result
const result = JSON.parse(res.result)
this.form.phone = result.phone_info.phoneNumber
}else{
uni.showModal({
title: res.message
@ -155,18 +156,17 @@
await this.$refs.form.validate()
const {
name,
nickName,
phone,
avatar,
headImage,
} = this.form
const params = {
name,
nickName,
phone,
avatar,
headImage,
}
// todo: check 415 Unsupported Media Type
const res = await this.$fetch('updateInfo', params, false)
if (res.code == 200) {


+ 8
- 12
pages_order/center/orderCard.vue View File

@ -11,27 +11,23 @@
</template>
<script>
import { mapState } from 'vuex'
export default {
props: {
statistics: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
}
},
computed: {
...mapState(['userCenterData']),
list() {
return [
{ id: '001', label: '待支付', value: this.statistics[0] || 0, index: 1, icon: '/pages_order/static/center/order-1.png' },
{ id: '002', label: '待发货', value: this.statistics[1] || 0, index: 2, icon: '/pages_order/static/center/order-2.png' },
{ id: '003', label: '待收货', value: this.statistics[2] || 0, index: 3, icon: '/pages_order/static/center/order-3.png' },
// 0 1 2
{ id: '001', label: '待支付', value: this.userCenterData.orderStatus0 || 0, index: 1, icon: '/pages_order/static/center/order-1.png' },
{ id: '002', label: '已支付', value: this.userCenterData.orderStatus1 || 0, index: 2, icon: '/pages_order/static/center/order-2.png' },
{ id: '003', label: '已完成', value: this.userCenterData.orderStatus2 || 0, index: 3, icon: '/pages_order/static/center/order-3.png' },
// todo: check
{ id: '004', label: '售后', value: this.statistics['afterSales'] || 0, index: 0, icon: '/pages_order/static/center/order-4.png' },
{ id: '004', label: '售后', value: 0, index: 0, icon: '/pages_order/static/center/order-4.png' },
{ id: '005', label: '全部', index: 0, icon: '/pages_order/static/center/order-5.png' },
]
}


+ 26
- 10
pages_order/comment/commentCard.vue View File

@ -5,10 +5,10 @@
<view class="flex left">
<view class="avatar">
<!-- todo: check key -->
<image class="avatar-img" :src="data.user.avatar" mode="scaleToFill"></image>
<image class="avatar-img" :src="data.user.headImage" mode="scaleToFill"></image>
</view>
<view class="info">
<view class="name">{{ data.user.name }}</view>
<view class="name">{{ data.user.nickName }}</view>
<view>{{ $dayjs(data.createTime).format('YYYY-MM-DD') }}</view>
</view>
</view>
@ -24,28 +24,28 @@
<view class="section score">
<view class="flex score-item">
<view class="score-item-label">行程</view>
<formRate :value="data.tripNum" :readonly="true"></formRate>
<formRate :value="data.processScore" :readonly="true"></formRate>
</view>
<view class="flex score-item">
<view class="score-item-label">景点</view>
<formRate :value="data.spotNum" :readonly="true"></formRate>
<formRate :value="data.spotScore" :readonly="true"></formRate>
</view>
<view class="flex score-item">
<view class="score-item-label">导师</view>
<formRate :value="data.mentorNum" :readonly="true"></formRate>
<formRate :value="data.teacherScore" :readonly="true"></formRate>
</view>
</view>
<view class="section operate">
<view class="flex section operate">
<button class="flex btn" @click="onComment">
<image class="icon" src="@/pages_order/static/comment/icon-comment.png" mode="aspectFill"></image>
<image class="icon" src="@/pages_order/static/comment/icon-comment.png" mode="widthFix"></image>
<view>评论</view>
</button>
<button v-if="data.liked" class="flex btn" @click="onLike">
<image class="icon" src="@/pages_order/static/comment/icon-like-active.png" mode="aspectFill"></image>
<image class="icon" src="@/pages_order/static/comment/icon-like-active.png" mode="widthFix"></image>
<view>点赞</view>
</button>
<button v-else class="flex btn" @click="onCancelLike">
<image class="icon" src="@/pages_order/static/comment/icon-like.png" mode="aspectFill"></image>
<image class="icon" src="@/pages_order/static/comment/icon-like.png" mode="widthFix"></image>
<view>点赞</view>
</button>
</view>
@ -89,7 +89,7 @@
images() {
const { image } = this.data || {}
return image?.split?.(',')
return image?.split?.(',')?.filter(val => val)
},
disabled() {
return this.mode !== 'edit'
@ -223,6 +223,22 @@
}
}
.operate {
justify-content: flex-start;
column-gap: 24rpx;
.btn {
column-gap: 8rpx;
font-size: 24rpx;
color: #999999;
.icon {
width: 32rpx;
height: auto;
}
}
}
.comment {
&-user {
column-gap: 16rpx;


+ 79
- 31
pages_order/comment/commentPopup.vue View File

@ -14,50 +14,50 @@
errorType="toast"
>
<view class="section">
<productCard :data="detail"></productCard>
<productCard :data="productCardData" style="background: linear-gradient(120deg, #DAF3FF, #FBFEFF 30%, #FBFEFF); border: 2rpx solid #FFFFFF;"></productCard>
</view>
<view class="section">
<view class="form-item">
<uv-form-item prop="tripNum" :customStyle="formItemStyle">
<uv-form-item prop="processScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">行程</view>
<view class="form-item-content">
<formRate v-model="form.tripNum"></formRate>
<formRate v-model="form.processScore"></formRate>
</view>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="spotNum" :customStyle="formItemStyle">
<uv-form-item prop="spotScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">景点</view>
<view class="form-item-content">
<formRate v-model="form.spotNum"></formRate>
<formRate v-model="form.spotScore"></formRate>
</view>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="mentorNum" :customStyle="formItemStyle">
<uv-form-item prop="teacherScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">导师</view>
<view class="form-item-content">
<formRate v-model="form.mentorNum"></formRate>
<formRate v-model="form.teacherScore"></formRate>
</view>
</view>
</uv-form-item>
</view>
</view>
<view class="form-item">
<uv-form-item prop="content" :customStyle="formItemStyle">
<uv-form-item prop="contentIds" :customStyle="formItemStyle">
<view class="form-item-content">
<view class="tags">
<view
v-for="(item, oIdx) in options" :key="oIdx"
:class="['tag', item === form.content ? 'is-active' : '']"
@click="onSelectContent(item)"
v-for="(item, oIdx) in configList.commentOptionList" :key="oIdx"
:class="['tag', form.contentIds.includes(item.id) ? 'is-active' : '']"
@click="onSelectContent(item.id)"
>
{{ item }}
{{ item.title }}
</view>
</view>
</view>
@ -89,29 +89,29 @@
// todo: fetch
detail: {},
form: {
tripNum: null,
spotNum: null,
mentorNum: null,
content: null,
processScore: null,
spotScore: null,
teacherScore: null,
contentIds: [],
},
rules: {
'tripNum': {
'processScore': {
type: 'number',
required: true,
message: '请为行程打分',
},
'spotNum': {
'spotScore': {
type: 'number',
required: true,
message: '请为景点打分',
},
'mentorNum': {
'teacherScore': {
type: 'number',
required: true,
message: '请为导师打分',
},
'content': {
type: 'string',
'contentIds': {
type: 'array',
required: true,
message: '请选择评语',
},
@ -120,20 +120,52 @@
options: [],
}
},
computed: {
productCardData() {
const {
activityId,
activityTitle,
activityBrief,
activityTag,
startDate,
endDate,
} = this.detail
return {
time: 'time',
product: {
id: activityId,
title: activityTitle,
brief: activityBrief,
tagDetails: activityTag,
dateList: [
{
id: 'time',
startDate,
endDate,
}
]
}
}
},
},
methods: {
async getData() {
// todo: fetch order product
},
async open(id) {
async open(id, detail) {
console.log('open', id, detail)
this.id = id
await this.getData()
this.detail = detail
// todo: fetch order product
// await this.getData()
this.form = {
tripNum: null,
spotNum: null,
mentorNum: null,
content: null,
processScore: null,
spotScore: null,
teacherScore: null,
contentIds: [],
}
this.$refs.popup.open()
@ -144,21 +176,36 @@
onPopupChange(e) {
this.isShow = e.show
},
onSelectContent(content) {
this.form.content = content
onSelectContent(id) {
let arr = this.form.contentIds
this.form.contentIds = arr.includes(id) ? arr.filter(item => item !== id) : arr.concat(id)
},
async onPublish() {
try {
await this.$refs.form.validate()
const {
processScore,
spotScore,
teacherScore,
contentIds,
} = this.form
const commentOptionList = this.configList.commentOptionList
const content = contentIds.map(id => {
return commentOptionList.find(item => item.id === id)?.title
}).join('、')
const params = {
orderId: this.id,
processScore,
spotScore,
teacherScore,
content,
}
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('addComment', params)
uni.showToast({
icon: 'success',
@ -180,6 +227,7 @@
<style lang="scss" scoped>
.popup__view {
width: 100vw;
display: flex;
flex-direction: column;


+ 2
- 14
pages_order/comment/commentRecords.vue View File

@ -12,7 +12,7 @@
<image class="icon" src="@/static/image/icon-mark-highlight.png" mode="widthFix"></image>
</view>
<view class="title">
{{ `来自 ${item.productName}` }}
{{ `来自 ${item.activityTitle || ''}` }}
</view>
</view>
<commentCard :data="item"></commentCard>
@ -36,21 +36,9 @@
},
data() {
return {
// todo
mixinsListApi: '',
mixinsListApi: 'queryMyCommentList',
}
},
onShow() {
console.log('onShow')
},
onLoad(arg) {
console.log('onLoad')
const { productId } = arg
this.queryParams.productId = productId
this.getData()
},
methods: {
},
}


+ 43
- 12
pages_order/comment/commentRecordsOfProduct.vue View File

@ -1,7 +1,7 @@
<template>
<view class="page__view">
<navbar title="全部评" leftClick @leftClick="$utils.navigateBack" bgColor="#FFFFFF" />
<navbar title="全部评" leftClick @leftClick="$utils.navigateBack" bgColor="#FFFFFF" />
<view class="main">
@ -28,19 +28,17 @@
},
data() {
return {
// todo
mixinsListApi: '',
queryParams: {
pageNo: 1,
pageSize: 10,
activityId: '',
},
mixinsListApi: 'queryCommentList',
}
},
onShow() {
console.log('onShow')
},
onLoad(arg) {
console.log('onLoad')
const { productId } = arg
this.queryParams.productId = productId
const { id } = arg
this.queryParams.activityId = id
this.getData()
},
methods: {
@ -63,8 +61,41 @@
border-radius: 24rpx;
&-item {
padding-bottom: 40rpx;
border-bottom: 2rpx solid #F5F5F5;
& + & {
margin-top: 16rpx;
margin-top: 40rpx;
}
&:last-child {
border: none;
}
&-header {
justify-content: flex-start;
column-gap: 24rpx;
margin-bottom: 14rpx;
.mark {
width: 36rpx;
height: 36rpx;
background: linear-gradient(to right, #21FEEC, #019AF9);
border-radius: 50%;
.icon {
width: 24rpx;
height: auto;
}
}
.title {
flex: 1;
font-size: 30rpx;
font-weight: 600;
line-height: 1.4;
color: #00A9FF;
}
}
}
}


+ 81
- 76
pages_order/comment/recordFormPopup.vue View File

@ -10,18 +10,17 @@
<uv-form
ref="form"
:model="form"
:rules="rules"
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="project" :customStyle="formItemStyle">
<uv-form-item prop="activityId" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
关联项目
</view>
<view class="form-item-content">
<view class="flex row" @click="openRelatePojectPicker">
<view v-if="form.project" class="text">{{ projectDesc }}</view>
<view v-if="form.activityId" class="text">{{ projectDesc }}</view>
<view v-else class="text placeholder">请选择关联项目</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
@ -30,31 +29,31 @@
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="tripNum" :customStyle="formItemStyle">
<uv-form-item prop="processScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">行程</view>
<view class="form-item-content">
<formRate v-model="form.tripNum"></formRate>
<formRate v-model="form.processScore"></formRate>
</view>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="spotNum" :customStyle="formItemStyle">
<uv-form-item prop="spotScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">景点</view>
<view class="form-item-content">
<formRate v-model="form.spotNum"></formRate>
<formRate v-model="form.spotScore"></formRate>
</view>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="mentorNum" :customStyle="formItemStyle">
<uv-form-item prop="teacherScore" :customStyle="formItemStyle">
<view class="flex row">
<view class="form-item-label">导师</view>
<view class="form-item-content">
<formRate v-model="form.mentorNum"></formRate>
<formRate v-model="form.teacherScore"></formRate>
</view>
</view>
</uv-form-item>
@ -67,11 +66,11 @@
</view>
</uv-form-item>
</view>
<view class="form-item" v-for="(item, index) in questions" :key="item.id">
<view class="form-item" v-for="(item, index) in configList.experienceQuestionList" :key="item.id">
<uv-form-item :prop="`texts[${index}]`" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
{{ item.label }}
{{ item.question }}
</view>
<view class="form-item-content">
<formTextarea v-model="form.texts[index]"></formTextarea>
@ -89,6 +88,8 @@
</template>
<script>
import { mapState } from 'vuex'
import reloateProjectPopup from '@/pages_order/components/reloateProjectPopup.vue'
import formTextarea from '@/pages_order/components/formTextarea.vue'
import formUpload from '@/pages_order/components/formUpload.vue'
@ -105,88 +106,74 @@
return {
isShow: false,
form: {
project: null,
tripNum: null,
spotNum: null,
mentorNum: null,
activityId: null,
processScore: null,
spotScore: null,
teacherScore: null,
images: [],
texts: [],
},
rules: {
// todo
},
projects: [],
questions: [],
}
},
computed: {
...mapState(['userInfo', 'configList']),
projectDesc() {
const { project } = this.form
const target = this.projects?.find?.(item => item.id === project)
const { activityId } = this.form
const target = this.projects?.find?.(item => item.id === activityId)
return target?.name || ''
},
},
methods: {
getData() {
// todo
this.projects = [
{
id: '001',
name: '亲子•坝上双草原6日 |乌兰布统+锡林郭勒+长城',
},
{
id: '002',
name: '青青草原•云中岭 |5-10公里AB线强度可选',
},
{
id: '003',
name: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
},
{
id: '004',
name: '九色甘南|人间净土6日/7日深度游',
},
{
id: '005',
name: '北疆全景12日| 入疆首推!阿勒泰+伊犁+吐鲁番',
},
{
id: '006',
name: '塞上江南•神奇宁夏5日|穿越大漠与历史对话',
},
{
id: '007',
name: '尊享•天山环线9日| 伊犁全景+独库,头等舱大巴',
},
]
async fetchProjectOptions() {
try {
const records = (await this.$fetch('queryExperienceList', { pageNo: 1, pageSize: 1000, }))?.records
this.projects = records.map(item => {
return {
id: item.activityId,
name: item.activityTitle || item.activityId_dictText || ''
}
})
} catch (err) {
this.questions = [
{
id: '001',
label: '这次研学之旅,整体给你留下了怎样的印象?用几个词或几句话简单概括一下',
},
{
id: '002',
label: '在整个行程中,你最喜欢的部分是哪里?为什么?',
},
{
id: '003',
label: '你觉得这次研学的行程安排是否合理?有没有哪些地方让你觉得特别满意或需要改进的?',
}
},
setRules() {
const rules = {
'activityId': {
type: 'string',
required: true,
message: '请选择关联项目',
},
]
}
// todo: check
// this.questions.forEach((item, index) => {
// rules[`texts[${index}]`] = {
// type: 'string',
// required: true,
// message: `${item.label}`,
// }
// })
this.$refs.form.setRules(rules)
},
async open() {
await this.getData()
await this.fetchProjectOptions()
const texts = this.questions.map(() => '')
console.log('projects', this.projects)
console.log('experienceQuestionList', this.configList.experienceQuestionList)
const texts = this.configList.experienceQuestionList.map(() => '')
this.form = {
project: null,
tripNum: null,
spotNum: null,
mentorNum: null,
activityId: null,
processScore: null,
spotScore: null,
teacherScore: null,
images: [],
texts,
}
@ -198,25 +185,43 @@
},
onPopupChange(e) {
this.isShow = e.show
// todo: need settimeout?
setTimeout(() => {
this.setRules()
}, 800)
},
openRelatePojectPicker() {
this.$refs.reloateProjectPopup.open(this.form.project?.id || null)
this.$refs.reloateProjectPopup.open(this.form.activityId || null)
},
onRelateProjectChange(id) {
this.form.project = id
this.form.activityId = id
},
async onPublish() {
try {
await this.$refs.form.validate()
const {
activityId,
processScore,
spotScore,
teacherScore,
images,
texts,
} = this.form
const params = {
// todo: check
userId: this.userInfo.id,
activityId,
processScore,
spotScore,
teacherScore,
image: images.join(','),
content: texts.join('\r\n') // todo: check
}
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('addExperience', params)
uni.showToast({
icon: 'success',


+ 2
- 0
pages_order/components/reloateProjectPopup.vue View File

@ -49,6 +49,8 @@
methods: {
async open(projectId) {
this.selectedId = projectId
console.log('selectedId', this.selectedId)
console.log('options', this.options)
this.$refs.popup.open()
},
close() {


+ 4
- 3
pages_order/coupon/couponList/couponCard.vue View File

@ -1,11 +1,11 @@
<template>
<view class="flex card">
<view class="flex price">
¥<view class="highlight">{{ data.price }}</view>
¥<view class="highlight">{{ data.discountAmount }}</view>
</view>
<view class="flex flex-column info">
<view class="title">{{ data.label }}</view>
<view class="desc">{{ `有效期至 ${data.validTime}` }}</view>
<view class="title">{{ data.title }}</view>
<view class="desc">{{ `有效期至 ${$dayjs(data.validDate).format('YYYY-MM-DD')}` }}</view>
<button class="btn" @click="jumpToCategory">去使用</button>
</view>
</view>
@ -88,6 +88,7 @@
font-size: 30rpx;
font-weight: 500;
line-height: 1.4;
color: #FFFFFF;
background: linear-gradient(to right, #21FEEC, #019AF9);
border: 2rpx solid #00A9FF;
border-radius: 28rpx;


+ 2
- 38
pages_order/coupon/couponList/index.vue View File

@ -28,52 +28,16 @@
},
data() {
return {
// todo: check key
mixinsListApi: '',
mixinsListApi: 'queryCouponList',
queryParams: {
pageNo: 1,
pageSize: 10,
status: 0,
},
selectedId: null,
}
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
label: '专属福利】20元红包',
price: 20,
validTime: '2026-04-28',
},
{
id: '002',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '003',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '004',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '005',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
]
},
onSelect(id) {
console.log('onSelect', id)
this.selectedId = id


+ 3
- 3
pages_order/coupon/couponSelect/couponCard.vue View File

@ -4,11 +4,11 @@
<uv-radio :name="data.id"></uv-radio>
</view>
<view class="flex price">
¥<view class="highlight">{{ data.price }}</view>
¥<view class="highlight">{{ data.discountAmount }}</view>
</view>
<view class="flex flex-column info">
<view class="title">{{ data.label }}</view>
<view class="desc">{{ `有效期至 ${data.validTime}` }}</view>
<view class="title">{{ data.title }}</view>
<view class="desc">{{ `有效期至 ${data.validDate}` }}</view>
</view>
</view>
</template>


+ 2
- 38
pages_order/coupon/couponSelect/index.vue View File

@ -38,11 +38,11 @@
},
data() {
return {
// todo: check key
mixinsListApi: '',
mixinsListApi: 'queryCouponList',
queryParams: {
pageNo: 1,
pageSize: 10,
status: 0,
},
selectedId: null,
}
@ -67,42 +67,6 @@
this.$store.commit('setCouponInfo', target)
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
label: '专属福利】20元红包',
price: 20,
validTime: '2026-04-28',
},
{
id: '002',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '003',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '004',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
{
id: '005',
label: '专属福利】400元红包',
price: 400,
validTime: '2026-04-28',
},
]
},
},
}
</script>


+ 16
- 0
pages_order/growing/activity/index.vue View File

@ -112,6 +112,22 @@
},
methods: {
async getData() {
try {
const result = await this.$fetch('queryExperienceById', { recordId: this.id })
const { image, thoughts } = result
this.detail = {
highlights: image?.split?.(',') || [],
// todo: check key
thoughts,
// todo: check key about ""
}
} catch (err) {
}
return
// todo
this.detail = {


+ 20
- 18
pages_order/live/formPopup.vue View File

@ -14,14 +14,14 @@
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="project" :customStyle="formItemStyle">
<uv-form-item prop="activityId" :customStyle="formItemStyle">
<view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
关联项目
</view>
<view class="form-item-content">
<view class="flex row" @click="openRelatePojectPicker">
<view v-if="form.project" class="text">{{ projectDesc }}</view>
<view v-if="form.activityId" class="text">{{ projectDesc }}</view>
<view v-else class="text placeholder">请选择关联项目</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
@ -75,14 +75,14 @@
data() {
return {
form: {
project: null,
activityId: null,
area: null,
latitude: null,
longitude: null,
images: [],
},
rules: {
'project': {
'activityId': {
type: 'string',
required: true,
message: '请选择关联项目',
@ -104,8 +104,8 @@
},
computed: {
projectDesc() {
const { project } = this.form
const target = this.projects?.find?.(item => item.id === project)
const { activityId } = this.form
const target = this.projects?.find?.(item => item.id === activityId)
return target?.name || ''
},
@ -160,18 +160,15 @@
]
},
async open(id) {
// todo: auto bind project by id?
// todo: auto bind activityId by id?
await this.getData()
const texts = this.questions.map(() => '')
this.form = {
project: null,
tripNum: null,
spotNum: null,
mentorNum: null,
activityId: null,
area: null,
latitude: null,
longitude: null,
images: [],
texts,
}
this.$refs.popup.open()
@ -180,10 +177,10 @@
this.$refs.popup.close()
},
openRelatePojectPicker() {
this.$refs.reloateProjectPopup.open(this.form.project?.id || null)
this.$refs.reloateProjectPopup.open(this.form.activityId?.id || null)
},
onRelateProjectChange(id) {
this.form.project = id
this.form.activityId = id
},
//
selectAddr() {
@ -212,13 +209,18 @@
await this.$refs.form.validate()
const {
activityId,
area,
images,
} = this.form
const params = {
activityId,
address: area,
image: images.join(',')
}
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('addImage', params)
uni.showToast({
icon: 'success',


+ 30
- 77
pages_order/live/index.vue View File

@ -1,14 +1,14 @@
<template>
<view class="page__view highlight">
<navbar :title="detail.title" leftClick @leftClick="$utils.navigateBack" />
<navbar :title="liveInfo.title" leftClick @leftClick="$utils.navigateBack" />
<view class="header">
<image class="cover-img" :src="detail.image" mode="widthFix"></image>
<image class="cover-img" :src="liveInfo.url" mode="widthFix"></image>
<view class="flex" style="padding: 40rpx 40rpx 0 40rpx;">
<view class="flex flex-column">
<view class="title">{{ detail.title }}</view>
<view class="tag">{{ detail.createTime }}</view>
<view class="title">{{ liveInfo.title }}</view>
<view class="tag">{{ liveInfo.createTime }}</view>
</view>
<view v-if="isManager" class="flex operate">
<view class="btn btn-add" @click="onAdd">新增记录</view>
@ -25,7 +25,7 @@
</view>
<view class="info">
<view class="flex title">
<view>{{ item.name }}</view>
<view>{{ item.createBy }}</view>
<image class="icon" src="@/static/image/icon-location.png" mode="widthFix"></image>
<view class="address text-ellipsis">{{ item.address }}</view>
</view>
@ -34,7 +34,7 @@
</view>
<view class="section-content record">
<view class="record-item" v-for="(image, imgIdx) in item.images" :key="imgIdx">
<image class="img" :src="image" mode="scaleToFill"></image>
<image class="img" :src="image" mode="aspectFill"></image>
</view>
</view>
</view>
@ -47,6 +47,8 @@
</template>
<script>
import { mapState } from 'vuex'
import mixinsList from '@/mixins/list.js'
import SYStackedCarousel from '@/uni_modules/SY-StackedCarousel/components/SY-StackedCarousel/SY-StackedCarousel.vue'
@ -60,93 +62,44 @@
},
data() {
return {
id: null,
detail: {},
bannerList: [],
current: 0,
queryParams: {
pageNo: 1,
pageSize: 10,
id: '',
imageId: '',
},
// todo
mixinsListApi: '',
mixinsListApi: 'queryImageContentList',
// todo: fetch
isManager: false,
isManager: true,
}
},
computed: {
swiperCurrent() {
return this.bannerList[this.current]
},
...mapState(['liveInfo']),
},
onLoad(arg) {
const { id } = arg
this.id = id
this.fetchDetail()
this.queryParams.id = id
this.queryParams.imageId = id
this.getData()
},
methods: {
async fetchDetail() {
// todo: fetch
this.detail = {
id: '001',
image: '/static/image/temp-20.png',
title: '趣玩新加坡',
createTime: '2025-04-18',
}
},
// todo: delete
getData() {
this.list = [
{
id: '001',
avatar: '/pages_order/static/temp-30.png',
name: '战斗世界',
address: '241 Orchard Road, Singapore 238863',
createTime: '2023-04-18 12:00:00',
images: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
]
},
{
id: '001',
avatar: '/pages_order/static/temp-30.png',
name: '战斗世界',
address: '10 Bayfront Avenue, Singapore 018956',
createTime: '2023-04-18 12:00:00',
images: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
]
},
]
},
clickHandler(item, index) {
console.log("item: ", item);
console.log("index: ", index);
this.current = index
},
changeHandler(index) {
console.log("当前触发change事件,返回索引: ", index);
getCoverImage(image) {
return image?.split?.(',')?.[0]
},
getDataThen(records) {
this.list = records.map(item => {
const { id, avatar, createBy, address, image, createTime } = item
return {
id,
// todo: check key
avatar: avatar || '/pages_order/static/center/avatar-default.png',
createBy,
address,
images: image?.split?.(',') || [],
createTime,
}
})
},
onAdd() {
this.$refs.formPopup.open()


+ 21
- 62
pages_order/live/list.vue View File

@ -6,7 +6,7 @@
<view class="swiper">
<SYStackedCarousel
height="536rpx"
:images="bannerList"
:images="list"
:current="current"
:autoplay="true"
horizontalMargin="25"
@ -42,7 +42,7 @@
</view>
<view class="section-content record">
<view class="record-item" v-for="(image, imgIdx) in item.images" :key="imgIdx">
<image class="img" :src="image" mode="scaleToFill"></image>
<image class="img" :src="image" mode="aspectFill"></image>
</view>
</view>
</view>
@ -70,79 +70,37 @@
},
data() {
return {
bannerList: [],
current: 0,
queryParams: {
pageNo: 1,
pageSize: 10,
id: '',
},
// todo
mixinsListApi: '',
mixinsListApi: 'queryImageList',
// todo: fetch
isManager: true,
}
},
computed: {
swiperCurrent() {
return this.bannerList[this.current]
return this.list[this.current]
},
},
onLoad() {
this.fetchBanner()
async onLoad() {
this.getData()
},
methods: {
async fetchBanner() {
this.bannerList = [
{
url: '/static/image/temp-20.png',
title: '趣玩新加坡',
createTime: '2025-04-18',
},
{
url: '/static/image/temp-20.png',
title: '坝上双草原',
createTime: '2025-04-18',
},
{
url: '/static/image/temp-20.png',
title: '牛湖线',
createTime: '2025-04-18',
},
]
},
// todo: delete
getData() {
this.list = [
{
id: '001',
title: '桂林深度游',
images: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
]
},
{
id: '002',
title: '西双版纳雨林10+体验',
images: [
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
'/pages_order/static/temp-38.png',
]
},
]
getDataThen(records) {
this.list = records.map(item => {
const { id, image, activityId_dictText, createTime } = item
const images = image?.split?.(',') || []
return {
id,
url: images?.[0],
images,
title: activityId_dictText,
createTime: this.$dayjs(createTime).format('YYYY-MM-DD'),
}
})
},
clickHandler(item, index) {
console.log("item: ", item);
console.log("index: ", index);
this.current = index
},
changeHandler(index) {
@ -155,6 +113,7 @@
this.$refs.formPopup.open()
},
showAll(id) {
this.$store.commit('setLiveInfo', this.list.find(item => item.id === id))
this.$utils.navigateTo(`/pages_order/live/index?id=${id}`)
},
},


+ 15
- 7
pages_order/member/memberApplyCard.vue View File

@ -7,7 +7,7 @@
</view>
<view class="row">
<view class="row-label">申请人ID</view>
<view class="row-content">{{ data.userId }}</view>
<view class="row-content">{{ data.bindId }}</view>
</view>
<view class="row">
<view class="row-label">申请时间</view>
@ -44,13 +44,21 @@
}
},
methods: {
onReject() {
// todo: fetch reject
this.$emit('submitted')
async fetchUpdate(status) {
try {
await this.$fetch('updateBind', { id: this.data.id, status }) // (status)0- 1- 2-
return true
} catch (err) {
return false
}
},
async onReject() {
const succ = await this.fetchUpdate(2)
succ && this.$emit('submitted')
},
onConfirm() {
// todo: fetch confirm
this.$emit('submitted')
async onConfirm() {
const succ = await this.fetchUpdate(1)
succ && this.$emit('submitted')
},
},
}


+ 11
- 9
pages_order/member/memberBind.vue View File

@ -16,7 +16,7 @@
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="id" :customStyle="formItemStyle">
<uv-form-item prop="bindId" :customStyle="formItemStyle">
<view class="form-item-label">绑定人ID</view>
<view class="form-item-content">
<view class="flex search">
@ -37,7 +37,7 @@
<view class="form-item" v-for="item in list" :key="item.id">
<view
:class="['flex', 'list-item', item.id === form.id ? 'is-active' : '']"
@click="onSelect"
@click="onSelect(item.id)"
>
<view class="avatar">
<image class="img" :src="item.avatar" mode="scaleToFill"></image>
@ -55,7 +55,7 @@
</view>
<view class="bottom">
<button class="btn" @click="onSubmit">提现</button>
<button class="btn" @click="onSubmit">申请</button>
</view>
</view>
@ -82,10 +82,10 @@
// todo
mixinsListApi: '',
form: {
id: null,
bindId: null,
},
rules: {
'id': {
'bindId': {
type: 'string',
required: true,
message: '请选择绑定人',
@ -99,21 +99,23 @@
this.queryParams.title = this.keyword
this.getData()
},
onSelect(id) {
this.form.id = id
onSelect(bindId) {
this.form.bindId = bindId
},
async onSubmit() {
try {
await this.$refs.form.validate()
const {
bindId,
} = this.form
const params = {
bindId,
userId: this.userInfo.id,
}
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('addBind', params)
uni.showToast({
icon: 'success',


+ 1
- 1
pages_order/member/memberCard.vue View File

@ -11,7 +11,7 @@
</view>
<view class="row">
<view class="row-label">申请人ID</view>
<view class="row-content">{{ data.userId }}</view>
<view class="row-content">{{ data.bindId }}</view>
</view>
</view>
</view>


+ 9
- 54
pages_order/member/memberList.vue View File

@ -8,7 +8,7 @@
<view class="tabs">
<uv-tabs
:list="tabs"
:current="current"
:current="queryParams.status"
:scrollable="false"
lineColor="#00A9FF"
lineWidth="48rpx"
@ -32,7 +32,7 @@
</view>
<view class="list">
<template v-if="current == 0">
<template v-if="queryParams.status == 0">
<view class="list-item" v-for="item in list" :key="item.id">
<memberApplyCard :data="item" @submitted="getData"></memberApplyCard>
</view>
@ -68,9 +68,12 @@
{ name: '绑定申请' },
{ name: '已绑定' },
],
// todo
mixinsListApi: '',
current: 0,
queryParams: {
pageNo: 1,
pageSize: 10,
status: 0, // (status)0- 1- 2-
},
mixinsListApi: 'queryBindList',
}
},
onShow() {
@ -80,57 +83,9 @@
this.clickTabs({ index: arg.index || 0 })
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
name: '周小艺',
userId: '15558661691',
type: 0,
createTime: '2025-04-28 08:14',
},
{
id: '002',
name: '周小艺',
userId: '15558661691',
type: 0,
createTime: '2025-04-28 08:14',
},
{
id: '003',
name: '周小艺',
userId: '15558661691',
type: 1,
createTime: '2025-04-28 08:14',
},
{
id: '004',
name: '周小艺',
userId: '15558661691',
type: 0,
createTime: '2025-04-28 08:14',
},
{
id: '005',
name: '周小艺',
userId: '15558661691',
type: 0,
createTime: '2025-04-28 08:14',
},
]
},
//tab
clickTabs({ index }) {
console.log('clickTabs')
this.current = index
if (index == 0) {
delete this.queryParams.status
} else {
this.queryParams.status = index - 1
}
this.queryParams.status = index
this.getData()
},
},


+ 3
- 43
pages_order/member/switch.vue View File

@ -11,7 +11,6 @@
size="36rpx"
iconSize="36rpx"
activeColor="#00A9FF"
@change="onRadioChange"
>
<view class="list-item" v-for="item in list" :key="item.id">
<memberCard
@ -40,12 +39,12 @@
},
data() {
return {
// todo: check key
mixinsListApi: '',
queryParams: {
pageNo: 1,
pageSize: 10,
status: 1, // (status)0- 1- 2-
},
mixinsListApi: 'queryBindList',
selectedId: null,
}
},
@ -54,7 +53,7 @@
},
onLoad(arg) {
if (this.memberInfo?.id) {
this.memberInfo = this.memberInfo.id
this.selectedId = this.memberInfo.id
}
this.getData()
@ -69,49 +68,10 @@
this.$store.commit('setMemberInfo', target)
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
name: '周小艺',
userId: '15558661691',
type: 0,
},
{
id: '002',
name: '周小艺',
userId: '15558661691',
type: 0,
},
{
id: '003',
name: '周小艺',
userId: '15558661691',
type: 1,
},
{
id: '004',
name: '周小艺',
userId: '15558661691',
type: 0,
},
{
id: '005',
name: '周小艺',
userId: '15558661691',
type: 0,
},
]
},
onSelect(id) {
console.log('onSelect', id)
this.selectedId = id
},
onRadioChange(e) {
console.log('onRadioChange', e)
},
},
}
</script>


+ 10
- 7
pages_order/message/card.vue View File

@ -5,12 +5,12 @@
<view class="desc">{{ data.createTime }}</view>
</view>
<view class="card-content">
{{ data.content }}
<uv-parse :content="data.content"></uv-parse>
</view>
<view class="card-footer">
<button class="btn">了解详情</button>
<button class="btn" @click="jumpToDetail">了解详情</button>
</view>
<view v-if="data.new" class="dot"></view>
<view v-if="data.isRead == '0'" class="dot"></view>
</view>
</template>
@ -41,7 +41,9 @@ export default {
font-weight: 400;
line-height: 1.4;
background-image: linear-gradient(164deg,#DAF3FF 88rpx, #FBFEFF 176rpx, #FBFEFF);
background: linear-gradient(110deg, #DAF3FF, #FBFEFF 25%, #FBFEFF);
border: 2rpx solid #FFFFFF;
border-radius: 32rpx;
&-header {
.title {
@ -58,14 +60,15 @@ export default {
&-content {
margin-top: 16rpx;
max-height: 176rpx;
font-size: 26rpx;
line-height: 1.7;
color: #666666;
overflow: hidden;
text-overflow: ellipsis;
display:-webkit-box; //
-webkit-box-orient:vertical; //--
-webkit-line-clamp:4; //
// text-overflow: ellipsis;
// display:-webkit-box; //
// -webkit-box-orient:vertical; //--
// -webkit-line-clamp:4; //
}
&-footer {


+ 15
- 5
pages_order/message/index.vue View File

@ -1,6 +1,6 @@
<template>
<view class="page__view">
<navbar title="详情" leftClick @leftClick="$utils.navigateBack" />
<navbar title="详情" leftClick @leftClick="$utils.navigateBack" bgColor="#FFFFFF" />
<view class="main">
<view class="card">
@ -9,18 +9,21 @@
<view class="desc">{{ detail.createTime }}</view>
</view>
<view class="card-content">
{{ detail.content }}
<uv-parse :content="detail.content"></uv-parse>
</view>
</view>
</view>
<view class="bottom">
<view class="flex bottom">
<button plain class="flex flex-column btn btn-simple" open-type="contact">
<image class="icon" src="@/pages_order/static/product/icon-service.png" mode="widthFix"></image>
<view>联系客服</view>
</button>
<button class="col btn" @click="onContactMentor">联系导师</button>
</view>
<contactMentorPopup ref="contactMentorPopup" ></contactMentorPopup>
</view>
</template>
@ -45,9 +48,15 @@
},
methods: {
async getData() {
// todo
// todo: mark read
try {
this.detail = await this.$fetch('queryNoticeById', { noticeId: this.id })
} catch (err) {
}
},
onContactMentor() {
this.$refs.contactMentorPopup.open(this.detail.teacherPhone)
},
},
}
@ -58,6 +67,7 @@
.page__view {
width: 100vw;
min-height: 100vh;
background: $uni-bg-color;
position: relative;
/deep/ .nav-bar__view {


+ 1
- 2
pages_order/message/list.vue View File

@ -25,8 +25,7 @@
},
data() {
return {
// todo: check key
mixinsListApi: '',
mixinsListApi: 'queryNoticeList',
}
},
methods: {


+ 2
- 15
pages_order/order/components/orderInfoView.vue View File

@ -23,7 +23,7 @@
<view class="row-content">
<view class="flex total-price">
<view>¥</view>
<view class="highlight">{{ totalPrice }}</view>
<view class="highlight">{{ data.payAmount }}</view>
<view class="light" v-if="data.discount">
{{ `优惠(${data.discount}` }}
</view>
@ -46,7 +46,7 @@
<view class="card-header">订单信息</view>
<view class="row">
<view class="row-label">订单编号</view>
<view class="row-content">{{ data.orderNo }}</view>
<view class="row-content">{{ data.id }}</view>
</view>
<view class="row">
<view class="row-label">下单时间</view>
@ -94,19 +94,6 @@
return timeOptions?.find?.(item => item.id === time) || {}
},
totalPrice() {
const { adults, teenager, child } = this.data
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage
let total = 0
adults && (total += adults * (adultsPrice || 0))
teenager && (total += teenager * (teenagerPrice || 0))
child && (total += child * (childPrice || 0))
return total
},
members() {
const { members } = this.data
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage


+ 24
- 8
pages_order/order/components/productCard.vue View File

@ -1,10 +1,10 @@
<template>
<view class="card info">
<view class="card-header">{{ product.name }}</view>
<view class="card info" :style="style">
<view class="card-header">{{ product.title }}</view>
<view class="card-content">
<view class="row desc">{{ product.desc }}</view>
<view class="flex row tags" v-if="product.tags && product.tags.length">
<view class="tag" v-for="(tag, tIdx) in product.tags" :key="tIdx">
<view class="row desc">{{ product.brief }}</view>
<view class="flex row tags" v-if="tagList.length">
<view class="tag" v-for="(tag, tIdx) in tagList" :key="tIdx">
{{ tag }}
</view>
</view>
@ -45,11 +45,17 @@
product() {
return this.data?.product || {}
},
tagList() {
// todo: check key
const { tagDetails } = this.product || {}
return tagDetails?.length ? tagDetails.split('、') : []
},
productPackage() {
const { time, product } = this.data
const { timeOptions } = product || {}
const { time, product } = this.data || {}
const { dateList } = product || {}
return timeOptions?.find?.(item => item.id === time) || {}
return dateList?.find?.(item => item.id === time) || {}
},
days() {
console.log('productPackage', this.productPackage)
@ -58,6 +64,15 @@
return this.$dayjs(endDate).diff(this.$dayjs(startDate), 'day')
},
},
watch: {
data: {
handler(val) {
console.log('watch data', val)
},
deep: true,
immediate: true
},
},
}
</script>
@ -92,6 +107,7 @@
.desc {
font-size: 26rpx;
white-space: pre-wrap;
color: #8B8B8B;
}


+ 75
- 114
pages_order/order/orderConfirm/index.vue View File

@ -40,15 +40,10 @@
<view class="card-header">订单详情</view>
<view style="margin-top: 16rpx;">
<uv-form-item prop="members" :customStyle="formItemStyle">
<!-- style="width: calc(100vw - 40rpx*2);" -->
<view>
<peopleNumberInput
:adults.sync="form.adults"
:teenager.sync="form.teenager"
:child.sync="form.child"
:adultsPrice="productPackage.adultsPrice"
:teenagerPrice="productPackage.teenagerPrice"
:childPrice="productPackage.childPrice"
<peopleNumberInput style="width: calc(100vw - 40rpx*2);"
v-model="form.prices"
:options="orderInfo.priceList"
></peopleNumberInput>
<memberChooseView
@ -65,7 +60,7 @@
<view class="form-item-label">选择优惠券</view>
<view class="form-item-content">
<view class="flex row" @click="jumpToSelectCoupon">
<view v-if="form.couponId" class="text">{{ couponInfo.label }}</view>
<view v-if="form.couponId" class="text">{{ couponInfo.title }}</view>
<view v-else class="text placeholder">请选择</view>
<uv-icon name="arrow-right" color="#C6C6C6" size="32rpx"></uv-icon>
</view>
@ -161,14 +156,41 @@
data() {
return {
form: {
name: null,
phone: null,
adults: 0,
teenager: 0,
child: 0,
name: '',
phone: '',
prices: [],
members: [],
couponId: null,
receiptId: null,
couponId: '',
receiptId: '',
},
rules: {
'name': {
type: 'string',
required: true,
message: '请输入真实姓名',
},
'phone': {
type: 'string',
required: true,
message: '请输入手机号码',
},
'prices': {
type: 'array',
message: '请选择人数',
validator: (rule, value, callback) => {
if (value.some(num => num > 0)) {
return true
}
return false
},
},
'members': {
type: 'array',
required: true,
message: '请选择出行人',
},
},
checkboxValue: [],
formItemStyle: { padding: 0 },
@ -178,39 +200,31 @@
...mapState(['configList', 'userInfo', 'orderInfo', 'couponInfo']),
productPackage() {
const { time, product } = this.orderInfo
const { timeOptions } = product || {}
const { dateList } = product || {}
return timeOptions?.find?.(item => item.id === time) || {}
return dateList?.find?.(item => item.id === time) || {}
},
totolPeople() {
const { adults, teenager, child } = this.form
const { prices } = this.orderInfo
return (adults || 0) + (teenager || 0) + (child || 0)
return prices.reduce((total, num) => {
return total + num
}, 0)
},
totalPrice() {
const { adults, teenager, child, couponId } = this.form
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage
priceOrigin() {
const { prices, priceList } = this.orderInfo
let total = 0
adults && (total += adults * (adultsPrice || 0))
teenager && (total += teenager * (teenagerPrice || 0))
child && (total += child * (childPrice || 0))
couponId && (total -= (this.couponInfo?.price || 0))
return total
return prices.reduce((total, num, index) => {
return total + priceList[index].price * (num || 0)
}, 0)
},
discount() {
return this.couponInfo?.discountAmount || 0
},
totalPrice() {
return this.priceOrigin - this.discount
},
},
watch: {
form: {
handler(val) {
this.$refs.form.setRules(this.getRules())
},
deep: true
}
},
onShow() {
if (this.couponInfo) {
this.form.couponId = this.couponInfo.id
@ -221,65 +235,27 @@
console.log('orderInfo', this.orderInfo)
this.initData()
},
onReady() {
this.$refs.form.setRules(this.getRules())
},
onReady() {
this.$refs.form.setRules(this.rules);
},
onUnload() {
this.$store.commit('setCouponInfo', null)
},
methods: {
getRules() {
const { adults, teenager, child } = this.form
return {
'name': {
type: 'string',
required: true,
message: '请输入真实姓名',
},
'phone': {
type: 'string',
required: true,
message: '请输入手机号码',
},
'adults': {
type: 'number',
required: true,
message: '请选择人数',
validator: (rule, value, callback) => {
if (adults || teenager || child) {
return true
}
return false
},
},
'members': {
type: 'array',
required: true,
message: '请选择出行人',
},
}
},
initData() {
const {
time,
adults,
teenager,
child,
prices,
members,
} = this.orderInfo
this.form = {
name: null,
phone: null,
adults,
teenager,
child,
name: '',
phone: '',
prices,
members: members.map(item => ({ ...item, isSelected: true })),
couponId: null,
receiptId: null,
couponId: '',
receiptId: '',
}
},
jumpToSelectCoupon() {
@ -323,52 +299,37 @@
const {
name,
phone,
adults,
teenager,
child,
prices,
members,
couponId,
receiptId,
} = this.form
const { startDate, endDate } = time
const { startDate, endDate } = this.productPackage
let params = {
activityId: product.id,
startDate,
endDate,
dayNum: this.$dayjs(endDate).diff(this.$dayjs(startDate), 'day'),
couponId,
receiptId,
name,
phone,
priceOrigin: this.priceOrigin,
discount: this.discount,
priceDiscount: this.totalPrice,
payAmount: this.totalPrice,
tourisIds: members.map(touris => touris.id).join(',')
}
const result = await this.$fetch('createOrder', params)
// todo: check result includes order id?
const orderId = await this.$fetch('createOrder', params)
const orderInfo = {
product,
couponInfo: this.couponInfo,
time,
adults,
teenager,
child,
members,
couponId,
receiptId,
name,
phone,
}
this.$store.commit('setOrderInfo', orderInfo)
// todo: get id?
uni.navigateTo({
url: `/pages_order/order/orderPay/index?id=${result.id}`
url: `/pages_order/order/orderPay/index?id=${orderId}`
})
} catch (err) {
console.log('createOrder', err)
}
},


+ 54
- 61
pages_order/order/orderConfirm/infoPopup.vue View File

@ -8,6 +8,7 @@
<uv-form
ref="form"
:model="form"
:rules="rules"
errorType="toast"
>
<view class="section">
@ -19,28 +20,24 @@
<image class="img" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image>
</button>
</view>
<timeCalendarSelect ref="timeCalendarSelect" v-model="form.time" :options="data.timeOptions"></timeCalendarSelect>
<timeCalendarSelect ref="timeCalendarSelect" v-model="form.time" :options="data.dateList"></timeCalendarSelect>
<view class="flex section-content">
<timeOptionsSelect style="width: calc(100vw - 40rpx*2);"
v-model="form.time"
:options="data.timeOptions"
:options="data.dateList"
></timeOptionsSelect>
</view>
</uv-form-item>
</view>
<view class="section">
<uv-form-item prop="adults" :customStyle="formItemStyle">
<uv-form-item prop="prices" :customStyle="formItemStyle">
<view class="flex section-header">
<view>选择人数</view>
</view>
<view class="flex section-content">
<peopleNumberInput style="width: calc(100vw - 40rpx*2);"
:adults.sync="form.adults"
:teenager.sync="form.teenager"
:child.sync="form.child"
:adultsPrice="selectTimeObj.adultsPrice"
:teenagerPrice="selectTimeObj.teenagerPrice"
:childPrice="selectTimeObj.childPrice"
v-model="form.prices"
:options="priceList"
></peopleNumberInput>
</view>
</uv-form-item>
@ -77,6 +74,12 @@
import timeCalendarSelect from '@/pages_order/order/orderConfirm/timeCalendarSelect.vue'
import peopleNumberInput from '@/pages_order/order/orderConfirm/peopleNumberInput.vue'
const TYPE_INDEX_MAPPING = {
'成人': 0,
'青少年': 1,
'儿童': 2,
}
export default {
components: {
timeOptionsSelect,
@ -96,61 +99,21 @@
options: [],
form: {
time: null,
adults: 0,
teenager: 0,
child: 0,
prices: [],
members: [],
},
formItemStyle: { padding: 0 },
}
},
computed : {
...mapState(['configList', 'travelerList']),
selectTimeObj() {
const { time: id } = this.form
const { timeOptions } = this.data
if (id) {
return timeOptions?.find?.(option => option.id === id) || {}
}
return timeOptions?.[0] || {}
},
},
watch: {
travelerList(val) {
if (val?.length) {
this.form.members = val
this.$store.commit('setTravelerList', [])
}
},
form: {
handler(val) {
this.$refs.form.setRules(this.getRules())
},
deep: true
}
},
onReady() {
this.$refs.form.setRules(this.getRules())
},
methods: {
getRules() {
const { adults, teenager, child } = this.form
return {
rules: {
'time': {
type: 'string',
required: true,
message: '请选择团期',
},
'adults': {
type: 'number',
required: true,
'prices': {
type: 'array',
message: '请选择人数',
validator: (rule, value, callback) => {
if (adults || teenager || child) {
if (value.some(num => num > 0)) {
return true
}
@ -162,14 +125,47 @@
required: true,
message: '请选择出行人',
},
},
formItemStyle: { padding: 0 },
}
},
computed : {
...mapState(['configList', 'userInfo', 'travelerList']),
priceList() {
const { time: id } = this.form
const { dateList } = this.data
let priceList = dateList?.[0]?.priceList || []
if (id) {
priceList = dateList?.find?.(option => option.id === id)?.priceList || []
}
priceList.sort((a, b) => {
return TYPE_INDEX_MAPPING[a.period_dictText] - TYPE_INDEX_MAPPING[b.period_dictText]
})
return priceList
},
},
watch: {
travelerList(val) {
if (val?.length) {
this.form.members = val
this.$store.commit('setTravelerList', [])
}
},
},
onReady() {
this.$refs.form.setRules(this.rules);
},
methods: {
openTimePicker() {
this.$refs.timeCalendarSelect.open()
},
async getDefaultMembers() {
try {
return (await this.$fetch('queryTouristList', { isDefault: '1' })).records
return (await this.$fetch('queryTouristList', { pageNo: 1, pageSize: 1000, isDefault: '1' })).records
} catch (err) {
return []
}
@ -202,18 +198,15 @@
const {
time,
adults,
teenager,
child,
prices,
members,
} = this.form
const orderInfo = {
product: this.data,
priceList: this.priceList,
time,
adults,
teenager,
child,
prices,
members,
}
this.$store.commit('setOrderInfo', orderInfo)


+ 14
- 8
pages_order/order/orderConfirm/memberCard.vue View File

@ -16,7 +16,7 @@
<view class="info">
<view class="flex name">
<view>{{ data.name }}</view>
<view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view>
<view :class="['tag', `tag-${type}`]">{{ typeDesc }}</view>
</view>
<view class="id">{{ data.cerNo }}</view>
</view>
@ -24,12 +24,6 @@
</template>
<script>
const MEMBER_TYPE_AND_DESC_MAPPING = {
0: '成人',
1: '青少年',
2: '儿童',
}
export default {
props: {
@ -61,7 +55,19 @@
}
},
typeDesc() {
return MEMBER_TYPE_AND_DESC_MAPPING[this.data.type]
const { periodId } = this.data
return this.configList.periodList?.find?.(item => item.id === periodId)?.title
},
type() {
if (this.typeDesc == '青少年') {
return 1
}
if (this.typeDesc == '儿童') {
return 2
}
return 0
},
},
watch: {


+ 34
- 96
pages_order/order/orderConfirm/peopleNumberInput.vue View File

@ -1,69 +1,19 @@
<template>
<view class="input__view" :style="style">
<view class="flex row">
<view class="flex row" v-for="(item, index) in options" :key="item.id">
<view class="flex row-label">
<view class="title">成人</view>
<view class="desc">(18周岁以上)</view>
<view class="title">{{ item.period_dictText }}</view>
<!-- todo: check key -->
<view class="desc" v-if="getTypeDesc(item.period_dictText)">{{ `(${getTypeDesc(item.period_dictText)})` }}</view>
<view class="flex price">
<text>¥</text>
<text class="highlight">{{ adultsPrice }}</text>
<text class="highlight">{{ item.price }}</text>
</view>
</view>
<view class="row-content">
<uv-number-box
v-model="adultsNum"
:min="0"
:integer="true"
:inputWidth="68"
bgColor="transparent"
:iconStyle="{
background: '#F7F8FA',
fontSize: '13px',
lineHeight: 1,
padding: '12px',
borderRadius: '50%',
}"
></uv-number-box>
</view>
</view>
<view class="flex row">
<view class="flex row-label">
<view class="title">青少年</view>
<view class="desc">(14周岁以上)</view>
<view class="flex price">
<text>¥</text>
<text class="highlight">{{ teenagerPrice }}</text>
</view>
</view>
<view class="row-content">
<uv-number-box
v-model="teenagerNum"
:min="0"
:integer="true"
:inputWidth="68"
bgColor="transparent"
:iconStyle="{
background: '#F7F8FA',
fontSize: '13px',
lineHeight: 1,
padding: '12px',
borderRadius: '50%',
}"
></uv-number-box>
</view>
</view>
<view class="flex row">
<view class="flex row-label">
<view class="title">儿童</view>
<view class="desc">(14周岁以下)</view>
<view class="flex price">
<text>¥</text>
<text class="highlight">{{ childPrice }}</text>
</view>
</view>
<view class="row-content">
<uv-number-box
v-model="childNum"
:value="value[index]"
@input="onInput(index, $event)"
:min="0"
:integer="true"
:inputWidth="68"
@ -82,31 +32,25 @@
</template>
<script>
const TYPE_DESC = {
'成人': '(18周岁以上)',
'青少年': '(14周岁以上)',
'儿童': '(14周岁以下)',
}
export default {
props: {
adults: {
type: Number,
default: 0,
},
teenager: {
type: Number,
default: 0,
},
child: {
type: Number,
default: 0,
},
adultsPrice: {
type: Number,
default: 0,
},
teenagerPrice: {
type: Number,
default: 0,
value: {
type: Array,
default() {
return []
}
},
childPrice: {
type: Number,
default: 0,
options: {
type: Array,
default() {
return []
}
},
style: {
type: String,
@ -114,29 +58,23 @@
},
},
computed: {
adultsNum: {
prices: {
set(val) {
this.$emit('update:adults', val)
this.$emit('input', val)
},
get() {
return this.adults
return this.value
}
},
teenagerNum: {
set(val) {
this.$emit('update:teenager', val)
},
get() {
return this.teenager
}
},
methods: {
onInput(index, value) {
let prices = [...this.prices]
prices[index] = value
this.prices = prices
},
childNum: {
set(val) {
this.$emit('update:child', val)
},
get() {
return this.child
}
getTypeDesc(type) {
return TYPE_DESC[type]
},
},
}


+ 2
- 3
pages_order/order/orderConfirm/timeOptionsSelect.vue View File

@ -8,9 +8,9 @@
>
<view class="option-item-content">
<view class="flex time">
<view class="time-val">{{ item.startDate }}</view>
<view class="time-val">{{ $dayjs(item.startDate).format('MM/DD') }}</view>
<view class="time-split">-</view>
<view class="time-val">{{ item.endDate }}</view>
<view class="time-val">{{ $dayjs(item.endDate).format('MM/DD') }}</view>
</view>
<view class="flex price">
<view class="price-val">
@ -126,7 +126,6 @@
.price {
margin-top: 4rpx;
justify-content: flex-start;
align-items: baseline;
column-gap: 8rpx;
white-space: nowrap;


+ 44
- 157
pages_order/order/orderDetail/index.vue View File

@ -4,7 +4,7 @@
<view class="main">
<productCard :data="detail"></productCard>
<productCard :data="productCardData"></productCard>
<orderInfoView :data="detail"></orderInfoView>
@ -19,30 +19,6 @@
</view>
<view class="bottom">
<view class="agreement">
<uv-checkbox-group
v-model="checkboxValue"
shape="circle"
>
<uv-checkbox
size="40rpx"
icon-size="40rpx"
activeColor="#00A9FF"
:name="1"
></uv-checkbox>
</uv-checkbox-group>
<view class="desc">
我已阅读并同意
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_agreement', '退订政策')">退订政策</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '合同范本')">合同范本</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '预订须知')">预订须知</text>
<!-- todo: 替换配置项key -->
<text class="highlight" @click="$refs.modal.open('config_privacy', '安全提示')">安全提示</text>
</view>
</view>
<view class="flex bar">
<button plain class="flex flex-column btn btn-simple" open-type="contact">
<image class="icon" src="@/pages_order/static/product/icon-service.png" mode="widthFix"></image>
@ -51,15 +27,14 @@
<!-- 已支付 -->
<template v-if="detail.status == 1">
<button class="col btn" @click="onContactMentor">联系导师</button>
<button class="col btn" @click.stop="onFinish">已完成</button>
</template>
<!-- 待评价 -->
<template v-else-if="data.status == 2">
<button class="btn" @click="onComment">立即评价</button>
</template>
<!-- 已完成 -->
<template v-else-if="detail.status == 3">
<button class="col btn" @click="onComment">立即评价</button>
<button class="col btn" @click="onApplyService">申请售后</button>
</template>
<view class="col" v-else></view>
</view>
</view>
@ -67,8 +42,6 @@
<commentPopup ref="commentPopup" @submitted="getData"></commentPopup>
<agreementModal ref="modal" @confirm="onConfirmAgreement"></agreementModal>
</view>
</template>
@ -79,7 +52,6 @@
import orderInfoView from '@/pages_order/order/components/orderInfoView.vue'
import contactMentorPopup from '@/pages_order/order/components/contactMentorPopup.vue'
import commentPopup from '@/pages_order/comment/commentPopup.vue'
import agreementModal from '@/pages_order/components/agreementModal.vue'
export default {
components: {
@ -87,7 +59,6 @@
orderInfoView,
contactMentorPopup,
commentPopup,
agreementModal,
},
data() {
return {
@ -97,27 +68,33 @@
},
computed: {
...mapState(['configList', 'userInfo', 'orderInfo']),
productPackage() {
const { time, product } = this.detail
const { timeOptions } = product || {}
return timeOptions?.find?.(item => item.id === time) || {}
productCardData() {
const {
activityId,
activityTitle,
activityBrief,
activityTag,
startDate,
endDate,
} = this.detail
return {
time: 'time',
product: {
id: activityId,
title: activityTitle,
brief: activityBrief,
tagDetails: activityTag,
dateList: [
{
id: 'time',
startDate,
endDate,
}
]
}
}
},
totalPrice() {
const { adults, teenager, child, coupon, couponInfo } = this.detail
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage
let total = 0
adults && (total += adults * (adultsPrice || 0))
teenager && (total += teenager * (teenagerPrice || 0))
child && (total += child * (childPrice || 0))
coupon && (total -= (couponInfo?.price || 0))
return total
},
},
onLoad(arg) {
const { id } = arg
@ -125,8 +102,9 @@
this.getData()
},
onPullDownRefresh() {
this.getData()
async onPullDownRefresh() {
await this.getData()
uni.stopPullDownRefresh()
},
methods: {
async getData() {
@ -134,119 +112,28 @@
this.detail = await this.$fetch('queryOrderById', { orderId: this.id })
return
this.detail = {
product: {
id: '001',
image: new Array(6).fill('/static/image/temp-20.png').join(','),
name: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
desc: '每天车程4小时内,含一程高铁丨喀拉峻草原、夏塔古道、昭苏天马、赛里木湖、昭苏油菜花、伊犁薰衣草丨吐鲁番坎儿井&火焰山',
tags: ['坝上草原', '自然探索', '户外探索', '亲子游玩'],
priceDiscount: 688.99,
priceOrigin: 1200,
registered: 4168,
timeOptions: [
{
id: '0011',
startDate: '08/25',
endDate: '09/01',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0012',
startDate: '09/02',
endDate: '09/11',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0013',
startDate: '09/12',
endDate: '09/19',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
],
},
time: "0012",
adults: 2,
teenager: 1,
child: 1,
members: [
{
id: "001",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "李梓发",
type: 0,
},
{
id: "002",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "吴彦谦",
type: 0,
},
{
id: "003",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "冯云",
type: 1,
},
{
id: "004",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "冯思钗",
type: 2,
},
],
coupon: "001",
discount: 88,
invoice: null,
name: "测试",
phone: "13345678910",
orderNo: 'BH872381728321983929',
createTime: '2025-04-28 08:14',
mentorPhone: '0731-599327-8899',
status: 1,
}
console.log('orderInfo', this.detail)
// todo: check fetch by id?
// this.detail = await this.$fetch('queryOrderById', { id: this.id })
} catch (err) {
}
uni.stopPullDownRefresh()
},
onComment(id) {
this.$refs.commentPopup.open(id)
onComment() {
this.$refs.commentPopup.open(this.id, this.detail)
},
onApplyService() {
// todo
},
onContactMentor() {
this.$refs.contactMentorPopup.open(this.detail.mentorPhone)
this.$refs.contactMentorPopup.open(this.detail.teacherPhone)
},
async onFinish() {
try {
await this.$fetch('updateOrder', { id: this.id, status: '2' }) // 0 1 2
this.getData()
} catch (err) {
}
},
},
}


+ 11
- 12
pages_order/order/orderList/index.vue View File

@ -35,7 +35,7 @@
<view class="card" v-for="item in list" :key="item.id">
<orderCard
:data="item"
@comment="onComment(item.id)"
@comment="onComment(item.id, item)"
@applyService="onApplyService"
@contatcMentor="onContactMentor"
@statusChange="getData"
@ -44,7 +44,7 @@
</view>
<contactMentorPopup ref="contactMentorPopup" :phone="data.mentorPhone"></contactMentorPopup>
<contactMentorPopup ref="contactMentorPopup" ></contactMentorPopup>
<commentPopup ref="commentPopup" @submitted="getData"></commentPopup>
@ -68,16 +68,15 @@
},
data() {
return {
// 0 1 2 3 4
// 0 1 2 // isService0- 1-
tabs: [
{ name: '全部' },
{ name: '待支付' },
{ name: '待发货' },
{ name: '待收货' },
{ name: '待评价' },
{ name: '已支付' },
{ name: '已完成' },
{ name: '售后' },
],
// todo
mixinsListApi: '',
mixinsListApi: 'queryOrderList',
current: 0,
}
},
@ -100,15 +99,15 @@
}
this.getData()
},
onComment(id) {
this.$refs.commentPopup.open(id)
onComment(id, detail) {
this.$refs.commentPopup.open(id, detail)
},
onApplyService(obj) {
// todo
// this.$refs.serviceSelectPopup.open(obj)
},
onContactMentor(mentorPhone) {
this.$refs.contactMentorPopup.open(mentorPhone)
onContactMentor(teacherPhone) {
this.$refs.contactMentorPopup.open(teacherPhone)
},
},
}


+ 27
- 30
pages_order/order/orderList/orderCard.vue View File

@ -1,29 +1,30 @@
<template>
<view class="card" @click="jumpToOrderDetail">
<view class="flex top">
{{ data.title }}
<view class="top">
{{ data.activityTitle }}
</view>
<view :class="['tag', `tag-${data.status}`]">
{{ statusDesc }}
{{ data.status_dictText }}
</view>
<view class="flex row">
<view class="row-label">联系人</view>
<view class="row-content">{{ data.customerName }}</view>
<view class="row-content">{{ data.name }}</view>
</view>
<view class="flex row">
<view class="row-label">下单时间</view>
<view class="row-content">{{ data.orderDate }}</view>
<view class="row-content">{{ data.createTime }}</view>
</view>
<view class="flex row">
<view class="row-label">联系电话</view>
<view class="row-content">{{ data.customerPhone }}</view>
<view class="row-content">{{ data.phone }}</view>
</view>
<view class="bottom">
<view class="flex bottom">
<view class="flex row">
<text class="row-label">总价格</text>
<text class="flex row-content price">¥</text><text class="highlight">{{ data.orderAmount }}</text>
<text class="flex row-content price">¥<text class="highlight">{{ data.payAmount }}</text></text>
</view>
<view class="flex btns">
<!-- 订单状态 0待支付 1已支付 2已完成 -->
<!-- 待支付 -->
<template v-if="data.status == 0">
<button class="btn" @click.stop="onPay">立即支付</button>
@ -31,32 +32,24 @@
<!-- 已支付 -->
<template v-else-if="data.status == 1">
<button class="btn" @click.stop="onContactMentor">联系导师</button>
</template>
<!-- 待评价 -->
<template v-else-if="data.status == 2">
<button class="btn" @click.stop="onComment">立即评价</button>
<button class="btn" @click.stop="onFinish">已完成</button>
</template>
<!-- 已完成 -->
<template v-else-if="data.status == 3">
<template v-else-if="data.status == 2">
<button class="btn" @click.stop="onApplyService">申请售后</button>
<button class="btn" @click.stop="onComment">立即评价</button>
</template>
<!-- 售后 -->
<template v-else-if="data.status == 4">
<!-- todo -->
<!-- <template v-else-if="data.status == 4">
</template>
</template> -->
</view>
</view>
</view>
</template>
<script>
const STATUS_AND_DESC_MAPPING = {
0: '待支付',
1: '已支付',
2: '待评价',
3: '已完成',
4: '售后',
}
export default {
props: {
@ -67,18 +60,12 @@
}
}
},
computed: {
statusDesc() {
const { status } = this.data
return STATUS_AND_DESC_MAPPING[status]
},
},
methods: {
onPay() {
this.$utils.navigateTo(`/pages_order/order/orderPay/index?id=${this.data.id}`)
},
onContactMentor() {
this.$emit('contatcMentor', this.data.mentorPhone)
this.$emit('contatcMentor', this.data.teacherPhone)
},
onComment() {
this.$emit('comment')
@ -97,6 +84,15 @@
this.$utils.navigateTo(`/pages_order/order/orderDetail/index?id=${this.data.id}`)
}
},
async onFinish() {
try {
await this.$fetch('updateOrder', { id: this.data.id, status: '2' }) // 0 1 2
this.$emit('statusChange')
} catch (err) {
}
},
},
}
</script>
@ -129,6 +125,7 @@
}
.row {
margin-top: 16rpx;
justify-content: flex-start;
column-gap: 4rpx;
@ -147,10 +144,10 @@
}
.row + .row {
margin-top: 16rpx;
}
.bottom {
margin-top: 16rpx;
justify-content: space-between;
.price {


+ 87
- 133
pages_order/order/orderPay/index.vue View File

@ -3,18 +3,26 @@
<navbar leftClick @leftClick="$utils.navigateBack" >
<view class="flex">
<view>待支付</view>
<view>
<view>剩余</view>
<!-- todo -->
<view>10:00</view>
</view>
<view>后关闭</view>
<template v-if="time">
<uv-count-down
:time="time"
format="mm:ss"
autoStart
millisecond
@change="onChange">
<view class="flex countdown">
<text>剩余</text>
<text>{{ `${timeData.minutes}:${timeData.seconds}` }}</text>
</view>
</uv-count-down>
<view>后关闭</view>
</template>
</view>
</navbar>
<view class="main">
<productCard :data="detail"></productCard>
<productCard :data="productCardData"></productCard>
<orderInfoView :data="detail"></orderInfoView>
@ -64,7 +72,7 @@
</view>
<view class="price-unit">¥</view>
<view class="price-value">
{{ totalPrice }}
{{ detail.payAmount }}
</view>
</view>
<button class="col btn btn-primary" @click="onPay">立即支付</button>
@ -93,150 +101,80 @@
return {
id: null,
detail: {},
time: null,
timeData: {},
checkboxValue: [],
}
},
computed: {
...mapState(['configList', 'userInfo', 'orderInfo']),
productPackage() {
const { time, product } = this.detail
const { timeOptions } = product || {}
productCardData() {
const {
activityId,
activityTitle,
activityBrief,
activityTag,
startDate,
endDate,
} = this.detail
return timeOptions?.find?.(item => item.id === time) || {}
return {
time: 'time',
product: {
id: activityId,
title: activityTitle,
brief: activityBrief,
tagDetails: activityTag,
dateList: [
{
id: 'time',
startDate,
endDate,
}
]
}
}
},
totalPrice() {
const { adults, teenager, child, coupon, couponInfo } = this.detail
const { adultsPrice, teenagerPrice, childPrice } = this.productPackage
let total = 0
adults && (total += adults * (adultsPrice || 0))
teenager && (total += teenager * (teenagerPrice || 0))
child && (total += child * (childPrice || 0))
coupon && (total -= (couponInfo?.price || 0))
return total
},
},
onLoad({ id }) {
async onLoad({ id }) {
this.id = id
// console.log('orderInfo', this.orderInfo)
// this.detail = this.orderInfo
// todo: check fetch by id?
this.fetchOrderDetail()
await this.fetchOrderDetail()
// todo
// this.updateCountdown()
},
onPullDownRefresh() {
this.fetchOrderDetail()
async onPullDownRefresh() {
await this.fetchOrderDetail()
uni.stopPullDownRefresh()
},
methods: {
async fetchOrderDetail() {
try {
this.detail = {
product: {
id: '001',
image: new Array(6).fill('/static/image/temp-20.png').join(','),
name: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
desc: '每天车程4小时内,含一程高铁丨喀拉峻草原、夏塔古道、昭苏天马、赛里木湖、昭苏油菜花、伊犁薰衣草丨吐鲁番坎儿井&火焰山',
tags: ['坝上草原', '自然探索', '户外探索', '亲子游玩'],
priceDiscount: 688.99,
priceOrigin: 1200,
registered: 4168,
timeOptions: [
{
id: '0011',
startDate: '08/25',
endDate: '09/01',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0012',
startDate: '09/02',
endDate: '09/11',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0013',
startDate: '09/12',
endDate: '09/19',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
],
},
time: "0012",
adults: 2,
teenager: 1,
child: 1,
members: [
{
id: "001",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "李梓发",
type: 0,
},
{
id: "002",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "吴彦谦",
type: 0,
},
{
id: "003",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "冯云",
type: 1,
},
{
id: "004",
cerNo: "430223********9999",
isDefault: false,
isSelected: true,
name: "冯思钗",
type: 2,
},
],
coupon: "001",
discount: 88,
invoice: null,
name: "测试",
phone: "13345678910",
orderNo: 'BH872381728321983929',
createTime: '2025-04-28 08:14',
status: 0,
}
console.log('orderInfo', this.detail)
try {
// todo: check fetch by id?
// this.detail = await this.$fetch('queryOrderById', { id: this.id })
this.detail = await this.$fetch('queryOrderById', { orderId: this.id })
console.log('orderInfo', this.detail)
} catch (err) {
} catch (err) {
}
}
uni.stopPullDownRefresh()
uni.stopPullDownRefresh()
},
onConfirmAgreement(confirm) {
if (confirm) {
this.checkboxValue = [1]
} else {
this.checkboxValue = []
}
},
async onPay() {
if(!this.checkboxValue.length){
return uni.showToast({
title: '请先同意《退订政策》《合同范本》《预订须知》《安全提示》',
icon:'none'
})
}
try {
const result = await this.$fetch('payOrder', { orderId: this.id })
@ -258,6 +196,22 @@
}
},
updateCountdown() {
let current = dayjs()
let startTime = dayjs(this.detail.createTime)
if (startTime.isSameOrBefore(current)) {
this.time = null
return
}
this.time = startTime.diff(current, 'second')
},
onChange(e) {
this.timeData = e
},
},
}
</script>


+ 3
- 3
pages_order/partner/apply.vue View File

@ -47,10 +47,10 @@
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="recommend" :customStyle="formItemStyle">
<uv-form-item prop="inviteId" :customStyle="formItemStyle">
<view class="form-item-label">推荐人</view>
<view class="form-item-content">
<formInput v-model="form.recommend"></formInput>
<formInput v-model="form.inviteId"></formInput>
</view>
</uv-form-item>
</view>
@ -78,7 +78,7 @@
form: {
name: null,
phone: null,
recommend: null,
inviteId: null,
},
rules: {
'name': {


+ 5
- 97
pages_order/partner/team.vue View File

@ -57,11 +57,14 @@
{ name: '直推用户列表' },
{ name: '间推用户列表' },
],
// todo
mixinsListApi: '',
current: 0,
}
},
computed: {
mixinsListApi() {
return this.current == 0 ? 'queryDirectList' : 'queryIndirectList'
}
},
onShow() {
console.log('onShow')
},
@ -69,105 +72,10 @@
this.clickTabs({ index: arg.index || 0 })
},
methods: {
// todo: delete
getData() {
this.list = [
{
id: '001',
avatar: '/pages_order/static/temp-30.png',
name: '李世海',
price: 10,
createTime: '2025-07-15',
},
{
id: '002',
avatar: '/pages_order/static/temp-30.png',
name: '周静',
price: 10,
createTime: '2025-07-15',
},
{
id: '003',
avatar: '/pages_order/static/temp-30.png',
name: '周海',
price: 10,
createTime: '2025-07-15',
},
{
id: '004',
avatar: '/pages_order/static/temp-30.png',
name: '冯启彬',
price: 10,
createTime: '2025-07-15',
},
{
id: '005',
avatar: '/pages_order/static/temp-30.png',
name: '李娉',
price: 10,
createTime: '2025-07-15',
},
{
id: '006',
avatar: '/pages_order/static/temp-30.png',
name: '李书萍',
price: 10,
createTime: '2025-07-15',
},
{
id: '007',
avatar: '/pages_order/static/temp-30.png',
name: '李世海',
price: 10,
createTime: '2025-07-15',
},
{
id: '008',
avatar: '/pages_order/static/temp-30.png',
name: '周静',
price: 10,
createTime: '2025-07-15',
},
{
id: '009',
avatar: '/pages_order/static/temp-30.png',
name: '周海',
price: 10,
createTime: '2025-07-15',
},
{
id: '010',
avatar: '/pages_order/static/temp-30.png',
name: '冯启彬',
price: 10,
createTime: '2025-07-15',
},
{
id: '011',
avatar: '/pages_order/static/temp-30.png',
name: '李娉',
price: 10,
createTime: '2025-07-15',
},
{
id: '012',
avatar: '/pages_order/static/temp-30.png',
name: '李书萍',
price: 10,
createTime: '2025-07-15',
},
]
},
//tab
clickTabs({ index }) {
console.log('clickTabs')
this.current = index
if (index == 0) {
delete this.queryParams.status
} else {
this.queryParams.status = index - 1
}
this.getData()
},
},


+ 13
- 10
pages_order/partner/withdraw.vue View File

@ -16,18 +16,18 @@
errorType="toast"
>
<view class="form-item">
<uv-form-item prop="name" :customStyle="formItemStyle">
<uv-form-item prop="userName" :customStyle="formItemStyle">
<view class="form-item-label">真实姓名</view>
<view class="form-item-content">
<formInput v-model="form.name"></formInput>
<formInput v-model="form.userName"></formInput>
</view>
</uv-form-item>
</view>
<view class="form-item">
<uv-form-item prop="amount" :customStyle="formItemStyle">
<uv-form-item prop="transferAmount" :customStyle="formItemStyle">
<view class="form-item-label">提现金额</view>
<view class="form-item-content">
<formInput v-model="form.amount"></formInput>
<formInput v-model="form.transferAmount"></formInput>
</view>
</uv-form-item>
</view>
@ -64,16 +64,16 @@
data() {
return {
form: {
name: null,
amount: null,
userName: null,
transferAmount: null,
},
rules: {
'name': {
'userName': {
type: 'string',
required: true,
message: '请输入真实姓名',
},
'amount': {
'transferAmount': {
type: 'string',
required: true,
message: '请输入提现金额',
@ -88,13 +88,16 @@
await this.$refs.form.validate()
const {
userName,
transferAmount,
} = this.form
const params = {
userName,
transferAmount,
}
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('cashout', params)
uni.showToast({
icon: 'success',


+ 5
- 5
pages_order/product/commentList.vue View File

@ -3,15 +3,15 @@
<view class="list-item" v-for="item in list" :key="item.id">
<view class="flex user">
<view class="avatar">
<image class="img" :src="item.avatar" mode="scaleToFill"></image>
<image class="img" :src="item.user.headImage" mode="scaleToFill"></image>
</view>
<view class="name">{{ item.name }}</view>
<view class="time">{{ item.createTime }}</view>
<view class="name">{{ item.user.nickName }}</view>
<view class="time">{{ $dayjs(item.createTime).format('YYYY-MM-DD') }}</view>
</view>
<view class="flex content">
<view class="content-text">{{ item.content }}</view>
<view class="content-img">
<image class="img" v-if="getCoverImg(item)" :src="getCoverImg(item)" mode="aspectFill"></image>
<view class="content-img" v-if="getCoverImg(item)">
<image class="img" :src="getCoverImg(item)" mode="aspectFill"></image>
</view>
</view>
</view>


+ 17
- 85
pages_order/product/productDetail.vue View File

@ -44,8 +44,7 @@
<view class="card">
<view class="card-header">选择团期</view>
<view class="card-content">
<!-- todo: check key -->
<timeOptionsSelect v-model="selectTime" :options="detail.timeOptions"></timeOptionsSelect>
<timeOptionsSelect v-model="selectTime" :options="detail.dateList"></timeOptionsSelect>
</view>
</view>
@ -197,88 +196,21 @@
} catch (err) {
}
return
// todo: delete
this.detail = {
id: '001',
image: new Array(6).fill('/static/image/temp-20.png').join(','),
title: '新疆天山行7/9日丨醉美伊犁&吐鲁番双套餐',
brief: '每天车程4小时内,含一程高铁丨喀拉峻草原、夏塔古道、昭苏天马、赛里木湖、昭苏油菜花、伊犁薰衣草丨吐鲁番坎儿井&火焰山',
tagDetails: ['坝上草原', '自然探索', '户外探索', '亲子游玩'],
priceDiscount: 688.99,
priceOrigin: 1200,
applyNum: 4168,
timeOptions: [
{
id: '0011',
startDate: '08/25',
endDate: '09/01',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0012',
startDate: '09/02',
endDate: '09/11',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
{
id: '0013',
startDate: '09/12',
endDate: '09/19',
priceDiscount: 1200.99,
priceOrigin: 2300,
adultsPrice: 2400,
teenagerPrice: 1800,
childPrice: 1200.99,
},
],
special: `
<p style="font-size: 36rpx;">
行程亮点
</p>
`,
target: `
<p style="font-size: 36rpx;">
课程目标
<p>
`,
process: `
<p style="font-size: 36rpx;">
详细行程
<p>
`,
}
},
async fetchComment(id) {
// todo: fetch by activity id
this.commentList = [
{
avatar: '/pages_order/static/temp-30.png',
name: '战斗世界',
createTime: '2025-07-12',
content: '凌玉姐姐很温柔很耐心很负责我很喜欢她龙哥知识渊博很幽默给我们讲解很多内容行程很有趣我学到了很多东西最难忘的就是库木塔格沙漠我们爬到了很高的顶端看夕阳绝美还有我也很喜欢夏塔古道我们爬到了第四个卡拉房子的最远端看到了壮观的雪山下次还想参加活动去南疆',
image: '/pages_order/static/temp-38.png',
},
{
avatar: '/pages_order/static/temp-30.png',
name: '战斗世界',
createTime: '2025-07-12',
content: '凌玉姐姐很温柔很耐心很负责我很喜欢她龙哥知识渊博很幽默给我们讲解很多内容行程很有趣我学到了很多东西最难忘的就是库木塔格沙漠我们爬到了很高的顶端看夕阳绝美还有我也很喜欢夏塔古道我们爬到了第四个卡拉房子的最远端看到了壮观的雪山下次还想参加活动去南疆',
image: '/pages_order/static/temp-38.png',
},
]
async fetchComment(activityId) {
try {
const queryParams = {
pageNo: 1,
pageSize: 2,
activityId,
}
this.commentList = (await this.$fetch('queryCommentList', queryParams))?.records
console.log('commentList', this.commentList)
} catch (err) {
console.log('fetchComment', err)
}
},
onCollect() {
this.$store.dispatch('collect', this.id)
@ -289,7 +221,7 @@
this.$refs.orderInfoPopup.open({ selectTime: this.selectTime })
},
jumpToCommentRecords() {
this.$utils.navigateTo(`/pages_order/comment/commentRecordsOfProduct?productId=${this.id}`)
this.$utils.navigateTo(`/pages_order/comment/commentRecordsOfProduct?id=${this.id}`)
},
//tab
clickTabs({ index }) {
@ -440,7 +372,7 @@
}
.detail {
font-size: 0;
// font-size: 0;
}
.bottom {


+ 14
- 9
pages_order/traveler/travelerCard.vue View File

@ -12,8 +12,7 @@
<view class="info">
<view class="flex name">
<view>{{ data.name }}</view>
<!-- todo: transform periodId to desc -->
<view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view>
<view :class="['tag', `tag-${type}`]">{{ typeDesc }}</view>
</view>
<view class="id">{{ data.cerNo }}</view>
</view>
@ -48,12 +47,6 @@
</template>
<script>
const MEMBER_TYPE_AND_DESC_MAPPING = {
0: '成人',
1: '青少年',
2: '儿童',
}
export default {
props: {
@ -85,7 +78,19 @@
}
},
typeDesc() {
return MEMBER_TYPE_AND_DESC_MAPPING[this.data.type]
const { periodId } = this.data
return this.configList.periodList?.find?.(item => item.id === periodId)?.title
},
type() {
if (this.typeDesc == '青少年') {
return 1
}
if (this.typeDesc == '儿童') {
return 2
}
return 0
},
},
watch: {


+ 2
- 4
pages_order/traveler/travelerList.vue View File

@ -50,7 +50,7 @@
},
onLoad(arg) {
const { selectIds } = arg
this.selectedIdList = selectIds?.split?.(',') || []
this.selectedIdList = selectIds?.split?.(',')?.filter(val => val) || []
this.getData()
},
@ -73,10 +73,8 @@
},
async onDefaultChange(id, val) {
try {
const target = this.list.find(item => item.id === id)
const params = {
...target,
id,
isDefault: val ? '1' : '0',
}


+ 24
- 43
pages_order/traveler/travelerPopup.vue View File

@ -50,10 +50,10 @@
labelSize="26rpx"
>
<uv-radio
v-for="(item, index) in periodOptions"
:key="index"
:label="item.label"
:name="item.value"
v-for="item in configList.periodList"
:key="item.id"
:label="item.title"
:name="item.id"
:customStyle="{ flex: 1 }"
></uv-radio>
</uv-radio-group>
@ -261,25 +261,6 @@
},
},
formItemStyle: { padding: 0 },
// todo: fetch
periodOptions: [
{
id: '001',
label: '成人',
value: '0',
},
{
id: '002',
label: '青少年',
value: '1',
},
{
id: '003',
label: '儿童',
value: '2',
},
],
// todo: check
sexOptions: [
{
id: '001',
@ -317,18 +298,18 @@
} = result
this.form = {
name,
cerNo,
name: name || '',
cerNo: cerNo || '',
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
phone: phone || '',
wechat: wechat || '',
school: school || '',
grade: grade || '',
age: age || '',
remark: remark || '',
emergencyPhone: emergencyPhone || '',
chaperonPhone: chaperonPhone || '',
}
} catch (err) {
@ -345,19 +326,19 @@
this.id = null
this.title = '添加出行人'
this.form = {
name: null,
cerNo: null,
name: '',
cerNo: '',
// todo: fetch default
periodId: 0,
sex: 0,
phone: null,
wechat: null,
school: null,
grade: null,
age: null,
remark: null,
emergencyPhone: null,
chaperonPhone: null,
phone: '',
wechat: '',
school: '',
grade: '',
age: '',
remark: '',
emergencyPhone: '',
chaperonPhone: '',
}
}


+ 37
- 25
store/store.js View File

@ -12,10 +12,12 @@ const store = new Vuex.Store({
configList: {}, //配置列表
shop : false,//身份判断如果不需要,可以删除
userInfo : {}, //用户信息
userCenterData: {},
travelerList: null,
orderInfo: null,
couponInfo: null,
memberInfo: null,
liveInfo: null,
},
getters: {
// 角色 true为水洗店 false为酒店 : 身份判断如果不需要,可以删除
@ -25,29 +27,29 @@ const store = new Vuex.Store({
},
mutations: {
// 初始化配置
initConfig(state){
api('getConfig', res => {
const configList = {
...state.configList,
}
if (res.code == 200) {
res.result.forEach(n => {
configList[n.keyName] = n.keyContent;
configList[n.keyName + '_keyValue'] = n.keyValue;
});
}
state.configList = configList
uni.$emit('initConfig', state.configList)
})
// let config = ['getPrivacyPolicy', 'getUserAgreement']
// config.forEach(k => {
// api(k, res => {
// if (res.code == 200) {
// state.configList[k] = res.result
// }
// })
// })
async initConfig(state) {
const recordsn> pan class="o">= (await fetch('getConfig'))?.records
const configList = {
...state.configList,
}
records.forEach(n => {
configList[n.paramCode] = n.paramImage || n.paramText || n.paramTextarea;
});
const periodList = (await fetch('queryPeriodList')).records
configList['periodList'] = periodList
const commentOptionList = (await fetch('queryCommentOptionList')).records
configList['commentOptionList'] = commentOptionList
const experienceQuestionList = (await fetch('queryExperienceQuestionList')).records
configList['experienceQuestionList'] = experienceQuestionList
state.configList = configList
uni.$emit('initConfig', state.configList)
},
// 微信登录
login(state){
@ -86,14 +88,20 @@ const store = new Vuex.Store({
},
// 获取用户个人信息
getUserInfo(state){
// todo delete
return
api('getInfo', res => {
if(res.code == 200){
state.userInfo = res.result
}
})
},
// 获取个人基础数据
getUserCenterData(state){
api('queryUserCenterData', res => {
if(res.code == 200){
state.userCenterData = res.result
}
})
},
// 退出登录
logout(state){
uni.showModal({
@ -122,6 +130,10 @@ const store = new Vuex.Store({
setMemberInfo(state, data) {
state.memberInfo = data
},
setLiveInfo(state, data) {
console.log('liveInfo', data)
state.liveInfo = data
},
},
actions: {
async collect(state, activityId) {


Loading…
Cancel
Save