Przeglądaj źródła

服务查询详情完成

xiaohaizhao 2 miesięcy temu
rodzic
commit
ec0e63ad10

+ 3 - 1
pages.json

@@ -26,6 +26,8 @@
 			"style": {
 				"navigationBarTitleText": "服务详情"
 			}
+		},{
+			"path": "pages/serviceSeeking/work"
 		},
 		{
 			"path": "pages/bookingService/index",
@@ -42,7 +44,7 @@
 		{
 			"path": "pages/select/myProduct",
 			"style": {
-				"navigationBarTitleText": "选择产品"
+				"navigationBarTitleText": "我的资产"
 			}
 		}
 	],

+ 0 - 340
pages/select/accessories.vue

@@ -1,340 +0,0 @@
-<template>
-    <block v-if="!isBom">
-        <view class="search-box">
-            <up-search placeholder="搜索关键词" v-model="keyword" height="35" @blur="onSearch" :clearabled="false"
-                :showAction="false" />
-            <view v-if="content.where.condition" class="clear" @click.stop="onSearch('')">
-                <up-icon name="close-circle-fill" size="20" />
-            </view>
-        </view>
-        <view style="height: 20rpx;" />
-    </block>
-
-    <My_listbox v-if="!isBom" ref="listBox" :empty="!list.length" :pullDown="!isBom" @getlist="getList">
-        <showList :result="resultIds" :list='list' @onClick="onSelect" />
-        <view style="height: 200rpx;" />
-    </My_listbox>
-
-    <view v-else-if="bomList.length" class="bom">
-        <view class="left">
-            <view class="class1" :class="active.class1 == index ? 'class1active' : ''" @click="changeClass1(index)"
-                v-for="(item, index) in bomList" :key="item.plm_bomid" hover-class="navigator-hover">
-                {{ item.bomname }}
-            </view>
-        </view>
-
-        <view class="right">
-            <My_listbox ref="listBox" :pullDown="false">
-                <up-collapse :value="collapse1" @change="changeCollapse1($event)">
-                    <up-collapse-item :ref="el => {
-                        if (el) {
-                            collapseRefs['collapse' + item.plm_bomid] = el
-                        }
-                    }" :cellCustomStyle="{
-                        backgroundColor: '#fff',
-                    }" v-for="item in bomList[active.class1].subdep" :key="item.plm_bomid" :title="item.bomname"
-                        :name="item.plm_bomid">
-                        <up-collapse @change="changeCollapse($event, item.plm_bomid)" v-if="item.subdep.length"
-                            :name="item.plm_bomid">
-                            <up-collapse-item :cellCustomStyle="{
-                                backgroundColor: '#fff',
-                            }" :ref="el => {
-                                if (el) {
-                                    collapseRefs['collapse' + item.plm_bomid] = el
-                                }
-                            }" v-for="item1 in item.subdep" :key="item1.plm_bomid" :title="item1.bomname"
-                                :name="item1.plm_bomid">
-                                <showList v-if="item1.items.length" size="small" :result="resultIds" :list='item1.items'
-                                    @onClick="onSelect" />
-                            </up-collapse-item>
-                        </up-collapse>
-
-                        <showList v-if="item.items.length" size="small" :result="resultIds" :list='item.items'
-                            @onClick="onSelect" />
-                    </up-collapse-item>
-                </up-collapse>
-                <view style="height: 200rpx;" />
-            </My_listbox>
-        </view>
-    </view>
-
-    <My_listbox v-else ref="listBox" :empty="true" @getlist="getBomList" />
-    <view class="footer">
-        <My-button :text="`确定添加(${resultIds.length})`" @onClick="onAdd" />
-    </view>
-</template>
-
-<script setup>
-import { ref, reactive, getCurrentInstance, nextTick } from 'vue';
-import { onLoad } from '@dcloudio/uni-app';
-import showList from "./accessoriesList.vue"
-const { $Http } = getCurrentInstance().proxy;
-
-const listBox = ref(null);
-const isBom = ref(false);
-let result = reactive([]);
-const resultIds = ref([]);
-
-const content = reactive({
-    loading: false,
-    "pageNumber": 1,
-    "pageSize": 20,
-    "where": {
-        "condition": ""
-    }
-})
-
-function onAdd() {
-    $Http.selectAcc(result)
-}
-
-function onSelect(e) {
-    if (result.some(item => item.itemid == e.itemid)) {
-        result = result.filter(item => item.itemid != e.itemid);
-    } else {
-        result.push(e);
-    }
-    resultIds.value = result.map(item => item.itemid);
-}
-
-const list = ref([]);
-
-onLoad((options) => {
-    console.log("options", options)
-    console.log("$Http", $Http)
-
-    result = result.concat(JSON.parse(options.list || '[]'));
-    resultIds.value = result.map(item => item.itemid);
-    console.log("初始选中", result, resultIds.value)
-    let content1 = $Http.content1;
-    content.sys_enterpriseid = content1.sys_enterpriseid;
-    content.sa_workorderid = content1.sa_workorderid;
-
-    if (content1.sku) $Http.basic({
-        "id": 2025080610424703,
-        "content": content1
-    }).then(res => {
-        console.log("查询产品是否存在BOM", res)
-        if (res.data == 0) {
-            // 不存在BOM
-            getList(true);
-        } else {
-            // 存在BOM
-            isBom.value = true;
-            getBomList();
-        }
-    })
-})
-
-const bomList = ref([]);
-
-let active = reactive({
-    class1: 0
-});
-
-function changeClass1(index) {
-    active.class1 = index;
-}
-
-// 折叠面板
-const collapseRefs = ref({})
-const collapse1 = ref([])
-
-function changeCollapse1(e) {
-    collapse1.value = e.filter(v => v.status == 'open').map(v => v.name)
-}
-
-function changeCollapse(e, id) {
-    nextTick(() => {
-        collapseRefs.value['collapse' + id].init()
-    });
-    setTimeout(() => {
-        nextTick(() => {
-            collapseRefs.value['collapse' + id].init()
-        });
-    }, 330);
-}
-
-// 有bom
-function getBomList() {
-    $Http.basic({
-        "id": "2025080610425503",
-        content: {
-            "sa_aftersalesbomid": content.sa_workorderid,
-            "sys_enterpriseid": content.sys_enterpriseid,
-        }
-    }).then(res => {
-        console.log("获取bom配件列表", res)
-        listBox.value.refreshToComplete();
-        listBox.value.setHeight();
-        if (res.code == 1) {
-            bomList.value = processBomData(res.data)
-            console.log("bomList", bomList.value);
-        } else {
-            if (res.msg) uni.showToast({
-                title: res.msg,
-                icon: 'none'
-            });
-        }
-    })
-}
-
-function processBomData(originalData) {
-    // 1. 提取所有一级分类节点
-    const topLevelNodes = [];
-
-    // 遍历原始数据
-    originalData.forEach(dataSet => {
-        dataSet.bom?.forEach(rootNode => {
-            // 提取根节点下的一级分类
-            if (rootNode.subdep && rootNode.subdep.length > 0) {
-                topLevelNodes.push(...rootNode.subdep);
-            }
-        });
-    });
-
-    // 2. 递归处理节点
-    const processNode = (node) => {
-        node.items = node.items || [];
-        node.subdep = node.subdep || [];
-        // 如果当前节点没有items和subdep,直接返回null
-        if (node.items.length === 0 && node.subdep.length === 0) return null;
-
-        try {
-            if (node.items.length) node.items = node.items.map(item => {
-                item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
-                return item;
-            });
-        } catch (error) {
-
-        }
-        // 创建新节点副本
-        const newNode = { ...node };
-        // 处理子节点
-        if (node.subdep.length) newNode.subdep = node.subdep.map(subNode => processNode(subNode)).filter(subNode => subNode !== null);
-        return newNode;
-    };
-
-    // 3. 处理所有一级分类节点
-    return topLevelNodes.map(node => processNode(node)).filter(node => node && (node.subdep.length || node.items.length));
-}
-
-
-// 无BOM
-
-const keyword = ref('');
-
-function onSearch(e) {
-    if (content.where.condition == e) return;
-    content.where.condition = e;
-    keyword.value = e;
-    getList(true);
-}
-
-function getList(init = false) {
-    if (isBom.value) return;
-    if (content.loading) return;
-    if (init) content.pageNumber = 1;
-    content.loading = true;
-    $Http.basic({
-        "id": "2025080610425103",
-        content
-    }).then(res => {
-        console.log("获取配件列表", res)
-        content.loading = false;
-        listBox.value.refreshToComplete();
-        listBox.value.setHeight();
-        res.data = res.data.map(item => {
-            item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
-            return item;
-        });
-        if (res.code == 1) {
-            list.value = reactive(res.firstPage ? res.data : list.value.concat(res.data));
-            content.pageTotal = res.pageTotal;
-            content.pageNumber = res.pageNumber;
-        } else {
-            if (res.msg) uni.showToast({
-                title: res.msg,
-                icon: 'none'
-            });
-        }
-    })
-}
-</script>
-
-<style lang="scss" scoped>
-.bom {
-    width: 100vw;
-    display: flex;
-    min-height: 100vh;
-
-    .left {
-        width: 250rpx;
-        background: #fff;
-        flex-shrink: 0;
-
-        .class1 {
-            padding: 30rpx 30rpx;
-            width: 250rpx;
-            box-sizing: border-box;
-            background: #FFFFFF;
-            border-radius: 0rpx 8rpx 0rpx 0rpx;
-            font-family: PingFang SC, PingFang SC;
-            font-size: 28rpx;
-            color: #999999;
-        }
-
-        .class1active {
-            position: relative;
-            background: #F7F7FF;
-            color: #3774F6;
-        }
-
-        .class1active::after {
-            content: '';
-            position: absolute;
-            left: 0;
-            top: 0;
-            width: 8rpx;
-            height: 100%;
-            background: #3774F6;
-        }
-    }
-
-    .right {
-        flex: 1;
-
-
-    }
-}
-
-.search-box {
-    position: relative;
-    padding: 20rpx;
-    background: #fff;
-
-    .clear {
-        position: absolute;
-        display: flex;
-        align-items: center;
-        right: 0;
-        top: 50%;
-        transform: translateY(-50%);
-        width: 80rpx;
-        padding-left: 10rpx;
-        height: 70rpx;
-        z-index: 2;
-    }
-}
-
-.footer {
-    position: fixed;
-    bottom: 0;
-    left: 0;
-    width: 100%;
-    height: 120rpx;
-    padding: 10rpx 20rpx;
-    background: #fff;
-    box-sizing: border-box;
-}
-</style>

+ 0 - 164
pages/select/accessoriesList.vue

@@ -1,164 +0,0 @@
-<template>
-    <view :class="size">
-        <view v-for="item in list" :key="item.itemid" hover-class="navigator-hover" class="item"
-            :class="result.includes(item.itemid) ? 'radio' : ''" @click="click(item)">
-            <view class="left" @click.stop="previewImge(item.imageUrl)">
-                <up-image :show-loading="true" :src="item.imageUrl" width="100%" height="100%" />
-            </view>
-            <view class="right">
-                <view class="itemname">
-                    {{ item.itemname || '--' }}
-                </view>
-                <view class="row">
-                    型号:{{ item.model || '--' }}
-                </view>
-                <view class="row">
-                    分类:{{ item.bomfullname || '--' }}
-                </view>
-                <view class="row">
-                    售价:<text class="price">{{ $Http.formatNumber(item.price) }}</text>
-                </view>
-            </view>
-        </view>
-    </view>
-</template>
-
-<script setup>
-import { defineProps, defineEmits } from 'vue';
-const emit = defineEmits(['uploadCallback'])
-
-import { getCurrentInstance } from 'vue';
-const { $Http } = getCurrentInstance().proxy;
-
-const props = defineProps({
-    list: {
-        type: Array
-    },
-    result: {
-        type: Array,
-        default: () => []
-    },
-    onClick: {
-        type: Function,
-        default: () => { }
-    },
-    size: {
-        type: String,
-        default: 'large' // small, large
-    }
-});
-
-function click(item) {
-    emit('onClick', item);
-}
-
-function previewImge(url) {
-    if (!url) return;
-    uni.previewImage({
-        urls: [url],
-        current: url
-    });
-}
-</script>
-
-<style lang="scss" scoped>
-.item {
-    display: flex;
-    width: 100%;
-    background: #FFFFFF;
-    border-radius: 20rpx;
-    padding: 16rpx;
-    box-sizing: border-box;
-    margin-top: 16rpx;
-
-    .left {
-        flex-shrink: 0;
-        width: 148rpx;
-        height: 148rpx;
-        background: #FFFFFF;
-        border-radius: 8rpx;
-        border: 2rpx solid #707070;
-        margin-right: 16rpx;
-        overflow: hidden;
-    }
-
-    .right {
-        right: 1;
-
-        .itemname {
-            line-height: 34rpx;
-            font-family: PingFang SC, PingFang SC;
-            font-weight: bold;
-            font-size: 24rpx;
-            color: #333333;
-        }
-
-        .row {
-            line-height: 28rpx;
-            font-family: PingFang SC, PingFang SC;
-            font-size: 20rpx;
-            color: #999999;
-
-            .price {
-                color: #FA5151;
-            }
-        }
-
-    }
-}
-
-.large {
-    width: 690rpx;
-    margin: 0 auto;
-
-    .item {
-        padding: 20rpx;
-        margin-top: 20rpx;
-
-        .left {
-            width: 180rpx;
-            height: 180rpx;
-            background: #FFFFFF;
-            margin-right: 20rpx;
-        }
-
-        .right {
-
-            .itemname {
-                line-height: 38rpx;
-                font-size: 34rpx;
-            }
-
-            .row {
-                font-size: 28rpx;
-                margin-top: 12rpx;
-            }
-
-        }
-    }
-}
-
-.radio {
-    background: #3774F6;
-
-    .right {
-        right: 1;
-
-        .itemname {
-            color: #fff;
-        }
-
-        .row {
-            color: #fff;
-
-            .price {
-                color: #fff;
-            }
-        }
-    }
-}
-
-.item:first-child {
-    margin-top: 0;
-}
-</style>

+ 117 - 253
pages/serviceSeeking/detail.vue

@@ -1,16 +1,16 @@
 <template>
     <view v-if="time">
         <view style="background-color: #fff;padding: 20rpx 0;">
-            <up-steps :current="current" dot activeColor="#0279FE">
+            <up-steps v-if="steps.length" :current="current" dot activeColor="#0279FE">
                 <up-steps-item v-for="item in steps" :key="item.title" :title="item.title" />
             </up-steps>
         </view>
         <view class="main">
             <view class="billno" style="margin-bottom: -24rpx;">
-                工单编号:{{ detail.billno }}
+                预约单号:{{ detail.billno }}
             </view>
             <view class="row">
-                <view class="label col-center">服务类型</view>
+                <view class="label col-center">预约类型</view>
                 <view class="servicetype"
                     :style="{ 'background': { '安装': '#70B603', '维修': '#D9001B', '清洁': '#3874F6', '清洗': '#3874F6' }[detail.servicetype] || '#999999' }">
                     {{ detail.servicetype || '--' }}</view>
@@ -23,51 +23,47 @@
                 <view class="label">故障类型</view>
                 <view class="value">{{ detail.class2 || '--' }}</view>
             </view>
-            <view class="row">
-                <view class="label">服务地址</view>
-                <view class="value">{{ detail.province + detail.city + detail.county + detail.address || '--' }}</view>
-            </view>
-            <view class="row" style="align-items: center;">
-                <view class="label justify">联系人</view>
-                <view class="value phonenumber">{{ detail.scenecontact || '--' }}
-                    <block v-if="detail.scenecontactphonenumber">
-                        <text style="margin: 0 20rpx 0 10rpx;">
-                            {{ detail.scenecontactphonenumber }}
-                        </text>
-                        <My-button :customStyle="{
-                            width: '142rpx',
-                            height: '48rpx',
-                            'background-color': '#FFFFFF',
-                            'color': '#3874F6',
-                            borderRadius: '10rpx'
-                        }" :frontIconStyle="{
-                            marginRight: '6rpx',
-                        }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.scenecontactphonenumber" />
-                    </block>
-                </view>
-            </view>
-            <view class="row">
-                <view class="label">派单日期</view>
-                <view class="value">{{ detail.createdate || '--' }}</view>
-            </view>
-            <view class="row">
-                <view class="label">服务需求</view>
-                <view class="value">{{ detail.remarks || '--' }}</view>
-            </view>
             <up-transition :show="transition">
+                <view class="row">
+                    <view class="label">服务地址</view>
+                    <view class="value">{{ detail.province + detail.city + detail.county + detail.address || '--' }}
+                    </view>
+                </view>
+                <view class="row" style="align-items: center;">
+                    <view class="label justify">联系人</view>
+                    <view class="value phonenumber">{{ detail.scenecontact || '--' }}
+                        <block v-if="detail.scenecontactphonenumber">
+                            <text style="margin: 0 20rpx 0 10rpx;">
+                                {{ detail.scenecontactphonenumber }}
+                            </text>
+                            <My-button :customStyle="{
+                                width: '142rpx',
+                                height: '48rpx',
+                                'background-color': '#FFFFFF',
+                                'color': '#3874F6',
+                                borderRadius: '10rpx'
+                            }" :frontIconStyle="{
+                                marginRight: '6rpx',
+                            }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.scenecontactphonenumber" />
+                        </block>
+                    </view>
+                </view>
+                <view class="row">
+                    <view class="label">服务需求</view>
+                    <view class="value">{{ detail.remarks || '--' }}</view>
+                </view>
                 <view class="transition">
                     <up-divider />
                     <view class="row" v-if="detail.enterprisename">
                         <view class="label justify">销售商</view>
                         <view class="value">{{ detail.enterprisename || '--' }}</view>
                     </view>
-                    <view class="row" v-if="detail.itemsText.length">
+                    <view class="row">
                         <view class="label">产品信息</view>
                         <view class="value">
-                            <view class="col-center" v-for="(item, index) in detail.itemsText" :key="index">
-                                <view class="value"><text v-if="detail.itemsText.length != 1">{{ index + 1 }}. </text>{{
-                                    item }}
-                                </view>
+                            <view class="col-center" style="display: block;">
+                                <view class="value">{{ detail.itemname }}</view>
+                                <view class="value" style="margin-top: 8px;">{{ detail.model }}</view>
                             </view>
                         </view>
                     </view>
@@ -75,13 +71,12 @@
                         <view class="label justify">序列号</view>
                         <view class="value">{{ detail.sku || '--' }}</view>
                     </view>
-                    <view class="row" v-if="detail.customername || detail.customerphonenumber"
-                        style="align-items: center;">
+                    <view class="row" v-if="detail.name || detail.phonenumber" style="align-items: center;">
                         <view class="label justify">客户信息</view>
-                        <view class="value phonenumber">{{ detail.customername || '' }}
-                            <block v-if="detail.customerphonenumber">
+                        <view class="value phonenumber">{{ detail.name || '' }}
+                            <block v-if="detail.phonenumber">
                                 <text style="margin: 0 20rpx 0 10rpx;">
-                                    {{ detail.customerphonenumber }}
+                                    {{ detail.phonenumber }}
                                 </text>
                                 <My-button :customStyle="{
                                     width: '142rpx',
@@ -89,7 +84,7 @@
                                     'background-color': '#FFFFFF',
                                     'color': '#3874F6',
                                     borderRadius: '10rpx'
-                                }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.customerphonenumber" />
+                                }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.phonenumber" />
                             </block>
                         </view>
                     </view>
@@ -108,61 +103,51 @@
                     </view>
                 </view>
             </up-transition>
-            <block v-if="detail.status == '进行中'">
-                <view style="height: 40rpx;" />
-                <view class="changeTransition" hover-class="navigator-hover" @click="transition = !transition">
-                    详细信息
-                    <view class="iconfont icon-dianjizhankai" :class="transition ? 'shrink' : ''" />
+            <block v-if="detail.serviceenterprisename">
+                <up-divider />
+                <view class="row">
+                    <view class="label">服务地址</view>
+                    <view class="value">{{ detail.serviceenterprisename || '--' }}
+                    </view>
                 </view>
-            </block>
-            <!-- 底部按钮 -->
-            <view v-if="detail.status == '待接单'" class="but-box">
-                <view class="but-box-item" v-if="detail.customerphonenumber">
-                    <My-button :customStyle="{
-                        'background-color': '#FFFFFF',
-                        'color': '#3874F6',
-                    }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.customerphonenumber" />
+                <view class="row" style="align-items: center;">
+                    <view class="label justify">联系人</view>
+                    <view class="value phonenumber">
+                        <block v-if="detail.scenecontactphonenumber">
+                            <text style="margin: 0 20rpx 0 10rpx;">
+                                {{ detail.servicephonenumber }}
+                            </text>
+                            <My-button :customStyle="{
+                                width: '142rpx',
+                                height: '48rpx',
+                                'background-color': '#FFFFFF',
+                                'color': '#3874F6',
+                                borderRadius: '10rpx'
+                            }" :frontIconStyle="{
+                                marginRight: '6rpx',
+                            }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="detail.servicephonenumber" />
+                        </block>
+                    </view>
                 </view>
-                <view class="but-box-item" @click="takeOrderShow = true">
-                    <My-button frontIcon="icon-jiedan" text="接单" />
-                    <up-modal negativeTop="100" :show="takeOrderShow" title="是否确认接单?" showCancelButton
-                        @confirm="takeOrders" @cancel="takeOrderShow = false" ref="uModal"
-                        :asyncClose="true"></up-modal>
+            </block>
+            <view class="row" v-if="detail.refusereason">
+                <view class="label">受理说明</view>
+                <view class="value">{{ detail.refusereason || '--' }}
                 </view>
             </view>
-            <!-- 底部按钮 -->
-            <view v-else-if="detail.status == '待开始'" class="but-box">
-                <view class="but-box-item" @click="toChangeMsg">
-                    <My-button :customStyle="{
-                        'background-color': '#FFFFFF',
-                        'color': '#3874F6',
-                    }" text="信息修改" />
-                </view>
-                <view class="but-box-item" @click="!detail.sku ? toCMTips() : confirmStartShow = true">
-                    <My-button text="确认开始" />
-                    <up-modal negativeTop="100" :show="confirmStartShow" showCancelButton @confirm="confirmStart"
-                        @cancel="confirmStartShow = false" ref="uModal" :asyncClose="true">
-                        <view class="slot-content">
-                            <view>
-                                请仔细核对服务信息和客户信息
-                            </view>
-                            <view style="margin-top: 20rpx;">
-                                开始工单后确认信息将不可修改!
-                            </view>
-                        </view>
-                    </up-modal>
-                </view>
+            <view style="height: 40rpx;" />
+            <view class="changeTransition" hover-class="navigator-hover" @click="transition = !transition">
+                详细信息
+                <view class="iconfont icon-dianjizhankai" :class="transition ? 'shrink' : ''" />
             </view>
         </view>
+    </view>
 
-        <view class="main" v-if="current >= 2 && detail.nodes.length" style="padding: 30rpx;">
+    <up-transition :show="detail.nodes.length != 0">
+        <view class="main" style="padding: 30rpx;">
             <nodes ref="Nodes" :nodes="detail.nodes" />
-            <view v-if="detail.status == '进行中'" style='width: 60%;margin: 40rpx auto 0;padding-bottom: 30rpx;'
-                @click="submit"><My-button text="完工提交" />
-            </view>
         </view>
-
-    </view>
+    </up-transition>
 
     <view style="height: 50px;" />
 </template>
@@ -177,187 +162,66 @@ const transition = ref(true);
 const Nodes = ref(null);
 
 const current = ref(-1);
-const steps = reactive([
-    { title: '接单', value: '待接单' },
-    { title: '开始', value: '待开始' },
-    { title: '进行中', value: '进行中' },
-    { title: '提交', value: '提交' },
-    { title: '完工', value: '已完成' }
-]);
-let sa_workorderid = 0;
-onLoad((options) => {
-    sa_workorderid = options.id;
-});
+const steps = ref([]);
 
-onUnload(() => {
-    delete $Http.content1
+let sa_serviceorderid = 0;
+onLoad((options) => {
+    sa_serviceorderid = options.id;
+    getDetail()
 });
 
 const time = ref(new Date().getTime());
 
-onShow(() => {
-    getDetail()
-})
-
 let detail = reactive({
-    itemsText: [],
-    servicetype: ""
+    servicetype: "",
+    nodes: [],
 });
 
 function getDetail() {
-    $Http.basic({ "id": "20230208140103", "content": { "nocache": true, sa_workorderid } }).then(res => {
-        console.log("工单详情", res)
-        $Http.content1 = {
-            itemid: res.data.itemid,
-            sku: res.data.sku,
-            sys_enterpriseid: res.data.sys_enterpriseid,
-            sa_workorderid: res.data.sa_workorderid,
-        }
+    $Http.basic({ "id": "20230206091603", "content": { "nocache": true, sa_serviceorderid } }).then(res => {
+        console.log("服务申请单详情", res)
         if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
-        try {
-            res.data.itemsText = res.data.titems.map(item => {
-                return `${item.itemname} ${item.model}`;
-            })
-        } catch (error) {
-
-        }
-
-        if (res.data.status == '进行中' && detail.servicetype == '') transition.value = false;
         time.value = new Date().getTime()
-        detail = reactive(res.data);
-        current.value = steps.findIndex(item => item.value === res.data.status);
-    })
-}
-
-// 提交工单
-function submit() {
-    // 收集所有必填末级节点
-    const requiredLeafNodes = [];
-
-    // 递归查找末级节点
-    function findLeafNodes(nodeList) {
-        for (const node of nodeList) {
-            // 检查是否为末级节点(没有子节点)
-            if (!node.child || node.child.length === 0) {
-                // 检查是否是必填节点(required == 11)
-                if (node.workpresetjson?.required == 11 && node.status !== "1") {
-                    requiredLeafNodes.push(node);
-                }
+        res.data.nodes = [];
+        const now = new Date();
+        now.setHours(0, 0, 0, 0); // Ignore time part for comparison
+        res.data.inqualityguaranteeperiod = res.data.cardbegdate && res.data.cardenddate
+            ? (new Date(res.data.cardbegdate) <= now && now <= new Date(res.data.cardenddate) ? 1 : 0)
+            : 0;
+        Object.assign(detail, res.data);
+        if (res.data.status == '拒绝受理') {
+            steps.value = [{ title: '已申请', value: '待分配' },
+            { title: '无需服务', value: '拒绝受理' }]
+            current.value = 1;
+        } else {
+            steps.value = [{ title: '已申请', value: '待分配' },
+            { title: '已分配', value: '待受理' },
+            { title: '已受理', value: '待服务' },
+            { title: '服务中', value: '服务中' },
+            { title: '已完结', value: '已完结' }]
+            if (res.data.status == '新建') {
+                current.value = 0
             } else {
-                // 递归检查子节点
-                findLeafNodes(node.child);
+                current.value = steps.value.findIndex(item => item.value === res.data.status);
             }
-        }
-    }
-    // 开始查找
-    findLeafNodes(detail.nodes);
-    // 检查所有必填末级节点是否已完成
-    const allCompleted = requiredLeafNodes.every(node => node.status === "1");
-    if (allCompleted) {
-        uni.showModal({
-            confirmText: '继续提交',
-            content: '请确认工单内容,提交后不可修改!',
-            success: ({ confirm }) => {
-                if (confirm) {
-                    $Http.basic({
-                        id: 2025072315401603,
-                        "content": {
-                            "sa_workorderid": detail.sa_workorderid
-                        }
-                    }).then(res => {
-                        console.log("提交结果", res)
-                        uni.showToast({
-                            title: res.code == 1 ? '提交成功' : res.msg,
-                            icon: 'none'
-                        });
-                        if (res.code == 1) {
-                            getDetail();
-                            transition.value = true;
-                        }
-                    })
-                }
-            },
-        })
-    } else {
-        uni.showModal({
-            confirmText: '关闭',
-            content: '还有工序未完成,不能提交!',
-            showCancel: false
-        })
-    }
-}
-
-
-// 接单
-const takeOrderShow = ref(false);
-
-function takeOrders() {
-    $Http.basic({
-        id: 20230210101103,
-        "content": {
-            "sa_workorderid": detail.sa_workorderid
-        }
-    }).then(res => {
-        console.log("接单结果", res)
-        if (res.code == 1) {
-            takeOrderShow.value = false;
-            getDetail();
-            uni.showToast({
-                title: '接单成功',
-                icon: 'none'
-            });
-        } else {
-            if (res.msg) uni.showToast({
-                title: res.msg,
-                icon: 'none'
-            });
+            $Http.basic({ "id": 20230207154203, "content": { "sa_serviceorderid": sa_serviceorderid, pageSize: 1 } }).then(res => {
+                console.log("服务申请单工单列表", res)
+                if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
+                if (res.data.length) getWorkorderDetail(res.data[0].sa_workorderid)
+            })
         }
     })
 }
 
-function toCMTips() {
-    uni.showModal({
-        confirmText: '前去修改',
-        content: '请完善产品信息和客户信息,确认开始后将不可修改!',
-        success: ({ confirm }) => {
-            if (confirm) toChangeMsg();
-        },
+function getWorkorderDetail(sa_workorderid) {
+    $Http.basic({ "id": "20230208140103", "content": { "nocache": true, sa_workorderid } }).then(res => {
+        console.log("工单详情", res)
+        if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
+        time.value = new Date().getTime()
+        Object.assign(detail, res.data);
     })
 }
 
-// 修改信息
-function toChangeMsg() {
-    uni.navigateTo({
-        url: `/pages/workOrder/changeMsg?id=` + sa_workorderid
-    });
-};
-
-// 确认开始
-const confirmStartShow = ref(false);
-
-function confirmStart() {
-    $Http.basic({
-        id: 20230209144503,
-        "content": {
-            "sa_workorderid": detail.sa_workorderid
-        }
-    }).then(res => {
-        console.log("确认开始", res)
-        if (res.code == 1) {
-            confirmStartShow.value = false;
-            getDetail();
-            uni.showToast({
-                title: '确认开始成功',
-                icon: 'none'
-            });
-        } else {
-            if (res.msg) uni.showToast({
-                title: res.msg,
-                icon: 'none'
-            });
-        }
-    })
-}
 
 defineExpose({ detail })
 
@@ -409,7 +273,7 @@ defineExpose({ detail })
 
         .label {
             position: relative;
-            width: 108rpx;
+            width: 115rpx;
             color: #999999;
             box-sizing: border-box;
             flex-shrink: 0;

+ 23 - 18
pages/serviceSeeking/index.vue

@@ -10,24 +10,26 @@
     </view>
     <My_listbox ref="listBox" :empty="!list.length" @getlist="getList">
         <view style="height: 18rpx;" />
-        <navigator class="item" v-for="item in list" :key="item.sa_serviceorderid"
-            :url="'/pages/serviceSeeking/detail?id=' + item.sa_serviceorderid" hover-class="navigator-hover">
-            <view class="head">
-                <view class="tag"
-                    :style="{ 'background': { '已完结': '#333', '拒绝受理': '#333' }[item.status] || '#3874F6' }">
-                    {{ item.status }}
+        <view class="item" v-for="item in list" :key="item.sa_serviceorderid" hover-class="navigator-hover">
+            <navigator :url="'/pages/serviceSeeking/detail?id=' + item.sa_serviceorderid" hover-class="none">
+                <view class="head">
+                    <view class="tag"
+                        :style="{ 'background': { '已完结': '#333', '拒绝受理': '#333' }[item.status] || '#3874F6' }">
+                        {{ item.status }}
+                    </view>
+                    <view class="time">
+                        {{ item.createdate }}
+                    </view>
                 </view>
-                <view class="time">
-                    {{ item.createdate }}
+                <view class="address">
+                    {{ item.address }}
                 </view>
-            </view>
-            <view class="address">
-                {{ item.address }}
-            </view>
-            <view class="user">
-                {{ item.serviceenterprisename + ' ' + item.servicephonenumber }}
-            </view>
-            <view class="but-box" @click.stop>
+                <view class="user">
+                    {{ item.serviceenterprisename + ' ' + item.servicephonenumber }}
+                </view>
+            </navigator>
+
+            <view class="but-box" @click="stopPropagation">
                 <view class="but-box-item" v-if="item.servicephonenumber">
                     <My-button :customStyle="{
                         'background-color': '#FFFFFF',
@@ -36,13 +38,13 @@
                     }" frontIcon="icon-bodadianhua1" text="电话" :phonenumber="item.servicephonenumber" />
                 </view>
 
-                <navigator :url="'/pages/workOrder/detail?id=' + item.sa_serviceorderid" class="but-box-item">
+                <navigator :url="'/pages/serviceSeeking/detail?id=' + item.sa_serviceorderid" class="but-box-item">
                     <My-button :customStyle="{
                         height: '70rpx',
                     }" frontIcon="icon-jiedan" text="查询" />
                 </navigator>
             </view>
-        </navigator>
+        </view>
     </My_listbox>
 </template>
 
@@ -112,6 +114,9 @@ function getList(init = false) {
     })
 }
 
+function stopPropagation(event) {
+    event.stopPropagation();
+}
 </script>
 
 <style lang="scss" scoped>

+ 2 - 1
pages/serviceSeeking/modules/nodes.vue

@@ -43,6 +43,7 @@ const props = defineProps({
         type: [String, Number],
     }
 });
+
 function toWork(item) {
     try {
         if (item.child.length) return;
@@ -54,7 +55,7 @@ function toWork(item) {
     $Http.data = item;
 
     uni.navigateTo({
-        url: '/pages/workOrder/work',
+        url: '/pages/serviceSeeking/work',
     })
 }
 

+ 373 - 0
pages/serviceSeeking/work.vue

@@ -0,0 +1,373 @@
+<template>
+    <view class="content">
+        <up-form :model="form" labelWidth="70" ref="uFormRef" disabled>
+            <block v-if="workpresetjson.questionedit != 0">
+                <up-form-item label="故障类型" prop="itemtype" :required="workpresetjson.questionedit == 11">
+                    <view class="options-box">
+                        <view class="option" :class="form.itemtype == item.value ? 'active' : ''"
+                            v-for="item in questionoption" :key="item.value"
+                            @click="clickRadio(item.value, 'itemtype')">
+                            {{ item.value }}
+                        </view>
+                    </view>
+                </up-form-item>
+                <up-form-item label="问题编辑" prop="questionedit" :required="workpresetjson.questionedit == 11">
+                    <up-textarea maxlength="499" :disabled="data.status == 1" v-model="form.questionedit"
+                        placeholder="问题编辑" autoHeight height="20" />
+                </up-form-item>
+            </block>
+
+
+            <up-form-item v-if="workpresetjson.passcheck != 0" label="合格确认" prop="passcheck"
+                :required="workpresetjson.passcheck == 11">
+                <view class="options-box">
+                    <view class="option" :class="form.passcheck == item.value ? 'active' : ''" v-for="item in [
+                        { value: '1', name: '正常' },
+                        { value: '0', name: '异常' }]" :key="item.value" @click="clickRadio(item.value, 'passcheck')">
+                        {{ item.name }}
+                    </view>
+                </view>
+            </up-form-item>
+
+            <view v-if="workpresetjson.additem != 0">
+                <up-form-item label="是否更换配件" prop="additem" :required="workpresetjson.additem == 11">
+                    <view class="options-box">
+                        <view class="option" :class="form.additem == item.value ? 'active' : ''" v-for="item in [
+                            { value: '1', name: '是' },
+                            { value: '0', name: '否' }]" :key="item.value" @click="clickRadio(item.value, 'additem')">
+                            {{ item.name }}
+                        </view>
+                    </view>
+                </up-form-item>
+
+                <block v-if="form.additem == 1">
+                    <up-form-item :label="`新配件(${data.newtitems.length})`" prop="newtitems" required>
+                        <view class="options-box">
+                            <view class="option active" hover-class="navigator-hover" @click="toAddItem('newtitems')">
+                                + 去添加新配件
+                            </view>
+                        </view>
+                    </up-form-item>
+                    <accList :list="data.newtitems" :disabled="data.status == 1"
+                        @deleteItem="deleteItem($event, 'newtitems')" />
+
+                    <up-form-item :label="`旧配件(${data.oldtitems.length})`">
+                        <view class="options-box">
+                            <view class="option active" hover-class="navigator-hover" @click="toAddItem('oldtitems')">
+                                + 去添加旧配件
+                            </view>
+                        </view>
+                    </up-form-item>
+                    <accList :list="data.oldtitems" :disabled="data.status == 1"
+                        @deleteItem="deleteItem($event, 'oldtitems')" />
+                </block>
+            </view>
+
+            <up-form-item v-if="workpresetjson.confirm != 0" label="确认信息" prop="confirm"
+                :required="workpresetjson.confirm == 11">
+                <view class="options-box">
+                    <view class="option" :class="form.confirm == item ? 'active' : ''"
+                        v-for="(item) in workpresetjson.confirm_options" :key="item"
+                        @click="clickRadio(item, 'confirm')">
+                        {{ item }}
+                    </view>
+                </view>
+            </up-form-item>
+
+            <up-form-item v-if="workpresetjson.amountpay != 0" label="费用支付" prop="amountpay"
+                :required="workpresetjson.amountpay == 11">
+                <up-input :disabled="data.status == 1" v-model="form.amountpay" type="number" placeholder="费用支付">
+                    <template #suffix>
+                        元
+                    </template>
+                </up-input>
+            </up-form-item>
+
+            <up-form-item v-if="workpresetjson.fileupload != 0" label="拍照" prop="fileupload"
+                :required="rules.fileupload[0].required">
+
+                <up-image v-if="data.status == 1 && data.attinfos.length == 0" :show-loading="true" src="" width="80px"
+                    height="80px" @click="click"></up-image>
+                <My_upload v-else :disabled="data.status == 1" ref="upload" :fileList="data.attinfos"
+                    @uploadCallback="uploadCallback" />
+            </up-form-item>
+
+            <up-form-item v-if="workpresetjson.textedit != 0" label="文字说明" prop="textedit"
+                :required="rules.textedit[0].required">
+                <up-textarea maxlength="499" :disabled="data.status == 1" v-model="form.textedit" placeholder="文字说明"
+                    autoHeight height="20" />
+            </up-form-item>
+        </up-form>
+        <view style="height: 50px;" />
+        <page-container :show="true" :overlay="false" @beforeleave="beforeleave" />
+    </view>
+</template>
+
+<script setup>
+import { ref, reactive, getCurrentInstance, watch } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import accList from "./modules/products.vue";
+
+const { $Http } = getCurrentInstance().proxy;
+const uFormRef = ref(null);
+const upload = ref(null);
+
+let formModified = ref(false);
+
+function beforeleave(e) {
+    if (formModified.value && data.status != '1') {
+        uni.showModal({
+            title: '提示',
+            content: '是否保存当前编辑内容?',
+            confirmText: '保存',
+            cancelText: '不保存',
+            success: function (res) {
+                if (res.confirm) {
+                    save()
+                    setTimeout(() => {
+                        uni.navigateBack()
+                    }, 500);
+                } else if (res.cancel) {
+                    uni.navigateBack()
+                }
+            }
+        });
+    } else {
+        uni.navigateBack()
+    }
+}
+
+// 去添加配件
+function toAddItem(key = 'oldtitems') {
+    if (data.status == '1') return;
+    $Http.basicsData = {
+        selected: key,
+        newtitems: deepCloneArray(data.newtitems) || [],
+        oldtitems: deepCloneArray(data.oldtitems) || [],
+    }
+    uni.navigateTo({
+        url: '/pages/select/accessories'
+    });
+    $Http.selectAcc = (res) => {
+        data.newtitems = res.newtitems;
+        data.oldtitems = res.oldtitems;
+        form.newtitems = res.newtitems.length ? '1' : '';
+
+        uni.navigateBack();
+        delete $Http.selectAcc
+        delete $Http.basicsData
+    }
+}
+
+// 帮我写一个[{},{}] 深拷贝的方法
+function deepCloneArray(arr) {
+    return arr.map(item => {
+        return { ...item };
+    })
+}
+
+// 删除配件
+function deleteItem(item, key = 'oldtitems') {
+    data[key] = data[key].filter(v => v.itemid !== item.itemid);
+    if (key == 'newtitems') form.newtitems = data.newtitems.length ? '1' : '';
+}
+
+const form = reactive({
+    textedit: '', // 上传文本
+    confirm: "", // 确认信息
+    itemtype: "", // 故障类型
+    questionedit: "", // 问题编辑
+    additem: "", // 是否更换配件
+    passcheck: "", //合格确认 异常时 文字和图片必填
+    amountpay: "", // 费用支付
+    fileupload: "", // 上传图片
+    oldtitems: "",//配件
+    newtitems: "",//配件
+});
+
+let keys = {
+    textedit: 'textcontent', // 文本内容
+    amountpay: 'amount', // 费用支付
+    confirm: 'confirm_value', // 确认信息
+    itemtype: "questionoption",
+    questionedit: "questionedit",
+}
+
+// keys 与 form 互相转换字段
+let formToContent = (form) => {
+    let content = {};
+    for (let key in form) {
+        if (keys[key]) {
+            content[keys[key]] = form[key];
+        } else {
+            content[key] = form[key];
+        }
+    }
+    if (content.amount === '') content.amount = 0;
+    return content;
+}
+
+let data = {
+    attinfos: []
+};
+let workpresetjson = reactive({});
+
+let rules = reactive({
+    textedit: [
+        { required: false, message: '请输入说明', trigger: 'blur' }
+    ],
+    fileupload: [
+        { required: false, message: '请上传图片', trigger: 'change' }
+    ],
+});
+const questionoption = ref([]);
+
+function clickRadio() { }
+
+onLoad(() => {
+    data = reactive($Http.data);
+    data.status = 1;
+    delete $Http.data;
+
+    form.fileupload = data.attinfos.length ? '1' : '';
+    uni.setNavigationBarTitle({
+        title: data.title,
+    })
+    workpresetjson = Object.assign(workpresetjson, data.workpresetjson);
+
+    if (workpresetjson.additem) {
+        data.oldtitems = data.detail[0].oldtitems.map(item => {
+            item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
+            return item;
+        });
+        data.newtitems = data.detail[0].newtitems.map(item => {
+            item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
+            return item;
+        });
+
+        form.newtitems = data.newtitems.length ? '1' : '';
+        form.oldtitems = data.oldtitems.length ? '1' : '';
+        form.additem = form.newtitems || form.oldtitems ? '1' : '0';
+
+    }
+
+    rules = Object.assign(rules, {
+        textedit: [
+            { required: workpresetjson.textedit == 11, message: '请输入说明', trigger: 'blur' },
+            { min: 2, max: 500, message: '长度在 2 到 500 个字符', trigger: 'blur' }
+        ],
+        confirm: [
+            { required: workpresetjson.confirm == 11, message: '请选择确认信息', trigger: 'change' }
+        ],
+        itemtype: [
+            { required: workpresetjson.questionedit == 11, message: '请选择故障类型', trigger: 'change' }
+        ],
+        questionedit: [
+            { required: workpresetjson.questionedit == 11, message: '请输入问题编辑', trigger: 'blur' },
+            { min: 2, max: 500, message: '长度在 2 到 500 个字符', trigger: 'blur' }
+        ],
+        additem: [
+            { required: workpresetjson.additem == 11, message: '请选择是否更换配件', trigger: 'change' }
+        ],
+        passcheck: [
+            { required: workpresetjson.passcheck == 11, message: '请选择合格确认', trigger: 'change' }
+        ],
+        amountpay: [
+            { required: workpresetjson.amountpay == 11, message: '请输入费用支付', trigger: 'blur', validator: (rule, value) => value !== '' },
+            { pattern: /^(0|[1-9]\d*)(\.\d{1,2})?$/, message: '请输入正确的金额', trigger: 'blur' }
+        ],
+        fileupload: [
+            { required: workpresetjson.fileupload == 11, message: '请上传图片', trigger: 'change' }
+        ],
+        additem: [{ required: workpresetjson.additem == 11, message: '请选择是否更换配件', trigger: 'change' }]
+
+    })
+
+    setTimeout(() => {
+        if (data.passcheck == '0') {
+            rules.textedit[0].required = true;
+            rules.fileupload[0].required = true;
+        }
+        uFormRef.value.setRules(rules);
+    });
+
+    if (workpresetjson.questionedit) $Http.getClass(workpresetjson.questionoption).then(res => {
+        questionoption.value = res.data;
+        if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
+    })
+
+    for (let key in keys) {
+        if (data[keys[key]]) {
+            form[key] = data[keys[key]];
+            console.log(key, form[key])
+        }
+    }
+});
+
+
+
+</script>
+
+<style lang="scss" scoped>
+.content {
+    width: 100vw;
+    padding: 20px;
+    box-sizing: border-box;
+    min-height: 100vh;
+    background: #fff;
+
+
+    .picker {
+        width: 100%;
+        // border-bottom: 1px solid #dadbde;
+        font-size: 32rpx;
+        color: #606266;
+        padding: 9px;
+        border-radius: 8rpx;
+    }
+
+    .title {
+        font-size: 34rpx;
+        color: #4773EE;
+        margin: 20rpx 0;
+        font-weight: bold;
+    }
+
+    .options-box {
+        position: relative;
+        top: -6rpx;
+        display: flex;
+        flex-wrap: wrap;
+        width: 100%;
+        box-sizing: border-box;
+
+        .option {
+            border: 1px solid #dadbde;
+            border-radius: 8rpx;
+            padding: 10rpx 20rpx;
+            margin-right: 18rpx;
+            margin-top: 12rpx;
+            transition: background-color 0.3s, color 0.3s, border-color 0.3s;
+            text-align: center;
+            min-width: 80rpx;
+        }
+
+        .active {
+            background: #006EF7;
+            color: #fff;
+            border-color: #006EF7;
+        }
+    }
+
+    .but-box {
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        margin-top: 40rpx;
+
+        .but-box-item {
+            width: 45%;
+        }
+    }
+}
+</style>