浏览代码

feat: 沟通页面

chenjj 1 月之前
父节点
当前提交
7875f24ef4

+ 79 - 0
components/PositioningMap/index.vue

@@ -0,0 +1,79 @@
+<template>
+    <view>
+        <map id="wxMapId" :longitude="mapData.location.lng" :latitude="mapData.location.lat" :markers="markers"
+            style="width: 100%; height: 50vh;"></map>
+    </view>
+</template>
+
+<script setup>
+import { ref, onMounted, watch } from 'vue';
+const QQMapWX = require('../../static/sdk/qqmap-wx-jssdk.js')
+// 接收外部传入的地址
+const props = defineProps({
+    address: {
+        type: String,
+        required: true,
+        default: '重庆市永川区中山路街道文昌路700号'
+    }
+});
+
+// 地图上下文
+const mapCtx = ref(null);
+const markers = ref([]);
+
+const mapData = ref({
+    location: {
+        lat: 0,
+        lng: 0
+    }
+})
+let qqmapsdk = null;
+
+onMounted(() => {
+    mapCtx.value = wx.createMapContext('wxMapId');
+
+    qqmapsdk = new QQMapWX({
+        key: 'KFEBZ-P2GKZ-A5PX4-7Q6Y7-KXOBF-XCB4C'
+    });
+
+
+    // 如果地址已经传入,立即进行地址转经纬度
+    if (props.address) {
+        geocodeAddress(props.address);
+    }
+});
+
+// 监听地址变化
+watch(() => props.address, (newAddress) => {
+    if (newAddress) {
+        geocodeAddress(newAddress);
+    }
+});
+
+// 地址转经纬度
+const geocodeAddress = (address) => {
+    console.log('地址', address);
+
+    qqmapsdk.geocoder({
+        address: props.address,
+        success: function (res) {
+            console.log('初始化地图上下文', res);
+            mapData.value = res.result;
+            markers.value = [{ latitude: res.result.location.lat, longitude: res.result.location.lng,id: 1, }];
+        },
+        fail: function (error) {
+            console.error(error);
+        },
+    })
+
+};
+
+</script>
+
+<style lang="scss" scoped>
+map {
+    width: 100%;
+    height: 40vh;
+    /* 确保地图占满整个视图高度 */
+}
+</style>

+ 192 - 0
components/Slide/index.vue

@@ -0,0 +1,192 @@
+<template>
+    <view class="slider-verify" :style="'background-color:' + sBgColor" @touchend="touchend">
+        <view class="slider-prompt" :style="success ? 'color:' + sColor : 'color:' + dColor">{{ success ? sliderText.successText : sliderText.startText }}</view>
+        <view class="slider-bg" :style="{ 'transform': 'translateX(' + oldx + 'px)', backgroundColor: dBgColor }"></view>
+        <movable-area class="slider-area" :animation="true">
+            <movable-view 
+                :style="`background-color: ${sliderText.successColor};border-color: ${success ? sBgColor : dBgColor} `"
+                :class="{ 'movable-btn': true, 'movable-success': success }" :x="x" direction="horizontal" @change="onMove"
+                :disabled="isDisable">
+                {{sliderText.btnText}}
+            </movable-view>
+        </movable-area>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        //是否禁止拖动
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        //偏移量
+        offset: {
+            type: Number,
+            default: 3
+        },
+        //滑动轨道默认背景色
+        dBgColor: {
+            type: String,
+            default: '#f0f0f0'
+        },
+        //滑动轨道滑过背景色
+        sBgColor: {
+            type: String,
+            default: '#b1d7ff'
+        },
+        //默认文字颜色
+        dColor: {
+            type: String,
+            default: '#8a8a8a'
+        },
+        //成功文字颜色
+        sColor: {
+            type: String,
+            default: '#FFFFFF'
+        },
+        sliderText: {
+            type: Object,
+            default: {
+                successText:'验证通过',
+                startText:'拖动滑块验证',
+                successColor: '#72c13f',
+                btnText: '开始'
+            }
+        },
+
+    },
+    data() {
+        return {
+            x: 0,
+            oldx: 0,
+            success: false, //是否验证成功
+            verification: 0, //验证次数
+            isDisable: this.disabled,
+            screenWidth: 0
+        };
+    },
+    mounted() {
+        const systemInfo = uni.getSystemInfoSync()
+        this.screenWidth = systemInfo.screenWidth
+    },
+    methods: {
+        onMove(e) {
+            this.oldx = e.detail.x
+        },
+        touchend() {
+            if (this.success || (this.oldx < 1 && this.oldx != 0.1)) return
+            this.x = this.oldx
+            var promptW = 0
+            var onTrackW = 0
+            uni.createSelectorQuery().in(this).select(".slider-prompt").boundingClientRect(data => {
+                if (data.width > 0) {
+                    promptW = data.width
+                    uni.createSelectorQuery().in(this).select(".movable-btn").boundingClientRect(data => {
+                        if (data.width > 0) {
+                            onTrackW = data.width
+                            if (this.oldx != 0.1) this.verification++
+                            if (this.oldx > (promptW - onTrackW - this.offset)) {
+                                this.success = true
+                                this.isDisable = true
+                                this.verificationSuccess(true)
+                            } else {
+                                this.$nextTick(() => {
+                                    this.x = 0
+                                    this.oldx = 0
+                                })
+                                this.verificationSuccess(false)
+                            }
+                        }
+                    }).exec()
+                }
+            }).exec()
+        },
+        verificationSuccess(state) {
+            let obj = {
+                state: state,
+                verification: this.verification
+            }
+            this.$emit("change", obj)
+        },
+        //重置初始化状态
+        initialization() {
+            this.x = 0
+            this.oldx = 0.1
+            this.verification = 0
+            this.success = false
+            this.isDisable = false
+            this.touchend()
+        }
+    }
+}
+</script>
+
+<style scoped>
+.slider-verify {
+    position: relative;
+    width: 100%;
+    height: 100rpx;
+    overflow: hidden;
+}
+
+.slider-prompt {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 32rpx;
+    z-index: 99;
+}
+
+.slider-bg {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+
+.slider-area {
+    position: absolute;
+    top: 0;
+    left: 0;
+    height: 100%;
+    width: 100%;
+    z-index: 999;
+}
+
+.movable-btn {
+    width: 150rpx;
+    height: 100%;
+    border: solid 1px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 17px;
+    color: #fff;
+    /* width: 100rpx;
+    height: 100%;
+    box-sizing: border-box;
+    background-color: #FFFFFF;
+    border: solid 1px;
+    background-image: url(/static/img/go-right.png);
+    background-position: center;
+    background-size: 34rpx auto;
+    background-repeat: no-repeat;
+    display: flex;
+    align-content: center;
+    justify-content: center; */
+}
+
+.movable-success {
+    /* border: solid 1px;
+    background-image: url(/static/img/success.png);
+    background-size: 40rpx auto; */
+}
+</style>

+ 4 - 0
index.html

@@ -2,6 +2,7 @@
 <html lang="en">
   <head>
     <meta charset="UTF-8" />
+    <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> 
     <script>
       var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
         CSS.supports('top: constant(a)'))
@@ -16,5 +17,8 @@
   <body>
     <div id="app"><!--app-html--></div>
     <script type="module" src="/main.js"></script>
+
+    <!-- index.html -->
+    <!-- <script src="https://map.qq.com/api/js?v=2.exp&key=KFEBZ-P2GKZ-A5PX4-7Q6Y7-KXOBF-XCB4C"></script> -->
   </body>
 </html>

+ 3 - 0
main.js

@@ -10,6 +10,9 @@ export function createApp() {
   app.use(uviewPlus)
   app.use(plugins)
   app.use(store)
+
+
+
   return {
     app
   }

+ 1 - 1
manifest.json

@@ -50,7 +50,7 @@
     "quickapp" : {},
     /* 小程序特有相关 */
     "mp-weixin" : {
-        "appid" : "wxf8cc1f7fffc41354",
+        "appid" : "wxed3f482559db6196",
         "setting" : {
             "urlCheck" : false,
             "postcss" : true,

+ 6 - 0
pages.json

@@ -86,6 +86,12 @@
 			{
 				"navigationBarTitleText" : "订单详情"
 			}
+		},
+		{
+			"path": "pages/order/handle",
+			"style": {
+				"navigationBarTitleText": "订单处理"
+			}
 		}
 	    
         // ,{

+ 4 - 0
pages/classify.vue

@@ -90,7 +90,11 @@ function btnClick(row,type) {
 		uni.navigateTo({
 			url: `/pages/order/order?orderId=${row.secondOrderId}`
 		});
+		return
 	}
+	uni.navigateTo({
+			url: `/pages/order/handle?orderId=${row.secondOrderId}`
+		});
 
 }
 provide('onClick', btnClick);

+ 209 - 0
pages/order/handle.vue

@@ -0,0 +1,209 @@
+<!-- 订单详情 -->
+<template>
+    <view class="order-detail">
+        <view class="service-info order-card">
+            <PositioningMap />
+        </view>
+        <view class="user-info order-card">
+            <view class="user-box">
+                <view class="info-list">
+                    <view>被服务人员:{{ detaile.name }}</view>
+                    <view @click="onPhone">电话号码:<label class="phone">{{ detaile.telephone }}</label></view>
+                    <view>地址:{{ detaile.address }}</view>
+                    <view>备注信息:{{ detaile.remark }}</view>
+
+                </view>
+            </view>
+        </view>
+
+        <view class=" footer-g">
+            <Slide ref="verify" @change='change' :sliderText="slideData" />
+        </view>
+    </view>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import { getVolunteerOrderInfo } from '@/api/volunteer.js'
+import { getAddress } from '@/api/address.js'
+import PositioningMap from '@/components//PositioningMap/index.vue'
+import Slide from '@/components/Slide/index.vue'
+
+import { wxMakePhoneCall } from '@/utils/wxRequest.js'
+import { computed } from 'vue';
+
+const fileList = ref([]);
+const orderId = ref('');
+const detaile = ref({});
+const verify = ref(null);
+
+const orderStatus = ref(false);//false:未开始服务 true:服务已开始,待上传图片
+const onPhone = (phone) => {
+    wxMakePhoneCall(phone)
+}
+
+const slideData = computed(() => {
+    //服务已开始,待上传图片
+    if (orderStatus.value) {
+        return { successText: '服务已完成', startText: '拖动滑块结束服务', successColor: '#f64a1f', btnText: '结束' }
+    }
+    return { successText: '服务已开始', startText: '拖动滑块开始服务', successColor: '#72c13f', btnText: '开始' }
+})
+
+const getOrderDetail = async () => {
+    try {
+        uni.showLoading({
+            title: '数据加载中...'
+        });
+        const res = await getVolunteerOrderInfo({ orderId: orderId.value });
+        const ad_res = await getAddress(res.data.addressId);
+        detaile.value = {
+            ...res.data,
+            address: ad_res.data.address,
+            name: ad_res.data.name,
+            telephone: ad_res.data.telephone
+        };
+    } catch (error) {
+        console.log('error', error);
+        uni.showToast({
+            title: error.msg,
+            icon: 'error',
+        })
+    } finally {
+        uni.hideLoading();
+    }
+}
+
+const change = (e) => {
+    console.log('验证信息:', e)
+    console.log('验证是否成功:' + e.state)
+    console.log('验证次数:' + e.verification)
+    if (e.state && !orderStatus.value) {
+        setTimeout(() => {
+            verify.value.initialization();
+            // 验证成功
+            orderStatus.value = true;
+        }, 1000)
+    }
+    if (e.state && orderStatus.value) {
+        console.log('完成任务')
+        uni.redirectTo({ url: `/pages/order/order?orderId=${orderId.value}` });
+    }
+}
+const onSubmit = () => {
+    console.log('submit', fileList.value);
+
+}
+
+onLoad((options) => {
+    console.log('options', options);
+    orderId.value = options.orderId;
+    getOrderDetail();
+
+})
+</script>
+<style lang="scss" scoped>
+.order-detail {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding: 12px 12px 24px;
+    background: rgba(245, 245, 245, 1);
+
+
+    .order-card {
+        border-radius: 8px;
+        background: rgba(255, 255, 255, 1);
+        padding: 12px;
+        margin-bottom: 12px;
+    }
+
+    .font-title {
+        margin-bottom: 12px;
+    }
+
+    .user-box {
+        display: flex;
+
+        .user-img {
+            width: 65.8px;
+            height: 65.8px;
+            margin-right: 12px;
+        }
+
+    }
+
+    .register-box {
+        display: flex;
+        margin-bottom: 12px;
+
+        .register-img {
+            width: 90px;
+            height: 90px;
+            margin-right: 12px;
+        }
+
+    }
+
+    .info-list {
+        flex: 1;
+        font-size: 14px;
+        font-weight: 500;
+        letter-spacing: 0px;
+        line-height: 23.27px;
+        color: rgba(51, 51, 51, 1);
+    }
+
+    .price {
+        font-size: 18px;
+        font-weight: 500;
+        color: rgba(246, 74, 31, 1);
+
+        .price-yuan {
+            font-size: 13px;
+            font-weight: 700;
+            color: rgba(246, 74, 31, 1);
+        }
+    }
+
+    .footer-g {
+        padding: 12px;
+        position: absolute;
+        bottom: 18px;
+        left: 0px;
+        right: 0px;
+        background: rgba(255, 255, 255, 1);
+
+    }
+
+    .upload-img {
+        height: 68px;
+        width: 68px;
+        margin-right: 12px;
+        margin-bottom: 12px;
+    }
+
+    .upload-box {
+        display: flex;
+        flex-wrap: wrap;
+
+        .upload-img-item {
+            position: relative;
+
+            .delete-icon {
+                position: absolute;
+                top: -7px;
+                right: 7px;
+                z-index: 1;
+            }
+        }
+    }
+
+    .phone {
+        color: #3c9cff;
+    }
+}
+</style>

+ 4 - 5
pages/order/list/listItem.vue

@@ -20,8 +20,8 @@
                 <view class="item-btns">
                     <up-button type="error" text="查看" size="mini" :custom-style="btn_style"
                         @click="onClick(1)"></up-button>
-                    <!-- <up-button type="error" text="沟通" size="mini" :custom-style="btn_style" @click="onClick(2)"></up-button>
-                        <up-button type="error" text="上传照片" size="mini" :custom-style="btn_style" @click="onClick(3)"></up-button> -->
+                   <up-button type="error" text="沟通" size="mini" :custom-style="btn_style" @click="onClick(2)"></up-button>
+                         <!-- <up-button type="error" text="上传照片" size="mini" :custom-style="btn_style" @click="onClick(3)"></up-button> -->
                 </view>
             </view>
         </view>
@@ -53,10 +53,9 @@ const btn_style = ` width: 120rpx; height: 50rpx; font-size: 24rpx;border-radius
 /**
  * 1: 查看
  * 2:沟通
- * 3:上传照片
  */
-function onClick() {
-    inject_click(props.data, 1);
+function onClick(type) {
+    inject_click(props.data, type);
 }
 </script>
 

+ 1 - 1
pages/order/order.vue

@@ -6,7 +6,7 @@
 			<view class="user-box">
 				<view class="info-list">
 					<view>被服务人员:{{ detaile.name }}</view>
-					<view @click="onPhone" class="phone">电话号码:{{ detaile.telephone }}</view>
+					<view @click="onPhone">电话号码:<label class="phone">{{ detaile.telephone }}</label></view>
 					<view>地址:{{ detaile.address }}</view>
 				</view>
 			</view>

二进制
static/img/go-right.png


二进制
static/img/success.png


文件差异内容过多而无法显示
+ 1122 - 0
static/sdk/qqmap-wx-jssdk.js


文件差异内容过多而无法显示
+ 1 - 0
static/sdk/qqmap-wx-jssdk.min.js