Commit 38584a8dede525a86b0322dada87c216a7b0a9ff
1 parent
6107e055
feat: 新增角色
Showing
35 changed files
with
2402 additions
and
937 deletions
garbage-removal/.env.production
garbage-removal/package-lock.json
| ... | ... | @@ -24,6 +24,7 @@ |
| 24 | 24 | "@dcloudio/uni-quickapp-webview": "3.0.0-3090620231104002", |
| 25 | 25 | "clipboard": "^2.0.11", |
| 26 | 26 | "dayjs": "^1.11.10", |
| 27 | + "js-md5": "^0.8.3", | |
| 27 | 28 | "pinia": "2.0.33", |
| 28 | 29 | "pinia-plugin-persist-uni": "^1.2.0", |
| 29 | 30 | "sass": "1.58.3", |
| ... | ... | @@ -8603,6 +8604,11 @@ |
| 8603 | 8604 | "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==", |
| 8604 | 8605 | "license": "BSD-3-Clause" |
| 8605 | 8606 | }, |
| 8607 | + "node_modules/js-md5": { | |
| 8608 | + "version": "0.8.3", | |
| 8609 | + "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz", | |
| 8610 | + "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==" | |
| 8611 | + }, | |
| 8606 | 8612 | "node_modules/js-tokens": { |
| 8607 | 8613 | "version": "4.0.0", |
| 8608 | 8614 | "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", | ... | ... |
garbage-removal/package.json
garbage-removal/src/apis/address.js
| ... | ... | @@ -2,7 +2,7 @@ import { request } from "@/utils/request"; |
| 2 | 2 | /** |
| 3 | 3 | * @method 新增用户地址 |
| 4 | 4 | */ |
| 5 | -export async function addAddress( params, config) { | |
| 5 | +export async function addAddress(params, config) { | |
| 6 | 6 | return await request.post( |
| 7 | 7 | `/user/save/address`, |
| 8 | 8 | params, |
| ... | ... | @@ -12,7 +12,7 @@ export async function addAddress( params, config) { |
| 12 | 12 | /** |
| 13 | 13 | * @method 获取用户地址 |
| 14 | 14 | */ |
| 15 | -export async function queryAddress( type) { | |
| 15 | +export async function queryAddress(type) { | |
| 16 | 16 | return await request.get( |
| 17 | 17 | `/user/query/address/${type}` |
| 18 | 18 | ); |
| ... | ... | @@ -20,8 +20,8 @@ export async function queryAddress( type) { |
| 20 | 20 | /** |
| 21 | 21 | * @method 编辑用户地址 |
| 22 | 22 | */ |
| 23 | -export async function updateAddress( params,config) { | |
| 24 | - return await request.post( | |
| 23 | +export async function updateAddress(params, config) { | |
| 24 | + return await request.post( | |
| 25 | 25 | `/user/update/address`, |
| 26 | 26 | params, |
| 27 | 27 | config |
| ... | ... | @@ -30,8 +30,8 @@ export async function updateAddress( params,config) { |
| 30 | 30 | /** |
| 31 | 31 | * @method 编辑用户地址 |
| 32 | 32 | */ |
| 33 | -export async function deleteAddress( id) { | |
| 34 | - return await request.delete( | |
| 33 | +export async function deleteAddress(id) { | |
| 34 | + return await request.delete( | |
| 35 | 35 | `/user/delete/address/${id}` |
| 36 | 36 | ); |
| 37 | 37 | } | ... | ... |
garbage-removal/src/main.js
| 1 | 1 | import uviewPlus from '@/uview-plus'; |
| 2 | +import md5 from 'js-md5'; | |
| 2 | 3 | import * as Pinia from 'pinia'; |
| 3 | 4 | import piniaPersistUni from "pinia-plugin-persist-uni"; |
| 4 | 5 | import { createSSRApp } from "vue"; |
| 5 | 6 | import mixin from './common/mixin'; |
| 7 | + | |
| 6 | 8 | // 引入uView对小程序分享的mixin封装 |
| 7 | 9 | import mpShare from '@/uview-plus/libs/mixin/mpShare.js'; |
| 8 | 10 | import App from "./App.vue"; |
| ... | ... | @@ -47,7 +49,7 @@ export function createApp() { |
| 47 | 49 | const app = createSSRApp(App); |
| 48 | 50 | const pinia = Pinia.createPinia() |
| 49 | 51 | app.use(uviewPlus) |
| 50 | - | |
| 52 | + // 配置uView | |
| 51 | 53 | // 调用setConfig方法,方法内部会进行对象属性深度合并,可以放心嵌套配置 |
| 52 | 54 | // 需要在app.use(uview-plus)之后执行 |
| 53 | 55 | uni.$u.setConfig({ |
| ... | ... | @@ -64,6 +66,7 @@ export function createApp() { |
| 64 | 66 | } |
| 65 | 67 | } |
| 66 | 68 | }) |
| 69 | + uni.$u.md5 = md5 | |
| 67 | 70 | pinia.use(piniaPersistUni); |
| 68 | 71 | app.use(pinia); |
| 69 | 72 | app.mixin(mpShare); | ... | ... |
garbage-removal/src/manifest.json
| ... | ... | @@ -51,7 +51,14 @@ |
| 51 | 51 | /* 小程序特有相关 */ |
| 52 | 52 | "mp-weixin" : { |
| 53 | 53 | "lazyCodeLoading" : "requiredComponents", |
| 54 | + "requiredPrivateInfos": ["getLocation", "chooseLocation"], | |
| 54 | 55 | "appid" : "wxc3f60667dc9d6cea", |
| 56 | + "permission":{ | |
| 57 | + "scope.userLocation":{ | |
| 58 | + "desc":"你的位置信息将用于小程序位置接口的" | |
| 59 | + } | |
| 60 | + }, | |
| 61 | + "libVersion": "latest", | |
| 55 | 62 | "setting" : { |
| 56 | 63 | "urlCheck" : false |
| 57 | 64 | }, | ... | ... |
garbage-removal/src/pages.json
| ... | ... | @@ -26,6 +26,13 @@ |
| 26 | 26 | } |
| 27 | 27 | }, |
| 28 | 28 | { |
| 29 | + "path": "pages/wode/choose/index", | |
| 30 | + "style": { | |
| 31 | + "navigationBarTitleText": "账户类型", | |
| 32 | + "enablePullDownRefresh": false | |
| 33 | + } | |
| 34 | + }, | |
| 35 | + { | |
| 29 | 36 | "path": "pages/login/index", |
| 30 | 37 | "style": { |
| 31 | 38 | "navigationBarTitleText": "装饰装修垃圾智慧功能模块登录", |
| ... | ... | @@ -38,12 +45,6 @@ |
| 38 | 45 | "enablePullDownRefresh": false |
| 39 | 46 | } |
| 40 | 47 | },{ |
| 41 | - "path": "pages/wode/choose/index", | |
| 42 | - "style": { | |
| 43 | - "navigationBarTitleText": "选择身份", | |
| 44 | - "enablePullDownRefresh": false | |
| 45 | - } | |
| 46 | - },{ | |
| 47 | 48 | "path": "pages/order/detail/index", |
| 48 | 49 | "style": { |
| 49 | 50 | "navigationBarTitleText": "派单详情", |
| ... | ... | @@ -123,6 +124,13 @@ |
| 123 | 124 | "navigationBarBackgroundColor":"#53c21d", |
| 124 | 125 | "enablePullDownRefresh": false |
| 125 | 126 | } |
| 127 | + }, | |
| 128 | + { | |
| 129 | + "path": "pages/home/search/index", | |
| 130 | + "style": { | |
| 131 | + "navigationBarTitleText": "公司搜索", | |
| 132 | + "enablePullDownRefresh": false | |
| 133 | + } | |
| 126 | 134 | },{ |
| 127 | 135 | "path": "pages/order/index", |
| 128 | 136 | "style": { | ... | ... |
garbage-removal/src/pages/home/address/addSite.vue
| ... | ... | @@ -2,29 +2,30 @@ |
| 2 | 2 | <view class="wrap"> |
| 3 | 3 | <view class="wrap-from-container"> |
| 4 | 4 | <city-select v-model="cityPikerShowFlag" @city-change="handleCityChange"></city-select> |
| 5 | - <u--form :labelStyle="{ color: '#909399' }" labelWidth="140" labelPosition="left" :model="addressInfo" | |
| 5 | + <u--form :labelStyle="{ color: '#303133' }" labelWidth="140" labelPosition="top" :model="addressInfo" | |
| 6 | 6 | ref="addressFrom"> |
| 7 | 7 | <u-form-item :required="true" label="所在地区" prop="addressArea" borderBottom> |
| 8 | 8 | <view @click.stop="showRegionPicker" hover-class="click-box" style="width: 100%;"> |
| 9 | 9 | <u--input border="none" readonly style="pointer-events:none" type="text" v-model="addressInfo.addressArea" |
| 10 | - placeholder-class="line" placeholder="省市区县、乡镇等"></u--input> | |
| 10 | + placeholder-class="line" placeholder="请选着所在地区"></u--input> | |
| 11 | 11 | </view> |
| 12 | 12 | </u-form-item> |
| 13 | 13 | <u-form-item :required="true" label="详细地址" prop="addressDetail" borderBottom> |
| 14 | 14 | <view @click.stop="chooseAddressDetail" class="wrap-from-container-address-details" |
| 15 | - style="width: 100%;overflow:hidden; text-overflow: ellipsis;" hover-class="click-box"> | |
| 16 | - <u--input border="none" readonly type="text" style="pointer-events:none" v-model="addressInfo.addressDetail" | |
| 17 | - placeholder-class="line" placeholder="请选着所在地址" suffixIcon="map-fill" | |
| 18 | - suffixIconStyle="font-size: 28rpx;color: #909399"></u--input> | |
| 15 | + style="color:#606266;font-size: 28rpx;width: 100%;" hover-class="click-box"> | |
| 16 | + <view style="pointer-events: none; width: 100%;"> | |
| 17 | + <up-textarea :disabled="true" color="#606266" border="none" autoHeight style="pointer-events:none" | |
| 18 | + v-model="addressInfo.addressDetail" placeholder="请选择详细地址"></up-textarea> | |
| 19 | + </view> | |
| 19 | 20 | </view> |
| 20 | 21 | </u-form-item> |
| 21 | 22 | <u-form-item :required="true" label="联系人" prop="contactPerson" borderBottom> |
| 22 | - <u--input border="none" type="text" v-model="addressInfo.contactPerson" placeholder-class="line" | |
| 23 | - placeholder="联系人"></u--input> | |
| 23 | + <u--input color="#606266" border="none" type="text" v-model="addressInfo.contactPerson" | |
| 24 | + placeholder-class="line" placeholder="联系人"></u--input> | |
| 24 | 25 | </u-form-item> |
| 25 | 26 | <u-form-item :required="true" label="联系电话" prop="contactIphoneNumber" borderBottom> |
| 26 | - <u--input border="none" type="text" v-model="addressInfo.contactIphoneNumber" placeholder-class="line" | |
| 27 | - placeholder="联系电话"></u--input> | |
| 27 | + <u--input color="#606266" border="none" type="text" v-model="addressInfo.contactIphoneNumber" | |
| 28 | + placeholder-class="line" placeholder="联系电话"></u--input> | |
| 28 | 29 | </u-form-item> |
| 29 | 30 | </u--form> |
| 30 | 31 | </view> |
| ... | ... | @@ -103,7 +104,6 @@ const showRegionPicker = () => { |
| 103 | 104 | } |
| 104 | 105 | |
| 105 | 106 | const handleCityChange = (e) => { |
| 106 | - console.log(e); | |
| 107 | 107 | addressInfo.addressArea = e.province.label + '-' + e.city.label + '-' + e.area.label; |
| 108 | 108 | } |
| 109 | 109 | |
| ... | ... | @@ -165,6 +165,7 @@ const submit = () => { |
| 165 | 165 | * 打开地图选择地址 |
| 166 | 166 | */ |
| 167 | 167 | const chooseAddressDetail = () => { |
| 168 | + console.log('打开地图选择地址'); | |
| 168 | 169 | let coordinate = 'gcj02'; |
| 169 | 170 | uni.chooseLocation({ |
| 170 | 171 | type: coordinate, |
| ... | ... | @@ -174,7 +175,28 @@ const chooseAddressDetail = () => { |
| 174 | 175 | addressInfo.garLongitude = res.longitude |
| 175 | 176 | addressInfo.garLatitude = res.latitude |
| 176 | 177 | addressInfo.garCoordinate = coordinate |
| 178 | + // #ifdef MP-WEIXIN | |
| 179 | + let SecretKey = "DsNi4Hug4POlYLJ8AaloKB6Uob5fvL8l"; | |
| 180 | + let key = "HNEBZ-PWHLR-M5AWP-WMRT3-XEOHJ-Y2BHY"; | |
| 181 | + let md5Param = `/ws/geocoder/v1/?key=${key}&location=${res.latitude},${res.longitude}`; | |
| 182 | + let locApi = `https://apis.map.qq.com` | |
| 183 | + let sig = uni.$u.md5(md5Param + SecretKey) | |
| 184 | + uni.request({ | |
| 185 | + url: locApi + md5Param + "&sig=" + sig, | |
| 186 | + method: 'GET', | |
| 187 | + success: (res) => { | |
| 188 | + let component = res.data.result.address_component; | |
| 189 | + if (component.province == "湖南省") { | |
| 190 | + addressInfo.addressDetail = addressInfo.addressDetail.replace(component.province + component.city + component.district, "") | |
| 191 | + addressInfo.addressArea = component.province + '-' + component.city + '-' + component.district; | |
| 192 | + } | |
| 193 | + } | |
| 194 | + }); | |
| 195 | + // #endif | |
| 177 | 196 | } |
| 197 | + }, | |
| 198 | + fail: function (res) { | |
| 199 | + console.log(res); | |
| 178 | 200 | } |
| 179 | 201 | }); |
| 180 | 202 | } |
| ... | ... | @@ -211,8 +233,10 @@ const reset = () => { |
| 211 | 233 | </script> |
| 212 | 234 | |
| 213 | 235 | <style lang="scss" scoped> |
| 214 | -::v-deep .u-input--square { | |
| 215 | - // width: 100%; | |
| 236 | +::v-deep .u-textarea { | |
| 237 | + width: 100%; | |
| 238 | + padding: 0px !important; | |
| 239 | + background: white !important; | |
| 216 | 240 | } |
| 217 | 241 | |
| 218 | 242 | .wrap { | ... | ... |
garbage-removal/src/pages/home/address/index.vue
| ... | ... | @@ -58,7 +58,10 @@ const handleClickChangeCurrentAddress = (res) => { |
| 58 | 58 | contactIphoneNumber: res.garUserContactTel, |
| 59 | 59 | defaultFlag: true, |
| 60 | 60 | addressDetail: res.garRemark, |
| 61 | - garAddressId: res.garAddressId | |
| 61 | + garAddressId: res.garAddressId, | |
| 62 | + garLongitude: res.garLongitude, | |
| 63 | + garLatitude: res.garLatitude, | |
| 64 | + garCoordinate: res.garCoordinate | |
| 62 | 65 | }).then(res => { |
| 63 | 66 | getData(); |
| 64 | 67 | uni.$u.toast(res.data.msg) | ... | ... |
garbage-removal/src/pages/home/clean/company-detail/index.vue
| ... | ... | @@ -11,7 +11,12 @@ |
| 11 | 11 | {{ headerData.name }} |
| 12 | 12 | </view> |
| 13 | 13 | <view class="company-content-right-area"> |
| 14 | - 注册区划:{{ headerData.registrationArea }} | |
| 14 | + <view class="company-content-right-address"> | |
| 15 | + 注册区划:{{ headerData.registrationArea }} | |
| 16 | + </view> | |
| 17 | + <view class="company-content-right-button" @click="handlerClickJumpMap"> | |
| 18 | + 一键导航 | |
| 19 | + </view> | |
| 15 | 20 | </view> |
| 16 | 21 | </view> |
| 17 | 22 | </view> |
| ... | ... | @@ -27,7 +32,7 @@ |
| 27 | 32 | <view v-if="item.label != '道路运输许可证'" class="company-content-base-data-info-item-txt"> |
| 28 | 33 | {{ item.value }} |
| 29 | 34 | </view> |
| 30 | - <view v-else class="company-content-base-data-info-item-txt"> | |
| 35 | + <view v-else-if="item.value" class="company-content-base-data-info-item-txt"> | |
| 31 | 36 | <u-upload :fileList="[item.value]" name="3" multiple :maxCount="10" :previewFullImage="true" |
| 32 | 37 | :isReadOnly="true"></u-upload> |
| 33 | 38 | </view> |
| ... | ... | @@ -139,6 +144,25 @@ const handleCleanGarbage = (companyObj, tel, userAddress) => { |
| 139 | 144 | url: `pages/home/clean/index?companyObj=${JSON.stringify(companyObj)}&tel=${tel}&userAddress=${JSON.stringify(userAddress)}`, |
| 140 | 145 | }) |
| 141 | 146 | } |
| 147 | +const handlerClickJumpMap = () => { | |
| 148 | + const gps = companyInfo.value.officeAddressGps.split(',') | |
| 149 | + uni.showModal({ | |
| 150 | + title: '提示', | |
| 151 | + content: '是否跳转到app定位进行导航?', | |
| 152 | + success: function (res) { | |
| 153 | + if (res.confirm) { | |
| 154 | + uni.openLocation({ | |
| 155 | + latitude: Number(gps[1]), | |
| 156 | + longitude: Number(gps[0]), | |
| 157 | + success: function () { | |
| 158 | + console.log('success'); | |
| 159 | + } | |
| 160 | + }); | |
| 161 | + } | |
| 162 | + } | |
| 163 | + }) | |
| 164 | + console.log('跳转定位到公司位置'); | |
| 165 | +} | |
| 142 | 166 | |
| 143 | 167 | const initData = (baseData) => { |
| 144 | 168 | baseDataList.value[0].value = baseData.legalRepresentative |
| ... | ... | @@ -221,6 +245,21 @@ $custom-bottom-height: 200rpx; |
| 221 | 245 | .company-content-right-area { |
| 222 | 246 | font-size: 25rpx; |
| 223 | 247 | color: $u-info; |
| 248 | + display: flex; | |
| 249 | + justify-content: space-between; | |
| 250 | + align-items: center; | |
| 251 | + | |
| 252 | + .company-content-right-button { | |
| 253 | + padding: 10rpx 15rpx; | |
| 254 | + background: #19be6b; | |
| 255 | + box-sizing: border-box; | |
| 256 | + border-radius: 20rpx; | |
| 257 | + font-size: 18rpx; | |
| 258 | + color: #ffffff; | |
| 259 | + display: flex; | |
| 260 | + justify-content: center; | |
| 261 | + align-items: center; | |
| 262 | + } | |
| 224 | 263 | } |
| 225 | 264 | } |
| 226 | 265 | ... | ... |
garbage-removal/src/pages/home/clean/index-back.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="mask-box"> | |
| 3 | + <liu-delivery-time :isMask="true" :change="changeTime" ref="chooseTime" title="请选择预约时间"></liu-delivery-time> | |
| 4 | + <u-picker closeOnClickOverlay :show="carTypeShowFlag" :columns="candidates" :itemHeight="100" | |
| 5 | + @confirm="handlePickerCarInfoConfirm" @cancel="handleCarInfoClick(false)" | |
| 6 | + @close="handleCarInfoClick(false)"></u-picker> | |
| 7 | + <u-picker closeOnClickOverlay :show="garbageTypeShowFlag" :columns="garbageTypeList" :itemHeight="100" | |
| 8 | + @confirm="handlePickerGarbageTypeConfirm" @close="handleGarbageTypeClick(false)" | |
| 9 | + @cancel="handleGarbageTypeClick(false)"></u-picker> | |
| 10 | + <u-popup :zIndex="10074" closeOnClickOverlay :show="carPopupShowFlag" :round="10" @close="handlePopupClick(false)" | |
| 11 | + @open="handlePopupClick(true)"> | |
| 12 | + <view class="company-clean-container-car-popup"> | |
| 13 | + <!-- 主要内容 --> | |
| 14 | + <view class="company-clean-container-car-popup-content"> | |
| 15 | + <view class="company-clean-container-car-popup-content-title"> | |
| 16 | + <view style="text-align: center;"> | |
| 17 | + 车辆类型 | |
| 18 | + </view> | |
| 19 | + </view> | |
| 20 | + <view class="company-clean-container-car-popup-content-box"> | |
| 21 | + <view class="company-clean-container-car-popup-content-box-item" v-for="(item, index) in garCarInfoList" | |
| 22 | + :key="index"> | |
| 23 | + <view class="company-clean-container-car-popup-content-box-item-text"> | |
| 24 | + {{ item.garOrderCarType }} | |
| 25 | + </view> | |
| 26 | + <view class="company-clean-container-car-popup-content-box-item-number" hover-class="hoverClickStyle"> | |
| 27 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 28 | + v-model="garCarInfoList[item.garOrderCarType].garOrderCarNumber" :disabledInput="true"></u-number-box> | |
| 29 | + </view> | |
| 30 | + </view> | |
| 31 | + | |
| 32 | + </view> | |
| 33 | + </view> | |
| 34 | + <!-- 占位盒子 --> | |
| 35 | + <view class="company-clean-container-car-popup-button-safe"> | |
| 36 | + | |
| 37 | + </view> | |
| 38 | + </view> | |
| 39 | + </u-popup> | |
| 40 | + </view> | |
| 41 | + <view class="company-clean-container"> | |
| 42 | + <view class="company-clean-container-box"> | |
| 43 | + <view class="company-clean-container-header"> | |
| 44 | + <view class="company-clean-container-header-address"> | |
| 45 | + {{ userAddress.garUserAddress }}{{ userAddress.garRemark }} | |
| 46 | + </view> | |
| 47 | + <view class="company-clean-container-header-base-info"> | |
| 48 | + {{ userAddress.garUserContactName }} {{ userAddress.garUserContactTel }} | |
| 49 | + </view> | |
| 50 | + <view @click.stop="handleTimeChoose" class="company-clean-container-header-reservation"> | |
| 51 | + <view class="company-clean-container-header-reservation-left"> | |
| 52 | + <text style="color: red;">*</text> <u-icon name="calendar" size="40"></u-icon>预约时间 | |
| 53 | + </view> | |
| 54 | + <view class="company-clean-container-header-reservation-right"> | |
| 55 | + <text style="margin-right: 10rpx;">{{ dayTime ? dayTime : "请选择时间" }}</text> <u-icon name="arrow-right" | |
| 56 | + size="25"></u-icon> | |
| 57 | + </view> | |
| 58 | + </view> | |
| 59 | + </view> | |
| 60 | + <view class="company-clean-container-car-main"> | |
| 61 | + <view class="company-clean-container-car-main-content"> | |
| 62 | + <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-type"> | |
| 63 | + <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 64 | + style="color: red;">*</text>车辆类型:</text> | |
| 65 | + <!-- <uni-combox label="" :candidates="candidates" placeholder="请选择运输车辆类型" | |
| 66 | + v-model="paramFrom.carType"></uni-combox> --> | |
| 67 | + <view class="" hover-class="hoverClickStyle" @click.stop="handleCarInfoClick(true)"> | |
| 68 | + <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.carType" | |
| 69 | + type="text" placeholder-class="line" readonly /> | |
| 70 | + </view> | |
| 71 | + </view> | |
| 72 | + <view class="company-clean-container-car-main-content-type"> | |
| 73 | + <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 74 | + style="color: red;">*</text>垃圾类型:</text> | |
| 75 | + <view hover-class="hoverClickStyle" @click.stop="handleGarbageTypeClick(true)"> | |
| 76 | + <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.garbageType" | |
| 77 | + type="text" placeholder-class="line" readonly /> | |
| 78 | + </view> | |
| 79 | + </view> | |
| 80 | + <view class="company-clean-container-car-main-content-img"> | |
| 81 | + <image class="company-clean-container-car-main-content-img" :src="carFront" /> | |
| 82 | + </view> | |
| 83 | + <view class="company-clean-container-car-main-content-remark"> | |
| 84 | + {{ garCarTransportInfo }} | |
| 85 | + </view> | |
| 86 | + | |
| 87 | + <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-number"> | |
| 88 | + <view class="company-clean-container-car-main-content-number-txt"> | |
| 89 | + <text style="color: red;">*</text>协商车辆数量: | |
| 90 | + </view> | |
| 91 | + <view class="company-clean-container-car-main-content-number-button"> | |
| 92 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 93 | + v-model="garCarInfoList[paramFrom.carType].garOrderCarNumber"></u-number-box> | |
| 94 | + </view> | |
| 95 | + </view> | |
| 96 | + <view class="company-clean-container-car-main-content-prompt"> | |
| 97 | + 温馨提示:垃圾类型不符合,企业有权拒绝清运。 | |
| 98 | + </view> | |
| 99 | + </view> | |
| 100 | + </view> | |
| 101 | + <view class="company-clean-container-site-image-info"> | |
| 102 | + <view class="company-clean-container-site-image-info-remark"> | |
| 103 | + <text style="color: red;">*</text>现场照片(最多上传10张) | |
| 104 | + </view> | |
| 105 | + <view class="company-clean-container-site-image-info-img"> | |
| 106 | + <u-upload width="200" height="150" :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" | |
| 107 | + multiple :maxCount="10" :previewFullImage="true"></u-upload> | |
| 108 | + </view> | |
| 109 | + <view class="company-clean-container-site-image-info-input-remark"> | |
| 110 | + 填写备注 | |
| 111 | + </view> | |
| 112 | + <view class="company-clean-container-site-image-info-input-remark-box"> | |
| 113 | + <u--textarea v-model="paramFrom.remark" placeholder="请输入内容"></u--textarea> | |
| 114 | + </view> | |
| 115 | + </view> | |
| 116 | + <view class="company-clean-container-site-image-info-sure-button"> | |
| 117 | + <view class="company-clean-container-site-image-info-sure-button-radio"> | |
| 118 | + <view @click="changeAgree"> | |
| 119 | + <u-checkbox-group v-model="paramFrom.sureReadFlag" placement="row"> | |
| 120 | + <u-checkbox activeColor="#5ac725" :customStyle="{ marginBottom: '0px', marginTop: '1px' }" size="25" | |
| 121 | + labelSize="25" shape="square" :key="0" :name="true" :labelDisabled="true" | |
| 122 | + labelColor="#909399"></u-checkbox> | |
| 123 | + </u-checkbox-group> | |
| 124 | + </view> | |
| 125 | + <view> | |
| 126 | + 本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。 | |
| 127 | + </view> | |
| 128 | + </view> | |
| 129 | + </view> | |
| 130 | + </view> | |
| 131 | + <view class="company-clean-bottom" style="z-index: 10074;"> | |
| 132 | + <movable-area v-if="!carPopupShowFlag" ref="movableAreaElement" class="movableArea"> | |
| 133 | + <movable-view class="movableView" :x="x" :y="y" direction="all" @change="onChange"> | |
| 134 | + <view class="company-clean-call-box-container"> | |
| 135 | + <u-icon @click="handleContactClick(tel)" name="phone-fill" color="#ffffff" size="50"></u-icon> | |
| 136 | + </view> | |
| 137 | + </movable-view> | |
| 138 | + </movable-area> | |
| 139 | + <view class="company-clean-bottom-box"> | |
| 140 | + <view class="company-clean-bottom-left"> | |
| 141 | + <view class="company-clean-bottom-left-icon"> | |
| 142 | + <u-icon @click="carPopupShowFlag = true" :stop="true" size="50" name="car-fill"></u-icon> | |
| 143 | + </view> | |
| 144 | + <view class="company-clean-bottom-left-number"> | |
| 145 | + <up-badge :type="type" max="99" :value="garCarNumberCount"></up-badge> | |
| 146 | + </view> | |
| 147 | + </view> | |
| 148 | + <view class="company-clean-bottom-right"> | |
| 149 | + <u-button @click="handleOderSure" shape="square" color="#a9e08f" text="立即派单"></u-button> | |
| 150 | + </view> | |
| 151 | + </view> | |
| 152 | + </view> | |
| 153 | + </view> | |
| 154 | +</template> | |
| 155 | + | |
| 156 | +<script setup> | |
| 157 | +import { queryCarList } from '@/apis/carinfo.js'; | |
| 158 | +import { uploadFilePromise } from '@/apis/common.js'; | |
| 159 | +import { saveOrder } from '@/apis/order.js'; | |
| 160 | +import liuDeliveryTime from "@/components/liu-delivery-time/liu-delivery-time.vue"; | |
| 161 | +import { useMainStore } from '@/stores/index.js'; | |
| 162 | +import { onLoad } from '@dcloudio/uni-app'; | |
| 163 | +import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue'; | |
| 164 | +const { proxy } = getCurrentInstance(); | |
| 165 | + | |
| 166 | +const store = useMainStore(); | |
| 167 | +const userType = computed(() => store.userType) | |
| 168 | +const x = ref(5) | |
| 169 | +const y = ref() | |
| 170 | +const movableAreaElement = ref() | |
| 171 | +const companyObj = ref() | |
| 172 | +const tel = ref() | |
| 173 | +const carTypeShowFlag = ref(false) | |
| 174 | +const garbageTypeShowFlag = ref(false) | |
| 175 | +const carPopupShowFlag = ref(false) | |
| 176 | +const userAddress = ref({ | |
| 177 | + garUserContactName: "", | |
| 178 | + garUserContactTel: "", | |
| 179 | + garRemark: "", | |
| 180 | + garUserAddress: "", | |
| 181 | + garCoordinate: "", | |
| 182 | + garLongitude: "", | |
| 183 | + garLatitude: "", | |
| 184 | +}) | |
| 185 | +// 车辆信息 | |
| 186 | +const garCarInfoList = ref({}) | |
| 187 | +const garCarLabelInfoList = ref({}) | |
| 188 | +const garCarLabelInfoNow = ref() | |
| 189 | +const garCarTransportInfo = computed(() => { | |
| 190 | + try { | |
| 191 | + let carInfo = garCarLabelInfoNow.value | |
| 192 | + let lengthWidthHeight = carInfo.lengthWidthHeight.split(";"); | |
| 193 | + let boxLength = lengthWidthHeight[0]; // 箱子的长度(单位:米) | |
| 194 | + let boxWidth = lengthWidthHeight[1]; // 箱子的宽度(单位:米) | |
| 195 | + let boxHeight = lengthWidthHeight[2]; // 箱子的高度(单位:米) | |
| 196 | + | |
| 197 | + let bagLength = 0.75; // 袋子的长度(单位:米) | |
| 198 | + let bagWidth = 0.45; // 袋子的宽度(单位:米) | |
| 199 | + let bagHeight = 0.22; // 袋子的高度(单位:米) | |
| 200 | + | |
| 201 | + let boxVolume = boxLength * boxWidth * boxHeight; // 箱子的体积(单位:立方米) | |
| 202 | + let bagVolume = bagLength * bagWidth * bagHeight; // 袋子的体积(单位:立方米) | |
| 203 | + | |
| 204 | + let bagCount = Math.floor(boxVolume / bagVolume); // 箱子可以容纳的袋子数量(向下取整) | |
| 205 | + | |
| 206 | + return `箱体长${boxLength}m宽${boxWidth}m高${boxHeight}m,最多课容纳约${bagCount}袋袋装修垃圾(75cm * 45cm每袋)。` | |
| 207 | + } catch (error) { | |
| 208 | + return "符合装修垃圾运输管理规范的新型环保智能装修垃圾运输车。" | |
| 209 | + } | |
| 210 | + | |
| 211 | +}) | |
| 212 | +// 车辆数量 | |
| 213 | +const garCarNumberCount = computed(() => { | |
| 214 | + let count = 0; | |
| 215 | + if (garCarInfoList.value) { | |
| 216 | + for (const key in garCarInfoList.value) { | |
| 217 | + const element = garCarInfoList.value[key]; | |
| 218 | + count = typeof element.garOrderCarNumber === 'number' ? count + element.garOrderCarNumber : count; | |
| 219 | + console.log(element.garOrderCarNumber instanceof Number); | |
| 220 | + } | |
| 221 | + } | |
| 222 | + console.log(count); | |
| 223 | + return count; | |
| 224 | +}) | |
| 225 | +const garbageTypeList = ref([["装修垃圾", "建筑垃圾"]]) | |
| 226 | +const paramFrom = ref({ | |
| 227 | + carNumber: 0, | |
| 228 | + remark: "", | |
| 229 | + sureReadFlag: [], | |
| 230 | + carType: "", | |
| 231 | + garbageType: "装修垃圾" | |
| 232 | +}) | |
| 233 | +const dayTime = ref() | |
| 234 | + | |
| 235 | +const chooseTime = ref() | |
| 236 | +const fileList = ref([]) | |
| 237 | +const candidates = ref([]) | |
| 238 | +const handleTimeChoose = () => { | |
| 239 | + chooseTime.value.open(); | |
| 240 | +} | |
| 241 | + | |
| 242 | +const changeTime = (e) => { | |
| 243 | + dayTime.value = e.value | |
| 244 | +} | |
| 245 | +const changeAgree = (e) => { | |
| 246 | + // paramFrom.value.sureReadFlag = e | |
| 247 | + paramFrom.value.sureReadFlag[0] = !paramFrom.value.sureReadFlag[0] | |
| 248 | +} | |
| 249 | +const onChange = (e) => { | |
| 250 | + // console.log(e); | |
| 251 | +} | |
| 252 | + | |
| 253 | +const handlePopupClick = (val) => { | |
| 254 | + carPopupShowFlag.value = val | |
| 255 | +} | |
| 256 | + | |
| 257 | +/** | |
| 258 | + * 初始化信息 | |
| 259 | + */ | |
| 260 | +onLoad((options) => { | |
| 261 | + companyObj.value = JSON.parse(options.companyObj); | |
| 262 | + tel.value = options.tel; | |
| 263 | + userAddress.value = JSON.parse(options.userAddress); | |
| 264 | + queryCarList({ companyId: companyObj.value.id }).then(res => { | |
| 265 | + // 设置车辆类型 | |
| 266 | + candidates.value = [[...new Set(res.data.rows | |
| 267 | + .filter(item => item.containerVolume) | |
| 268 | + .map(item => { | |
| 269 | + garCarLabelInfoList.value[item.containerVolume + "方车"] = item | |
| 270 | + return item.containerVolume + "方车" | |
| 271 | + })) | |
| 272 | + ]]; | |
| 273 | + // 设置初始车辆数量 | |
| 274 | + candidates.value[0].forEach((item, index) => { | |
| 275 | + garCarInfoList.value[item] = { | |
| 276 | + garOrderCarNumber: 0, | |
| 277 | + garOrderCarType: item | |
| 278 | + } | |
| 279 | + }) | |
| 280 | + // 设置默认车辆 | |
| 281 | + paramFrom.value.carType = candidates.value[0][0]; | |
| 282 | + garCarLabelInfoNow.value = garCarLabelInfoList.value[paramFrom.value.carType] | |
| 283 | + }) | |
| 284 | +}) | |
| 285 | + | |
| 286 | + | |
| 287 | +const handleCarInfoClick = (val) => { | |
| 288 | + carTypeShowFlag.value = val | |
| 289 | +} | |
| 290 | +const handleGarbageTypeClick = (val) => { | |
| 291 | + garbageTypeShowFlag.value = val | |
| 292 | +} | |
| 293 | +/** | |
| 294 | + * 拨打电话回调 | |
| 295 | + */ | |
| 296 | +const handleContactClick = (val) => { | |
| 297 | + uni.makePhoneCall({ phoneNumber: val }).then(res => { | |
| 298 | + }).catch(err => { }); | |
| 299 | +} | |
| 300 | + | |
| 301 | +// 删除图片 | |
| 302 | +const deletePic = (event) => { | |
| 303 | + fileList.value.splice(event.index, 1); | |
| 304 | +}; | |
| 305 | + | |
| 306 | +// 新增图片 | |
| 307 | +const afterRead = async (event) => { | |
| 308 | + // 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式 | |
| 309 | + let lists = [].concat(event.file); | |
| 310 | + let fileListLen = fileList.value.length; | |
| 311 | + lists.map((item) => { | |
| 312 | + fileList.value.push({ | |
| 313 | + ...item, | |
| 314 | + status: 'uploading', | |
| 315 | + message: '上传中', | |
| 316 | + }); | |
| 317 | + }); | |
| 318 | + for (let i = 0; i < lists.length; i++) { | |
| 319 | + let requestPath = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_BASE_FILE_UPLOAD_PREFIX; | |
| 320 | + const result = await uploadFilePromise(requestPath, lists[i].url); | |
| 321 | + let item = fileList.value[fileListLen]; | |
| 322 | + fileList.value.splice(fileListLen, 1, { | |
| 323 | + ...item, | |
| 324 | + status: 'success', | |
| 325 | + message: '', | |
| 326 | + url: result.data.fileName, | |
| 327 | + }); | |
| 328 | + fileListLen++; | |
| 329 | + } | |
| 330 | +}; | |
| 331 | + | |
| 332 | + | |
| 333 | +const handlePickerGarbageTypeConfirm = (e) => { | |
| 334 | + paramFrom.value.garbageType = e.value | |
| 335 | + garbageTypeShowFlag.value = false | |
| 336 | +} | |
| 337 | +const handlePickerCarInfoConfirm = (e) => { | |
| 338 | + paramFrom.value.carType = e.value | |
| 339 | + garCarLabelInfoNow.value = garCarLabelInfoList.value[paramFrom.value.carType] | |
| 340 | + carTypeShowFlag.value = false | |
| 341 | + console.log(garCarLabelInfoNow.value); | |
| 342 | +} | |
| 343 | + | |
| 344 | +/** | |
| 345 | + * 处理下单 | |
| 346 | + */ | |
| 347 | +const handleOderSure = () => { | |
| 348 | + let garCarInfos = []; | |
| 349 | + for (const key in garCarInfoList.value) { | |
| 350 | + garCarInfos.push(garCarInfoList.value[key]) | |
| 351 | + } | |
| 352 | + | |
| 353 | + let params = { | |
| 354 | + /** | |
| 355 | + * 派单地址 | |
| 356 | + */ | |
| 357 | + garOrderAddress: userAddress.value.garUserAddress, | |
| 358 | + | |
| 359 | + /** | |
| 360 | + * 派单详细地址 | |
| 361 | + */ | |
| 362 | + garOrderAddressDetails: userAddress.value.garRemark, | |
| 363 | + | |
| 364 | + /** | |
| 365 | + * 派单姓名 | |
| 366 | + */ | |
| 367 | + garOrderContactName: userAddress.value.garUserContactName, | |
| 368 | + garCarInfoList: garCarInfos, | |
| 369 | + | |
| 370 | + /** | |
| 371 | + * 垃圾类型 | |
| 372 | + */ | |
| 373 | + garOrderTrashType: paramFrom.value.garbageType, | |
| 374 | + | |
| 375 | + /** | |
| 376 | + * 派单人电话 | |
| 377 | + */ | |
| 378 | + garOrderContactTel: userAddress.value.garUserContactTel, | |
| 379 | + | |
| 380 | + /** | |
| 381 | + * 承接经营单位 | |
| 382 | + */ | |
| 383 | + garOrderCompanyId: companyObj.value.id, | |
| 384 | + | |
| 385 | + /** | |
| 386 | + * 公司名称 | |
| 387 | + */ | |
| 388 | + garOrderCompanyName: companyObj.value.name, | |
| 389 | + | |
| 390 | + /** | |
| 391 | + * 公司负责人电话 | |
| 392 | + */ | |
| 393 | + garOrderCompanyTel: companyObj.value.servicePhone, | |
| 394 | + | |
| 395 | + /** | |
| 396 | + * 约定时间 | |
| 397 | + */ | |
| 398 | + garOrderAgreementTime: dayTime.value, | |
| 399 | + /** | |
| 400 | + * 备注 | |
| 401 | + */ | |
| 402 | + garRemark: paramFrom.value.remark, | |
| 403 | + /** | |
| 404 | + * 图片列表 | |
| 405 | + */ | |
| 406 | + imageUrls: fileList.value.map(item => item.url), | |
| 407 | + garLongitude: userAddress.value.garLongitude, | |
| 408 | + garLatitude: userAddress.value.garLatitude, | |
| 409 | + garCoordinate: userAddress.value.garCoordinate, | |
| 410 | + } | |
| 411 | + if (!validateParams(params)) { | |
| 412 | + return; | |
| 413 | + } | |
| 414 | + | |
| 415 | + saveOrder(params).then(res => { | |
| 416 | + // TODO 派单详情 | |
| 417 | + if (res.data.success) { | |
| 418 | + if (userType.value === "运输驾驶员") { | |
| 419 | + uni.$u.toast("派单成功,请切换成且角色查看派单详情") | |
| 420 | + setTimeout(() => { | |
| 421 | + uni.$u.route({ | |
| 422 | + type: 'navigateBack', | |
| 423 | + url: `pages/home/index`, | |
| 424 | + }) | |
| 425 | + }, 300) | |
| 426 | + } else { | |
| 427 | + uni.$u.route({ | |
| 428 | + type: "redirect", | |
| 429 | + url: `pages/order/detail/index`, | |
| 430 | + params: { | |
| 431 | + orderId: res.data.data | |
| 432 | + } | |
| 433 | + }) | |
| 434 | + uni.$u.toast(res.data.msg) | |
| 435 | + } | |
| 436 | + | |
| 437 | + } | |
| 438 | + }) | |
| 439 | +} | |
| 440 | + | |
| 441 | + | |
| 442 | +/** | |
| 443 | + * 校验参数 | |
| 444 | + * @param {Object} params | |
| 445 | + */ | |
| 446 | +const validateParams = (params) => { | |
| 447 | + if (!paramFrom.value.sureReadFlag[0]) { | |
| 448 | + jumpPrompt('请勾选"本人已确认信息真实有效,并将上诉信息告知市容环境卫生主管部门"') | |
| 449 | + return false; | |
| 450 | + } | |
| 451 | + for (const key in params) { | |
| 452 | + if (!params[key] && key != "garRemark") { | |
| 453 | + switch (key) { | |
| 454 | + case "garOrderAgreementTime": | |
| 455 | + jumpPrompt('请选择预约时间') | |
| 456 | + break; | |
| 457 | + | |
| 458 | + } | |
| 459 | + return false; | |
| 460 | + } | |
| 461 | + if (key === "garCarInfoList") { | |
| 462 | + let count = 0; | |
| 463 | + params[key].forEach(item => { | |
| 464 | + count += item.garOrderCarNumber; | |
| 465 | + }) | |
| 466 | + if (count === 0) { | |
| 467 | + jumpPrompt('请添加车辆数量') | |
| 468 | + return false; | |
| 469 | + } | |
| 470 | + } | |
| 471 | + | |
| 472 | + if (key == "imageUrls") { | |
| 473 | + if (params[key].length == 0) { | |
| 474 | + jumpPrompt('请上传现场图片') | |
| 475 | + return false; | |
| 476 | + } | |
| 477 | + if (!validateImage(params[key])) { | |
| 478 | + uni.$u.toast('请等待图片上传完毕') | |
| 479 | + return false; | |
| 480 | + } | |
| 481 | + } | |
| 482 | + } | |
| 483 | + return true; | |
| 484 | +} | |
| 485 | + | |
| 486 | +const jumpPrompt = (msg) => { | |
| 487 | + uni.showModal({ | |
| 488 | + title: '提示', | |
| 489 | + content: msg, | |
| 490 | + showCancel: false, | |
| 491 | + success: function (res) { | |
| 492 | + if (res.confirm) { | |
| 493 | + } else if (res.cancel) { | |
| 494 | + } | |
| 495 | + } | |
| 496 | + }); | |
| 497 | +} | |
| 498 | +const validateImage = (fileList) => { | |
| 499 | + for (let index = 0; index < fileList.length; index++) { | |
| 500 | + const str = fileList[index]; | |
| 501 | + if (!str.startsWith("/profile/upload")) { | |
| 502 | + return false; | |
| 503 | + } | |
| 504 | + } | |
| 505 | + return true; | |
| 506 | +} | |
| 507 | + | |
| 508 | + | |
| 509 | +// 开始执行一次 | |
| 510 | +watch(carPopupShowFlag, (val) => { | |
| 511 | + // console.log(val); | |
| 512 | + // carPopupShowFlag.value = val | |
| 513 | + if (!val) { | |
| 514 | + setTimeout(() => { | |
| 515 | + nextTick(() => { | |
| 516 | + let areaHeight; | |
| 517 | + // select中的参数就如css选择器一样选择元素 | |
| 518 | + let movableArea = uni.createSelectorQuery().in(proxy).select(".movableArea"); | |
| 519 | + movableArea.boundingClientRect(function (data) { | |
| 520 | + // data - 包含元素的高度等信息 | |
| 521 | + areaHeight = data.height; | |
| 522 | + y.value = areaHeight > 40 ? (areaHeight - 40) : areaHeight; | |
| 523 | + }).exec(function (res) { | |
| 524 | + // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据 | |
| 525 | + }) | |
| 526 | + }) | |
| 527 | + }, 0); | |
| 528 | + } | |
| 529 | +}, { | |
| 530 | + immediate: true | |
| 531 | +}) | |
| 532 | + | |
| 533 | +</script> | |
| 534 | + | |
| 535 | +<style lang="scss" scoped> | |
| 536 | +$custom-marin-bottom: 20rpx; | |
| 537 | +$custom-page-padding: 20rpx; | |
| 538 | +$custom-border-radio: 20rpx; | |
| 539 | +$custom-bottom-height: 200rpx; | |
| 540 | + | |
| 541 | + | |
| 542 | +.company-clean-container { | |
| 543 | + height: 100%; | |
| 544 | + width: 100%; | |
| 545 | + background-color: $u-info-light; | |
| 546 | + box-sizing: border-box; | |
| 547 | + overflow-y: scroll; | |
| 548 | + | |
| 549 | + | |
| 550 | + .company-clean-container-box { | |
| 551 | + height: 100%; | |
| 552 | + width: 100%; | |
| 553 | + padding: $custom-page-padding; | |
| 554 | + box-sizing: border-box; | |
| 555 | + | |
| 556 | + .company-clean-container-header { | |
| 557 | + padding: $custom-page-padding; | |
| 558 | + box-sizing: border-box; | |
| 559 | + background-color: #ffffff; | |
| 560 | + border-radius: $custom-border-radio; | |
| 561 | + margin-bottom: $custom-marin-bottom; | |
| 562 | + | |
| 563 | + .company-clean-container-header-address { | |
| 564 | + font-size: 30rpx; | |
| 565 | + font-weight: bold; | |
| 566 | + color: $u-main-color; | |
| 567 | + } | |
| 568 | + | |
| 569 | + .company-clean-container-header-base-info { | |
| 570 | + font-size: 25rpx; | |
| 571 | + color: $u-info; | |
| 572 | + line-height: 80rpx; | |
| 573 | + } | |
| 574 | + | |
| 575 | + .company-clean-container-header-reservation { | |
| 576 | + display: flex; | |
| 577 | + justify-content: space-between; | |
| 578 | + font-size: 25rpx; | |
| 579 | + @include handleClick; | |
| 580 | + | |
| 581 | + .company-clean-container-header-reservation-left { | |
| 582 | + display: flex; | |
| 583 | + align-items: center; | |
| 584 | + color: $u-content-color; | |
| 585 | + } | |
| 586 | + | |
| 587 | + .company-clean-container-header-reservation-right { | |
| 588 | + display: flex; | |
| 589 | + align-items: center; | |
| 590 | + color: $u-content-color; | |
| 591 | + } | |
| 592 | + } | |
| 593 | + | |
| 594 | + | |
| 595 | + } | |
| 596 | + | |
| 597 | + .company-clean-container-car-main { | |
| 598 | + padding: $custom-page-padding; | |
| 599 | + border-radius: $custom-border-radio; | |
| 600 | + box-sizing: border-box; | |
| 601 | + background-color: #ffffff; | |
| 602 | + margin-bottom: $custom-marin-bottom; | |
| 603 | + | |
| 604 | + .company-clean-container-car-main-title { | |
| 605 | + font-size: 30rpx; | |
| 606 | + font-weight: bold; | |
| 607 | + color: #a9e08f; | |
| 608 | + display: flex; | |
| 609 | + justify-content: center; | |
| 610 | + } | |
| 611 | + | |
| 612 | + .company-clean-container-car-main-content { | |
| 613 | + width: 100%; | |
| 614 | + display: flex; | |
| 615 | + flex-direction: column; | |
| 616 | + justify-content: center; | |
| 617 | + | |
| 618 | + .company-clean-container-car-main-content-img { | |
| 619 | + width: 600rpx; | |
| 620 | + height: 400rpx; | |
| 621 | + | |
| 622 | + .company-clean-container-car-main-content-img { | |
| 623 | + width: 600rpx; | |
| 624 | + height: 400rpx; | |
| 625 | + } | |
| 626 | + } | |
| 627 | + | |
| 628 | + .company-clean-container-car-main-content-remark { | |
| 629 | + color: $u-tips-color; | |
| 630 | + font-size: 23rpx; | |
| 631 | + line-height: 30rpx; | |
| 632 | + padding: $custom-page-padding; | |
| 633 | + background-color: $u-info-light; | |
| 634 | + word-break: break-all; | |
| 635 | + } | |
| 636 | + | |
| 637 | + .company-clean-container-car-main-content-type { | |
| 638 | + margin-top: $custom-marin-bottom; | |
| 639 | + margin-bottom: $custom-marin-bottom; | |
| 640 | + display: flex; | |
| 641 | + justify-content: space-between; | |
| 642 | + border-radius: $custom-border-radio; | |
| 643 | + // background-color: $u-info-light; | |
| 644 | + box-sizing: border-box; | |
| 645 | + | |
| 646 | + .company-clean-container-car-main-content-type-price-area { | |
| 647 | + display: flex; | |
| 648 | + justify-content: flex-start; | |
| 649 | + align-items: center; | |
| 650 | + color: $u-info; | |
| 651 | + white-space: nowrap; | |
| 652 | + } | |
| 653 | + } | |
| 654 | + | |
| 655 | + .company-clean-container-car-main-content-number { | |
| 656 | + display: flex; | |
| 657 | + justify-content: space-between; | |
| 658 | + font-size: 28rpx; | |
| 659 | + color: $u-tips-color; | |
| 660 | + font-weight: small; | |
| 661 | + align-items: center; | |
| 662 | + | |
| 663 | + .company-clean-container-car-main-content-number-txt { | |
| 664 | + line-height: 80rpx; | |
| 665 | + } | |
| 666 | + | |
| 667 | + .company-clean-container-car-main-content-number-button {} | |
| 668 | + } | |
| 669 | + } | |
| 670 | + | |
| 671 | + | |
| 672 | + } | |
| 673 | + | |
| 674 | + .company-clean-container-car-main-content-prompt { | |
| 675 | + color: $u-tips-color; | |
| 676 | + font-size: 23rpx; | |
| 677 | + line-height: 30rpx; | |
| 678 | + padding: $custom-page-padding; | |
| 679 | + word-break: break-all; | |
| 680 | + text-align: center; | |
| 681 | + } | |
| 682 | + | |
| 683 | + .company-clean-container-site-image-info { | |
| 684 | + padding: $custom-page-padding; | |
| 685 | + background-color: #ffffff; | |
| 686 | + border-radius: $custom-border-radio; | |
| 687 | + color: $u-info; | |
| 688 | + font-size: 28rpx; | |
| 689 | + margin-bottom: $custom-marin-bottom; | |
| 690 | + | |
| 691 | + .company-clean-container-site-image-info-remark { | |
| 692 | + line-height: 80rpx; | |
| 693 | + | |
| 694 | + } | |
| 695 | + | |
| 696 | + .company-clean-container-site-image-info-img {} | |
| 697 | + | |
| 698 | + .company-clean-container-site-image-info-input-remark { | |
| 699 | + line-height: 80rpx; | |
| 700 | + } | |
| 701 | + | |
| 702 | + .company-clean-container-site-image-info-input-remark-box {} | |
| 703 | + } | |
| 704 | + | |
| 705 | + .company-clean-container-site-image-info-sure-button { | |
| 706 | + padding-bottom: $custom-bottom-height; | |
| 707 | + font-size: 28rpx; | |
| 708 | + | |
| 709 | + .company-clean-container-site-image-info-sure-button-radio { | |
| 710 | + padding: $custom-page-padding; | |
| 711 | + box-sizing: border-box; | |
| 712 | + display: flex; | |
| 713 | + // flex-flow: row wrap; | |
| 714 | + font-size: 25rpx; | |
| 715 | + color: $u-info; | |
| 716 | + } | |
| 717 | + } | |
| 718 | + } | |
| 719 | + | |
| 720 | + .company-clean-bottom { | |
| 721 | + position: absolute; | |
| 722 | + width: 100%; | |
| 723 | + // height: 100%; | |
| 724 | + bottom: 0; | |
| 725 | + left: 0; | |
| 726 | + // 阴影 | |
| 727 | + box-shadow: 0 0 10rpx 0 rgba(0, 0, 0, 0.1); | |
| 728 | + | |
| 729 | + .movableArea { | |
| 730 | + pointer-events: none; | |
| 731 | + position: fixed; | |
| 732 | + left: 0; | |
| 733 | + top: 0; | |
| 734 | + width: 100%; | |
| 735 | + height: calc(100% - $custom-bottom-height); | |
| 736 | + // z-index: 99; | |
| 737 | + | |
| 738 | + .movableView { | |
| 739 | + pointer-events: auto; | |
| 740 | + min-height: 60rpx; | |
| 741 | + min-width: 60rpx; | |
| 742 | + | |
| 743 | + .company-clean-call-box-container { | |
| 744 | + min-height: 60rpx; | |
| 745 | + min-width: 60rpx; | |
| 746 | + display: flex; | |
| 747 | + align-items: center; | |
| 748 | + justify-content: center; | |
| 749 | + background-color: #a9e08f; | |
| 750 | + border-radius: 100%; | |
| 751 | + } | |
| 752 | + } | |
| 753 | + } | |
| 754 | + | |
| 755 | + .company-clean-bottom-box { | |
| 756 | + height: $custom-bottom-height; | |
| 757 | + background-color: #ffffff; | |
| 758 | + padding: 50rpx; | |
| 759 | + box-sizing: border-box; | |
| 760 | + display: flex; | |
| 761 | + justify-content: space-between; | |
| 762 | + align-items: center; | |
| 763 | + | |
| 764 | + .company-clean-bottom-left { | |
| 765 | + display: flex; | |
| 766 | + | |
| 767 | + .company-clean-bottom-left-icon { | |
| 768 | + transform: rotateY(180deg); | |
| 769 | + } | |
| 770 | + | |
| 771 | + } | |
| 772 | + | |
| 773 | + .company-clean-bottom-right { | |
| 774 | + min-width: 200rpx; | |
| 775 | + } | |
| 776 | + } | |
| 777 | + | |
| 778 | + } | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | +} | |
| 783 | + | |
| 784 | +.hoverClickStyle { | |
| 785 | + @include handleClick; | |
| 786 | +} | |
| 787 | + | |
| 788 | +// 弹出框 | |
| 789 | +.company-clean-container-car-popup { | |
| 790 | + min-height: 450rpx; | |
| 791 | + padding: $custom-page-padding; | |
| 792 | + box-sizing: border-box; | |
| 793 | + | |
| 794 | + .company-clean-container-car-popup-content { | |
| 795 | + font-size: 28rpx; | |
| 796 | + | |
| 797 | + .company-clean-container-car-popup-content-box { | |
| 798 | + box-sizing: border-box; | |
| 799 | + padding: $custom-page-padding; | |
| 800 | + border: 2rpx solid #a9e08f; | |
| 801 | + border-radius: 10rpx; | |
| 802 | + | |
| 803 | + .company-clean-container-car-popup-content-box-item { | |
| 804 | + display: flex; | |
| 805 | + align-items: center; | |
| 806 | + justify-content: space-between; | |
| 807 | + margin: 20rpx 0; | |
| 808 | + box-sizing: border-box; | |
| 809 | + | |
| 810 | + .company-clean-container-car-popup-content-box-item-text {} | |
| 811 | + | |
| 812 | + .company-clean-container-car-popup-content-box-item-number {} | |
| 813 | + } | |
| 814 | + } | |
| 815 | + | |
| 816 | + .company-clean-container-car-popup-content-title { | |
| 817 | + color: $u-main-color; | |
| 818 | + box-sizing: border-box; | |
| 819 | + margin-bottom: 20rpx; | |
| 820 | + font-size: 30rpx; | |
| 821 | + font-weight: bold; | |
| 822 | + } | |
| 823 | + } | |
| 824 | + | |
| 825 | + .company-clean-container-car-popup-button-safe { | |
| 826 | + width: 100%; | |
| 827 | + height: $custom-bottom-height; | |
| 828 | + } | |
| 829 | +} | |
| 830 | +</style> | ... | ... |
garbage-removal/src/pages/home/clean/index.vue
| ... | ... | @@ -60,18 +60,41 @@ |
| 60 | 60 | <view class="company-clean-container-car-main"> |
| 61 | 61 | <view class="company-clean-container-car-main-content"> |
| 62 | 62 | <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-type"> |
| 63 | - <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 64 | - style="color: red;">*</text>车辆类型:</text> | |
| 65 | - <!-- <uni-combox label="" :candidates="candidates" placeholder="请选择运输车辆类型" | |
| 66 | - v-model="paramFrom.carType"></uni-combox> --> | |
| 67 | - <view class="" hover-class="hoverClickStyle" @click.stop="handleCarInfoClick(true)"> | |
| 63 | + <view class="company-clean-container-car-main-content-type-price-area"> | |
| 64 | + <text style="color: red;">*</text>车辆类型: | |
| 65 | + </view> | |
| 66 | + <!-- <scrollText :candidates="candidates" /> --> | |
| 67 | + <view style="display:flex; align-items: center;" hover-class="hoverClickStyle" | |
| 68 | + @click.stop="handleCarInfoClick(true)"> | |
| 68 | 69 | <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.carType" |
| 69 | 70 | type="text" placeholder-class="line" readonly /> |
| 70 | 71 | </view> |
| 71 | 72 | </view> |
| 73 | + <!-- <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-type"> | |
| 74 | + <view class="company-clean-container-car-main-content-type-price-area"> | |
| 75 | + <text style="color: red;">*</text>协商车辆: | |
| 76 | + </view> | |
| 77 | + <view class="company-clean-container-car-main-content-number-button"> | |
| 78 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 79 | + v-model="garCarInfoList[paramFrom.carType].garOrderCarNumber"></u-number-box> | |
| 80 | + </view> | |
| 81 | + </view> --> | |
| 82 | + <view class="company-clean-container-car-main-content"> | |
| 83 | + <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-type"> | |
| 84 | + <view class="company-clean-container-car-main-content-type-price-area"> | |
| 85 | + <text style="color: red;">*</text>车辆数量: | |
| 86 | + </view> | |
| 87 | + <view class="company-clean-container-car-main-content-number-button" style="width: 308rpx;"> | |
| 88 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 89 | + v-model="garCarInfoList[paramFrom.carType].garOrderCarNumber"></u-number-box> | |
| 90 | + </view> | |
| 91 | + </view> | |
| 92 | + </view> | |
| 93 | + | |
| 72 | 94 | <view class="company-clean-container-car-main-content-type"> |
| 73 | - <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 74 | - style="color: red;">*</text>垃圾类型:</text> | |
| 95 | + <view class="company-clean-container-car-main-content-type-price-area"> | |
| 96 | + <text style="color: red;">*</text>垃圾类型: | |
| 97 | + </view> | |
| 75 | 98 | <view hover-class="hoverClickStyle" @click.stop="handleGarbageTypeClick(true)"> |
| 76 | 99 | <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.garbageType" |
| 77 | 100 | type="text" placeholder-class="line" readonly /> |
| ... | ... | @@ -83,16 +106,6 @@ |
| 83 | 106 | <view class="company-clean-container-car-main-content-remark"> |
| 84 | 107 | {{ garCarTransportInfo }} |
| 85 | 108 | </view> |
| 86 | - | |
| 87 | - <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-number"> | |
| 88 | - <view class="company-clean-container-car-main-content-number-txt"> | |
| 89 | - <text style="color: red;">*</text>添加车辆数量 | |
| 90 | - </view> | |
| 91 | - <view class="company-clean-container-car-main-content-number-button"> | |
| 92 | - <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 93 | - v-model="garCarInfoList[paramFrom.carType].garOrderCarNumber"></u-number-box> | |
| 94 | - </view> | |
| 95 | - </view> | |
| 96 | 109 | <view class="company-clean-container-car-main-content-prompt"> |
| 97 | 110 | 温馨提示:垃圾类型不符合,企业有权拒绝清运。 |
| 98 | 111 | </view> |
| ... | ... | @@ -100,26 +113,46 @@ |
| 100 | 113 | </view> |
| 101 | 114 | <view class="company-clean-container-site-image-info"> |
| 102 | 115 | <view class="company-clean-container-site-image-info-remark"> |
| 103 | - <text style="color: red;">*</text>现场照片(最多上传10张) | |
| 116 | + <text style="color: red;">*</text>要求装车完成后虚上传现场照片(最少1张,最多上传10张),照片须看清全貌。 | |
| 104 | 117 | </view> |
| 105 | 118 | <view class="company-clean-container-site-image-info-img"> |
| 106 | - <u-upload width="200" height="150" :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" | |
| 107 | - multiple :maxCount="10" :previewFullImage="true"></u-upload> | |
| 119 | + <u-upload width="200" height="150" :fileList="fileList" @afterRead="afterRead" :deletable="deletable" | |
| 120 | + @delete="deletePic" name="3" multiple :maxCount="10" :previewFullImage="true"></u-upload> | |
| 108 | 121 | </view> |
| 109 | - <view class="company-clean-container-site-image-info-input-remark"> | |
| 110 | - 填写备注 | |
| 122 | + <view class="company-in-car-store-box"> | |
| 123 | + <view class="company-in-car-store-box-content" | |
| 124 | + style="font-size: 15rpx;display: flex;color: white; justify-content: flex-end;"> | |
| 125 | + <view | |
| 126 | + :class="paramFrom.garInCarStore ? 'company-in-car-store-box-text-yes' : 'company-in-car-store-box-text-no'" | |
| 127 | + @click="handleInCarClick" style="padding: 10rpx;box-sizing: border-box;border-radius: 15rpx;"> | |
| 128 | + 需要进入车库? | |
| 129 | + </view> | |
| 130 | + </view> | |
| 111 | 131 | </view> |
| 112 | - <view class="company-clean-container-site-image-info-input-remark-box"> | |
| 113 | - <u--textarea v-model="paramFrom.remark" placeholder="请输入内容"></u--textarea> | |
| 132 | + <view v-if="paramFrom.garInCarStore" class="company-in-car-store-box-info"> | |
| 133 | + <view class="company-clean-container-site-image-info-input-remark"> | |
| 134 | + 填写备注 | |
| 135 | + </view> | |
| 136 | + <view class="company-clean-container-site-image-info-input-remark-box"> | |
| 137 | + <u--textarea v-model="paramFrom.remark" placeholder="请输入内容"></u--textarea> | |
| 138 | + </view> | |
| 139 | + <view class="company-in-car-store-box-prompt" style="margin-top: 20rpx; font-size: 23rpx;"> | |
| 140 | + 提示:需要进入车库需要写车辆限高,部门车库限高2.3m,如果装修垃圾在车库,要考虑车辆是否能进入。 | |
| 141 | + </view> | |
| 114 | 142 | </view> |
| 115 | 143 | </view> |
| 116 | 144 | <view class="company-clean-container-site-image-info-sure-button"> |
| 117 | 145 | <view class="company-clean-container-site-image-info-sure-button-radio"> |
| 118 | - <u-checkbox-group v-model="paramFrom.sureReadFlag" placement="row"> | |
| 119 | - <u-checkbox activeColor="#a9e08f" size="25" labelSize="25" shape="circle" @change="changeAgree" :key="0" | |
| 120 | - :name="true" :labelDisabled="true" labelColor="#909399" | |
| 121 | - label="本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。"></u-checkbox> | |
| 122 | - </u-checkbox-group> | |
| 146 | + <view @click="changeAgree"> | |
| 147 | + <u-checkbox-group v-model="paramFrom.sureReadFlag" placement="row"> | |
| 148 | + <u-checkbox activeColor="#5ac725" :customStyle="{ marginBottom: '0px', marginTop: '1px' }" size="25" | |
| 149 | + labelSize="25" shape="square" :key="0" :name="true" :labelDisabled="true" | |
| 150 | + labelColor="#909399"></u-checkbox> | |
| 151 | + </u-checkbox-group> | |
| 152 | + </view> | |
| 153 | + <view> | |
| 154 | + 本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。 | |
| 155 | + </view> | |
| 123 | 156 | </view> |
| 124 | 157 | </view> |
| 125 | 158 | </view> |
| ... | ... | @@ -141,7 +174,7 @@ |
| 141 | 174 | </view> |
| 142 | 175 | </view> |
| 143 | 176 | <view class="company-clean-bottom-right"> |
| 144 | - <u-button @click="handleOderSure" shape="circle" color="#a9e08f" text="立即派单"></u-button> | |
| 177 | + <u-button @click="handleOderSure" shape="square" color="#a9e08f" text="立即派单"></u-button> | |
| 145 | 178 | </view> |
| 146 | 179 | </view> |
| 147 | 180 | </view> |
| ... | ... | @@ -153,16 +186,17 @@ import { queryCarList } from '@/apis/carinfo.js'; |
| 153 | 186 | import { uploadFilePromise } from '@/apis/common.js'; |
| 154 | 187 | import { saveOrder } from '@/apis/order.js'; |
| 155 | 188 | import liuDeliveryTime from "@/components/liu-delivery-time/liu-delivery-time.vue"; |
| 189 | +import garbageUrl from '@/static/image/garbage.png'; | |
| 156 | 190 | import { useMainStore } from '@/stores/index.js'; |
| 157 | 191 | import { onLoad } from '@dcloudio/uni-app'; |
| 158 | 192 | import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue'; |
| 159 | 193 | const { proxy } = getCurrentInstance(); |
| 160 | - | |
| 161 | 194 | const store = useMainStore(); |
| 162 | 195 | const userType = computed(() => store.userType) |
| 163 | 196 | const x = ref(5) |
| 164 | 197 | const y = ref() |
| 165 | 198 | const movableAreaElement = ref() |
| 199 | +const deletable = ref(false) | |
| 166 | 200 | const companyObj = ref() |
| 167 | 201 | const tel = ref() |
| 168 | 202 | const carTypeShowFlag = ref(false) |
| ... | ... | @@ -223,12 +257,19 @@ const paramFrom = ref({ |
| 223 | 257 | remark: "", |
| 224 | 258 | sureReadFlag: [], |
| 225 | 259 | carType: "", |
| 226 | - garbageType: "装修垃圾" | |
| 260 | + garbageType: ["装修垃圾"], | |
| 261 | + garInCarStore: false | |
| 262 | + | |
| 227 | 263 | }) |
| 228 | 264 | const dayTime = ref() |
| 229 | 265 | |
| 230 | 266 | const chooseTime = ref() |
| 231 | -const fileList = ref([]) | |
| 267 | +const fileList = ref([ | |
| 268 | + { | |
| 269 | + url: garbageUrl, | |
| 270 | + label: '预览' | |
| 271 | + } | |
| 272 | +]) | |
| 232 | 273 | const candidates = ref([]) |
| 233 | 274 | const handleTimeChoose = () => { |
| 234 | 275 | chooseTime.value.open(); |
| ... | ... | @@ -239,6 +280,7 @@ const changeTime = (e) => { |
| 239 | 280 | } |
| 240 | 281 | const changeAgree = (e) => { |
| 241 | 282 | // paramFrom.value.sureReadFlag = e |
| 283 | + paramFrom.value.sureReadFlag[0] = !paramFrom.value.sureReadFlag[0] | |
| 242 | 284 | } |
| 243 | 285 | const onChange = (e) => { |
| 244 | 286 | // console.log(e); |
| ... | ... | @@ -277,6 +319,9 @@ onLoad((options) => { |
| 277 | 319 | }) |
| 278 | 320 | }) |
| 279 | 321 | |
| 322 | +const handleInCarClick = () => { | |
| 323 | + paramFrom.value.garInCarStore = !paramFrom.value.garInCarStore | |
| 324 | +} | |
| 280 | 325 | |
| 281 | 326 | const handleCarInfoClick = (val) => { |
| 282 | 327 | carTypeShowFlag.value = val |
| ... | ... | @@ -321,6 +366,10 @@ const afterRead = async (event) => { |
| 321 | 366 | }); |
| 322 | 367 | fileListLen++; |
| 323 | 368 | } |
| 369 | + fileList.value = fileList.value.filter(item => { | |
| 370 | + deletable.value = true | |
| 371 | + return !item.label | |
| 372 | + }) | |
| 324 | 373 | }; |
| 325 | 374 | |
| 326 | 375 | |
| ... | ... | @@ -364,7 +413,7 @@ const handleOderSure = () => { |
| 364 | 413 | /** |
| 365 | 414 | * 垃圾类型 |
| 366 | 415 | */ |
| 367 | - garOrderTrashType: paramFrom.value.garbageType, | |
| 416 | + garOrderTrashType: paramFrom.value.garbageType[0], | |
| 368 | 417 | |
| 369 | 418 | /** |
| 370 | 419 | * 派单人电话 |
| ... | ... | @@ -397,10 +446,11 @@ const handleOderSure = () => { |
| 397 | 446 | /** |
| 398 | 447 | * 图片列表 |
| 399 | 448 | */ |
| 400 | - imageUrls: fileList.value.map(item => item.url), | |
| 449 | + imageUrls: fileList.value.filter(item => !item.label).map(item => item.url), | |
| 401 | 450 | garLongitude: userAddress.value.garLongitude, |
| 402 | 451 | garLatitude: userAddress.value.garLatitude, |
| 403 | 452 | garCoordinate: userAddress.value.garCoordinate, |
| 453 | + garInCarStore: paramFrom.value.garInCarStore | |
| 404 | 454 | } |
| 405 | 455 | if (!validateParams(params)) { |
| 406 | 456 | return; |
| ... | ... | @@ -410,7 +460,7 @@ const handleOderSure = () => { |
| 410 | 460 | // TODO 派单详情 |
| 411 | 461 | if (res.data.success) { |
| 412 | 462 | if (userType.value === "运输驾驶员") { |
| 413 | - uni.$u.toast("派单成功,请切换成且角色查看订单详情") | |
| 463 | + uni.$u.toast("派单成功,请切换成且角色查看派单详情") | |
| 414 | 464 | setTimeout(() => { |
| 415 | 465 | uni.$u.route({ |
| 416 | 466 | type: 'navigateBack', |
| ... | ... | @@ -438,11 +488,16 @@ const handleOderSure = () => { |
| 438 | 488 | * @param {Object} params |
| 439 | 489 | */ |
| 440 | 490 | const validateParams = (params) => { |
| 491 | + | |
| 441 | 492 | if (!paramFrom.value.sureReadFlag[0]) { |
| 442 | 493 | jumpPrompt('请勾选"本人已确认信息真实有效,并将上诉信息告知市容环境卫生主管部门"') |
| 443 | 494 | return false; |
| 444 | 495 | } |
| 445 | 496 | for (const key in params) { |
| 497 | + // 跳过garInCarStore | |
| 498 | + if (key == "garInCarStore") { | |
| 499 | + continue; | |
| 500 | + } | |
| 446 | 501 | if (!params[key] && key != "garRemark") { |
| 447 | 502 | switch (key) { |
| 448 | 503 | case "garOrderAgreementTime": |
| ... | ... | @@ -683,7 +738,7 @@ $custom-bottom-height: 200rpx; |
| 683 | 738 | margin-bottom: $custom-marin-bottom; |
| 684 | 739 | |
| 685 | 740 | .company-clean-container-site-image-info-remark { |
| 686 | - line-height: 80rpx; | |
| 741 | + line-height: 50rpx; | |
| 687 | 742 | |
| 688 | 743 | } |
| 689 | 744 | |
| ... | ... | @@ -703,8 +758,9 @@ $custom-bottom-height: 200rpx; |
| 703 | 758 | .company-clean-container-site-image-info-sure-button-radio { |
| 704 | 759 | padding: $custom-page-padding; |
| 705 | 760 | box-sizing: border-box; |
| 706 | - // display: flex; | |
| 761 | + display: flex; | |
| 707 | 762 | // flex-flow: row wrap; |
| 763 | + font-size: 25rpx; | |
| 708 | 764 | color: $u-info; |
| 709 | 765 | } |
| 710 | 766 | } |
| ... | ... | @@ -820,4 +876,12 @@ $custom-bottom-height: 200rpx; |
| 820 | 876 | height: $custom-bottom-height; |
| 821 | 877 | } |
| 822 | 878 | } |
| 879 | + | |
| 880 | +.company-in-car-store-box-text-yes { | |
| 881 | + background: #a9e08f; | |
| 882 | +} | |
| 883 | + | |
| 884 | +.company-in-car-store-box-text-no { | |
| 885 | + background: #909399; | |
| 886 | +} | |
| 823 | 887 | </style> | ... | ... |
garbage-removal/src/pages/home/clean/scroll-text.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="car-type-list-box" :style="activeStyle"> | |
| 3 | + <span v-for="(item, index) in candidates[0]" :key="index">{{ item }}</span> | |
| 4 | + | |
| 5 | + </view> | |
| 6 | +</template> | |
| 7 | + | |
| 8 | +<script setup> | |
| 9 | +import { getCurrentInstance, onMounted, ref } from "vue"; | |
| 10 | +const { proxy } = getCurrentInstance(); | |
| 11 | +const activeStyle = ref({ | |
| 12 | + height: '100rpx', | |
| 13 | + display: 'flex', | |
| 14 | + justifyContent: 'center', | |
| 15 | + alignItems: 'center', | |
| 16 | + flexDirection: 'column', | |
| 17 | + overflowY: 'auto', | |
| 18 | +}) | |
| 19 | +// uniapp 限制不能直接获取操作dom只能通过动态绑定style修改样式 | |
| 20 | +const props = defineProps({ | |
| 21 | + candidates: { | |
| 22 | + type: Array, | |
| 23 | + required: true, | |
| 24 | + default: () => [] | |
| 25 | + } | |
| 26 | +}) | |
| 27 | +const columns = ref(props.candidates[0]) | |
| 28 | +onMounted(() => { | |
| 29 | + // carTypeBox.value.style.height = minHeight.value + 'rpx'; | |
| 30 | + | |
| 31 | + | |
| 32 | +}) | |
| 33 | +</script> | |
| 34 | + | |
| 35 | +<style lang="scss" scoped></style> | ... | ... |
garbage-removal/src/pages/home/index.vue
| ... | ... | @@ -18,72 +18,101 @@ |
| 18 | 18 | <!-- 公司容器 --> |
| 19 | 19 | <view class="company-box"> |
| 20 | 20 | <view class="info-box"> |
| 21 | - <view class="info-box-item" v-for="(item, index) in infoBoxList" :key="index"> | |
| 21 | + <view class="info-box-item" hover-class="click-box" v-for="(item, index) in infoBoxList" :key="index"> | |
| 22 | 22 | <view class="info-box-item-icon" :class="item.icon"> |
| 23 | 23 | </view> |
| 24 | 24 | <view class="info-box-item-text">{{ item.text }}</view> |
| 25 | 25 | </view> |
| 26 | 26 | </view> |
| 27 | 27 | <view class="company-container"> |
| 28 | - <span class="company-label-info">可进行垃圾清运单位</span> | |
| 29 | 28 | <view class="company-list-box" v-if="addressInfo"> |
| 30 | 29 | <view class="company-list-header"> |
| 31 | 30 | <view class="company-list-header-left"> |
| 32 | - 综合排序 | |
| 31 | + <u-dropdown> | |
| 32 | + <u-dropdown-item :height="'240rpx'" :placement="'left'" v-model="registrationAreaValue" | |
| 33 | + @change="handleDropdownAreaChange" :title="'所属区域'" :options="dropdownOptions[0]"></u-dropdown-item> | |
| 34 | + <u-dropdown-item :placement="'center'" v-model="carTypeValue" @change="handleDropdownCarChange" | |
| 35 | + :title="'车辆类型'" :options="dropdownOptions[1]"></u-dropdown-item> | |
| 36 | + <u-dropdown-item :placement="'right'" v-model="sortValue" @change="handleDropdownSortChange" | |
| 37 | + :title="dropdownOptions[2][sortValue].label" :options="dropdownOptions[2]"></u-dropdown-item> | |
| 38 | + </u-dropdown> | |
| 33 | 39 | </view> |
| 34 | - <view class="company-list-header-right"> | |
| 35 | - <u-search placeholder="请输入" :searchIconSize="40" disabled @click="handleSearchClick" | |
| 36 | - :showAction="false"></u-search> | |
| 40 | + <view class="company-list-header-right" @tap.stop="handleSearchClick"> | |
| 41 | + <view | |
| 42 | + style="display: inline-block; width: 100%;pointer-events: none;margin: 10rpx 0rpx; box-sizing: border-box;"> | |
| 43 | + <u-search :searchIconSize="40" :disabled="true" :placeholder="'搜索'" :showAction="false"></u-search> | |
| 44 | + </view> | |
| 37 | 45 | </view> |
| 38 | 46 | </view> |
| 39 | 47 | <view class="company-list-content"> |
| 40 | 48 | <view class="company-list-content-box"> |
| 41 | 49 | <z-paging ref="paging" :fixed="false" v-model="companyList" @query="queryList"> |
| 42 | 50 | <empty-view slot:empty></empty-view> |
| 43 | - <view class="company-list-item" v-for="item in companyList" :key="item.id"> | |
| 51 | + <view class="company-list-item" v-for="(item, index) in companyList" :key="item.id"> | |
| 44 | 52 | <view class="company-list-item-main"> |
| 45 | - <view class="company-list-item-main-left"> | |
| 46 | - <image class="company-list-item-main-left-img" | |
| 47 | - :src="item.carParkPanorama ? item.carParkPanorama : 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png'" /> | |
| 48 | - </view> | |
| 49 | - <view class="company-list-item-main-right" | |
| 50 | - @click="handleDetailClick(item, item.servicePhone, userAddress)"> | |
| 53 | + <view class="company-list-item-main-right"> | |
| 51 | 54 | <view class="company-list-item-main-right-name"> |
| 52 | - {{ item.name }} | |
| 55 | + <view class="company-list-item-main-right-name-label-recently" | |
| 56 | + v-if="index == 0 && sortValue == 0"> | |
| 57 | + {{ "距离最近" }} | |
| 58 | + </view> | |
| 59 | + <view class="company-list-item-main-right-name-label-distance"> | |
| 60 | + {{ "距离" + item.distance + "公里" }} | |
| 61 | + </view> | |
| 62 | + <view class="company-list-item-main-right-name-label-name"> | |
| 63 | + {{ item.name }} | |
| 64 | + </view> | |
| 53 | 65 | </view> |
| 54 | - <view class="company-list-item-main-right-score"> | |
| 55 | - <text class="company-list-item-main-right-text">评分:</text> | |
| 56 | - <view v-if="item.score != 0" class="company-list-item-main-right-score-start"> | |
| 57 | - <!-- <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" :key="todo" | |
| 66 | + <view class="company-list-item-main-box" style="display: flex;"> | |
| 67 | + <view class="company-list-item-main-left-box" style="flex: 1;"> | |
| 68 | + <view class="company-list-item-main-bottom-box" | |
| 69 | + @click="handleDetailClick(item, item.servicePhone, userAddress)"> | |
| 70 | + <view class="company-list-item-main-right-score"> | |
| 71 | + <text class="company-list-item-main-right-text">评分:</text> | |
| 72 | + <view v-if="item.score != 0" class="company-list-item-main-right-score-start"> | |
| 73 | + <!-- <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" :key="todo" | |
| 58 | 74 | color="#f9ae3d" size="28"></u-icon> --> |
| 59 | - <u-rate activeColor="#f9ae3d" inactive-color="#f9ae3d" size="28" :modelValue="item.score" | |
| 60 | - allowHalf readonly></u-rate> | |
| 75 | + <u-rate activeColor="#f9ae3d" inactive-color="#f9ae3d" size="28" | |
| 76 | + :modelValue="item.score" allowHalf readonly></u-rate> | |
| 77 | + </view> | |
| 78 | + <text v-if="item.score > 0" class="company-list-item-main-right-text" | |
| 79 | + style="color: #fd5d00;"> | |
| 80 | + {{ item.score }}分 | |
| 81 | + </text> | |
| 82 | + <text v-else class="company-list-item-main-right-text" | |
| 83 | + style="color: #fd5d00;">最近一月暂无评分</text> | |
| 84 | + </view> | |
| 85 | + <view class="company-list-item-main-right-price-number"> | |
| 86 | + <view class="company-list-item-main-right-price"> | |
| 87 | + 报价:<text style="color: #fd5d00;">¥400起 </text> | |
| 88 | + </view> | |
| 89 | + <view class="company-list-item-main-right-number"> | |
| 90 | + 清运数:<text class="company-list-item-main-right-number-text">{{ item.cleanNumber }}</text> | |
| 91 | + </view> | |
| 92 | + </view> | |
| 93 | + </view> | |
| 94 | + <view class="company-list-item-bottom-contact-company" style="display: flex;"> | |
| 95 | + <up-icon name="phone" color="#a9e08f"></up-icon> | |
| 96 | + <view @click="handleContactClick(item.servicePhone)" | |
| 97 | + style="display: flex; justify-content: center; align-items: center" color="#a9e08f"> | |
| 98 | + {{ item.servicePhone }} | |
| 99 | + </view> | |
| 100 | + </view> | |
| 61 | 101 | </view> |
| 62 | - <text v-if="item.score > 0" class="company-list-item-main-right-text" style="color: #fd5d00;">{{ | |
| 63 | - item.score }}分</text> | |
| 64 | - <text v-else class="company-list-item-main-right-text" style="color: #fd5d00;">最近一月暂无评分</text> | |
| 65 | - </view> | |
| 66 | - <view class="company-list-item-main-right-price-number"> | |
| 67 | - <view class="company-list-item-main-right-price">报价:<text | |
| 68 | - style="color: #fd5d00;">¥400起 </text></view> | |
| 69 | - <view class="company-list-item-main-right-number"> | |
| 70 | - 清运数:<text class="company-list-item-main-right-number-text">{{ item.cleanNumber }}</text> | |
| 102 | + <view class="company-list-item-main-right-box" | |
| 103 | + style="display: flex; justify-content: flex-end; align-items: flex-end;color:#458B74;font-weight: bold;"> | |
| 104 | + <view class="company-list-item-main-right-box-text" | |
| 105 | + @click="handleCleanGarbage(item, item.servicePhone, userAddress)"> | |
| 106 | + 垃圾清运 -> | |
| 107 | + </view> | |
| 71 | 108 | </view> |
| 72 | 109 | </view> |
| 73 | - <view class="company-list-item-main-right-remark"> | |
| 110 | + <!-- <view class="company-list-item-main-right-remark"> | |
| 74 | 111 | {{ item.remark }} |
| 75 | - </view> | |
| 112 | + </view> --> | |
| 76 | 113 | </view> |
| 77 | 114 | </view> |
| 78 | 115 | <view class="company-list-item-bottom"> |
| 79 | - <view class="company-list-item-bottom-contact-company"> | |
| 80 | - <u-button @click="handleContactClick(item.servicePhone)" color="#a9e08f" size="normal" | |
| 81 | - type="success" :hairline="true" shape="circle" text="联系公司"></u-button> | |
| 82 | - </view> | |
| 83 | - <view class="company-list-item-bottom-button-clean"> | |
| 84 | - <u-button @click="handleCleanGarbage(item, item.servicePhone, userAddress)" type="success" | |
| 85 | - :hairline="true" size="normal" shape="circle" text="垃圾清运"></u-button> | |
| 86 | - </view> | |
| 87 | 116 | </view> |
| 88 | 117 | </view> |
| 89 | 118 | </z-paging> |
| ... | ... | @@ -108,7 +137,7 @@ |
| 108 | 137 | </view> |
| 109 | 138 | </template> |
| 110 | 139 | |
| 111 | -<script setup > | |
| 140 | +<script setup> | |
| 112 | 141 | import { queryAddress } from '@/apis/address.js'; |
| 113 | 142 | import { queryEnterpriseList } from '@/apis/company.js'; |
| 114 | 143 | import { onLoad, onShow } from '@dcloudio/uni-app'; |
| ... | ... | @@ -121,13 +150,72 @@ const topMargin = ref(null);//状态栏高度 |
| 121 | 150 | const musicheadHeight = ref(); |
| 122 | 151 | const paging = ref(null) |
| 123 | 152 | const swiperImageList = ref([{ |
| 124 | - image: 'https://cdn.uviewui.com/uview/swiper/swiper1.png', | |
| 153 | + image: 'https://tse2-mm.cn.bing.net/th/id/OIP-C.o6VdtT8EY8mHjzoX7qAlrQAAAA?w=261&h=180&c=7&r=0&o=5&dpr=1.5&pid=1.7' | |
| 125 | 154 | }, { |
| 126 | - image: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', | |
| 155 | + image: 'https://tse3-mm.cn.bing.net/th/id/OIP-C.LwNUQLX3A3PIJ0Rzm4ATOwHaEQ?w=304&h=180&c=7&r=0&o=5&dpr=1.5&pid=1.7', | |
| 127 | 156 | }]) |
| 128 | 157 | |
| 129 | 158 | const userAddress = ref({}) |
| 130 | 159 | const addressInfo = ref() |
| 160 | +const sortValue = ref(0) | |
| 161 | +const registrationAreaValue = ref('') | |
| 162 | +const registrationAreaRealValue = ref('') | |
| 163 | +const carTypeValue = ref('') | |
| 164 | +const carTypeRealValue = ref('') | |
| 165 | +const dropdownOptions = ref([ | |
| 166 | + [{ | |
| 167 | + label: '芙蓉区', | |
| 168 | + value: '芙蓉区', | |
| 169 | + }, | |
| 170 | + { | |
| 171 | + label: '天心区', | |
| 172 | + value: '天心区' | |
| 173 | + }, | |
| 174 | + { | |
| 175 | + label: '岳麓区', | |
| 176 | + value: '岳麓区' | |
| 177 | + }, | |
| 178 | + { | |
| 179 | + label: '开福区', | |
| 180 | + value: '开福区' | |
| 181 | + }, | |
| 182 | + { | |
| 183 | + label: '雨花区', | |
| 184 | + value: '雨花区' | |
| 185 | + }, | |
| 186 | + { | |
| 187 | + label: '望城区', | |
| 188 | + value: '望城区' | |
| 189 | + }, | |
| 190 | + { | |
| 191 | + label: '长沙县', | |
| 192 | + value: '长沙县' | |
| 193 | + }, | |
| 194 | + { | |
| 195 | + label: '浏阳市', | |
| 196 | + value: '浏阳市' | |
| 197 | + }, | |
| 198 | + { | |
| 199 | + label: '宁乡市', | |
| 200 | + value: '宁乡市' | |
| 201 | + } | |
| 202 | + ], [{ | |
| 203 | + label: '暂未开放', | |
| 204 | + value: '暂未开放', | |
| 205 | + },] | |
| 206 | + , [{ | |
| 207 | + label: '距离排序', | |
| 208 | + value: 0, | |
| 209 | + }, | |
| 210 | + { | |
| 211 | + label: '清运排序', | |
| 212 | + value: 1 | |
| 213 | + }, | |
| 214 | + { | |
| 215 | + label: '评价排序', | |
| 216 | + value: 2 | |
| 217 | + }] | |
| 218 | +]) | |
| 131 | 219 | |
| 132 | 220 | // 信息指南 |
| 133 | 221 | const infoBoxList = ref([{ |
| ... | ... | @@ -159,6 +247,39 @@ const handleContactClick = (val) => { |
| 159 | 247 | } |
| 160 | 248 | |
| 161 | 249 | /** |
| 250 | + * 下拉框改变 | |
| 251 | + * @param {number} val | |
| 252 | + */ | |
| 253 | +const handleDropdownSortChange = (val) => { | |
| 254 | + sortValue.value = val; | |
| 255 | + // 重新获取列表 | |
| 256 | + paging.value.reload() | |
| 257 | +} | |
| 258 | +const handleDropdownAreaChange = (val) => { | |
| 259 | + if (registrationAreaRealValue.value == val) { | |
| 260 | + registrationAreaValue.value = '' | |
| 261 | + registrationAreaRealValue.value = '' | |
| 262 | + // 重新获取列表 | |
| 263 | + paging.value.reload() | |
| 264 | + return | |
| 265 | + } | |
| 266 | + registrationAreaRealValue.value = val; | |
| 267 | + // 重新获取列表 | |
| 268 | + paging.value.reload() | |
| 269 | +} | |
| 270 | +const handleDropdownCarChange = (val) => { | |
| 271 | + if (carTypeRealValue.value == val) { | |
| 272 | + carTypeValue.value = '' | |
| 273 | + carTypeRealValue.value = '' | |
| 274 | + // 重新获取列表 | |
| 275 | + paging.value.reload() | |
| 276 | + return | |
| 277 | + } | |
| 278 | + carTypeRealValue.value = val; | |
| 279 | + // 重新获取列表 | |
| 280 | + paging.value.reload() | |
| 281 | +} | |
| 282 | +/** | |
| 162 | 283 | * 跳转地址 |
| 163 | 284 | */ |
| 164 | 285 | function handleAddressInfo() { |
| ... | ... | @@ -202,9 +323,7 @@ const handleCleanClick = () => { |
| 202 | 323 | } |
| 203 | 324 | } |
| 204 | 325 | }); |
| 205 | - | |
| 206 | 326 | } |
| 207 | - | |
| 208 | 327 | return |
| 209 | 328 | |
| 210 | 329 | } |
| ... | ... | @@ -229,8 +348,10 @@ const handleCleanGarbage = (companyObj, tel, userAddress) => { |
| 229 | 348 | /** |
| 230 | 349 | * 搜索 |
| 231 | 350 | */ |
| 232 | -const handleSearchClick = () => { | |
| 233 | - console.log("search"); | |
| 351 | +const handleSearchClick = (e) => { | |
| 352 | + uni.$u.route({ | |
| 353 | + url: `pages/home/search/index`, | |
| 354 | + }) | |
| 234 | 355 | } |
| 235 | 356 | |
| 236 | 357 | /** |
| ... | ... | @@ -281,8 +402,16 @@ const initData = () => { |
| 281 | 402 | }) |
| 282 | 403 | } |
| 283 | 404 | const queryList = (pageNo, pageSize) => { |
| 405 | + let query = { | |
| 406 | + companyType: 1, | |
| 407 | + pageNum: pageNo, | |
| 408 | + pageSize, | |
| 409 | + orderByColumn: sortValue.value, | |
| 410 | + registrationArea: registrationAreaValue.value, | |
| 411 | + searchValue: carTypeValue.value | |
| 412 | + } | |
| 284 | 413 | // 查询公司信息 |
| 285 | - queryEnterpriseList({ companyType: 1, pageNum: pageNo, pageSize }).then(res => { | |
| 414 | + queryEnterpriseList(query).then(res => { | |
| 286 | 415 | paging.value.complete(res.data.data.list); |
| 287 | 416 | }) |
| 288 | 417 | } |
| ... | ... | @@ -310,13 +439,19 @@ const queryList = (pageNo, pageSize) => { |
| 310 | 439 | |
| 311 | 440 | ::v-deep .u-swiper { |
| 312 | 441 | height: 400rpx !important; |
| 442 | + background-size: 100% 100% !important; | |
| 313 | 443 | |
| 314 | 444 | .u-swiper__wrapper { |
| 315 | 445 | height: 400rpx !important; |
| 446 | + background-size: 100% 100% !important; | |
| 316 | 447 | } |
| 317 | 448 | |
| 318 | 449 | .u-swiper__wrapper__item__wrapper__image { |
| 319 | 450 | height: 400rpx !important; |
| 451 | + | |
| 452 | + &>div { | |
| 453 | + background-size: 100% 100% !important; | |
| 454 | + } | |
| 320 | 455 | } |
| 321 | 456 | } |
| 322 | 457 | |
| ... | ... | @@ -356,7 +491,7 @@ const queryList = (pageNo, pageSize) => { |
| 356 | 491 | z-index: 200; |
| 357 | 492 | box-sizing: border-box; |
| 358 | 493 | padding: 30rpx; |
| 359 | - margin-top: 330rpx; | |
| 494 | + margin-top: 300rpx; | |
| 360 | 495 | flex: 1; |
| 361 | 496 | display: flex; |
| 362 | 497 | flex-direction: column; |
| ... | ... | @@ -460,16 +595,16 @@ const queryList = (pageNo, pageSize) => { |
| 460 | 595 | flex: 1; |
| 461 | 596 | display: flex; |
| 462 | 597 | flex-direction: column; |
| 598 | + box-sizing: border-box; | |
| 463 | 599 | |
| 464 | 600 | .company-list-header { |
| 465 | - display: flex; | |
| 466 | 601 | font-size: small; |
| 467 | 602 | font-weight: small; |
| 468 | 603 | align-items: center; |
| 469 | 604 | |
| 470 | 605 | .company-list-header-left { |
| 471 | - width: 200rpx; | |
| 472 | 606 | text-align: center; |
| 607 | + margin-bottom: 15rpx; | |
| 473 | 608 | } |
| 474 | 609 | |
| 475 | 610 | .company-list-header-right { |
| ... | ... | @@ -520,14 +655,49 @@ const queryList = (pageNo, pageSize) => { |
| 520 | 655 | font-size: 25rpx; |
| 521 | 656 | |
| 522 | 657 | .company-list-item-main-right-name { |
| 523 | - font-weight: bold; | |
| 658 | + // font-weight: bold; | |
| 524 | 659 | color: $u-main-color; |
| 525 | 660 | font-size: 30rpx; |
| 661 | + display: flex; | |
| 662 | + line-height: 20rpx !important; | |
| 663 | + | |
| 664 | + .company-list-item-main-right-name-label-recently { | |
| 665 | + margin-right: 10rpx; | |
| 666 | + font-size: 16rpx; | |
| 667 | + display: flex; | |
| 668 | + align-items: center; | |
| 669 | + justify-content: center; | |
| 670 | + padding: 8rpx 13rpx; | |
| 671 | + box-sizing: border-box; | |
| 672 | + border-radius: 25rpx; | |
| 673 | + background: #19a97c; | |
| 674 | + color: #ffffff | |
| 675 | + } | |
| 676 | + | |
| 677 | + .company-list-item-main-right-name-label-distance { | |
| 678 | + margin-right: 10rpx; | |
| 679 | + font-size: 16rpx; | |
| 680 | + display: flex; | |
| 681 | + align-items: center; | |
| 682 | + justify-content: center; | |
| 683 | + padding: 8rpx 13rpx; | |
| 684 | + box-sizing: border-box; | |
| 685 | + border-radius: 25rpx; | |
| 686 | + background: #deab11; | |
| 687 | + } | |
| 688 | + | |
| 689 | + .company-list-item-main-right-name-label-name { | |
| 690 | + display: flex; | |
| 691 | + align-items: center; | |
| 692 | + justify-content: center; | |
| 693 | + font-size: 30rpx; | |
| 694 | + } | |
| 526 | 695 | } |
| 527 | 696 | |
| 528 | 697 | .company-list-item-main-right-score { |
| 529 | 698 | display: flex; |
| 530 | 699 | font-size: small; |
| 700 | + font-size: 24rpx; | |
| 531 | 701 | |
| 532 | 702 | .company-list-item-main-right-text { |
| 533 | 703 | text-align: center; |
| ... | ... | @@ -571,7 +741,9 @@ const queryList = (pageNo, pageSize) => { |
| 571 | 741 | .company-list-item-bottom { |
| 572 | 742 | display: flex; |
| 573 | 743 | justify-content: space-around; |
| 574 | - margin-top: 20rpx; | |
| 744 | + font-size: 25rpx; | |
| 745 | + color: #909399; | |
| 746 | + margin-bottom: 50rpx; | |
| 575 | 747 | |
| 576 | 748 | .company-list-item-bottom-contact-company { |
| 577 | 749 | flex: 1; |
| ... | ... | @@ -592,6 +764,30 @@ const queryList = (pageNo, pageSize) => { |
| 592 | 764 | } |
| 593 | 765 | } |
| 594 | 766 | } |
| 767 | +} | |
| 595 | 768 | |
| 769 | +.click-box { | |
| 770 | + @include handleClick; | |
| 771 | + transform: all 0.5s; | |
| 772 | +} | |
| 773 | + | |
| 774 | +.company-label-title-box { | |
| 775 | + width: 100%; | |
| 776 | + | |
| 777 | + .company-label-title-top { | |
| 778 | + display: flex; | |
| 779 | + justify-content: space-between; | |
| 780 | + width: 100%; | |
| 781 | + | |
| 782 | + .company-label-title-top-left { | |
| 783 | + width: 100%; | |
| 784 | + } | |
| 785 | + | |
| 786 | + .company-label-title-top-right { | |
| 787 | + width: 100%; | |
| 788 | + display: flex; | |
| 789 | + justify-content: flex-end; | |
| 790 | + } | |
| 791 | + } | |
| 596 | 792 | } |
| 597 | 793 | </style> | ... | ... |
garbage-removal/src/pages/home/search/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="search-container"> | |
| 3 | + <view class="search-box"> | |
| 4 | + <u-search placeholder="请输入" :searchIconSize="40" :disabled="true" @click="handleSearchClick" | |
| 5 | + :showAction="false"></u-search> | |
| 6 | + </view> | |
| 7 | + </view> | |
| 8 | +</template> | |
| 9 | + | |
| 10 | +<script setup> | |
| 11 | + | |
| 12 | +</script> | |
| 13 | + | |
| 14 | +<style lang="scss" scoped></style> | ... | ... |
garbage-removal/src/pages/login/code.vue
| ... | ... | @@ -74,7 +74,9 @@ const checkVerifyNum = (code) => { |
| 74 | 74 | if (res.data.success) { |
| 75 | 75 | verifyFlag.value = false; |
| 76 | 76 | store.tempToken = res.data.data.token |
| 77 | - proxy.$u.route(`pages/wode/choose/index`, res.data.data) | |
| 77 | + uni.navigateTo({ | |
| 78 | + url: `/pages/wode/choose/index?ruleVos= ${encodeURIComponent(JSON.stringify(res.data.data.ruleVos))}` | |
| 79 | + }); | |
| 78 | 80 | } else { |
| 79 | 81 | verifyFlag.value = true; |
| 80 | 82 | } | ... | ... |
garbage-removal/src/pages/login/index.vue
| ... | ... | @@ -21,11 +21,14 @@ |
| 21 | 21 | </view> |
| 22 | 22 | </view> --> |
| 23 | 23 | <view class="hint"> |
| 24 | - <u-checkbox-group v-model="agree" placement="row" @change="groupChange"> | |
| 25 | - <u-checkbox shape="circle" :customStyle="{ marginBottom: '8px', marginTop: '2px' }" :key="0" :name="true" | |
| 26 | - @change="radioChange"> | |
| 27 | - </u-checkbox> | |
| 28 | - </u-checkbox-group> | |
| 24 | + <view style="display: flex; justify-content: flex-start;" @click="radioChange"> | |
| 25 | + <u-checkbox-group v-model="agree" placement="row" @change="groupChange"> | |
| 26 | + <!-- 选中颜色为绿色 --> | |
| 27 | + <u-checkbox shape="square" activeColor="green" :size="24" | |
| 28 | + :customStyle="{ marginBottom: '0px', marginTop: '1px' }" :key="0" :name="true"> | |
| 29 | + </u-checkbox> | |
| 30 | + </u-checkbox-group> | |
| 31 | + </view> | |
| 29 | 32 | <view class="prompt-txt"> |
| 30 | 33 | 登录代表同意 |
| 31 | 34 | <text class="link" @click="handleUserAgreement">用户协议、隐私政策,</text> |
| ... | ... | @@ -41,7 +44,7 @@ import { userLogin } from "@/apis/user.js"; |
| 41 | 44 | export default { |
| 42 | 45 | data() { |
| 43 | 46 | return { |
| 44 | - tel: '18977778888', | |
| 47 | + tel: '13222222222', | |
| 45 | 48 | agree: [] |
| 46 | 49 | } |
| 47 | 50 | }, |
| ... | ... | @@ -92,8 +95,8 @@ export default { |
| 92 | 95 | handleUserAgreement() { |
| 93 | 96 | console.log("user click agreement"); |
| 94 | 97 | }, |
| 95 | - radioChange(e) { | |
| 96 | - this.agree = e | |
| 98 | + radioChange() { | |
| 99 | + this.agree[0] = !this.agree[0] | |
| 97 | 100 | }, |
| 98 | 101 | handleWeixinLogin(wxInfo) { |
| 99 | 102 | uni.login({ |
| ... | ... | @@ -190,7 +193,7 @@ export default { |
| 190 | 193 | |
| 191 | 194 | .hint { |
| 192 | 195 | padding: 20rpx 40rpx; |
| 193 | - font-size: 20rpx; | |
| 196 | + font-size: 25rpx; | |
| 194 | 197 | color: $u-tips-color; |
| 195 | 198 | display: flex; |
| 196 | 199 | justify-content: flex-start; | ... | ... |
garbage-removal/src/pages/order/detail/index.vue
| ... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 | @click.stop="handlerJumpOtherApp(dataGram.garLatitude, dataGram.garLongitude, dataGram.garCoordinate)"> |
| 34 | 34 | <text class="order-detail-container-header-title">派单地点:</text> |
| 35 | 35 | <view class="order-detail-container-header-content" style="text-decoration: underline"> |
| 36 | - {{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }} | |
| 36 | + <text selectable='true'>{{ dataGram.garOrderAddress + dataGram.garOrderAddressDetails }}</text> | |
| 37 | 37 | </view> |
| 38 | 38 | </view> |
| 39 | 39 | <view class="order-detail-container-header-item"> |
| ... | ... | @@ -58,7 +58,7 @@ |
| 58 | 58 | <view class="order-detail-container-header-item"> |
| 59 | 59 | <text class="order-detail-container-header-title">派单号:</text> |
| 60 | 60 | <view class="order-detail-container-header-content"> |
| 61 | - {{ orderId }} | |
| 61 | + <text selectable="true">{{ orderId }}</text> | |
| 62 | 62 | </view> |
| 63 | 63 | <!-- 生成二维码 --> |
| 64 | 64 | <view class="order-detail-container-header-qrCode" style="display: flex; align-items: center;"> |
| ... | ... | @@ -104,7 +104,7 @@ |
| 104 | 104 | <view class="order-detail-container-header-item"> |
| 105 | 105 | <text class="order-detail-container-header-title">联系电话:</text> |
| 106 | 106 | <view class="order-detail-container-header-content"> |
| 107 | - {{ dataGram.garOrderContactTel }} | |
| 107 | + <text selectable="true">{{ dataGram.garOrderContactTel }}</text> | |
| 108 | 108 | <view class="icon-box" style="display: flex; align-items: center; justify-content: center;"> |
| 109 | 109 | <u-icon v-if="dataGram.handleFlag" name="phone" size="28" |
| 110 | 110 | @click="handleContactClick(dataGram.garOrderContactTel)"></u-icon> |
| ... | ... | @@ -170,50 +170,50 @@ |
| 170 | 170 | <view class="order-detail-bottom-box"> |
| 171 | 171 | <view class=" order-detail-bottom-left"> |
| 172 | 172 | <u-button v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" |
| 173 | - @click="handleSubmitSuccess(orderId)" shape="circle" color="#a9e08f" text="完成派单"></u-button> | |
| 173 | + @click="handleSubmitSuccess(orderId)" shape="square" color="#a9e08f" text="完成派单"></u-button> | |
| 174 | 174 | <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '企业负责人' && dataGram.garCancelFlag === 0" |
| 175 | - @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 175 | + @click="handleOderCancelClick()" shape="square" color="#a9e08f" text="取消派单"></u-button> | |
| 176 | 176 | <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '运输驾驶员' && dataGram.garCancelFlag === 0" |
| 177 | - @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 177 | + @click="handleOderCancelClick()" shape="square" color="#a9e08f" text="取消派单"></u-button> | |
| 178 | 178 | <u-button v-if="dataGram.garOrderHandlerStatus === 1 && userType == '企业负责人'" |
| 179 | - @click="handleOrderDispatchClick(orderId)" shape="circle" color="#a9e08f" | |
| 179 | + @click="handleOrderDispatchClick(orderId)" shape="square" color="#a9e08f" | |
| 180 | 180 | :text="dataGram.garOrderMatchFlag === 0 ? '派单下发' : '继续下发'"></u-button> |
| 181 | 181 | </view> |
| 182 | 182 | <view class="order-detail-bottom-right"> |
| 183 | 183 | <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '居民用户' && dataGram.garCancelFlag === 0" |
| 184 | - @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 184 | + @click="handleOderCancelClick()" shape="square" color="#a9e08f" text="取消派单"></u-button> | |
| 185 | 185 | <u-button @click="driverHandleOrder(orderId)" |
| 186 | 186 | v-if="dataGram.garOrderHandlerStatus === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" |
| 187 | - shape="circle" color="#a9e08f" text="处理派单"></u-button> | |
| 187 | + shape="square" color="#a9e08f" text="处理派单"></u-button> | |
| 188 | 188 | <u-button @click="handleOrder(orderId)" |
| 189 | 189 | v-if="dataGram.garOrderHandlerStatus === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '企业负责人'" |
| 190 | - shape="circle" color="#a9e08f" text="处理派单"></u-button> | |
| 190 | + shape="square" color="#a9e08f" text="处理派单"></u-button> | |
| 191 | 191 | <u-button @click="handleUploadImage(orderId, 'putOnImages')" |
| 192 | 192 | v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" |
| 193 | - shape="circle" color="#a9e08f" text="上传图片"></u-button> | |
| 193 | + shape="square" color="#a9e08f" text="上传图片"></u-button> | |
| 194 | 194 | <!-- <u-button @click="handleUploadImage(orderId, 'putOnImages')" |
| 195 | 195 | v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putOnImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" |
| 196 | - shape="circle" color="#a9e08f" text="装车照片"></u-button> | |
| 196 | + shape="square" color="#a9e08f" text="装车照片"></u-button> | |
| 197 | 197 | <u-button @click="handleUploadImage(orderId, 'putDownImages')" |
| 198 | 198 | v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" |
| 199 | - shape="circle" color="#a9e08f" text="卸车照片"></u-button> --> | |
| 199 | + shape="square" color="#a9e08f" text="卸车照片"></u-button> --> | |
| 200 | 200 | <!-- <u-button @click="handleUploadImage(orderId, 'putDownImages')" |
| 201 | 201 | v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '企业负责人'" |
| 202 | - shape="circle" color="#a9e08f" text="上传照片"></u-button> --> | |
| 202 | + shape="square" color="#a9e08f" text="上传照片"></u-button> --> | |
| 203 | 203 | <u-button @click="handleEvaluate(orderId, userType)" |
| 204 | - v-if="dataGram.garEvaluateFlag === 0 && userType === '居民用户'" shape="circle" color="#a9e08f" | |
| 204 | + v-if="dataGram.garEvaluateFlag === 0 && userType === '居民用户'" shape="square" color="#a9e08f" | |
| 205 | 205 | text="去评价"></u-button> |
| 206 | 206 | <u-button @click="handleEvaluate(orderId, userType)" |
| 207 | - v-if="dataGram.garHandlerEvaluateFlag === 0 && userType === '企业负责人'" shape="circle" color="#a9e08f" | |
| 207 | + v-if="dataGram.garHandlerEvaluateFlag === 0 && userType === '企业负责人'" shape="square" color="#a9e08f" | |
| 208 | 208 | text="去评价"></u-button> |
| 209 | 209 | <u-button @click="handleEvaluateDetail(orderId, userType)" |
| 210 | - v-if="dataGram.garHandlerEvaluateFlag === 1 && userType === '企业负责人'" shape="circle" color="#a9e08f" | |
| 210 | + v-if="dataGram.garHandlerEvaluateFlag === 1 && userType === '企业负责人'" shape="square" color="#a9e08f" | |
| 211 | 211 | text="查看评价"></u-button> |
| 212 | 212 | <u-button @click="handleEvaluateDetail(orderId, userType)" |
| 213 | - v-if="dataGram.garEvaluateFlag === 1 && userType === '居民用户'" shape="circle" color="#a9e08f" | |
| 213 | + v-if="dataGram.garEvaluateFlag === 1 && userType === '居民用户'" shape="square" color="#a9e08f" | |
| 214 | 214 | text="查看评价"></u-button> |
| 215 | 215 | <u-button v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType != '运输驾驶员'" |
| 216 | - @click="handleSubmitSuccess(orderId)" shape="circle" color="#a9e08f" text="完成派单"></u-button> | |
| 216 | + @click="handleSubmitSuccess(orderId)" shape="square" color="#a9e08f" text="完成派单"></u-button> | |
| 217 | 217 | </view> |
| 218 | 218 | </view> |
| 219 | 219 | </view> |
| ... | ... | @@ -253,30 +253,39 @@ const cancelShow = ref(false) |
| 253 | 253 | const currentCancelName = ref("") |
| 254 | 254 | const qrCodeRef = ref() |
| 255 | 255 | const qrCodeText = ref() |
| 256 | -const list = ref([ | |
| 257 | - { | |
| 258 | - name: '长时间无人接单', | |
| 259 | - }, | |
| 260 | - { | |
| 261 | - name: '派单信息填写有误', | |
| 262 | - }, | |
| 263 | - { | |
| 264 | - name: '线下协商有问题', | |
| 265 | - }, | |
| 266 | - { | |
| 267 | - name: '不需要清运了', | |
| 268 | - }, | |
| 269 | - { | |
| 270 | - name: '其他', | |
| 271 | - }, | |
| 272 | - { | |
| 273 | - name: '提交', | |
| 256 | +const list = computed(() => { | |
| 257 | + let reason = [ | |
| 258 | + { | |
| 259 | + name: '派单信息填写有误', | |
| 260 | + }, | |
| 261 | + { | |
| 262 | + name: '线下协商有问题', | |
| 263 | + }, | |
| 264 | + { | |
| 265 | + name: '不需要清运了', | |
| 266 | + }, | |
| 267 | + { | |
| 268 | + name: '其他', | |
| 269 | + }, | |
| 270 | + { | |
| 271 | + name: '提交', | |
| 272 | + } | |
| 273 | + ] | |
| 274 | + if (userType.value === '居民用户') { | |
| 275 | + reason.unshift({ | |
| 276 | + name: '长时间无人接单', | |
| 277 | + }) | |
| 278 | + } else { | |
| 279 | + reason.unshift({ | |
| 280 | + name: '无修改权限' | |
| 281 | + }) | |
| 274 | 282 | } |
| 275 | -]) | |
| 283 | + return reason | |
| 284 | +}) | |
| 276 | 285 | |
| 277 | 286 | // 创建二维码 |
| 278 | 287 | const createQrCodeLocal = (orderId) => { |
| 279 | - // 获取本地地址拼接订单id | |
| 288 | + // 获取本地地址拼接派单id | |
| 280 | 289 | showUQRcode.value = true; |
| 281 | 290 | const hostname = window.location.hostname; |
| 282 | 291 | const port = window.location.port; |
| ... | ... | @@ -362,7 +371,6 @@ const handleContactClick = (val) => { |
| 362 | 371 | } |
| 363 | 372 | |
| 364 | 373 | const handlerJumpOtherApp = (latitude, longitude, garCoordinate) => { |
| 365 | - console.log(latitude, longitude); | |
| 366 | 374 | // 给出提示确定要跳转吗 |
| 367 | 375 | uni.showModal({ |
| 368 | 376 | title: '提示', | ... | ... |
garbage-removal/src/pages/order/upload/index.vue
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | <view class="upload-image-box-submit-box"> |
| 21 | 21 | <view class="upload-image-box-submit-box-button" @click="handleSubmit(orderId, putType)"> |
| 22 | 22 | <view class="upload-image-box-submit-box-button-container"> |
| 23 | - <up-button color="#19be6b" type="primary" shape="circle" text="确定"></up-button> | |
| 23 | + <up-button color="#19be6b" type="primary" shape="square" text="确定"></up-button> | |
| 24 | 24 | </view> |
| 25 | 25 | </view> |
| 26 | 26 | </view> | ... | ... |
garbage-removal/src/pages/wode/choose/index.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="wrap"> |
| 3 | - <u-radio-group v-model="userType" placement="row" @change="groupChange"> | |
| 4 | - <view class="choose-type" v-for="(item, index) in typeList"> | |
| 5 | - <u-radio size="28" labelSize="28" :key="index" :label="item.name" :name="item.name" @change="radioChange"> | |
| 6 | - </u-radio> | |
| 7 | - </view> | |
| 8 | - </u-radio-group> | |
| 9 | - <!-- 角色信息匹配 --> | |
| 10 | - <view class="rule-label-info-box"> | |
| 11 | - <view class="manager-info" v-if="userType === '居民用户'"> | |
| 12 | - <view class="manager-info-parent-company-name"> | |
| 13 | - 派单前请输先完善地址信息~ | |
| 14 | - </view> | |
| 15 | - </view> | |
| 16 | - <view class="manager-info" v-if="userType === '运输驾驶员'"> | |
| 17 | - <view v-if="tempUserType === '运输驾驶员'" class="manager-info-parent-company-name"> | |
| 18 | - {{ unitInfo.transportCompanyName }}运输公司-运输驾驶员 | |
| 19 | - </view> | |
| 20 | - <view v-else class="manager-info-parent-company-name"> | |
| 21 | - 未匹配到该手机号绑定的运输公司! | |
| 3 | + <view class="choose-type-box"> | |
| 4 | + <view class="choose-type-item" :class="item.isNow ? 'itemActive' : ''" v-for=" (item, index) in typeList" | |
| 5 | + :key="index" @click="handlerClick(item)"> | |
| 6 | + <view class="choose-type-item-top" :class="item.classStyle"> | |
| 7 | + <view class="choose-type-item-image" width="100%" height="100%"> | |
| 8 | + <image :src="item.image" shape="circle" mode="aspectFill"> | |
| 9 | + </image> | |
| 10 | + </view> | |
| 11 | + <view class="choose-type-item-text"> | |
| 12 | + <view class="choose-type-item-text-right"> | |
| 13 | + <view v-if="item.company" class="choose-tyep-item-text-right-compay"> | |
| 14 | + {{ item.company }} | |
| 15 | + </view> | |
| 16 | + <view class="choose-tyep-item-text-right-info"> | |
| 17 | + {{ item.info }} | |
| 18 | + </view> | |
| 19 | + <view class="choose-type-item-text-right-label"> | |
| 20 | + {{ item.label }} | |
| 21 | + </view> | |
| 22 | + </view> | |
| 23 | + </view> | |
| 22 | 24 | </view> |
| 23 | - </view> | |
| 24 | - <view class="manager-info" v-if="userType === '企业负责人'"> | |
| 25 | - <view v-if="tempUserType === '企业负责人'" class="manager-info-parent-company-name"> | |
| 26 | - {{ unitInfo.transportCompanyName }}服务账号 | |
| 27 | - </view> | |
| 28 | - <view v-else class="manager-info-parent-company-name"> | |
| 29 | - 未匹配到该手机号绑定运输公司公司服务账号! | |
| 25 | + <view class="choose-type-item-bottom"> | |
| 26 | + <view class="choose-type-item-bottom-button" | |
| 27 | + :class="item.isNow ? 'choose-type-item-bottom-button-active' : ''"> | |
| 28 | + {{ item.isNow ? '当前身份' : '切换此身份' }} | |
| 29 | + <up-icon name="checkmark-circle-fill" :color="item.isNow ? '#35bef7' : ''" size="28"></up-icon> | |
| 30 | + </view> | |
| 30 | 31 | </view> |
| 31 | 32 | </view> |
| 32 | 33 | </view> |
| 33 | - <view class="choose-button"> | |
| 34 | - <u-button shape="circle" color="#a9e08f" @click="submit(userType)">确定</u-button> | |
| 34 | + <view class="choose-user-bottom-button-box"> | |
| 35 | + <view class="choose-user-bottom-button-box-button" @click="submit(userType)"> | |
| 36 | + 下一步 | |
| 37 | + </view> | |
| 35 | 38 | </view> |
| 36 | 39 | </view> |
| 40 | + | |
| 41 | + | |
| 37 | 42 | </template> |
| 38 | 43 | |
| 39 | 44 | <script setup> |
| ... | ... | @@ -42,25 +47,72 @@ import { useMainStore } from '@/stores/index.js'; |
| 42 | 47 | import { setRequestToken } from '@/utils/request/request.js'; |
| 43 | 48 | import { onLoad } from "@dcloudio/uni-app"; |
| 44 | 49 | import { ref } from 'vue'; |
| 50 | +const userType = ref('') | |
| 51 | +const imageBase = "data:image/jpeg;base64,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"; | |
| 45 | 52 | const store = useMainStore(); |
| 46 | -const userType = ref("居民用户") | |
| 47 | -const tempUserType = ref() | |
| 48 | -const typeList = ref([{ name: "居民用户" }, { name: "运输驾驶员" }, { name: "企业负责人" }]) | |
| 49 | -const unitInfo = ref({}) | |
| 50 | -const radioChange = (e) => { | |
| 51 | -} | |
| 52 | -const groupChange = (e) => { | |
| 53 | +const typeList = ref([{ | |
| 54 | + label: "居民用户", | |
| 55 | + info: '下单清运', | |
| 56 | + image: imageBase, | |
| 57 | + order: 999, | |
| 58 | + classStyle: 'choose-type-item-top-back-sky', | |
| 59 | + isNow: false, | |
| 60 | + isExit: true, | |
| 61 | +}, { | |
| 62 | + label: "处理场所", | |
| 63 | + info: '负责现场指导', | |
| 64 | + company: '长沙xxxx', | |
| 65 | + image: imageBase, | |
| 66 | + isExit: false, | |
| 67 | + classStyle: 'choose-type-item-top-back-pink', | |
| 68 | + order: 3, | |
| 69 | + isNow: false, | |
| 70 | +}, { | |
| 71 | + label: "运输驾驶员", | |
| 72 | + info: '负责垃圾清运', | |
| 73 | + company: '长沙xxxx', | |
| 74 | + image: imageBase, | |
| 75 | + isExit: false, | |
| 76 | + classStyle: 'choose-type-item-top-back-blue', | |
| 77 | + order: 2, | |
| 78 | + isNow: false, | |
| 79 | +}, { | |
| 80 | + label: "企业负责人", | |
| 81 | + info: '负责订单处理', | |
| 82 | + company: '长沙xxxx', | |
| 83 | + image: imageBase, | |
| 84 | + isExit: false, | |
| 85 | + classStyle: 'choose-type-item-top-back-sun', | |
| 86 | + order: 1, | |
| 87 | + isNow: false, | |
| 88 | +}]) | |
| 89 | +const unitInfo = ref([]) | |
| 90 | +const handlerClick = (val) => { | |
| 91 | + if (val.isExit) { | |
| 92 | + val.isNow = true; | |
| 93 | + userType.value = val.label; | |
| 94 | + typeList.value.forEach((item) => { | |
| 95 | + if (val.label !== item.label) { | |
| 96 | + item.isNow = false | |
| 97 | + } | |
| 98 | + }) | |
| 99 | + } else { | |
| 100 | + // 提示 当前账号未绑定,无法选中 | |
| 101 | + uni.showToast({ | |
| 102 | + title: '账号未绑定,无法选中', | |
| 103 | + icon: 'none', | |
| 104 | + duration: 1500 | |
| 105 | + }) | |
| 106 | + } | |
| 53 | 107 | } |
| 54 | - | |
| 55 | 108 | const submit = (userType) => { |
| 56 | 109 | setRequestToken(store.tempToken) |
| 57 | 110 | updateUserInfo({ garUserType: userType }).then(res => { |
| 58 | - store.token = store.tempToken | |
| 59 | - store.tempToken = ""; | |
| 60 | 111 | if (res.data.success) { |
| 112 | + store.token = store.tempToken | |
| 113 | + store.tempToken = ""; | |
| 61 | 114 | store.userType = userType; |
| 62 | - unitInfo.value.userType = userType | |
| 63 | - store.userInfo = unitInfo.value | |
| 115 | + store.userInfo = unitInfo.value[userType] | |
| 64 | 116 | uni.$u.route({ |
| 65 | 117 | type: "switchTab", |
| 66 | 118 | url: `pages/home/index`, |
| ... | ... | @@ -70,10 +122,29 @@ const submit = (userType) => { |
| 70 | 122 | |
| 71 | 123 | } |
| 72 | 124 | onLoad((options) => { |
| 73 | - unitInfo.value = options | |
| 74 | - userType.value = options.userType | |
| 75 | - tempUserType.value = options.userType | |
| 76 | - // submit(options.userType) | |
| 125 | + // let loginInfo = JSON.parse(options) | |
| 126 | + let loginInfo = JSON.parse(decodeURIComponent(options.ruleVos)) | |
| 127 | + for (let index = 0; index < loginInfo.length; index++) { | |
| 128 | + const element = loginInfo[index]; | |
| 129 | + unitInfo.value[element.userType] = element | |
| 130 | + } | |
| 131 | + let order = 999; | |
| 132 | + let index = 0; | |
| 133 | + // typeList优先级最高的设置isNow 为 true | |
| 134 | + if (loginInfo.length > 1) { | |
| 135 | + typeList.value.forEach((item, i) => { | |
| 136 | + if (unitInfo.value[item.label]) { | |
| 137 | + item.isExit = true; | |
| 138 | + if (item.order < order) { | |
| 139 | + order = item.order; | |
| 140 | + index = i; | |
| 141 | + } | |
| 142 | + } | |
| 143 | + }) | |
| 144 | + typeList.value[index].isNow = true | |
| 145 | + userType.value = typeList.value[index].label | |
| 146 | + } | |
| 147 | + console.log(typeList.value, "typeList.value"); | |
| 77 | 148 | }) |
| 78 | 149 | </script> |
| 79 | 150 | |
| ... | ... | @@ -82,50 +153,177 @@ onLoad((options) => { |
| 82 | 153 | height: 100%; |
| 83 | 154 | width: 100%; |
| 84 | 155 | box-sizing: border-box; |
| 85 | - padding: 20rpx; | |
| 156 | + // padding: 20rpx; | |
| 86 | 157 | background-color: $u-info-light; |
| 87 | 158 | |
| 88 | - .choose-type { | |
| 89 | - // width: 100%; | |
| 90 | - box-sizing: border-box; | |
| 91 | - padding: 20rpx; | |
| 92 | - background-color: #ffffff; | |
| 93 | - border-radius: 20rpx; | |
| 94 | - margin-right: 20rpx; | |
| 159 | + | |
| 160 | + .choose-type-box { | |
| 161 | + width: 750rpx; | |
| 95 | 162 | display: flex; |
| 96 | - align-items: center; | |
| 163 | + flex-direction: column; | |
| 97 | 164 | justify-content: center; |
| 165 | + align-items: center; | |
| 166 | + box-sizing: border-box; | |
| 167 | + padding: 20rpx 70rpx; | |
| 168 | + | |
| 169 | + .choose-type-item { | |
| 170 | + width: 100%; | |
| 171 | + height: 270rpx; | |
| 172 | + box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1); | |
| 173 | + margin-bottom: 40rpx; | |
| 174 | + border-radius: 15rpx 15rpx 0rpx 0rpx; | |
| 175 | + | |
| 176 | + | |
| 177 | + .choose-type-item-top-back-blue { | |
| 178 | + background: linear-gradient(135deg, #a1c4fd, #c2e9fb) !important; | |
| 179 | + } | |
| 180 | + | |
| 181 | + .choose-type-item-top-back-pink { | |
| 182 | + background: linear-gradient(135deg, #c7e9fb, #a6defa, #80d4f9, #5bc9f8, #35bef7) !important; | |
| 183 | + } | |
| 184 | + | |
| 185 | + .choose-type-item-top-back-sun { | |
| 186 | + background: linear-gradient(135deg, #f6d365, #fda085) !important; | |
| 187 | + } | |
| 188 | + | |
| 189 | + .choose-type-item-top-back-sky { | |
| 190 | + background: linear-gradient(135deg, #c2ef8c, #83e455) !important; | |
| 191 | + } | |
| 192 | + | |
| 193 | + .choose-type-item-top { | |
| 194 | + height: 235rpx; | |
| 195 | + display: flex; | |
| 196 | + align-items: center; | |
| 197 | + box-sizing: border-box; | |
| 198 | + padding: 30rpx; | |
| 199 | + border-radius: 15rpx 15rpx 5rpx 5rpx; | |
| 200 | + box-shadow: 0px 2px 10px 0px rgba(0, 0, 0, 0.1); | |
| 201 | + | |
| 202 | + .choose-type-item-image { | |
| 203 | + width: 140rpx; | |
| 204 | + height: 170rpx; | |
| 205 | + border-radius: 50%; | |
| 206 | + display: flex; | |
| 207 | + align-items: center; | |
| 208 | + justify-content: flex-start; | |
| 209 | + margin-right: 20rpx; | |
| 210 | + | |
| 211 | + image { | |
| 212 | + width: 100%; | |
| 213 | + height: 100%; | |
| 214 | + } | |
| 215 | + } | |
| 216 | + | |
| 217 | + .choose-type-item-text { | |
| 218 | + width: 100%; | |
| 219 | + height: 100%; | |
| 220 | + | |
| 221 | + .choose-type-item-text-right { | |
| 222 | + width: 100%; | |
| 223 | + height: 100%; | |
| 224 | + display: flex; | |
| 225 | + flex-direction: column; | |
| 226 | + align-items: flex-start; | |
| 227 | + justify-content: space-around; | |
| 228 | + color: white; | |
| 229 | + | |
| 230 | + .choose-tyep-item-text-right-info { | |
| 231 | + font-size: 28rpx; | |
| 232 | + } | |
| 233 | + | |
| 234 | + .choose-tyep-item-text-right-compay { | |
| 235 | + font-weight: bolder; | |
| 236 | + line-height: 35rpx; | |
| 237 | + font-size: 32rpx; | |
| 238 | + } | |
| 239 | + | |
| 240 | + .choose-type-item-text-right-label { | |
| 241 | + font-size: 23rpx; | |
| 242 | + padding: 8rpx 15rpx; | |
| 243 | + border-radius: 5rpx; | |
| 244 | + color: $u-info-dark; | |
| 245 | + font-weight: 600; | |
| 246 | + margin-bottom: 10rpx; | |
| 247 | + background: #ffffffad; | |
| 248 | + border: 3rpx solid white; | |
| 249 | + } | |
| 250 | + } | |
| 251 | + } | |
| 252 | + | |
| 253 | + } | |
| 254 | + | |
| 255 | + .choose-type-item-bottom { | |
| 256 | + width: 100%; | |
| 257 | + height: 35rpx; | |
| 258 | + box-sizing: border-box; | |
| 259 | + display: flex; | |
| 260 | + align-items: center; | |
| 261 | + justify-content: flex-end; | |
| 262 | + background: #ffffff; | |
| 263 | + | |
| 264 | + .choose-type-item-bottom-button { | |
| 265 | + font-size: 25rpx; | |
| 266 | + color: #999999; | |
| 267 | + display: flex; | |
| 268 | + } | |
| 269 | + | |
| 270 | + .choose-type-item-bottom-button-active { | |
| 271 | + color: #35bef7 !important; | |
| 272 | + } | |
| 273 | + } | |
| 274 | + } | |
| 98 | 275 | |
| 99 | - &:last-child { | |
| 100 | - margin-right: 20rpx; | |
| 276 | + .itemActive { | |
| 277 | + animation: overScroll 0.5s forwards ease-in-out; | |
| 101 | 278 | } |
| 102 | 279 | |
| 280 | + @keyframes overScroll { | |
| 281 | + 0% { | |
| 282 | + transform: translateY(8rpx); | |
| 283 | + } | |
| 103 | 284 | |
| 104 | - } | |
| 285 | + 20% { | |
| 286 | + transform: translateY(-4rpx); | |
| 287 | + } | |
| 105 | 288 | |
| 106 | - .rule-label-info-box { | |
| 107 | - box-sizing: border-box; | |
| 108 | - margin-top: 20rpx; | |
| 289 | + 40% { | |
| 290 | + transform: translateY(8rpx); | |
| 291 | + } | |
| 109 | 292 | |
| 110 | - .manager-info { | |
| 111 | - font-size: 25rpx; | |
| 112 | - color: $u-main-color; | |
| 113 | - box-sizing: border-box; | |
| 293 | + 60% { | |
| 294 | + transform: translateY(-4rpx); | |
| 295 | + } | |
| 114 | 296 | |
| 115 | - .manager-info-parent-company-name { | |
| 116 | - color: $u-info; | |
| 297 | + 80% { | |
| 298 | + transform: translateY(8rpx); | |
| 299 | + } | |
| 300 | + | |
| 301 | + 100% { | |
| 302 | + transform: translateY(0); | |
| 117 | 303 | } |
| 118 | 304 | } |
| 119 | 305 | } |
| 120 | 306 | |
| 121 | - | |
| 122 | - .choose-button { | |
| 123 | - position: relative; | |
| 307 | + .choose-user-bottom-button-box { | |
| 124 | 308 | width: 100%; |
| 125 | - height: 100%; | |
| 309 | + height: 80rpx; | |
| 126 | 310 | display: flex; |
| 127 | - justify-content: center; | |
| 128 | 311 | align-items: center; |
| 312 | + justify-content: center; | |
| 313 | + box-sizing: border-box; | |
| 314 | + | |
| 315 | + .choose-user-bottom-button-box-button { | |
| 316 | + width: 80%; | |
| 317 | + height: 100%; | |
| 318 | + background: #23d283; | |
| 319 | + border-radius: 30rpx; | |
| 320 | + color: white; | |
| 321 | + font-size: 30rpx; | |
| 322 | + display: flex; | |
| 323 | + align-items: center; | |
| 324 | + justify-content: center; | |
| 325 | + @include handleClick; | |
| 326 | + } | |
| 129 | 327 | } |
| 130 | 328 | } |
| 131 | 329 | </style> | ... | ... |
garbage-removal/src/static/image/garbage.png
0 → 100644
249 KB
garbage-removal/src/uview-plus/components/u-calendar/u-calendar.vue
| 1 | 1 | <template> |
| 2 | - <u-popup | |
| 3 | - :show="show" | |
| 4 | - mode="bottom" | |
| 5 | - closeable | |
| 6 | - @close="close" | |
| 7 | - :round="round" | |
| 8 | - :closeOnClickOverlay="closeOnClickOverlay" | |
| 9 | - > | |
| 2 | + <u-popup :show="show" mode="bottom" closeable @close="close" :round="round" | |
| 3 | + :closeOnClickOverlay="closeOnClickOverlay"> | |
| 10 | 4 | <view class="u-calendar"> |
| 11 | - <uHeader | |
| 12 | - :title="title" | |
| 13 | - :subtitle="subtitle" | |
| 14 | - :showSubtitle="showSubtitle" | |
| 15 | - :showTitle="showTitle" | |
| 16 | - ></uHeader> | |
| 17 | - <scroll-view | |
| 18 | - :style="{ | |
| 19 | - height: $u.addUnit(listHeight) | |
| 20 | - }" | |
| 21 | - scroll-y | |
| 22 | - @scroll="onScroll" | |
| 23 | - :scroll-top="scrollTop" | |
| 24 | - :scrollIntoView="scrollIntoView" | |
| 25 | - > | |
| 26 | - <uMonth | |
| 27 | - :color="color" | |
| 28 | - :rowHeight="rowHeight" | |
| 29 | - :showMark="showMark" | |
| 30 | - :months="months" | |
| 31 | - :mode="mode" | |
| 32 | - :maxCount="maxCount" | |
| 33 | - :startText="startText" | |
| 34 | - :endText="endText" | |
| 35 | - :defaultDate="defaultDate" | |
| 36 | - :minDate="innerMinDate" | |
| 37 | - :maxDate="innerMaxDate" | |
| 38 | - :maxMonth="monthNum" | |
| 39 | - :readonly="readonly" | |
| 40 | - :maxRange="maxRange" | |
| 41 | - :rangePrompt="rangePrompt" | |
| 42 | - :showRangePrompt="showRangePrompt" | |
| 43 | - :allowSameDay="allowSameDay" | |
| 44 | - ref="month" | |
| 45 | - @monthSelected="monthSelected" | |
| 46 | - @updateMonthTop="updateMonthTop" | |
| 47 | - ></uMonth> | |
| 5 | + <uHeader :title="title" :subtitle="subtitle" :showSubtitle="showSubtitle" :showTitle="showTitle"></uHeader> | |
| 6 | + <scroll-view :style="{ | |
| 7 | + height: $u.addUnit(listHeight) | |
| 8 | + }" scroll-y @scroll="onScroll" :scroll-top="scrollTop" :scrollIntoView="scrollIntoView"> | |
| 9 | + <uMonth :color="color" :rowHeight="rowHeight" :showMark="showMark" :months="months" :mode="mode" | |
| 10 | + :maxCount="maxCount" :startText="startText" :endText="endText" :defaultDate="defaultDate" | |
| 11 | + :minDate="innerMinDate" :maxDate="innerMaxDate" :maxMonth="monthNum" :readonly="readonly" :maxRange="maxRange" | |
| 12 | + :rangePrompt="rangePrompt" :showRangePrompt="showRangePrompt" :allowSameDay="allowSameDay" ref="month" | |
| 13 | + @monthSelected="monthSelected" @updateMonthTop="updateMonthTop"></uMonth> | |
| 48 | 14 | </scroll-view> |
| 49 | 15 | <slot name="footer" v-if="showConfirm"> |
| 50 | 16 | <view class="u-calendar__confirm"> |
| 51 | - <u-button | |
| 52 | - shape="circle" | |
| 53 | - :text=" | |
| 54 | - buttonDisabled ? confirmDisabledText : confirmText | |
| 55 | - " | |
| 56 | - :color="color" | |
| 57 | - @click="confirm" | |
| 58 | - :disabled="buttonDisabled" | |
| 59 | - ></u-button> | |
| 17 | + <u-button shape="square" :text="buttonDisabled ? confirmDisabledText : confirmText | |
| 18 | + " :color="color" @click="confirm" :disabled="buttonDisabled"></u-button> | |
| 60 | 19 | </view> |
| 61 | 20 | </slot> |
| 62 | 21 | </view> |
| ... | ... | @@ -67,12 +26,11 @@ |
| 67 | 26 | import uHeader from './header.vue' |
| 68 | 27 | import uMonth from './month.vue' |
| 69 | 28 | import props from './props.js' |
| 70 | -import util from './util.js' | |
| 71 | 29 | // import dayjs from '../../libs/util/dayjs.min.js' |
| 72 | 30 | import dayjs from 'dayjs/esm/index' |
| 73 | -import Calendar from '../../libs/util/calendar.js' | |
| 74 | -import mpMixin from '../../libs/mixin/mpMixin.js' | |
| 75 | 31 | import mixin from '../../libs/mixin/mixin.js' |
| 32 | +import mpMixin from '../../libs/mixin/mpMixin.js' | |
| 33 | +import Calendar from '../../libs/util/calendar.js' | |
| 76 | 34 | /** |
| 77 | 35 | * Calendar 日历 |
| 78 | 36 | * @description 此组件用于单个选择日期,范围选择日期等,日历被包裹在底部弹起的容器中. |
| ... | ... | @@ -129,7 +87,7 @@ export default { |
| 129 | 87 | // month组件中选择的日期数组 |
| 130 | 88 | selected: [], |
| 131 | 89 | scrollIntoView: '', |
| 132 | - scrollTop:0, | |
| 90 | + scrollTop: 0, | |
| 133 | 91 | // 过滤处理方法 |
| 134 | 92 | innerFormatter: (value) => value |
| 135 | 93 | } |
| ... | ... | @@ -168,9 +126,8 @@ export default { |
| 168 | 126 | subtitle() { |
| 169 | 127 | // 初始化时,this.months为空数组,所以需要特别判断处理 |
| 170 | 128 | if (this.months.length) { |
| 171 | - return `${this.months[this.monthIndex].year}年${ | |
| 172 | - this.months[this.monthIndex].month | |
| 173 | - }月` | |
| 129 | + return `${this.months[this.monthIndex].year}年${this.months[this.monthIndex].month | |
| 130 | + }月` | |
| 174 | 131 | } else { |
| 175 | 132 | return '' |
| 176 | 133 | } |
| ... | ... | @@ -320,9 +277,9 @@ export default { |
| 320 | 277 | scrollIntoDefaultMonth(selected) { |
| 321 | 278 | // 查询默认日期在可选列表的下标 |
| 322 | 279 | const _index = this.months.findIndex(({ |
| 323 | - year, | |
| 324 | - month | |
| 325 | - }) => { | |
| 280 | + year, | |
| 281 | + month | |
| 282 | + }) => { | |
| 326 | 283 | month = uni.$u.padZero(month) |
| 327 | 284 | return `${year}-${month}` === selected |
| 328 | 285 | }) | ... | ... |
garbage-removal/src/uview-plus/components/u-cell-group/props.js
garbage-removal/src/uview-plus/components/u-cell-group/u-cell-group.vue
| 1 | 1 | <template> |
| 2 | - <view :style="[$u.addStyle(customStyle)]" :class="[customClass]" class="u-cell-group"> | |
| 3 | - <view v-if="title" class="u-cell-group__title"> | |
| 4 | - <slot name="title"> | |
| 2 | + <view :style="[$u.addStyle(activeStyle)]" :class="[customClass]" class="u-cell-group"> | |
| 3 | + <view v-if="title" class="u-cell-group__title"> | |
| 4 | + <slot name="title"> | |
| 5 | 5 | <text class="u-cell-group__title__text">{{ title }}</text> |
| 6 | 6 | </slot> |
| 7 | - </view> | |
| 8 | - <view class="u-cell-group__wrapper"> | |
| 7 | + </view> | |
| 8 | + <view class="u-cell-group__wrapper"> | |
| 9 | 9 | <u-line v-if="border"></u-line> |
| 10 | - <slot /> | |
| 11 | - </view> | |
| 12 | - </view> | |
| 10 | + <slot /> | |
| 11 | + </view> | |
| 12 | + </view> | |
| 13 | 13 | </template> |
| 14 | 14 | |
| 15 | 15 | <script> |
| 16 | - import props from './props.js'; | |
| 17 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 18 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 19 | - /** | |
| 20 | - * cellGroup 单元格 | |
| 21 | - * @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。 | |
| 22 | - * @tutorial https://uviewui.com/components/cell.html | |
| 23 | - * | |
| 24 | - * @property {String} title 分组标题 | |
| 25 | - * @property {Boolean} border 是否显示外边框 (默认 true ) | |
| 26 | - * @property {Object} customStyle 定义需要用到的外部样式 | |
| 27 | - * | |
| 28 | - * @event {Function} click 点击cell列表时触发 | |
| 29 | - * @example <u-cell-group title="设置喜好"> | |
| 30 | - */ | |
| 31 | - export default { | |
| 32 | - name: 'u-cell-group', | |
| 33 | - mixins: [mpMixin, mixin, props], | |
| 34 | - } | |
| 16 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 17 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 18 | +import props from './props.js'; | |
| 19 | +/** | |
| 20 | + * cellGroup 单元格 | |
| 21 | + * @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。 | |
| 22 | + * @tutorial https://uviewui.com/components/cell.html | |
| 23 | + * | |
| 24 | + * @property {String} title 分组标题 | |
| 25 | + * @property {Boolean} border 是否显示外边框 (默认 true ) | |
| 26 | + * @property {Object} customStyle 定义需要用到的外部样式 | |
| 27 | + * | |
| 28 | + * @event {Function} click 点击cell列表时触发 | |
| 29 | + * @example <u-cell-group title="设置喜好"> | |
| 30 | + */ | |
| 31 | +export default { | |
| 32 | + name: 'u-cell-group', | |
| 33 | + mixins: [mpMixin, mixin, props], | |
| 34 | +} | |
| 35 | 35 | </script> |
| 36 | 36 | |
| 37 | 37 | <style lang="scss" scoped> |
| 38 | - @import "../../libs/css/components.scss"; | |
| 39 | - | |
| 40 | - $u-cell-group-title-padding: 16px 16px 8px !default; | |
| 41 | - $u-cell-group-title-font-size: 15px !default; | |
| 42 | - $u-cell-group-title-line-height: 16px !default; | |
| 43 | - $u-cell-group-title-color: $u-main-color !default; | |
| 38 | +@import "../../libs/css/components.scss"; | |
| 39 | + | |
| 40 | +$u-cell-group-title-padding: 16px 16px 8px !default; | |
| 41 | +$u-cell-group-title-font-size: 15px !default; | |
| 42 | +$u-cell-group-title-line-height: 16px !default; | |
| 43 | +$u-cell-group-title-color: $u-main-color !default; | |
| 44 | 44 | |
| 45 | - .u-cell-group { | |
| 46 | - flex: 1; | |
| 47 | - | |
| 48 | - &__title { | |
| 49 | - padding: $u-cell-group-title-padding; | |
| 45 | +.u-cell-group { | |
| 46 | + flex: 1; | |
| 50 | 47 | |
| 51 | - &__text { | |
| 52 | - font-size: $u-cell-group-title-font-size; | |
| 53 | - line-height: $u-cell-group-title-line-height; | |
| 54 | - color: $u-cell-group-title-color; | |
| 55 | - } | |
| 56 | - } | |
| 57 | - | |
| 58 | - &__wrapper { | |
| 59 | - position: relative; | |
| 48 | + &__title { | |
| 49 | + padding: $u-cell-group-title-padding; | |
| 50 | + | |
| 51 | + &__text { | |
| 52 | + font-size: $u-cell-group-title-font-size; | |
| 53 | + line-height: $u-cell-group-title-line-height; | |
| 54 | + color: $u-cell-group-title-color; | |
| 60 | 55 | } |
| 61 | - } | |
| 62 | -</style> | |
| 56 | + } | |
| 63 | 57 | |
| 58 | + &__wrapper { | |
| 59 | + position: relative; | |
| 60 | + } | |
| 61 | +} | |
| 62 | +</style> | ... | ... |
garbage-removal/src/uview-plus/components/u-checkbox/u-checkbox.vue
| ... | ... | @@ -7,10 +7,10 @@ |
| 7 | 7 | </slot> |
| 8 | 8 | </view> |
| 9 | 9 | <text @tap.stop="labelClickHandler" :style="{ |
| 10 | - color: elDisabled ? elInactiveColor : elLabelColor, | |
| 11 | - fontSize: elLabelSize, | |
| 12 | - lineHeight: elLabelSize | |
| 13 | - }" style="flex-wrap: wrap;">{{ label }}</text> | |
| 10 | + color: elDisabled ? elInactiveColor : elLabelColor, | |
| 11 | + fontSize: elLabelSize, | |
| 12 | + lineHeight: elLabelSize | |
| 13 | + }" style="flex-wrap: wrap;">{{ label }}</text> | |
| 14 | 14 | </view> |
| 15 | 15 | </template> |
| 16 | 16 | |
| ... | ... | @@ -89,7 +89,7 @@ export default { |
| 89 | 89 | }, |
| 90 | 90 | // 组件选中激活时的颜色 |
| 91 | 91 | elActiveColor() { |
| 92 | - return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 92 | + return this.activeColor ? "#5ac725" : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 93 | 93 | }, |
| 94 | 94 | // 组件选未中激活时的颜色 |
| 95 | 95 | elInactiveColor() { | ... | ... |
garbage-removal/src/uview-plus/components/u-dropdown-item/props.js
| 1 | -import defprops from '../../libs/config/props'; | |
| 2 | 1 | export default { |
| 3 | 2 | props: { |
| 3 | + // #ifdef VUE3 | |
| 4 | 4 | // 当前选中项的value值 |
| 5 | + modelValue: { | |
| 6 | + type: [Number, String, Array], | |
| 7 | + default: '' | |
| 8 | + }, | |
| 9 | + // #endif | |
| 10 | + // #ifdef VUE2 | |
| 11 | + // 当前选中项的value值 | |
| 5 | 12 | value: { |
| 6 | 13 | type: [Number, String, Array], |
| 7 | 14 | default: '' |
| 8 | 15 | }, |
| 16 | + // #endif | |
| 9 | 17 | // 菜单项标题 |
| 10 | 18 | title: { |
| 11 | 19 | type: [String, Number], |
| ... | ... | @@ -32,6 +40,11 @@ export default { |
| 32 | 40 | closeOnClickOverlay: { |
| 33 | 41 | type: Boolean, |
| 34 | 42 | default: true |
| 43 | + }, | |
| 44 | + // 对齐方式 | |
| 45 | + placement: { | |
| 46 | + type: String, | |
| 47 | + default: 'center' | |
| 35 | 48 | } |
| 36 | 49 | } |
| 37 | 50 | } | ... | ... |
garbage-removal/src/uview-plus/components/u-dropdown-item/u-dropdown-item.vue
| 1 | 1 | <template> |
| 2 | - <view class="u-drawdown-item"> | |
| 3 | - <u-overlay | |
| 4 | - customStyle="top: 126px" | |
| 5 | - :show="show" | |
| 6 | - :closeOnClickOverlay="closeOnClickOverlay" | |
| 7 | - @click="overlayClick" | |
| 8 | - ></u-overlay> | |
| 9 | - <view | |
| 10 | - class="u-drawdown-item__content" | |
| 11 | - :style="[style]" | |
| 12 | - :animation="animationData" | |
| 13 | - ref="animation" | |
| 14 | - > | |
| 15 | - <slot /> | |
| 16 | - </view> | |
| 2 | + <view class="u-dropdown-item" v-if="active" @touchmove.stop.prevent="() => { }" @tap.stop.prevent="() => { }"> | |
| 3 | + <block v-if="!$slots.default && !$slots.$default"> | |
| 4 | + <scroll-view scroll-y="true" :style="{ height: $u.addUnit(height) }"> | |
| 5 | + <view class="u-dropdown-item__options"> | |
| 6 | + <up-cell-group :activeStyle="activeStyle"> | |
| 7 | + <up-cell @click="cellClick(item.value)" :border="false" :arrow="false" :title="item.label" | |
| 8 | + v-for="(item, index) in options" :key="index" | |
| 9 | + :title-style="{ color: modelValue == item.value ? activeColor : inactiveColor }"> | |
| 10 | + <up-icon v-if="modelValue == item.value" name="checkbox-mark" :color="activeColor" size="32"></up-icon> | |
| 11 | + </up-cell> | |
| 12 | + </up-cell-group> | |
| 13 | + </view> | |
| 14 | + </scroll-view> | |
| 15 | + </block> | |
| 16 | + <slot v-else /> | |
| 17 | 17 | </view> |
| 18 | 18 | </template> |
| 19 | 19 | |
| 20 | 20 | <script> |
| 21 | - // #ifdef APP-NVUE | |
| 22 | - const animation = uni.requireNativePlugin('animation') | |
| 23 | - const dom = uni.requireNativePlugin('dom') | |
| 24 | - // #endif | |
| 25 | - import props from './props.js'; | |
| 26 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 27 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 28 | - /** | |
| 29 | - * Drawdownitem | |
| 30 | - * @description | |
| 31 | - * @tutorial url | |
| 32 | - * @property {String} | |
| 33 | - * @event {Function} | |
| 34 | - * @example | |
| 35 | - */ | |
| 36 | - export default { | |
| 37 | - name: 'u-drawdown-item', | |
| 38 | - mixins: [mpMixin, mixin, props], | |
| 39 | - data() { | |
| 40 | - return { | |
| 41 | - show: false, | |
| 42 | - top: '126px', | |
| 43 | - // uni.createAnimation的导出数据 | |
| 44 | - animationData: {}, | |
| 45 | - } | |
| 46 | - }, | |
| 47 | - mounted() { | |
| 48 | - this.init() | |
| 49 | - }, | |
| 50 | - watch: { | |
| 51 | - // 发生变化时,需要去更新父组件对应的值 | |
| 52 | - dataChange(newValue, oldValue) { | |
| 53 | - this.updateParentData() | |
| 54 | - } | |
| 55 | - }, | |
| 56 | - computed: { | |
| 57 | - // 监听对应变量的变化 | |
| 58 | - dataChange() { | |
| 59 | - return [this.title, this.disabled] | |
| 60 | - }, | |
| 61 | - style() { | |
| 62 | - const style = { | |
| 63 | - zIndex: 10071, | |
| 64 | - position: 'fixed', | |
| 65 | - display: 'flex', | |
| 66 | - left: 0, | |
| 67 | - right: 0 | |
| 68 | - } | |
| 69 | - style.top = uni.$u.addUnit(this.top) | |
| 70 | - return style | |
| 21 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 22 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 23 | +import props from './props.js'; | |
| 24 | +/** | |
| 25 | + * dropdown-item 下拉菜单 | |
| 26 | + * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景 | |
| 27 | + * @tutorial https://ijry.github.io/uview-plus/components/dropdown.html | |
| 28 | + * @property {String | Number} v-model 双向绑定选项卡选择值 | |
| 29 | + * @property {String} title 菜单项标题 | |
| 30 | + * @property {Array[Object]} options 选项数据,如果传入了默认slot,此参数无效 | |
| 31 | + * @property {Boolean} disabled 是否禁用此选项卡(默认false) | |
| 32 | + * @property {String | Number} duration 选项卡展开和收起的过渡时间,单位ms(默认300) | |
| 33 | + * @property {String | Number} height 弹窗下拉内容的高度(内容超出将会滚动)(默认auto) | |
| 34 | + * @example <u-dropdown-item title="标题"></u-dropdown-item> | |
| 35 | + */ | |
| 36 | +export default { | |
| 37 | + name: 'u-dropdown-item', | |
| 38 | + mixins: [mpMixin, mixin, props], | |
| 39 | + options: { | |
| 40 | + styleIsolation: 'shared', | |
| 41 | + }, | |
| 42 | + data() { | |
| 43 | + return { | |
| 44 | + activeStyle: {}, | |
| 45 | + active: false, // 当前项是否处于展开状态 | |
| 46 | + activeColor: '#2979ff', // 激活时左边文字和右边对勾图标的颜色 | |
| 47 | + inactiveColor: '#606266', // 未激活时左边文字和右边对勾图标的颜色 | |
| 48 | + } | |
| 49 | + }, | |
| 50 | + computed: { | |
| 51 | + // 监听props是否发生了变化,有些值需要传递给父组件u-dropdown,无法双向绑定 | |
| 52 | + propsChange() { | |
| 53 | + return `${this.title}-${this.disabled}`; | |
| 54 | + } | |
| 55 | + }, | |
| 56 | + watch: { | |
| 57 | + propsChange(n) { | |
| 58 | + // 当值变化时,通知父组件重新初始化,让父组件执行每个子组件的init()方法 | |
| 59 | + // 将所有子组件数据重新整理一遍 | |
| 60 | + if (this.parent) this.parent.init(); | |
| 61 | + } | |
| 62 | + }, | |
| 63 | + created() { | |
| 64 | + // 父组件的实例 | |
| 65 | + this.parent = false; | |
| 66 | + }, | |
| 67 | + emits: ['update:modelValue', 'change'], | |
| 68 | + methods: { | |
| 69 | + activeStyleInit() { | |
| 70 | + this.activeStyle = { | |
| 71 | + alignItems: this.placement == 'center' ? 'center' : this.placement == 'right' ? 'flex-end' : 'flex-start', | |
| 71 | 72 | } |
| 72 | 73 | }, |
| 73 | - methods: { | |
| 74 | - init() { | |
| 75 | - this.updateParentData() | |
| 76 | - }, | |
| 77 | - // 更新父组件所需的数据 | |
| 78 | - updateParentData() { | |
| 79 | - // 获取父组件u-dropdown | |
| 80 | - this.getParentData('u-dropdown') | |
| 81 | - if (!this.parent) uni.$u.error('u-dropdown-item必须配合u-dropdown使用') | |
| 82 | - // 查找父组件menuList数组中对应的标题数据 | |
| 83 | - const menuIndex = this.parent.menuList.findIndex(item => item.title === this.title) | |
| 84 | - const menuContent = { | |
| 74 | + init() { | |
| 75 | + // 获取父组件u-dropdown | |
| 76 | + let parent = this.$u.$parent.call(this, 'u-dropdown'); | |
| 77 | + if (parent) { | |
| 78 | + this.parent = parent; | |
| 79 | + // 将子组件的激活颜色配置为父组件设置的激活和未激活时的颜色 | |
| 80 | + this.activeColor = parent.activeColor; | |
| 81 | + this.inactiveColor = parent.inactiveColor; | |
| 82 | + // 将本组件的this,放入到父组件的children数组中,让父组件可以操作本(子)组件的方法和属性 | |
| 83 | + // push进去前,显判断是否已经存在了本实例,因为在子组件内部数据变化时,会通过父组件重新初始化子组件 | |
| 84 | + let exist = parent.children.find(val => { | |
| 85 | + return this === val; | |
| 86 | + }) | |
| 87 | + if (!exist) parent.children.push(this); | |
| 88 | + if (parent.children.length == 1) this.active = true; | |
| 89 | + // 父组件无法监听children的变化,故将子组件的title,传入父组件的menuList数组中 | |
| 90 | + parent.menuList.push({ | |
| 85 | 91 | title: this.title, |
| 86 | 92 | disabled: this.disabled |
| 87 | - } | |
| 88 | - if (menuIndex >= 0) { | |
| 89 | - // 如果能找到,则直接修改 | |
| 90 | - this.parent.menuList[menuIndex] = menuContent; | |
| 91 | - } else { | |
| 92 | - // 如果无法找到,则为第一次添加,直接push即可 | |
| 93 | - this.parent.menuList.push(menuContent); | |
| 94 | - } | |
| 95 | - }, | |
| 96 | - async setContentAnimate(height) { | |
| 97 | - this.animating = true | |
| 98 | - // #ifdef APP-NVUE | |
| 99 | - const ref = this.$refs['animation'].ref | |
| 100 | - animation.transition(ref, { | |
| 101 | - styles: { | |
| 102 | - height: uni.$u.addUnit(height) | |
| 103 | - }, | |
| 104 | - duration: this.duration, | |
| 105 | - timingFunction: 'ease-in-out', | |
| 106 | - }, () => { | |
| 107 | - this.animating = false | |
| 108 | - }) | |
| 109 | - // #endif | |
| 110 | - | |
| 111 | - // #ifndef APP-NVUE | |
| 112 | - const animation = uni.createAnimation({ | |
| 113 | - timingFunction: 'ease-in-out', | |
| 114 | 93 | }); |
| 115 | - animation | |
| 116 | - .height(height) | |
| 117 | - .step({ | |
| 118 | - duration: this.duration, | |
| 119 | - }) | |
| 120 | - .step() | |
| 121 | - // 导出动画数据给面板的animationData值 | |
| 122 | - this.animationData = animation.export() | |
| 123 | - // 标识动画结束 | |
| 124 | - uni.$u.sleep(this.duration).then(() => { | |
| 125 | - this.animating = false | |
| 126 | - }) | |
| 127 | - // #endif | |
| 128 | - }, | |
| 129 | - overlayClick() { | |
| 130 | - this.show = false | |
| 131 | - this.setContentAnimate(0) | |
| 132 | 94 | } |
| 133 | 95 | }, |
| 96 | + // cell被点击 | |
| 97 | + cellClick(value) { | |
| 98 | + // 修改通过v-model绑定的值 | |
| 99 | + // #ifdef VUE2 | |
| 100 | + this.$emit('input', value); | |
| 101 | + // #endif | |
| 102 | + // #ifdef VUE3 | |
| 103 | + this.$emit('update:modelValue', value); | |
| 104 | + // #endif | |
| 105 | + // 通知父组件(u-dropdown)收起菜单 | |
| 106 | + this.parent.close(); | |
| 107 | + // 发出事件,抛出当前勾选项的value | |
| 108 | + this.$emit('change', value); | |
| 109 | + } | |
| 110 | + }, | |
| 111 | + mounted() { | |
| 112 | + this.init(); | |
| 113 | + this.activeStyleInit(); | |
| 134 | 114 | } |
| 115 | +} | |
| 135 | 116 | </script> |
| 136 | 117 | |
| 137 | -<style lang="scss" scoped> | |
| 138 | - @import '../../libs/css/components.scss'; | |
| 139 | - | |
| 140 | - .u-drawdown-item { | |
| 141 | - | |
| 142 | - &__content { | |
| 143 | - background-color: #FFFFFF; | |
| 144 | - overflow: hidden; | |
| 145 | - height: 0; | |
| 146 | - } | |
| 118 | +<style scoped lang="scss"> | |
| 119 | +@import "../../libs/css/components.scss"; | |
| 120 | + | |
| 121 | +.u-dropdown-item__options { | |
| 122 | + ::v-deep .u-cell-group { | |
| 123 | + background: #ffffffeb; | |
| 147 | 124 | } |
| 125 | + | |
| 126 | +} | |
| 148 | 127 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-dropdown/props.js
| 1 | -import defprops from '../../libs/config/props'; | |
| 2 | 1 | export default { |
| 3 | 2 | props: { |
| 4 | - // 标题选中时的样式 | |
| 5 | - activeStyle: { | |
| 6 | - type: [String, Object], | |
| 7 | - default: () => ({ | |
| 8 | - color: '#2979ff', | |
| 9 | - fontSize: '14px' | |
| 10 | - }) | |
| 3 | + // 菜单标题和选项的激活态颜色 | |
| 4 | + activeColor: { | |
| 5 | + type: String, | |
| 6 | + default: '#2979ff' | |
| 11 | 7 | }, |
| 12 | - // 标题未选中时的样式 | |
| 13 | - inactiveStyle: { | |
| 14 | - type: [String, Object], | |
| 15 | - default: () => ({ | |
| 16 | - color: '#606266', | |
| 17 | - fontSize: '14px' | |
| 18 | - }) | |
| 8 | + // 菜单标题和选项的未激活态颜色 | |
| 9 | + inactiveColor: { | |
| 10 | + type: String, | |
| 11 | + default: '#606266' | |
| 19 | 12 | }, |
| 20 | 13 | // 点击遮罩是否关闭菜单 |
| 21 | 14 | closeOnClickMask: { |
| ... | ... | @@ -45,7 +38,7 @@ export default { |
| 45 | 38 | // 标题的字体大小 |
| 46 | 39 | titleSize: { |
| 47 | 40 | type: [Number, String], |
| 48 | - default: 14 | |
| 41 | + default: 28 | |
| 49 | 42 | }, |
| 50 | 43 | // 下拉出来的内容部分的圆角值 |
| 51 | 44 | borderRadius: { | ... | ... |
garbage-removal/src/uview-plus/components/u-dropdown/u-dropdown.vue
| 1 | 1 | <template> |
| 2 | - <view class="u-drawdown"> | |
| 3 | - <view | |
| 4 | - class="u-dropdown__menu" | |
| 5 | - :style="{ | |
| 6 | - height: $u.addUnit(height) | |
| 7 | - }" | |
| 8 | - ref="u-dropdown__menu" | |
| 9 | - > | |
| 10 | - <view | |
| 11 | - class="u-dropdown__menu__item" | |
| 12 | - v-for="(item, index) in menuList" | |
| 13 | - :key="index" | |
| 14 | - @tap.stop="clickHandler(item, index)" | |
| 15 | - > | |
| 16 | - <view class="u-dropdown__menu__item__content"> | |
| 17 | - <text | |
| 18 | - class="u-dropdown__menu__item__content__text" | |
| 19 | - :style="[index === current ? activeStyle : inactiveStyle]" | |
| 20 | - >{{item.title}}</text> | |
| 21 | - <view | |
| 22 | - class="u-dropdown__menu__item__content__arrow" | |
| 23 | - :class="[index === current && 'u-dropdown__menu__item__content__arrow--rotate']" | |
| 24 | - > | |
| 25 | - <u-icon | |
| 26 | - :name="menuIcon" | |
| 27 | - :size="$u.addUnit(menuIconSize)" | |
| 28 | - ></u-icon> | |
| 2 | + <view class="u-dropdown"> | |
| 3 | + <view class="u-dropdown__menu" :style="{ | |
| 4 | + height: $u.addUnit(height) | |
| 5 | + }" :class="{ | |
| 6 | + 'u-border-bottom': borderBottom | |
| 7 | + }"> | |
| 8 | + <view class="u-dropdown__menu__item" v-for="(item, index) in menuList" :key="index" @tap.stop="menuClick(index)"> | |
| 9 | + <view class="u-flex u-flex-row"> | |
| 10 | + <text class="u-dropdown__menu__item__text" :style="{ | |
| 11 | + color: item.disabled ? '#c0c4cc' : (index === current || highlightIndex == index) ? activeColor : inactiveColor, | |
| 12 | + fontSize: $u.addUnit(titleSize) | |
| 13 | + }">{{ item.title }}</text> | |
| 14 | + <view class="u-dropdown__menu__item__arrow" :class="{ | |
| 15 | + 'u-dropdown__menu__item__arrow--rotate': index === current | |
| 16 | + }"> | |
| 17 | + <u-icon :custom-style="{ display: 'flex' }" :name="menuIcon" :size="$u.addUnit(menuIconSize)" | |
| 18 | + :color="index === current || highlightIndex == index ? activeColor : '#c0c4cc'"></u-icon> | |
| 29 | 19 | </view> |
| 30 | 20 | </view> |
| 31 | 21 | </view> |
| 32 | 22 | </view> |
| 33 | - <view class="u-dropdown__content"> | |
| 34 | - <slot /> | |
| 23 | + <view class="u-dropdown__content" :style="[contentStyle, { | |
| 24 | + transition: `opacity ${duration / 1000}s linear`, | |
| 25 | + top: $u.addUnit(height), | |
| 26 | + height: contentHeight + 'px' | |
| 27 | + }]" @tap="maskClick" @touchmove.stop.prevent> | |
| 28 | + <view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]"> | |
| 29 | + <slot></slot> | |
| 30 | + </view> | |
| 31 | + <view class="u-dropdown__content__mask"></view> | |
| 35 | 32 | </view> |
| 36 | 33 | </view> |
| 37 | 34 | </template> |
| 38 | 35 | |
| 39 | 36 | <script> |
| 40 | - import props from './props.js'; | |
| 41 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 42 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 43 | - /** | |
| 44 | - * Dropdown | |
| 45 | - * @description | |
| 46 | - * @tutorial url | |
| 47 | - * @property {String} | |
| 48 | - * @event {Function} | |
| 49 | - * @example | |
| 50 | - */ | |
| 51 | - export default { | |
| 52 | - name: 'u-dropdown', | |
| 53 | - mixins: [mixin, props], | |
| 54 | - data() { | |
| 55 | - return { | |
| 56 | - // �˵����� | |
| 57 | - menuList: [], | |
| 58 | - current: 0 | |
| 37 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 38 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 39 | +import props from './props.js'; | |
| 40 | +/** | |
| 41 | + * dropdown 下拉菜单 | |
| 42 | + * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景 | |
| 43 | + * @tutorial https://ijry.github.io/uview-plus/components/dropdown.html | |
| 44 | + * @property {String} active-color 标题和选项卡选中的颜色(默认#2979ff) | |
| 45 | + * @property {String} inactive-color 标题和选项卡未选中的颜色(默认#606266) | |
| 46 | + * @property {Boolean} close-on-click-mask 点击遮罩是否关闭菜单(默认true) | |
| 47 | + * @property {Boolean} close-on-click-self 点击当前激活项标题是否关闭菜单(默认true) | |
| 48 | + * @property {String | Number} duration 选项卡展开和收起的过渡时间,单位ms(默认300) | |
| 49 | + * @property {String | Number} height 标题菜单的高度,单位任意(默认80) | |
| 50 | + * @property {String | Number} border-radius 菜单展开内容下方的圆角值,单位任意(默认0) | |
| 51 | + * @property {Boolean} border-bottom 标题菜单是否显示下边框(默认false) | |
| 52 | + * @property {String | Number} title-size 标题的字体大小,单位任意,数值默认为rpx单位(默认28) | |
| 53 | + * @event {Function} open 下拉菜单被打开时触发 | |
| 54 | + * @event {Function} close 下拉菜单被关闭时触发 | |
| 55 | + * @example <u-dropdown></u-dropdown> | |
| 56 | + */ | |
| 57 | +export default { | |
| 58 | + name: 'u-dropdown', | |
| 59 | + mixins: [mpMixin, mixin, props], | |
| 60 | + data() { | |
| 61 | + return { | |
| 62 | + showDropdown: true, // 是否打开下来菜单, | |
| 63 | + menuList: [], // 显示的菜单 | |
| 64 | + active: false, // 下拉菜单的状态 | |
| 65 | + // 当前是第几个菜单处于激活状态,小程序中此处不能写成false或者"",否则后续将current赋值为0, | |
| 66 | + // 无能的TX没有使用===而是使用==判断,导致程序认为前后二者没有变化,从而不会触发视图更新 | |
| 67 | + current: 99999, | |
| 68 | + // 外层内容的样式,初始时处于底层,且透明 | |
| 69 | + contentStyle: { | |
| 70 | + zIndex: -1, | |
| 71 | + opacity: 0 | |
| 72 | + }, | |
| 73 | + // 让某个菜单保持高亮的状态 | |
| 74 | + highlightIndex: 99999, | |
| 75 | + contentHeight: 0 | |
| 76 | + } | |
| 77 | + }, | |
| 78 | + computed: { | |
| 79 | + // 下拉出来部分的样式 | |
| 80 | + popupStyle() { | |
| 81 | + let style = {}; | |
| 82 | + // 进行Y轴位移,展开状态时,恢复原位。收齐状态时,往上位移100%,进行隐藏 | |
| 83 | + style.transform = `translateY(${this.active ? 0 : '-100%'})` | |
| 84 | + style['transition-duration'] = this.duration / 1000 + 's'; | |
| 85 | + style.borderRadius = `0 0 ${this.$u.addUnit(this.borderRadius)} ${this.$u.addUnit(this.borderRadius)}`; | |
| 86 | + return style; | |
| 87 | + } | |
| 88 | + }, | |
| 89 | + created() { | |
| 90 | + // 引用所有子组件(u-dropdown-item)的this,不能在data中声明变量,否则在微信小程序会造成循环引用而报错 | |
| 91 | + this.children = []; | |
| 92 | + }, | |
| 93 | + mounted() { | |
| 94 | + this.getContentHeight(); | |
| 95 | + }, | |
| 96 | + emits: ['open', 'close'], | |
| 97 | + methods: { | |
| 98 | + init() { | |
| 99 | + // 当某个子组件内容变化时,触发父组件的init,父组件再让每一个子组件重新初始化一遍 | |
| 100 | + // 以保证数据的正确性 | |
| 101 | + this.menuList = []; | |
| 102 | + this.children.map(child => { | |
| 103 | + child.init(); | |
| 104 | + }) | |
| 105 | + }, | |
| 106 | + // 点击菜单 | |
| 107 | + menuClick(index) { | |
| 108 | + // 判断是否被禁用 | |
| 109 | + if (this.menuList[index].disabled) return; | |
| 110 | + // 如果点击时的索引和当前激活项索引相同,意味着点击了激活项,需要收起下拉菜单 | |
| 111 | + if (index === this.current && this.closeOnClickSelf) { | |
| 112 | + this.close(); | |
| 113 | + // 等动画结束后,再移除下拉菜单中的内容,否则直接移除,也就没有下拉菜单收起的效果了 | |
| 114 | + setTimeout(() => { | |
| 115 | + this.children[index].active = false; | |
| 116 | + }, this.duration) | |
| 117 | + return; | |
| 118 | + } | |
| 119 | + this.open(index); | |
| 120 | + }, | |
| 121 | + // 打开下拉菜单 | |
| 122 | + open(index) { | |
| 123 | + // 嵌套popup使用时可能获取不到正确的高度,重新计算 | |
| 124 | + if (this.contentHeight < 1) this.getContentHeight() | |
| 125 | + // 重置高亮索引,否则会造成多个菜单同时高亮 | |
| 126 | + // this.highlightIndex = 9999; | |
| 127 | + // 展开时,设置下拉内容的样式 | |
| 128 | + this.contentStyle = { | |
| 129 | + zIndex: 11, | |
| 59 | 130 | } |
| 131 | + // 标记展开状态以及当前展开项的索引 | |
| 132 | + this.active = true; | |
| 133 | + this.current = index; | |
| 134 | + // 历遍所有的子元素,将索引匹配的项标记为激活状态,因为子元素是通过v-if控制切换的 | |
| 135 | + // 之所以不是因display: none,是因为nvue没有display这个属性 | |
| 136 | + this.children.map((val, idx) => { | |
| 137 | + val.active = index == idx ? true : false; | |
| 138 | + }) | |
| 139 | + this.$emit('open', this.current); | |
| 60 | 140 | }, |
| 61 | - computed: { | |
| 62 | - | |
| 141 | + // 设置下拉菜单处于收起状态 | |
| 142 | + close() { | |
| 143 | + this.$emit('close', this.current); | |
| 144 | + // 设置为收起状态,同时current归位,设置为空字符串 | |
| 145 | + this.active = false; | |
| 146 | + this.current = 99999; | |
| 147 | + // 下拉内容的样式进行调整,不透明度设置为0 | |
| 148 | + this.contentStyle = { | |
| 149 | + zIndex: -1, | |
| 150 | + opacity: 0 | |
| 151 | + } | |
| 63 | 152 | }, |
| 64 | - created() { | |
| 65 | - // �������������(u-dropdown-item)��this��������data��������������������С��������ѭ�����ö����� | |
| 66 | - this.children = []; | |
| 153 | + // 点击遮罩 | |
| 154 | + maskClick() { | |
| 155 | + // 如果不允许点击遮罩,直接返回 | |
| 156 | + if (!this.closeOnClickMask) return; | |
| 157 | + this.close(); | |
| 67 | 158 | }, |
| 68 | - methods: { | |
| 69 | - clickHandler(item, index) { | |
| 70 | - this.children.map(child => { | |
| 71 | - if(child.title === item.title) { | |
| 72 | - // this.queryRect('u-dropdown__menu').then(size => { | |
| 73 | - child.$emit('click') | |
| 74 | - child.setContentAnimate(child.show ? 0 : 300) | |
| 75 | - child.show = !child.show | |
| 76 | - // }) | |
| 77 | - } else { | |
| 78 | - child.show = false | |
| 79 | - child.setContentAnimate(0) | |
| 80 | - } | |
| 81 | - }) | |
| 82 | - }, | |
| 83 | - // ��ȡ��ǩ�ijߴ�λ�� | |
| 84 | - queryRect(el) { | |
| 85 | - // #ifndef APP-NVUE | |
| 86 | - // $uGetRectΪuView�Դ��Ľڵ��ѯ����https://ijry.github.io/uview-plus/.uviewui.com/js/getRect.html | |
| 87 | - // ����ڲ�һ����this.$uGetRect�������Ϊthis.$u.getRect�����߹���һ�£����Ʋ�ͬ | |
| 88 | - return new Promise(resolve => { | |
| 89 | - this.$uGetRect(`.${el}`).then(size => { | |
| 90 | - resolve(size) | |
| 91 | - }) | |
| 92 | - }) | |
| 93 | - // #endif | |
| 94 | - | |
| 95 | - // #ifdef APP-NVUE | |
| 96 | - // nvue�£�ʹ��domģ���ѯԪ�ظ߶� | |
| 97 | - // ����һ��promise���õ��ô˷�����������ʹ��then�ص� | |
| 98 | - return new Promise(resolve => { | |
| 99 | - dom.getComponentRect(this.$refs[el], res => { | |
| 100 | - resolve(res.size) | |
| 101 | - }) | |
| 102 | - }) | |
| 103 | - // #endif | |
| 104 | - }, | |
| 159 | + // 外部手动设置某个菜单高亮 | |
| 160 | + highlight(index = undefined) { | |
| 161 | + this.highlightIndex = index !== undefined ? index : 99999; | |
| 105 | 162 | }, |
| 163 | + // 获取下拉菜单内容的高度 | |
| 164 | + getContentHeight() { | |
| 165 | + // 这里的原理为,因为dropdown组件是相对定位的,它的下拉出来的内容,必须给定一个高度 | |
| 166 | + // 才能让遮罩占满菜单一下,直到屏幕底部的高度 | |
| 167 | + // this.$u.sys()为uView封装的获取设备信息的方法 | |
| 168 | + let windowHeight = this.$u.sys().windowHeight; | |
| 169 | + this.$uGetRect('.u-dropdown__menu').then(res => { | |
| 170 | + // 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本) | |
| 171 | + // H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离 | |
| 172 | + // 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成 | |
| 173 | + // 这里取菜单栏的botton值合理的,不能用res.top,否则页面会造成滚动 | |
| 174 | + this.contentHeight = windowHeight - res.bottom; | |
| 175 | + }) | |
| 176 | + } | |
| 106 | 177 | } |
| 178 | +} | |
| 107 | 179 | </script> |
| 108 | 180 | |
| 109 | -<style lang="scss"> | |
| 110 | - @import '../../libs/css/components.scss'; | |
| 181 | +<style scoped lang="scss"> | |
| 182 | +@import "../../libs/css/components.scss"; | |
| 183 | + | |
| 184 | +.u-dropdown { | |
| 185 | + flex: 1; | |
| 186 | + width: 100%; | |
| 187 | + position: relative; | |
| 111 | 188 | |
| 112 | - .u-dropdown { | |
| 189 | + &__menu { | |
| 190 | + @include flex; | |
| 191 | + position: relative; | |
| 192 | + z-index: 11; | |
| 193 | + height: 80rpx; | |
| 113 | 194 | |
| 114 | - &__menu { | |
| 195 | + &__item { | |
| 196 | + flex: 1; | |
| 115 | 197 | @include flex; |
| 198 | + justify-content: center; | |
| 199 | + align-items: center; | |
| 116 | 200 | |
| 117 | - &__item { | |
| 118 | - flex: 1; | |
| 201 | + .u-flex-row { | |
| 202 | + flex-direction: row; | |
| 203 | + } | |
| 204 | + | |
| 205 | + &__text { | |
| 206 | + font-size: 28rpx; | |
| 207 | + color: $u-content-color; | |
| 208 | + } | |
| 209 | + | |
| 210 | + &__arrow { | |
| 211 | + margin-left: 6rpx; | |
| 212 | + transition: transform .3s; | |
| 213 | + align-items: center; | |
| 119 | 214 | @include flex; |
| 120 | - justify-content: center; | |
| 121 | 215 | |
| 122 | - &__content { | |
| 123 | - @include flex; | |
| 124 | - align-items: center; | |
| 216 | + &--rotate { | |
| 217 | + transform: rotate(180deg); | |
| 125 | 218 | } |
| 126 | 219 | } |
| 127 | 220 | } |
| 128 | 221 | } |
| 222 | + | |
| 223 | + &__content { | |
| 224 | + position: absolute; | |
| 225 | + z-index: 8; | |
| 226 | + width: 100%; | |
| 227 | + left: 0px; | |
| 228 | + bottom: 0; | |
| 229 | + overflow: hidden; | |
| 230 | + | |
| 231 | + | |
| 232 | + &__mask { | |
| 233 | + position: absolute; | |
| 234 | + z-index: 9; | |
| 235 | + // background: rgba(0, 0, 0, .3); | |
| 236 | + width: 100%; | |
| 237 | + left: 0; | |
| 238 | + top: 0; | |
| 239 | + bottom: 0; | |
| 240 | + } | |
| 241 | + | |
| 242 | + &__popup { | |
| 243 | + position: relative; | |
| 244 | + z-index: 10; | |
| 245 | + transition: all 0.3s; | |
| 246 | + transform: translate3D(0, -100%, 0); | |
| 247 | + overflow: hidden; | |
| 248 | + } | |
| 249 | + } | |
| 250 | + | |
| 251 | +} | |
| 129 | 252 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-form-item/u-form-item.vue
| ... | ... | @@ -7,19 +7,20 @@ |
| 7 | 7 | <slot name="label"> |
| 8 | 8 | <!-- {{required}} --> |
| 9 | 9 | <view class="u-form-item__body__left" v-if="required || leftIcon || label" :style="{ |
| 10 | - width: $u.addUnit(labelWidth || parentData.labelWidth), | |
| 11 | - marginBottom: parentData.labelPosition === 'left' ? 0 : '5px', | |
| 12 | - }"> | |
| 10 | + width: $u.addUnit(labelWidth || parentData.labelWidth), | |
| 11 | + marginBottom: parentData.labelPosition === 'left' ? 0 : '5px', | |
| 12 | + }"> | |
| 13 | 13 | <!-- 为了块对齐 --> |
| 14 | 14 | <view class="u-form-item__body__left__content"> |
| 15 | 15 | <!-- nvue不支持伪元素before --> |
| 16 | - <text v-if="required" class="u-form-item__body__left__content__required">*</text> | |
| 16 | + <text v-if="required" class="u-form-item__body__left__content__required" | |
| 17 | + style="top: -3px !important;font-size: 14px !important;">*</text> | |
| 17 | 18 | <view class="u-form-item__body__left__content__icon" v-if="leftIcon"> |
| 18 | 19 | <u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon> |
| 19 | 20 | </view> |
| 20 | 21 | <text class="u-form-item__body__left__content__label" :style="[parentData.labelStyle, { |
| 21 | - justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end' | |
| 22 | - }]">{{ label }}</text> | |
| 22 | + justifyContent: parentData.labelAlign === 'left' ? 'flex-start' : parentData.labelAlign === 'center' ? 'center' : 'flex-end' | |
| 23 | + }]">{{ label }}</text> | |
| 23 | 24 | </view> |
| 24 | 25 | </view> |
| 25 | 26 | </slot> |
| ... | ... | @@ -36,8 +37,8 @@ |
| 36 | 37 | </view> |
| 37 | 38 | <slot name="error"> |
| 38 | 39 | <text v-if="!!message && parentData.errorType === 'message'" class="u-form-item__body__right__message" :style="{ |
| 39 | - marginLeft: $u.addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth)) | |
| 40 | - }">{{ message }}</text> | |
| 40 | + marginLeft: $u.addUnit(parentData.labelPosition === 'top' ? 0 : (labelWidth || parentData.labelWidth)) | |
| 41 | + }">{{ message }}</text> | |
| 41 | 42 | </slot> |
| 42 | 43 | <u-line v-if="borderBottom" |
| 43 | 44 | :color="message && parentData.errorType === 'border-bottom' ? $u.color.error : propsLine.color" | ... | ... |
garbage-removal/src/uview-plus/components/u-search/u-search.vue
| 1 | 1 | <template> |
| 2 | - <view | |
| 3 | - class="u-search" | |
| 4 | - @tap="clickHandler" | |
| 5 | - :style="[{ | |
| 6 | - margin: margin, | |
| 7 | - }, $u.addStyle(customStyle)]" | |
| 8 | - > | |
| 9 | - <view | |
| 10 | - class="u-search__content" | |
| 11 | - :style="{ | |
| 12 | - backgroundColor: bgColor, | |
| 13 | - borderRadius: shape == 'round' ? '100px' : '4px', | |
| 14 | - borderColor: borderColor, | |
| 15 | - }" | |
| 16 | - > | |
| 2 | + <view class="u-search" :style="[{ | |
| 3 | + margin: margin, | |
| 4 | + }, $u.addStyle(customStyle)]"> | |
| 5 | + <view class="u-search__content" :style="{ | |
| 6 | + backgroundColor: bgColor, | |
| 7 | + borderRadius: shape == 'round' ? '100px' : '4px', | |
| 8 | + borderColor: borderColor, | |
| 9 | + }"> | |
| 17 | 10 | <template v-if="$slots.label || label !== null"> |
| 18 | 11 | <slot name="label"> |
| 19 | 12 | <text class="u-search__content__label">{{ label }}</text> |
| 20 | 13 | </slot> |
| 21 | 14 | </template> |
| 22 | 15 | <view class="u-search__content__icon"> |
| 23 | - <u-icon | |
| 24 | - @tap="clickIcon" | |
| 25 | - :size="searchIconSize" | |
| 26 | - :name="searchIcon" | |
| 27 | - :color="searchIconColor ? searchIconColor : color" | |
| 28 | - ></u-icon> | |
| 16 | + <u-icon @click.stop="clickIcon" :size="searchIconSize" :name="searchIcon" | |
| 17 | + :color="searchIconColor ? searchIconColor : color"></u-icon> | |
| 29 | 18 | </view> |
| 30 | - <input | |
| 31 | - confirm-type="search" | |
| 32 | - @blur="blur" | |
| 33 | - :value="keyword" | |
| 34 | - @confirm="search" | |
| 35 | - @input="inputChange" | |
| 36 | - :disabled="disabled" | |
| 37 | - @focus="getFocus" | |
| 38 | - :focus="focus" | |
| 39 | - :maxlength="maxlength" | |
| 40 | - placeholder-class="u-search__content__input--placeholder" | |
| 41 | - :placeholder="placeholder" | |
| 42 | - :placeholder-style="`color: ${placeholderColor}`" | |
| 43 | - class="u-search__content__input" | |
| 44 | - type="text" | |
| 45 | - :style="[{ | |
| 46 | - textAlign: inputAlign, | |
| 47 | - color: color, | |
| 48 | - backgroundColor: bgColor, | |
| 49 | - height: $u.addUnit(height) | |
| 50 | - }, inputStyle]" | |
| 51 | - /> | |
| 52 | - <view | |
| 53 | - class="u-search__content__icon u-search__content__close" | |
| 54 | - v-if="keyword && clearabled && focused" | |
| 55 | - @tap="clear" | |
| 56 | - > | |
| 57 | - <u-icon | |
| 58 | - name="close" | |
| 59 | - size="11" | |
| 60 | - color="#ffffff" | |
| 61 | - customStyle="line-height: 12px" | |
| 62 | - ></u-icon> | |
| 19 | + <input @tap.stop="clickHandler" confirm-type="search" @blur="blur" :value="keyword" @confirm="search" | |
| 20 | + @input="inputChange" :disabled="disabled" @focus="getFocus" :focus="focus" :maxlength="maxlength" | |
| 21 | + placeholder-class="u-search__content__input--placeholder" :placeholder="placeholder" | |
| 22 | + :placeholder-style="`color: ${placeholderColor}`" class="u-search__content__input" type="text" :style="[{ | |
| 23 | + textAlign: inputAlign, | |
| 24 | + color: color, | |
| 25 | + backgroundColor: bgColor, | |
| 26 | + height: $u.addUnit(height) | |
| 27 | + }, inputStyle]" /> | |
| 28 | + <view class="u-search__content__icon u-search__content__close" v-if="keyword && clearabled && focused" | |
| 29 | + @tap="clear"> | |
| 30 | + <u-icon name="close" size="11" color="#ffffff" customStyle="line-height: 12px"></u-icon> | |
| 63 | 31 | </view> |
| 64 | 32 | </view> |
| 65 | - <text | |
| 66 | - :style="[actionStyle]" | |
| 67 | - class="u-search__action" | |
| 68 | - :class="[(showActionBtn || show) && 'u-search__action--active']" | |
| 69 | - @tap.stop.prevent="custom" | |
| 70 | - >{{ actionText }}</text> | |
| 33 | + <text :style="[actionStyle]" class="u-search__action" | |
| 34 | + :class="[(showActionBtn || show) && 'u-search__action--active']" @tap.stop.prevent="custom">{{ actionText | |
| 35 | + }}</text> | |
| 71 | 36 | </view> |
| 72 | 37 | </template> |
| 73 | 38 | |
| 74 | 39 | <script> |
| 75 | - import props from './props.js'; | |
| 76 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 77 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 40 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 41 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 42 | +import props from './props.js'; | |
| 78 | 43 | |
| 79 | - /** | |
| 80 | - * search 搜索框 | |
| 81 | - * @description 搜索组件,集成了常见搜索框所需功能,用户可以一键引入,开箱即用。 | |
| 82 | - * @tutorial https://ijry.github.io/uview-plus/components/search.html | |
| 83 | - * @property {String} shape 搜索框形状,round-圆形,square-方形(默认 'round' ) | |
| 84 | - * @property {String} bgColor 搜索框背景颜色(默认 '#f2f2f2' ) | |
| 85 | - * @property {String} placeholder 占位文字内容(默认 '请输入关键字' ) | |
| 86 | - * @property {Boolean} clearabled 是否启用清除控件(默认 true ) | |
| 87 | - * @property {Boolean} focus 是否自动获得焦点(默认 false ) | |
| 88 | - * @property {Boolean} showAction 是否显示右侧控件(默认 true ) | |
| 89 | - * @property {Object} actionStyle 右侧控件的样式,对象形式 | |
| 90 | - * @property {String} actionText 右侧控件文字(默认 '搜索' ) | |
| 91 | - * @property {String} inputAlign 输入框内容水平对齐方式 (默认 'left' ) | |
| 92 | - * @property {Object} inputStyle 自定义输入框样式,对象形式 | |
| 93 | - * @property {Boolean} disabled 是否启用输入框(默认 false ) | |
| 94 | - * @property {String} borderColor 边框颜色,配置了颜色,才会有边框 (默认 'transparent' ) | |
| 95 | - * @property {String} searchIconColor 搜索图标的颜色,默认同输入框字体颜色 (默认 '#909399' ) | |
| 96 | - * @property {Number | String} searchIconSize 搜索图标的字体,默认22 | |
| 97 | - * @property {String} color 输入框字体颜色(默认 '#606266' ) | |
| 98 | - * @property {String} placeholderColor placeholder的颜色(默认 '#909399' ) | |
| 99 | - * @property {String} searchIcon 输入框左边的图标,可以为uView图标名称或图片路径 (默认 'search' ) | |
| 100 | - * @property {String} margin 组件与其他上下左右元素之间的距离,带单位的字符串形式,如"30px" (默认 '0' ) | |
| 101 | - * @property {Boolean} animation 是否开启动画,见上方说明(默认 false ) | |
| 102 | - * @property {String} value 输入框初始值 | |
| 103 | - * @property {String | Number} maxlength 输入框最大能输入的长度,-1为不限制长度 (默认 '-1' ) | |
| 104 | - * @property {String | Number} height 输入框高度,单位px(默认 64 ) | |
| 105 | - * @property {String | Number} label 搜索框左边显示内容 | |
| 106 | - * @property {Object} customStyle 定义需要用到的外部样式 | |
| 107 | - * | |
| 108 | - * @event {Function} change 输入框内容发生变化时触发 | |
| 109 | - * @event {Function} search 用户确定搜索时触发,用户按回车键,或者手机键盘右下角的"搜索"键时触发 | |
| 110 | - * @event {Function} custom 用户点击右侧控件时触发 | |
| 111 | - * @event {Function} clear 用户点击清除按钮时触发 | |
| 112 | - * @example <u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search> | |
| 113 | - */ | |
| 114 | - export default { | |
| 115 | - name: "u-search", | |
| 116 | - mixins: [mpMixin, mixin, props], | |
| 117 | - data() { | |
| 118 | - return { | |
| 119 | - keyword: '', | |
| 120 | - showClear: false, // 是否显示右边的清除图标 | |
| 121 | - show: false, | |
| 122 | - // 标记input当前状态是否处于聚焦中,如果是,才会显示右侧的清除控件 | |
| 123 | - focused: this.focus | |
| 124 | - // 绑定输入框的值 | |
| 125 | - // inputValue: this.value | |
| 126 | - }; | |
| 127 | - }, | |
| 128 | - watch: { | |
| 129 | - keyword(nVal) { | |
| 130 | - // 双向绑定值,让v-model绑定的值双向变化 | |
| 131 | - // #ifdef VUE3 | |
| 132 | - this.$emit("update:modelValue", nVal); | |
| 133 | - // #endif | |
| 134 | - // #ifdef VUE2 | |
| 135 | - this.$emit('input', nVal); | |
| 136 | - // #endif | |
| 137 | - // 触发change事件,事件效果和v-model双向绑定的效果一样,让用户多一个选择 | |
| 138 | - this.$emit('change', nVal); | |
| 139 | - }, | |
| 44 | +/** | |
| 45 | + * search 搜索框 | |
| 46 | + * @description 搜索组件,集成了常见搜索框所需功能,用户可以一键引入,开箱即用。 | |
| 47 | + * @tutorial https://ijry.github.io/uview-plus/components/search.html | |
| 48 | + * @property {String} shape 搜索框形状,round-圆形,square-方形(默认 'round' ) | |
| 49 | + * @property {String} bgColor 搜索框背景颜色(默认 '#f2f2f2' ) | |
| 50 | + * @property {String} placeholder 占位文字内容(默认 '请输入关键字' ) | |
| 51 | + * @property {Boolean} clearabled 是否启用清除控件(默认 true ) | |
| 52 | + * @property {Boolean} focus 是否自动获得焦点(默认 false ) | |
| 53 | + * @property {Boolean} showAction 是否显示右侧控件(默认 true ) | |
| 54 | + * @property {Object} actionStyle 右侧控件的样式,对象形式 | |
| 55 | + * @property {String} actionText 右侧控件文字(默认 '搜索' ) | |
| 56 | + * @property {String} inputAlign 输入框内容水平对齐方式 (默认 'left' ) | |
| 57 | + * @property {Object} inputStyle 自定义输入框样式,对象形式 | |
| 58 | + * @property {Boolean} disabled 是否启用输入框(默认 false ) | |
| 59 | + * @property {String} borderColor 边框颜色,配置了颜色,才会有边框 (默认 'transparent' ) | |
| 60 | + * @property {String} searchIconColor 搜索图标的颜色,默认同输入框字体颜色 (默认 '#909399' ) | |
| 61 | + * @property {Number | String} searchIconSize 搜索图标的字体,默认22 | |
| 62 | + * @property {String} color 输入框字体颜色(默认 '#606266' ) | |
| 63 | + * @property {String} placeholderColor placeholder的颜色(默认 '#909399' ) | |
| 64 | + * @property {String} searchIcon 输入框左边的图标,可以为uView图标名称或图片路径 (默认 'search' ) | |
| 65 | + * @property {String} margin 组件与其他上下左右元素之间的距离,带单位的字符串形式,如"30px" (默认 '0' ) | |
| 66 | + * @property {Boolean} animation 是否开启动画,见上方说明(默认 false ) | |
| 67 | + * @property {String} value 输入框初始值 | |
| 68 | + * @property {String | Number} maxlength 输入框最大能输入的长度,-1为不限制长度 (默认 '-1' ) | |
| 69 | + * @property {String | Number} height 输入框高度,单位px(默认 64 ) | |
| 70 | + * @property {String | Number} label 搜索框左边显示内容 | |
| 71 | + * @property {Object} customStyle 定义需要用到的外部样式 | |
| 72 | + * | |
| 73 | + * @event {Function} change 输入框内容发生变化时触发 | |
| 74 | + * @event {Function} search 用户确定搜索时触发,用户按回车键,或者手机键盘右下角的"搜索"键时触发 | |
| 75 | + * @event {Function} custom 用户点击右侧控件时触发 | |
| 76 | + * @event {Function} clear 用户点击清除按钮时触发 | |
| 77 | + * @example <u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search> | |
| 78 | + */ | |
| 79 | +export default { | |
| 80 | + name: "u-search", | |
| 81 | + mixins: [mpMixin, mixin, props], | |
| 82 | + data() { | |
| 83 | + return { | |
| 84 | + keyword: '', | |
| 85 | + showClear: false, // 是否显示右边的清除图标 | |
| 86 | + show: false, | |
| 87 | + // 标记input当前状态是否处于聚焦中,如果是,才会显示右侧的清除控件 | |
| 88 | + focused: this.focus | |
| 89 | + // 绑定输入框的值 | |
| 90 | + // inputValue: this.value | |
| 91 | + }; | |
| 92 | + }, | |
| 93 | + watch: { | |
| 94 | + keyword(nVal) { | |
| 95 | + // 双向绑定值,让v-model绑定的值双向变化 | |
| 140 | 96 | // #ifdef VUE3 |
| 141 | - modelValue: { | |
| 142 | - immediate: true, | |
| 143 | - handler(nVal) { | |
| 144 | - this.keyword = nVal; | |
| 145 | - } | |
| 146 | - }, | |
| 97 | + this.$emit("update:modelValue", nVal); | |
| 147 | 98 | // #endif |
| 148 | 99 | // #ifdef VUE2 |
| 149 | - value: { | |
| 150 | - immediate: true, | |
| 151 | - handler(nVal) { | |
| 152 | - this.keyword = nVal; | |
| 153 | - } | |
| 154 | - }, | |
| 100 | + this.$emit('input', nVal); | |
| 155 | 101 | // #endif |
| 102 | + // 触发change事件,事件效果和v-model双向绑定的效果一样,让用户多一个选择 | |
| 103 | + this.$emit('change', nVal); | |
| 156 | 104 | }, |
| 157 | - computed: { | |
| 158 | - showActionBtn() { | |
| 159 | - return !this.animation && this.showAction | |
| 105 | + // #ifdef VUE3 | |
| 106 | + modelValue: { | |
| 107 | + immediate: true, | |
| 108 | + handler(nVal) { | |
| 109 | + this.keyword = nVal; | |
| 160 | 110 | } |
| 161 | 111 | }, |
| 162 | - emits: ['clear', 'search', 'custom', 'focus', 'blur', 'click', 'clickIcon', 'update:modelValue', 'change'], | |
| 163 | - methods: { | |
| 164 | - // 目前HX2.6.9 v-model双向绑定无效,故监听input事件获取输入框内容的变化 | |
| 165 | - inputChange(e) { | |
| 166 | - this.keyword = e.detail.value; | |
| 167 | - }, | |
| 168 | - // 清空输入 | |
| 169 | - // 也可以作为用户通过this.$refs形式调用清空输入框内容 | |
| 170 | - clear() { | |
| 171 | - this.keyword = ''; | |
| 172 | - // 延后发出事件,避免在父组件监听clear事件时,value为更新前的值(不为空) | |
| 173 | - this.$nextTick(() => { | |
| 174 | - this.$emit('clear'); | |
| 175 | - }) | |
| 176 | - }, | |
| 177 | - // 确定搜索 | |
| 178 | - search(e) { | |
| 179 | - this.$emit('search', e.detail.value); | |
| 180 | - try { | |
| 181 | - // 收起键盘 | |
| 182 | - uni.hideKeyboard(); | |
| 183 | - } catch (e) {} | |
| 184 | - }, | |
| 185 | - // 点击右边自定义按钮的事件 | |
| 186 | - custom() { | |
| 187 | - this.$emit('custom', this.keyword); | |
| 188 | - try { | |
| 189 | - // 收起键盘 | |
| 190 | - uni.hideKeyboard(); | |
| 191 | - } catch (e) {} | |
| 192 | - }, | |
| 193 | - // 获取焦点 | |
| 194 | - getFocus() { | |
| 195 | - this.focused = true; | |
| 196 | - // 开启右侧搜索按钮展开的动画效果 | |
| 197 | - if (this.animation && this.showAction) this.show = true; | |
| 198 | - this.$emit('focus', this.keyword); | |
| 199 | - }, | |
| 200 | - // 失去焦点 | |
| 201 | - blur() { | |
| 202 | - // 最开始使用的是监听图标@touchstart事件,自从hx2.8.4后,此方法在微信小程序出错 | |
| 203 | - // 这里改为监听点击事件,手点击清除图标时,同时也发生了@blur事件,导致图标消失而无法点击,这里做一个延时 | |
| 204 | - setTimeout(() => { | |
| 205 | - this.focused = false; | |
| 206 | - }, 100) | |
| 207 | - this.show = false; | |
| 208 | - this.$emit('blur', this.keyword); | |
| 209 | - }, | |
| 210 | - // 点击搜索框,只有disabled=true时才发出事件,因为禁止了输入,意味着是想跳转真正的搜索页 | |
| 211 | - clickHandler() { | |
| 212 | - if (this.disabled) this.$emit('click'); | |
| 213 | - }, | |
| 214 | - // 点击左边图标 | |
| 215 | - clickIcon() { | |
| 216 | - this.$emit('clickIcon'); | |
| 112 | + // #endif | |
| 113 | + // #ifdef VUE2 | |
| 114 | + value: { | |
| 115 | + immediate: true, | |
| 116 | + handler(nVal) { | |
| 117 | + this.keyword = nVal; | |
| 217 | 118 | } |
| 119 | + }, | |
| 120 | + // #endif | |
| 121 | + }, | |
| 122 | + computed: { | |
| 123 | + showActionBtn() { | |
| 124 | + return !this.animation && this.showAction | |
| 125 | + } | |
| 126 | + }, | |
| 127 | + emits: ['clear', 'search', 'custom', 'focus', 'blur', 'click', 'clickIcon', 'update:modelValue', 'change'], | |
| 128 | + methods: { | |
| 129 | + // 目前HX2.6.9 v-model双向绑定无效,故监听input事件获取输入框内容的变化 | |
| 130 | + inputChange(e) { | |
| 131 | + this.keyword = e.detail.value; | |
| 132 | + }, | |
| 133 | + // 清空输入 | |
| 134 | + // 也可以作为用户通过this.$refs形式调用清空输入框内容 | |
| 135 | + clear() { | |
| 136 | + this.keyword = ''; | |
| 137 | + // 延后发出事件,避免在父组件监听clear事件时,value为更新前的值(不为空) | |
| 138 | + this.$nextTick(() => { | |
| 139 | + this.$emit('clear'); | |
| 140 | + }) | |
| 141 | + }, | |
| 142 | + // 确定搜索 | |
| 143 | + search(e) { | |
| 144 | + this.$emit('search', e.detail.value); | |
| 145 | + try { | |
| 146 | + // 收起键盘 | |
| 147 | + uni.hideKeyboard(); | |
| 148 | + } catch (e) { } | |
| 149 | + }, | |
| 150 | + // 点击右边自定义按钮的事件 | |
| 151 | + custom() { | |
| 152 | + this.$emit('custom', this.keyword); | |
| 153 | + try { | |
| 154 | + // 收起键盘 | |
| 155 | + uni.hideKeyboard(); | |
| 156 | + } catch (e) { } | |
| 157 | + }, | |
| 158 | + // 获取焦点 | |
| 159 | + getFocus() { | |
| 160 | + this.focused = true; | |
| 161 | + // 开启右侧搜索按钮展开的动画效果 | |
| 162 | + if (this.animation && this.showAction) this.show = true; | |
| 163 | + this.$emit('focus', this.keyword); | |
| 164 | + }, | |
| 165 | + // 失去焦点 | |
| 166 | + blur() { | |
| 167 | + // 最开始使用的是监听图标@touchstart事件,自从hx2.8.4后,此方法在微信小程序出错 | |
| 168 | + // 这里改为监听点击事件,手点击清除图标时,同时也发生了@blur事件,导致图标消失而无法点击,这里做一个延时 | |
| 169 | + setTimeout(() => { | |
| 170 | + this.focused = false; | |
| 171 | + }, 100) | |
| 172 | + this.show = false; | |
| 173 | + this.$emit('blur', this.keyword); | |
| 174 | + }, | |
| 175 | + // 点击搜索框,只有disabled=true时才发出事件,因为禁止了输入,意味着是想跳转真正的搜索页 | |
| 176 | + clickHandler() { | |
| 177 | + if (this.disabled) this.$emit('click'); | |
| 178 | + }, | |
| 179 | + // 点击左边图标 | |
| 180 | + clickIcon() { | |
| 181 | + this.$emit('clickIcon'); | |
| 218 | 182 | } |
| 219 | 183 | } |
| 184 | +} | |
| 220 | 185 | </script> |
| 221 | 186 | |
| 222 | 187 | <style lang="scss" scoped> |
| ... | ... | @@ -242,8 +207,9 @@ $u-search-action-margin-left: 5px !default; |
| 242 | 207 | /* #ifdef H5 */ |
| 243 | 208 | // iOS15在H5下,hx的某些版本,input type=search时,会多了一个搜索图标,进行移除 |
| 244 | 209 | [type="search"]::-webkit-search-decoration { |
| 245 | - display: none; | |
| 210 | + display: none; | |
| 246 | 211 | } |
| 212 | + | |
| 247 | 213 | /* #endif */ |
| 248 | 214 | |
| 249 | 215 | .u-search { | ... | ... |
garbage-removal/src/uview-plus/components/u-textarea/u-textarea.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-textarea" :class="textareaClass" :style="[textareaStyle]"> |
| 3 | - <textarea | |
| 4 | - class="u-textarea__field" | |
| 5 | - :value="innerValue" | |
| 6 | - :style="{ height: $u.addUnit(height) }" | |
| 7 | - :placeholder="placeholder" | |
| 8 | - :placeholder-style="$u.addStyle(placeholderStyle, 'string')" | |
| 9 | - :placeholder-class="placeholderClass" | |
| 10 | - :disabled="disabled" | |
| 11 | - :focus="focus" | |
| 12 | - :autoHeight="autoHeight" | |
| 13 | - :fixed="fixed" | |
| 14 | - :cursorSpacing="cursorSpacing" | |
| 15 | - :cursor="cursor" | |
| 16 | - :showConfirmBar="showConfirmBar" | |
| 17 | - :selectionStart="selectionStart" | |
| 18 | - :selectionEnd="selectionEnd" | |
| 19 | - :adjustPosition="adjustPosition" | |
| 20 | - :disableDefaultPadding="disableDefaultPadding" | |
| 21 | - :holdKeyboard="holdKeyboard" | |
| 22 | - :maxlength="maxlength" | |
| 23 | - :confirm-type="confirmType" | |
| 24 | - :ignoreCompositionEvent="ignoreCompositionEvent" | |
| 25 | - @focus="onFocus" | |
| 26 | - @blur="onBlur" | |
| 27 | - @linechange="onLinechange" | |
| 28 | - @input="onInput" | |
| 29 | - @confirm="onConfirm" | |
| 30 | - @keyboardheightchange="onKeyboardheightchange" | |
| 31 | - ></textarea> | |
| 32 | - <text | |
| 33 | - class="u-textarea__count" | |
| 34 | - :style="{ | |
| 35 | - 'background-color': disabled ? 'transparent' : '#fff', | |
| 36 | - }" | |
| 37 | - v-if="count" | |
| 38 | - >{{ innerValue.length }}/{{ maxlength }}</text | |
| 39 | - > | |
| 3 | + <textarea class="u-textarea__field" :value="innerValue" :style="{ height: $u.addUnit(height) }" | |
| 4 | + :placeholder="placeholder" :placeholder-style="$u.addStyle(placeholderStyle, 'string')" | |
| 5 | + :placeholder-class="placeholderClass" :disabled="disabled" :focus="focus" :autoHeight="autoHeight" | |
| 6 | + :fixed="fixed" :cursorSpacing="cursorSpacing" :cursor="cursor" :showConfirmBar="showConfirmBar" | |
| 7 | + :selectionStart="selectionStart" :selectionEnd="selectionEnd" :adjustPosition="adjustPosition" | |
| 8 | + :disableDefaultPadding="disableDefaultPadding" :holdKeyboard="holdKeyboard" :maxlength="maxlength" | |
| 9 | + :confirm-type="confirmType" :ignoreCompositionEvent="ignoreCompositionEvent" @focus="onFocus" @blur="onBlur" | |
| 10 | + @linechange="onLinechange" @input="onInput" @confirm="onConfirm" | |
| 11 | + @keyboardheightchange="onKeyboardheightchange"></textarea> | |
| 12 | + <text class="u-textarea__count" :style="{ | |
| 13 | + 'background-color': disabled ? 'transparent' : '#fff', | |
| 14 | + }" v-if="count">{{ innerValue.length }}/{{ maxlength }}</text> | |
| 40 | 15 | </view> |
| 41 | 16 | </template> |
| 42 | 17 | |
| 43 | 18 | <script> |
| 44 | -import props from "./props.js"; | |
| 45 | -import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 46 | 19 | import mixin from '../../libs/mixin/mixin.js'; |
| 20 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 21 | +import props from "./props.js"; | |
| 47 | 22 | /** |
| 48 | 23 | * Textarea 文本域 |
| 49 | 24 | * @description 文本域此组件满足了可能出现的表单信息补充,编辑等实际逻辑的功能,内置了字数校验等 |
| ... | ... | @@ -84,64 +59,64 @@ import mixin from '../../libs/mixin/mixin.js'; |
| 84 | 59 | export default { |
| 85 | 60 | name: "u-textarea", |
| 86 | 61 | mixins: [mpMixin, mixin, props], |
| 87 | - data() { | |
| 88 | - return { | |
| 89 | - // 输入框的值 | |
| 90 | - innerValue: "", | |
| 91 | - // 是否处于获得焦点状态 | |
| 92 | - focused: false, | |
| 93 | - // value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化 | |
| 94 | - firstChange: true, | |
| 95 | - // value绑定值的变化是由内部还是外部引起的 | |
| 96 | - changeFromInner: false, | |
| 97 | - // 过滤处理方法 | |
| 98 | - innerFormatter: value => value | |
| 99 | - } | |
| 100 | - }, | |
| 101 | - created() { | |
| 102 | - }, | |
| 103 | - watch: { | |
| 62 | + data() { | |
| 63 | + return { | |
| 64 | + // 输入框的值 | |
| 65 | + innerValue: "", | |
| 66 | + // 是否处于获得焦点状态 | |
| 67 | + focused: false, | |
| 68 | + // value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化 | |
| 69 | + firstChange: true, | |
| 70 | + // value绑定值的变化是由内部还是外部引起的 | |
| 71 | + changeFromInner: false, | |
| 72 | + // 过滤处理方法 | |
| 73 | + innerFormatter: value => value | |
| 74 | + } | |
| 75 | + }, | |
| 76 | + created() { | |
| 77 | + }, | |
| 78 | + watch: { | |
| 104 | 79 | // #ifdef VUE2 |
| 105 | - value: { | |
| 106 | - immediate: true, | |
| 107 | - handler(newVal, oldVal) { | |
| 108 | - this.innerValue = newVal; | |
| 109 | - /* #ifdef H5 */ | |
| 110 | - // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 | |
| 111 | - if ( | |
| 112 | - this.firstChange === false && | |
| 113 | - this.changeFromInner === false | |
| 114 | - ) { | |
| 115 | - this.valueChange(); | |
| 116 | - } | |
| 117 | - /* #endif */ | |
| 118 | - this.firstChange = false; | |
| 119 | - // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 | |
| 120 | - this.changeFromInner = false; | |
| 121 | - }, | |
| 122 | - }, | |
| 80 | + value: { | |
| 81 | + immediate: true, | |
| 82 | + handler(newVal, oldVal) { | |
| 83 | + this.innerValue = newVal; | |
| 84 | + /* #ifdef H5 */ | |
| 85 | + // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 | |
| 86 | + if ( | |
| 87 | + this.firstChange === false && | |
| 88 | + this.changeFromInner === false | |
| 89 | + ) { | |
| 90 | + this.valueChange(); | |
| 91 | + } | |
| 92 | + /* #endif */ | |
| 93 | + this.firstChange = false; | |
| 94 | + // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 | |
| 95 | + this.changeFromInner = false; | |
| 96 | + }, | |
| 97 | + }, | |
| 123 | 98 | // #endif |
| 124 | 99 | // #ifdef VUE3 |
| 125 | 100 | modelValue: { |
| 126 | - immediate: true, | |
| 127 | - handler(newVal, oldVal) { | |
| 128 | - this.innerValue = newVal; | |
| 129 | - /* #ifdef H5 */ | |
| 130 | - // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 | |
| 131 | - if ( | |
| 132 | - this.firstChange === false && | |
| 133 | - this.changeFromInner === false | |
| 134 | - ) { | |
| 135 | - this.valueChange(); | |
| 136 | - } | |
| 137 | - /* #endif */ | |
| 138 | - this.firstChange = false; | |
| 139 | - // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 | |
| 140 | - this.changeFromInner = false; | |
| 141 | - }, | |
| 142 | - } | |
| 101 | + immediate: true, | |
| 102 | + handler(newVal, oldVal) { | |
| 103 | + this.innerValue = newVal; | |
| 104 | + /* #ifdef H5 */ | |
| 105 | + // 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 | |
| 106 | + if ( | |
| 107 | + this.firstChange === false && | |
| 108 | + this.changeFromInner === false | |
| 109 | + ) { | |
| 110 | + this.valueChange(); | |
| 111 | + } | |
| 112 | + /* #endif */ | |
| 113 | + this.firstChange = false; | |
| 114 | + // 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 | |
| 115 | + this.changeFromInner = false; | |
| 116 | + }, | |
| 117 | + } | |
| 143 | 118 | // #endif |
| 144 | - }, | |
| 119 | + }, | |
| 145 | 120 | computed: { |
| 146 | 121 | // 组件的类名 |
| 147 | 122 | textareaClass() { |
| ... | ... | @@ -176,10 +151,10 @@ export default { |
| 176 | 151 | emits: ['update:modelValue', 'linechange', 'focus', 'blur', 'change', 'confirm', 'keyboardheightchange'], |
| 177 | 152 | // #endif |
| 178 | 153 | methods: { |
| 179 | - // 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用 | |
| 180 | - setFormatter(e) { | |
| 181 | - this.innerFormatter = e | |
| 182 | - }, | |
| 154 | + // 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用 | |
| 155 | + setFormatter(e) { | |
| 156 | + this.innerFormatter = e | |
| 157 | + }, | |
| 183 | 158 | onFocus(e) { |
| 184 | 159 | this.$emit("focus", e); |
| 185 | 160 | }, |
| ... | ... | @@ -192,34 +167,34 @@ export default { |
| 192 | 167 | this.$emit("linechange", e); |
| 193 | 168 | }, |
| 194 | 169 | onInput(e) { |
| 195 | - let { value = "" } = e.detail || {}; | |
| 196 | - // 格式化过滤方法 | |
| 197 | - const formatter = this.formatter || this.innerFormatter | |
| 198 | - const formatValue = formatter(value) | |
| 199 | - // 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效 | |
| 200 | - this.innerValue = value | |
| 201 | - this.$nextTick(() => { | |
| 202 | - this.innerValue = formatValue; | |
| 203 | - this.valueChange(); | |
| 204 | - }) | |
| 170 | + let { value = "" } = e.detail || {}; | |
| 171 | + // 格式化过滤方法 | |
| 172 | + const formatter = this.formatter || this.innerFormatter | |
| 173 | + const formatValue = formatter(value) | |
| 174 | + // 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效 | |
| 175 | + this.innerValue = value | |
| 176 | + this.$nextTick(() => { | |
| 177 | + this.innerValue = formatValue; | |
| 178 | + this.valueChange(); | |
| 179 | + }) | |
| 205 | 180 | }, |
| 206 | - // 内容发生变化,进行处理 | |
| 207 | - valueChange() { | |
| 208 | - const value = this.innerValue; | |
| 209 | - this.$nextTick(() => { | |
| 181 | + // 内容发生变化,进行处理 | |
| 182 | + valueChange() { | |
| 183 | + const value = this.innerValue; | |
| 184 | + this.$nextTick(() => { | |
| 210 | 185 | // #ifdef VUE3 |
| 211 | 186 | this.$emit("update:modelValue", value); |
| 212 | 187 | // #endif |
| 213 | 188 | // #ifdef VUE2 |
| 214 | 189 | this.$emit("input", value); |
| 215 | 190 | // #endif |
| 216 | - // 标识value值的变化是由内部引起的 | |
| 217 | - this.changeFromInner = true; | |
| 218 | - this.$emit("change", value); | |
| 219 | - // 尝试调用u-form的验证方法 | |
| 220 | - uni.$u.formValidate(this, "change"); | |
| 221 | - }); | |
| 222 | - }, | |
| 191 | + // 标识value值的变化是由内部引起的 | |
| 192 | + this.changeFromInner = true; | |
| 193 | + this.$emit("change", value); | |
| 194 | + // 尝试调用u-form的验证方法 | |
| 195 | + uni.$u.formValidate(this, "change"); | |
| 196 | + }); | |
| 197 | + }, | |
| 223 | 198 | onConfirm(e) { |
| 224 | 199 | this.$emit("confirm", e); |
| 225 | 200 | }, |
| ... | ... | @@ -239,7 +214,7 @@ export default { |
| 239 | 214 | position: relative; |
| 240 | 215 | @include flex; |
| 241 | 216 | flex: 1; |
| 242 | - padding: 9px; | |
| 217 | + padding: 9px; | |
| 243 | 218 | |
| 244 | 219 | &--radius { |
| 245 | 220 | border-radius: 4px; |
| ... | ... | @@ -257,7 +232,7 @@ export default { |
| 257 | 232 | flex: 1; |
| 258 | 233 | font-size: 15px; |
| 259 | 234 | color: $u-content-color; |
| 260 | - width: 100%; | |
| 235 | + width: 100%; | |
| 261 | 236 | } |
| 262 | 237 | |
| 263 | 238 | &__count { | ... | ... |
garbage-removal/src/uview-plus/components/u-upload/u-upload.vue
| ... | ... | @@ -5,14 +5,14 @@ |
| 5 | 5 | <view class="u-upload__wrap__preview" v-for="(item, index) in lists" :key="index"> |
| 6 | 6 | <image v-if="item.isImage || (item.type && item.type === 'image')" :src="item.thumb || item.url" |
| 7 | 7 | :mode="imageMode" class="u-upload__wrap__preview__image" @tap="onPreviewImage(item)" :style="[{ |
| 8 | - width: $u.addUnit(width), | |
| 9 | - height: $u.addUnit(height) | |
| 10 | - }]" /> | |
| 8 | + // width: $u.addUnit(width), | |
| 9 | + // height: $u.addUnit(height) | |
| 10 | + }]" /> | |
| 11 | 11 | <view v-else class="u-upload__wrap__preview__other"> |
| 12 | 12 | <u-icon color="#80CBF9" size="26" |
| 13 | 13 | :name="item.isVideo || (item.type && item.type === 'video') ? 'movie' : 'folder'"></u-icon> |
| 14 | 14 | <text class="u-upload__wrap__preview__other__text">{{ item.isVideo || (item.type && item.type === 'video') ? |
| 15 | - '视频' : '文件' }}</text> | |
| 15 | + '视频' : '文件' }}</text> | |
| 16 | 16 | </view> |
| 17 | 17 | <view class="u-upload__status" v-if="item.status === 'uploading' || item.status === 'failed'"> |
| 18 | 18 | <view class="u-upload__status__icon"> |
| ... | ... | @@ -48,9 +48,9 @@ |
| 48 | 48 | </view> |
| 49 | 49 | <view v-else class="u-upload__button" :hover-class="!disabled ? 'u-upload__button--hover' : ''" |
| 50 | 50 | hover-stay-time="150" @tap="chooseFile" :class="[disabled && 'u-upload__button--disabled']" :style="[{ |
| 51 | - width: $u.addUnit(width), | |
| 52 | - height: $u.addUnit(height) | |
| 53 | - }]"> | |
| 51 | + // width: $u.addUnit(width), | |
| 52 | + // height: $u.addUnit(height) | |
| 53 | + }]"> | |
| 54 | 54 | <u-icon :name="uploadIcon" size="26" :color="uploadIconColor"></u-icon> |
| 55 | 55 | <text v-if="uploadText" class="u-upload__button__text">{{ uploadText }}</text> |
| 56 | 56 | </view> |
| ... | ... | @@ -251,7 +251,7 @@ export default { |
| 251 | 251 | // 预览图片 |
| 252 | 252 | onPreviewImage(item) { |
| 253 | 253 | if (!item.isImage || !this.previewFullImage) return |
| 254 | - let baseUrl = import.meta.env.VITE_BASE_URL; | |
| 254 | + let baseUrl = item.url.startsWith('/profile/upload/') ? import.meta.env.VITE_BASE_URL : item.url; | |
| 255 | 255 | let imageArray = this.lists.filter((item) => this.accept === 'image' || uni.$u.test.image(item.url || item.thumb)).map((item) => item.url || item.thumb); |
| 256 | 256 | for (let index = 0; index < imageArray.length; index++) { |
| 257 | 257 | if (!imageArray[index].startsWith(baseUrl)) { | ... | ... |
garbage-removal/vite.config.js
garbage-removal/yarn.lock
| ... | ... | @@ -4368,6 +4368,11 @@ jpeg-js@^0.3.4: |
| 4368 | 4368 | resolved "https://registry.npmmirror.com/jpeg-js/-/jpeg-js-0.3.7.tgz" |
| 4369 | 4369 | integrity sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ== |
| 4370 | 4370 | |
| 4371 | +js-md5@^0.8.3: | |
| 4372 | + version "0.8.3" | |
| 4373 | + resolved "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz" | |
| 4374 | + integrity sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ== | |
| 4375 | + | |
| 4371 | 4376 | js-tokens@^4.0.0: |
| 4372 | 4377 | version "4.0.0" |
| 4373 | 4378 | resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz" | ... | ... |