feat:接口对接,功能实现

This commit is contained in:
faiz 2024-10-23 09:48:48 +08:00
parent fe4d817b42
commit 8ad2b0296e
15 changed files with 756 additions and 261 deletions

View File

@ -3,7 +3,8 @@ type ServiceEnv = Record<ServiceEnvType, ServiceEnvConfig>
const serviceEnv: ServiceEnv = { const serviceEnv: ServiceEnv = {
dev: { dev: {
url: 'http://192.168.0.100:8787', // url: 'https://hex.jipinq.cn',
url: '/api',
json: 'http://localhost:8080', json: 'http://localhost:8080',
}, },
test: { test: {
@ -11,7 +12,7 @@ const serviceEnv: ServiceEnv = {
json: 'http://localhost:8080', json: 'http://localhost:8080',
}, },
prod: { prod: {
url: 'http://localhost:8080', url: 'https://hex.jipinq.cn',
json: 'http://localhost:8080', json: 'http://localhost:8080',
}, },
} }

View File

@ -1,5 +1,5 @@
{ {
"name" : "452", "name" : "旅游度假预约出行系统",
"appid" : "__UNI__FAB99D9", "appid" : "__UNI__FAB99D9",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.0",
@ -50,7 +50,7 @@
"quickapp" : {}, "quickapp" : {},
/* */ /* */
"mp-weixin" : { "mp-weixin" : {
"appid" : "wx56a1f8716a60996d", "appid" : "wx2e8b2af5ed5b28b4",
"setting" : { "setting" : {
"urlCheck" : false "urlCheck" : false
}, },

View File

@ -1,21 +1,28 @@
<template> <template>
<view class="home-head" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> <view class="home-head" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
<view class="nav"> <view class="nav">
<wd-icon @click='onBack' name="thin-arrow-left" size="35rpx"></wd-icon> <wd-icon @click="onBack" name="thin-arrow-left" size="35rpx"></wd-icon>
<text class='nav_title'>旅游度假 预约出行系统</text> <text class="nav_title">旅游度假 预约出行系统</text>
</view> </view>
<view class="main" v-if="status"> <view class="main" v-if="status">
<view class="list flex"> <view class="list flex">
<view class="lable">出游日期</view> <view class="lable">出游日期</view>
<view class="">2024年09月2日-2024年09月13日</view> <view class="">{{ travelDate }}</view>
</view> </view>
<wd-form ref="form" :model="model"> <wd-form ref="form" :model="model">
<wd-cell-group> <wd-cell-group>
<wd-picker prop='num' :rules="[{ required: true, message: '请选择出游人数' }]" :columns="columns" label="出游人数" v-model="model.num" @confirm="handleConfirm" /> <wd-picker
prop="num"
:rules="[{ required: true, message: '请选择出游人数' }]"
:columns="columns"
label="出游人数"
v-model="model.num"
@confirm="handleConfirm"
/>
<!-- <wd-icon name="camera" size="22px"></wd-icon> --> <!-- <wd-icon name="camera" size="22px"></wd-icon> -->
<view class="mist" v-for="(item, index) in model.num"> <view class="mist list flex">
<wd-input <!-- <wd-input
:key="index" :key="index"
:label="'出游券码截图' + (index+1)" :label="'出游券码截图' + (index+1)"
:prop="'voucher.' + index + '.value'" :prop="'voucher.' + index + '.value'"
@ -24,15 +31,23 @@
disabled disabled
no-border no-border
suffixIcon='camera' suffixIcon='camera'
@clicksuffixicon='handleUpdat(index)'
v-model="model.code_pic[index]" v-model="model.code_pic[index]"
placeholder="出游券码截图" placeholder="出游券码截图"
:rules="[{ required: true, message: '请填写出游券码截图' + (index+1) }]" :rules="[{ required: true, message: '请填写出游券码截图' + (index+1) }]"
/> /> -->
<view class='tip flex' @click="handleVoucherCode"> <view style="font-size: 28rpx; width: 200rpx">出游券码截图</view>
<wd-upload
v-model:file-list="fileList"
:limit="model.num"
:upload-method="customUpload"
@change="handleChange"
></wd-upload>
<view class="tip flex" @click="handleVoucherCode">
<view class="tip-bor flex items-center"> <view class="tip-bor flex items-center">
<image src="../../static/home/tip.png" mode=""></image> <image src="../../static/home/tip.png" mode=""></image>
</view> </view>
<view style="color: #2A8AFF;font-size: 22rpx;">如何查看券码</view> <view style="color: #2a8aff; font-size: 22rpx">如何查看券码</view>
</view> </view>
</view> </view>
<wd-input <wd-input
@ -53,9 +68,19 @@
clearable clearable
v-model="model.mobile" v-model="model.mobile"
placeholder="请输入出游人电话" placeholder="请输入出游人电话"
:rules="[{ required: true, message: '请填写出游人电话' }]" :rules="[
{ required: true, message: '请填写出游人电话' },
{ validator: checkPhone, message: '请填写正确的电话' }
]"
/>
<wd-textarea
no-border
size="large"
label-width="100rpx"
label="备注"
v-model="model.note"
placeholder="请填写备注"
/> />
<wd-textarea no-border size="large" label-width="100rpx" label="备注" v-model="model.note" placeholder="请填写备注" />
</wd-cell-group> </wd-cell-group>
<view class="footer"> <view class="footer">
@ -66,47 +91,50 @@
<view class="main" v-else> <view class="main" v-else>
<view class="status-icon"> <view class="status-icon">
<image src="../../static/home/scuss.png" mode=""></image> <image src="../../static/home/scuss.png" mode=""></image>
<view style="margin-top: 28rpx;"> <view style="margin-top: 28rpx">预约成功</view>
预约成功
</view> </view>
</view> </view>
</view> <!-- <view class="main" v-if="showQuan">
<view class="main" v-if="showQuan">
<image class="quan" src="../../static/home/quan.png"></image> <image class="quan" src="../../static/home/quan.png"></image>
</view> </view> -->
<wd-popup v-model="show" position='center' custom-style='border-radius: 25rpx;width:525rpx' @close="handleClose"> <wd-popup
v-model="show"
position="center"
custom-style="border-radius: 25rpx;width:525rpx"
@close="handleClose"
>
<view class="pop"> <view class="pop">
<view class="pop-title">确认预约</view> <view class="pop-title">确认预约</view>
<view class="pop-tip">预约成功后取消或修改需联系商家</view> <view class="pop-tip">预约成功后取消或修改需联系商家</view>
<view class="pop-list flex items-center"> <view class="pop-list flex items-center">
<view class="pop-icon flex items-center justify-center"> <view class="pop-icon flex items-center justify-center">
<wd-icon color='#1096FD' name="check" size="22rpx"></wd-icon> <wd-icon color="#1096FD" name="check" size="22rpx"></wd-icon>
</view> </view>
<view class="pop-desc overflow"> 欧洲13国12天9晚双飞游</view> <view class="pop-desc overflow">{{ productName }}</view>
</view> </view>
<view class="pop-list flex items-center"> <view class="pop-list flex items-center">
<view class="pop-icon flex items-center justify-center"> <view class="pop-icon flex items-center justify-center">
<wd-icon color='#1096FD' name="check" size="22rpx"></wd-icon> <wd-icon color="#1096FD" name="check" size="22rpx"></wd-icon>
</view> </view>
<view class="pop-desc overflow"> 2024.09.02(周一)-2024.09.13(周五)</view> <view class="pop-desc overflow">{{ travelDate }}</view>
</view> </view>
<view class="pop-list flex items-center"> <view class="pop-list flex items-center">
<view class="pop-icon flex items-center justify-center"> <view class="pop-icon flex items-center justify-center">
<wd-icon color='#1096FD' name="check" size="22rpx"></wd-icon> <wd-icon color="#1096FD" name="check" size="22rpx"></wd-icon>
</view> </view>
<view class="pop-desc overflow"> 1</view> <view class="pop-desc overflow">{{ model.num }}</view>
</view> </view>
<view class="pop-list flex items-center"> <view class="pop-list flex items-center">
<view class="pop-icon flex items-center justify-center"> <view class="pop-icon flex items-center justify-center">
<wd-icon color='#1096FD' name="check" size="22rpx"></wd-icon> <wd-icon color="#1096FD" name="check" size="22rpx"></wd-icon>
</view> </view>
<view class="pop-desc overflow"> 吴生</view> <view class="pop-desc overflow">{{ model.name }}</view>
</view> </view>
<view class="pop-list flex items-center"> <view class="pop-list flex items-center">
<view class="pop-icon flex items-center justify-center"> <view class="pop-icon flex items-center justify-center">
<wd-icon color='#1096FD' name="check" size="22rpx"></wd-icon> <wd-icon color="#1096FD" name="check" size="22rpx"></wd-icon>
</view> </view>
<view class="pop-desc overflow"> 13588779988</view> <view class="pop-desc overflow">{{ model.mobile }}</view>
</view> </view>
</view> </view>
<view class="bottom flex items-center"> <view class="bottom flex items-center">
@ -118,89 +146,181 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
// import {uploadImageOne} from '@/utils'
import { getServiceEnvConfig } from "@/config";
import { orderBook } from "@/service/api/user/index";
import { orderDetail } from "@/service/api/user/index";
import { showToast, checkPhone } from "@/utils";
const config = getServiceEnvConfig(import.meta.env);
import type {
UploadMethod,
UploadFile
} from "@/uni_modules/wot-design-uni/components/wd-upload/types";
const fileList = ref<UploadFile[]>([]);
// //
const { safeAreaInsets } = uni.getSystemInfoSync() const { safeAreaInsets } = uni.getSystemInfoSync();
// const { success: showSuccess } = useToast() // const { success: showSuccess } = useToast()
const status = ref(1) const status = ref(1);
const showQuan = ref(false) const showQuan = ref(false);
const show = ref(false);
const show = ref(false)
const handleVoucherCode = () => { const handleVoucherCode = () => {
// status.value = 0
// showQuan.value = true
uni.navigateTo({ uni.navigateTo({
url:'/pages/appointment-quan/index' url: "/pages/appointment-quan/index"
}) });
};
// const handleUpdat =(event:any)=>{
// uploadImageOne('/api/upload/index', res => {
// console.log(res)
// })
// }
//
const customUpload: UploadMethod = (file, formData, options) => {
const uploadTask = uni.uploadFile({
url: config.url + "/api/upload/index",
header: options.header,
name: options.name,
fileName: options.name,
fileType: options.fileType,
formData,
filePath: file.url,
success(res) {
if (res.statusCode === options.statusCode) {
//
options.onSuccess(res, file, formData);
} else {
//
options.onError({ ...res, errMsg: res.errMsg || "" }, file, formData);
}
},
fail(err) {
//
options.onError(err, file, formData);
}
});
//
uploadTask.onProgressUpdate(res => {
options.onProgress(res, file);
});
};
//
const handleChange = ({ fileList }) => {
fileList.value = fileList;
};
//
const handleClose = () => {
show.value = false;
};
//
const handleSave = () => {
orderBook(model).then((res: any) => {
if (res.msg == "ok") {
show.value = false;
status.value = 0;
} else {
show.value = false;
showToast({
icon: "none",
title: res.error
});
setTimeout(() => {
uni.switchTab({
url: "/pages/index/index"
});
}, 1000);
}
});
};
const travelDate = ref("");
const detailData = ref({});
const productName = ref("");
//
onLoad(async ({ date, start, order_id }) => {
travelDate.value = decodeURIComponent(date);
model.travel_date = start;
model.order_id = order_id;
let res: any = await orderDetail({ order_id });
if (res.msg == "ok") {
productName.value = res.data.product_name;
console.log(productName.value);
}
});
const model = reactive<{
num: number;
code_pic: Array;
name: String;
mobile: String;
note: String;
travel_date: String;
order_id: String;
}>({
num: 1,
code_pic: [],
name: "",
mobile: "",
note: "",
travel_date: "",
order_id: ""
});
const form = ref();
const columns = ref([1, 2, 3, 4, 5, 6, 7]);
//
function handleConfirm({ value }) {
model.num = value;
let count = fileList.value.length - value;
fileList.value.splice(-count, count);
} }
const handleClose = ()=>{ const handleSubmit = () => {
show.value = false console.log(fileList.value);
if (!fileList.value.length) {
return showToast({
icon: "none",
title: "请上传出游券码截图"
});
} }
const handleSave = ()=>{ model.code_pic = fileList.value.map(item => {
return JSON.parse(item.response).data;
});
// if(model.code_pic.length<model.num){
// return showToast({
// icon: "none",
// title: ""
// });
// }
form.value form.value
.validate() .validate()
.then(({ valid, errors }) => { .then(({ valid, errors }) => {
if (valid) { if (valid) {
// showSuccess({ show.value = true;
// msg: ''
// })
show.value = false
} }
}) })
.catch((error) => { .catch(error => {
console.log(error, 'error') console.log(error, "error");
}) });
} };
onLoad(() => {
console.log(safeAreaInsets)
})
const model = reactive<{
num: number,
code_pic: Array,
name:string,
mobile:string,
note:string
}>({
num: 1,
code_pic: [],
name:'',
mobile:'',
note:''
})
const form = ref()
const columns = ref([1, 2, 3, 4, 5, 6, 7])
function handleConfirm({ value }) {
model.num = value
}
const handleSubmit = ()=> {
show.value = true
// form.value
// .validate()
// .then(({ valid, errors }) => {
// if (valid) {
// // showSuccess({
// // msg: ''
// // })
// }
// })
// .catch((error) => {
// console.log(error, 'error')
// })
}
const handleAppointment = () => { const handleAppointment = () => {
uni.navigateTo({ uni.navigateTo({
url:'/pages/appointment-time/index' url: "/pages/appointment-time/index"
}) });
} };
const onBack = () => { const onBack = () => {
uni.navigateBack({ delta: 1 }) if (status.value) {
uni.navigateBack({ delta: 1 });
} else {
uni.switchTab({
url: "/pages/index/index"
});
} }
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -210,7 +330,7 @@ const onBack = ()=>{
color: #181818; color: #181818;
} }
.pdf { .pdf {
color: #0095FF; color: #0095ff;
font-size: 24rpx; font-size: 24rpx;
font-weight: bold; font-weight: bold;
} }
@ -224,7 +344,7 @@ const onBack = ()=>{
} }
.btn { .btn {
// margin-top: 160rpx; // margin-top: 160rpx;
background: #1170FF; background: #1170ff;
border-radius: 50rpx; border-radius: 50rpx;
padding: 20rpx 230rpx; padding: 20rpx 230rpx;
text-align: center; text-align: center;
@ -241,7 +361,7 @@ const onBack = ()=>{
} }
.pop-icon { .pop-icon {
border-radius: 50%; border-radius: 50%;
background: #E7F4FE; background: #e7f4fe;
width: 36rpx; width: 36rpx;
height: 36rpx; height: 36rpx;
} }
@ -266,15 +386,16 @@ const onBack = ()=>{
.bottom { .bottom {
width: 100%; width: 100%;
margin-top: 45rpx; margin-top: 45rpx;
border-top: 1px solid #D8D8D8; border-top: 1px solid #d8d8d8;
justify-content: space-between; justify-content: space-between;
.bottom-btn-left,.bottom-btn-right{ .bottom-btn-left,
.bottom-btn-right {
padding: 25rpx 0; padding: 25rpx 0;
width: 50%; width: 50%;
text-align: center; text-align: center;
} }
.bottom-btn-right { .bottom-btn-right {
border-left: 1px solid #D8D8D8; border-left: 1px solid #d8d8d8;
} }
} }
.status-icon { .status-icon {
@ -287,8 +408,12 @@ const onBack = ()=>{
} }
} }
.mist { .mist {
position: relative;
.tip { .tip {
margin-left: 28rpx; position: absolute;
left: 28rpx;
top: 80rpx;
// margin-left: 28rpx;
.tip-bor { .tip-bor {
margin-right: 10rpx; margin-right: 10rpx;
image { image {
@ -338,7 +463,7 @@ const onBack = ()=>{
border: 1px solid #444444; border: 1px solid #444444;
} }
::v-deep.wd-input__icon { ::v-deep.wd-input__icon {
color: #1170FF; color: #1170ff;
} }
// ::v-deep.wd-picker__cell{ // ::v-deep.wd-picker__cell{
// padding: 0; // padding: 0;

View File

@ -7,7 +7,7 @@
</view> </view>
<view class="main"> <view class="main">
<image class="quan" src="../../static/home/quan.png"></image> <image class="quan" src="http://hex.jipinq.cn/quan.png"></image>
</view> </view>
</view> </view>
</template> </template>

View File

@ -8,13 +8,13 @@
<view class="head-title"> <view class="head-title">
<text class="txt">选择出行日期</text> <text class="txt">选择出行日期</text>
<text class="data">可选</text> <text class="data">可选</text>
<text class="rde">12天9</text> <text class="rde">{{maxRange}}{{nights}}</text>
<text class="desc">·所选日期为北京时间</text> <text class="desc">·所选日期为北京时间</text>
</view> </view>
<wd-calendar-view custom-class='data' :panel-height='500' :formatter="formatter" :max-range="7" type="daterange" :show-panel-title='false' v-model="dataTime" @change="handleChange" /> <wd-calendar-view custom-class='data' :panel-height='500' :min-date='getProductId()' :formatter="formatter" :max-range="maxRange" type="daterange" :show-panel-title='false' v-model="dataTime" @change="handleChange" />
</view> </view>
<view class="bottom"> <view class="bottom">
<view class="desc">09.02-09.13 共12天9晚</view> <view class="desc">{{dataDesc}}</view>
<view class="btn" @click="handleMise"> <view class="btn" @click="handleMise">
下一步 下一步
</view> </view>
@ -23,9 +23,26 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { showToast } from '@/utils'
// //
const { safeAreaInsets } = uni.getSystemInfoSync() const { safeAreaInsets } = uni.getSystemInfoSync()
const dataTime = ref([])
const maxRange = ref(0)
const order_id = ref('')
const nights = ref(0)
onLoad(({day,id,night}) => {
maxRange.value = Number(day)
nights.value = night
order_id.value = id
})
const getProductId =()=>{
//
const yesterday = new Date();
const timestamp = yesterday.getTime(); //
return timestamp
}
const dataTime = ref([0,0])
const dataDesc = ref('') const dataDesc = ref('')
// //
const formatter = (day) => { const formatter = (day) => {
@ -40,10 +57,9 @@ const formatter = (day) => {
const nowDa = now.getDate() const nowDa = now.getDate()
day.bottomInfo = '可约' day.bottomInfo = '可约'
// if (year === nowYear && month === nowMonth && da === nowDa) { if (year === nowYear && month === nowMonth && da === nowDa) {
// day.topInfo = '' day.topInfo = '今天'
// } }
if (month === 5 && da === 18) { if (month === 5 && da === 18) {
day.topInfo = '618大促' day.topInfo = '618大促'
} }
@ -73,34 +89,110 @@ const formatter = (day) => {
const onBack = ()=>{ const onBack = ()=>{
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
} }
function isArrayOfNonEmptyValues(arr) {
// 使 every
return arr.every(item => item !== null && item !== undefined && item !== ''&& item);
}
const handleMise = ()=>{ const handleMise = ()=>{
uni.navigateTo({ let {days} = calculateDaysAndNights(travelStartDate.value,travelEndDate.value)
url:'/pages/appointment-form/index' if(isArrayOfNonEmptyValues(dataTime.value)){
if(days<maxRange.value){
return showToast({
icon: 'none',
title: '出发与结束日期不能小于7天',
}) })
} }
uni.navigateTo({
url:`/pages/appointment-form/index?date=${encodeURIComponent(travelDate.value)}&start=${travelStartDate.value}&order_id=${order_id.value}`
})
}else{
return showToast({
icon: 'none',
title: '选择出发与结束日期',
})
}
}
function getEndDateAfterNDays(startTimestamp:any, n:any) {
//
if (isNaN(startTimestamp) || typeof n !== 'number' || n < 0) {
throw new Error('Invalid input');
}
// Date
const start = new Date(startTimestamp * 1000);
// n
const end = new Date(start);
end.setDate(start.getDate() + n);
//
const endTimestamp = end.getTime() / 1000;
return endTimestamp;
}
function calculateDaysAndNights(startDate, endDate) {
// Date
const start = new Date(startDate);
const end = new Date(endDate);
//
const diffInMilliseconds = end - start;
//
const diffInDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
//
const nights = diffInDays;
// 1
const days = diffInDays + 1;
return { days, nights };
}
function padZero(num) {
return num < 10 ? '0' + num : num;
}
const travelDate = ref('')
const travelStartDate = ref('')
const travelEndDate = ref('')
const handleChange = ({ value })=>{ const handleChange = ({ value })=>{
const date = new Date(value[0]) const date = new Date(value[0])
// console.log(getEndDateAfterNDays(value[0],maxRange.value));
console.log(dataTime.value);
// dataTime.value[1] = getEndDateAfterNDays(value[0],maxRange.value)
// console.log(dataTime.value);
const now = new Date(value[1]) const now = new Date(value[1])
// const year = date.getFullYear() const year = date.getFullYear()
const month = date.getMonth() const month = date.getMonth()+1
const da = date.getDate() const da = date.getDate()
// const nowYear = now.getFullYear() const nowYear = now.getFullYear()
const nowMonth = now.getMonth() const nowMonth = now.getMonth()+1
const nowDa = now.getDate() const nowDa = now.getDate()
let {days,nights} = calculateDaysAndNights(`${year}-${padZero(month)}-${padZero(da)}`,`${nowYear}-${padZero(nowMonth)}-${padZero(nowDa)}`)
let wth = value[1]?`${days}${nights}`:''
// console.log(nowDa-da); // console.log(nowDa-da);
dataDesc.value = `${month}.${da}-${nowMonth}.${nowDa}` dataDesc.value = `${padZero(month)}.${padZero(da)}-${value[1]?padZero(nowMonth):''}${value[1]?'.':''}${value[1]?padZero(nowDa):''} ${wth}`
console.log(dataDesc.value) travelDate.value = `${year}${padZero(month)}${padZero(da)}日-${nowYear}${padZero(nowMonth)}${padZero(nowDa)}`
travelStartDate.value = `${year}-${padZero(month)}-${padZero(da)}`
travelEndDate.value = `${nowYear}-${padZero(nowMonth)}-${padZero(nowDa)}`
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
::v-deep .wd-month-panel__weeks,::v-deep .wd-month__day,::v-deep .wd-month__title,::v-deep .wd-month__day-text{
font-weight: 700;
}
::v-deep .wd-month__day{
height: var(--wot-calendar-day-height, 54px);
// line-height: var(--wot-calendar-day-height, 54px);
}
.txt{ .txt{
color: #181818; color: #181818;
font-size: 32rpx; font-size: 32rpx;

View File

@ -11,7 +11,7 @@
<view class="phone_input"> <view class="phone_input">
<wd-input no-border use-suffix-slot type="text" v-model="phone" center> <wd-input no-border use-suffix-slot type="text" v-model="phone" center>
<template #suffix> <template #suffix>
<view class="phone_btn">查询</view> <view class="phone_btn" @click="handleServe">查询</view>
</template > </template >
</wd-input> </wd-input>
</view> </view>
@ -19,55 +19,27 @@
<view class="home-list"> <view class="home-list">
<view class="list_title">查询结果:</view> <view class="list_title">查询结果:</view>
<view class="list_main"> <view class="list_main">
<view class="list_item"> <view class="list_item" v-for="(item) in serveOrderList">
<view class="order flex items-center"> <view class="order flex items-center">
<view class="id">订单编号4566888888</view> <view class="id">订单编号{{item.sn}}</view>
<!-- <view class="btn">去预约</view> --> <view v-if="item.can_book||item.is_book" class="btn" :class="item.is_book?'is-disabled':''" @click="handleAppointment(item.id)">{{item.is_book?'已提交':'去预约'}}</view>
</view> </view>
<view class="stroke"> <view class="stroke">
<text class="stroke_lable">行程</text> <text class="stroke_lable">行程</text>
<text class="stroke_desc">欧洲12天纯玩</text> <text class="stroke_desc">{{item.product_name}}</text>
</view> </view>
<view class="content flex items-center"> <view class="content flex items-center">
<view class="content_item"> <view class="content_item">
<view class="title">订单金额</view> <view class="title">订单金额</view>
<view class="desc">6800</view> <view class="desc">{{item.actual_price}}</view>
</view> </view>
<view class="content_item"> <view class="content_item">
<view class="title">状态</view> <view class="title">状态</view>
<wd-text size="24rpx" type="success" text="已使用"></wd-text> <wd-text size="24rpx" bold :type="item.can_book||item.is_book?'success':'error'" :text="item.h5_os_status_name"></wd-text>
<!-- <wd-text type="error" text="错误"></wd-text>
<wd-text text="默认"></wd-text>
<view class="desc">已使用</view> -->
</view> </view>
<view class="content_item"> <view class="content_item">
<view class="title">下单平台</view> <view class="title">下单平台</view>
<view class="desc">美团官方视频号直播</view> <view class="desc">{{item.h5_os_name}}</view>
</view>
</view>
</view>
<view class="list_item">
<view class="order flex items-center">
<view class="id">订单编号4566888888</view>
<view class="btn" @click="handleAppointment">去预约</view>
</view>
<view class="stroke">
<text class="stroke_lable">行程</text>
<text class="stroke_desc">欧洲12天纯玩</text>
</view>
<view class="content flex items-center">
<view class="content_item">
<view class="title">订单金额</view>
<view class="desc">6800</view>
</view>
<view class="content_item">
<view class="title">状态</view>
<wd-text type="error" size="24rpx" text="未预约"></wd-text>
<!-- <view class="desc">未预约</view> -->
</view>
<view class="content_item">
<view class="title">下单平台</view>
<view class="desc">美团官方视频号直播</view>
</view> </view>
</view> </view>
</view> </view>
@ -77,7 +49,10 @@
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {orderList} from '@/service/api/user/index'
import { getErrorMsg, hideLoading, showErrorModal, showLoading, showToast } from '@/utils'
// //
const { safeAreaInsets } = uni.getSystemInfoSync() const { safeAreaInsets } = uni.getSystemInfoSync()
@ -87,14 +62,35 @@ onLoad(() => {
}) })
const phone = ref('') const phone = ref('')
const handleAppointment = ()=>{ const handleAppointment = (id:[string,number])=>{
uni.navigateTo({ uni.navigateTo({
url:'/pages/user-info/index' url:`/pages/user-info/index?id=${id}`
}) })
} }
const serveOrderList = ref([])
const handleServe = async()=>{
let res = await orderList({mobile:phone.value})
if(res.msg =='ok'){
serveOrderList.value = res.data.data
}else{
showToast({
icon: 'none',
title: res.error,
})
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.is-disabled{
background: #D0D0D0 !important;
pointer-events: none;
// color: #181818 !important;
}
::v-deep .uni-input-input{
font-weight: 700;
}
.main-title-color { .main-title-color {
color: #d14328; color: #d14328;
} }
@ -208,6 +204,7 @@ const handleAppointment = ()=>{
.desc{ .desc{
margin-top: 14rpx; margin-top: 14rpx;
font-size: 24rpx; font-size: 24rpx;
font-weight: 700;
} }
} }
} }

View File

@ -8,23 +8,20 @@
<view class="main-item txt"> <view class="main-item txt">
<view class="main-title">下单行程</view> <view class="main-title">下单行程</view>
<view class="main-desc">欧洲12天纯玩</view> <view class="main-desc overflow">{{detailData.product_name}}</view>
</view> </view>
<view class="main-item"> <view class="main-item">
<view class="main-title txt">查看详细行程</view> <view class="main-title txt">查看详细行程</view>
<view class="flex items-center main_pdf flex-wrap"> <view class="flex items-center main_pdf flex-wrap">
<view class="main-desc pdf overflow">出境旅游合同.pdf</view> <view class="main-desc pdf overflow" @click="previewWechat(detailData.product.trip_info)">出境旅游合同.pdf</view>
</view> </view>
</view> </view>
<view class="main-item"> <view class="main-item">
<view class="main-title txt">查看旅游合同</view> <view class="main-title txt">查看旅游合同</view>
<view class="flex items-center main_pdf flex-wrap"> <view class="flex items-center main_pdf flex-wrap">
<view class="main-desc pdf overflow">出境旅游合同.pdf</view> <view class="main-desc pdf overflow" @click="previewWechat(detailData.travel_contract)">出境旅游合同.pdf</view>
<view class="main-desc pdf overflow">出境旅游合同.pdf</view>
<view class="main-desc pdf overflow">出境旅游合同.pdf</view>
<view class="main-desc pdf overflow">出境旅游合同.pdf</view>
</view> </view>
</view> </view>
@ -34,27 +31,28 @@
<view class="main_content_left"> <view class="main_content_left">
<view class="list"> <view class="list">
<text class="lable">姓名:</text> <text class="lable">姓名:</text>
<text class="box">李达</text> <text class="box">{{detailData.admin&&detailData.admin.name}}</text>
</view> </view>
<view class="list"> <view class="list">
<text class="lable">手机号:</text> <text class="lable">手机号:</text>
<text class="box">13355558888</text> <text class="box">{{detailData.mobile}}</text>
</view> </view>
<view class="list"> <view class="list">
<text class="lable">微信号:</text> <text class="lable">微信号:</text>
<text class="box">13355558888</text> <text class="box">{{detailData.admin&&detailData.admin.wechat}}</text>
</view> </view>
<view class="list"> <view class="list">
<text class="lable">职位:</text> <text class="lable">职位:</text>
<text class="box">金牌管家</text> <text class="box">{{detailData.admin&&detailData.admin.job}}</text>
</view> </view>
<view class="list"> <view class="list">
<text class="lable">服务承诺:</text> <text class="lable">服务承诺:</text>
<text class="box">顾客是上帝</text> <text class="box">{{detailData.admin&&detailData.admin.service_promise}}</text>
</view> </view>
</view> </view>
<view class="main_content_right"> <view class="main_content_right">
<image src="../../static/home/user.png" mode=""></image> <image v-if="detailData.admin&&detailData.admin.wechat_pic" :src="detailData.admin.wechat_pic" mode=""></image>
<image v-else src="../../static/home/user.png" mode=""></image>
</view> </view>
</view> </view>
<view class="btn" @click="handleAppointment"> 预约出行 </view> <view class="btn" @click="handleAppointment"> 预约出行 </view>
@ -65,18 +63,50 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {orderDetail} from '@/service/api/user/index'
// //
const { safeAreaInsets } = uni.getSystemInfoSync() const { safeAreaInsets } = uni.getSystemInfoSync()
onLoad(() => { const detailData = ref({})
console.log(safeAreaInsets) const order_id = ref('')
onLoad(async({id}) => {
order_id.value = id
let res:any = await orderDetail({order_id:id})
if(res.msg == 'ok'){
detailData.value = res.data
// console.log(res.data);
}
console.log(detailData.value)
}) })
const handleAppointment = ()=>{ const handleAppointment = ()=>{
uni.navigateTo({ uni.navigateTo({
url:'/pages/appointment-time/index' url:`/pages/appointment-time/index?day=${detailData.value.product.day}&night=${detailData.value.product.night}&id=${order_id.value}`
}) })
} }
//,.doc,.docx,.xls,.xlsx,.pdf
const previewWechat=(urlPdf:String)=> {
uni.showLoading({
title: '正在加载中..'
})
uni.downloadFile({
url: urlPdf,
success: function(res) {
var filePath = res.tempFilePath;
uni.openDocument({
filePath: filePath,
showMenu: true,
success: function(res) {
console.log('打开文档成功');
uni.hideLoading()
},
});
},
complete: function(r) {
uni.hideLoading()
}
});
}
const onBack = ()=>{ const onBack = ()=>{
uni.navigateBack({ delta: 1 }) uni.navigateBack({ delta: 1 })
} }

View File

@ -10,6 +10,27 @@ export function fetchUserInfo() {
url: 'xxxxxxxxxxxx/user', url: 'xxxxxxxxxxxx/user',
}) })
} }
// 订单预约
export function orderBook(data:any) {
return apiResquest.post({
url: 'order/book',
data
})
}
// 查询列表
export function orderList(data:any) {
return apiResquest.get({
url: 'order/index',
data
})
}
// 订单详情
export function orderDetail(data:any) {
return apiResquest.get({
url: 'order/detail',
data
})
}
// async () => { // async () => {
// const { age, name } = await fetchUserInfo() // const { age, name } = await fetchUserInfo()

View File

@ -12,7 +12,7 @@ export const apiResquest = createRequest(
}, },
}, },
{ {
requestInterceptors: [tokenRequestInterceptor], // requestInterceptors: [tokenRequestInterceptor],
responseInterceptors: [statusResponseInterceptor, resultResponseInterceptor], responseInterceptors: [statusResponseInterceptor, resultResponseInterceptor],
}) })

View File

@ -35,12 +35,13 @@ export function createRequest(baseRequestConfig: RequestConfig, interceptorConfi
return new Promise<T>((resolve, reject) => { return new Promise<T>((resolve, reject) => {
uni.request({ uni.request({
url: `${baseURL}${url}`, url: `${baseURL}/api/${url}`,
method, method,
header, header,
timeout, timeout,
data, data,
success(result) { success(result:any) {
// console.log(result)
try { try {
// 响应拦截器 // 响应拦截器
result = invokeArrayFns(responseInterceptors as Function[], result) result = invokeArrayFns(responseInterceptors as Function[], result)
@ -55,9 +56,10 @@ export function createRequest(baseRequestConfig: RequestConfig, interceptorConfi
reject(msg) reject(msg)
return return
} }
// console.log(result.data)
resolve(result.data)
// 自定义返回数据 // 自定义返回数据
resolve(returnData(result.data) as T) // resolve(returnData(result.data) as T)
// 显示成功toast // 显示成功toast
if (successMsg) { if (successMsg) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -2,3 +2,5 @@ export * from './error'
export * from './modal' export * from './modal'
export * from './route' export * from './route'
export * from './storage' export * from './storage'
export * from './updataImg'
export * from './validate'

View File

@ -0,0 +1,139 @@
import { getServiceEnvConfig } from '@/config'
const config = getServiceEnvConfig(import.meta.env)
/**
* toast
*/
const msg = (params:any, callback:any) => {
setTimeout(() => {
uni.showToast({
title: typeof params === 'string' ? params : params.title,
duration: params.item || 1500,
mask: params.mask || true,
icon: params.icon || 'none'
})
setTimeout(() => {
if (typeof callback === "function") { callback() };
}, params.item || 1500)
}, 0)
}
/*
*
* @param object opt
* @param callable successCallback data
* @param callable errorCallback
*/
export const uploadImageOne = function (opt:any, successCallback:Function, errorCallback:Function) {
if (typeof opt === "string") {
let url = opt;
opt = {};
opt.url = url;
}
let count = opt.count || 1,
sizeType = opt.sizeType || ["compressed"],
sourceType = opt.sourceType || ["album", "camera"],
is_load = opt.is_load || true,
uploadUrl = opt.url || "";
// inputName = opt.name || "field";
uni.chooseImage({
count: count, //最多可以选择的图片总数
sizeType: sizeType, // 可以指定是原图还是压缩图,默认二者都有
sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有
success: async (res:any) => {
let image = [];
let filesLen = res.tempFiles.length;
let exceeded_list = [];
let uploadMaxSize = 10;
let imageList = [];
let urlPath = config.url + uploadUrl;
if (count === 1) {
console.log(await uploadFile(urlPath, res.tempFilePaths[0], opt, "图片上传中"));
successCallback &&
successCallback(await uploadFile(urlPath, res.tempFilePaths[0], opt, "图片上传中"));
} else {
for (let i = 0; i < res.tempFiles.length; i++) {
if (Math.ceil(res.tempFiles[i].size / 1024) < uploadMaxSize * 1024) {
image.push(res.tempFiles[i].path);
} else {
exceeded_list.push(i + 1);
filesLen = filesLen - 1;
// #ifdef APP-PLUS
plus.nativeUI.alert(
`${[...new Set(exceeded_list)].join(",")}张图片超出限制${uploadMaxSize}MB,已过滤`
);
// #endif
// #ifndef APP-PLUS
uni.showModal({
content: `${[...new Set(exceeded_list)].join(
","
)}${uploadMaxSize}MB,`,
});
// #endif
continue;
}
}
for (const key in image) {
let data = await uploadFile(urlPath, image[key], opt, "图片上传中");
imageList.push(data.data.url);
}
successCallback && successCallback(imageList);
}
},
});
}
const uploadFile = (urlPath:any, localPath:any, opt:any, message:any) => {
console.log(urlPath);
console.log(localPath);
return new Promise(async resolve => {
//启动上传等待中...
if (message)
uni.showLoading({
title: message,
});
uni.uploadFile({
url: urlPath,
filePath: localPath,
name: opt.name || "file",
header: {
// 'Authorization': 'Bearer ' + uni.getStorageSync('access-token'),
'accept': 'application/json',
},
// header: {
// // #ifdef MP
// "Content-Type": "multipart/form-data",
// // #endif
// // [TOKENNAME]: "Bearer " + store.state.app.token,
// },
success: function (res) {
uni.hideLoading();
if (res.statusCode == 403) {
// uni.showToast({
// title: res.data,
// duration:1500,
// icon: 'none'
// })
} else {
let data = res.data ? JSON.parse(res.data) : {};
if (data.status == 'success') {
resolve(data);
} else {
// uni.showToast({
// title: data.message,
// duration:1500,
// icon: 'none'
// })
}
}
},
fail: function (res:any) {
uni.hideLoading();
// uni.showToast({
// title: res.errMsg,
// duration:1500,
// icon: 'none'
// })
},
});
});
}

View File

@ -0,0 +1,69 @@
/**
* 验证小数点后两位及多个小数
* money 金额
*/
export function isMoney(money) {
var reg = /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/;
if (reg.test(money)) {
return true;
} else {
return false;
}
}
/**
* 验证手机号码
*/
export function checkPhone(phone) {
var reg = /^1(3|4|5|6|7|8|9)\d{9}$/;
if (reg.test(phone)) {
return true;
} else {
return false;
}
}
/**
* 验证名字 中国
*/
export function checkCname(cn) {
var reg = /^[\u4e00-\u9fa5]{2,5}$/;
if (reg.test(cn)) {
return true;
} else {
return false;
}
}
/**
* 验证名字银行卡
*/
export function checkBank(card) {
var reg = /^\d{16,19}$/;
if (reg.test(card)) {
return true;
} else {
return false;
}
}
/**
* 验证邮箱
*/
export function isEmailAvailable(emailInput) {
var myreg =
/^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/;
if (!myreg.test(emailInput)) {
return false;
} else {
return true;
}
}
/**
* 验证身份证
*/
export function isIDcardAvailable(idCard) {
var myreg = /^[1-9]\d{14}(\d{2}(\d|X|x))?$/;
if (!myreg.test(idCard)) {
return false;
} else {
return true;
}
}

View File

@ -36,4 +36,21 @@ export default defineConfig({
} }
} }
}, },
server: {
port: 9529,
open: false,
proxy: {
"/api": {
target: "https://hex.jipinq.cn",
changeOrigin: true,
// pathRewrite: {
// '^/api': '/'
// },
rewrite: (path) => {
console.log(path)
return path.replace(/^\/api/, "")
},
},
},
}
}) })