From 229c56de6a1816120bdc17ca94545301cb6103a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?TOP=E7=B3=AF=E7=B1=B3?= <1130395124@qq.com>
Date: Sun, 12 Feb 2023 23:14:02 +0800
Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=A1=AE=E8=AE=A4=E8=AE=A2?=
 =?UTF-8?q?=E5=8D=95=E9=A1=B5=E9=9D=A2=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=B0=8F?=
 =?UTF-8?q?=E7=BB=84=E4=BB=B6=E7=9B=AE=E5=BD=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/components/auth/agreement.vue             |  67 ++++
 src/components/banner/banner.vue              |   8 +-
 src/components/cate/cate.vue                  |  17 +-
 src/components/cate/template/cate.vue         |   7 +-
 src/components/cate/template/list.vue         |  59 +---
 src/components/layout/layout.vue              |  21 +-
 src/components/service/preview-item.vue       |  79 +++++
 src/components/widgets/checkbox.vue           |  57 +++
 .../add.vue => widgets/count-modify.vue}      |  24 +-
 src/components/widgets/switch.vue             |  54 +++
 src/core/libs/utils.js                        |   6 +-
 src/pages/auth/auth.vue                       |   8 +-
 src/pages/index/index.vue                     |   2 +-
 src/pages/member/address.vue                  |   8 +-
 src/pages/member/member.vue                   |   6 +-
 src/pages/order/cart.vue                      |  26 ++
 src/pages/order/create.vue                    | 333 +++++++++++++++++-
 src/pages/service/cate.vue                    |  12 +-
 src/pages/service/detail.vue                  |  10 +-
 src/pages/service/list.vue                    |  20 +-
 20 files changed, 717 insertions(+), 107 deletions(-)
 create mode 100644 src/components/auth/agreement.vue
 create mode 100644 src/components/service/preview-item.vue
 create mode 100644 src/components/widgets/checkbox.vue
 rename src/components/{mini/add.vue => widgets/count-modify.vue} (76%)
 create mode 100644 src/components/widgets/switch.vue
 create mode 100644 src/pages/order/cart.vue

diff --git a/src/components/auth/agreement.vue b/src/components/auth/agreement.vue
new file mode 100644
index 0000000..df82c8a
--- /dev/null
+++ b/src/components/auth/agreement.vue
@@ -0,0 +1,67 @@
+<template>
+    <view class="agreement">
+        <widget-check-box :checked="defaultState" @change="change" />
+        <view class="description">
+            <text class="text">我已阅读并同意</text>
+            <text class="link">《熊熊安装服务协议》</text>
+            <text class="link">《隐私政策》</text>
+        </view>
+    </view>
+</template>
+
+<script>
+import WidgetCheckBox from "@/components/widgets/checkbox";
+export default {
+    name: "auth-agreement",
+    data() {
+        return {};
+    },
+    props: {
+        defaultState: {
+            type: Boolean,
+            default: false,
+        },
+    },
+    components: {
+        WidgetCheckBox,
+    },
+    created() {},
+    mounted() {},
+    destroyed() {},
+    methods: {
+        change(state) {
+            this.$emit("agree", state);
+        },
+    },
+};
+</script>
+
+<style lang="less" scoped>
+.agreement {
+    width: 100%;
+    display: flex;
+    align-items: flex-start;
+    line-height: 40rpx;
+    .icon-box {
+        .iconfont {
+            color: #c7c7c7;
+            font-size: 40rpx;
+        }
+    }
+    .icon-box.active {
+        .iconfont {
+            color: #8194f2;
+        }
+    }
+    .description {
+        font-size: 22rpx;
+        margin-left: 10rpx;
+        .text {
+            color: #333333;
+        }
+        .link {
+            color: #8194f2;
+        }
+    }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/banner/banner.vue b/src/components/banner/banner.vue
index 8f06f41..19ce165 100644
--- a/src/components/banner/banner.vue
+++ b/src/components/banner/banner.vue
@@ -11,7 +11,11 @@
         >
             <swiper-item v-for="(item, index) in list" :key="index">
                 <view class="swiper-item" @click="clickItem(item)">
-                    <image class="banner-image" :src="item.image" mode="scaleToFill" />
+                    <image
+                        class="banner-image"
+                        :src="item.image"
+                        mode="scaleToFill"
+                    />
                 </view>
             </swiper-item>
         </swiper>
@@ -20,7 +24,7 @@
                 class="swiper-dot-item"
                 v-for="(value, key) in list.length"
                 :key="key"
-                :class="{'active': key === currentIndex}"
+                :class="{ active: key === currentIndex }"
             ></view>
         </view>
     </view>
diff --git a/src/components/cate/cate.vue b/src/components/cate/cate.vue
index 0d6bf33..b0ffbb8 100644
--- a/src/components/cate/cate.vue
+++ b/src/components/cate/cate.vue
@@ -39,16 +39,14 @@
                         :style="{
                             height:
                                 index == data.length - 1
-                                    ? cateType == 'cate'
-                                        ? 'calc(100vh - 70rpx)'
-                                        : '100vh'
+                                    ? wrapHeight + $utils.rpx2px(110) + 'px'
                                     : 'auto',
                         }"
                     >
                         <cate-tmpl
                             v-if="cateType === 'cate'"
                             :data="item"
-                            @clickCate="clickCate"
+                            @clickItem="clickItem"
                         ></cate-tmpl>
                         <list-tmpl
                             v-if="cateType === 'list'"
@@ -124,6 +122,7 @@ export default {
         // H5窗口高度会计算tabbar高度,这里减去
         this.wrapHeight -= this.$utils.rpx2px(100);
         // #endif
+        // this.switchCate(5);
     },
     destroyed() {},
     methods: {
@@ -255,8 +254,14 @@ export default {
                 }
             }
         },
-        clickCate(id) {
-            this.$emit("clickCate", id);
+        switchCate(id) {
+            let idx = 0;
+            this.data.forEach((item, index) => {
+                if (item.id == id) {
+                    idx = index;
+                }
+            });
+            this.swichMenu(idx);
         },
         clickItem(id) {
             this.$emit("clickItem", id);
diff --git a/src/components/cate/template/cate.vue b/src/components/cate/template/cate.vue
index e626976..de0f95b 100644
--- a/src/components/cate/template/cate.vue
+++ b/src/components/cate/template/cate.vue
@@ -8,7 +8,7 @@
                 class="thumb-box"
                 v-for="(child, index1) in data.child"
                 :key="index1"
-                @click="clickItem(child.id, child.name)"
+                @click="clickItem(child.id)"
             >
                 <image
                     class="item-menu-image"
@@ -38,8 +38,8 @@ export default {
     mounted() {},
     destroyed() {},
     methods: {
-        clickItem(id, name) {
-            this.$emit("clickCate", id);
+        clickItem(id) {
+            this.$emit("clickItem", id);
         },
     },
 };
@@ -48,6 +48,7 @@ export default {
 <style lang="less" scoped>
 .item-title {
     font-size: 26rpx;
+    line-height: 26rpx;
     color: #010101;
     font-weight: bold;
 }
diff --git a/src/components/cate/template/list.vue b/src/components/cate/template/list.vue
index 02fe7b0..60f5ee5 100644
--- a/src/components/cate/template/list.vue
+++ b/src/components/cate/template/list.vue
@@ -9,27 +9,16 @@
                 v-for="(child, index1) in data.child"
                 :key="index1"
             >
-                <image
-                    class="cover-image"
-                    mode="aspectFill"
-                    :src="child.icon"
-                    @click="clickItem(child.id, child.name)"
-                ></image>
-                <view class="item-box" @click="clickItem(child.id, child.name)">
-                    <view class="title">{{ child.name }}</view>
-                    <view class="text-box">
-                        {{ "已服务113256次" }}
-                    </view>
-                    <view class="price">¥158元起</view>
-                </view>
-                <mini-add class="component-add" :initNumber="child.buyNumber" />
+                <service-preview-item :data="child" @clickItem="clickItem" />
+                <widget-count-modify class="component-add" :initNumber="child.buyNumber" />
             </view>
         </view>
     </view>
 </template>
 
 <script>
-import MiniAdd from "@/components/mini/add";
+import WidgetCountModify from "@/components/widgets/count-modify";
+import ServicePreviewItem from "@/components/service/preview-item";
 export default {
     name: "component-cate-template-list",
     data() {
@@ -41,12 +30,15 @@ export default {
             default: [],
         },
     },
-    components: { MiniAdd },
+    components: {
+        WidgetCountModify,
+        ServicePreviewItem,
+    },
     created() {},
     mounted() {},
     destroyed() {},
     methods: {
-        clickItem(id, name) {
+        clickItem(id) {
             this.$emit("clickItem", id);
         },
     },
@@ -56,6 +48,7 @@ export default {
 <style lang="less" scoped>
 .item-title {
     font-size: 26rpx;
+    line-height: 26rpx;
     color: #8b8b8b;
     font-weight: bold;
 }
@@ -66,10 +59,8 @@ export default {
 .thumb-box {
     position: relative;
     width: 100%;
-    display: flex;
-    justify-content: space-between;
     margin-top: 40rpx;
-    
+
     .component-add {
         position: absolute;
         right: 0;
@@ -79,32 +70,4 @@ export default {
 .thumb-box:nth-child(3n) {
     margin-right: 0;
 }
-.cover-image {
-    width: 130rpx;
-    height: 130rpx;
-    box-sizing: border-box;
-    border-radius: 20rpx;
-    border: 2rpx solid #d8d8d8;
-}
-.item-box {
-    width: 300rpx;
-    display: flex;
-    justify-content: space-between;
-    flex-direction: column;
-    padding-left: 50rpx;
-    .title {
-        font-size: 26rpx;
-        font-weight: bold;
-        color: #010101;
-    }
-    .text-box {
-        display: inline-block;
-        font-size: 22rpx;
-        color: #333333;
-    }
-    .price {
-        font-size: 30rpx;
-        color: #ec7655;
-    }
-}
 </style>
\ No newline at end of file
diff --git a/src/components/layout/layout.vue b/src/components/layout/layout.vue
index d7e847b..885f61b 100644
--- a/src/components/layout/layout.vue
+++ b/src/components/layout/layout.vue
@@ -1,12 +1,15 @@
 <template>
-    <view class="page-layout" :style="{ backgroundColor: pageBackgroundColor }">
+    <view
+        class="page-layout"
+        :style="{ backgroundColor: backgroundColor, minHeight: minHeight }"
+    >
         <view
             class="page-header"
             :class="[textColor]"
             :style="{
                 height: header.height + 'px',
                 paddingTop: header.pt + 'px',
-                backgroundColor: backgroundColor,
+                backgroundColor: headerBackgroundColor,
             }"
         >
             <!-- 首页选择地址 -->
@@ -60,7 +63,15 @@ export default {
     },
     components: {},
     props: {
-        pageBackgroundColor: {
+        minHeight: {
+            type: String,
+            default: "100vh",
+        },
+        backgroundColor: {
+            type: String,
+            default: "unset",
+        },
+        headerBackgroundColor: {
             type: String,
             default: "unset",
         },
@@ -80,10 +91,6 @@ export default {
             type: String,
             default: "dark",
         },
-        backgroundColor: {
-            type: String,
-            default: "unset",
-        },
     },
     computed: {
         ...mapState({
diff --git a/src/components/service/preview-item.vue b/src/components/service/preview-item.vue
new file mode 100644
index 0000000..fe11222
--- /dev/null
+++ b/src/components/service/preview-item.vue
@@ -0,0 +1,79 @@
+<template>
+    <view>
+        <view class="preview-item">
+            <image
+                class="cover-image"
+                mode="aspectFill"
+                :src="data.icon"
+                @click="clickItem(data.id)"
+            ></image>
+            <view class="item-box" @click="clickItem(data.id)">
+                <view class="title">{{ data.name }}</view>
+                <view class="text-box">
+                    {{ "已服务113256次" }}
+                </view>
+                <view class="price">¥158元起</view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    name: "service-preview-item",
+    data() {
+        return {};
+    },
+    props: {
+        data: {
+            type: Object,
+            default: () => {},
+        },
+    },
+    components: {},
+    created() {},
+    mounted() {},
+    destroyed() {},
+    methods: {
+        clickItem(id) {
+            this.$emit("clickItem", id);
+        },
+    },
+};
+</script>
+
+<style lang="less" scoped>
+.preview-item {
+    width: 100%;
+    display: flex;
+    justify-content: flex-start;
+}
+.cover-image {
+    width: 130rpx;
+    height: 130rpx;
+    box-sizing: border-box;
+    border-radius: 20rpx;
+    border: 2rpx solid #d8d8d8;
+}
+.item-box {
+    width: 306rpx;
+    display: flex;
+    justify-content: space-between;
+    flex-direction: column;
+    padding-left: 50rpx;
+    .title {
+        font-size: 26rpx;
+        font-weight: bold;
+        color: #010101;
+    }
+    .text-box {
+        display: inline-block;
+        font-size: 22rpx;
+        color: #333333;
+    }
+    .price {
+        font-size: 30rpx;
+        color: #ec7655;
+    }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/widgets/checkbox.vue b/src/components/widgets/checkbox.vue
new file mode 100644
index 0000000..b0d678f
--- /dev/null
+++ b/src/components/widgets/checkbox.vue
@@ -0,0 +1,57 @@
+<template>
+    <view
+        class="checkbox"
+        :class="[state ? 'active' : '']"
+        :style="{ fontSize: $utils.rpx2px(size) + 'px' }"
+        @click="changeCheckBox"
+    >
+        <text v-if="state" class="iconfont icon-xuanzeyixuanze"></text>
+        <text v-if="!state" class="iconfont icon-xuanzeweixuanze"></text>
+    </view>
+</template>
+
+<script>
+export default {
+    name: "widget-checkbox",
+    data() {
+        return {
+            state: false,
+        };
+    },
+    props: {
+        size: {
+            type: Number,
+            default: 40,
+        },
+        checked: {
+            type: Boolean,
+            default: false,
+        },
+    },
+    components: {},
+    created() {
+        this.state = this.checked;
+    },
+    mounted() {},
+    destroyed() {},
+    methods: {
+        changeCheckBox() {
+            this.state = !this.state;
+            this.$emit("change", this.state);
+        },
+    },
+};
+</script>
+
+<style lang="less" scoped>
+.checkbox {
+    .iconfont {
+        color: #c7c7c7;
+    }
+}
+.checkbox.active {
+    .iconfont {
+        color: #8194f2;
+    }
+}
+</style>
\ No newline at end of file
diff --git a/src/components/mini/add.vue b/src/components/widgets/count-modify.vue
similarity index 76%
rename from src/components/mini/add.vue
rename to src/components/widgets/count-modify.vue
index 8ba7e6a..f93e52e 100644
--- a/src/components/mini/add.vue
+++ b/src/components/widgets/count-modify.vue
@@ -1,5 +1,5 @@
 <template>
-    <view class="mini-add" :class="[number > 0 ? 'between' : 'end']">
+    <view class="count-modify" :class="[number > 0 ? 'between' : 'end']">
         <view v-if="number > 0" class="btn sub" @click="sub">
             <text class="iconfont icon-jianhao"></text>
         </view>
@@ -12,7 +12,7 @@
 
 <script>
 export default {
-    name: "mini-add",
+    name: "widget-count-modify",
     data() {
         return {
             number: 0,
@@ -21,12 +21,12 @@ export default {
     props: {
         initNumber: {
             type: Number,
-            default: 0
+            default: 0,
         },
         data: {
             type: Object,
-            default: () => {}
-        }
+            default: () => {},
+        },
     },
     components: {},
     created() {
@@ -41,31 +41,31 @@ export default {
             } else {
                 this.number = 0;
             }
-            this.$emit('onSub', this.data, this.number);
+            this.$emit("onSub", this.data, this.number);
         },
         add() {
             this.number++;
-            this.$emit('onAdd', this.data, this.number);
-        }
+            this.$emit("onAdd", this.data, this.number);
+        },
     },
 };
 </script>
 
 <style lang="less" scoped>
-.mini-add {
+.count-modify {
     width: 130rpx;
     height: 35rpx;
     display: flex;
     align-items: center;
     .num {
-        color: #2D2D2D;
+        color: #2d2d2d;
         font-size: 30rpx;
     }
 }
-.mini-add.between {
+.count-modify.between {
     justify-content: space-between;
 }
-.mini-add.end {
+.count-modify.end {
     justify-content: flex-end;
 }
 .btn.sub .iconfont,
diff --git a/src/components/widgets/switch.vue b/src/components/widgets/switch.vue
new file mode 100644
index 0000000..70f9893
--- /dev/null
+++ b/src/components/widgets/switch.vue
@@ -0,0 +1,54 @@
+<template>
+    <view
+        class="switch"
+        :class="[state ? 'active' : '']"
+        :style="{ fontSize: $utils.rpx2px(size) + 'px' }"
+        @click="changeSwitch"
+    >
+        <text v-if="!state" class="iconfont icon-kaiguan-guan"></text>
+        <text v-if="state" class="iconfont icon-kaiguan-kai"></text>
+    </view>
+</template>
+
+<script>
+export default {
+    name: "widget-switch",
+    data() {
+        return {
+            state: false,
+        };
+    },
+    props: {
+        size: {
+            type: Number,
+            default: 34,
+        },
+        open: {
+            type: Boolean,
+            default: false,
+        },
+    },
+    components: {},
+    created() {
+        this.state = this.open;
+    },
+    mounted() {},
+    destroyed() {},
+    methods: {
+        changeSwitch() {
+            this.state = !this.state;
+            this.$emit("change", this.state);
+        },
+    },
+};
+</script>
+
+<style lang="less" scoped>
+.switch {
+    font-size: 35rpx;
+    color: #c7c7c7;
+}
+.switch.active {
+    color: #8194f2;
+}
+</style>
\ No newline at end of file
diff --git a/src/core/libs/utils.js b/src/core/libs/utils.js
index 9550eab..ff67ddf 100644
--- a/src/core/libs/utils.js
+++ b/src/core/libs/utils.js
@@ -145,12 +145,14 @@ function debounce(func, wait = 500, immediate = false) {
 }
 
 function px2rpx(px) {
-    const { windowWidth } = uni.getStorageSync('system_config');
+    let { windowWidth } = uni.getStorageSync('system_config');
+    windowWidth = (windowWidth > 750) ? 750 : windowWidth;
     return 750 * (px / windowWidth);
 }
 
 function rpx2px(rpx) {
-    const { windowWidth } = uni.getStorageSync('system_config');
+    let { windowWidth } = uni.getStorageSync('system_config');
+    windowWidth = (windowWidth > 750) ? 750 : windowWidth;
     return (rpx / 750) * windowWidth;
 }
 
diff --git a/src/pages/auth/auth.vue b/src/pages/auth/auth.vue
index 7b17fd7..ced4903 100644
--- a/src/pages/auth/auth.vue
+++ b/src/pages/auth/auth.vue
@@ -1,7 +1,5 @@
 <template>
-    <app-layout backgroundColor="#00418c" textColor="light">
-        <view class="body">登录</view>
-    </app-layout>
+    <app-layout headerBackgroundColor="#00418c" textColor="light"> </app-layout>
 </template>
 
 <script>
@@ -11,7 +9,9 @@ export default {
     data() {
         return {};
     },
-    components: { AppLayout },
+    components: {
+        AppLayout,
+    },
     onLoad() {},
     onShow() {},
     onReady() {},
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index fc055b8..3e8bef9 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -1,5 +1,5 @@
 <template>
-    <app-layout backgroundColor="#4B65ED" textColor="light" btnType="city" title="熊熊安装队">
+    <app-layout headerBackgroundColor="#4B65ED" textColor="light" btnType="city" title="熊熊安装队">
         <view class="search">
             <view class="input-box">
                 <view class="icon">
diff --git a/src/pages/member/address.vue b/src/pages/member/address.vue
index b2ec709..2bd36e5 100644
--- a/src/pages/member/address.vue
+++ b/src/pages/member/address.vue
@@ -1,7 +1,5 @@
 <template>
-    <app-layout backgroundColor="#00418c" textColor="light">
-        
-    </app-layout>
+    <app-layout headerBackgroundColor="#00418c" textColor="light"> </app-layout>
 </template>
 
 <script>
@@ -11,7 +9,9 @@ export default {
     data() {
         return {};
     },
-    components: { AppLayout },
+    components: {
+        AppLayout,
+    },
     onLoad() {},
     onShow() {},
     onReady() {},
diff --git a/src/pages/member/member.vue b/src/pages/member/member.vue
index c0c0f53..b696c0f 100644
--- a/src/pages/member/member.vue
+++ b/src/pages/member/member.vue
@@ -1,5 +1,5 @@
 <template>
-    <app-layout backgroundColor="#f00" textColor="light">个人中心</app-layout>
+    <app-layout headerBackgroundColor="#f00" textColor="light"> </app-layout>
 </template>
 
 <script>
@@ -10,7 +10,9 @@ export default {
     data() {
         return {};
     },
-    components: { AppLayout },
+    components: {
+        AppLayout,
+    },
     computed: {
         ...mapState("user", {
             userInfo: (state) => state.userInfo,
diff --git a/src/pages/order/cart.vue b/src/pages/order/cart.vue
new file mode 100644
index 0000000..24de6f7
--- /dev/null
+++ b/src/pages/order/cart.vue
@@ -0,0 +1,26 @@
+<template>
+    <app-layout headerBackgroundColor="#00418c" textColor="light">
+        购物车
+    </app-layout>
+</template>
+
+<script>
+import AppLayout from "@/components/layout/layout";
+export default {
+    name: "order-cart",
+    data() {
+        return {};
+    },
+    components: {
+        AppLayout,
+    },
+    onLoad() {},
+    onShow() {},
+    onReady() {},
+    onReachBottom() {},
+    onPullDownRefresh() {},
+    methods: {},
+};
+</script>
+
+<style lang="less" scoped></style>
\ No newline at end of file
diff --git a/src/pages/order/create.vue b/src/pages/order/create.vue
index 30a44e9..0cb322e 100644
--- a/src/pages/order/create.vue
+++ b/src/pages/order/create.vue
@@ -1,27 +1,348 @@
 <template>
-    <app-layout backgroundColor="#00418c" title="确认订单" textColor="light">
+    <app-layout
+        headerBackgroundColor="#F6F6F6"
+        title="确认订单"
+        textColor="dark"
+        backgroundColor="#F6F6F6"
+    >
+        <view class="tips">
+            <text class="iconfont icon-tixing"></text>
+            <text class="text-container">
+                保险公司承保,人身财产,双重保障,下单无忧!
+            </text>
+        </view>
+        <view class="form-container">
+            <view class="select-group">
+                <view class="select-item address" @click="selectAddress">
+                    <text class="iconfont icon-dingwei"></text>
+                    <text class="text limit-line clamp-1">{{
+                        addressText ? addressText : "请选择上门地址"
+                    }}</text>
+                    <text class="iconfont icon-jinru"></text>
+                </view>
+                <view class="select-item datetime" @click="selectDateTime">
+                    <text class="iconfont icon-shijian"></text>
+                    <picker
+                        mode="date"
+                        :value="datetime"
+                        @change="bindDateChange"
+                        class="text"
+                    >
+                        <view class="uni-input">{{
+                            datetime ? datetime : "选择期望上门时间"
+                        }}</view>
+                    </picker>
+                    <text class="iconfont icon-jinru"></text>
+                </view>
+            </view>
+            <view class="service-view">
+                <service-preview-item
+                    class="service-item"
+                    v-for="(item, idx) in serviceList"
+                    :key="idx"
+                    :data="item"
+                />
+            </view>
+            <view class="insurance">
+                <view class="title-box">
+                    <view class="title" @click="insuranceModal">
+                        <text class="text">意外保</text>
+                        <text class="iconfont icon-shuoming"></text>
+                    </view>
+                    <text class="desc">全面保证您的人身财产安全</text>
+                </view>
+                <view class="switch-container">
+                    <text class="price">¥ 6.00</text>
+                    <widget-switch @change="changeInsurance" />
+                </view>
+            </view>
+            <view class="demand">
+                <text class="title">留言</text>
+                <textarea
+                    class="text-area"
+                    v-model="message"
+                    placeholder="补充描述您的需求,或其他特殊情况"
+                    placeholder-class="textarea-placeholder"
+                />
+            </view>
+            <view class="agreement-container">
+                <agreement @agree="agree" />
+            </view>
+        </view>
+        <view
+            class="pay-component"
+            :style="{ bottom: config.safeAreaInsets.bottom + 'px' }"
+        >
+            <text class="price">¥306.00</text>
+            <view class="pay" @click="pay">
+                <div class="text">去支付</div>
+            </view>
+        </view>
     </app-layout>
 </template>
 
 <script>
 import AppLayout from "@/components/layout/layout";
+import ServicePreviewItem from "@/components/service/preview-item";
+import Agreement from "@/components/auth/agreement";
+import WidgetSwitch from "@/components/widgets/switch";
+import { mapState } from "vuex";
 export default {
     name: "order-create",
     data() {
-        return {};
+        return {
+            addressId: 0,
+            addressText: "",
+            datetime: "",
+            insurance: false,
+            message: "",
+            isAgree: false,
+            serviceList: [
+                {
+                    id: 2,
+                    name: "空调安装",
+                    icon: require("@/static/temp/cate/1.png"),
+                    buyNumber: 1,
+                },
+                {
+                    id: 3,
+                    name: "空调拆卸",
+                    icon: require("@/static/temp/cate/2.png"),
+                    buyNumber: 1,
+                },
+            ],
+        };
+    },
+    components: {
+        AppLayout,
+        ServicePreviewItem,
+        Agreement,
+        WidgetSwitch,
+    },
+    computed: {
+        ...mapState({
+            config: (state) => state.system.config,
+        }),
     },
-    components: { AppLayout },
     onLoad() {},
     onShow() {},
     onReady() {},
     onReachBottom() {},
     onPullDownRefresh() {},
-    methods: {},
+    methods: {
+        bindDateChange(e) {
+            this.datetime = e.detail.value;
+        },
+        selectAddress() {
+            console.log("选择地址");
+        },
+        selectDateTime() {
+            console.log("选择时间");
+        },
+        insuranceModal() {
+            uni.showModal({
+                title: "什么是意外保?",
+                content:
+                    "意外保是中国人寿的保险产品,全面保证您的人身财产安全。",
+                showCancel: false,
+            });
+        },
+        changeInsurance(state) {
+            this.insurance = state;
+            console.log(this.insurance);
+        },
+        agree(state) {
+            this.isAgree = state;
+            console.log(this.isAgree);
+        },
+        pay() {
+            if (!this.isAgree) {
+                uni.showToast({
+                    title: "请先阅读并同意《熊熊安装服务协议》《隐私政策》",
+                    icon: "none",
+                });
+                return;
+            }
+        },
+    },
 };
 </script>
 
 <style lang="less" scoped>
-.finish {
-    margin: 20rpx 0;
+.tips {
+    width: 710rpx;
+    height: 75rpx;
+    margin: 0 auto;
+    display: flex;
+    align-items: center;
+    background-color: #ffffff;
+    box-sizing: border-box;
+    padding: 0 10rpx;
+    .iconfont {
+        font-size: 40rpx;
+        color: #ffa800;
+        margin-right: 26rpx;
+    }
+    .text-container {
+        color: #a0a0a0;
+        font-size: 22rpx;
+        line-height: 22rpx;
+    }
+}
+.form-container {
+    width: 100%;
+    margin-top: 16rpx;
+}
+.select-group {
+    width: 100%;
+    .select-item {
+        position: relative;
+        display: flex;
+        align-items: center;
+        background-color: #ffffff;
+        box-sizing: border-box;
+        margin-top: 2rpx;
+        padding: 0 30rpx;
+        .text {
+            width: 100%;
+            height: 116rpx;
+            line-height: 116rpx;
+            font-size: 30rpx;
+            color: #2d2d2d;
+            padding-left: 26rpx;
+        }
+    }
+    .select-item:first-child {
+        margin-top: 0;
+    }
+    .iconfont.icon-dingwei,
+    .iconfont.icon-shijian {
+        color: #8194f2;
+    }
+    .iconfont.icon-dingwei {
+        font-size: 44rpx;
+    }
+    .iconfont.icon-shijian {
+        font-size: 40rpx;
+    }
+    .iconfont.icon-jinru {
+        font-size: 37rpx;
+        color: #a7a7a7;
+    }
+}
+.service-view {
+    margin-top: 16rpx;
+    padding: 24rpx 40rpx;
+    background-color: #ffffff;
+    .service-item {
+        display: block;
+        margin-top: 28rpx;
+    }
+    .service-item:first-child {
+        margin-top: 0;
+    }
+}
+.insurance {
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    box-sizing: border-box;
+    padding: 38rpx 40rpx;
+    background-color: #ffffff;
+    border-top: 2rpx solid #e8e7e7;
+    .title-box {
+        .title {
+            font-size: 30rpx;
+            line-height: 30rpx;
+            .text {
+                font-weight: bold;
+                color: #010101;
+            }
+            .iconfont {
+                color: #8194f2;
+                margin-left: 8rpx;
+            }
+        }
+        .desc {
+            display: inline-block;
+            line-height: 22rpx;
+            font-size: 22rpx;
+            color: #333333;
+            margin-top: 16rpx;
+        }
+    }
+    .switch-container {
+        display: flex;
+        line-height: 100%;
+        .price {
+            font-size: 30rpx;
+            color: #ec7655;
+            margin-right: 38rpx;
+        }
+    }
+}
+.demand {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 38rpx 40rpx;
+    .title {
+        font-size: 30rpx;
+        font-weight: bold;
+        color: #010101;
+    }
+    .text-area {
+        width: 100%;
+        height: 130rpx;
+        box-sizing: border-box;
+        background-color: #ffffff;
+        padding: 24rpx;
+        font-size: 26rpx;
+        color: #333333;
+        margin-top: 12rpx;
+        border-radius: 10rpx;
+    }
+    .textarea-placeholder {
+        color: #909090;
+    }
+}
+.agreement-container {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 0 40rpx 40rpx 40rpx;
+}
+.pay-component {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    max-width: 750px;
+    width: 100%;
+    height: 100rpx;
+    margin: 0 auto;
+    background-color: #ffffff;
+    box-sizing: border-box;
+    padding: 0 40rpx;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .price {
+        font-size: 42rpx;
+        font-weight: bold;
+        color: #ec7655;
+    }
+    .pay {
+        width: 223rpx;
+        height: 71rpx;
+        background: #8194f2;
+        border-radius: 31rpx;
+        text-align: center;
+        .text {
+            line-height: 71rpx;
+            font-size: 32rpx;
+            font-weight: bold;
+            color: #ffffff;
+        }
+    }
 }
 </style>
\ No newline at end of file
diff --git a/src/pages/service/cate.vue b/src/pages/service/cate.vue
index 7ead678..cb76873 100644
--- a/src/pages/service/cate.vue
+++ b/src/pages/service/cate.vue
@@ -1,5 +1,11 @@
 <template>
-    <app-layout btnType="unset" title="分类" pageBackgroundColor="#F6F6F6" backgroundColor="#F6F6F6">
+    <app-layout
+        minHeight="unset"
+        btnType="unset"
+        title="分类"
+        backgroundColor="#F6F6F6"
+        headerBackgroundColor="#F6F6F6"
+    >
         <view class="search">
             <view class="input-box">
                 <view class="icon">
@@ -19,7 +25,7 @@
                 :offsetHeight="95"
                 :data="data"
                 cateType="cate"
-                @clickCate="clickCate"
+                @clickItem="clickItem"
             />
         </view>
     </app-layout>
@@ -96,7 +102,7 @@ export default {
     onReachBottom() {},
     onPullDownRefresh() {},
     methods: {
-        clickCate(id) {
+        clickItem(id) {
             uni.navigateTo({
                 url: "/pages/service/list?id=" + id,
             });
diff --git a/src/pages/service/detail.vue b/src/pages/service/detail.vue
index b0877d6..72fd44e 100644
--- a/src/pages/service/detail.vue
+++ b/src/pages/service/detail.vue
@@ -1,9 +1,9 @@
 <template>
     <app-layout
-        backgroundColor="#F6F6F6"
+        headerBackgroundColor="#F6F6F6"
         :title="pageTitle"
         textColor="dark"
-        pageBackgroundColor="#F6F6F6"
+        backgroundColor="#F6F6F6"
     >
         <view class="service-header">
             <view
@@ -94,7 +94,7 @@
                 :style="{ bottom: config.safeAreaInsets.bottom + 'px' }"
             >
                 <view class="price">
-                    <text class="text">¥306.00</text>
+                    <text class="text">¥306.00</text>
                 </view>
                 <view class="btn-group">
                     <view class="cart">
@@ -132,7 +132,9 @@ export default {
             },
         };
     },
-    components: { AppLayout },
+    components: {
+        AppLayout,
+    },
     computed: {
         ...mapState({
             config: (state) => state.system.config,
diff --git a/src/pages/service/list.vue b/src/pages/service/list.vue
index bcfa4c3..330dc33 100644
--- a/src/pages/service/list.vue
+++ b/src/pages/service/list.vue
@@ -1,5 +1,11 @@
 <template>
-    <app-layout btnType="back" title="服务列表" backgroundColor="#FFFFFF" pageBackgroundColor="#FFFFFF">
+    <app-layout
+        minHeight="unset"
+        btnType="back"
+        title="服务列表"
+        headerBackgroundColor="#FFFFFF"
+        backgroundColor="#FFFFFF"
+    >
         <view class="cate">
             <app-cate
                 :offsetHeight="0"
@@ -20,7 +26,7 @@
                     <text class="text">99</text>
                 </view>
             </view>
-            <view class="order-btn">
+            <view class="order-btn" @click="createOrder">
                 <text class="text">去下单</text>
             </view>
         </view>
@@ -96,7 +102,10 @@ export default {
             bottom: 0,
         };
     },
-    components: { AppLayout, AppCate },
+    components: {
+        AppLayout,
+        AppCate,
+    },
     computed: {
         ...mapState({
             config: (state) => state.system.config,
@@ -108,6 +117,11 @@ export default {
     onReachBottom() {},
     onPullDownRefresh() {},
     methods: {
+        createOrder() {
+            uni.navigateTo({
+                url: "/pages/order/create",
+            });
+        },
         clickItem(id) {
             uni.navigateTo({
                 url: "/pages/service/detail?id=" + id,