2 Commits

38 changed files with 598 additions and 559 deletions
Unified View
  1. +1
    -1
      api/fetch.js
  2. +3
    -1
      api/model/activity.js
  3. +2
    -2
      api/model/login.js
  4. +29
    -1
      api/model/order.js
  5. +0
    -1
      components/config/PrivacyAgreementPoup.vue
  6. +5
    -15
      components/home/bgSwiperView.vue
  7. +6
    -6
      components/home/categoryView.vue
  8. +3
    -8
      components/home/productView.vue
  9. +13
    -1
      components/home/recommendView.vue
  10. +5
    -24
      components/home/swiperView.vue
  11. +1
    -1
      components/partner/posterPopup.vue
  12. +14
    -4
      components/product/productCard.vue
  13. +122
    -43
      pages/index/category.vue
  14. +62
    -75
      pages/index/index.vue
  15. +4
    -1
      pages_order/article/index.vue
  16. +10
    -8
      pages_order/article/search.vue
  17. +1
    -1
      pages_order/auth/wxUserInfo.vue
  18. +1
    -1
      pages_order/comment/commentRecordsOfProduct.vue
  19. +65
    -23
      pages_order/live/index.vue
  20. +41
    -7
      pages_order/live/list.vue
  21. +1
    -1
      pages_order/order/components/orderInfoView.vue
  22. +4
    -16
      pages_order/order/orderConfirm/index.vue
  23. +1
    -40
      pages_order/order/orderConfirm/infoPopup.vue
  24. +1
    -1
      pages_order/order/orderConfirm/memberCard.vue
  25. +3
    -2
      pages_order/order/orderConfirm/timeOptionsSelect.vue
  26. +13
    -8
      pages_order/order/orderDetail/index.vue
  27. +11
    -6
      pages_order/order/orderPay/index.vue
  28. +2
    -3
      pages_order/product/collectList.vue
  29. +28
    -26
      pages_order/product/productDetail.vue
  30. +16
    -63
      pages_order/product/search.vue
  31. +8
    -31
      pages_order/traveler/travelerCard.vue
  32. +27
    -88
      pages_order/traveler/travelerList.vue
  33. +93
    -39
      pages_order/traveler/travelerPopup.vue
  34. BIN
      static/image/icon-close.png
  35. BIN
      static/image/icon-service.png
  36. +2
    -7
      store/store.js
  37. +0
    -1
      uni_modules/uv-tabs/components/uv-tabs/uv-tabs.vue
  38. +0
    -3
      uni_modules/uv-vtabs/components/uv-vtabs/uv-vtabs.vue

+ 1
- 1
api/fetch.js View File

@ -1,7 +1,7 @@
import api from './api.js' import api from './api.js'
const fetch = (key, data = {}, transform = true, loadingTitle) => { const fetch = (key, data = {}, transform = true, loadingTitle) => {
return new Promise(resolve => {
return new Promise((resolve, reject) => {
const callback = (res) => { const callback = (res) => {
if (!transform) { if (!transform) {


+ 3
- 1
api/model/activity.js View File

@ -19,7 +19,9 @@ const api = {
// 首页&分类-收藏研学活动 // 首页&分类-收藏研学活动
collectionActivity: { collectionActivity: {
url: '/activity/collectionActivity', url: '/activity/collectionActivity',
method: 'GET',
method: 'POST',
auth: true,
limit : 500,
}, },
} }

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

@ -5,14 +5,14 @@
const api = { const api = {
// 微信登录接口 // 微信登录接口
wxLogin: { wxLogin: {
url: '/login_common/appletLogin',
url: '/login/login',
method: 'GET', method: 'GET',
limit : 500, limit : 500,
showLoading : true, showLoading : true,
}, },
// 获取绑定手机号码 // 获取绑定手机号码
bindPhone: { bindPhone: {
url: '/login_common/bindPhone',
url: '/login/bindPhone',
method: 'GET', method: 'GET',
auth: true, auth: true,
}, },


+ 29
- 1
api/model/order.js View File

@ -20,13 +20,41 @@ const api = {
showLoading : true, showLoading : true,
}, },
// 我的订单-支付订单 // 我的订单-支付订单
createOrder: {
payOrder: {
url: '/order/payOrder', url: '/order/payOrder',
method: 'POST', method: 'POST',
auth: true, auth: true,
limit : 500, limit : 500,
showLoading : true, showLoading : true,
}, },
// 我的订单-查询出行人列表
queryTouristList: {
url: '/order/queryTouristList',
method: 'GET',
auth: true,
},
// 我的订单-查询出行人详情
queryTouristById: {
url: '/order/queryTouristById',
method: 'GET',
auth: true,
},
// 我的订单-添加出行人
addTourist: {
url: '/order/addTourist',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
// 我的订单-修改出行人信息
updateTourist: {
url: '/order/updateTourist',
method: 'POST',
auth: true,
limit : 500,
showLoading : true,
},
} }
export default api export default api

+ 0
- 1
components/config/PrivacyAgreementPoup.vue View File

@ -50,7 +50,6 @@
if(wx.getPrivacySetting){ if(wx.getPrivacySetting){
wx.getPrivacySetting({ wx.getPrivacySetting({
success: res => { success: res => {
console.log(res)
if (res.needAuthorization) { if (res.needAuthorization) {
// //
this.init() this.init()


+ 5
- 15
components/home/bgSwiperView.vue View File

@ -21,22 +21,12 @@
this.getData() this.getData()
}, },
methods: { methods: {
getData() {
// todo: fetch
this.bannerList = [
{
image: '/static/image/bg.png',
},
{
image: '/static/image/bg.png',
},
{
image: '/static/image/bg.png',
},
]
async getData() {
try {
this.bannerList = (await this.$fetch('queryBannerList', { type: 0 })).records // type0- 1-
} catch (err) {
}
}, },
}, },
} }


+ 6
- 6
components/home/categoryView.vue View File

@ -27,31 +27,31 @@
id: '001', id: '001',
icon: '/static/image/temp-1.png', icon: '/static/image/temp-1.png',
label: '主题研学', label: '主题研学',
path: `/pages/index/category?categoryId=009`,
path: `/pages/index/category?categoryId=1962345709817106434`,
}, },
{ {
id: '002', id: '002',
icon: '/static/image/temp-2.png', icon: '/static/image/temp-2.png',
label: '社会实践', label: '社会实践',
path: `/pages/index/category?categoryId=008`,
path: `/pages/index/category?categoryId=1962346300198948866`,
}, },
{ {
id: '003', id: '003',
icon: '/static/image/temp-3.png', icon: '/static/image/temp-3.png',
label: '研学交流', label: '研学交流',
path: `/pages/index/category?categoryId=010`,
path: `/pages/index/category?categoryId=1962346769759670273`,
}, },
{ {
id: '004', id: '004',
icon: '/static/image/temp-4.png', icon: '/static/image/temp-4.png',
label: '周末研学', label: '周末研学',
path: `/pages/index/category?categoryId=006`,
path: `/pages/index/category?categoryId=1962346834884628481`,
}, },
{ {
id: '005', id: '005',
icon: '/static/image/temp-5.png', icon: '/static/image/temp-5.png',
label: '假期专项', label: '假期专项',
path: `/pages/index/category?categoryId=011`,
path: `/pages/index/category?categoryId=1962346960097185793`,
}, },
{ {
id: '006', id: '006',
@ -68,7 +68,7 @@
id: '008', id: '008',
icon: '/static/image/temp-8.png', icon: '/static/image/temp-8.png',
label: '本地研学', label: '本地研学',
path: `/pages/index/category?categoryId=012`,
path: `/pages/index/category?categoryId=1962347024639135745`,
}, },
{ {
id: '009', id: '009',


+ 3
- 8
components/home/productView.vue View File

@ -66,22 +66,17 @@
} }
}, },
created() { created() {
this.fetchCategory()
this.fetchRecommend()
}, },
methods: { methods: {
fetchCategory() {
fetchRecommend() {
// todo: fetch // todo: fetch
this.tabs = [ this.tabs = [
{ name: '全部' }, { name: '全部' },
// todo: jump to detail
{ id: '001', name: '草原运动会', disabled: true, },
{ id: '002', name: '我的韶山行', disabled: true, },
{ id: '003', name: '出境游', disabled: true, },
{ id: '1962342791093227522', name: '研学活动一', disabled: true, },
] ]
}, },
onClickTab(e) { onClickTab(e) {
console.log('onClickTab', e.index)
this.current = 0 this.current = 0
const index = e.index const index = e.index


+ 13
- 1
components/home/recommendView.vue View File

@ -1,6 +1,6 @@
<template> <template>
<view class="recommend"> <view class="recommend">
<view class="flex recommend-item" v-for="item in recommendList" :key="item.id">
<view class="flex recommend-item" v-for="item in recommendList" :key="item.id" @click="onClick(item)">
<image class="img" :src="item.icon" mode="widthFix"></image> <image class="img" :src="item.icon" mode="widthFix"></image>
<view> <view>
<view class="label">{{ item.label }}</view> <view class="label">{{ item.label }}</view>
@ -32,22 +32,34 @@
label: '限时优惠', label: '限时优惠',
desc: '速抢折扣', desc: '速抢折扣',
highlight: true, highlight: true,
path: `/pages_order/product/search?isDiscount=1&title=限时优惠`,
}, },
{ {
id: '002', id: '002',
icon: '/static/image/temp-12.png', icon: '/static/image/temp-12.png',
label: '口碑爆款', label: '口碑爆款',
desc: '热销推荐', desc: '热销推荐',
path: `/pages_order/product/search?isHot=1&title=口碑爆款`,
}, },
{ {
id: '003', id: '003',
icon: '/static/image/temp-13.png', icon: '/static/image/temp-13.png',
label: '新上线路', label: '新上线路',
desc: '全新上线', desc: '全新上线',
path: `/pages_order/product/search?isNew=1&title=新上线路`,
}, },
] ]
}, },
onClick(target) {
const { path } = target
if (path) {
uni.navigateTo({
url: path
})
}
},
}, },
} }
</script> </script>


+ 5
- 24
components/home/swiperView.vue View File

@ -22,31 +22,12 @@
this.getData() this.getData()
}, },
methods: { methods: {
getData() {
// todo: fetch
this.bannerList = [
{
image: '/static/image/temp-14.png',
},
{
image: '/static/image/temp-14.png',
},
{
image: '/static/image/temp-14.png',
},
{
image: '/static/image/temp-14.png',
},
{
image: '/static/image/temp-14.png',
},
{
image: '/static/image/temp-14.png',
},
]
async getData() {
try {
this.bannerList = (await this.$fetch('queryBannerList', { type: 1 })).records // type0- 1-
} catch (err) {
}
}, },
onClickBanner(index) { onClickBanner(index) {
console.log('onClickBanner', index) console.log('onClickBanner', index)


+ 1
- 1
components/partner/posterPopup.vue View File

@ -265,7 +265,7 @@
ctx.restore(); ctx.restore();
ctx.save() ctx.save()
maxWidth = 520 * Ratio / dpr
maxWidth = 560 * Ratio / dpr
lineHeight = 60 * Ratio / dpr lineHeight = 60 * Ratio / dpr
ctx.font = "normal normal 600 16px normal"; ctx.font = "normal normal 600 16px normal";
ctx.fillStyle = "#181818"; ctx.fillStyle = "#181818";


+ 14
- 4
components/product/productCard.vue View File

@ -8,8 +8,7 @@
<view class="flex flex-column product-info"> <view class="flex flex-column product-info">
<view class="product-info-top"> <view class="product-info-top">
<view class="product-name text-ellipsis-2">{{ data.title }}</view> <view class="product-name text-ellipsis-2">{{ data.title }}</view>
<!-- todo: check key -->
<view class="product-desc text-ellipsis">{{ data.tagList.join('·') }}</view>
<view class="product-desc text-ellipsis" v-if="tagDesc">{{ tagDesc }}</view>
</view> </view>
<view class="flex product-info-bottom"> <view class="flex product-info-bottom">
<view class="product-detail"> <view class="product-detail">
@ -68,11 +67,22 @@
} }
}, },
computed: { computed: {
tagDesc() {
// todo: check key
const { tagList } = this.data
return tagList?.length ? tagList.split('、').join('·') : ''
return
const { categoryId_dictText, timeId_dictText, ageId_dictText } = this.data
return [categoryId_dictText, timeId_dictText, ageId_dictText].filter(val => val).join('·')
},
priceInt() { priceInt() {
return parseInt(this.data.priceDiscount)
return Math.floor(this.data.priceDiscount)
}, },
priceFrac() { priceFrac() {
return (this.data.priceDiscount % this.priceInt).toFixed(2).slice(1)
let frac = this.data.priceDiscount % this.priceInt
return frac > 0 ? frac.toFixed(2).slice(1) : ''
}, },
collectBtnWidth() { collectBtnWidth() {
return this.isCollected ? 80 : 56 return this.isCollected ? 80 : 56


+ 122
- 43
pages/index/category.vue View File

@ -224,66 +224,145 @@
async fetchCategoryList() { async fetchCategoryList() {
this.categoryList = [ this.categoryList = [
{ {
id: '001',
name: '国际游',
children: [],
"key": "1962345168240185345",
"title": "国际游",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '002',
name: '夏令营',
children: [],
"key": "1962345225345634305",
"title": "夏令营",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '003',
name: '周末营',
children: [],
"key": "1962345290571255810",
"title": "周末营",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '004',
name: '周边游',
children: [],
"key": "1962345372007862273",
"title": "周边游",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '005',
name: '定制游',
children: [],
"key": "1962345497681793025",
"title": "定制游",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '006',
name: '周末活动',
children: [],
"key": "1962345589524467714",
"title": "周末活动",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '007',
name: '亲子活动',
children: [],
"key": "1962345642188148737",
"title": "亲子活动",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '008',
name: '社会实践',
children: [],
"key": "1962345709817106434",
"title": "主题研学",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '009',
name: '主题研学',
children: [],
"key": "1962346300198948866",
"title": "社会实践",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '010',
name: '研学交流',
children: [],
"key": "1962346769759670273",
"title": "研学交流",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '011',
name: '假期专项',
children: [],
"key": "1962346834884628481",
"title": "周末研学",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
{ {
id: '012',
name: '本地研学',
children: [],
"key": "1962346960097185793",
"title": "假期专享",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}, },
]
{
"key": "1962347024639135745",
"title": "本地研学",
"icon": null,
"parentId": "0",
"value": null,
"code": null,
"children": null,
"leaf": true
}
].map(item => {
const { key, title } = item
return {
id: key,
name: title,
children: []
}
})
return return
try { try {
this.categoryList = (await this.$fetch('getCategoryList', { pageSize: 1000 }))?.records?.map(item => ({ id: item.id, name: item.name, children: [] })) this.categoryList = (await this.$fetch('getCategoryList', { pageSize: 1000 }))?.records?.map(item => ({ id: item.id, name: item.name, children: [] }))
@ -421,6 +500,12 @@
}, },
async queryProductList(categoryId) { async queryProductList(categoryId) {
try {
return (await this.$fetch('queryActivityList', { ...this.queryParams, categoryId }))?.records || []
} catch (err) {
return []
}
return [ return [
{ {
id: '001', id: '001',
@ -477,12 +562,6 @@
applyNum: 4168, applyNum: 4168,
}, },
] ]
try {
return (await this.$fetch('queryActivityList', { ...this.queryParams, categoryId }))?.records || []
} catch (err) {
return []
}
}, },
async initList() { async initList() {
console.log('queryParams', this.queryParams) console.log('queryParams', this.queryParams)


+ 62
- 75
pages/index/index.vue View File

@ -1,5 +1,5 @@
<template> <template>
<view class="page__view">
<movable-area class="page__view">
<!-- <view class="bg"> <!-- <view class="bg">
<image class="img" src="@/static/image/bg.png" mode="widthFix"></image> <image class="img" src="@/static/image/bg.png" mode="widthFix"></image>
</view> --> </view> -->
@ -54,12 +54,22 @@
</view> </view>
</view> </view>
<!-- todo: 联系客服 -->
<movable-view v-if="showBtnService" class="movable-view" :x="273" :y="628" direction="all">
<view class="movable-content">
<button class="flex btn btn-service" open-type="contact">
<view class="label">联系客服</view>
<image class="icon" src="@/static/image/icon-service.png" mode="widthFix"></image>
</button>
<button class="flex btn btn-close" @click.stop="showBtnService = false">
<image class="icon" src="@/static/image/icon-close.png" mode="widthFix"></image>
</button>
</view>
</movable-view>
<tabber select="home" /> <tabber select="home" />
</view>
</movable-area>
</template> </template>
<script> <script>
@ -88,12 +98,11 @@
return { return {
keyword: '', keyword: '',
isFocusSearch: false, isFocusSearch: false,
// todo
mixinsListApi: '',
mixinsListApi: 'queryActivityList',
showBtnService: true,
} }
}, },
onLoad() { onLoad() {
this.fetchBanner()
}, },
computed: { computed: {
searchStyle() { searchStyle() {
@ -113,67 +122,7 @@
return this.isFocusSearch ? focusStyle : blurStyle return this.isFocusSearch ? focusStyle : blurStyle
}, },
}, },
methods: {
// todo: delete
getData() {
this.list = [
{
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,
},
]
this.total = this.list.length
},
methods: {
search() { search() {
console.log('search', this.keyword) console.log('search', this.keyword)
uni.navigateTo({ uni.navigateTo({
@ -181,13 +130,6 @@
}) })
// this.keyword = '' // this.keyword = ''
}, },
async fetchBanner() {
try {
await this.$fetch('queryBannerList')
} catch (err) {
}
},
}, },
} }
</script> </script>
@ -311,4 +253,49 @@
} }
} }
.movable {
&-view {
position: fixed;
width: auto;
height: auto;
}
&-content {
position: relative;
.btn {
&-service {
column-gap: 4rpx;
padding: 6rpx 6rpx 6rpx 18rpx;
background: linear-gradient(to right, #21FEEC, #019AF9);
border: 2rpx solid #00A9FF;
border-radius: 40rpx;
.label {
white-space: nowrap;
font-size: 24rpx;
font-weight: 500;
color: #FFFFFF;
text-shadow: 0 1px 2px #135A98;
}
.icon {
width: 64rpx;
height: auto;
}
}
&-close {
width: 32rpx;
height: auto;
position: absolute;
top: 0;
left: 0;
transform: translate(-10rpx, -10rpx);
}
}
}
}
</style> </style>

+ 4
- 1
pages_order/article/index.vue View File

@ -2,7 +2,7 @@
<view class="page__view"> <view class="page__view">
<!-- 导航栏 --> <!-- 导航栏 -->
<navbar :title="details.title" leftClick @leftClick="$utils.navigateBack" />
<navbar :title="details.title" leftClick @leftClick="$utils.navigateBack" bgColor="#FFFFFF" />
<!-- <image class="img" :src="details.details" mode="widthFix"></image> --> <!-- <image class="img" :src="details.details" mode="widthFix"></image> -->
<uv-parse :content="details.details"></uv-parse> <uv-parse :content="details.details"></uv-parse>
@ -33,6 +33,9 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page__view {
background: $uni-bg-color;
}
.img { .img {
width: 100vw; width: 100vw;


+ 10
- 8
pages_order/article/search.vue View File

@ -25,7 +25,7 @@
<view class="list"> <view class="list">
<template v-if="total"> <template v-if="total">
<view class="list-item" v-for="item in list" :key="item.id" @click="jumpToDetail(item.id)">
<view class="flex list-item" v-for="item in list" :key="item.id" @click="jumpToDetail(item.id)">
<view class="cover"> <view class="cover">
<image class="img" :src="item.image" mode="aspectFill"></image> <image class="img" :src="item.image" mode="aspectFill"></image>
</view> </view>
@ -72,9 +72,6 @@
this.getData() this.getData()
}, },
methods: { methods: {
// todo: delete
getData() {
},
search() { search() {
this.queryParams.pageNo = 1 this.queryParams.pageNo = 1
this.queryParams.pageSize = 10 this.queryParams.pageSize = 10
@ -108,6 +105,10 @@
<style scoped lang="scss"> <style scoped lang="scss">
.page__view {
background: linear-gradient(#DAF3FF, #FBFEFF 250rpx, #FBFEFF);
}
.search { .search {
$h: 64rpx; $h: 64rpx;
$radius: 32rpx; $radius: 32rpx;
@ -150,14 +151,15 @@
padding: 12rpx 40rpx; padding: 12rpx 40rpx;
&-item { &-item {
align-items: flex-start;
column-gap: 16rpx; column-gap: 16rpx;
padding: 24rpx;
background: #F9F9F9;
border: 2rpx solid #FFFFFF;
border-radius: 24rpx;
& + & { & + & {
margin-top: 40rpx; margin-top: 40rpx;
padding: 24rpx;
background: #F9F9F9;
border: 2rpx solid #FFFFFF;
border-radius: 24rpx;
} }
.cover { .cover {


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

@ -136,7 +136,7 @@
}, },
getPhone(e){ getPhone(e){
this.$api('bindPhone', { this.$api('bindPhone', {
code : e.detail.code
phoneCode : e.detail.code
}, res => { }, res => {
if(res.code == 200){ if(res.code == 200){


+ 1
- 1
pages_order/comment/commentRecordsOfProduct.vue View File

@ -1,7 +1,7 @@
<template> <template>
<view class="page__view"> <view class="page__view">
<navbar title="全部评论" leftClick @leftClick="$utils.navigateBack" />
<navbar title="全部评论" leftClick @leftClick="$utils.navigateBack" bgColor="#FFFFFF" />
<view class="main"> <view class="main">


+ 65
- 23
pages_order/live/index.vue View File

@ -4,9 +4,9 @@
<navbar :title="detail.title" leftClick @leftClick="$utils.navigateBack" /> <navbar :title="detail.title" leftClick @leftClick="$utils.navigateBack" />
<view class="header"> <view class="header">
<image class="icon" :src="detail.image" mode="widthFix"></image>
<view class="flex" style="padding: 0 40rpx;">
<view class="flex">
<image class="cover-img" :src="detail.image" 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="title">{{ detail.title }}</view>
<view class="tag">{{ detail.createTime }}</view> <view class="tag">{{ detail.createTime }}</view>
</view> </view>
@ -19,10 +19,9 @@
<view class="main"> <view class="main">
<view class="section" v-for="item in list" :key="item.id"> <view class="section" v-for="item in list" :key="item.id">
<view class="section-header">
<view class="flex section-header">
<view class="avatar"> <view class="avatar">
<!-- todo: check key -->
<image class="avatar-img" src="@/pages_order/static/temp-30.png" mode="scaleToFill"></image>
<image class="avatar-img" :src="item.avatar" mode="scaleToFill"></image>
</view> </view>
<view class="info"> <view class="info">
<view class="flex title"> <view class="flex title">
@ -73,7 +72,7 @@
// todo // todo
mixinsListApi: '', mixinsListApi: '',
// todo: fetch // todo: fetch
isManager: true,
isManager: false,
} }
}, },
computed: { computed: {
@ -92,21 +91,52 @@
}, },
methods: { methods: {
async fetchDetail() { async fetchDetail() {
this.bannerList = [
{
url: '/pages_order/static/temp-23.png',
title: '趣玩新加坡',
createTime: '2025-04-18',
},
// todo: fetch
this.detail = {
id: '001',
image: '/static/image/temp-20.png',
title: '趣玩新加坡',
createTime: '2025-04-18',
}
},
// todo: delete
getData() {
this.list = [
{ {
url: '/pages_order/static/temp-24.png',
title: '坝上双草原',
createTime: '2025-04-18',
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',
]
}, },
{ {
url: '/pages_order/static/temp-25.png',
title: '牛湖线',
createTime: '2025-04-18',
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',
]
}, },
] ]
}, },
@ -129,9 +159,15 @@
.header { .header {
margin-top: 40rpx; margin-top: 40rpx;
font-size: 0;
.cover-img {
width: 100%;
height: auto;
border-radius: 40rpx;
}
.title { .title {
margin-top: 12rpx;
font-size: 28rpx; font-size: 28rpx;
font-weight: 600; font-weight: 600;
color: #252545; color: #252545;
@ -165,13 +201,14 @@
} }
.main { .main {
padding: 0 40rpx;
padding: 0 40rpx 40rpx 40rpx;
} }
.section { .section {
margin-top: 40rpx; margin-top: 40rpx;
&-header { &-header {
column-gap: 24rpx;
.avatar { .avatar {
flex: none; flex: none;
@ -189,12 +226,12 @@
.info { .info {
flex: 1; flex: 1;
column-gap: 24rpx;
min-width: 0;
.title { .title {
column-gap: 8rpx; column-gap: 8rpx;
white-space: nowrap; white-space: nowrap;
font-size: 26rpx;
font-size: 36rpx;
font-weight: 600; font-weight: 600;
color: #252545; color: #252545;
@ -205,6 +242,7 @@
.address { .address {
flex: 1; flex: 1;
font-weight: 400;
font-size: 24rpx; font-size: 24rpx;
color: #00A9FF; color: #00A9FF;
} }
@ -212,6 +250,9 @@
.desc { .desc {
margin-top: 8rpx; margin-top: 8rpx;
font-size: 24rpx;
font-weight: 400;
color: #8B8B8B;
} }
} }
@ -228,6 +269,7 @@
gap: 16rpx; gap: 16rpx;
&-item { &-item {
height: 300rpx;
border: 2rpx solid #CDCDCD; border: 2rpx solid #CDCDCD;
border-radius: 12rpx; border-radius: 12rpx;
overflow: hidden; overflow: hidden;


+ 41
- 7
pages_order/live/list.vue View File

@ -17,7 +17,7 @@
@change="changeHandler" @change="changeHandler"
> >
</SYStackedCarousel> </SYStackedCarousel>
<view class="flex" v-if="swiperCurrent">
<view class="flex flex-column" v-if="swiperCurrent">
<view class="title">{{ swiperCurrent.title }}</view> <view class="title">{{ swiperCurrent.title }}</view>
<view class="tag">{{ swiperCurrent.createTime }}</view> <view class="tag">{{ swiperCurrent.createTime }}</view>
</view> </view>
@ -30,12 +30,12 @@
</view> </view>
<view class="section" v-for="item in list" :key="item.id"> <view class="section" v-for="item in list" :key="item.id">
<view class="section-header">
<view class="flex section-header">
<view class="flex title"> <view class="flex title">
<view>{{ item.title }}</view> <view>{{ item.title }}</view>
<view v-if="isManager" class="btn btn-add" @click="onAdd(item.id)">新增记录</view> <view v-if="isManager" class="btn btn-add" @click="onAdd(item.id)">新增记录</view>
</view> </view>
<button class="flex btn btn-all" @click="showAll">
<button class="flex btn btn-all" @click="showAll(item.id)">
<view>查看全部</view> <view>查看全部</view>
<image class="icon" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image> <image class="icon" src="@/static/image/icon-arrow-right.png" mode="widthFix"></image>
</button> </button>
@ -95,22 +95,51 @@
async fetchBanner() { async fetchBanner() {
this.bannerList = [ this.bannerList = [
{ {
url: '/pages_order/static/temp-23.png',
url: '/static/image/temp-20.png',
title: '趣玩新加坡', title: '趣玩新加坡',
createTime: '2025-04-18', createTime: '2025-04-18',
}, },
{ {
url: '/pages_order/static/temp-24.png',
url: '/static/image/temp-20.png',
title: '坝上双草原', title: '坝上双草原',
createTime: '2025-04-18', createTime: '2025-04-18',
}, },
{ {
url: '/pages_order/static/temp-25.png',
url: '/static/image/temp-20.png',
title: '牛湖线', title: '牛湖线',
createTime: '2025-04-18', 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',
]
},
]
},
clickHandler(item, index) { clickHandler(item, index) {
console.log("item: ", item); console.log("item: ", item);
console.log("index: ", index); console.log("index: ", index);
@ -125,6 +154,9 @@
onAdd() { onAdd() {
this.$refs.formPopup.open() this.$refs.formPopup.open()
}, },
showAll(id) {
this.$utils.navigateTo(`/pages_order/live/index?id=${id}`)
},
}, },
} }
</script> </script>
@ -152,7 +184,7 @@
} }
.main { .main {
padding: 0 40rpx;
padding: 0 40rpx 40rpx 40rpx;
} }
.header { .header {
@ -178,6 +210,7 @@
margin-top: 64rpx; margin-top: 64rpx;
&-header { &-header {
justify-content: space-between;
font-size: 36rpx; font-size: 36rpx;
font-weight: 500; font-weight: 500;
color: #191919; color: #191919;
@ -222,6 +255,7 @@
gap: 16rpx; gap: 16rpx;
&-item { &-item {
height: 300rpx;
border: 2rpx solid #CDCDCD; border: 2rpx solid #CDCDCD;
border-radius: 12rpx; border-radius: 12rpx;
overflow: hidden; overflow: hidden;


+ 1
- 1
pages_order/order/components/orderInfoView.vue View File

@ -14,7 +14,7 @@
<view>{{ getTypeDesc(item.type) }}</view> <view>{{ getTypeDesc(item.type) }}</view>
<view class="light">{{ getTypeTips(item.type) }}</view> <view class="light">{{ getTypeTips(item.type) }}</view>
</view> </view>
<view class="info-bottom">{{ item.idNo }}</view>
<view class="info-bottom">{{ item.cerNo }}</view>
</view> </view>
<view class="flex price">¥<view class="highlight">{{ item.price }}</view></view> <view class="flex price">¥<view class="highlight">{{ item.price }}</view></view>
</view> </view>


+ 4
- 16
pages_order/order/orderConfirm/index.vue View File

@ -342,7 +342,9 @@
phone, phone,
} }
await this.$fetch('createOrder', params)
const result = await this.$fetch('createOrder', params)
// todo: check result includes order id?
const orderInfo = { const orderInfo = {
product, product,
@ -362,7 +364,7 @@
// todo: get id? // todo: get id?
uni.navigateTo({ uni.navigateTo({
url: `/pages_order/order/orderPay/index`
url: `/pages_order/order/orderPay/index?id=${result.id}`
}) })
} catch (err) { } catch (err) {
@ -370,20 +372,6 @@
} }
}, },
onPaySuccess() {
setTimeout(() => {
// todo: check jump to order list page ?
uni.reLaunch({
url: `/pages_order/order/orderList/index`
});
}, 700)
},
onPayCancel() {
// todo: check jump to order list page?
uni.redirectTo({
url: `/pages_order/order/orderList/index?index=1`
});
},
}, },
} }
</script> </script>


+ 1
- 40
pages_order/order/orderConfirm/infoPopup.vue View File

@ -169,46 +169,7 @@
}, },
async getDefaultMembers() { async getDefaultMembers() {
try { try {
// todo: fetch defalt members
return [
{
id: '001',
name: '李梓发',
idNo: '430223********9999',
type: 0,
},
{
id: '002',
name: '吴彦谦',
idNo: '430223********9999',
type: 0,
},
{
id: '003',
name: '冯云',
idNo: '430223********9999',
type: 1,
},
{
id: '004',
name: '冯思钗',
idNo: '430223********9999',
type: 2,
},
{
id: '005',
name: '李书萍',
idNo: '430223********9999',
type: 0,
},
{
id: '006',
name: '冯艺莲',
idNo: '430223********9999',
type: 1,
},
]
return (await this.$fetch('queryTouristList', { isDefault: '1' })).records
} catch (err) { } catch (err) {
return [] return []
} }


+ 1
- 1
pages_order/order/orderConfirm/memberCard.vue View File

@ -18,7 +18,7 @@
<view>{{ data.name }}</view> <view>{{ data.name }}</view>
<view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view> <view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view>
</view> </view>
<view class="id">{{ data.idNo }}</view>
<view class="id">{{ data.cerNo }}</view>
</view> </view>
</view> </view>
</template> </template>


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

@ -58,10 +58,11 @@
}, },
methods: { methods: {
priceInt(priceDiscount) { priceInt(priceDiscount) {
return parseInt(priceDiscount)
return Math.floor(priceDiscount)
}, },
priceFrac(priceDiscount) { priceFrac(priceDiscount) {
return (priceDiscount % this.priceInt(priceDiscount)).toFixed(2).slice(1)
let frac = priceDiscount % this.priceInt(priceDiscount)
return frac > 0 ? frac.toFixed(2).slice(1) : ''
}, },
}, },
} }


+ 13
- 8
pages_order/order/orderDetail/index.vue View File

@ -91,6 +91,7 @@
}, },
data() { data() {
return { return {
id: null,
detail: {}, detail: {},
} }
}, },
@ -118,10 +119,10 @@
return total return total
}, },
}, },
onLoad() {
// console.log('orderInfo', this.orderInfo)
// this.detail = this.orderInfo
// todo: check fetch by id?
onLoad(arg) {
const { id } = arg
this.id = id
this.getData() this.getData()
}, },
onPullDownRefresh() { onPullDownRefresh() {
@ -131,6 +132,10 @@
async getData() { async getData() {
try { try {
this.detail = await this.$fetch('queryOrderById', { orderId: this.id })
return
this.detail = { this.detail = {
product: { product: {
id: '001', id: '001',
@ -181,7 +186,7 @@
members: [ members: [
{ {
id: "001", id: "001",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "李梓发", name: "李梓发",
@ -189,7 +194,7 @@
}, },
{ {
id: "002", id: "002",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "吴彦谦", name: "吴彦谦",
@ -197,7 +202,7 @@
}, },
{ {
id: "003", id: "003",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "冯云", name: "冯云",
@ -205,7 +210,7 @@
}, },
{ {
id: "004", id: "004",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "冯思钗", name: "冯思钗",


+ 11
- 6
pages_order/order/orderPay/index.vue View File

@ -91,6 +91,7 @@
}, },
data() { data() {
return { return {
id: null,
detail: {}, detail: {},
} }
}, },
@ -118,7 +119,9 @@
return total return total
}, },
}, },
onLoad() {
onLoad({ id }) {
this.id = id
// console.log('orderInfo', this.orderInfo) // console.log('orderInfo', this.orderInfo)
// this.detail = this.orderInfo // this.detail = this.orderInfo
// todo: check fetch by id? // todo: check fetch by id?
@ -181,7 +184,7 @@
members: [ members: [
{ {
id: "001", id: "001",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "李梓发", name: "李梓发",
@ -189,7 +192,7 @@
}, },
{ {
id: "002", id: "002",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "吴彦谦", name: "吴彦谦",
@ -197,7 +200,7 @@
}, },
{ {
id: "003", id: "003",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "冯云", name: "冯云",
@ -205,7 +208,7 @@
}, },
{ {
id: "004", id: "004",
idNo: "430223********9999",
cerNo: "430223********9999",
isDefault: false, isDefault: false,
isSelected: true, isSelected: true,
name: "冯思钗", name: "冯思钗",
@ -236,8 +239,10 @@
async onPay() { async onPay() {
try { try {
// todo: fetch pay
const result = await this.$fetch('payOrder', { orderId: this.id })
await uni.requestPaymentWxPay({ result })
uni.showToast({ uni.showToast({
title: '支付成功', title: '支付成功',
icon: 'none' icon: 'none'


+ 2
- 3
pages_order/product/collectList.vue View File

@ -6,7 +6,7 @@
<view class="list"> <view class="list">
<view class="list-item" v-for="item in list" :key="item.id"> <view class="list-item" v-for="item in list" :key="item.id">
<productCard :data="item" :isCollected="true" @collect="getData"></productCard>
<productCard :data="item.activity" :isCollected="true" @collect="getData"></productCard>
</view> </view>
</view> </view>
</view> </view>
@ -24,8 +24,7 @@
}, },
data() { data() {
return { return {
// todo: queryCollectionActivityList
mixinsListApi: '',
mixinsListApi: 'queryCollectionActivityList',
} }
}, },
} }


+ 28
- 26
pages_order/product/productDetail.vue View File

@ -1,8 +1,9 @@
<template> <template>
<view class="page__view"> <view class="page__view">
<navbar title="活动详情" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="transparent" />
<view class="main"> <view class="main">
<navbar title="活动详情" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="transparent" />
<view class="swiper"> <view class="swiper">
<uv-swiper <uv-swiper
:list="bannerList" :list="bannerList"
@ -18,10 +19,9 @@
<view class="card info"> <view class="card info">
<view class="card-header">{{ detail.title }}</view> <view class="card-header">{{ detail.title }}</view>
<view class="card-content"> <view class="card-content">
<!-- todo: check key -->
<view class="desc">{{ detail.brief }}</view> <view class="desc">{{ detail.brief }}</view>
<view class="flex tags" v-if="detail.tagDetails">
<view class="tag" v-for="(tag, tIdx) in detail.tagDetails" :key="tIdx">
<view class="flex tags" v-if="tagList.length">
<view class="tag" v-for="(tag, tIdx) in tagList" :key="tIdx">
{{ tag }} {{ tag }}
</view> </view>
</view> </view>
@ -147,11 +147,18 @@
return Array.isArray(image) ? image : image.split(',') return Array.isArray(image) ? image : image.split(',')
}, },
tagList() {
// todo: check key
const { tagDetails } = this.detail || {}
return tagDetails?.length ? tagDetails.split('、') : []
},
priceInt() { priceInt() {
return parseInt(this.detail.priceDiscount)
return Math.floor(this.detail.priceDiscount)
}, },
priceFrac() { priceFrac() {
return (this.detail.priceDiscount % this.priceInt).toFixed(2).slice(1)
let frac = this.detail.priceDiscount % this.priceInt
return frac > 0 ? frac.toFixed(2).slice(1) : ''
}, },
displayContent() { displayContent() {
const { const {
@ -181,6 +188,18 @@
}, },
methods: { methods: {
async fetchDetail(activityId) { async fetchDetail(activityId) {
try {
const result = await this.$fetch('queryActivityById', { activityId })
// todo: init options
this.detail = result
} catch (err) {
}
return
// todo: delete // todo: delete
this.detail = { this.detail = {
id: '001', id: '001',
@ -239,18 +258,6 @@
<p> <p>
`, `,
} }
return
try {
const result = await this.$fetch('queryActivityById', { activityId })
// todo: init options
this.detail = result
} catch (err) {
}
}, },
async fetchComment(id) { async fetchComment(id) {
@ -298,18 +305,12 @@
min-height: 100vh; min-height: 100vh;
background: linear-gradient(#DAF3FF, #F3F3F3 500rpx, #F3F3F3); background: linear-gradient(#DAF3FF, #F3F3F3 500rpx, #F3F3F3);
position: relative; position: relative;
/deep/ .nav-bar__view {
position: fixed;
top: 0;
left: 0;
}
} }
.main { .main {
width: 100vw; width: 100vw;
padding: calc(var(--status-bar-height) + 120rpx) 0 198rpx 0;
// padding: calc(var(--status-bar-height) + 120rpx) 0 198rpx 0;
padding-bottom: 198rpx;
box-sizing: border-box; box-sizing: border-box;
} }
@ -357,6 +358,7 @@
.desc { .desc {
font-size: 26rpx; font-size: 26rpx;
white-space: pre-wrap;
color: #8B8B8B; color: #8B8B8B;
} }


+ 16
- 63
pages_order/product/search.vue View File

@ -2,7 +2,7 @@
<view class="page__view"> <view class="page__view">
<!-- 导航栏 --> <!-- 导航栏 -->
<navbar title="搜索结果" leftClick @leftClick="$utils.navigateBack" bgColor="transparent" color="#191919" />
<navbar :title="title" leftClick @leftClick="$utils.navigateBack" bgColor="transparent" color="#191919" />
<!-- 搜索栏 --> <!-- 搜索栏 -->
<view :class="['flex', 'search', isFocusSearch ? 'is-focus' : '']" > <view :class="['flex', 'search', isFocusSearch ? 'is-focus' : '']" >
@ -56,6 +56,7 @@
}, },
data() { data() {
return { return {
title: '搜索结果',
keyword: '', keyword: '',
isFocusSearch: false, isFocusSearch: false,
queryParams: { queryParams: {
@ -68,75 +69,27 @@
mixinsListApi: 'queryActivityList', mixinsListApi: 'queryActivityList',
} }
}, },
onLoad({ search }) {
onLoad({ search, title, isDiscount, isHot, isNew }) {
if (search) { if (search) {
this.keyword = search this.keyword = search
this.queryParams.title = search this.queryParams.title = search
} }
if (title) {
this.title = title
}
if (isDiscount) {
this.queryParams.isDiscount = isDiscount
}
if (isHot) {
this.queryParams.isHot = isHot
}
if (isNew) {
this.queryParams.isNew = isNew
}
this.getData() this.getData()
}, },
methods: {
// todo: delete
getData() {
this.list = [
{
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,
},
]
this.total = this.list.length
},
methods: {
search() { search() {
this.queryParams.pageNo = 1 this.queryParams.pageNo = 1
this.queryParams.pageSize = 10 this.queryParams.pageSize = 10


+ 8
- 31
pages_order/traveler/travelerCard.vue View File

@ -2,24 +2,20 @@
<view class="card"> <view class="card">
<view class="flex top"> <view class="flex top">
<view> <view>
<uv-checkbox-group
v-model="selectCheckboxValue"
@change="onSelectChange"
>
<uv-checkbox
size="36rpx"
icon-size="36rpx"
activeColor="#00A9FF"
:name="1"
></uv-checkbox>
</uv-checkbox-group>
<uv-checkbox
size="36rpx"
icon-size="36rpx"
activeColor="#00A9FF"
:name="data.id"
></uv-checkbox>
</view> </view>
<view class="info"> <view class="info">
<view class="flex name"> <view class="flex name">
<view>{{ data.name }}</view> <view>{{ data.name }}</view>
<!-- todo: transform periodId to desc -->
<view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view> <view :class="['tag', `tag-${data.type}`]">{{ typeDesc }}</view>
</view> </view>
<view class="id">{{ data.idNo }}</view>
<view class="id">{{ data.cerNo }}</view>
</view> </view>
</view> </view>
<view class="flex bottom"> <view class="flex bottom">
@ -70,25 +66,10 @@
}, },
data() { data() {
return { return {
selectCheckboxValue: [],
defaultCheckboxValue: [], defaultCheckboxValue: [],
} }
}, },
computed: { computed: {
isSelected: {
set(val) {
this.selectCheckboxValue = val ? [1]: []
if (this.data.isSelected == val) {
return
}
this.$emit('selectChange', val)
},
get() {
return this.selectCheckboxValue.length ? true : false
}
},
isDefault: { isDefault: {
set(val) { set(val) {
this.defaultCheckboxValue = val ? [1]: [] this.defaultCheckboxValue = val ? [1]: []
@ -110,7 +91,6 @@
watch: { watch: {
data: { data: {
handler(val) { handler(val) {
this.isSelected = val.isSelected
this.isDefault = val.isDefault this.isDefault = val.isDefault
}, },
immediate: true, immediate: true,
@ -118,9 +98,6 @@
} }
}, },
methods: { methods: {
onSelectChange(val) {
this.isSelected = val.length ? true : false
},
onDefaultChange(val) { onDefaultChange(val) {
this.isDefault = val.length ? true : false this.isDefault = val.length ? true : false
}, },


+ 27
- 88
pages_order/traveler/travelerList.vue View File

@ -4,17 +4,16 @@
<navbar title="选择出行人" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" /> <navbar title="选择出行人" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" />
<view class="main"> <view class="main">
<view class="card" v-for="item in list" :key="item.id">
<travelerCard
:data="item"
@defaultChange="onDefaultChange(item.id, $event)"
@selectChange="onSelectChange(item.id, $event)"
@edit="onEdit(item.id)"
@delete="onDelete(item.id)"
></travelerCard>
</view>
<uv-checkbox-group v-model="selectedIdList" placement="column">
<view class="card" v-for="item in list" :key="item.id">
<travelerCard
:data="item"
@defaultChange="onDefaultChange(item.id, $event)"
@edit="onEdit(item.id)"
@delete="onDelete(item.id)"
></travelerCard>
</view>
</uv-checkbox-group>
</view> </view>
<view class="flex bottom"> <view class="flex bottom">
@ -41,8 +40,7 @@
}, },
data() { data() {
return { return {
// todo: check key
mixinsListApi: '',
mixinsListApi: 'queryTouristList',
queryParams: { queryParams: {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
@ -63,91 +61,32 @@
this.$store.commit('setTravelerList', list) this.$store.commit('setTravelerList', list)
}, },
methods: { methods: {
updateSelectIdList() {
this.selectedIdList = this.list.filter(item => item.isSelected).map(item => item.id)
},
// todo: delete
getData() {
let records = [
{
id: '001',
name: '李梓发',
idNo: '430223********9999',
type: 0,
isSelected: false,
isDefault: false,
},
{
id: '002',
name: '吴彦谦',
idNo: '430223********9999',
type: 0,
isSelected: false,
isDefault: false,
},
{
id: '003',
name: '冯云',
idNo: '430223********9999',
type: 1,
isSelected: false,
isDefault: false,
},
{
id: '004',
name: '冯思钗',
idNo: '430223********9999',
type: 2,
isSelected: false,
isDefault: false,
},
{
id: '005',
name: '李书萍',
idNo: '430223********9999',
type: 0,
isSelected: false,
isDefault: false,
},
{
id: '006',
name: '冯艺莲',
idNo: '430223********9999',
type: 1,
isSelected: false,
isDefault: false,
},
]
this.selectedIdList.forEach(id => {
const target = records.find(item => item.id === id)
target.isSelected = true
getDataThen(records) {
this.list = records.map(item => {
return {
...item,
// todo: transform periodId to type and type desc
type: 0, // 0- 1- 2-
isDefault: item.isDefault == '1' ? true : false
}
}) })
this.list = records
this.updateSelectIdList()
}, },
async onDefaultChange(id, val) { async onDefaultChange(id, val) {
try { try {
// todo: fetch
// await this.$fetch('setAddressDefault', { addressId })
const target = this.list.find(item => item.id === id) const target = this.list.find(item => item.id === id)
target.isDefault = val
const params = {
...target,
isDefault: val ? '1' : '0',
}
await this.$fetch('updateTourist', params)
this.updateSelectIdList()
target.isDefault = val
} catch (err) { } catch (err) {
} }
}, },
onSelectChange(id, val) {
const target = this.list.find(item => item.id === id)
target.isSelected = val
this.updateSelectIdList()
},
async onDelete(id) { async onDelete(id) {
uni.showToast({ uni.showToast({
@ -157,7 +96,7 @@
try { try {
// todo: check api & key // todo: check api & key
// await this.$fetch('deleteAddress', { id })
// await this.$fetch('deleteTourist', { id })
uni.showToast({ uni.showToast({
icon: 'success', icon: 'success',


+ 93
- 39
pages_order/traveler/travelerPopup.vue View File

@ -25,13 +25,13 @@
</uv-form-item> </uv-form-item>
</view> </view>
<view class="form-item"> <view class="form-item">
<uv-form-item prop="idNo" :customStyle="formItemStyle">
<uv-form-item prop="cerNo" :customStyle="formItemStyle">
<view class="form-item-label"> <view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image> <image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
身份证号 身份证号
</view> </view>
<view class="form-item-content"> <view class="form-item-content">
<formInput v-model="form.idNo"></formInput>
<formInput v-model="form.cerNo"></formInput>
</view> </view>
</uv-form-item> </uv-form-item>
</view> </view>
@ -42,7 +42,7 @@
类型 类型
</view> </view>
<view class="form-item-content"> <view class="form-item-content">
<uv-radio-group v-model="form.type"
<uv-radio-group v-model="form.periodId"
iconColor="#00A9FF" iconColor="#00A9FF"
iconSize="36rpx" iconSize="36rpx"
size="36rpx" size="36rpx"
@ -50,7 +50,7 @@
labelSize="26rpx" labelSize="26rpx"
> >
<uv-radio <uv-radio
v-for="(item, index) in typeOptions"
v-for="(item, index) in periodOptions"
:key="index" :key="index"
:label="item.label" :label="item.label"
:name="item.value" :name="item.value"
@ -61,13 +61,13 @@
</uv-form-item> </uv-form-item>
</view> </view>
<view class="form-item"> <view class="form-item">
<uv-form-item prop="gender" :customStyle="formItemStyle">
<uv-form-item prop="sex" :customStyle="formItemStyle">
<view class="form-item-label"> <view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image> <image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
性别 性别
</view> </view>
<view class="form-item-content"> <view class="form-item-content">
<uv-radio-group v-model="form.gender"
<uv-radio-group v-model="form.sex"
iconColor="#00A9FF" iconColor="#00A9FF"
iconSize="36rpx" iconSize="36rpx"
size="36rpx" size="36rpx"
@ -75,7 +75,7 @@
labelSize="26rpx" labelSize="26rpx"
> >
<uv-radio <uv-radio
v-for="(item, index) in genderOptions"
v-for="(item, index) in sexOptions"
:key="index" :key="index"
:label="item.label" :label="item.label"
:name="item.value" :name="item.value"
@ -97,10 +97,10 @@
</uv-form-item> </uv-form-item>
</view> </view>
<view class="form-item"> <view class="form-item">
<uv-form-item prop="wx" :customStyle="formItemStyle">
<uv-form-item prop="wechat" :customStyle="formItemStyle">
<view class="form-item-label">微信号</view> <view class="form-item-label">微信号</view>
<view class="form-item-content"> <view class="form-item-content">
<formInput v-model="form.wx"></formInput>
<formInput v-model="form.wechat"></formInput>
</view> </view>
</uv-form-item> </uv-form-item>
</view> </view>
@ -137,24 +137,24 @@
</uv-form-item> </uv-form-item>
</view> </view>
<view class="form-item"> <view class="form-item">
<uv-form-item prop="emergencyContact" :customStyle="formItemStyle">
<uv-form-item prop="emergencyPhone" :customStyle="formItemStyle">
<view class="form-item-label"> <view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image> <image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
紧急联系人 紧急联系人
</view> </view>
<view class="form-item-content"> <view class="form-item-content">
<formInput v-model="form.emergencyContact"></formInput>
<formInput v-model="form.emergencyPhone"></formInput>
</view> </view>
</uv-form-item> </uv-form-item>
</view> </view>
<view class="form-item"> <view class="form-item">
<uv-form-item prop="guardiancontact" :customStyle="formItemStyle">
<uv-form-item prop="chaperonPhone" :customStyle="formItemStyle">
<view class="form-item-label"> <view class="form-item-label">
<image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image> <image class="icon" src="@/pages_order/static/icon-require.png" mode="widthFix"></image>
监护人联系方式 监护人联系方式
</view> </view>
<view class="form-item-content"> <view class="form-item-content">
<formInput v-model="form.guardiancontact"></formInput>
<formInput v-model="form.chaperonPhone"></formInput>
</view> </view>
</uv-form-item> </uv-form-item>
</view> </view>
@ -211,17 +211,17 @@
title: null, title: null,
form: { form: {
name: null, name: null,
idNo: null,
type: 0,
gender: 0,
cerNo: null,
periodId: 0,
sex: 0,
phone: null, phone: null,
wx: null,
wechat: null,
school: null, school: null,
grade: null, grade: null,
age: null, age: null,
remark: null, remark: null,
emergencyContact: null,
guardiancontact: null,
emergencyPhone: null,
chaperonPhone: null,
}, },
rules: { rules: {
'name': { 'name': {
@ -229,17 +229,17 @@
required: true, required: true,
message: '请输入姓名', message: '请输入姓名',
}, },
'idNo': {
'cerNo': {
type: 'string', type: 'string',
required: true, required: true,
message: '请输入身份证号', message: '请输入身份证号',
}, },
'type': {
'periodId': {
type: 'string', type: 'string',
required: true, required: true,
message: '请选择类型', message: '请选择类型',
}, },
'gender': {
'sex': {
type: 'string', type: 'string',
required: true, required: true,
message: '请选择性别', message: '请选择性别',
@ -249,20 +249,20 @@
required: true, required: true,
message: '请输入手机号', message: '请输入手机号',
}, },
'emergencyContact': {
'emergencyPhone': {
type: 'string', type: 'string',
required: true, required: true,
message: '请输入紧急联系人联系方式', message: '请输入紧急联系人联系方式',
}, },
'guardiancontact': {
'chaperonPhone': {
type: 'string', type: 'string',
required: true, required: true,
message: '请输入监护人联系方式', message: '请输入监护人联系方式',
}, },
}, },
formItemStyle: { padding: 0 }, formItemStyle: { padding: 0 },
// todo: check
typeOptions: [
// todo: fetch
periodOptions: [
{ {
id: '001', id: '001',
label: '成人', label: '成人',
@ -279,7 +279,8 @@
value: '2', value: '2',
}, },
], ],
genderOptions: [
// todo: check
sexOptions: [
{ {
id: '001', id: '001',
label: '男', label: '男',
@ -295,10 +296,40 @@
} }
}, },
methods: { methods: {
async fetchTravelerDetail(id) {
async fetchTravelerDetail(personId) {
try { try {
// todo: fetch
const result = await this.$fetch('queryTouristById', { personId })
const {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
} = result
this.form = {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
}
} catch (err) { } catch (err) {
@ -315,17 +346,18 @@
this.title = '添加出行人' this.title = '添加出行人'
this.form = { this.form = {
name: null, name: null,
idNo: null,
type: 0,
gender: 0,
cerNo: null,
// todo: fetch default
periodId: 0,
sex: 0,
phone: null, phone: null,
wx: null,
wechat: null,
school: null, school: null,
grade: null, grade: null,
age: null, age: null,
remark: null, remark: null,
emergencyContact: null,
guardiancontact: null,
emergencyPhone: null,
chaperonPhone: null,
} }
} }
@ -353,16 +385,39 @@
await this.$refs.form.validate() await this.$refs.form.validate()
const { const {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
} = this.form } = this.form
const params = { const params = {
name,
cerNo,
periodId,
sex,
phone,
wechat,
school,
grade,
age,
remark,
emergencyPhone,
chaperonPhone,
} }
if (this.id) { if (this.id) {
params.id = this.id params.id = this.id
// todo: fetch
// await this.$fetch('updateAddress', params)
await this.$fetch('updateTourist', params)
uni.showToast({ uni.showToast({
icon: 'success', icon: 'success',
@ -371,8 +426,7 @@
} else { } else {
// todo: fetch
// await this.$fetch('addAddress', params)
await this.$fetch('addTourist', params)
uni.showToast({ uni.showToast({
icon: 'success', icon: 'success',


BIN
static/image/icon-close.png View File

Before After
Width: 48  |  Height: 48  |  Size: 978 B

BIN
static/image/icon-service.png View File

Before After
Width: 96  |  Height: 96  |  Size: 8.0 KiB

+ 2
- 7
store/store.js View File

@ -86,6 +86,8 @@ const store = new Vuex.Store({
}, },
// 获取用户个人信息 // 获取用户个人信息
getUserInfo(state){ getUserInfo(state){
// todo delete
return
api('getInfo', res => { api('getInfo', res => {
if(res.code == 200){ if(res.code == 200){
state.userInfo = res.result state.userInfo = res.result
@ -125,13 +127,6 @@ const store = new Vuex.Store({
async collect(state, activityId) { async collect(state, activityId) {
console.log('collect', activityId) console.log('collect', activityId)
// todo: delete
uni.showToast({
icon: 'success',
title: '已收藏',
});
return true
try { try {
await fetch('collectionActivity', { activityId }) await fetch('collectionActivity', { activityId })


+ 0
- 1
uni_modules/uv-tabs/components/uv-tabs/uv-tabs.vue View File

@ -135,7 +135,6 @@
current: { current: {
immediate: true, immediate: true,
handler (newValue, oldValue) { handler (newValue, oldValue) {
console.log('watch current', newValue, oldValue, this.innerCurrent)
// //
if (newValue !== this.innerCurrent) { if (newValue !== this.innerCurrent) {
this.innerCurrent = newValue this.innerCurrent = newValue


+ 0
- 3
uni_modules/uv-vtabs/components/uv-vtabs/uv-vtabs.vue View File

@ -202,7 +202,6 @@
}, },
watch: { watch: {
current(newVal){ current(newVal){
console.log('watch current', newVal)
if(!this.touching) if(!this.touching)
this.$nextTick(()=>{ this.$nextTick(()=>{
this.init(newVal?newVal:0); this.init(newVal?newVal:0);
@ -277,7 +276,6 @@
}, },
// //
async clickHandler(currentIndex) { async clickHandler(currentIndex) {
console.log('clickHandler', currentIndex, this.activeIndex)
if (currentIndex == this.activeIndex) return; if (currentIndex == this.activeIndex) return;
this.touching = true; this.touching = true;
this.activeIndex = currentIndex; this.activeIndex = currentIndex;
@ -287,7 +285,6 @@
// #ifndef MP-WEIXIN // #ifndef MP-WEIXIN
this.contentScrollTo = `content_${currentIndex}`; this.contentScrollTo = `content_${currentIndex}`;
// #endif // #endif
console.log('contentScrollTop', this.contentScrollTop)
} }
this.timer && clearTimeout(this.timer); this.timer && clearTimeout(this.timer);
throttle(()=>{ throttle(()=>{


Loading…
Cancel
Save