Commit 3972b9236af55ef4156468e34d280ab1b528144b

Authored by guzijian
1 parent 98c47411

feat: 优化获取验证码界面,优化工具类方法,优化u-message-input在ios端输入问题

garbage-removal/.env.production
1 -# VITE_BASE_URL=http://1.14.107.94:8820 1 +VITE_BASE_URL=http://101.95.0.106:10001/workflow
2 # VITE_BASE_FILE_UPLOAD_PREFIX=/common/upload 2 # VITE_BASE_FILE_UPLOAD_PREFIX=/common/upload
3 # VITE_STOMP_URL=http://localhost:8860/ws 3 # VITE_STOMP_URL=http://localhost:8860/ws
garbage-removal/src/App.vue
@@ -8,14 +8,9 @@ onLaunch(async () => { @@ -8,14 +8,9 @@ onLaunch(async () => {
8 console.log("onLaunch"); 8 console.log("onLaunch");
9 if (store.token) { 9 if (store.token) {
10 setRequestToken(store.token); 10 setRequestToken(store.token);
11 - // store.userInfo = (await getUserInfo()).data.data;  
12 uni.switchTab({ 11 uni.switchTab({
13 url: "/pages/home/index", 12 url: "/pages/home/index",
14 }); 13 });
15 - } else {  
16 - uni.reLaunch({  
17 - url: "/pages/login/index",  
18 - });  
19 } 14 }
20 }); 15 });
21 </script> 16 </script>
garbage-removal/src/apis/user.js
@@ -15,6 +15,16 @@ export async function userLogin( params, config) { @@ -15,6 +15,16 @@ export async function userLogin( params, config) {
15 } 15 }
16 16
17 /** 17 /**
  18 + * @method 退出登录
  19 + */
  20 +export async function loginOut( params, config) {
  21 + return await request.post(
  22 + `${prefix}/logout`,
  23 + );
  24 +}
  25 +
  26 +
  27 +/**
18 * @method 获取用户信息 28 * @method 获取用户信息
19 */ 29 */
20 export async function getUserInfo(config) { 30 export async function getUserInfo(config) {
garbage-removal/src/components/uni-combox/index.vue 0 → 100644
  1 +<template>
  2 + <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
  3 + <view v-if="label" class="uni-combox__label" :style="labelStyle">
  4 + <text>{{ label }}</text>
  5 + </view>
  6 + <view class="uni-combox__input-box">
  7 + <input class="uni-combox__input" type="text" :placeholder="placeholder" placeholder-class="uni-combox__input-plac"
  8 + v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" />
  9 + <uni-icons :type="showSelector ? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector">
  10 + </uni-icons>
  11 + </view>
  12 + <view class="uni-combox__selector" v-if="showSelector">
  13 + <view class="uni-popper__arrow"></view>
  14 + <scroll-view scroll-y="true" class="uni-combox__selector-scroll">
  15 + <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
  16 + <text>{{ emptyTips }}</text>
  17 + </view>
  18 + <view class="uni-combox__selector-item" v-for="(item, index) in filterCandidates" :key="index"
  19 + @click="onSelectorClick(index)">
  20 + <text>{{ item }}</text>
  21 + </view>
  22 + </scroll-view>
  23 + </view>
  24 + </view>
  25 +</template>
  26 +
  27 +<script>
  28 +/**
  29 + * Combox 组合输入框
  30 + * @description 组合输入框一般用于既可以输入也可以选择的场景
  31 + * @tutorial https://ext.dcloud.net.cn/plugin?id=1261
  32 + * @property {String} label 左侧文字
  33 + * @property {String} labelWidth 左侧内容宽度
  34 + * @property {String} placeholder 输入框占位符
  35 + * @property {Array} candidates 候选项列表
  36 + * @property {String} emptyTips 筛选结果为空时显示的文字
  37 + * @property {String} value 组合框的值
  38 + */
  39 +export default {
  40 + name: 'uniCombox',
  41 + emits: ['input', 'update:modelValue'],
  42 + props: {
  43 + border: {
  44 + type: Boolean,
  45 + default: true
  46 + },
  47 + label: {
  48 + type: String,
  49 + default: ''
  50 + },
  51 + labelWidth: {
  52 + type: String,
  53 + default: 'auto'
  54 + },
  55 + placeholder: {
  56 + type: String,
  57 + default: ''
  58 + },
  59 + candidates: {
  60 + type: Array,
  61 + default() {
  62 + return []
  63 + }
  64 + },
  65 + emptyTips: {
  66 + type: String,
  67 + default: '无匹配项'
  68 + },
  69 + // #ifndef VUE3
  70 + value: {
  71 + type: [String, Number],
  72 + default: ''
  73 + },
  74 + // #endif
  75 + // #ifdef VUE3
  76 + modelValue: {
  77 + type: [String, Number],
  78 + default: ''
  79 + },
  80 + // #endif
  81 + },
  82 + data() {
  83 + return {
  84 + showSelector: false,
  85 + inputVal: ''
  86 + }
  87 + },
  88 + computed: {
  89 + labelStyle() {
  90 + if (this.labelWidth === 'auto') {
  91 + return ""
  92 + }
  93 + return `width: ${this.labelWidth}`
  94 + },
  95 + filterCandidates() {
  96 + return this.candidates.filter((item) => {
  97 + return item.toString().indexOf(this.inputVal) > -1
  98 + })
  99 + },
  100 + filterCandidatesLength() {
  101 + return this.filterCandidates.length
  102 + }
  103 + },
  104 + watch: {
  105 + // #ifndef VUE3
  106 + value: {
  107 + handler(newVal) {
  108 + this.inputVal = newVal
  109 + },
  110 + immediate: true
  111 + },
  112 + // #endif
  113 + // #ifdef VUE3
  114 + modelValue: {
  115 + handler(newVal) {
  116 + this.inputVal = newVal
  117 + },
  118 + immediate: true
  119 + },
  120 + // #endif
  121 + },
  122 + methods: {
  123 + toggleSelector() {
  124 + this.showSelector = !this.showSelector
  125 + },
  126 + onFocus() {
  127 + this.showSelector = true
  128 + },
  129 + onBlur() {
  130 + setTimeout(() => {
  131 + this.showSelector = false
  132 + }, 153)
  133 + },
  134 + onSelectorClick(index) {
  135 + this.inputVal = this.filterCandidates[index]
  136 + this.showSelector = false
  137 + this.$emit('input', this.inputVal)
  138 + this.$emit('update:modelValue', this.inputVal)
  139 + },
  140 + onInput() {
  141 + setTimeout(() => {
  142 + this.$emit('input', this.inputVal)
  143 + this.$emit('update:modelValue', this.inputVal)
  144 + })
  145 + }
  146 + }
  147 +}
  148 +</script>
  149 +
  150 +<style lang="scss" scoped>
  151 +.uni-combox {
  152 + font-size: 14px;
  153 + border: 1px solid #DCDFE6;
  154 + border-radius: 4px;
  155 + padding: 6px 10px;
  156 + position: relative;
  157 + /* #ifndef APP-NVUE */
  158 + display: flex;
  159 + /* #endif */
  160 + // height: 40px;
  161 + flex-direction: row;
  162 + align-items: center;
  163 + // border-bottom: solid 1px #DDDDDD;
  164 + color: $u-info;
  165 +}
  166 +
  167 +.uni-combox__label {
  168 + font-size: 16px;
  169 + line-height: 22px;
  170 + padding-right: 10px;
  171 + color: #999999;
  172 +}
  173 +
  174 +.uni-combox__input-box {
  175 + position: relative;
  176 + /* #ifndef APP-NVUE */
  177 + display: flex;
  178 + /* #endif */
  179 + flex: 1;
  180 + flex-direction: row;
  181 + align-items: center;
  182 +}
  183 +
  184 +.uni-combox__input {
  185 + flex: 1;
  186 + font-size: 14px;
  187 + height: 22px;
  188 + line-height: 22px;
  189 + color: $u-info;
  190 +}
  191 +
  192 +.uni-combox__input-plac {
  193 + font-size: 14px;
  194 + color: #999;
  195 +}
  196 +
  197 +.uni-combox__selector {
  198 + /* #ifndef APP-NVUE */
  199 + box-sizing: border-box;
  200 + /* #endif */
  201 + position: absolute;
  202 + top: calc(100% + 12px);
  203 + left: 0;
  204 + width: 100%;
  205 + background-color: #FFFFFF;
  206 + border: 1px solid #EBEEF5;
  207 + border-radius: 6px;
  208 + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  209 + z-index: 2;
  210 + padding: 4px 0;
  211 +}
  212 +
  213 +.uni-combox__selector-scroll {
  214 + /* #ifndef APP-NVUE */
  215 + max-height: 200px;
  216 + box-sizing: border-box;
  217 + /* #endif */
  218 +}
  219 +
  220 +.uni-combox__selector-empty,
  221 +.uni-combox__selector-item {
  222 + /* #ifndef APP-NVUE */
  223 + display: flex;
  224 + cursor: pointer;
  225 + /* #endif */
  226 + line-height: 36px;
  227 + font-size: 14px;
  228 + text-align: center;
  229 + // border-bottom: solid 1px #DDDDDD;
  230 + padding: 0px 10px;
  231 +}
  232 +
  233 +.uni-combox__selector-item:hover {
  234 + background-color: #f9f9f9;
  235 +}
  236 +
  237 +.uni-combox__selector-empty:last-child,
  238 +.uni-combox__selector-item:last-child {
  239 + /* #ifndef APP-NVUE */
  240 + border-bottom: none;
  241 + /* #endif */
  242 +}
  243 +
  244 +// picker 弹出层通用的指示小三角
  245 +.uni-popper__arrow,
  246 +.uni-popper__arrow::after {
  247 + position: absolute;
  248 + display: block;
  249 + width: 0;
  250 + height: 0;
  251 + border-color: transparent;
  252 + border-style: solid;
  253 + border-width: 6px;
  254 +}
  255 +
  256 +.uni-popper__arrow {
  257 + filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  258 + top: -6px;
  259 + left: 10%;
  260 + margin-right: 3px;
  261 + border-top-width: 0;
  262 + border-bottom-color: #EBEEF5;
  263 +}
  264 +
  265 +.uni-popper__arrow::after {
  266 + content: " ";
  267 + top: 1px;
  268 + margin-left: -6px;
  269 + border-top-width: 0;
  270 + border-bottom-color: #fff;
  271 +}
  272 +
  273 +.uni-combox__no-border {
  274 + border: none;
  275 +}
  276 +</style>
garbage-removal/src/pages/home/clean/index.vue
@@ -3,15 +3,14 @@ @@ -3,15 +3,14 @@
3 <view class="company-clean-container-box"> 3 <view class="company-clean-container-box">
4 <view class="company-clean-container-header"> 4 <view class="company-clean-container-header">
5 <view class="company-clean-container-header-address"> 5 <view class="company-clean-container-header-address">
6 - {{ userAddress.garUserAddress + userAddress.garRemark }} 6 + {{ userAddress.garUserAddress }}{{ userAddress.garRemark }}
7 </view> 7 </view>
8 <view class="company-clean-container-header-base-info"> 8 <view class="company-clean-container-header-base-info">
9 {{ userAddress.garUserContactName }} {{ userAddress.garUserContactTel }} 9 {{ userAddress.garUserContactName }} {{ userAddress.garUserContactTel }}
10 </view> 10 </view>
11 <view class="company-clean-container-header-reservation"> 11 <view class="company-clean-container-header-reservation">
12 <view class="company-clean-container-header-reservation-left"> 12 <view class="company-clean-container-header-reservation-left">
13 - <u-icon name="calendar" size="40"></u-icon>  
14 - 预约时间 13 + <text style="color: red;">*</text> <u-icon name="calendar" size="40"></u-icon>预约时间
15 </view> 14 </view>
16 <view class="company-clean-container-header-reservation-right"> 15 <view class="company-clean-container-header-reservation-right">
17 <text style="margin-right: 10rpx;" @click="handleTimeChoose">{{ dayTime ? dayTime : "请选择时间" }}</text> <u-icon 16 <text style="margin-right: 10rpx;" @click="handleTimeChoose">{{ dayTime ? dayTime : "请选择时间" }}</text> <u-icon
@@ -21,28 +20,31 @@ @@ -21,28 +20,31 @@
21 </view> 20 </view>
22 </view> 21 </view>
23 <view class="company-clean-container-car-main"> 22 <view class="company-clean-container-car-main">
24 - <view class="company-clean-container-car-main-title"> 23 + <!-- <view class="company-clean-container-car-main-title">
25 自卸车 24 自卸车
26 - </view> 25 + </view> -->
27 <view class="company-clean-container-car-main-content"> 26 <view class="company-clean-container-car-main-content">
28 - <view class="company-clean-container-car-main-content-img"> 27 + <view class="company-clean-container-car-main-content-type">
  28 + <text class="company-clean-container-car-main-content-type-price-area"><text
  29 + style="color: red;">*</text>垃圾类型:</text>
  30 + <uni-combox label="" :candidates="garbageTypeList" placeholder="请选择垃圾类型"
  31 + v-model="paramFrom.garbageType"></uni-combox>
  32 + </view>
  33 + <!-- <view class="company-clean-container-car-main-content-img">
29 <image class="company-clean-container-car-main-content-img" /> 34 <image class="company-clean-container-car-main-content-img" />
30 </view> 35 </view>
31 <view class="company-clean-container-car-main-content-remark"> 36 <view class="company-clean-container-car-main-content-remark">
32 箱体长4.2m宽1.1,高0.7,最多课容纳约110袋袋装修垃圾(75cm*45每袋) 37 箱体长4.2m宽1.1,高0.7,最多课容纳约110袋袋装修垃圾(75cm*45每袋)
33 - </view> 38 + </view> -->
34 <view class="company-clean-container-car-main-content-type"> 39 <view class="company-clean-container-car-main-content-type">
35 - <view class="company-clean-container-car-main-content-type-choose">  
36 - <text style="margin-right: 10rpx;">6方车</text>  
37 - <u-icon name="arrow-down" size="30" color="#ffffff"></u-icon>  
38 - </view>  
39 - <view class="company-clean-container-car-main-content-type-price-area">  
40 - 车  
41 - </view> 40 + <text class="company-clean-container-car-main-content-type-price-area"><text
  41 + style="color: red;">*</text>车辆类型:</text>
  42 + <uni-combox label="" :candidates="candidates" placeholder="请选择运输车辆类型"
  43 + v-model="paramFrom.carType"></uni-combox>
42 </view> 44 </view>
43 <view class="company-clean-container-car-main-content-number"> 45 <view class="company-clean-container-car-main-content-number">
44 <view class="company-clean-container-car-main-content-number-txt"> 46 <view class="company-clean-container-car-main-content-number-txt">
45 - 添加车辆数量 47 + <text style="color: red;">*</text>添加车辆数量
46 </view> 48 </view>
47 <view class="company-clean-container-car-main-content-number-button"> 49 <view class="company-clean-container-car-main-content-number-button">
48 <u-number-box :min="1" integer buttonSize="46" v-model="paramFrom.carNumber"></u-number-box> 50 <u-number-box :min="1" integer buttonSize="46" v-model="paramFrom.carNumber"></u-number-box>
@@ -72,8 +74,8 @@ @@ -72,8 +74,8 @@
72 <view class="company-clean-container-site-image-info-sure-button"> 74 <view class="company-clean-container-site-image-info-sure-button">
73 <view class="company-clean-container-site-image-info-sure-button-radio"> 75 <view class="company-clean-container-site-image-info-sure-button-radio">
74 <u-radio-group v-model="paramFrom.sureReadFlag"> 76 <u-radio-group v-model="paramFrom.sureReadFlag">
75 - <u-radio activeColor="#a9e08f" size="27" labelSize="25" :labelDisabled="true" labelColor="#909399"  
76 - label=""></u-radio>本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。 77 + <u-radio activeColor="#a9e08f" size="27" labelSize="25" :name="true" :labelDisabled="true"
  78 + labelColor="#909399" label=""></u-radio>本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。
77 </u-radio-group> 79 </u-radio-group>
78 </view> 80 </view>
79 </view> 81 </view>
@@ -103,6 +105,7 @@ import { queryCarList } from &#39;@/apis/carinfo.js&#39;; @@ -103,6 +105,7 @@ import { queryCarList } from &#39;@/apis/carinfo.js&#39;;
103 import { uploadFilePromise } from '@/apis/common.js'; 105 import { uploadFilePromise } from '@/apis/common.js';
104 import { saveOrder } from '@/apis/order.js'; 106 import { saveOrder } from '@/apis/order.js';
105 import liuDeliveryTime from "@/components/liu-delivery-time/liu-delivery-time.vue"; 107 import liuDeliveryTime from "@/components/liu-delivery-time/liu-delivery-time.vue";
  108 +import uniCombox from "@/components/uni-combox/index.vue";
106 import { onLoad } from '@dcloudio/uni-app'; 109 import { onLoad } from '@dcloudio/uni-app';
107 import { getCurrentInstance, onMounted, ref } from 'vue'; 110 import { getCurrentInstance, onMounted, ref } from 'vue';
108 const { proxy } = getCurrentInstance(); 111 const { proxy } = getCurrentInstance();
@@ -111,18 +114,25 @@ const y = ref() @@ -111,18 +114,25 @@ const y = ref()
111 const movableAreaElement = ref() 114 const movableAreaElement = ref()
112 const companyObj = ref() 115 const companyObj = ref()
113 const tel = ref() 116 const tel = ref()
114 -const userAddress = ref()  
115 -const carList = ref(); 117 +const userAddress = ref({
  118 + garUserContactName: "",
  119 + garUserContactTel: "",
  120 + garRemark: "",
  121 + garUserAddress: ""
  122 +})
  123 +const garbageTypeList = ref(["建筑垃圾", "装修垃圾"])
116 const paramFrom = ref({ 124 const paramFrom = ref({
117 - carNumber: 0, 125 + carNumber: 1,
118 remark: "", 126 remark: "",
119 - sureReadFlag: false 127 + sureReadFlag: false,
  128 + carType: "",
  129 + garbageType: "装修垃圾"
120 }) 130 })
121 const dayTime = ref() 131 const dayTime = ref()
122 132
123 const chooseTime = ref() 133 const chooseTime = ref()
124 const fileList = ref([]) 134 const fileList = ref([])
125 - 135 +const candidates = ref([])
126 const handleTimeChoose = () => { 136 const handleTimeChoose = () => {
127 chooseTime.value.open(); 137 chooseTime.value.open();
128 } 138 }
@@ -135,12 +145,12 @@ const changeTime = (e) =&gt; { @@ -135,12 +145,12 @@ const changeTime = (e) =&gt; {
135 */ 145 */
136 onLoad((options) => { 146 onLoad((options) => {
137 companyObj.value = JSON.parse(options.companyObj); 147 companyObj.value = JSON.parse(options.companyObj);
138 - console.log(companyObj.value);  
139 tel.value = options.tel; 148 tel.value = options.tel;
140 userAddress.value = JSON.parse(options.userAddress); 149 userAddress.value = JSON.parse(options.userAddress);
141 - queryCarList({ companyId: companyObj.value.id }.then(res => {  
142 - carList.value = res.data.rows  
143 - })) 150 + queryCarList({ companyId: companyObj.value.id }).then(res => {
  151 + candidates.value = res.data.rows.map(item => item.carType)
  152 + console.log(candidates.value);
  153 + })
144 }) 154 })
145 155
146 /** 156 /**
@@ -188,14 +198,13 @@ const afterRead = async (event) =&gt; { @@ -188,14 +198,13 @@ const afterRead = async (event) =&gt; {
188 * 处理车子数量 198 * 处理车子数量
189 */ 199 */
190 const handleCarInfo = () => { 200 const handleCarInfo = () => {
191 - console.log("车子数量"); 201 +
192 } 202 }
193 203
194 /** 204 /**
195 * 处理下单 205 * 处理下单
196 */ 206 */
197 const handleOderSure = () => { 207 const handleOderSure = () => {
198 - console.log("下单了", companyObj.value);  
199 let params = { 208 let params = {
200 /** 209 /**
201 * 订单地址 210 * 订单地址
@@ -211,11 +220,13 @@ const handleOderSure = () =&gt; { @@ -211,11 +220,13 @@ const handleOderSure = () =&gt; {
211 * 订单姓名 220 * 订单姓名
212 */ 221 */
213 garOrderContactName: userAddress.value.garUserContactName, 222 garOrderContactName: userAddress.value.garUserContactName,
  223 + garOrderCarNumber: paramFrom.value.carNumber,
  224 + garOrderCarType: paramFrom.value.carType,
214 225
215 /** 226 /**
216 * 垃圾类型 227 * 垃圾类型
217 */ 228 */
218 - garOrderTrashType: "建筑垃圾", 229 + garOrderTrashType: paramFrom.value.garbageType,
219 230
220 /** 231 /**
221 * 订单人电话 232 * 订单人电话
@@ -254,7 +265,6 @@ const handleOderSure = () =&gt; { @@ -254,7 +265,6 @@ const handleOderSure = () =&gt; {
254 return; 265 return;
255 } 266 }
256 saveOrder(params).then(res => { 267 saveOrder(params).then(res => {
257 - console.log(res);  
258 // TODO 订单详情 268 // TODO 订单详情
259 if (res.data.success) { 269 if (res.data.success) {
260 uni.$u.route({ 270 uni.$u.route({
@@ -284,6 +294,73 @@ onMounted(() =&gt; { @@ -284,6 +294,73 @@ onMounted(() =&gt; {
284 }) 294 })
285 295
286 const validateParams = (params) => { 296 const validateParams = (params) => {
  297 + if (!paramFrom.value.sureReadFlag) {
  298 + jumpPrompt('请勾选"本人已确认信息真实有效,并将上诉信息告知市容环境卫生主管部门"')
  299 + return false;
  300 + }
  301 + for (const key in params) {
  302 + if (!params[key] && key != "garRemark") {
  303 + switch (key) {
  304 + case "garOrderAgreementTime":
  305 + jumpPrompt('请选择预约时间')
  306 + break;
  307 + case "garOrderTrashType":
  308 + jumpPrompt('请选择垃圾类型')
  309 + break;
  310 + case "garOrderCarType":
  311 + jumpPrompt('请选择车辆类型')
  312 + break;
  313 + }
  314 + return false;
  315 + }
  316 + console.log("key:", key, key == "imageUrls");
  317 + if (key == "imageUrls") {
  318 + if (params[key].length == 0) {
  319 + jumpPrompt('请上传现场图片')
  320 + return false;
  321 + }
  322 + if (!validateImage(params[key])) {
  323 + uni.$u.toast('请等待图片上传完毕')
  324 + return false;
  325 + }
  326 + }
  327 + }
  328 +
  329 + return true;
  330 +}
  331 +
  332 +const jumpPrompt = (msg) => {
  333 + uni.showModal({
  334 + title: '提示',
  335 + content: msg,
  336 + showCancel: false,
  337 + success: function (res) {
  338 + if (res.confirm) {
  339 + } else if (res.cancel) {
  340 + }
  341 + }
  342 + });
  343 +}
  344 +const validateImage = (fileList) => {
  345 + console.log(fileList);
  346 +
  347 + for (let index = 0; index < fileList.length; index++) {
  348 + const str = fileList[index];
  349 + // #ifdef H5
  350 + if (str.startsWith("blob")) {
  351 + return false;
  352 + }
  353 + // #endif
  354 + // #ifdef MP-WEIXIN
  355 + if (uni.$u.test.contains(str, "/tmp/")) {
  356 + return false;
  357 + }
  358 + // #endif
  359 +
  360 + }
  361 + //
  362 + // #ifdef
  363 +
287 return true; 364 return true;
288 } 365 }
289 366
@@ -396,30 +473,15 @@ $custom-bottom-height: 200rpx; @@ -396,30 +473,15 @@ $custom-bottom-height: 200rpx;
396 display: flex; 473 display: flex;
397 justify-content: space-between; 474 justify-content: space-between;
398 border-radius: $custom-border-radio; 475 border-radius: $custom-border-radio;
399 - background-color: $u-info-light; 476 + // background-color: $u-info-light;
400 box-sizing: border-box; 477 box-sizing: border-box;
401 - font-size: 30rpx;  
402 -  
403 - .company-clean-container-car-main-content-type-choose {  
404 - width: 230rpx;  
405 - color: #ffffff;  
406 - display: flex;  
407 - justify-content: center;  
408 - align-items: center;  
409 - background-color: #a9e08f;  
410 - padding: 30rpx $custom-page-padding 30rpx $custom-page-padding;  
411 - box-sizing: border-box;  
412 - border-radius: $custom-border-radio 0 0 $custom-border-radio;  
413 - }  
414 478
415 .company-clean-container-car-main-content-type-price-area { 479 .company-clean-container-car-main-content-type-price-area {
416 - width: 100%;  
417 display: flex; 480 display: flex;
418 - justify-content: flex-end; 481 + justify-content: flex-start;
419 align-items: center; 482 align-items: center;
420 - box-sizing: border-box;  
421 - color: $u-tips-color;  
422 - padding-right: $custom-page-padding; 483 + color: $u-info;
  484 + white-space: nowrap;
423 } 485 }
424 } 486 }
425 487
garbage-removal/src/pages/home/index.vue
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 28
29 <view class="company-container"> 29 <view class="company-container">
30 <span class="company-label-info">可进行垃圾清运单位</span> 30 <span class="company-label-info">可进行垃圾清运单位</span>
31 - <view class="company-list-box"> 31 + <view class="company-list-box" v-if="addressInfo">
32 <view class="company-list-header"> 32 <view class="company-list-header">
33 <view class="company-list-header-left"> 33 <view class="company-list-header-left">
34 综合排序 34 综合排序
@@ -85,12 +85,26 @@ @@ -85,12 +85,26 @@
85 </view> 85 </view>
86 </view> 86 </view>
87 </z-paging> 87 </z-paging>
88 -  
89 </view> 88 </view>
90 </view> 89 </view>
91 </view> 90 </view>
  91 + <view class="company-empty" v-else @click="handleCleanClick">
  92 + <view class="empty-text-title">
  93 + 请先添加地址
  94 + </view>
  95 + <view class="empty-text-content">
  96 + 房屋装饰装修过程中产生的砖瓦、木材、熟料等废弃物
  97 + </view>
  98 + <view class="empty-text-box">
  99 + <view class="empty-text-box-button">
  100 + 立即清运
  101 + </view>
  102 + </view>
  103 + </view>
  104 +
92 </view> 105 </view>
93 </view> 106 </view>
  107 +
94 </view> 108 </view>
95 </template> 109 </template>
96 110
@@ -107,8 +121,6 @@ const topMargin = ref(null);//状态栏高度 @@ -107,8 +121,6 @@ const topMargin = ref(null);//状态栏高度
107 const musicheadHeight = ref(); 121 const musicheadHeight = ref();
108 const paging = ref(null) 122 const paging = ref(null)
109 const swiperImageList = ref([{ 123 const swiperImageList = ref([{
110 - image: 'https://cdn.uviewui.com/uview/swiper/swiper2.png',  
111 -}, {  
112 image: 'https://cdn.uviewui.com/uview/swiper/swiper1.png', 124 image: 'https://cdn.uviewui.com/uview/swiper/swiper1.png',
113 }, { 125 }, {
114 image: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', 126 image: 'https://cdn.uviewui.com/uview/swiper/swiper3.png',
@@ -154,7 +166,21 @@ function handleAddressInfo() { @@ -154,7 +166,21 @@ function handleAddressInfo() {
154 url: `pages/home/address/index`, 166 url: `pages/home/address/index`,
155 }) 167 })
156 } 168 }
157 - 169 +const handleCleanClick = () => {
  170 + uni.showModal({
  171 + title: '',
  172 + content: '请先添加清运地址',
  173 + success: function (res) {
  174 + if (res.confirm) {
  175 + uni.$u.route({
  176 + url: `pages/home/address/index`,
  177 + })
  178 + } else if (res.cancel) {
  179 + console.log('用户点击取消');
  180 + }
  181 + }
  182 + });
  183 +}
158 /** 184 /**
159 * 公司详情 185 * 公司详情
160 */ 186 */
@@ -209,7 +235,7 @@ const initData = () =&gt; { @@ -209,7 +235,7 @@ const initData = () =&gt; {
209 userAddress.value = null; 235 userAddress.value = null;
210 // 查询用户当前地址 236 // 查询用户当前地址
211 queryAddress('CURRENT').then(res => { 237 queryAddress('CURRENT').then(res => {
212 - if (res.data.data instanceof Array) { 238 + if (res.data.data && res.data.data[0]) {
213 addressInfo.value = res.data.data[0].garUserAddress + res.data.data[0].garRemark 239 addressInfo.value = res.data.data[0].garUserAddress + res.data.data[0].garRemark
214 userAddress.value = JSON.stringify(res.data.data[0] ? res.data.data[0] : {}); 240 userAddress.value = JSON.stringify(res.data.data[0] ? res.data.data[0] : {});
215 } 241 }
@@ -345,6 +371,45 @@ const queryList = (pageNo, pageSize) =&gt; { @@ -345,6 +371,45 @@ const queryList = (pageNo, pageSize) =&gt; {
345 font-size: 30rpx; 371 font-size: 30rpx;
346 width: 100%; 372 width: 100%;
347 color: $u-info-dark; 373 color: $u-info-dark;
  374 +
  375 + }
  376 +
  377 + .company-empty {
  378 + width: 100%;
  379 + height: 300rpx;
  380 + box-sizing: border-box;
  381 + border-radius: 20rpx;
  382 + background: linear-gradient(to bottom, $u-primary, $u-primary-disabled);
  383 + // background-image: url("https://cdn.uviewui.com/uview/swiper/swiper2.png");
  384 + color: #ffffff;
  385 + background-size: 100% 100%;
  386 + padding: 20rpx;
  387 +
  388 + .empty-text-title {
  389 + font-size: 30rpx;
  390 + line-height: 60rpx;
  391 + }
  392 +
  393 + .empty-text-content {
  394 + font-size: small;
  395 + width: 60%;
  396 + line-height: 40rpx;
  397 + }
  398 +
  399 + .empty-text-box {
  400 + // width: 0%;
  401 + display: flex;
  402 +
  403 + .empty-text-box-button {
  404 + margin-top: 20rpx;
  405 + padding: 15rpx 30rpx 15rpx 30rpx;
  406 + white-space: nowrap;
  407 + box-sizing: border-box;
  408 + border-radius: 50rpx;
  409 + background-color: orange;
  410 + font-size: 25rpx;
  411 + }
  412 + }
348 } 413 }
349 414
350 .company-list-box { 415 .company-list-box {
@@ -485,5 +550,6 @@ const queryList = (pageNo, pageSize) =&gt; { @@ -485,5 +550,6 @@ const queryList = (pageNo, pageSize) =&gt; {
485 } 550 }
486 } 551 }
487 } 552 }
  553 +
488 } 554 }
489 </style> 555 </style>
garbage-removal/src/pages/login/code.vue
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <view class="key-input"> 3 <view class="key-input">
4 <view class="title">输入验证码</view> 4 <view class="title">输入验证码</view>
5 <view class="tips">验证码已发送至 +{{ startIphoneNumber }}</view> 5 <view class="tips">验证码已发送至 +{{ startIphoneNumber }}</view>
6 - <u-message-input :focus="true" :value="value" @change="change" @finish="finish" mode="bottomLine" 6 + <u-message-input :value="value" :focus="true" @change="change" @finish="finish" mode="bottomLine"
7 :maxlength="maxlength"></u-message-input> 7 :maxlength="maxlength"></u-message-input>
8 <text v-if="verifyFlag" class="error">验证码错误,请重新输入</text> 8 <text v-if="verifyFlag" class="error">验证码错误,请重新输入</text>
9 <view class="captcha"> 9 <view class="captcha">
@@ -18,7 +18,8 @@ @@ -18,7 +18,8 @@
18 import { sendCode, userLogin } from "@/apis/user.js"; 18 import { sendCode, userLogin } from "@/apis/user.js";
19 import { useMainStore } from '@/stores/index.js'; 19 import { useMainStore } from '@/stores/index.js';
20 import { onLoad } from "@dcloudio/uni-app"; 20 import { onLoad } from "@dcloudio/uni-app";
21 -import { ref } from "vue"; 21 +import { getCurrentInstance, ref } from "vue";
  22 +const { proxy } = getCurrentInstance();
22 const store = useMainStore(); 23 const store = useMainStore();
23 const verifyFlag = ref(false) 24 const verifyFlag = ref(false)
24 const iphoneNumber = ref("") 25 const iphoneNumber = ref("")
@@ -32,15 +33,7 @@ onLoad((options) =&gt; { @@ -32,15 +33,7 @@ onLoad((options) =&gt; {
32 iphoneNumber.value = options.iphoneNumber; 33 iphoneNumber.value = options.iphoneNumber;
33 startIphoneNumber.value = handleIphoneNumber("" + options.iphoneNumber); 34 startIphoneNumber.value = handleIphoneNumber("" + options.iphoneNumber);
34 getCaptcha(iphoneNumber.value) 35 getCaptcha(iphoneNumber.value)
35 - let interval = setInterval(() => {  
36 - second.value--;  
37 - if (second.value <= 0) {  
38 - show.value = true  
39 - clearInterval(interval);  
40 - }  
41 - }, 1000);  
42 }) 36 })
43 -  
44 const handleIphoneNumber = (tel) => { 37 const handleIphoneNumber = (tel) => {
45 return tel.replace(tel.substring(3, 7), "****"); 38 return tel.replace(tel.substring(3, 7), "****");
46 } 39 }
@@ -49,6 +42,9 @@ const getCaptcha = (iphoneNumber) =&gt; { @@ -49,6 +42,9 @@ const getCaptcha = (iphoneNumber) =&gt; {
49 value.value = '' 42 value.value = ''
50 second.value = 10 43 second.value = 10
51 show.value = false; 44 show.value = false;
  45 + sendCode(iphoneNumber).then(res => {
  46 + proxy.$u.toast(res.data.data)
  47 + })
52 let interval = setInterval(() => { 48 let interval = setInterval(() => {
53 second.value--; 49 second.value--;
54 if (second.value <= 0) { 50 if (second.value <= 0) {
@@ -56,9 +52,7 @@ const getCaptcha = (iphoneNumber) =&gt; { @@ -56,9 +52,7 @@ const getCaptcha = (iphoneNumber) =&gt; {
56 clearInterval(interval); 52 clearInterval(interval);
57 } 53 }
58 }, 1000); 54 }, 1000);
59 - sendCode(iphoneNumber).then(res => {  
60 - console.log(res);  
61 - }) 55 +
62 } 56 }
63 // 收不到验证码选择时的选择 57 // 收不到验证码选择时的选择
64 const noCaptcha = () => { 58 const noCaptcha = () => {
@@ -80,7 +74,7 @@ const checkVerifyNum = (code) =&gt; { @@ -80,7 +74,7 @@ const checkVerifyNum = (code) =&gt; {
80 if (res.data.success) { 74 if (res.data.success) {
81 verifyFlag.value = false; 75 verifyFlag.value = false;
82 store.tempToken = res.data.data 76 store.tempToken = res.data.data
83 - uni.$u.route({ 77 + proxy.$u.route({
84 url: `pages/wode/choose/index`, 78 url: `pages/wode/choose/index`,
85 }) 79 })
86 } else { 80 } else {
@@ -91,6 +85,7 @@ const checkVerifyNum = (code) =&gt; { @@ -91,6 +85,7 @@ const checkVerifyNum = (code) =&gt; {
91 85
92 // change事件侦听 86 // change事件侦听
93 const change = (value) => { 87 const change = (value) => {
  88 + // console.log("value:", value);
94 } 89 }
95 90
96 // 输入完验证码最后一位执行 91 // 输入完验证码最后一位执行
@@ -115,6 +110,8 @@ const finish = (value) =&gt; { @@ -115,6 +110,8 @@ const finish = (value) =&gt; {
115 .key-input { 110 .key-input {
116 padding: 30rpx 0; 111 padding: 30rpx 0;
117 112
  113 + -webkit-user-select: text !important;
  114 +
118 text { 115 text {
119 display: none; 116 display: none;
120 } 117 }
garbage-removal/src/pages/login/index.vue
@@ -34,7 +34,7 @@ import { userLogin } from &quot;@/apis/user.js&quot;; @@ -34,7 +34,7 @@ import { userLogin } from &quot;@/apis/user.js&quot;;
34 export default { 34 export default {
35 data() { 35 data() {
36 return { 36 return {
37 - tel: '18980249160' 37 + tel: '18977778888'
38 } 38 }
39 }, 39 },
40 computed: { 40 computed: {
garbage-removal/src/pages/order/detail/index.vue
@@ -27,7 +27,6 @@ @@ -27,7 +27,6 @@
27 {{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }} 27 {{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}
28 </view> 28 </view>
29 </view> 29 </view>
30 -  
31 <view class="order-detail-container-header-item"> 30 <view class="order-detail-container-header-item">
32 <text class="order-detail-container-header-title">现场图片:</text> 31 <text class="order-detail-container-header-title">现场图片:</text>
33 <view class="order-detail-container-header-content"> 32 <view class="order-detail-container-header-content">
@@ -42,13 +41,19 @@ @@ -42,13 +41,19 @@
42 </view> 41 </view>
43 </view> 42 </view>
44 <view class="order-detail-container-header-item"> 43 <view class="order-detail-container-header-item">
  44 + <text class="order-detail-container-header-title">车辆类型:</text>
  45 + <view class="order-detail-container-header-content">
  46 + {{ dataGram.garOrderCarType }}
  47 + </view>
  48 + </view>
  49 + <view class="order-detail-container-header-item">
45 <text class="order-detail-container-header-title">垃圾类型:</text> 50 <text class="order-detail-container-header-title">垃圾类型:</text>
46 <view class="order-detail-container-header-content"> 51 <view class="order-detail-container-header-content">
47 {{ dataGram.garOrderTrashType }} 52 {{ dataGram.garOrderTrashType }}
48 </view> 53 </view>
49 </view> 54 </view>
50 <view class="order-detail-container-header-item"> 55 <view class="order-detail-container-header-item">
51 - <text class="order-detail-container-header-title">单号:</text> 56 + <text class="order-detail-container-header-title">单号:</text>
52 <view class="order-detail-container-header-content"> 57 <view class="order-detail-container-header-content">
53 {{ orderId }} 58 {{ orderId }}
54 </view> 59 </view>
@@ -75,7 +80,7 @@ @@ -75,7 +80,7 @@
75 <text class="order-detail-container-header-title">联系电话:</text> 80 <text class="order-detail-container-header-title">联系电话:</text>
76 <view class="order-detail-container-header-content"> 81 <view class="order-detail-container-header-content">
77 {{ dataGram.garOrderContactTel }} 82 {{ dataGram.garOrderContactTel }}
78 - <u-icon name="phone" size="28" @click="handleContactClick(dataGram.garOrderCompanyTel)"></u-icon> 83 + <u-icon name="phone" size="28" @click="handleContactClick(dataGram.garOrderContactTel)"></u-icon>
79 </view> 84 </view>
80 </view> 85 </view>
81 <view class="order-detail-container-header-item"> 86 <view class="order-detail-container-header-item">
@@ -96,35 +101,42 @@ @@ -96,35 +101,42 @@
96 <view class="order-detail-container-header-card-title"> 101 <view class="order-detail-container-header-card-title">
97 处理信息 102 处理信息
98 </view> 103 </view>
99 - <view class="order-detail-container-header-item">  
100 - <text class="order-detail-container-header-title">负责人:</text>  
101 - <view class="order-detail-container-header-content">  
102 - {{ dataGram.garOrderHandlerId }} 104 + <view v-if="dataGram.garOrderHandlerId" style="width: 100%;">
  105 + <view class="order-detail-container-header-item">
  106 + <text class="order-detail-container-header-title">负责人:</text>
  107 + <view class="order-detail-container-header-content">
  108 + {{ dataGram.garOrderHandleName }}
  109 + </view>
103 </view> 110 </view>
104 - </view>  
105 - <view class="order-detail-container-header-item">  
106 - <text class="order-detail-container-header-title">装车照片:</text>  
107 - <view class="order-detail-container-header-content">  
108 - <u-upload :fileList="putOnImages" name="3" multiple :maxCount="20" :previewFullImage="true"  
109 - :isReadOnly="true"></u-upload> 111 + <view class="order-detail-container-header-item">
  112 + <text class="order-detail-container-header-title">联系方式:</text>
  113 + <view class="order-detail-container-header-content">
  114 + {{ dataGram.garOrderHandleTel }}
  115 + </view>
110 </view> 116 </view>
111 - </view>  
112 - <view class="order-detail-container-header-item">  
113 - <text class="order-detail-container-header-title">卸车照片:</text>  
114 - <view class="order-detail-container-header-content">  
115 - <u-upload :fileList="putDownImages" name="3" multiple :maxCount="20" :previewFullImage="true"  
116 - :isReadOnly="true"></u-upload> 117 + <view class="order-detail-container-header-item">
  118 + <text class="order-detail-container-header-title">装车照片:</text>
  119 + <view class="order-detail-container-header-content">
  120 + <u-upload :fileList="putOnImages" name="3" multiple :maxCount="20" :previewFullImage="true"
  121 + :isReadOnly="true"></u-upload>
  122 + </view>
117 </view> 123 </view>
118 - </view>  
119 - <!-- <view class="order-detail-container-header-item">  
120 - <text class="order-detail-container-header-title">备注:</text>  
121 - <view class="order-detail-container-header-content">  
122 - {{ dataGram.garRemark }} 124 + <view class="order-detail-container-header-item">
  125 + <text class="order-detail-container-header-title">卸车照片:</text>
  126 + <view class="order-detail-container-header-content">
  127 + <u-upload :fileList="putDownImages" name="3" multiple :maxCount="20" :previewFullImage="true"
  128 + :isReadOnly="true"></u-upload>
  129 + </view>
123 </view> 130 </view>
124 - </view> --> 131 + </view>
  132 + <view v-else class="empty-image"
  133 + style="width: 100%; display: flex; justify-content: center; align-items: center;">
  134 + <image class="image-style" style="width: 200rpx; height: 200rpx;" :src="emptyBase64Image"></image>
  135 + </view>
125 </view> 136 </view>
126 </view> 137 </view>
127 - <view class="space-box"></view> 138 + <!-- 占位符 -->
  139 + <view class="space-box">{{ spaceStr }}</view>
128 <view class="order-detail-bottom"> 140 <view class="order-detail-bottom">
129 <view class="order-detail-bottom-box"> 141 <view class="order-detail-bottom-box">
130 <view class="order-detail-bottom-left"> 142 <view class="order-detail-bottom-left">
@@ -135,8 +147,8 @@ @@ -135,8 +147,8 @@
135 <view class="order-detail-bottom-right"> 147 <view class="order-detail-bottom-right">
136 <u-button @click="handleOrder(orderId)" v-if="dataGram.garOrderHandlerStatus == 0 && dataGram.handleFlag" 148 <u-button @click="handleOrder(orderId)" v-if="dataGram.garOrderHandlerStatus == 0 && dataGram.handleFlag"
137 shape="circle" color="#a9e08f" text="处理派单"></u-button> 149 shape="circle" color="#a9e08f" text="处理派单"></u-button>
138 - <u-button @click="handleUploadImage(orderId)" v-if="dataGram.garOrderHandlerStatus == 1" shape="circle"  
139 - color="#a9e08f" text="上传照片"></u-button> 150 + <u-button @click="handleUploadImage(orderId)" v-if="dataGram.garOrderHandlerStatus == 1 && dataGram.handleFlag"
  151 + shape="circle" color="#a9e08f" text="上传照片"></u-button>
140 <u-button @click="handleEvaluate(orderId)" v-if="dataGram.garEvaluateFlag == 0" shape="circle" color="#a9e08f" 152 <u-button @click="handleEvaluate(orderId)" v-if="dataGram.garEvaluateFlag == 0" shape="circle" color="#a9e08f"
141 text="去评价"></u-button> 153 text="去评价"></u-button>
142 </view> 154 </view>
@@ -147,6 +159,7 @@ @@ -147,6 +159,7 @@
147 159
148 <script setup> 160 <script setup>
149 import { queryOrderDetail, updateOrder } from "@/apis/order.js"; 161 import { queryOrderDetail, updateOrder } from "@/apis/order.js";
  162 +import zStatic from '@/components/z-paging/js/z-paging-static';
150 import { onLoad, onShow } from '@dcloudio/uni-app'; 163 import { onLoad, onShow } from '@dcloudio/uni-app';
151 import { ref } from 'vue'; 164 import { ref } from 'vue';
152 const dataGram = ref(); 165 const dataGram = ref();
@@ -154,11 +167,14 @@ const orderId = ref(null) @@ -154,11 +167,14 @@ const orderId = ref(null)
154 const currentImages = ref([]) 167 const currentImages = ref([])
155 const putOnImages = ref([]) 168 const putOnImages = ref([])
156 const putDownImages = ref([]) 169 const putDownImages = ref([])
  170 +const emptyBase64Image = ref(zStatic.base64Empty)
  171 +const spaceStr = ref("")
157 /** 172 /**
158 * 初始化信息 173 * 初始化信息
159 */ 174 */
160 onLoad((options) => { 175 onLoad((options) => {
161 orderId.value = options.orderId 176 orderId.value = options.orderId
  177 + console.log(emptyBase64Image.value);
162 }) 178 })
163 const handleOrderDetail = (orderId) => { 179 const handleOrderDetail = (orderId) => {
164 queryOrderDetail(orderId).then(res => { 180 queryOrderDetail(orderId).then(res => {
@@ -209,7 +225,7 @@ const handleEvaluate = (orderId) =&gt; [ @@ -209,7 +225,7 @@ const handleEvaluate = (orderId) =&gt; [
209 const handleOrder = (orderId) => { 225 const handleOrder = (orderId) => {
210 updateOrder({ garOrderId: orderId, handleType: 0 }).then(res => { 226 updateOrder({ garOrderId: orderId, handleType: 0 }).then(res => {
211 if (res.data.success) { 227 if (res.data.success) {
212 - uni.$u.toast("派单状态已被改变") 228 + uni.$u.toast(res.data.data)
213 handleOrderDetail(orderId) 229 handleOrderDetail(orderId)
214 } 230 }
215 }) 231 })
@@ -257,6 +273,7 @@ $custom-bottom-height: 200rpx; @@ -257,6 +273,7 @@ $custom-bottom-height: 200rpx;
257 background-color: $u-info-light; 273 background-color: $u-info-light;
258 box-sizing: border-box; 274 box-sizing: border-box;
259 overflow-y: scroll; 275 overflow-y: scroll;
  276 + background: linear-gradient(to bottom, $u-success-dark, $u-info-light, $u-info-light, $u-info-light);
260 277
261 278
262 .order-detail-container-box { 279 .order-detail-container-box {
@@ -264,7 +281,6 @@ $custom-bottom-height: 200rpx; @@ -264,7 +281,6 @@ $custom-bottom-height: 200rpx;
264 width: 100%; 281 width: 100%;
265 padding: $custom-page-padding; 282 padding: $custom-page-padding;
266 box-sizing: border-box; 283 box-sizing: border-box;
267 - background: linear-gradient(to bottom, $u-success-dark, $u-info-light, $u-info-light, $u-info-light);  
268 284
269 .order-detail-top { 285 .order-detail-top {
270 @include card(); 286 @include card();
@@ -312,6 +328,7 @@ $custom-bottom-height: 200rpx; @@ -312,6 +328,7 @@ $custom-bottom-height: 200rpx;
312 328
313 .space-box { 329 .space-box {
314 padding-bottom: $custom-bottom-height; 330 padding-bottom: $custom-bottom-height;
  331 + margin-bottom: 40rpx;
315 } 332 }
316 333
317 334
garbage-removal/src/pages/order/upload/index.vue
@@ -98,12 +98,25 @@ const handleSubmit = (id, type) =&gt; { @@ -98,12 +98,25 @@ const handleSubmit = (id, type) =&gt; {
98 } 98 }
99 99
100 const validateImage = () => { 100 const validateImage = () => {
  101 +
101 for (let index = 0; index < fileList.value.length; index++) { 102 for (let index = 0; index < fileList.value.length; index++) {
102 const str = fileList.value[index].url; 103 const str = fileList.value[index].url;
  104 + // #ifdef H5
103 if (str.startsWith("blob")) { 105 if (str.startsWith("blob")) {
104 return false; 106 return false;
105 } 107 }
  108 + // #endif
  109 +
  110 + // #ifdef MP-WEIXIN
  111 + if (uni.$u.test.contains(str, "/tmp/")) {
  112 + return false;
  113 + }
  114 + // #endif
  115 +
106 } 116 }
  117 + //
  118 + // #ifdef
  119 +
107 return true; 120 return true;
108 } 121 }
109 122
garbage-removal/src/pages/wode/index.vue
@@ -18,42 +18,61 @@ @@ -18,42 +18,61 @@
18 18
19 <view class="u-m-t-20"> 19 <view class="u-m-t-20">
20 <u-cell-group> 20 <u-cell-group>
21 - <u-cell icon="map" title="地址管理"></u-cell> 21 + <u-cell icon="map" @click="handleAddressManager" title="地址管理"></u-cell>
22 </u-cell-group> 22 </u-cell-group>
23 </view> 23 </view>
24 24
25 <view class="u-m-t-20"> 25 <view class="u-m-t-20">
26 - <u-cell-group> 26 + <!-- <u-cell-group>
27 <u-cell icon="star" title="收藏"></u-cell> 27 <u-cell icon="star" title="收藏"></u-cell>
28 <u-cell icon="photo" title="相册"></u-cell> 28 <u-cell icon="photo" title="相册"></u-cell>
29 <u-cell icon="coupon" title="卡券"></u-cell> 29 <u-cell icon="coupon" title="卡券"></u-cell>
30 <u-cell icon="heart" title="关注"></u-cell> 30 <u-cell icon="heart" title="关注"></u-cell>
31 - </u-cell-group> 31 + </u-cell-group> -->
32 </view> 32 </view>
33 33
34 - <view class="u-m-t-20"> 34 + <view class="u-m-t-40">
35 <u-cell-group> 35 <u-cell-group>
36 - <u-cell icon="setting" title="设置"></u-cell> 36 + <u-cell icon="setting" @click="handleLoginOut" title="退出登录"></u-cell>
37 </u-cell-group> 37 </u-cell-group>
38 </view> 38 </view>
39 </view> 39 </view>
40 </template> 40 </template>
41 41
42 -<script> 42 +<script setup>
  43 +import { loginOut } from "@/apis/user";
43 import headImg from "@/static/image/st_pic.png"; 44 import headImg from "@/static/image/st_pic.png";
44 -export default {  
45 - data() {  
46 - return {  
47 - pic: headImg,  
48 - show: true 45 +import { useMainStore } from "@/stores/index";
  46 +import { ref } from "vue";
  47 +const store = useMainStore();
  48 +const pic = ref(headImg)
  49 +const show = ref(true)
  50 +const handleAddressManager = () => {
  51 + uni.$u.route({
  52 + url: `pages/home/address/index`,
  53 + })
  54 +}
  55 +const handleLoginOut = () => {
  56 + uni.showModal({
  57 + title: '提示',
  58 + content: '确定要退出码',
  59 + success: function (res) {
  60 + if (res.confirm) {
  61 + loginOut().then(res => {
  62 + if (res.data.success) {
  63 + store.token = null;
  64 + uni.$u.toast("已退出")
  65 + uni.$u.route({
  66 + type: "reLaunch",
  67 + url: "pages/login/index"
  68 + })
  69 + }
  70 + })
  71 + } else if (res.cancel) {
  72 + console.log('用户点击取消');
  73 + }
49 } 74 }
50 - },  
51 - onLoad() {  
52 -  
53 - },  
54 - methods: {  
55 -  
56 - } 75 + });
57 } 76 }
58 </script> 77 </script>
59 78
garbage-removal/src/static/image/logo-1.png deleted 100644 → 0

3.93 KB

garbage-removal/src/static/image/logo.png deleted 100644 → 0

3.93 KB

garbage-removal/src/utils/request/request.js
@@ -95,7 +95,7 @@ const reSetLoginStatus = () =&gt; { @@ -95,7 +95,7 @@ const reSetLoginStatus = () =&gt; {
95 title: "登录已过期,请重新登录!", 95 title: "登录已过期,请重新登录!",
96 icon: "none", 96 icon: "none",
97 }); 97 });
98 - uni.navigateTo({ 98 + uni.reLaunch({
99 url: "/pages/login/index", 99 url: "/pages/login/index",
100 }) 100 })
101 return 101 return
garbage-removal/src/uview-plus/components/u-message-input/u-message-input.vue
1 <template> 1 <template>
2 <view class="u-char-box"> 2 <view class="u-char-box">
3 <view class="u-char-flex"> 3 <view class="u-char-flex">
4 - <input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength" class="u-input" @input="getVal"/> 4 + <input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength"
  5 + class="u-input" @input="getVal" />
5 <view v-for="(item, index) in loopCharArr" :key="index"> 6 <view v-for="(item, index) in loopCharArr" :key="index">
6 <view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item', 7 <view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
7 charArrLength === index && mode == 'box' ? 'u-box-active' : '', 8 charArrLength === index && mode == 'box' ? 'u-box-active' : '',
8 mode === 'box' ? 'u-box' : '']" :style="{ 9 mode === 'box' ? 'u-box' : '']" :style="{
9 - fontWeight: bold ? 'bold' : 'normal',  
10 - fontSize: fontSize + 'rpx',  
11 - width: width + 'rpx',  
12 - height: width + 'rpx',  
13 - color: inactiveColor,  
14 - borderColor: charArrLength === index && mode == 'box' ? activeColor : inactiveColor  
15 - }"> 10 + fontWeight: bold ? 'bold' : 'normal',
  11 + fontSize: fontSize + 'rpx',
  12 + width: width + 'rpx',
  13 + height: width + 'rpx',
  14 + color: inactiveColor,
  15 + borderColor: charArrLength === index && mode == 'box' ? activeColor : inactiveColor
  16 +}">
16 <view class="u-placeholder-line" :style="{ 17 <view class="u-placeholder-line" :style="{
17 - display: charArrLength === index ? 'block' : 'none',  
18 - height: width * 0.5 +'rpx'  
19 - }"  
20 - v-if="mode !== 'middleLine'"  
21 - ></view>  
22 - <view v-if="mode === 'middleLine' && charArrLength <= index" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-middle-line-active' : '']"  
23 - class="u-middle-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>  
24 - <view v-if="mode === 'bottomLine'" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-bottom-line-active' : '']"  
25 - class="u-bottom-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>  
26 - <block v-if="!dotFill"> {{ charArr[index] ? charArr[index] : ''}}</block> 18 + display: charArrLength === index ? 'block' : 'none',
  19 + height: width * 0.5 + 'rpx'
  20 + }" v-if="mode !== 'middleLine'"></view>
  21 + <view v-if="mode === 'middleLine' && charArrLength <= index"
  22 + :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-middle-line-active' : '']"
  23 + class="u-middle-line"
  24 + :style="{ height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor }">
  25 + </view>
  26 + <view v-if="mode === 'bottomLine'"
  27 + :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-bottom-line-active' : '']"
  28 + class="u-bottom-line"
  29 + :style="{ height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor }">
  30 + </view>
  31 + <block v-if="!dotFill"> {{ charArr[index] ? charArr[index] : '' }}</block>
27 <block v-else> 32 <block v-else>
28 - <text class="u-dot">{{ charArr[index] ? '●' : ''}}</text> 33 + <text class="u-dot">{{ charArr[index] ? '●' : '' }}</text>
29 </block> 34 </block>
30 </view> 35 </view>
31 </view> 36 </view>
@@ -34,285 +39,287 @@ @@ -34,285 +39,287 @@
34 </template> 39 </template>
35 40
36 <script> 41 <script>
37 - /**  
38 - * messageInput 验证码输入框  
39 - * @description 该组件一般用于验证用户短信验证码的场景,也可以结合uView的键盘组件使用  
40 - * @tutorial https://www.uviewui.com/components/messageInput.html  
41 - * @property {String Number} maxlength 输入字符个数(默认4)  
42 - * @property {Boolean} dot-fill 是否用圆点填充(默认false)  
43 - * @property {String} mode 模式选择,见上方"基本使用"说明(默认box)  
44 - * @property {String Number} value 预置值  
45 - * @property {Boolean} breathe 是否开启呼吸效果,见上方说明(默认true)  
46 - * @property {Boolean} focus 是否自动获取焦点(默认false)  
47 - * @property {Boolean} bold 字体和输入横线是否加粗(默认true)  
48 - * @property {String Number} font-size 字体大小,单位rpx(默认60)  
49 - * @property {String} active-color 当前激活输入框的样式(默认#2979ff)  
50 - * @property {String} inactive-color 非激活输入框的样式,文字颜色同此值(默认#606266)  
51 - * @property {String | Number} width 输入框宽度,单位rpx,高等于宽(默认80)  
52 - * @property {Boolean} disabled-keyboard 禁止点击输入框唤起系统键盘(默认false)  
53 - * @event {Function} change 输入内容发生改变时触发,具体见官网说明  
54 - * @event {Function} finish 输入字符个数达maxlength值时触发,见官网说明  
55 - * @example <u-message-input mode="bottomLine"></u-message-input>  
56 - */  
57 - export default {  
58 - name: "u-message-input",  
59 - props: {  
60 - // 最大输入长度  
61 - maxlength: {  
62 - type: [Number, String],  
63 - default: 4  
64 - },  
65 - // 是否用圆点填充  
66 - dotFill: {  
67 - type: Boolean,  
68 - default: false  
69 - },  
70 - // 显示模式,box-盒子模式,bottomLine-横线在底部模式,middleLine-横线在中部模式  
71 - mode: {  
72 - type: String,  
73 - default: "box"  
74 - },  
75 - // 预置值  
76 - modelValue: {  
77 - type: [String, Number],  
78 - default: ''  
79 - },  
80 - // 当前激活输入item,是否带有呼吸效果  
81 - breathe: {  
82 - type: Boolean,  
83 - default: true  
84 - },  
85 - // 是否自动获取焦点  
86 - focus: {  
87 - type: Boolean,  
88 - default: false  
89 - },  
90 - // 字体是否加粗  
91 - bold: {  
92 - type: Boolean,  
93 - default: false  
94 - },  
95 - // 字体大小  
96 - fontSize: {  
97 - type: [String, Number],  
98 - default: 60  
99 - },  
100 - // 激活样式  
101 - activeColor: {  
102 - type: String,  
103 - default: '#2979ff'  
104 - },  
105 - // 未激活的样式  
106 - inactiveColor: {  
107 - type: String,  
108 - default: '#606266'  
109 - },  
110 - // 输入框的大小,单位rpx,宽等于高  
111 - width: {  
112 - type: [Number, String],  
113 - default: '80'  
114 - },  
115 - // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true  
116 - disabledKeyboard: {  
117 - type: Boolean,  
118 - default: false  
119 - } 42 +/**
  43 + * messageInput 验证码输入框
  44 + * @description 该组件一般用于验证用户短信验证码的场景,也可以结合uView的键盘组件使用
  45 + * @tutorial https://www.uviewui.com/components/messageInput.html
  46 + * @property {String Number} maxlength 输入字符个数(默认4)
  47 + * @property {Boolean} dot-fill 是否用圆点填充(默认false)
  48 + * @property {String} mode 模式选择,见上方"基本使用"说明(默认box)
  49 + * @property {String Number} value 预置值
  50 + * @property {Boolean} breathe 是否开启呼吸效果,见上方说明(默认true)
  51 + * @property {Boolean} focus 是否自动获取焦点(默认false)
  52 + * @property {Boolean} bold 字体和输入横线是否加粗(默认true)
  53 + * @property {String Number} font-size 字体大小,单位rpx(默认60)
  54 + * @property {String} active-color 当前激活输入框的样式(默认#2979ff)
  55 + * @property {String} inactive-color 非激活输入框的样式,文字颜色同此值(默认#606266)
  56 + * @property {String | Number} width 输入框宽度,单位rpx,高等于宽(默认80)
  57 + * @property {Boolean} disabled-keyboard 禁止点击输入框唤起系统键盘(默认false)
  58 + * @event {Function} change 输入内容发生改变时触发,具体见官网说明
  59 + * @event {Function} finish 输入字符个数达maxlength值时触发,见官网说明
  60 + * @example <u-message-input mode="bottomLine"></u-message-input>
  61 + */
  62 +export default {
  63 + name: "u-message-input",
  64 + props: {
  65 + // 最大输入长度
  66 + maxlength: {
  67 + type: [Number, String],
  68 + default: 4
  69 + },
  70 + // 是否用圆点填充
  71 + dotFill: {
  72 + type: Boolean,
  73 + default: false
  74 + },
  75 + // 显示模式,box-盒子模式,bottomLine-横线在底部模式,middleLine-横线在中部模式
  76 + mode: {
  77 + type: String,
  78 + default: "box"
  79 + },
  80 + // 预置值
  81 + modelValue: {
  82 + type: [String, Number],
  83 + default: ''
  84 + },
  85 + // 当前激活输入item,是否带有呼吸效果
  86 + breathe: {
  87 + type: Boolean,
  88 + default: true
  89 + },
  90 + // 是否自动获取焦点
  91 + focus: {
  92 + type: Boolean,
  93 + default: false
  94 + },
  95 + // 字体是否加粗
  96 + bold: {
  97 + type: Boolean,
  98 + default: false
  99 + },
  100 + // 字体大小
  101 + fontSize: {
  102 + type: [String, Number],
  103 + default: 60
  104 + },
  105 + // 激活样式
  106 + activeColor: {
  107 + type: String,
  108 + default: '#2979ff'
120 }, 109 },
121 - watch: {  
122 - // maxlength: {  
123 - // // 此值设置为true,会在组件加载后无需maxlength变化就会执行一次本监听函数,无需再created生命周期中处理  
124 - // immediate: true,  
125 - // handler(val) {  
126 - // this.maxlength = Number(val);  
127 - // }  
128 - // },  
129 - modelValue: {  
130 - immediate: true,  
131 - handler(val) {  
132 - // 转为字符串  
133 - val = String(val);  
134 - // 超出部分截掉  
135 - this.valueModel = val.substring(0, this.maxlength);  
136 - }  
137 - }, 110 + // 未激活的样式
  111 + inactiveColor: {
  112 + type: String,
  113 + default: '#606266'
138 }, 114 },
139 - data() {  
140 - return {  
141 - valueModel: "" 115 + // 输入框的大小,单位rpx,宽等于高
  116 + width: {
  117 + type: [Number, String],
  118 + default: '80'
  119 + },
  120 + // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
  121 + disabledKeyboard: {
  122 + type: Boolean,
  123 + default: false
  124 + }
  125 + },
  126 + watch: {
  127 + // maxlength: {
  128 + // // 此值设置为true,会在组件加载后无需maxlength变化就会执行一次本监听函数,无需再created生命周期中处理
  129 + // immediate: true,
  130 + // handler(val) {
  131 + // this.maxlength = Number(val);
  132 + // }
  133 + // },
  134 + modelValue: {
  135 + immediate: true,
  136 + handler(val) {
  137 + // 转为字符串
  138 + val = String(val);
  139 + // 超出部分截掉
  140 + this.valueModel = val.substring(0, this.maxlength);
142 } 141 }
143 }, 142 },
144 - emits: ['change', 'finish'],  
145 - computed: {  
146 - // 是否显示呼吸灯效果  
147 - animationClass() {  
148 - return (index) => {  
149 - if (this.breathe && this.charArr.length == index) return 'u-breathe';  
150 - else return '';  
151 - }  
152 - },  
153 - // 用于显示字符  
154 - charArr() {  
155 - return this.valueModel.split('');  
156 - },  
157 - charArrLength() {  
158 - return this.charArr.length;  
159 - },  
160 - // 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for  
161 - loopCharArr() {  
162 - return new Array(this.maxlength); 143 + },
  144 + data() {
  145 + return {
  146 + valueModel: ""
  147 + }
  148 + },
  149 + emits: ['change', 'finish'],
  150 + computed: {
  151 + // 是否显示呼吸灯效果
  152 + animationClass() {
  153 + return (index) => {
  154 + if (this.breathe && this.charArr.length == index) return 'u-breathe';
  155 + else return '';
163 } 156 }
164 }, 157 },
165 - methods: {  
166 - getVal(e) {  
167 - let {  
168 - value  
169 - } = e.detail  
170 - this.valueModel = value;  
171 - // 判断长度是否超出了maxlength值,理论上不会发生,因为input组件设置了maxlength属性值  
172 - if (String(value).length > this.maxlength) return;  
173 - // 未达到maxlength之前,发送change事件,达到后发送finish事件  
174 - this.$emit('change', value);  
175 - if (String(value).length == this.maxlength) {  
176 - this.$emit('finish', value);  
177 - } 158 + // 用于显示字符
  159 + charArr() {
  160 + return this.valueModel.split('');
  161 + },
  162 + charArrLength() {
  163 + return this.charArr.length;
  164 + },
  165 + // 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
  166 + loopCharArr() {
  167 + return new Array(this.maxlength);
  168 + }
  169 + },
  170 + methods: {
  171 + getVal(e) {
  172 + let {
  173 + value
  174 + } = e.detail
  175 + this.valueModel = value;
  176 + // 判断长度是否超出了maxlength值,理论上不会发生,因为input组件设置了maxlength属性值
  177 + if (String(value).length > this.maxlength) return;
  178 + // 未达到maxlength之前,发送change事件,达到后发送finish事件
  179 + this.$emit('change', value);
  180 + if (String(value).length == this.maxlength) {
  181 + this.$emit('finish', value);
178 } 182 }
179 } 183 }
180 } 184 }
  185 +}
181 </script> 186 </script>
182 187
183 <style scoped lang="scss"> 188 <style scoped lang="scss">
184 - // 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错  
185 - @mixin vue-flex($direction: row) {  
186 - /* #ifndef APP-NVUE */  
187 - display: flex;  
188 - flex-direction: $direction;  
189 - /* #endif */  
190 - }  
191 -  
192 - @keyframes breathe {  
193 - 0% {  
194 - opacity: 0.3;  
195 - } 189 +// 定义混入指令,用于在非nvue环境下的flex定义,因为nvue没有display属性,会报错
  190 +@mixin vue-flex($direction: row) {
  191 + /* #ifndef APP-NVUE */
  192 + display: flex;
  193 + flex-direction: $direction;
  194 + /* #endif */
  195 +}
196 196
197 - 50% {  
198 - opacity: 1;  
199 - }  
200 -  
201 - 100% {  
202 - opacity: 0.3;  
203 - } 197 +@keyframes breathe {
  198 + 0% {
  199 + opacity: 0.3;
204 } 200 }
205 201
206 - .u-char-box {  
207 - text-align: center; 202 + 50% {
  203 + opacity: 1;
208 } 204 }
209 205
210 - .u-char-flex {  
211 - @include vue-flex;  
212 - justify-content: center;  
213 - flex-wrap: wrap;  
214 - position: relative; 206 + 100% {
  207 + opacity: 0.3;
215 } 208 }
  209 +}
216 210
217 - .u-input {  
218 - position: absolute;  
219 - top: 0;  
220 - left: -100%;  
221 - width: 200%;  
222 - height: 100%;  
223 - text-align: left;  
224 - z-index: 9;  
225 - opacity: 0;  
226 - background: none;  
227 - } 211 +.u-char-box {
  212 + text-align: center;
  213 +}
228 214
229 - .u-char-item {  
230 - position: relative;  
231 - width: 90rpx;  
232 - height: 90rpx;  
233 - margin: 10rpx 10rpx;  
234 - font-size: 60rpx;  
235 - font-weight: bold;  
236 - color: $u-main-color;  
237 - line-height: 90rpx;  
238 - @include vue-flex;  
239 - justify-content: center;  
240 - align-items: center;  
241 - } 215 +.u-char-flex {
  216 + @include vue-flex;
  217 + justify-content: center;
  218 + flex-wrap: wrap;
  219 + position: relative;
  220 + -webkit-user-select: text !important;
  221 +}
242 222
243 - .u-middle-line {  
244 - border: none;  
245 - } 223 +.u-input {
  224 + position: absolute;
  225 + top: 0;
  226 + left: -100%;
  227 + width: 200%;
  228 + height: 100%;
  229 + text-align: left;
  230 + z-index: 9;
  231 + opacity: 0;
  232 + background: none;
  233 + -webkit-user-select: text !important;
  234 +}
246 235
247 - .u-box {  
248 - box-sizing: border-box;  
249 - border: 2rpx solid #cccccc;  
250 - border-radius: 6rpx;  
251 - } 236 +.u-char-item {
  237 + position: relative;
  238 + width: 90rpx;
  239 + height: 90rpx;
  240 + margin: 10rpx 10rpx;
  241 + font-size: 60rpx;
  242 + font-weight: bold;
  243 + color: $u-main-color;
  244 + line-height: 90rpx;
  245 + @include vue-flex;
  246 + justify-content: center;
  247 + align-items: center;
  248 +}
252 249
253 - .u-box-active {  
254 - overflow: hidden;  
255 - animation-timing-function: ease-in-out;  
256 - animation-duration: 1500ms;  
257 - animation-iteration-count: infinite;  
258 - animation-direction: alternate;  
259 - border: 2rpx solid $u-primary;  
260 - } 250 +.u-middle-line {
  251 + border: none;
  252 +}
261 253
262 - .u-middle-line-active {  
263 - background: $u-primary;  
264 - } 254 +.u-box {
  255 + box-sizing: border-box;
  256 + border: 2rpx solid #cccccc;
  257 + border-radius: 6rpx;
  258 +}
265 259
266 - .u-breathe {  
267 - animation: breathe 2s infinite ease;  
268 - } 260 +.u-box-active {
  261 + overflow: hidden;
  262 + animation-timing-function: ease-in-out;
  263 + animation-duration: 1500ms;
  264 + animation-iteration-count: infinite;
  265 + animation-direction: alternate;
  266 + border: 2rpx solid $u-primary;
  267 +}
269 268
270 - .u-placeholder-line {  
271 - /* #ifndef APP-NVUE */  
272 - display: none;  
273 - /* #endif */  
274 - position: absolute;  
275 - left: 50%;  
276 - top: 50%;  
277 - transform: translate(-50%, -50%);  
278 - width: 2rpx;  
279 - height: 40rpx;  
280 - background: #333333;  
281 - animation: twinkling 1.5s infinite ease;  
282 - } 269 +.u-middle-line-active {
  270 + background: $u-primary;
  271 +}
283 272
284 - .u-animation-breathe {  
285 - animation-name: breathe;  
286 - } 273 +.u-breathe {
  274 + animation: breathe 2s infinite ease;
  275 +}
287 276
288 - .u-dot {  
289 - font-size: 34rpx;  
290 - line-height: 34rpx;  
291 - } 277 +.u-placeholder-line {
  278 + /* #ifndef APP-NVUE */
  279 + display: none;
  280 + /* #endif */
  281 + position: absolute;
  282 + left: 50%;
  283 + top: 50%;
  284 + transform: translate(-50%, -50%);
  285 + width: 2rpx;
  286 + height: 40rpx;
  287 + background: #333333;
  288 + animation: twinkling 1.5s infinite ease;
  289 +}
292 290
293 - .u-middle-line {  
294 - height: 4px;  
295 - background: #000000;  
296 - width: 80%;  
297 - position: absolute;  
298 - border-radius: 2px;  
299 - top: 50%;  
300 - left: 50%;  
301 - transform: translate(-50%, -50%);  
302 - } 291 +.u-animation-breathe {
  292 + animation-name: breathe;
  293 +}
303 294
304 - .u-bottom-line-active {  
305 - background: $u-primary;  
306 - } 295 +.u-dot {
  296 + font-size: 34rpx;
  297 + line-height: 34rpx;
  298 +}
307 299
308 - .u-bottom-line {  
309 - height: 4px;  
310 - background: #000000;  
311 - width: 80%;  
312 - position: absolute;  
313 - border-radius: 2px;  
314 - bottom: 0;  
315 - left: 50%;  
316 - transform: translate(-50%);  
317 - } 300 +.u-middle-line {
  301 + height: 4px;
  302 + background: #000000;
  303 + width: 80%;
  304 + position: absolute;
  305 + border-radius: 2px;
  306 + top: 50%;
  307 + left: 50%;
  308 + transform: translate(-50%, -50%);
  309 +}
  310 +
  311 +.u-bottom-line-active {
  312 + background: $u-primary;
  313 +}
  314 +
  315 +.u-bottom-line {
  316 + height: 4px;
  317 + background: #000000;
  318 + width: 80%;
  319 + position: absolute;
  320 + border-radius: 2px;
  321 + bottom: 0;
  322 + left: 50%;
  323 + transform: translate(-50%);
  324 +}
318 </style> 325 </style>