Commit feb53f80ce7984a64f7e7dd16774876ce2bea2d4
1 parent
3972b923
feat: 新增取消订单
Showing
18 changed files
with
1319 additions
and
1237 deletions
garbage-removal/src/pages/home/address/addSite.vue
| ... | ... | @@ -239,11 +239,12 @@ const reset = () => { |
| 239 | 239 | |
| 240 | 240 | .submit-button { |
| 241 | 241 | display: flex; |
| 242 | - width: 600rpx; | |
| 242 | + margin: auto; | |
| 243 | + width: 80%; | |
| 243 | 244 | line-height: 100rpx; |
| 244 | 245 | position: absolute; |
| 245 | 246 | bottom: 30rpx; |
| 246 | - left: 80rpx; | |
| 247 | + left: 10%; | |
| 247 | 248 | font-size: 30rpx; |
| 248 | 249 | color: #ffffff; |
| 249 | 250 | ... | ... |
garbage-removal/src/pages/home/address/index.vue
garbage-removal/src/pages/home/clean/company-detail/index.vue
| ... | ... | @@ -120,7 +120,6 @@ const serverData = ref([ |
| 120 | 120 | * 拨打电话回调 |
| 121 | 121 | */ |
| 122 | 122 | const handleContactClick = (val) => { |
| 123 | - console.log("拨打电话"); | |
| 124 | 123 | uni.makePhoneCall({ phoneNumber: val }).then(res => { |
| 125 | 124 | console.log(res); |
| 126 | 125 | }).catch(err => { }); |
| ... | ... | @@ -142,7 +141,6 @@ const handleCleanGarbage = (companyObj, tel, userAddress) => { |
| 142 | 141 | } |
| 143 | 142 | |
| 144 | 143 | const initData = (baseData) => { |
| 145 | - console.log(baseData); | |
| 146 | 144 | baseDataList.value[0].value = baseData.legalRepresentative |
| 147 | 145 | baseDataList.value[1].value = baseData.safetyManagerName |
| 148 | 146 | baseDataList.value[2].value = baseData.safetyManagerPhone | ... | ... |
garbage-removal/src/pages/home/clean/index.vue
| ... | ... | @@ -55,7 +55,6 @@ |
| 55 | 55 | </view> |
| 56 | 56 | </view> |
| 57 | 57 | </view> |
| 58 | - | |
| 59 | 58 | <view class="company-clean-container-site-image-info"> |
| 60 | 59 | <view class="company-clean-container-site-image-info-remark"> |
| 61 | 60 | <text style="color: red;">*</text>现场照片(最多上传10张) |
| ... | ... | @@ -73,10 +72,11 @@ |
| 73 | 72 | </view> |
| 74 | 73 | <view class="company-clean-container-site-image-info-sure-button"> |
| 75 | 74 | <view class="company-clean-container-site-image-info-sure-button-radio"> |
| 76 | - <u-radio-group v-model="paramFrom.sureReadFlag"> | |
| 77 | - <u-radio activeColor="#a9e08f" size="27" labelSize="25" :name="true" :labelDisabled="true" | |
| 78 | - labelColor="#909399" label=""></u-radio>本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。 | |
| 79 | - </u-radio-group> | |
| 75 | + <u-checkbox-group v-model="paramFrom.sureReadFlag" placement="row"> | |
| 76 | + <u-checkbox activeColor="#a9e08f" size="25" labelSize="25" shape="circle" @change="changeAgree" :key="0" | |
| 77 | + :name="true" :labelDisabled="true" labelColor="#909399" | |
| 78 | + label="本人已确认信息真实有效,并将上述信息告知市容环境卫生主管部门。"></u-checkbox> | |
| 79 | + </u-checkbox-group> | |
| 80 | 80 | </view> |
| 81 | 81 | </view> |
| 82 | 82 | </view> |
| ... | ... | @@ -124,7 +124,7 @@ const garbageTypeList = ref(["建筑垃圾", "装修垃圾"]) |
| 124 | 124 | const paramFrom = ref({ |
| 125 | 125 | carNumber: 1, |
| 126 | 126 | remark: "", |
| 127 | - sureReadFlag: false, | |
| 127 | + sureReadFlag: [], | |
| 128 | 128 | carType: "", |
| 129 | 129 | garbageType: "装修垃圾" |
| 130 | 130 | }) |
| ... | ... | @@ -140,6 +140,12 @@ const handleTimeChoose = () => { |
| 140 | 140 | const changeTime = (e) => { |
| 141 | 141 | dayTime.value = e.value |
| 142 | 142 | } |
| 143 | +const changeAgree = (e) => { | |
| 144 | + // paramFrom.value.sureReadFlag = e | |
| 145 | +} | |
| 146 | +const onChange = (e) => { | |
| 147 | + // console.log(e); | |
| 148 | +} | |
| 143 | 149 | /** |
| 144 | 150 | * 初始化信息 |
| 145 | 151 | */ |
| ... | ... | @@ -148,8 +154,7 @@ onLoad((options) => { |
| 148 | 154 | tel.value = options.tel; |
| 149 | 155 | userAddress.value = JSON.parse(options.userAddress); |
| 150 | 156 | queryCarList({ companyId: companyObj.value.id }).then(res => { |
| 151 | - candidates.value = res.data.rows.map(item => item.carType) | |
| 152 | - console.log(candidates.value); | |
| 157 | + candidates.value = [...new Set(res.data.rows.map(item => item.carType))]; | |
| 153 | 158 | }) |
| 154 | 159 | }) |
| 155 | 160 | |
| ... | ... | @@ -287,14 +292,18 @@ onMounted(() => { |
| 287 | 292 | movableArea.boundingClientRect(function (data) { |
| 288 | 293 | // data - 包含元素的高度等信息 |
| 289 | 294 | areaHeight = data.height; |
| 290 | - y.value = areaHeight; | |
| 295 | + y.value = areaHeight > 20 ? (areaHeight - 20) : areaHeight; | |
| 291 | 296 | }).exec(function (res) { |
| 292 | 297 | // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据 |
| 293 | 298 | }) |
| 294 | 299 | }) |
| 295 | 300 | |
| 301 | +/** | |
| 302 | + * 校验参数 | |
| 303 | + * @param {Object} params | |
| 304 | + */ | |
| 296 | 305 | const validateParams = (params) => { |
| 297 | - if (!paramFrom.value.sureReadFlag) { | |
| 306 | + if (!paramFrom.value.sureReadFlag[0]) { | |
| 298 | 307 | jumpPrompt('请勾选"本人已确认信息真实有效,并将上诉信息告知市容环境卫生主管部门"') |
| 299 | 308 | return false; |
| 300 | 309 | } |
| ... | ... | @@ -313,7 +322,6 @@ const validateParams = (params) => { |
| 313 | 322 | } |
| 314 | 323 | return false; |
| 315 | 324 | } |
| 316 | - console.log("key:", key, key == "imageUrls"); | |
| 317 | 325 | if (key == "imageUrls") { |
| 318 | 326 | if (params[key].length == 0) { |
| 319 | 327 | jumpPrompt('请上传现场图片') |
| ... | ... | @@ -325,7 +333,6 @@ const validateParams = (params) => { |
| 325 | 333 | } |
| 326 | 334 | } |
| 327 | 335 | } |
| 328 | - | |
| 329 | 336 | return true; |
| 330 | 337 | } |
| 331 | 338 | |
| ... | ... | @@ -342,7 +349,6 @@ const jumpPrompt = (msg) => { |
| 342 | 349 | }); |
| 343 | 350 | } |
| 344 | 351 | const validateImage = (fileList) => { |
| 345 | - console.log(fileList); | |
| 346 | 352 | |
| 347 | 353 | for (let index = 0; index < fileList.length; index++) { |
| 348 | 354 | const str = fileList[index]; |
| ... | ... | @@ -542,8 +548,8 @@ $custom-bottom-height: 200rpx; |
| 542 | 548 | .company-clean-container-site-image-info-sure-button-radio { |
| 543 | 549 | padding: $custom-page-padding; |
| 544 | 550 | box-sizing: border-box; |
| 545 | - display: flex; | |
| 546 | - flex-flow: row wrap; | |
| 551 | + // display: flex; | |
| 552 | + // flex-flow: row wrap; | |
| 547 | 553 | color: $u-info; |
| 548 | 554 | } |
| 549 | 555 | } | ... | ... |
garbage-removal/src/pages/login/index.vue
| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | </view> |
| 12 | 12 | </view> |
| 13 | 13 | <view class="buttom"> |
| 14 | - <view class="loginType"> | |
| 14 | + <!-- <view class="loginType"> | |
| 15 | 15 | <view class="wechat item"> |
| 16 | 16 | <button class="box" open-type="getPhoneNumber" @getphonenumber="handleWeixinLogin"> |
| 17 | 17 | <view class="icon"><u-icon size="60" name="weixin-fill" color="rgb(83,194,64)"></u-icon> |
| ... | ... | @@ -19,11 +19,18 @@ |
| 19 | 19 | 微信登录 |
| 20 | 20 | </button> |
| 21 | 21 | </view> |
| 22 | - </view> | |
| 22 | + </view> --> | |
| 23 | 23 | <view class="hint"> |
| 24 | - 登录代表同意 | |
| 25 | - <text class="link" @click="handleUserAgreement">用户协议、隐私政策,</text> | |
| 26 | - 并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理 | |
| 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> | |
| 29 | + <view class="prompt-txt"> | |
| 30 | + 登录代表同意 | |
| 31 | + <text class="link" @click="handleUserAgreement">用户协议、隐私政策,</text> | |
| 32 | + 并授权使用您的账号信息(如昵称、头像、收获地址)以便您统一管理。 | |
| 33 | + </view> | |
| 27 | 34 | </view> |
| 28 | 35 | </view> |
| 29 | 36 | </view> |
| ... | ... | @@ -34,7 +41,8 @@ import { userLogin } from "@/apis/user.js"; |
| 34 | 41 | export default { |
| 35 | 42 | data() { |
| 36 | 43 | return { |
| 37 | - tel: '18977778888' | |
| 44 | + tel: '18977778888', | |
| 45 | + agree: [] | |
| 38 | 46 | } |
| 39 | 47 | }, |
| 40 | 48 | computed: { |
| ... | ... | @@ -48,11 +56,28 @@ export default { |
| 48 | 56 | } |
| 49 | 57 | }, |
| 50 | 58 | methods: { |
| 59 | + groupChange(e) { | |
| 60 | + console.log(e); | |
| 61 | + }, | |
| 51 | 62 | submit() { |
| 52 | 63 | if (this.$u.test.mobile(this.tel)) { |
| 53 | - this.$u.route({ | |
| 54 | - url: `pages/login/code?iphoneNumber=${this.tel}`, | |
| 55 | - }) | |
| 64 | + if (this.agree[0]) { | |
| 65 | + this.$u.route({ | |
| 66 | + url: `pages/login/code?iphoneNumber=${this.tel}`, | |
| 67 | + }) | |
| 68 | + } else { | |
| 69 | + let that = this | |
| 70 | + uni.showModal({ | |
| 71 | + title: '提示', | |
| 72 | + content: '需要同意登录协议', | |
| 73 | + success: function (res) { | |
| 74 | + if (res.confirm) { | |
| 75 | + that.agree[0] = true | |
| 76 | + } else if (res.cancel) { | |
| 77 | + } | |
| 78 | + } | |
| 79 | + }) | |
| 80 | + } | |
| 56 | 81 | } else { |
| 57 | 82 | this.$refs.uToastRef.show({ |
| 58 | 83 | type: 'default', |
| ... | ... | @@ -67,6 +92,9 @@ export default { |
| 67 | 92 | handleUserAgreement() { |
| 68 | 93 | console.log("user click agreement"); |
| 69 | 94 | }, |
| 95 | + radioChange(e) { | |
| 96 | + this.agree = e | |
| 97 | + }, | |
| 70 | 98 | handleWeixinLogin(wxInfo) { |
| 71 | 99 | uni.login({ |
| 72 | 100 | provider: 'weixin', |
| ... | ... | @@ -165,10 +193,16 @@ export default { |
| 165 | 193 | padding: 20rpx 40rpx; |
| 166 | 194 | font-size: 20rpx; |
| 167 | 195 | color: $u-tips-color; |
| 196 | + display: flex; | |
| 197 | + justify-content: flex-start; | |
| 168 | 198 | |
| 169 | - .link { | |
| 170 | - color: $u-warning; | |
| 199 | + .prompt-txt { | |
| 200 | + .link { | |
| 201 | + color: $u-warning; | |
| 202 | + } | |
| 171 | 203 | } |
| 204 | + | |
| 205 | + | |
| 172 | 206 | } |
| 173 | 207 | } |
| 174 | 208 | } | ... | ... |
garbage-removal/src/pages/order/detail/index.vue
| ... | ... | @@ -14,7 +14,11 @@ |
| 14 | 14 | </view> |
| 15 | 15 | <!-- 信息提示 --> |
| 16 | 16 | <view class="order-detail-container-box-card"> |
| 17 | - <text style="color: red;">请于交易完成后线下支付!!</text> | |
| 17 | + <text v-if="dataGram.garCancelFlag == 0" style="color: red;">请于交易完成后线下支付!!</text> | |
| 18 | + <view v-else style="display: flex;color: red;"> | |
| 19 | + <u-icon name="close-circle" color="red"></u-icon> | |
| 20 | + <text style="color: red;"> 订单已被取消!</text> | |
| 21 | + </view> | |
| 18 | 22 | </view> |
| 19 | 23 | <!-- 派单信息 --> |
| 20 | 24 | <view class="order-detail-container-box-card"> |
| ... | ... | @@ -134,23 +138,30 @@ |
| 134 | 138 | <image class="image-style" style="width: 200rpx; height: 200rpx;" :src="emptyBase64Image"></image> |
| 135 | 139 | </view> |
| 136 | 140 | </view> |
| 141 | + <view class="space-box">{{ spaceStr }}</view> | |
| 142 | + | |
| 137 | 143 | </view> |
| 138 | 144 | <!-- 占位符 --> |
| 139 | - <view class="space-box">{{ spaceStr }}</view> | |
| 140 | 145 | <view class="order-detail-bottom"> |
| 141 | 146 | <view class="order-detail-bottom-box"> |
| 142 | 147 | <view class="order-detail-bottom-left"> |
| 143 | - <!-- <u-button @click="handleOderSure" shape="circle" color="#a9e08f" text="取消订单"></u-button> --> | |
| 144 | - <u-button v-if="dataGram.garOrderHandlerStatus == 1" @click="handleSubmitSuccess(orderId)" shape="circle" | |
| 145 | - color="#a9e08f" text="完成派单"></u-button> | |
| 148 | + <!-- <u-button @click="handleOderCancelClick(orderId)" shape="circle" color="#a9e08f" text="取消订单"></u-button> --> | |
| 146 | 149 | </view> |
| 147 | 150 | <view class="order-detail-bottom-right"> |
| 148 | - <u-button @click="handleOrder(orderId)" v-if="dataGram.garOrderHandlerStatus == 0 && dataGram.handleFlag" | |
| 149 | - shape="circle" color="#a9e08f" text="处理派单"></u-button> | |
| 150 | - <u-button @click="handleUploadImage(orderId)" v-if="dataGram.garOrderHandlerStatus == 1 && dataGram.handleFlag" | |
| 151 | - shape="circle" color="#a9e08f" text="上传照片"></u-button> | |
| 151 | + <u-button @click="handleOrder(orderId)" | |
| 152 | + v-if="dataGram.garOrderHandlerStatus == 0 && dataGram.handleFlag && dataGram.garCancelFlag" shape="circle" | |
| 153 | + color="#a9e08f" text="处理派单"></u-button> | |
| 154 | + <u-button @click="handleUploadImage(orderId, 'putOnImages')" | |
| 155 | + v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putOnImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag" | |
| 156 | + shape="circle" color="#a9e08f" text="装车照片"></u-button> | |
| 157 | + <u-button @click="handleUploadImage(orderId, 'putDownImages')" | |
| 158 | + v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag" | |
| 159 | + shape="circle" color="#a9e08f" text="卸车照片"></u-button> | |
| 152 | 160 | <u-button @click="handleEvaluate(orderId)" v-if="dataGram.garEvaluateFlag == 0" shape="circle" color="#a9e08f" |
| 153 | 161 | text="去评价"></u-button> |
| 162 | + <u-button | |
| 163 | + v-if="dataGram.garOrderHandlerStatus == 1 && dataGram.putOnImages.length != 0 && dataGram.putDownImages.length != 0 && dataGram.garCancelFlag" | |
| 164 | + @click="handleSubmitSuccess(orderId)" shape="circle" color="#a9e08f" text="完成派单"></u-button> | |
| 154 | 165 | </view> |
| 155 | 166 | </view> |
| 156 | 167 | </view> |
| ... | ... | @@ -174,7 +185,6 @@ const spaceStr = ref("") |
| 174 | 185 | */ |
| 175 | 186 | onLoad((options) => { |
| 176 | 187 | orderId.value = options.orderId |
| 177 | - console.log(emptyBase64Image.value); | |
| 178 | 188 | }) |
| 179 | 189 | const handleOrderDetail = (orderId) => { |
| 180 | 190 | queryOrderDetail(orderId).then(res => { |
| ... | ... | @@ -197,7 +207,9 @@ const handleContactClick = (val) => { |
| 197 | 207 | uni.makePhoneCall({ phoneNumber: val }).then(res => { |
| 198 | 208 | }).catch(err => { }); |
| 199 | 209 | } |
| 210 | +const handleOderCancelClick = (orderId) => { | |
| 200 | 211 | |
| 212 | +} | |
| 201 | 213 | // 提交完成 |
| 202 | 214 | const handleSubmitSuccess = (orderId) => { |
| 203 | 215 | uni.showModal({ |
| ... | ... | @@ -212,7 +224,6 @@ const handleSubmitSuccess = (orderId) => { |
| 212 | 224 | } |
| 213 | 225 | }) |
| 214 | 226 | } else if (res.cancel) { |
| 215 | - console.log('用户点击取消'); | |
| 216 | 227 | } |
| 217 | 228 | } |
| 218 | 229 | }); |
| ... | ... | @@ -233,15 +244,14 @@ const handleOrder = (orderId) => { |
| 233 | 244 | |
| 234 | 245 | |
| 235 | 246 | const currentStep = (step) => { |
| 236 | - console.log(step); | |
| 237 | 247 | if (step > 2) { |
| 238 | 248 | return step - 1; |
| 239 | 249 | } |
| 240 | 250 | return step; |
| 241 | 251 | } |
| 242 | 252 | |
| 243 | -const handleUploadImage = (orderId) => { | |
| 244 | - uni.$u.route(`pages/order/upload/index?orderId=${orderId}`) | |
| 253 | +const handleUploadImage = (orderId, putType) => { | |
| 254 | + uni.$u.route(`pages/order/upload/index?orderId=${orderId}&putType=${putType}`) | |
| 245 | 255 | } |
| 246 | 256 | |
| 247 | 257 | onShow(() => { | ... | ... |
garbage-removal/src/pages/order/swiper-list-item/index.vue
| ... | ... | @@ -10,10 +10,11 @@ |
| 10 | 10 | <view class="store">{{ item.garOrderCompanyName }}</view> |
| 11 | 11 | <u-icon name="arrow-right" color="rgb(203,203,203)" :size="26"></u-icon> |
| 12 | 12 | </view> |
| 13 | - <view v-if="item.garOrderHandlerStatus === 0" class="right">待清运 </view> | |
| 14 | - <view v-if="item.garOrderHandlerStatus === 1" class="right">清运中 </view> | |
| 15 | - <view v-if="item.garEvaluateFlag === 0" class="right">待评价 </view> | |
| 16 | - <view v-if="item.garEvaluateFlag === 1" class="right">已评价 </view> | |
| 13 | + <view v-if="item.garOrderHandlerStatus === 0 && item.garCancelFlag === 0" class="right">待清运 </view> | |
| 14 | + <view v-if="item.garCancelFlag === 1" class="right">已取消 </view> | |
| 15 | + <view v-if="item.garOrderHandlerStatus === 1 && item.garCancelFlag === 0" class="right">清运中 </view> | |
| 16 | + <view v-if="item.garEvaluateFlag === 0 && item.garCancelFlag === 0" class="right">待评价 </view> | |
| 17 | + <view v-if="item.garEvaluateFlag === 1 && item.garCancelFlag === 0" class="right">已评价 </view> | |
| 17 | 18 | </view> |
| 18 | 19 | <view class="item" @click="handleClick(item.garOrderId)"> |
| 19 | 20 | <view class="left"> |
| ... | ... | @@ -25,21 +26,23 @@ |
| 25 | 26 | <view class="delivery-time">预约时间 {{ item.garOrderAgreementTime }}</view> |
| 26 | 27 | </view> |
| 27 | 28 | </view> |
| 28 | - <!-- <view class="bottom"> | |
| 29 | + <view class="bottom" v-if="item.garOrderHandlerStatus === 0 && item.garCancelFlag === 0"> | |
| 29 | 30 | <view class="more"> |
| 30 | - <u-icon name="more-dot-fill" color="rgb(203,203,203)"></u-icon> | |
| 31 | + <!-- <u-icon name="more-dot-fill" color="rgb(203,203,203)"></u-icon> --> | |
| 31 | 32 | </view> |
| 32 | - <view class="logistics btn" v-if="item.garOrderHandlerStatus === 0" @click="">取消订单</view> | |
| 33 | - <view class="evaluate btn" v-if="item.garOrderHandlerStatus === 4">评价</view> | |
| 34 | - </view> --> | |
| 33 | + <view hover-class="btn-hover" class="logistics btn" @click="handleCancelOrder(item.garOrderId)">取消派单</view> | |
| 34 | + </view> | |
| 35 | 35 | </view> |
| 36 | 36 | </view> |
| 37 | 37 | </z-paging> |
| 38 | + <u-action-sheet :closeOnClickOverlay="true" :closeOnClickAction="false" @actionSheetClose="handleClose" | |
| 39 | + @submitFunction="submitFunction" @select="selectClick" :actions="list" round="15" title="取消派单" :show="cancelShow"> | |
| 40 | + </u-action-sheet> | |
| 38 | 41 | </view> |
| 39 | 42 | </template> |
| 40 | 43 | |
| 41 | 44 | <script setup> |
| 42 | -import { queryOrderList } from "@/apis/order.js"; | |
| 45 | +import { queryOrderList, updateOrder } from "@/apis/order.js"; | |
| 43 | 46 | import { ref, watch } from 'vue'; |
| 44 | 47 | const props = defineProps({ |
| 45 | 48 | tabIndex: { |
| ... | ... | @@ -49,10 +52,73 @@ const props = defineProps({ |
| 49 | 52 | type: Number |
| 50 | 53 | } |
| 51 | 54 | }) |
| 55 | + | |
| 56 | +const currentCancelOrderId = ref(""); | |
| 57 | +const currentCancelName = ref(""); | |
| 58 | +const cancelShow = ref(false) | |
| 59 | +const list = ref([ | |
| 60 | + { | |
| 61 | + name: '长时间无人接单', | |
| 62 | + }, | |
| 63 | + { | |
| 64 | + name: '订单信息填写有误', | |
| 65 | + }, | |
| 66 | + { | |
| 67 | + name: '线下协商有问题', | |
| 68 | + }, | |
| 69 | + { | |
| 70 | + name: '不需要清运了', | |
| 71 | + }, | |
| 72 | + { | |
| 73 | + name: '其他', | |
| 74 | + }, | |
| 75 | + { | |
| 76 | + name: '提交', | |
| 77 | + } | |
| 78 | +]) | |
| 52 | 79 | const dataList = ref([]); |
| 53 | 80 | const paging = ref(null); |
| 54 | 81 | const firstLoaded = ref(false) |
| 82 | +/** | |
| 83 | + * 取消订单 | |
| 84 | + * @param {string} orderId | |
| 85 | + */ | |
| 86 | +const handleCancelOrder = (orderId) => { | |
| 87 | + currentCancelOrderId.value = orderId | |
| 88 | + cancelShow.value = true | |
| 89 | +} | |
| 90 | +const handleClose = (e) => { | |
| 91 | + cancelShow.value = false | |
| 92 | +} | |
| 55 | 93 | |
| 94 | +const selectClick = (index) => { | |
| 95 | + currentCancelName.value = index.name; | |
| 96 | +} | |
| 97 | +/** | |
| 98 | + * 提交取消订单 | |
| 99 | + */ | |
| 100 | +const submitFunction = (otherReason) => { | |
| 101 | + let reason = otherReason | |
| 102 | + if (currentCancelName.value != "其他") { | |
| 103 | + reason = currentCancelName.value | |
| 104 | + } | |
| 105 | + if (!reason) { | |
| 106 | + uni.$u.toast("请提供取消派单的原因") | |
| 107 | + return | |
| 108 | + } | |
| 109 | + let params = { | |
| 110 | + garOrderId: currentCancelOrderId.value, | |
| 111 | + garCancelFlag: 1, | |
| 112 | + garReason: reason | |
| 113 | + } | |
| 114 | + updateOrder(params).then(res => { | |
| 115 | + if (res.data.success) { | |
| 116 | + cancelShow.value = false | |
| 117 | + uni.$u.toast(res.data.data) | |
| 118 | + paging.value.reload(); | |
| 119 | + } | |
| 120 | + }) | |
| 121 | +} | |
| 56 | 122 | const handleClick = (orderId) => { |
| 57 | 123 | uni.$u.route({ |
| 58 | 124 | url: `pages/order/detail/index`, |
| ... | ... | @@ -70,7 +136,6 @@ const queryList = (pageNo, pageSize) => { |
| 70 | 136 | queryOrderList({ type: props.tabIndex, pageNo, pageSize }).then((res) => { |
| 71 | 137 | paging.value.complete(res.data.data.list); |
| 72 | 138 | firstLoaded.value = true |
| 73 | - console.log(res.data.data.list); | |
| 74 | 139 | }).catch(res => { |
| 75 | 140 | //如果请求失败写paging.value.complete(false),会自动展示错误页面 |
| 76 | 141 | //注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理 |
| ... | ... | @@ -89,7 +154,6 @@ watch(() => props.currentIndex, (val1, val2) => { |
| 89 | 154 | paging.value.reload(); |
| 90 | 155 | }, 50); |
| 91 | 156 | } |
| 92 | - | |
| 93 | 157 | } |
| 94 | 158 | }, { immediate: true }) |
| 95 | 159 | </script> |
| ... | ... | @@ -99,7 +163,7 @@ watch(() => props.currentIndex, (val1, val2) => { |
| 99 | 163 | height: 100%; |
| 100 | 164 | |
| 101 | 165 | .order { |
| 102 | - width: 710rpx; | |
| 166 | + width: 90%; | |
| 103 | 167 | background-color: #ffffff; |
| 104 | 168 | margin: 20rpx auto; |
| 105 | 169 | border-radius: 20rpx; |
| ... | ... | @@ -171,7 +235,7 @@ watch(() => props.currentIndex, (val1, val2) => { |
| 171 | 235 | |
| 172 | 236 | .bottom { |
| 173 | 237 | display: flex; |
| 174 | - margin-top: 40rpx; | |
| 238 | + margin-top: 20rpx; | |
| 175 | 239 | padding: 0 10rpx; |
| 176 | 240 | justify-content: space-between; |
| 177 | 241 | align-items: center; |
| ... | ... | @@ -186,6 +250,10 @@ watch(() => props.currentIndex, (val1, val2) => { |
| 186 | 250 | color: $u-info-dark; |
| 187 | 251 | } |
| 188 | 252 | |
| 253 | + .btn--hover { | |
| 254 | + background-color: $u-success-light; | |
| 255 | + } | |
| 256 | + | |
| 189 | 257 | .evaluate { |
| 190 | 258 | color: $u-warning-dark; |
| 191 | 259 | border-color: $u-warning-dark; | ... | ... |
garbage-removal/src/pages/order/upload/index.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="upload-image-box"> |
| 3 | 3 | <view class="upload-image-box-choose"> |
| 4 | - <text class="upload-image-box-choose-txt">请选择图片类型:</text> | |
| 4 | + <text class="upload-image-box-choose-txt">请上传{{ putType }}图片类型:</text> | |
| 5 | 5 | <view class="upload-image-box-choose-type"> |
| 6 | - <u-radio-group v-model="singleItem" @change="groupChange" placement="row"> | |
| 7 | - <u-radio activeColor="#19be6b" :customStyle="{ marginBottom: '8px' }" size="28" labelSize="28" | |
| 8 | - v-for="(item, index) in chooseList" :key="index" :label="item.name" :name="item.name" @change="radioChange"> | |
| 9 | - </u-radio> | |
| 10 | - </u-radio-group> | |
| 6 | + | |
| 11 | 7 | </view> |
| 12 | 8 | </view> |
| 13 | 9 | <view class="upload-image-box-bottom"> |
| 14 | - <text class="upload-image-box-bottom-txt">{{ singleItem }}(最多上传10张)</text> | |
| 10 | + <text class="upload-image-box-bottom-txt">{{ putType }}(最多上传10张)</text> | |
| 15 | 11 | <view class="upload-image-box-button-container"> |
| 16 | 12 | <u-upload :fileList="fileList" @afterRead="afterRead" @delete="deletePic" name="3" multiple :maxCount="10" |
| 17 | 13 | :previewFullImage="true" width="200" height="150"></u-upload> |
| 18 | 14 | </view> |
| 19 | 15 | </view> |
| 20 | 16 | <view class="upload-image-box-submit-box"> |
| 21 | - <view class="upload-image-box-submit-box-button" @click="handleSubmit(orderId, singleItem)"> | |
| 17 | + <view class="upload-image-box-submit-box-button" @click="handleSubmit(orderId, putType)"> | |
| 22 | 18 | <view class="upload-image-box-submit-box-button-container"> |
| 23 | 19 | <up-button color="#19be6b" type="primary" shape="circle" text="确定"></up-button> |
| 24 | 20 | </view> |
| ... | ... | @@ -31,23 +27,16 @@ |
| 31 | 27 | import { uploadFilePromise } from '@/apis/common.js'; |
| 32 | 28 | import { uploadImageUrlByType } from '@/apis/order.js'; |
| 33 | 29 | import { onLoad } from '@dcloudio/uni-app'; |
| 34 | -import { reactive, ref } from 'vue'; | |
| 35 | - | |
| 30 | +import { ref } from 'vue'; | |
| 31 | +const putType = ref("") | |
| 36 | 32 | const orderId = ref(); |
| 37 | 33 | const fileList = ref([]) |
| 38 | -const singleItem = ref("装车图片") | |
| 39 | -const chooseList = reactive([{ name: "装车图片" }, { name: "卸车图片" }]) | |
| 40 | 34 | // 删除图片 |
| 41 | 35 | const deletePic = (event) => { |
| 42 | 36 | fileList.value.splice(event.index, 1); |
| 43 | 37 | }; |
| 44 | 38 | |
| 45 | -const groupChange = (e) => { | |
| 46 | - console.log(e); | |
| 47 | -} | |
| 48 | -const radioChange = (e) => { | |
| 49 | - console.log(e); | |
| 50 | -} | |
| 39 | + | |
| 51 | 40 | |
| 52 | 41 | // 新增图片 |
| 53 | 42 | const afterRead = async (event) => { |
| ... | ... | @@ -82,11 +71,10 @@ const handleSubmit = (id, type) => { |
| 82 | 71 | } |
| 83 | 72 | let params = { |
| 84 | 73 | garOrderId: id, |
| 85 | - type: type == "装车图片" ? 1 : 2, | |
| 74 | + type: type == "装车照片" ? 1 : 2, | |
| 86 | 75 | imageUrls: fileList.value.map(item => item.url) |
| 87 | 76 | } |
| 88 | 77 | uploadImageUrlByType(params).then(res => { |
| 89 | - console.log(res); | |
| 90 | 78 | if (res.data.success) { |
| 91 | 79 | uni.$u.toast("图片上传完毕!"); |
| 92 | 80 | uni.$u.route({ |
| ... | ... | @@ -122,6 +110,7 @@ const validateImage = () => { |
| 122 | 110 | |
| 123 | 111 | onLoad((options) => { |
| 124 | 112 | orderId.value = options.orderId; |
| 113 | + putType.value = options.putType === "putOnImages" ? "装车照片" : "卸车照片"; | |
| 125 | 114 | }) |
| 126 | 115 | </script> |
| 127 | 116 | ... | ... |
garbage-removal/src/pages/wode/choose/index.vue
| ... | ... | @@ -22,10 +22,8 @@ const store = useMainStore(); |
| 22 | 22 | const userType = ref("居民用户") |
| 23 | 23 | const typeList = ref([{ name: "居民用户" }, { name: "管理负责人" }]) |
| 24 | 24 | const radioChange = (e) => { |
| 25 | - console.log(e); | |
| 26 | 25 | } |
| 27 | 26 | const groupChange = (e) => { |
| 28 | - console.log(e); | |
| 29 | 27 | } |
| 30 | 28 | const submit = (userType) => { |
| 31 | 29 | setRequestToken(store.tempToken) | ... | ... |
garbage-removal/src/utils/request/request.js
| ... | ... | @@ -51,6 +51,9 @@ const instance = axios.create({ |
| 51 | 51 | }); |
| 52 | 52 | // 请求拦截器 |
| 53 | 53 | instance.interceptors.request.use((config) => { |
| 54 | + if (requestUrlCheck(config.url)) { | |
| 55 | + setRequestToken(null); | |
| 56 | + } | |
| 54 | 57 | if (config.method.toLocaleLowerCase() == "get") { |
| 55 | 58 | handleGet(config); |
| 56 | 59 | } |
| ... | ... | @@ -58,7 +61,12 @@ instance.interceptors.request.use((config) => { |
| 58 | 61 | }); |
| 59 | 62 | // 响应拦截器 |
| 60 | 63 | instance.interceptors.response.use((response) => { |
| 61 | - if (response.data.code != 200) { | |
| 64 | + | |
| 65 | + // 没有网络时 message的内容为"Network Error" | |
| 66 | + if(response.errMsg === "request:fail"){ | |
| 67 | + uni.$u.toast("网络错误~") | |
| 68 | + } | |
| 69 | + if (response.data.code != 200) { | |
| 62 | 70 | if (response.data.code == 401) { |
| 63 | 71 | reSetLoginStatus(); |
| 64 | 72 | } else { |
| ... | ... | @@ -70,17 +78,18 @@ instance.interceptors.response.use((response) => { |
| 70 | 78 | } |
| 71 | 79 | return response; |
| 72 | 80 | }, (error) => { |
| 81 | + | |
| 73 | 82 | if (error.response.status) { |
| 74 | 83 | switch (error.response.status) { |
| 75 | 84 | case 401: |
| 76 | 85 | case 403: |
| 77 | - setRequestToken(null); | |
| 86 | + reSetLoginStatus(); | |
| 78 | 87 | break; |
| 79 | 88 | default: |
| 80 | 89 | break; |
| 81 | 90 | } |
| 82 | 91 | } |
| 83 | - uni.$u.toast("网络波动请再试~") | |
| 92 | + | |
| 84 | 93 | return Promise.reject(error) |
| 85 | 94 | }); |
| 86 | 95 | export default instance; |
| ... | ... | @@ -100,6 +109,15 @@ const reSetLoginStatus = () => { |
| 100 | 109 | }) |
| 101 | 110 | return |
| 102 | 111 | } |
| 112 | +let urlRegex = /\/user\/send\/verify/; | |
| 113 | + | |
| 114 | +/** | |
| 115 | + * 检查需要被拦截的路径 | |
| 116 | + */ | |
| 117 | +const requestUrlCheck = (url) => { | |
| 118 | + // 使用正则表达式进行匹配 | |
| 119 | + return urlRegex.test(url); | |
| 120 | +} | |
| 103 | 121 | |
| 104 | 122 | const handleGet = (config) => { |
| 105 | 123 | let strUrl = ""; |
| ... | ... | @@ -115,5 +133,4 @@ const handleGet = (config) => { |
| 115 | 133 | } |
| 116 | 134 | config.url += strUrl; |
| 117 | 135 | config.params = ""; |
| 118 | - console.log("请求拦截",config); | |
| 119 | 136 | } | ... | ... |
garbage-removal/src/uview-plus/components/u-action-sheet/props.js
garbage-removal/src/uview-plus/components/u-action-sheet/u-action-sheet.vue
| 1 | 1 | |
| 2 | 2 | <template> |
| 3 | - <u-popup | |
| 4 | - :show="show" | |
| 5 | - mode="bottom" | |
| 6 | - @close="closeHandler" | |
| 7 | - :safeAreaInsetBottom="safeAreaInsetBottom" | |
| 8 | - :round="round" | |
| 9 | - > | |
| 3 | + <u-popup :show="show" mode="bottom" @close="closeHandler" :safeAreaInsetBottom="safeAreaInsetBottom" :round="round"> | |
| 10 | 4 | <view class="u-action-sheet"> |
| 11 | - <view | |
| 12 | - class="u-action-sheet__header" | |
| 13 | - v-if="title" | |
| 14 | - > | |
| 15 | - <text class="u-action-sheet__header__title u-line-1">{{title}}</text> | |
| 16 | - <view | |
| 17 | - class="u-action-sheet__header__icon-wrap" | |
| 18 | - @tap.stop="cancel" | |
| 19 | - > | |
| 20 | - <u-icon | |
| 21 | - name="close" | |
| 22 | - size="17" | |
| 23 | - color="#c8c9cc" | |
| 24 | - bold | |
| 25 | - ></u-icon> | |
| 5 | + <view class="u-action-sheet__header" v-if="title"> | |
| 6 | + <text class="u-action-sheet__header__title u-line-1">{{ title }}</text> | |
| 7 | + <view class="u-action-sheet__header__icon-wrap" @click.stop="cancel"> | |
| 8 | + <u-icon name="close" size="17" color="#c8c9cc" bold></u-icon> | |
| 26 | 9 | </view> |
| 27 | 10 | </view> |
| 28 | - <text | |
| 29 | - class="u-action-sheet__description" | |
| 30 | - :style="[{ | |
| 31 | - marginTop: `${title && description ? 0 : '18px'}` | |
| 32 | - }]" | |
| 33 | - v-if="description" | |
| 34 | - >{{description}}</text> | |
| 11 | + <text class="u-action-sheet__description" :style="[{ | |
| 12 | + marginTop: `${title && description ? 0 : '18px'}` | |
| 13 | + }]" v-if="description">{{ description }}</text> | |
| 35 | 14 | <slot> |
| 36 | 15 | <u-line v-if="description"></u-line> |
| 37 | 16 | <view class="u-action-sheet__item-wrap"> |
| 38 | 17 | <view :key="index" v-for="(item, index) in actions"> |
| 39 | 18 | <!-- #ifdef MP --> |
| 40 | - <button | |
| 41 | - class="u-reset-button" | |
| 42 | - :openType="item.openType" | |
| 43 | - @getuserinfo="onGetUserInfo" | |
| 44 | - @contact="onContact" | |
| 45 | - @getphonenumber="onGetPhoneNumber" | |
| 46 | - @error="onError" | |
| 47 | - @launchapp="onLaunchApp" | |
| 48 | - @opensetting="onOpenSetting" | |
| 49 | - :lang="lang" | |
| 50 | - :session-from="sessionFrom" | |
| 51 | - :send-message-title="sendMessageTitle" | |
| 52 | - :send-message-path="sendMessagePath" | |
| 53 | - :send-message-img="sendMessageImg" | |
| 54 | - :show-message-card="showMessageCard" | |
| 55 | - :app-parameter="appParameter" | |
| 56 | - @tap="selectHandler(index)" | |
| 57 | - :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''" | |
| 58 | - > | |
| 19 | + <button v-if="item.name != '提交' && item.name != '其他'" class="u-reset-button" | |
| 20 | + :class="currentSelect == index ? 'u-action-sheet--active' : ''" :openType="item.openType" | |
| 21 | + @getuserinfo="onGetUserInfo" @contact="onContact" @getphonenumber="onGetPhoneNumber" @error="onError" | |
| 22 | + @launchapp="onLaunchApp" @opensetting="onOpenSetting" :lang="lang" :session-from="sessionFrom" | |
| 23 | + :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" | |
| 24 | + :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :app-parameter="appParameter" | |
| 25 | + @tap.stop="selectHandler(index)" | |
| 26 | + :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"> | |
| 59 | 27 | <!-- #endif --> |
| 60 | - <view | |
| 61 | - class="u-action-sheet__item-wrap__item" | |
| 62 | - @tap.stop="selectHandler(index)" | |
| 63 | - :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''" | |
| 64 | - :hover-stay-time="150" | |
| 65 | - > | |
| 28 | + <view v-if="item.name != '提交' && item.name != '其他'" class="u-action-sheet__item-wrap__item" | |
| 29 | + :class="currentSelect == index ? 'u-action-sheet--active' : ''" @tap.stop="selectHandler(index)" | |
| 30 | + :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''" :hover-stay-time="150"> | |
| 66 | 31 | <template v-if="!item.loading"> |
| 67 | - <text | |
| 68 | - class="u-action-sheet__item-wrap__item__name" | |
| 69 | - :style="[itemStyle(index)]" | |
| 70 | - >{{ item.name }}</text> | |
| 71 | - <text | |
| 72 | - v-if="item.subname" | |
| 73 | - class="u-action-sheet__item-wrap__item__subname" | |
| 74 | - >{{ item.subname }}</text> | |
| 32 | + <text class="u-action-sheet__item-wrap__item__name" :style="[itemStyle(index)]">{{ item.name }}</text> | |
| 33 | + <text v-if="item.subname" class="u-action-sheet__item-wrap__item__subname">{{ item.subname }}</text> | |
| 75 | 34 | </template> |
| 76 | - <u-loading-icon | |
| 77 | - v-else | |
| 78 | - custom-class="van-action-sheet__loading" | |
| 79 | - size="18" | |
| 80 | - mode="circle" | |
| 81 | - /> | |
| 35 | + <u-loading-icon v-else custom-class="van-action-sheet__loading" size="18" mode="circle" /> | |
| 82 | 36 | </view> |
| 83 | 37 | <!-- #ifdef MP --> |
| 84 | 38 | </button> |
| 85 | 39 | <!-- #endif --> |
| 40 | + <view v-if="item.name == '其他'" class="u-action-sheet__item-wrap__item" :hover-stay-time="150"> | |
| 41 | + <view class="parent-box"> | |
| 42 | + <u-collapse> | |
| 43 | + <u-collapse-item @selectHandler="selectHandler" :index="index" :name="item.name" ref="childRef" | |
| 44 | + title="其他" name="其他"> | |
| 45 | + <view class="u-collapse-content" style="width: 97vw;text-align: left;"> | |
| 46 | + <u--textarea v-model="otherReason" placeholder="请输入原因"></u--textarea> | |
| 47 | + </view> | |
| 48 | + </u-collapse-item> | |
| 49 | + </u-collapse> | |
| 50 | + </view> | |
| 51 | + </view> | |
| 52 | + <!-- #ifdef MP --> | |
| 53 | + <!-- <button v-if="item.name == '提交'" class="u-reset-button u-reset-button-btn" :openType="item.openType" | |
| 54 | + @getuserinfo="onGetUserInfo" @contact="onContact" @getphonenumber="onGetPhoneNumber" @error="onError" | |
| 55 | + @launchapp="onLaunchApp" @opensetting="onOpenSetting" :lang="lang" :session-from="sessionFrom" | |
| 56 | + :send-message-title="sendMessageTitle" :send-message-path="sendMessagePath" | |
| 57 | + :send-message-img="sendMessageImg" :show-message-card="showMessageCard" :app-parameter="appParameter" | |
| 58 | + @tap.stop="selectHandler(index,item.name)" :hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"> --> | |
| 59 | + <!-- #endif --> | |
| 60 | + <view v-if="item.name == '提交'" class="u-action-sheet__item-wrap__item u-reset-button-btn" | |
| 61 | + @tap.stop="handleSubmitFunction(item.name)" :hover-stay-time="150"> | |
| 62 | + <template v-if="!item.loading"> | |
| 63 | + <text class="u-action-sheet__item-wrap__item__name" :style="[itemStyle(index)]">{{ item.name }}</text> | |
| 64 | + </template> | |
| 65 | + <u-loading-icon v-else custom-class="van-action-sheet__loading" size="18" mode="circle" /> | |
| 66 | + </view> | |
| 67 | + <!-- #ifdef MP --> | |
| 68 | + <!-- </button> --> | |
| 69 | + <!-- #endif --> | |
| 86 | 70 | <u-line v-if="index !== actions.length - 1"></u-line> |
| 87 | 71 | </view> |
| 88 | 72 | </view> |
| 89 | 73 | </slot> |
| 90 | - <u-gap | |
| 91 | - bgColor="#eaeaec" | |
| 92 | - height="6" | |
| 93 | - v-if="cancelText" | |
| 94 | - ></u-gap> | |
| 74 | + <u-gap bgColor="#eaeaec" height="6" v-if="cancelText"></u-gap> | |
| 95 | 75 | <view hover-class="u-action-sheet--hover"> |
| 96 | - <text | |
| 97 | - @touchmove.stop.prevent | |
| 98 | - :hover-stay-time="150" | |
| 99 | - v-if="cancelText" | |
| 100 | - class="u-action-sheet__cancel-text" | |
| 101 | - @tap="cancel" | |
| 102 | - >{{cancelText}}</text> | |
| 76 | + <text @touchmove.stop.prevent :hover-stay-time="150" v-if="cancelText" class="u-action-sheet__cancel-text" | |
| 77 | + @tap.stop="cancel">{{ cancelText }}</text> | |
| 103 | 78 | </view> |
| 104 | 79 | </view> |
| 105 | 80 | </u-popup> |
| 106 | 81 | </template> |
| 107 | 82 | |
| 108 | 83 | <script> |
| 109 | - import openType from '../../libs/mixin/openType' | |
| 110 | - import button from '../../libs/mixin/button' | |
| 111 | - import props from './props.js'; | |
| 112 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 113 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 114 | - /** | |
| 115 | - * ActionSheet 操作菜单 | |
| 116 | - * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。 | |
| 117 | - * @tutorial https://ijry.github.io/uview-plus/components/actionSheet.html | |
| 118 | - * | |
| 119 | - * @property {Boolean} show 操作菜单是否展示 (默认 false ) | |
| 120 | - * @property {String} title 操作菜单标题 | |
| 121 | - * @property {String} description 选项上方的描述信息 | |
| 122 | - * @property {Array<Object>} actions 按钮的文字数组,见官方文档示例 | |
| 123 | - * @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮 | |
| 124 | - * @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true ) | |
| 125 | - * @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true ) | |
| 126 | - * @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error ) | |
| 127 | - * @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true ) | |
| 128 | - * @property {Number|String} round 圆角值,默认无圆角 (默认 0 ) | |
| 129 | - * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 | |
| 130 | - * @property {String} sessionFrom 会话来源,openType="contact"时有效 | |
| 131 | - * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效 | |
| 132 | - * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效 | |
| 133 | - * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效 | |
| 134 | - * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false ) | |
| 135 | - * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效 | |
| 136 | - * | |
| 137 | - * @event {Function} select 点击ActionSheet列表项时触发 | |
| 138 | - * @event {Function} close 点击取消按钮时触发 | |
| 139 | - * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效 | |
| 140 | - * @event {Function} contact 客服消息回调,openType="contact"时有效 | |
| 141 | - * @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效 | |
| 142 | - * @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效 | |
| 143 | - * @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效 | |
| 144 | - * @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效 | |
| 145 | - * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet> | |
| 146 | - */ | |
| 147 | - export default { | |
| 148 | - name: "u-action-sheet", | |
| 149 | - // 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到 | |
| 150 | - mixins: [openType, button, mixin, props], | |
| 151 | - data() { | |
| 152 | - return { | |
| 153 | - | |
| 84 | +import button from '../../libs/mixin/button'; | |
| 85 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 86 | +import openType from '../../libs/mixin/openType'; | |
| 87 | +import props from './props.js'; | |
| 88 | +/** | |
| 89 | + * ActionSheet 操作菜单 | |
| 90 | + * @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。 | |
| 91 | + * @tutorial https://ijry.github.io/uview-plus/components/actionSheet.html | |
| 92 | + * | |
| 93 | + * @property {Boolean} show 操作菜单是否展示 (默认 false ) | |
| 94 | + * @property {String} title 操作菜单标题 | |
| 95 | + * @property {String} description 选项上方的描述信息 | |
| 96 | + * @property {Array<Object>} actions 按钮的文字数组,见官方文档示例 | |
| 97 | + * @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮 | |
| 98 | + * @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 (默认 true ) | |
| 99 | + * @property {Boolean} safeAreaInsetBottom 处理底部安全区 (默认 true ) | |
| 100 | + * @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting |getPhoneNumber |error ) | |
| 101 | + * @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true ) | |
| 102 | + * @property {Number|String} round 圆角值,默认无圆角 (默认 0 ) | |
| 103 | + * @property {String} lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 | |
| 104 | + * @property {String} sessionFrom 会话来源,openType="contact"时有效 | |
| 105 | + * @property {String} sendMessageTitle 会话内消息卡片标题,openType="contact"时有效 | |
| 106 | + * @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径,openType="contact"时有效 | |
| 107 | + * @property {String} sendMessageImg 会话内消息卡片图片,openType="contact"时有效 | |
| 108 | + * @property {Boolean} showMessageCard 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,openType="contact"时有效 (默认 false ) | |
| 109 | + * @property {String} appParameter 打开 APP 时,向 APP 传递的参数,openType=launchApp 时有效 | |
| 110 | + * | |
| 111 | + * @event {Function} select 点击ActionSheet列表项时触发 | |
| 112 | + * @event {Function} close 点击取消按钮时触发 | |
| 113 | + * @event {Function} getuserinfo 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与 wx.getUserInfo 返回的一致,openType="getUserInfo"时有效 | |
| 114 | + * @event {Function} contact 客服消息回调,openType="contact"时有效 | |
| 115 | + * @event {Function} getphonenumber 获取用户手机号回调,openType="getPhoneNumber"时有效 | |
| 116 | + * @event {Function} error 当使用开放能力时,发生错误的回调,openType="error"时有效 | |
| 117 | + * @event {Function} launchapp 打开 APP 成功的回调,openType="launchApp"时有效 | |
| 118 | + * @event {Function} opensetting 在打开授权设置页后回调,openType="openSetting"时有效 | |
| 119 | + * @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet> | |
| 120 | + */ | |
| 121 | +export default { | |
| 122 | + name: "u-action-sheet", | |
| 123 | + // 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到 | |
| 124 | + mixins: [openType, button, mixin, props], | |
| 125 | + data() { | |
| 126 | + return { | |
| 127 | + currentSelect: -1, | |
| 128 | + otherReason: "", | |
| 129 | + accordion: false | |
| 130 | + } | |
| 131 | + }, watch: { | |
| 132 | + show(newValue, oldValue) { | |
| 133 | + if (newValue === true) { | |
| 134 | + this.currentSelect = -1 | |
| 135 | + this.otherReason = "" | |
| 136 | + this.accordion = false | |
| 137 | + } | |
| 138 | + } | |
| 139 | + }, | |
| 140 | + computed: { | |
| 141 | + // 操作项目的样式 | |
| 142 | + itemStyle() { | |
| 143 | + return (index) => { | |
| 144 | + let style = {}; | |
| 145 | + if (this.actions[index].color) style.color = this.actions[index].color | |
| 146 | + if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize) | |
| 147 | + // 选项被禁用的样式 | |
| 148 | + if (this.actions[index].disabled) style.color = '#c0c4cc' | |
| 149 | + return style; | |
| 154 | 150 | } |
| 155 | 151 | }, |
| 156 | - computed: { | |
| 157 | - // 操作项目的样式 | |
| 158 | - itemStyle() { | |
| 159 | - return (index) => { | |
| 160 | - let style = {}; | |
| 161 | - if (this.actions[index].color) style.color = this.actions[index].color | |
| 162 | - if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize) | |
| 163 | - // 选项被禁用的样式 | |
| 164 | - if (this.actions[index].disabled) style.color = '#c0c4cc' | |
| 165 | - return style; | |
| 166 | - } | |
| 167 | - }, | |
| 152 | + }, | |
| 153 | + methods: { | |
| 154 | + closeHandler() { | |
| 155 | + // 允许点击遮罩关闭时,才发出close事件 | |
| 156 | + if (this.closeOnClickOverlay) { | |
| 157 | + this.$emit('actionSheetClose') | |
| 158 | + } | |
| 168 | 159 | }, |
| 169 | - methods: { | |
| 170 | - closeHandler() { | |
| 171 | - // 允许点击遮罩关闭时,才发出close事件 | |
| 172 | - if(this.closeOnClickOverlay) { | |
| 173 | - this.$emit('close') | |
| 160 | + // 点击取消按钮 | |
| 161 | + cancel() { | |
| 162 | + this.$emit('actionSheetClose') | |
| 163 | + }, | |
| 164 | + selectHandler(index, name) { | |
| 165 | + if (name != "其他") { | |
| 166 | + if (this.accordion) { | |
| 167 | + this.$refs.childRef[0].clickHandler("抽屉"); | |
| 168 | + this.accordion = false; | |
| 174 | 169 | } |
| 175 | - }, | |
| 176 | - // 点击取消按钮 | |
| 177 | - cancel() { | |
| 178 | - this.$emit('close') | |
| 179 | - }, | |
| 180 | - selectHandler(index) { | |
| 181 | - const item = this.actions[index] | |
| 182 | - if (item && !item.disabled && !item.loading) { | |
| 183 | - this.$emit('select', item) | |
| 184 | - if (this.closeOnClickAction) { | |
| 185 | - this.$emit('close') | |
| 186 | - } | |
| 170 | + this.otherReason = '' | |
| 171 | + } | |
| 172 | + if (name == "其他") { | |
| 173 | + this.accordion = true; | |
| 174 | + } | |
| 175 | + this.currentSelect = index; | |
| 176 | + const item = this.actions[index] | |
| 177 | + if (item && !item.disabled && !item.loading) { | |
| 178 | + this.$emit('select', item) | |
| 179 | + if (this.closeOnClickAction) { | |
| 180 | + this.$emit('close') | |
| 187 | 181 | } |
| 188 | - }, | |
| 182 | + } | |
| 183 | + }, | |
| 184 | + handleSubmitFunction(name) { | |
| 185 | + if (name == "提交") { | |
| 186 | + this.$emit('submitFunction', this.otherReason); | |
| 187 | + } | |
| 189 | 188 | } |
| 190 | 189 | } |
| 190 | +} | |
| 191 | 191 | </script> |
| 192 | 192 | |
| 193 | 193 | <style lang="scss" scoped> |
| 194 | - @import "../../libs/css/components.scss"; | |
| 195 | - $u-action-sheet-reset-button-width:100% !default; | |
| 196 | - $u-action-sheet-title-font-size: 16px !default; | |
| 197 | - $u-action-sheet-title-padding: 12px 30px !default; | |
| 198 | - $u-action-sheet-title-color: $u-main-color !default; | |
| 199 | - $u-action-sheet-header-icon-wrap-right:15px !default; | |
| 200 | - $u-action-sheet-header-icon-wrap-top:15px !default; | |
| 201 | - $u-action-sheet-description-font-size:13px !default; | |
| 202 | - $u-action-sheet-description-color:14px !default; | |
| 203 | - $u-action-sheet-description-margin: 18px 15px !default; | |
| 204 | - $u-action-sheet-item-wrap-item-padding:15px !default; | |
| 205 | - $u-action-sheet-item-wrap-name-font-size:16px !default; | |
| 206 | - $u-action-sheet-item-wrap-subname-font-size:13px !default; | |
| 207 | - $u-action-sheet-item-wrap-subname-color: #c0c4cc !default; | |
| 208 | - $u-action-sheet-item-wrap-subname-margin-top:10px !default; | |
| 209 | - $u-action-sheet-cancel-text-font-size:16px !default; | |
| 210 | - $u-action-sheet-cancel-text-color:$u-content-color !default; | |
| 211 | - $u-action-sheet-cancel-text-font-size:15px !default; | |
| 212 | - $u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default; | |
| 194 | +@import "../../libs/css/components.scss"; | |
| 195 | +$u-action-sheet-reset-button-width: 100% !default; | |
| 196 | +$u-action-sheet-title-font-size: 16px !default; | |
| 197 | +$u-action-sheet-title-padding: 12px 30px !default; | |
| 198 | +$u-action-sheet-title-color: $u-main-color !default; | |
| 199 | +$u-action-sheet-header-icon-wrap-right: 15px !default; | |
| 200 | +$u-action-sheet-header-icon-wrap-top: 15px !default; | |
| 201 | +$u-action-sheet-description-font-size: 13px !default; | |
| 202 | +$u-action-sheet-description-color: 14px !default; | |
| 203 | +$u-action-sheet-description-margin: 18px 15px !default; | |
| 204 | +$u-action-sheet-item-wrap-item-padding: 15px !default; | |
| 205 | +$u-action-sheet-item-wrap-name-font-size: 16px !default; | |
| 206 | +$u-action-sheet-item-wrap-subname-font-size: 13px !default; | |
| 207 | +$u-action-sheet-item-wrap-subname-color: #c0c4cc !default; | |
| 208 | +$u-action-sheet-item-wrap-subname-margin-top: 10px !default; | |
| 209 | +$u-action-sheet-cancel-text-font-size: 16px !default; | |
| 210 | +$u-action-sheet-cancel-text-color: $u-content-color !default; | |
| 211 | +$u-action-sheet-cancel-text-font-size: 15px !default; | |
| 212 | +$u-action-sheet-cancel-text-hover-background-color: rgb(242, 243, 245) !default; | |
| 213 | 213 | |
| 214 | - .u-reset-button { | |
| 215 | - width: $u-action-sheet-reset-button-width; | |
| 216 | - } | |
| 214 | +.u-reset-button { | |
| 215 | + width: $u-action-sheet-reset-button-width; | |
| 216 | +} | |
| 217 | 217 | |
| 218 | - .u-action-sheet { | |
| 219 | - text-align: center; | |
| 220 | - &__header { | |
| 221 | - position: relative; | |
| 222 | - padding: $u-action-sheet-title-padding; | |
| 223 | - &__title { | |
| 224 | - font-size: $u-action-sheet-title-font-size; | |
| 225 | - color: $u-action-sheet-title-color; | |
| 226 | - font-weight: bold; | |
| 227 | - text-align: center; | |
| 228 | - } | |
| 218 | +.u-reset-button-btn { | |
| 219 | + margin: 20rpx 0; | |
| 220 | + background-color: $u-success; | |
| 221 | + width: $u-action-sheet-reset-button-width; | |
| 222 | + box-sizing: border-box; | |
| 223 | +} | |
| 229 | 224 | |
| 230 | - &__icon-wrap { | |
| 231 | - position: absolute; | |
| 232 | - right: $u-action-sheet-header-icon-wrap-right; | |
| 233 | - top: $u-action-sheet-header-icon-wrap-top; | |
| 234 | - } | |
| 235 | - } | |
| 236 | 225 | |
| 237 | - &__description { | |
| 238 | - font-size: $u-action-sheet-description-font-size; | |
| 239 | - color: $u-tips-color; | |
| 240 | - margin: $u-action-sheet-description-margin; | |
| 226 | +.u-action-sheet { | |
| 227 | + text-align: center; | |
| 228 | + | |
| 229 | + &__header { | |
| 230 | + position: relative; | |
| 231 | + padding: $u-action-sheet-title-padding; | |
| 232 | + | |
| 233 | + &__title { | |
| 234 | + font-size: $u-action-sheet-title-font-size; | |
| 235 | + color: $u-action-sheet-title-color; | |
| 236 | + font-weight: bold; | |
| 241 | 237 | text-align: center; |
| 242 | 238 | } |
| 243 | 239 | |
| 244 | - &__item-wrap { | |
| 240 | + &__icon-wrap { | |
| 241 | + position: absolute; | |
| 242 | + right: $u-action-sheet-header-icon-wrap-right; | |
| 243 | + top: $u-action-sheet-header-icon-wrap-top; | |
| 244 | + } | |
| 245 | + } | |
| 246 | + | |
| 247 | + &__description { | |
| 248 | + font-size: $u-action-sheet-description-font-size; | |
| 249 | + color: $u-tips-color; | |
| 250 | + margin: $u-action-sheet-description-margin; | |
| 251 | + text-align: center; | |
| 252 | + } | |
| 245 | 253 | |
| 246 | - &__item { | |
| 247 | - padding: $u-action-sheet-item-wrap-item-padding; | |
| 248 | - @include flex; | |
| 249 | - align-items: center; | |
| 250 | - justify-content: center; | |
| 251 | - flex-direction: column; | |
| 254 | + &__item-wrap { | |
| 252 | 255 | |
| 253 | - &__name { | |
| 254 | - font-size: $u-action-sheet-item-wrap-name-font-size; | |
| 255 | - color: $u-main-color; | |
| 256 | - text-align: center; | |
| 257 | - } | |
| 256 | + &__item { | |
| 257 | + padding: $u-action-sheet-item-wrap-item-padding; | |
| 258 | + @include flex; | |
| 259 | + align-items: center; | |
| 260 | + justify-content: center; | |
| 261 | + flex-direction: column; | |
| 258 | 262 | |
| 259 | - &__subname { | |
| 260 | - font-size: $u-action-sheet-item-wrap-subname-font-size; | |
| 261 | - color: $u-action-sheet-item-wrap-subname-color; | |
| 262 | - margin-top: $u-action-sheet-item-wrap-subname-margin-top; | |
| 263 | - text-align: center; | |
| 264 | - } | |
| 263 | + &__name { | |
| 264 | + font-size: $u-action-sheet-item-wrap-name-font-size; | |
| 265 | + color: $u-main-color; | |
| 266 | + text-align: center; | |
| 265 | 267 | } |
| 266 | - } | |
| 267 | 268 | |
| 268 | - &__cancel-text { | |
| 269 | - font-size: $u-action-sheet-cancel-text-font-size; | |
| 270 | - color: $u-action-sheet-cancel-text-color; | |
| 271 | - text-align: center; | |
| 272 | - padding: $u-action-sheet-cancel-text-font-size; | |
| 269 | + &__subname { | |
| 270 | + font-size: $u-action-sheet-item-wrap-subname-font-size; | |
| 271 | + color: $u-action-sheet-item-wrap-subname-color; | |
| 272 | + margin-top: $u-action-sheet-item-wrap-subname-margin-top; | |
| 273 | + text-align: center; | |
| 274 | + } | |
| 273 | 275 | } |
| 276 | + } | |
| 274 | 277 | |
| 275 | - &--hover { | |
| 276 | - background-color: $u-action-sheet-cancel-text-hover-background-color; | |
| 277 | - } | |
| 278 | + &__cancel-text { | |
| 279 | + font-size: $u-action-sheet-cancel-text-font-size; | |
| 280 | + color: $u-action-sheet-cancel-text-color; | |
| 281 | + text-align: center; | |
| 282 | + padding: $u-action-sheet-cancel-text-font-size; | |
| 283 | + } | |
| 284 | + | |
| 285 | + &--hover { | |
| 286 | + background-color: $u-success-light; | |
| 287 | + } | |
| 288 | + | |
| 289 | + &--active { | |
| 290 | + background-color: $u-success-light; | |
| 278 | 291 | } |
| 292 | +} | |
| 279 | 293 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-checkbox-group/u-checkbox-group.vue
| 1 | 1 | <template> |
| 2 | - <view | |
| 3 | - class="u-checkbox-group" | |
| 4 | - :class="bemClass" | |
| 5 | - > | |
| 2 | + <view class="u-checkbox-group" :class="bemClass"> | |
| 6 | 3 | <slot></slot> |
| 7 | 4 | </view> |
| 8 | 5 | </template> |
| 9 | 6 | |
| 10 | 7 | <script> |
| 11 | - import props from './props.js'; | |
| 12 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 13 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 14 | - /** | |
| 15 | - * checkboxGroup 复选框组 | |
| 16 | - * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便 | |
| 17 | - * @tutorial https://ijry.github.io/uview-plus/components/checkbox.html | |
| 18 | - * @property {String} name 标识符 | |
| 19 | - * @property {Array} value 绑定的值 | |
| 20 | - * @property {String} shape 形状,circle-圆形,square-方形 (默认 'square' ) | |
| 21 | - * @property {Boolean} disabled 是否禁用全部checkbox (默认 false ) | |
| 22 | - * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' ) | |
| 23 | - * @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' ) | |
| 24 | - * @property {String | Number} size 整个组件的尺寸 单位px (默认 18 ) | |
| 25 | - * @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' ) | |
| 26 | - * @property {String | Number} labelSize label的字体大小,px单位 (默认 14 ) | |
| 27 | - * @property {String} labelColor label的字体颜色 (默认 '#303133' ) | |
| 28 | - * @property {Boolean} labelDisabled 是否禁止点击文本操作 (默认 false ) | |
| 29 | - * @property {String} iconColor 图标颜色 (默认 '#ffffff' ) | |
| 30 | - * @property {String | Number} iconSize 图标的大小,单位px (默认 12 ) | |
| 31 | - * @property {String} iconPlacement 勾选图标的对齐方式,left-左边,right-右边 (默认 'left' ) | |
| 32 | - * @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false ) | |
| 33 | - * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象 | |
| 34 | - * @event {Function} input 修改通过v-model绑定的值时触发,回调为一个对象 | |
| 35 | - * @example <u-checkbox-group></u-checkbox-group> | |
| 36 | - */ | |
| 37 | - export default { | |
| 38 | - name: 'u-checkbox-group', | |
| 39 | - mixins: [mpMixin, mixin,props], | |
| 40 | - computed: { | |
| 41 | - // 这里computed的变量,都是子组件u-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化 | |
| 42 | - // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-checkbox-group) | |
| 43 | - // 拉取父组件新的变化后的参数 | |
| 44 | - parentData() { | |
| 45 | - return [ | |
| 8 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 9 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 10 | +import props from './props.js'; | |
| 11 | +/** | |
| 12 | + * checkboxGroup 复选框组 | |
| 13 | + * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便 | |
| 14 | + * @tutorial https://ijry.github.io/uview-plus/components/checkbox.html | |
| 15 | + * @property {String} name 标识符 | |
| 16 | + * @property {Array} value 绑定的值 | |
| 17 | + * @property {String} shape 形状,circle-圆形,square-方形 (默认 'square' ) | |
| 18 | + * @property {Boolean} disabled 是否禁用全部checkbox (默认 false ) | |
| 19 | + * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' ) | |
| 20 | + * @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' ) | |
| 21 | + * @property {String | Number} size 整个组件的尺寸 单位px (默认 18 ) | |
| 22 | + * @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' ) | |
| 23 | + * @property {String | Number} labelSize label的字体大小,px单位 (默认 14 ) | |
| 24 | + * @property {String} labelColor label的字体颜色 (默认 '#303133' ) | |
| 25 | + * @property {Boolean} labelDisabled 是否禁止点击文本操作 (默认 false ) | |
| 26 | + * @property {String} iconColor 图标颜色 (默认 '#ffffff' ) | |
| 27 | + * @property {String | Number} iconSize 图标的大小,单位px (默认 12 ) | |
| 28 | + * @property {String} iconPlacement 勾选图标的对齐方式,left-左边,right-右边 (默认 'left' ) | |
| 29 | + * @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false ) | |
| 30 | + * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象 | |
| 31 | + * @event {Function} input 修改通过v-model绑定的值时触发,回调为一个对象 | |
| 32 | + * @example <u-checkbox-group></u-checkbox-group> | |
| 33 | + */ | |
| 34 | +export default { | |
| 35 | + name: 'u-checkbox-group', | |
| 36 | + mixins: [mpMixin, mixin, props], | |
| 37 | + computed: { | |
| 38 | + // 这里computed的变量,都是子组件u-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化 | |
| 39 | + // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-checkbox-group) | |
| 40 | + // 拉取父组件新的变化后的参数 | |
| 41 | + parentData() { | |
| 42 | + return [ | |
| 46 | 43 | // #ifdef VUE2 |
| 47 | 44 | this.value, |
| 48 | 45 | // #endif |
| ... | ... | @@ -58,76 +55,76 @@ |
| 58 | 55 | this.iconSize, |
| 59 | 56 | this.borderBottom, |
| 60 | 57 | this.placement, |
| 61 | - ]; | |
| 62 | - }, | |
| 63 | - bemClass() { | |
| 64 | - // this.bem为一个computed变量,在mixin中 | |
| 65 | - return this.bem('checkbox-group', ['placement']) | |
| 66 | - }, | |
| 58 | + ]; | |
| 67 | 59 | }, |
| 68 | - watch: { | |
| 69 | - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 70 | - parentData: { | |
| 71 | - handler() { | |
| 60 | + bemClass() { | |
| 61 | + // this.bem为一个computed变量,在mixin中 | |
| 62 | + return this.bem('checkbox-group', ['placement']) | |
| 63 | + }, | |
| 64 | + }, | |
| 65 | + watch: { | |
| 66 | + // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 67 | + parentData: { | |
| 68 | + handler() { | |
| 72 | 69 | if (this.children.length) { |
| 73 | - this.children.map((child) => { | |
| 74 | - // 判断子组件(u-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 75 | - typeof child.init === "function" && child.init(); | |
| 76 | - }); | |
| 70 | + this.children.map((child) => { | |
| 71 | + // 判断子组件(u-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 72 | + typeof child.init === "function" && child.init(); | |
| 73 | + }); | |
| 77 | 74 | } |
| 78 | - }, | |
| 79 | - deep: true, | |
| 80 | 75 | }, |
| 76 | + deep: true, | |
| 81 | 77 | }, |
| 82 | - data() { | |
| 83 | - return { | |
| 78 | + }, | |
| 79 | + data() { | |
| 80 | + return { | |
| 84 | 81 | |
| 85 | - } | |
| 86 | - }, | |
| 87 | - created() { | |
| 88 | - this.children = [] | |
| 89 | - }, | |
| 90 | - // #ifdef VUE3 | |
| 91 | - emits: ['update:modelValue', 'change'], | |
| 92 | - // #endif | |
| 93 | - methods: { | |
| 94 | - // 将其他的checkbox设置为未选中的状态 | |
| 95 | - unCheckedOther(childInstance) { | |
| 96 | - const values = [] | |
| 97 | - this.children.map(child => { | |
| 98 | - // 将被选中的checkbox,放到数组中返回 | |
| 99 | - if (child.isChecked) { | |
| 100 | - values.push(child.name) | |
| 101 | - } | |
| 102 | - }) | |
| 103 | - // 发出事件 | |
| 104 | - this.$emit('change', values) | |
| 105 | - // 修改通过v-model绑定的值 | |
| 106 | - // #ifdef VUE3 | |
| 107 | - this.$emit("update:modelValue", values); | |
| 108 | - // #endif | |
| 109 | - // #ifdef VUE2 | |
| 110 | - this.$emit("input", values); | |
| 111 | - // #endif | |
| 112 | - }, | |
| 113 | 82 | } |
| 83 | + }, | |
| 84 | + created() { | |
| 85 | + this.children = [] | |
| 86 | + }, | |
| 87 | + // #ifdef VUE3 | |
| 88 | + emits: ['update:modelValue', 'change'], | |
| 89 | + // #endif | |
| 90 | + methods: { | |
| 91 | + // 将其他的checkbox设置为未选中的状态 | |
| 92 | + unCheckedOther(childInstance) { | |
| 93 | + const values = [] | |
| 94 | + this.children.map(child => { | |
| 95 | + // 将被选中的checkbox,放到数组中返回 | |
| 96 | + if (child.isChecked) { | |
| 97 | + values.push(child.name) | |
| 98 | + } | |
| 99 | + }) | |
| 100 | + // 发出事件 | |
| 101 | + this.$emit('change', values) | |
| 102 | + // 修改通过v-model绑定的值 | |
| 103 | + // #ifdef VUE3 | |
| 104 | + this.$emit("update:modelValue", values); | |
| 105 | + // #endif | |
| 106 | + // #ifdef VUE2 | |
| 107 | + this.$emit("input", values); | |
| 108 | + // #endif | |
| 109 | + }, | |
| 114 | 110 | } |
| 111 | +} | |
| 115 | 112 | </script> |
| 116 | 113 | |
| 117 | 114 | <style lang="scss" scoped> |
| 118 | - @import "../../libs/css/components.scss"; | |
| 115 | +@import "../../libs/css/components.scss"; | |
| 119 | 116 | |
| 120 | - .u-checkbox-group { | |
| 117 | +.u-checkbox-group { | |
| 121 | 118 | |
| 122 | - &--row { | |
| 123 | - /* #ifndef APP-NVUE */ | |
| 124 | - display: flex; | |
| 125 | - /* #endif */ | |
| 126 | - flex-flow: row wrap; | |
| 127 | - } | |
| 119 | + &--row { | |
| 120 | + /* #ifndef APP-NVUE */ | |
| 121 | + display: flex; | |
| 122 | + /* #endif */ | |
| 123 | + // flex-flow: row wrap; | |
| 124 | + } | |
| 128 | 125 | |
| 129 | - &--column { | |
| 130 | - @include flex(column); | |
| 131 | - } | |
| 126 | + &--column { | |
| 127 | + @include flex(column); | |
| 132 | 128 | } |
| 129 | +} | |
| 133 | 130 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-checkbox/u-checkbox.vue
| 1 | 1 | <template> |
| 2 | - <view | |
| 3 | - class="u-checkbox" | |
| 4 | - :style="[checkboxStyle]" | |
| 5 | - @tap.stop="wrapperClickHandler" | |
| 6 | - :class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']" | |
| 7 | - > | |
| 8 | - <view | |
| 9 | - class="u-checkbox__icon-wrap" | |
| 10 | - @tap.stop="iconClickHandler" | |
| 11 | - :class="iconClasses" | |
| 12 | - :style="[iconWrapStyle]" | |
| 13 | - > | |
| 2 | + <view class="u-checkbox" :style="[checkboxStyle]" @tap.stop="wrapperClickHandler" | |
| 3 | + :class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']"> | |
| 4 | + <view class="u-checkbox__icon-wrap" @tap.stop="iconClickHandler" :class="iconClasses" :style="[iconWrapStyle]"> | |
| 14 | 5 | <slot name="icon"> |
| 15 | - <u-icon | |
| 16 | - class="u-checkbox__icon-wrap__icon" | |
| 17 | - name="checkbox-mark" | |
| 18 | - :size="elIconSize" | |
| 19 | - :color="elIconColor" | |
| 20 | - /> | |
| 6 | + <u-icon class="u-checkbox__icon-wrap__icon" name="checkbox-mark" :size="elIconSize" :color="elIconColor" /> | |
| 21 | 7 | </slot> |
| 22 | 8 | </view> |
| 23 | - <text | |
| 24 | - @tap.stop="labelClickHandler" | |
| 25 | - :style="{ | |
| 26 | - color: elDisabled ? elInactiveColor : elLabelColor, | |
| 27 | - fontSize: elLabelSize, | |
| 28 | - lineHeight: elLabelSize | |
| 29 | - }" | |
| 30 | - >{{label}}</text> | |
| 9 | + <text @tap.stop="labelClickHandler" :style="{ | |
| 10 | + color: elDisabled ? elInactiveColor : elLabelColor, | |
| 11 | + fontSize: elLabelSize, | |
| 12 | + lineHeight: elLabelSize | |
| 13 | + }" style="flex-wrap: wrap;">{{ label }}</text> | |
| 31 | 14 | </view> |
| 32 | 15 | </template> |
| 33 | 16 | |
| 34 | 17 | <script> |
| 35 | - import props from './props.js'; | |
| 36 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 37 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 38 | - /** | |
| 39 | - * checkbox 复选框 | |
| 40 | - * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便 | |
| 41 | - * @tutorial https://uviewui.com/components/checkbox.html | |
| 42 | - * @property {String | Number | Boolean} name checkbox组件的标示符 | |
| 43 | - * @property {String} shape 形状,square为方形,circle为圆型 | |
| 44 | - * @property {String | Number} size 整体的大小 | |
| 45 | - * @property {Boolean} checked 是否默认选中 | |
| 46 | - * @property {String | Boolean} disabled 是否禁用 | |
| 47 | - * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 | |
| 48 | - * @property {String} inactiveColor 未选中的颜色 | |
| 49 | - * @property {String | Number} iconSize 图标的大小,单位px | |
| 50 | - * @property {String} iconColor 图标颜色 | |
| 51 | - * @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 | |
| 52 | - * @property {String} labelColor label的颜色 | |
| 53 | - * @property {String | Number} labelSize label的字体大小,px单位 | |
| 54 | - * @property {String | Boolean} labelDisabled 是否禁止点击提示语选中复选框 | |
| 55 | - * @property {Object} customStyle 定义需要用到的外部样式 | |
| 56 | - * | |
| 57 | - * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象 | |
| 58 | - * @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox> | |
| 59 | - */ | |
| 60 | - export default { | |
| 61 | - name: "u-checkbox", | |
| 62 | - mixins: [mpMixin, mixin, props], | |
| 63 | - data() { | |
| 64 | - return { | |
| 65 | - isChecked: false, | |
| 66 | - // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式 | |
| 67 | - // 故只能使用如此方法 | |
| 68 | - parentData: { | |
| 69 | - iconSize: 12, | |
| 70 | - labelDisabled: null, | |
| 71 | - disabled: null, | |
| 72 | - shape: 'square', | |
| 73 | - activeColor: null, | |
| 74 | - inactiveColor: null, | |
| 75 | - size: 18, | |
| 76 | - // #ifdef VUE2 | |
| 77 | - value: null, | |
| 78 | - // #endif | |
| 79 | - // #ifdef VUE3 | |
| 80 | - modelValue: null, | |
| 81 | - // #endif | |
| 82 | - iconColor: null, | |
| 83 | - placement: 'row', | |
| 84 | - borderBottom: false, | |
| 85 | - iconPlacement: 'left' | |
| 86 | - } | |
| 18 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 19 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 20 | +import props from './props.js'; | |
| 21 | +/** | |
| 22 | + * checkbox 复选框 | |
| 23 | + * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便 | |
| 24 | + * @tutorial https://uviewui.com/components/checkbox.html | |
| 25 | + * @property {String | Number | Boolean} name checkbox组件的标示符 | |
| 26 | + * @property {String} shape 形状,square为方形,circle为圆型 | |
| 27 | + * @property {String | Number} size 整体的大小 | |
| 28 | + * @property {Boolean} checked 是否默认选中 | |
| 29 | + * @property {String | Boolean} disabled 是否禁用 | |
| 30 | + * @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 | |
| 31 | + * @property {String} inactiveColor 未选中的颜色 | |
| 32 | + * @property {String | Number} iconSize 图标的大小,单位px | |
| 33 | + * @property {String} iconColor 图标颜色 | |
| 34 | + * @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式 | |
| 35 | + * @property {String} labelColor label的颜色 | |
| 36 | + * @property {String | Number} labelSize label的字体大小,px单位 | |
| 37 | + * @property {String | Boolean} labelDisabled 是否禁止点击提示语选中复选框 | |
| 38 | + * @property {Object} customStyle 定义需要用到的外部样式 | |
| 39 | + * | |
| 40 | + * @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象 | |
| 41 | + * @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox> | |
| 42 | + */ | |
| 43 | +export default { | |
| 44 | + name: "u-checkbox", | |
| 45 | + mixins: [mpMixin, mixin, props], | |
| 46 | + data() { | |
| 47 | + return { | |
| 48 | + isChecked: false, | |
| 49 | + // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式 | |
| 50 | + // 故只能使用如此方法 | |
| 51 | + parentData: { | |
| 52 | + iconSize: 12, | |
| 53 | + labelDisabled: null, | |
| 54 | + disabled: null, | |
| 55 | + shape: 'square', | |
| 56 | + activeColor: null, | |
| 57 | + inactiveColor: null, | |
| 58 | + size: 18, | |
| 59 | + // #ifdef VUE2 | |
| 60 | + value: null, | |
| 61 | + // #endif | |
| 62 | + // #ifdef VUE3 | |
| 63 | + modelValue: null, | |
| 64 | + // #endif | |
| 65 | + iconColor: null, | |
| 66 | + placement: 'row', | |
| 67 | + borderBottom: false, | |
| 68 | + iconPlacement: 'left' | |
| 69 | + } | |
| 70 | + } | |
| 71 | + }, | |
| 72 | + computed: { | |
| 73 | + // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置 | |
| 74 | + elDisabled() { | |
| 75 | + return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; | |
| 76 | + }, | |
| 77 | + // 是否禁用label点击 | |
| 78 | + elLabelDisabled() { | |
| 79 | + return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : | |
| 80 | + false; | |
| 81 | + }, | |
| 82 | + // 组件尺寸,对应size的值,默认值为21px | |
| 83 | + elSize() { | |
| 84 | + return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); | |
| 85 | + }, | |
| 86 | + // 组件的勾选图标的尺寸,默认12px | |
| 87 | + elIconSize() { | |
| 88 | + return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); | |
| 89 | + }, | |
| 90 | + // 组件选中激活时的颜色 | |
| 91 | + elActiveColor() { | |
| 92 | + return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 93 | + }, | |
| 94 | + // 组件选未中激活时的颜色 | |
| 95 | + elInactiveColor() { | |
| 96 | + return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : | |
| 97 | + '#c8c9cc'); | |
| 98 | + }, | |
| 99 | + // label的颜色 | |
| 100 | + elLabelColor() { | |
| 101 | + return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') | |
| 102 | + }, | |
| 103 | + // 组件的形状 | |
| 104 | + elShape() { | |
| 105 | + return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); | |
| 106 | + }, | |
| 107 | + // label大小 | |
| 108 | + elLabelSize() { | |
| 109 | + return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : | |
| 110 | + '15')) | |
| 111 | + }, | |
| 112 | + elIconColor() { | |
| 113 | + const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : | |
| 114 | + '#ffffff'); | |
| 115 | + // 图标的颜色 | |
| 116 | + if (this.elDisabled) { | |
| 117 | + // disabled状态下,已勾选的checkbox图标改为elInactiveColor | |
| 118 | + return this.isChecked ? this.elInactiveColor : 'transparent' | |
| 119 | + } else { | |
| 120 | + return this.isChecked ? iconColor : 'transparent' | |
| 87 | 121 | } |
| 88 | 122 | }, |
| 89 | - computed: { | |
| 90 | - // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置 | |
| 91 | - elDisabled() { | |
| 92 | - return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false; | |
| 93 | - }, | |
| 94 | - // 是否禁用label点击 | |
| 95 | - elLabelDisabled() { | |
| 96 | - return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled : | |
| 97 | - false; | |
| 98 | - }, | |
| 99 | - // 组件尺寸,对应size的值,默认值为21px | |
| 100 | - elSize() { | |
| 101 | - return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21); | |
| 102 | - }, | |
| 103 | - // 组件的勾选图标的尺寸,默认12px | |
| 104 | - elIconSize() { | |
| 105 | - return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12); | |
| 106 | - }, | |
| 107 | - // 组件选中激活时的颜色 | |
| 108 | - elActiveColor() { | |
| 109 | - return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff'); | |
| 110 | - }, | |
| 111 | - // 组件选未中激活时的颜色 | |
| 112 | - elInactiveColor() { | |
| 113 | - return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor : | |
| 114 | - '#c8c9cc'); | |
| 115 | - }, | |
| 116 | - // label的颜色 | |
| 117 | - elLabelColor() { | |
| 118 | - return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266') | |
| 119 | - }, | |
| 123 | + iconClasses() { | |
| 124 | + let classes = [] | |
| 120 | 125 | // 组件的形状 |
| 121 | - elShape() { | |
| 122 | - return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle'); | |
| 123 | - }, | |
| 124 | - // label大小 | |
| 125 | - elLabelSize() { | |
| 126 | - return uni.$u.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize : | |
| 127 | - '15')) | |
| 128 | - }, | |
| 129 | - elIconColor() { | |
| 130 | - const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor : | |
| 131 | - '#ffffff'); | |
| 132 | - // 图标的颜色 | |
| 133 | - if (this.elDisabled) { | |
| 134 | - // disabled状态下,已勾选的checkbox图标改为elInactiveColor | |
| 135 | - return this.isChecked ? this.elInactiveColor : 'transparent' | |
| 136 | - } else { | |
| 137 | - return this.isChecked ? iconColor : 'transparent' | |
| 138 | - } | |
| 139 | - }, | |
| 140 | - iconClasses() { | |
| 141 | - let classes = [] | |
| 142 | - // 组件的形状 | |
| 143 | - classes.push('u-checkbox__icon-wrap--' + this.elShape) | |
| 144 | - if (this.elDisabled) { | |
| 145 | - classes.push('u-checkbox__icon-wrap--disabled') | |
| 146 | - } | |
| 147 | - if (this.isChecked && this.elDisabled) { | |
| 148 | - classes.push('u-checkbox__icon-wrap--disabled--checked') | |
| 149 | - } | |
| 150 | - // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效 | |
| 151 | - // #ifdef MP-ALIPAY || MP-TOUTIAO | |
| 152 | - classes = classes.join(' ') | |
| 153 | - // #endif | |
| 154 | - return classes | |
| 155 | - }, | |
| 156 | - iconWrapStyle() { | |
| 157 | - // checkbox的整体样式 | |
| 158 | - const style = {} | |
| 159 | - style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff' | |
| 160 | - style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor | |
| 161 | - style.width = uni.$u.addUnit(this.elSize) | |
| 162 | - style.height = uni.$u.addUnit(this.elSize) | |
| 163 | - // 如果是图标在右边的话,移除它的右边距 | |
| 164 | - if (this.parentData.iconPlacement === 'right') { | |
| 165 | - style.marginRight = 0 | |
| 166 | - } | |
| 167 | - return style | |
| 168 | - }, | |
| 169 | - checkboxStyle() { | |
| 170 | - const style = {} | |
| 171 | - if (this.parentData.borderBottom && this.parentData.placement === 'row') { | |
| 172 | - uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-checkbox-group的placement设置为column才有效') | |
| 173 | - } | |
| 174 | - // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔 | |
| 175 | - if (this.parentData.borderBottom && this.parentData.placement === 'column') { | |
| 176 | - style.paddingBottom = '8px' | |
| 177 | - } | |
| 178 | - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 126 | + classes.push('u-checkbox__icon-wrap--' + this.elShape) | |
| 127 | + if (this.elDisabled) { | |
| 128 | + classes.push('u-checkbox__icon-wrap--disabled') | |
| 129 | + } | |
| 130 | + if (this.isChecked && this.elDisabled) { | |
| 131 | + classes.push('u-checkbox__icon-wrap--disabled--checked') | |
| 179 | 132 | } |
| 133 | + // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效 | |
| 134 | + // #ifdef MP-ALIPAY || MP-TOUTIAO | |
| 135 | + classes = classes.join(' ') | |
| 136 | + // #endif | |
| 137 | + return classes | |
| 180 | 138 | }, |
| 181 | - mounted() { | |
| 182 | - this.init() | |
| 139 | + iconWrapStyle() { | |
| 140 | + // checkbox的整体样式 | |
| 141 | + const style = {} | |
| 142 | + style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff' | |
| 143 | + style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor | |
| 144 | + style.width = uni.$u.addUnit(this.elSize) | |
| 145 | + style.height = uni.$u.addUnit(this.elSize) | |
| 146 | + // 如果是图标在右边的话,移除它的右边距 | |
| 147 | + if (this.parentData.iconPlacement === 'right') { | |
| 148 | + style.marginRight = 0 | |
| 149 | + } | |
| 150 | + return style | |
| 183 | 151 | }, |
| 184 | - methods: { | |
| 185 | - init() { | |
| 186 | - // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用 | |
| 187 | - this.updateParentData() | |
| 188 | - if (!this.parent) { | |
| 189 | - uni.$u.error('u-checkbox必须搭配u-checkbox-group组件使用') | |
| 190 | - } | |
| 191 | - // #ifdef VUE2 | |
| 192 | - const value = this.parentData.value | |
| 193 | - // #endif | |
| 194 | - // #ifdef VUE3 | |
| 195 | - const value = this.parentData.modelValue | |
| 196 | - // #endif | |
| 197 | - // 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断 | |
| 198 | - if (this.checked) { | |
| 199 | - this.isChecked = true | |
| 200 | - } else if (uni.$u.test.array(value)) { | |
| 201 | - // 查找数组是是否存在this.name元素值 | |
| 202 | - this.isChecked = value.some(item => { | |
| 203 | - return item === this.name | |
| 204 | - }) | |
| 205 | - } | |
| 206 | - }, | |
| 207 | - updateParentData() { | |
| 208 | - this.getParentData('u-checkbox-group') | |
| 209 | - }, | |
| 210 | - // 横向两端排列时,点击组件即可触发选中事件 | |
| 211 | - wrapperClickHandler(e) { | |
| 212 | - this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) | |
| 213 | - }, | |
| 214 | - // 点击图标 | |
| 215 | - iconClickHandler(e) { | |
| 216 | - this.preventEvent(e) | |
| 217 | - // 如果整体被禁用,不允许被点击 | |
| 218 | - if (!this.elDisabled) { | |
| 219 | - this.setRadioCheckedStatus() | |
| 220 | - } | |
| 221 | - }, | |
| 222 | - // 点击label | |
| 223 | - labelClickHandler(e) { | |
| 224 | - this.preventEvent(e) | |
| 225 | - // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态 | |
| 226 | - if (!this.elLabelDisabled && !this.elDisabled) { | |
| 227 | - this.setRadioCheckedStatus() | |
| 228 | - } | |
| 229 | - }, | |
| 230 | - emitEvent() { | |
| 231 | - this.$emit('change', this.isChecked) | |
| 232 | - // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时 | |
| 233 | - this.$nextTick(() => { | |
| 234 | - uni.$u.formValidate(this, 'change') | |
| 152 | + checkboxStyle() { | |
| 153 | + const style = {} | |
| 154 | + if (this.parentData.borderBottom && this.parentData.placement === 'row') { | |
| 155 | + uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-checkbox-group的placement设置为column才有效') | |
| 156 | + } | |
| 157 | + // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔 | |
| 158 | + if (this.parentData.borderBottom && this.parentData.placement === 'column') { | |
| 159 | + style.paddingBottom = '8px' | |
| 160 | + } | |
| 161 | + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 162 | + } | |
| 163 | + }, | |
| 164 | + mounted() { | |
| 165 | + this.init() | |
| 166 | + }, | |
| 167 | + methods: { | |
| 168 | + init() { | |
| 169 | + // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用 | |
| 170 | + this.updateParentData() | |
| 171 | + if (!this.parent) { | |
| 172 | + uni.$u.error('u-checkbox必须搭配u-checkbox-group组件使用') | |
| 173 | + } | |
| 174 | + // #ifdef VUE2 | |
| 175 | + const value = this.parentData.value | |
| 176 | + // #endif | |
| 177 | + // #ifdef VUE3 | |
| 178 | + const value = this.parentData.modelValue | |
| 179 | + // #endif | |
| 180 | + // 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断 | |
| 181 | + if (this.checked) { | |
| 182 | + this.isChecked = true | |
| 183 | + } else if (uni.$u.test.array(value)) { | |
| 184 | + // 查找数组是是否存在this.name元素值 | |
| 185 | + this.isChecked = value.some(item => { | |
| 186 | + return item === this.name | |
| 235 | 187 | }) |
| 236 | - }, | |
| 237 | - // 改变组件选中状态 | |
| 238 | - // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-checkbox实例 | |
| 239 | - // 将本组件外的其他u-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态 | |
| 240 | - setRadioCheckedStatus() { | |
| 241 | - // 将本组件标记为与原来相反的状态 | |
| 242 | - this.isChecked = !this.isChecked | |
| 243 | - this.emitEvent() | |
| 244 | - typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) | |
| 245 | 188 | } |
| 246 | 189 | }, |
| 247 | - watch:{ | |
| 248 | - checked(){ | |
| 249 | - this.isChecked = this.checked | |
| 190 | + updateParentData() { | |
| 191 | + this.getParentData('u-checkbox-group') | |
| 192 | + }, | |
| 193 | + // 横向两端排列时,点击组件即可触发选中事件 | |
| 194 | + wrapperClickHandler(e) { | |
| 195 | + this.parentData.iconPlacement === 'right' && this.iconClickHandler(e) | |
| 196 | + }, | |
| 197 | + // 点击图标 | |
| 198 | + iconClickHandler(e) { | |
| 199 | + this.preventEvent(e) | |
| 200 | + // 如果整体被禁用,不允许被点击 | |
| 201 | + if (!this.elDisabled) { | |
| 202 | + this.setRadioCheckedStatus() | |
| 203 | + } | |
| 204 | + }, | |
| 205 | + // 点击label | |
| 206 | + labelClickHandler(e) { | |
| 207 | + this.preventEvent(e) | |
| 208 | + // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态 | |
| 209 | + if (!this.elLabelDisabled && !this.elDisabled) { | |
| 210 | + this.setRadioCheckedStatus() | |
| 250 | 211 | } |
| 212 | + }, | |
| 213 | + emitEvent() { | |
| 214 | + this.$emit('change', this.isChecked) | |
| 215 | + // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时 | |
| 216 | + this.$nextTick(() => { | |
| 217 | + uni.$u.formValidate(this, 'change') | |
| 218 | + }) | |
| 219 | + }, | |
| 220 | + // 改变组件选中状态 | |
| 221 | + // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-checkbox实例 | |
| 222 | + // 将本组件外的其他u-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态 | |
| 223 | + setRadioCheckedStatus() { | |
| 224 | + // 将本组件标记为与原来相反的状态 | |
| 225 | + this.isChecked = !this.isChecked | |
| 226 | + this.emitEvent() | |
| 227 | + typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this) | |
| 228 | + } | |
| 229 | + }, | |
| 230 | + watch: { | |
| 231 | + checked() { | |
| 232 | + this.isChecked = this.checked | |
| 251 | 233 | } |
| 252 | 234 | } |
| 235 | +} | |
| 253 | 236 | </script> |
| 254 | 237 | |
| 255 | 238 | <style lang="scss" scoped> |
| 256 | - @import "../../libs/css/components.scss"; | |
| 257 | - $u-checkbox-icon-wrap-margin-right:6px !default; | |
| 258 | - $u-checkbox-icon-wrap-font-size:6px !default; | |
| 259 | - $u-checkbox-icon-wrap-border-width:1px !default; | |
| 260 | - $u-checkbox-icon-wrap-border-color:#c8c9cc !default; | |
| 261 | - $u-checkbox-icon-wrap-icon-line-height:0 !default; | |
| 262 | - $u-checkbox-icon-wrap-circle-border-radius:100% !default; | |
| 263 | - $u-checkbox-icon-wrap-square-border-radius:3px !default; | |
| 264 | - $u-checkbox-icon-wrap-checked-color:#fff !default; | |
| 265 | - $u-checkbox-icon-wrap-checked-background-color:red !default; | |
| 266 | - $u-checkbox-icon-wrap-checked-border-color:#2979ff !default; | |
| 267 | - $u-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default; | |
| 268 | - $u-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default; | |
| 269 | - $u-checkbox-label-margin-left:5px !default; | |
| 270 | - $u-checkbox-label-margin-right:12px !default; | |
| 271 | - $u-checkbox-label-color:$u-content-color !default; | |
| 272 | - $u-checkbox-label-font-size:15px !default; | |
| 273 | - $u-checkbox-label-disabled-color:#c8c9cc !default; | |
| 239 | +@import "../../libs/css/components.scss"; | |
| 240 | +$u-checkbox-icon-wrap-margin-right: 6px !default; | |
| 241 | +$u-checkbox-icon-wrap-font-size: 6px !default; | |
| 242 | +$u-checkbox-icon-wrap-border-width: 1px !default; | |
| 243 | +$u-checkbox-icon-wrap-border-color: #c8c9cc !default; | |
| 244 | +$u-checkbox-icon-wrap-icon-line-height: 0 !default; | |
| 245 | +$u-checkbox-icon-wrap-circle-border-radius: 100% !default; | |
| 246 | +$u-checkbox-icon-wrap-square-border-radius: 3px !default; | |
| 247 | +$u-checkbox-icon-wrap-checked-color: #fff !default; | |
| 248 | +$u-checkbox-icon-wrap-checked-background-color: red !default; | |
| 249 | +$u-checkbox-icon-wrap-checked-border-color: #2979ff !default; | |
| 250 | +$u-checkbox-icon-wrap-disabled-background-color: #ebedf0 !default; | |
| 251 | +$u-checkbox-icon-wrap-disabled-checked-color: #c8c9cc !default; | |
| 252 | +$u-checkbox-label-margin-left: 5px !default; | |
| 253 | +$u-checkbox-label-margin-right: 12px !default; | |
| 254 | +$u-checkbox-label-color: $u-content-color !default; | |
| 255 | +$u-checkbox-label-font-size: 15px !default; | |
| 256 | +$u-checkbox-label-disabled-color: #c8c9cc !default; | |
| 257 | + | |
| 258 | +.u-checkbox { | |
| 259 | + /* #ifndef APP-NVUE */ | |
| 260 | + @include flex(row); | |
| 261 | + /* #endif */ | |
| 262 | + // overflow: hidden; | |
| 263 | + flex-direction: row; | |
| 264 | + // align-items: center; | |
| 265 | + margin-bottom: 5px; | |
| 266 | + margin-top: 5px; | |
| 274 | 267 | |
| 275 | - .u-checkbox { | |
| 268 | + &-label--left { | |
| 269 | + flex-direction: row; | |
| 270 | + } | |
| 271 | + | |
| 272 | + &-label--right { | |
| 273 | + flex-direction: row-reverse; | |
| 274 | + justify-content: space-between; | |
| 275 | + } | |
| 276 | + | |
| 277 | + &__icon-wrap { | |
| 276 | 278 | /* #ifndef APP-NVUE */ |
| 277 | - @include flex(row); | |
| 279 | + box-sizing: border-box; | |
| 280 | + // nvue下,border-color过渡有问题 | |
| 281 | + transition-property: border-color, background-color, color; | |
| 282 | + transition-duration: 0.2s; | |
| 278 | 283 | /* #endif */ |
| 279 | - overflow: hidden; | |
| 280 | - flex-direction: row; | |
| 284 | + color: $u-content-color; | |
| 285 | + @include flex; | |
| 281 | 286 | align-items: center; |
| 282 | - margin-bottom: 5px; | |
| 283 | - margin-top: 5px; | |
| 287 | + justify-content: center; | |
| 288 | + color: transparent; | |
| 289 | + text-align: center; | |
| 290 | + margin-right: $u-checkbox-icon-wrap-margin-right; | |
| 284 | 291 | |
| 285 | - &-label--left { | |
| 286 | - flex-direction: row | |
| 287 | - } | |
| 292 | + font-size: $u-checkbox-icon-wrap-font-size; | |
| 293 | + border-width: $u-checkbox-icon-wrap-border-width; | |
| 294 | + border-color: $u-checkbox-icon-wrap-border-color; | |
| 295 | + border-style: solid; | |
| 288 | 296 | |
| 289 | - &-label--right { | |
| 290 | - flex-direction: row-reverse; | |
| 291 | - justify-content: space-between | |
| 297 | + /* #ifdef MP-TOUTIAO */ | |
| 298 | + // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下 | |
| 299 | + &__icon { | |
| 300 | + line-height: $u-checkbox-icon-wrap-icon-line-height; | |
| 292 | 301 | } |
| 293 | 302 | |
| 294 | - &__icon-wrap { | |
| 295 | - /* #ifndef APP-NVUE */ | |
| 296 | - box-sizing: border-box; | |
| 297 | - // nvue下,border-color过渡有问题 | |
| 298 | - transition-property: border-color, background-color, color; | |
| 299 | - transition-duration: 0.2s; | |
| 300 | - /* #endif */ | |
| 301 | - color: $u-content-color; | |
| 302 | - @include flex; | |
| 303 | - align-items: center; | |
| 304 | - justify-content: center; | |
| 305 | - color: transparent; | |
| 306 | - text-align: center; | |
| 307 | - margin-right: $u-checkbox-icon-wrap-margin-right; | |
| 308 | - | |
| 309 | - font-size: $u-checkbox-icon-wrap-font-size; | |
| 310 | - border-width: $u-checkbox-icon-wrap-border-width; | |
| 311 | - border-color: $u-checkbox-icon-wrap-border-color; | |
| 312 | - border-style: solid; | |
| 313 | - | |
| 314 | - /* #ifdef MP-TOUTIAO */ | |
| 315 | - // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下 | |
| 316 | - &__icon { | |
| 317 | - line-height: $u-checkbox-icon-wrap-icon-line-height; | |
| 318 | - } | |
| 319 | - | |
| 320 | - /* #endif */ | |
| 303 | + /* #endif */ | |
| 321 | 304 | |
| 322 | - &--circle { | |
| 323 | - border-radius: $u-checkbox-icon-wrap-circle-border-radius; | |
| 324 | - } | |
| 305 | + &--circle { | |
| 306 | + border-radius: $u-checkbox-icon-wrap-circle-border-radius; | |
| 307 | + } | |
| 325 | 308 | |
| 326 | - &--square { | |
| 327 | - border-radius: $u-checkbox-icon-wrap-square-border-radius; | |
| 328 | - } | |
| 309 | + &--square { | |
| 310 | + border-radius: $u-checkbox-icon-wrap-square-border-radius; | |
| 311 | + } | |
| 329 | 312 | |
| 330 | - &--checked { | |
| 331 | - color: $u-checkbox-icon-wrap-checked-color; | |
| 332 | - background-color: $u-checkbox-icon-wrap-checked-background-color; | |
| 333 | - border-color: $u-checkbox-icon-wrap-checked-border-color; | |
| 334 | - } | |
| 313 | + &--checked { | |
| 314 | + color: $u-checkbox-icon-wrap-checked-color; | |
| 315 | + background-color: $u-checkbox-icon-wrap-checked-background-color; | |
| 316 | + border-color: $u-checkbox-icon-wrap-checked-border-color; | |
| 317 | + } | |
| 335 | 318 | |
| 336 | - &--disabled { | |
| 337 | - background-color: $u-checkbox-icon-wrap-disabled-background-color !important; | |
| 338 | - } | |
| 319 | + &--disabled { | |
| 320 | + background-color: $u-checkbox-icon-wrap-disabled-background-color !important; | |
| 321 | + } | |
| 339 | 322 | |
| 340 | - &--disabled--checked { | |
| 341 | - color: $u-checkbox-icon-wrap-disabled-checked-color !important; | |
| 342 | - } | |
| 323 | + &--disabled--checked { | |
| 324 | + color: $u-checkbox-icon-wrap-disabled-checked-color !important; | |
| 343 | 325 | } |
| 326 | + } | |
| 344 | 327 | |
| 345 | - &__label { | |
| 346 | - /* #ifndef APP-NVUE */ | |
| 347 | - word-wrap: break-word; | |
| 348 | - /* #endif */ | |
| 349 | - margin-left: $u-checkbox-label-margin-left; | |
| 350 | - margin-right: $u-checkbox-label-margin-right; | |
| 351 | - color: $u-checkbox-label-color; | |
| 352 | - font-size: $u-checkbox-label-font-size; | |
| 328 | + &__label { | |
| 329 | + /* #ifndef APP-NVUE */ | |
| 330 | + word-wrap: break-word; | |
| 331 | + /* #endif */ | |
| 332 | + margin-left: $u-checkbox-label-margin-left; | |
| 333 | + margin-right: $u-checkbox-label-margin-right; | |
| 334 | + color: $u-checkbox-label-color; | |
| 335 | + font-size: $u-checkbox-label-font-size; | |
| 353 | 336 | |
| 354 | - &--disabled { | |
| 355 | - color: $u-checkbox-label-disabled-color; | |
| 356 | - } | |
| 337 | + &--disabled { | |
| 338 | + color: $u-checkbox-label-disabled-color; | |
| 357 | 339 | } |
| 358 | 340 | } |
| 341 | +} | |
| 359 | 342 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-collapse-item/u-collapse-item.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-collapse-item"> |
| 3 | - <u-cell | |
| 4 | - :title="title" | |
| 5 | - :value="value" | |
| 6 | - :label="label" | |
| 7 | - :icon="icon" | |
| 8 | - :isLink="isLink" | |
| 9 | - :clickable="clickable" | |
| 10 | - :border="parentData.border && showBorder" | |
| 11 | - @click="clickHandler" | |
| 12 | - :arrowDirection="expanded ? 'up' : 'down'" | |
| 13 | - :disabled="disabled" | |
| 14 | - > | |
| 3 | + <u-cell :title="title" :value="value" :label="label" :icon="icon" :isLink="isLink" :clickable="clickable" | |
| 4 | + :border="parentData.border && showBorder" @click="clickHandler" :arrowDirection="expanded ? 'up' : 'down'" | |
| 5 | + :disabled="disabled"> | |
| 15 | 6 | <!-- #ifndef MP-WEIXIN --> |
| 16 | 7 | <!-- 微信小程序不支持,因为微信中不支持 <slot name="title" slot="title" />的写法 --> |
| 17 | 8 | <template #title> |
| ... | ... | @@ -28,200 +19,189 @@ |
| 28 | 19 | </template> |
| 29 | 20 | <!-- #endif --> |
| 30 | 21 | </u-cell> |
| 31 | - <view | |
| 32 | - class="u-collapse-item__content" | |
| 33 | - :animation="animationData" | |
| 34 | - ref="animation" | |
| 35 | - > | |
| 36 | - <view | |
| 37 | - class="u-collapse-item__content__text content-class" | |
| 38 | - :id="elId" | |
| 39 | - :ref="elId" | |
| 40 | - ><slot /></view> | |
| 22 | + <view class="u-collapse-item__content" :animation="animationData" ref="animation"> | |
| 23 | + <view class="u-collapse-item__content__text content-class" :id="elId" :ref="elId"> | |
| 24 | + <slot /> | |
| 25 | + </view> | |
| 41 | 26 | </view> |
| 42 | 27 | <u-line v-if="parentData.border"></u-line> |
| 43 | 28 | </view> |
| 44 | 29 | </template> |
| 45 | 30 | |
| 46 | 31 | <script> |
| 47 | - import props from './props.js'; | |
| 48 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 49 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 50 | - import { nextTick } from 'vue' | |
| 51 | - // #ifdef APP-NVUE | |
| 52 | - const animation = uni.requireNativePlugin('animation') | |
| 53 | - const dom = uni.requireNativePlugin('dom') | |
| 54 | - // #endif | |
| 55 | - /** | |
| 56 | - * collapseItem 折叠面板Item | |
| 57 | - * @description 通过折叠面板收纳内容区域(搭配u-collapse使用) | |
| 58 | - * @tutorial https://ijry.github.io/uview-plus/components/collapse.html | |
| 59 | - * @property {String} title 标题 | |
| 60 | - * @property {String} value 标题右侧内容 | |
| 61 | - * @property {String} label 标题下方的描述信息 | |
| 62 | - * @property {Boolean} disbled 是否禁用折叠面板 ( 默认 false ) | |
| 63 | - * @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 ( 默认 true ) | |
| 64 | - * @property {Boolean} clickable 是否开启点击反馈 ( 默认 true ) | |
| 65 | - * @property {Boolean} border 是否显示内边框 ( 默认 true ) | |
| 66 | - * @property {String} align 标题的对齐方式 ( 默认 'left' ) | |
| 67 | - * @property {String | Number} name 唯一标识符 | |
| 68 | - * @property {String} icon 标题左侧图片,可为绝对路径的图片或内置图标 | |
| 69 | - * @event {Function} change 某个item被打开或者收起时触发 | |
| 70 | - * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item> | |
| 71 | - */ | |
| 72 | - export default { | |
| 73 | - name: "u-collapse-item", | |
| 74 | - mixins: [mpMixin, mixin, props], | |
| 75 | - data() { | |
| 76 | - return { | |
| 77 | - elId: uni.$u.guid(), | |
| 78 | - // uni.createAnimation的导出数据 | |
| 79 | - animationData: {}, | |
| 80 | - // 是否展开状态 | |
| 81 | - expanded: false, | |
| 82 | - // 根据expanded确定是否显示border,为了控制展开时,cell的下划线更好的显示效果,进行一定时间的延时 | |
| 83 | - showBorder: false, | |
| 84 | - // 是否动画中,如果是则不允许继续触发点击 | |
| 85 | - animating: false, | |
| 86 | - // 父组件u-collapse的参数 | |
| 87 | - parentData: { | |
| 88 | - accordion: false, | |
| 89 | - border: false | |
| 32 | +import { nextTick } from 'vue'; | |
| 33 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 34 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 35 | +import props from './props.js'; | |
| 36 | +// #ifdef APP-NVUE | |
| 37 | +const animation = uni.requireNativePlugin('animation') | |
| 38 | +const dom = uni.requireNativePlugin('dom') | |
| 39 | +// #endif | |
| 40 | +/** | |
| 41 | + * collapseItem 折叠面板Item | |
| 42 | + * @description 通过折叠面板收纳内容区域(搭配u-collapse使用) | |
| 43 | + * @tutorial https://ijry.github.io/uview-plus/components/collapse.html | |
| 44 | + * @property {String} title 标题 | |
| 45 | + * @property {String} value 标题右侧内容 | |
| 46 | + * @property {String} label 标题下方的描述信息 | |
| 47 | + * @property {Boolean} disbled 是否禁用折叠面板 ( 默认 false ) | |
| 48 | + * @property {Boolean} isLink 是否展示右侧箭头并开启点击反馈 ( 默认 true ) | |
| 49 | + * @property {Boolean} clickable 是否开启点击反馈 ( 默认 true ) | |
| 50 | + * @property {Boolean} border 是否显示内边框 ( 默认 true ) | |
| 51 | + * @property {String} align 标题的对齐方式 ( 默认 'left' ) | |
| 52 | + * @property {String | Number} name 唯一标识符 | |
| 53 | + * @property {String} icon 标题左侧图片,可为绝对路径的图片或内置图标 | |
| 54 | + * @event {Function} change 某个item被打开或者收起时触发 | |
| 55 | + * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item> | |
| 56 | + */ | |
| 57 | +export default { | |
| 58 | + name: "u-collapse-item", | |
| 59 | + mixins: [mpMixin, mixin, props], | |
| 60 | + data() { | |
| 61 | + return { | |
| 62 | + elId: uni.$u.guid(), | |
| 63 | + // uni.createAnimation的导出数据 | |
| 64 | + animationData: {}, | |
| 65 | + // 是否展开状态 | |
| 66 | + expanded: false, | |
| 67 | + // 根据expanded确定是否显示border,为了控制展开时,cell的下划线更好的显示效果,进行一定时间的延时 | |
| 68 | + showBorder: false, | |
| 69 | + // 是否动画中,如果是则不允许继续触发点击 | |
| 70 | + animating: false, | |
| 71 | + // 父组件u-collapse的参数 | |
| 72 | + parentData: { | |
| 73 | + accordion: false, | |
| 74 | + border: false | |
| 75 | + } | |
| 76 | + }; | |
| 77 | + }, | |
| 78 | + watch: { | |
| 79 | + expanded(n) { | |
| 80 | + clearTimeout(this.timer) | |
| 81 | + this.timer = null | |
| 82 | + // 这里根据expanded的值来进行一定的延时,是为了cell的下划线更好的显示效果 | |
| 83 | + this.timer = setTimeout(() => { | |
| 84 | + this.showBorder = n | |
| 85 | + }, n ? 10 : 290) | |
| 86 | + } | |
| 87 | + }, | |
| 88 | + mounted() { | |
| 89 | + this.init() | |
| 90 | + }, | |
| 91 | + methods: { | |
| 92 | + // 异步获取内容,或者动态修改了内容时,需要重新初始化 | |
| 93 | + async init() { | |
| 94 | + // 初始化数据 | |
| 95 | + this.updateParentData() | |
| 96 | + if (!this.parent) { | |
| 97 | + return uni.$u.error('u-collapse-item必须要搭配u-collapse组件使用') | |
| 98 | + } | |
| 99 | + const { | |
| 100 | + value, | |
| 101 | + accordion, | |
| 102 | + children = [] | |
| 103 | + } = this.parent | |
| 104 | + | |
| 105 | + if (accordion) { | |
| 106 | + if (uni.$u.test.array(value)) { | |
| 107 | + return uni.$u.error('手风琴模式下,u-collapse组件的value参数不能为数组') | |
| 90 | 108 | } |
| 91 | - }; | |
| 92 | - }, | |
| 93 | - watch: { | |
| 94 | - expanded(n) { | |
| 95 | - clearTimeout(this.timer) | |
| 96 | - this.timer = null | |
| 97 | - // 这里根据expanded的值来进行一定的延时,是为了cell的下划线更好的显示效果 | |
| 98 | - this.timer = setTimeout(() => { | |
| 99 | - this.showBorder = n | |
| 100 | - }, n ? 10 : 290) | |
| 109 | + this.expanded = this.name == value | |
| 110 | + } else { | |
| 111 | + if (!uni.$u.test.array(value) && value !== null) { | |
| 112 | + return uni.$u.error('非手风琴模式下,u-collapse组件的value参数必须为数组') | |
| 113 | + } | |
| 114 | + this.expanded = (value || []).some(item => item == this.name) | |
| 101 | 115 | } |
| 116 | + // 设置组件的展开或收起状态 | |
| 117 | + await nextTick() | |
| 118 | + this.setContentAnimate() | |
| 102 | 119 | }, |
| 103 | - mounted() { | |
| 104 | - this.init() | |
| 120 | + updateParentData() { | |
| 121 | + // 此方法在mixin中 | |
| 122 | + this.getParentData('u-collapse') | |
| 105 | 123 | }, |
| 106 | - methods: { | |
| 107 | - // 异步获取内容,或者动态修改了内容时,需要重新初始化 | |
| 108 | - async init() { | |
| 109 | - // 初始化数据 | |
| 110 | - this.updateParentData() | |
| 111 | - if (!this.parent) { | |
| 112 | - return uni.$u.error('u-collapse-item必须要搭配u-collapse组件使用') | |
| 113 | - } | |
| 114 | - const { | |
| 115 | - value, | |
| 116 | - accordion, | |
| 117 | - children = [] | |
| 118 | - } = this.parent | |
| 124 | + async setContentAnimate() { | |
| 125 | + // 每次面板打开或者收起时,都查询元素尺寸 | |
| 126 | + // 好处是,父组件从服务端获取内容后,变更折叠面板后可以获得最新的高度 | |
| 127 | + const rect = await this.queryRect() | |
| 128 | + const height = this.expanded ? rect.height : 0 | |
| 129 | + this.animating = true | |
| 130 | + // #ifdef APP-NVUE | |
| 131 | + const ref = this.$refs['animation'].ref | |
| 132 | + animation.transition(ref, { | |
| 133 | + styles: { | |
| 134 | + height: height + 'px' | |
| 135 | + }, | |
| 136 | + duration: this.duration, | |
| 137 | + // 必须设置为true,否则会到面板收起或展开时,页面其他元素不会随之调整它们的布局 | |
| 138 | + needLayout: true, | |
| 139 | + timingFunction: 'ease-in-out', | |
| 140 | + }, () => { | |
| 141 | + this.animating = false | |
| 142 | + }) | |
| 143 | + // #endif | |
| 119 | 144 | |
| 120 | - if (accordion) { | |
| 121 | - if (uni.$u.test.array(value)) { | |
| 122 | - return uni.$u.error('手风琴模式下,u-collapse组件的value参数不能为数组') | |
| 123 | - } | |
| 124 | - this.expanded = this.name == value | |
| 125 | - } else { | |
| 126 | - if (!uni.$u.test.array(value) && value !== null) { | |
| 127 | - return uni.$u.error('非手风琴模式下,u-collapse组件的value参数必须为数组') | |
| 128 | - } | |
| 129 | - this.expanded = (value || []).some(item => item == this.name) | |
| 130 | - } | |
| 131 | - // 设置组件的展开或收起状态 | |
| 132 | - await nextTick() | |
| 133 | - this.setContentAnimate() | |
| 134 | - }, | |
| 135 | - updateParentData() { | |
| 136 | - // 此方法在mixin中 | |
| 137 | - this.getParentData('u-collapse') | |
| 138 | - }, | |
| 139 | - async setContentAnimate() { | |
| 140 | - // 每次面板打开或者收起时,都查询元素尺寸 | |
| 141 | - // 好处是,父组件从服务端获取内容后,变更折叠面板后可以获得最新的高度 | |
| 142 | - const rect = await this.queryRect() | |
| 143 | - const height = this.expanded ? rect.height : 0 | |
| 144 | - this.animating = true | |
| 145 | - // #ifdef APP-NVUE | |
| 146 | - const ref = this.$refs['animation'].ref | |
| 147 | - animation.transition(ref, { | |
| 148 | - styles: { | |
| 149 | - height: height + 'px' | |
| 150 | - }, | |
| 145 | + // #ifndef APP-NVUE | |
| 146 | + const animation = uni.createAnimation({ | |
| 147 | + timingFunction: 'ease-in-out', | |
| 148 | + }); | |
| 149 | + animation | |
| 150 | + .height(height) | |
| 151 | + .step({ | |
| 151 | 152 | duration: this.duration, |
| 152 | - // 必须设置为true,否则会到面板收起或展开时,页面其他元素不会随之调整它们的布局 | |
| 153 | - needLayout: true, | |
| 154 | - timingFunction: 'ease-in-out', | |
| 155 | - }, () => { | |
| 156 | - this.animating = false | |
| 157 | 153 | }) |
| 158 | - // #endif | |
| 159 | - | |
| 160 | - // #ifndef APP-NVUE | |
| 161 | - const animation = uni.createAnimation({ | |
| 162 | - timingFunction: 'ease-in-out', | |
| 163 | - }); | |
| 164 | - animation | |
| 165 | - .height(height) | |
| 166 | - .step({ | |
| 167 | - duration: this.duration, | |
| 168 | - }) | |
| 169 | - .step() | |
| 170 | - // 导出动画数据给面板的animationData值 | |
| 171 | - this.animationData = animation.export() | |
| 172 | - // 标识动画结束 | |
| 173 | - uni.$u.sleep(this.duration).then(() => { | |
| 174 | - this.animating = false | |
| 175 | - }) | |
| 176 | - // #endif | |
| 177 | - }, | |
| 178 | - // 点击collapsehead头部 | |
| 179 | - clickHandler() { | |
| 180 | - if (this.disabled && this.animating) return | |
| 181 | - // 设置本组件为相反的状态 | |
| 182 | - this.parent && this.parent.onChange(this) | |
| 183 | - }, | |
| 184 | - // 查询内容高度 | |
| 185 | - queryRect() { | |
| 186 | - // #ifndef APP-NVUE | |
| 187 | - // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://ijry.github.io/uview-plus/js/getRect.html | |
| 188 | - // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同 | |
| 189 | - return new Promise(resolve => { | |
| 190 | - this.$uGetRect(`#${this.elId}`).then(size => { | |
| 191 | - resolve(size) | |
| 192 | - }) | |
| 193 | - }) | |
| 194 | - // #endif | |
| 195 | - | |
| 196 | - // #ifdef APP-NVUE | |
| 197 | - // nvue下,使用dom模块查询元素高度 | |
| 198 | - // 返回一个promise,让调用此方法的主体能使用then回调 | |
| 199 | - return new Promise(resolve => { | |
| 200 | - dom.getComponentRect(this.$refs[this.elId], res => { | |
| 201 | - resolve(res.size) | |
| 202 | - }) | |
| 203 | - }) | |
| 204 | - // #endif | |
| 154 | + .step() | |
| 155 | + // 导出动画数据给面板的animationData值 | |
| 156 | + this.animationData = animation.export() | |
| 157 | + // 标识动画结束 | |
| 158 | + uni.$u.sleep(this.duration).then(() => { | |
| 159 | + this.animating = false | |
| 160 | + }) | |
| 161 | + // #endif | |
| 162 | + }, | |
| 163 | + // 点击collapsehead头部 | |
| 164 | + clickHandler(scheduling) { | |
| 165 | + if (this.disabled && this.animating) return | |
| 166 | + // 设置本组件为相反的状态 | |
| 167 | + this.parent && this.parent.onChange(this) | |
| 168 | + if (scheduling == "抽屉") { | |
| 169 | + // this.$emit('selectHandler', this.index, this.name) | |
| 170 | + } else { | |
| 171 | + this.$emit('selectHandler', 4, "其他") | |
| 205 | 172 | } |
| 206 | 173 | }, |
| 207 | - }; | |
| 174 | + // 查询内容高度 | |
| 175 | + queryRect() { | |
| 176 | + // #ifndef APP-NVUE | |
| 177 | + // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://ijry.github.io/uview-plus/js/getRect.html | |
| 178 | + // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同 | |
| 179 | + return new Promise(resolve => { | |
| 180 | + this.$uGetRect(`#${this.elId}`).then(size => { | |
| 181 | + resolve(size) | |
| 182 | + }) | |
| 183 | + }) | |
| 184 | + // #endif | |
| 185 | + } | |
| 186 | + }, | |
| 187 | +}; | |
| 208 | 188 | </script> |
| 209 | 189 | |
| 210 | 190 | <style lang="scss" scoped> |
| 211 | - @import "../../libs/css/components.scss"; | |
| 191 | +@import "../../libs/css/components.scss"; | |
| 212 | 192 | |
| 213 | - .u-collapse-item { | |
| 193 | +.u-collapse-item { | |
| 214 | 194 | |
| 215 | - &__content { | |
| 216 | - overflow: hidden; | |
| 217 | - height: 0; | |
| 195 | + &__content { | |
| 196 | + overflow: hidden; | |
| 197 | + height: 0; | |
| 218 | 198 | |
| 219 | - &__text { | |
| 220 | - padding: 12px 15px; | |
| 221 | - color: $u-content-color; | |
| 222 | - font-size: 14px; | |
| 223 | - line-height: 18px; | |
| 224 | - } | |
| 199 | + &__text { | |
| 200 | + padding: 12px 15px; | |
| 201 | + color: $u-content-color; | |
| 202 | + font-size: 14px; | |
| 203 | + line-height: 18px; | |
| 225 | 204 | } |
| 226 | 205 | } |
| 206 | +} | |
| 227 | 207 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-collapse/props.js
garbage-removal/src/uview-plus/components/u-collapse/u-collapse.vue
| ... | ... | @@ -6,85 +6,86 @@ |
| 6 | 6 | </template> |
| 7 | 7 | |
| 8 | 8 | <script> |
| 9 | - import props from './props.js'; | |
| 10 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 11 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 12 | - /** | |
| 13 | - * collapse 折叠面板 | |
| 14 | - * @description 通过折叠面板收纳内容区域 | |
| 15 | - * @tutorial https://ijry.github.io/uview-plus/components/collapse.html | |
| 16 | - * @property {String | Number | Array} value 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number | |
| 17 | - * @property {Boolean} accordion 是否手风琴模式( 默认 false ) | |
| 18 | - * @property {Boolean} border 是否显示外边框 ( 默认 true ) | |
| 19 | - * @event {Function} change 当前激活面板展开时触发(如果是手风琴模式,参数activeNames类型为String,否则为Array) | |
| 20 | - * @example <u-collapse></u-collapse> | |
| 21 | - */ | |
| 22 | - export default { | |
| 23 | - name: "u-collapse", | |
| 24 | - mixins: [mpMixin, mixin,props], | |
| 25 | - watch: { | |
| 26 | - needInit() { | |
| 27 | - this.init() | |
| 28 | - }, | |
| 29 | - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 30 | - parentData() { | |
| 31 | - if (this.children.length) { | |
| 32 | - this.children.map(child => { | |
| 33 | - // 判断子组件(u-checkbox)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 34 | - typeof(child.updateParentData) === 'function' && child.updateParentData() | |
| 35 | - }) | |
| 36 | - } | |
| 37 | - } | |
| 38 | - }, | |
| 39 | - created() { | |
| 40 | - this.children = [] | |
| 9 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 10 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 11 | +import props from './props.js'; | |
| 12 | +/** | |
| 13 | + * collapse 折叠面板 | |
| 14 | + * @description 通过折叠面板收纳内容区域 | |
| 15 | + * @tutorial https://ijry.github.io/uview-plus/components/collapse.html | |
| 16 | + * @property {String | Number | Array} value 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number | |
| 17 | + * @property {Boolean} accordion 是否手风琴模式( 默认 false ) | |
| 18 | + * @property {Boolean} border 是否显示外边框 ( 默认 true ) | |
| 19 | + * @event {Function} change 当前激活面板展开时触发(如果是手风琴模式,参数activeNames类型为String,否则为Array) | |
| 20 | + * @example <u-collapse></u-collapse> | |
| 21 | + */ | |
| 22 | +export default { | |
| 23 | + name: "u-collapse", | |
| 24 | + mixins: [mpMixin, mixin, props], | |
| 25 | + watch: { | |
| 26 | + needInit() { | |
| 27 | + this.init() | |
| 41 | 28 | }, |
| 42 | - computed: { | |
| 43 | - needInit() { | |
| 44 | - // 通过computed,同时监听accordion和value值的变化 | |
| 45 | - // 再通过watch去执行init()方法,进行再一次的初始化 | |
| 46 | - return [this.accordion, this.value] | |
| 47 | - } | |
| 48 | - }, | |
| 49 | - methods: { | |
| 50 | - // 重新初始化一次内部的所有子元素 | |
| 51 | - init() { | |
| 29 | + // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件 | |
| 30 | + parentData() { | |
| 31 | + if (this.children.length) { | |
| 52 | 32 | this.children.map(child => { |
| 53 | - child.init() | |
| 33 | + // 判断子组件(u-checkbox)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值) | |
| 34 | + typeof (child.updateParentData) === 'function' && child.updateParentData() | |
| 54 | 35 | }) |
| 55 | - }, | |
| 56 | - /** | |
| 57 | - * collapse-item被点击时触发,由collapse统一处理各子组件的状态 | |
| 58 | - * @param {Object} target 被操作的面板的实例 | |
| 59 | - */ | |
| 60 | - onChange(target) { | |
| 61 | - let changeArr = [] | |
| 62 | - this.children.map((child, index) => { | |
| 63 | - // 如果是手风琴模式,将其他的折叠面板收起来 | |
| 64 | - if (this.accordion) { | |
| 65 | - child.expanded = child === target ? !target.expanded : false | |
| 36 | + } | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + created() { | |
| 40 | + this.children = [] | |
| 41 | + }, | |
| 42 | + computed: { | |
| 43 | + needInit() { | |
| 44 | + // 通过computed,同时监听accordion和value值的变化 | |
| 45 | + // 再通过watch去执行init()方法,进行再一次的初始化 | |
| 46 | + return [this.accordion, this.value] | |
| 47 | + } | |
| 48 | + }, | |
| 49 | + methods: { | |
| 50 | + | |
| 51 | + // 重新初始化一次内部的所有子元素 | |
| 52 | + init() { | |
| 53 | + this.children.map(child => { | |
| 54 | + child.init() | |
| 55 | + }) | |
| 56 | + }, | |
| 57 | + /** | |
| 58 | + * collapse-item被点击时触发,由collapse统一处理各子组件的状态 | |
| 59 | + * @param {Object} target 被操作的面板的实例 | |
| 60 | + */ | |
| 61 | + onChange(target) { | |
| 62 | + let changeArr = [] | |
| 63 | + this.children.map((child, index) => { | |
| 64 | + // 如果是手风琴模式,将其他的折叠面板收起来 | |
| 65 | + if (this.accordion) { | |
| 66 | + child.expanded = child === target ? !target.expanded : false | |
| 67 | + child.setContentAnimate() | |
| 68 | + } else { | |
| 69 | + if (child === target) { | |
| 70 | + child.expanded = !child.expanded | |
| 66 | 71 | child.setContentAnimate() |
| 67 | - } else { | |
| 68 | - if(child === target) { | |
| 69 | - child.expanded = !child.expanded | |
| 70 | - child.setContentAnimate() | |
| 71 | - } | |
| 72 | 72 | } |
| 73 | - // 拼接change事件中,数组元素的状态 | |
| 74 | - changeArr.push({ | |
| 75 | - // 如果没有定义name属性,则默认返回组件的index索引 | |
| 76 | - name: child.name || index, | |
| 77 | - status: child.expanded ? 'open' : 'close' | |
| 78 | - }) | |
| 73 | + } | |
| 74 | + // 拼接change事件中,数组元素的状态 | |
| 75 | + changeArr.push({ | |
| 76 | + // 如果没有定义name属性,则默认返回组件的index索引 | |
| 77 | + name: child.name || index, | |
| 78 | + status: child.expanded ? 'open' : 'close' | |
| 79 | 79 | }) |
| 80 | + }) | |
| 80 | 81 | |
| 81 | - this.$emit('change', changeArr) | |
| 82 | - this.$emit(target.expanded ? 'open' : 'close', target.name) | |
| 83 | - } | |
| 82 | + this.$emit('change', changeArr) | |
| 83 | + this.$emit(target.expanded ? 'open' : 'close', target.name) | |
| 84 | 84 | } |
| 85 | 85 | } |
| 86 | +} | |
| 86 | 87 | </script> |
| 87 | 88 | |
| 88 | 89 | <style lang="scss" scoped> |
| 89 | - @import "../../libs/css/components.scss"; | |
| 90 | +@import "../../libs/css/components.scss"; | |
| 90 | 91 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-popup/u-popup.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-popup"> |
| 3 | - <u-overlay | |
| 4 | - :show="show" | |
| 5 | - @click="overlayClick" | |
| 6 | - v-if="overlay" | |
| 7 | - :duration="overlayDuration" | |
| 8 | - :customStyle="overlayStyle" | |
| 9 | - :opacity="overlayOpacity" | |
| 10 | - ></u-overlay> | |
| 11 | - <u-transition | |
| 12 | - :show="show" | |
| 13 | - :customStyle="transitionStyle" | |
| 14 | - :mode="position" | |
| 15 | - :duration="duration" | |
| 16 | - @afterEnter="afterEnter" | |
| 17 | - @click="clickHandler" | |
| 18 | - > | |
| 19 | - <view | |
| 20 | - class="u-popup__content" | |
| 21 | - :style="[contentStyle]" | |
| 22 | - @tap.stop="noop" | |
| 23 | - > | |
| 3 | + <u-overlay :show="show" @click="overlayClick" v-if="overlay" :duration="overlayDuration" :customStyle="overlayStyle" | |
| 4 | + :opacity="overlayOpacity"></u-overlay> | |
| 5 | + <u-transition :show="show" :customStyle="transitionStyle" :mode="position" :duration="duration" | |
| 6 | + @afterEnter="afterEnter" @click="clickHandler"> | |
| 7 | + <view class="u-popup__content" :style="[contentStyle]" @tap.stop="noop"> | |
| 24 | 8 | <u-status-bar v-if="safeAreaInsetTop"></u-status-bar> |
| 25 | 9 | <slot></slot> |
| 26 | - <view | |
| 27 | - v-if="closeable" | |
| 28 | - @tap.stop="close" | |
| 29 | - class="u-popup__content__close" | |
| 30 | - :class="['u-popup__content__close--' + closeIconPos]" | |
| 31 | - hover-class="u-popup__content__close--hover" | |
| 32 | - hover-stay-time="150" | |
| 33 | - > | |
| 34 | - <u-icon | |
| 35 | - name="close" | |
| 36 | - color="#909399" | |
| 37 | - size="18" | |
| 38 | - bold | |
| 39 | - ></u-icon> | |
| 10 | + <view v-if="closeable" @tap.stop="close" class="u-popup__content__close" | |
| 11 | + :class="['u-popup__content__close--' + closeIconPos]" hover-class="u-popup__content__close--hover" | |
| 12 | + hover-stay-time="150"> | |
| 13 | + <u-icon name="close" color="#909399" size="18" bold></u-icon> | |
| 40 | 14 | </view> |
| 41 | 15 | <u-safe-bottom v-if="safeAreaInsetBottom"></u-safe-bottom> |
| 42 | 16 | </view> |
| ... | ... | @@ -45,262 +19,262 @@ |
| 45 | 19 | </template> |
| 46 | 20 | |
| 47 | 21 | <script> |
| 48 | - import props from './props.js'; | |
| 49 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 50 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 22 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 23 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 24 | +import props from './props.js'; | |
| 51 | 25 | |
| 52 | - /** | |
| 53 | - * popup 弹窗 | |
| 54 | - * @description 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义 | |
| 55 | - * @tutorial https://ijry.github.io/uview-plus/components/popup.html | |
| 56 | - * @property {Boolean} show 是否展示弹窗 (默认 false ) | |
| 57 | - * @property {Boolean} overlay 是否显示遮罩 (默认 true ) | |
| 58 | - * @property {String} mode 弹出方向(默认 'bottom' ) | |
| 59 | - * @property {String | Number} duration 动画时长,单位ms (默认 300 ) | |
| 60 | - * @property {String | Number} overlayDuration 遮罩层动画时长,单位ms (默认 350 ) | |
| 61 | - * @property {Boolean} closeable 是否显示关闭图标(默认 false ) | |
| 62 | - * @property {Object | String} overlayStyle 自定义遮罩的样式 | |
| 63 | - * @property {String | Number} overlayOpacity 遮罩透明度,0-1之间(默认 0.5) | |
| 64 | - * @property {Boolean} closeOnClickOverlay 点击遮罩是否关闭弹窗 (默认 true ) | |
| 65 | - * @property {String | Number} zIndex 层级 (默认 10075 ) | |
| 66 | - * @property {Boolean} safeAreaInsetBottom 是否为iPhoneX留出底部安全距离 (默认 true ) | |
| 67 | - * @property {Boolean} safeAreaInsetTop 是否留出顶部安全距离(状态栏高度) (默认 false ) | |
| 68 | - * @property {String} closeIconPos 自定义关闭图标位置(默认 'top-right' ) | |
| 69 | - * @property {String | Number} round 圆角值(默认 0) | |
| 70 | - * @property {Boolean} zoom 当mode=center时 是否开启缩放(默认 true ) | |
| 71 | - * @property {Object} customStyle 组件的样式,对象形式 | |
| 72 | - * @event {Function} open 弹出层打开 | |
| 73 | - * @event {Function} close 弹出层收起 | |
| 74 | - * @example <u-popup v-model="show"><text>出淤泥而不染,濯清涟而不妖</text></u-popup> | |
| 75 | - */ | |
| 76 | - export default { | |
| 77 | - name: 'u-popup', | |
| 78 | - mixins: [mpMixin, mixin, props], | |
| 79 | - data() { | |
| 80 | - return { | |
| 81 | - overlayDuration: this.duration + 50 | |
| 26 | +/** | |
| 27 | + * popup 弹窗 | |
| 28 | + * @description 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义 | |
| 29 | + * @tutorial https://ijry.github.io/uview-plus/components/popup.html | |
| 30 | + * @property {Boolean} show 是否展示弹窗 (默认 false ) | |
| 31 | + * @property {Boolean} overlay 是否显示遮罩 (默认 true ) | |
| 32 | + * @property {String} mode 弹出方向(默认 'bottom' ) | |
| 33 | + * @property {String | Number} duration 动画时长,单位ms (默认 300 ) | |
| 34 | + * @property {String | Number} overlayDuration 遮罩层动画时长,单位ms (默认 350 ) | |
| 35 | + * @property {Boolean} closeable 是否显示关闭图标(默认 false ) | |
| 36 | + * @property {Object | String} overlayStyle 自定义遮罩的样式 | |
| 37 | + * @property {String | Number} overlayOpacity 遮罩透明度,0-1之间(默认 0.5) | |
| 38 | + * @property {Boolean} closeOnClickOverlay 点击遮罩是否关闭弹窗 (默认 true ) | |
| 39 | + * @property {String | Number} zIndex 层级 (默认 10075 ) | |
| 40 | + * @property {Boolean} safeAreaInsetBottom 是否为iPhoneX留出底部安全距离 (默认 true ) | |
| 41 | + * @property {Boolean} safeAreaInsetTop 是否留出顶部安全距离(状态栏高度) (默认 false ) | |
| 42 | + * @property {String} closeIconPos 自定义关闭图标位置(默认 'top-right' ) | |
| 43 | + * @property {String | Number} round 圆角值(默认 0) | |
| 44 | + * @property {Boolean} zoom 当mode=center时 是否开启缩放(默认 true ) | |
| 45 | + * @property {Object} customStyle 组件的样式,对象形式 | |
| 46 | + * @event {Function} open 弹出层打开 | |
| 47 | + * @event {Function} close 弹出层收起 | |
| 48 | + * @example <u-popup v-model="show"><text>出淤泥而不染,濯清涟而不妖</text></u-popup> | |
| 49 | + */ | |
| 50 | +export default { | |
| 51 | + name: 'u-popup', | |
| 52 | + mixins: [mpMixin, mixin, props], | |
| 53 | + data() { | |
| 54 | + return { | |
| 55 | + overlayDuration: this.duration + 50 | |
| 56 | + } | |
| 57 | + }, | |
| 58 | + watch: { | |
| 59 | + show(newValue, oldValue) { | |
| 60 | + if (newValue === true) { | |
| 61 | + // #ifdef MP-WEIXIN | |
| 62 | + const children = this.$children | |
| 63 | + this.retryComputedComponentRect(children) | |
| 64 | + // #endif | |
| 82 | 65 | } |
| 83 | - }, | |
| 84 | - watch: { | |
| 85 | - show(newValue, oldValue) { | |
| 86 | - if (newValue === true) { | |
| 87 | - // #ifdef MP-WEIXIN | |
| 88 | - const children = this.$children | |
| 89 | - this.retryComputedComponentRect(children) | |
| 90 | - // #endif | |
| 91 | - } | |
| 66 | + } | |
| 67 | + }, | |
| 68 | + computed: { | |
| 69 | + transitionStyle() { | |
| 70 | + const style = { | |
| 71 | + zIndex: this.zIndex, | |
| 72 | + position: 'fixed', | |
| 73 | + display: 'flex', | |
| 74 | + } | |
| 75 | + style[this.mode] = 0 | |
| 76 | + if (this.mode === 'left') { | |
| 77 | + return uni.$u.deepMerge(style, { | |
| 78 | + bottom: 0, | |
| 79 | + top: 0, | |
| 80 | + }) | |
| 81 | + } else if (this.mode === 'right') { | |
| 82 | + return uni.$u.deepMerge(style, { | |
| 83 | + bottom: 0, | |
| 84 | + top: 0, | |
| 85 | + }) | |
| 86 | + } else if (this.mode === 'top') { | |
| 87 | + return uni.$u.deepMerge(style, { | |
| 88 | + left: 0, | |
| 89 | + right: 0 | |
| 90 | + }) | |
| 91 | + } else if (this.mode === 'bottom') { | |
| 92 | + return uni.$u.deepMerge(style, { | |
| 93 | + left: 0, | |
| 94 | + right: 0, | |
| 95 | + }) | |
| 96 | + } else if (this.mode === 'center') { | |
| 97 | + return uni.$u.deepMerge(style, { | |
| 98 | + alignItems: 'center', | |
| 99 | + 'justify-content': 'center', | |
| 100 | + top: 0, | |
| 101 | + left: 0, | |
| 102 | + right: 0, | |
| 103 | + bottom: 0 | |
| 104 | + }) | |
| 92 | 105 | } |
| 93 | 106 | }, |
| 94 | - computed: { | |
| 95 | - transitionStyle() { | |
| 96 | - const style = { | |
| 97 | - zIndex: this.zIndex, | |
| 98 | - position: 'fixed', | |
| 99 | - display: 'flex', | |
| 100 | - } | |
| 101 | - style[this.mode] = 0 | |
| 102 | - if (this.mode === 'left') { | |
| 103 | - return uni.$u.deepMerge(style, { | |
| 104 | - bottom: 0, | |
| 105 | - top: 0, | |
| 106 | - }) | |
| 107 | - } else if (this.mode === 'right') { | |
| 108 | - return uni.$u.deepMerge(style, { | |
| 109 | - bottom: 0, | |
| 110 | - top: 0, | |
| 111 | - }) | |
| 112 | - } else if (this.mode === 'top') { | |
| 113 | - return uni.$u.deepMerge(style, { | |
| 114 | - left: 0, | |
| 115 | - right: 0 | |
| 116 | - }) | |
| 107 | + contentStyle() { | |
| 108 | + const style = {} | |
| 109 | + // 通过设备信息的safeAreaInsets值来判断是否需要预留顶部状态栏和底部安全局的位置 | |
| 110 | + // 不使用css方案,是因为nvue不支持css的iPhoneX安全区查询属性 | |
| 111 | + const { | |
| 112 | + safeAreaInsets | |
| 113 | + } = uni.$u.sys() | |
| 114 | + if (this.mode !== 'center') { | |
| 115 | + style.flex = 1 | |
| 116 | + } | |
| 117 | + // 背景色,一般用于设置为transparent,去除默认的白色背景 | |
| 118 | + if (this.bgColor) { | |
| 119 | + style.backgroundColor = this.bgColor | |
| 120 | + } | |
| 121 | + if (this.round) { | |
| 122 | + const value = uni.$u.addUnit(this.round) | |
| 123 | + if (this.mode === 'top') { | |
| 124 | + style.borderBottomLeftRadius = value | |
| 125 | + style.borderBottomRightRadius = value | |
| 117 | 126 | } else if (this.mode === 'bottom') { |
| 118 | - return uni.$u.deepMerge(style, { | |
| 119 | - left: 0, | |
| 120 | - right: 0, | |
| 121 | - }) | |
| 127 | + style.borderTopLeftRadius = value | |
| 128 | + style.borderTopRightRadius = value | |
| 122 | 129 | } else if (this.mode === 'center') { |
| 123 | - return uni.$u.deepMerge(style, { | |
| 124 | - alignItems: 'center', | |
| 125 | - 'justify-content': 'center', | |
| 126 | - top: 0, | |
| 127 | - left: 0, | |
| 128 | - right: 0, | |
| 129 | - bottom: 0 | |
| 130 | - }) | |
| 131 | - } | |
| 132 | - }, | |
| 133 | - contentStyle() { | |
| 134 | - const style = {} | |
| 135 | - // 通过设备信息的safeAreaInsets值来判断是否需要预留顶部状态栏和底部安全局的位置 | |
| 136 | - // 不使用css方案,是因为nvue不支持css的iPhoneX安全区查询属性 | |
| 137 | - const { | |
| 138 | - safeAreaInsets | |
| 139 | - } = uni.$u.sys() | |
| 140 | - if (this.mode !== 'center') { | |
| 141 | - style.flex = 1 | |
| 130 | + style.borderRadius = value | |
| 142 | 131 | } |
| 143 | - // 背景色,一般用于设置为transparent,去除默认的白色背景 | |
| 144 | - if (this.bgColor) { | |
| 145 | - style.backgroundColor = this.bgColor | |
| 146 | - } | |
| 147 | - if(this.round) { | |
| 148 | - const value = uni.$u.addUnit(this.round) | |
| 149 | - if(this.mode === 'top') { | |
| 150 | - style.borderBottomLeftRadius = value | |
| 151 | - style.borderBottomRightRadius = value | |
| 152 | - } else if(this.mode === 'bottom') { | |
| 153 | - style.borderTopLeftRadius = value | |
| 154 | - style.borderTopRightRadius = value | |
| 155 | - } else if(this.mode === 'center') { | |
| 156 | - style.borderRadius = value | |
| 157 | - } | |
| 158 | - } | |
| 159 | - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 160 | - }, | |
| 161 | - position() { | |
| 162 | - if (this.mode === 'center') { | |
| 163 | - return this.zoom ? 'fade-zoom' : 'fade' | |
| 164 | - } | |
| 165 | - if (this.mode === 'left') { | |
| 166 | - return 'slide-left' | |
| 167 | - } | |
| 168 | - if (this.mode === 'right') { | |
| 169 | - return 'slide-right' | |
| 170 | - } | |
| 171 | - if (this.mode === 'bottom') { | |
| 172 | - return 'slide-up' | |
| 173 | - } | |
| 174 | - if (this.mode === 'top') { | |
| 175 | - return 'slide-down' | |
| 176 | - } | |
| 177 | - }, | |
| 132 | + } | |
| 133 | + return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)) | |
| 178 | 134 | }, |
| 179 | - methods: { | |
| 180 | - // 点击遮罩 | |
| 181 | - overlayClick() { | |
| 182 | - if (this.closeOnClickOverlay) { | |
| 183 | - this.$emit('close') | |
| 184 | - } | |
| 185 | - }, | |
| 186 | - close(e) { | |
| 135 | + position() { | |
| 136 | + if (this.mode === 'center') { | |
| 137 | + return this.zoom ? 'fade-zoom' : 'fade' | |
| 138 | + } | |
| 139 | + if (this.mode === 'left') { | |
| 140 | + return 'slide-left' | |
| 141 | + } | |
| 142 | + if (this.mode === 'right') { | |
| 143 | + return 'slide-right' | |
| 144 | + } | |
| 145 | + if (this.mode === 'bottom') { | |
| 146 | + return 'slide-up' | |
| 147 | + } | |
| 148 | + if (this.mode === 'top') { | |
| 149 | + return 'slide-down' | |
| 150 | + } | |
| 151 | + }, | |
| 152 | + }, | |
| 153 | + methods: { | |
| 154 | + // 点击遮罩 | |
| 155 | + overlayClick() { | |
| 156 | + if (this.closeOnClickOverlay) { | |
| 187 | 157 | this.$emit('close') |
| 188 | - }, | |
| 189 | - afterEnter() { | |
| 190 | - this.$emit('open') | |
| 191 | - }, | |
| 192 | - clickHandler() { | |
| 193 | - // 由于中部弹出时,其u-transition占据了整个页面相当于遮罩,此时需要发出遮罩点击事件,是否无法通过点击遮罩关闭弹窗 | |
| 194 | - if(this.mode === 'center') { | |
| 195 | - this.overlayClick() | |
| 158 | + } | |
| 159 | + }, | |
| 160 | + close(e) { | |
| 161 | + this.$emit('close') | |
| 162 | + }, | |
| 163 | + afterEnter() { | |
| 164 | + this.$emit('open') | |
| 165 | + }, | |
| 166 | + clickHandler() { | |
| 167 | + // 由于中部弹出时,其u-transition占据了整个页面相当于遮罩,此时需要发出遮罩点击事件,是否无法通过点击遮罩关闭弹窗 | |
| 168 | + if (this.mode === 'center') { | |
| 169 | + this.overlayClick() | |
| 170 | + } | |
| 171 | + this.$emit('click') | |
| 172 | + }, | |
| 173 | + // #ifdef MP-WEIXIN | |
| 174 | + retryComputedComponentRect(children) { | |
| 175 | + // 组件内部需要计算节点的组件 | |
| 176 | + const names = ['u-calendar-month', 'u-album', 'u-collapse-item', 'u-dropdown', 'u-index-item', 'u-index-list', | |
| 177 | + 'u-line-progress', 'u-list-item', 'u-rate', 'u-read-more', 'u-row', 'u-row-notice', 'u-scroll-list', | |
| 178 | + 'u-skeleton', 'u-slider', 'u-steps-item', 'u-sticky', 'u-subsection', 'u-swipe-action-item', 'u-tabbar', | |
| 179 | + 'u-tabs', 'u-tooltip' | |
| 180 | + ] | |
| 181 | + // 历遍所有的子组件节点 | |
| 182 | + for (let i = 0; i < children.length; i++) { | |
| 183 | + const child = children[i] | |
| 184 | + // 拿到子组件的子组件 | |
| 185 | + const grandChild = child.$children | |
| 186 | + // 判断如果在需要重新初始化的组件数组中名中,并且存在init方法的话,则执行 | |
| 187 | + if (names.includes(child.$options.name) && typeof child?.init === 'function') { | |
| 188 | + // 需要进行一定的延时,因为初始化页面需要时间 | |
| 189 | + uni.$u.sleep(50).then(() => { | |
| 190 | + child.init() | |
| 191 | + }) | |
| 196 | 192 | } |
| 197 | - this.$emit('click') | |
| 198 | - }, | |
| 199 | - // #ifdef MP-WEIXIN | |
| 200 | - retryComputedComponentRect(children) { | |
| 201 | - // 组件内部需要计算节点的组件 | |
| 202 | - const names = ['u-calendar-month', 'u-album', 'u-collapse-item', 'u-dropdown', 'u-index-item', 'u-index-list', | |
| 203 | - 'u-line-progress', 'u-list-item', 'u-rate', 'u-read-more', 'u-row', 'u-row-notice', 'u-scroll-list', | |
| 204 | - 'u-skeleton', 'u-slider', 'u-steps-item', 'u-sticky', 'u-subsection', 'u-swipe-action-item', 'u-tabbar', | |
| 205 | - 'u-tabs', 'u-tooltip' | |
| 206 | - ] | |
| 207 | - // 历遍所有的子组件节点 | |
| 208 | - for (let i = 0; i < children.length; i++) { | |
| 209 | - const child = children[i] | |
| 210 | - // 拿到子组件的子组件 | |
| 211 | - const grandChild = child.$children | |
| 212 | - // 判断如果在需要重新初始化的组件数组中名中,并且存在init方法的话,则执行 | |
| 213 | - if (names.includes(child.$options.name) && typeof child?.init === 'function') { | |
| 214 | - // 需要进行一定的延时,因为初始化页面需要时间 | |
| 215 | - uni.$u.sleep(50).then(() => { | |
| 216 | - child.init() | |
| 217 | - }) | |
| 218 | - } | |
| 219 | - // 如果子组件还有孙组件,进行递归历遍 | |
| 220 | - if (grandChild.length) { | |
| 221 | - this.retryComputedComponentRect(grandChild) | |
| 222 | - } | |
| 193 | + // 如果子组件还有孙组件,进行递归历遍 | |
| 194 | + if (grandChild.length) { | |
| 195 | + this.retryComputedComponentRect(grandChild) | |
| 223 | 196 | } |
| 224 | 197 | } |
| 225 | - // #endif | |
| 226 | 198 | } |
| 199 | + // #endif | |
| 227 | 200 | } |
| 201 | +} | |
| 228 | 202 | </script> |
| 229 | 203 | |
| 230 | 204 | <style lang="scss" scoped> |
| 231 | - @import "../../libs/css/components.scss"; | |
| 232 | - $u-popup-flex:1 !default; | |
| 233 | - $u-popup-content-background-color: #fff !default; | |
| 205 | +@import "../../libs/css/components.scss"; | |
| 206 | +$u-popup-flex: 1 !default; | |
| 207 | +$u-popup-content-background-color: #fff !default; | |
| 234 | 208 | |
| 235 | - .u-popup { | |
| 236 | - flex: $u-popup-flex; | |
| 209 | +.u-popup { | |
| 210 | + flex: $u-popup-flex; | |
| 237 | 211 | |
| 238 | - &__content { | |
| 239 | - background-color: $u-popup-content-background-color; | |
| 240 | - position: relative; | |
| 212 | + &__content { | |
| 213 | + background-color: $u-popup-content-background-color; | |
| 214 | + position: relative; | |
| 241 | 215 | |
| 242 | - &--round-top { | |
| 243 | - border-top-left-radius: 0; | |
| 244 | - border-top-right-radius: 0; | |
| 245 | - border-bottom-left-radius: 10px; | |
| 246 | - border-bottom-right-radius: 10px; | |
| 247 | - } | |
| 216 | + &--round-top { | |
| 217 | + border-top-left-radius: 0; | |
| 218 | + border-top-right-radius: 0; | |
| 219 | + border-bottom-left-radius: 10px; | |
| 220 | + border-bottom-right-radius: 10px; | |
| 221 | + } | |
| 248 | 222 | |
| 249 | - &--round-left { | |
| 250 | - border-top-left-radius: 0; | |
| 251 | - border-top-right-radius: 10px; | |
| 252 | - border-bottom-left-radius: 0; | |
| 253 | - border-bottom-right-radius: 10px; | |
| 254 | - } | |
| 223 | + &--round-left { | |
| 224 | + border-top-left-radius: 0; | |
| 225 | + border-top-right-radius: 10px; | |
| 226 | + border-bottom-left-radius: 0; | |
| 227 | + border-bottom-right-radius: 10px; | |
| 228 | + } | |
| 255 | 229 | |
| 256 | - &--round-right { | |
| 257 | - border-top-left-radius: 10px; | |
| 258 | - border-top-right-radius: 0; | |
| 259 | - border-bottom-left-radius: 10px; | |
| 260 | - border-bottom-right-radius: 0; | |
| 261 | - } | |
| 230 | + &--round-right { | |
| 231 | + border-top-left-radius: 10px; | |
| 232 | + border-top-right-radius: 0; | |
| 233 | + border-bottom-left-radius: 10px; | |
| 234 | + border-bottom-right-radius: 0; | |
| 235 | + } | |
| 262 | 236 | |
| 263 | - &--round-bottom { | |
| 264 | - border-top-left-radius: 10px; | |
| 265 | - border-top-right-radius: 10px; | |
| 266 | - border-bottom-left-radius: 0; | |
| 267 | - border-bottom-right-radius: 0; | |
| 268 | - } | |
| 237 | + &--round-bottom { | |
| 238 | + border-top-left-radius: 10px; | |
| 239 | + border-top-right-radius: 10px; | |
| 240 | + border-bottom-left-radius: 0; | |
| 241 | + border-bottom-right-radius: 0; | |
| 242 | + } | |
| 269 | 243 | |
| 270 | - &--round-center { | |
| 271 | - border-top-left-radius: 10px; | |
| 272 | - border-top-right-radius: 10px; | |
| 273 | - border-bottom-left-radius: 10px; | |
| 274 | - border-bottom-right-radius: 10px; | |
| 275 | - } | |
| 244 | + &--round-center { | |
| 245 | + border-top-left-radius: 10px; | |
| 246 | + border-top-right-radius: 10px; | |
| 247 | + border-bottom-left-radius: 10px; | |
| 248 | + border-bottom-right-radius: 10px; | |
| 249 | + } | |
| 276 | 250 | |
| 277 | - &__close { | |
| 278 | - position: absolute; | |
| 251 | + &__close { | |
| 252 | + position: absolute; | |
| 279 | 253 | |
| 280 | - &--hover { | |
| 281 | - opacity: 0.4; | |
| 282 | - } | |
| 254 | + &--hover { | |
| 255 | + opacity: 0.4; | |
| 283 | 256 | } |
| 257 | + } | |
| 284 | 258 | |
| 285 | - &__close--top-left { | |
| 286 | - top: 15px; | |
| 287 | - left: 15px; | |
| 288 | - } | |
| 259 | + &__close--top-left { | |
| 260 | + top: 15px; | |
| 261 | + left: 15px; | |
| 262 | + } | |
| 289 | 263 | |
| 290 | - &__close--top-right { | |
| 291 | - top: 15px; | |
| 292 | - right: 15px; | |
| 293 | - } | |
| 264 | + &__close--top-right { | |
| 265 | + top: 15px; | |
| 266 | + right: 15px; | |
| 267 | + } | |
| 294 | 268 | |
| 295 | - &__close--bottom-left { | |
| 296 | - bottom: 15px; | |
| 297 | - left: 15px; | |
| 298 | - } | |
| 269 | + &__close--bottom-left { | |
| 270 | + bottom: 15px; | |
| 271 | + left: 15px; | |
| 272 | + } | |
| 299 | 273 | |
| 300 | - &__close--bottom-right { | |
| 301 | - right: 15px; | |
| 302 | - bottom: 15px; | |
| 303 | - } | |
| 274 | + &__close--bottom-right { | |
| 275 | + right: 15px; | |
| 276 | + bottom: 15px; | |
| 304 | 277 | } |
| 305 | 278 | } |
| 279 | +} | |
| 306 | 280 | </style> | ... | ... |