Commit fec135c8dcdbe9ce2e604420090cbe2affbc378f
1 parent
dda8d67e
feat: 新增派单下发,增加企业负责人角色
Showing
27 changed files
with
3218 additions
and
609 deletions
Too many changes to show.
To preserve performance only 27 of 29 files are displayed.
garbage-removal/src/apis/order.js
| ... | ... | @@ -44,7 +44,28 @@ export async function uploadEvaluate(params, config) { |
| 44 | 44 | return await request.post(`/order/evaluate`, params, config); |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | - | |
| 47 | +/** | |
| 48 | + * 匿名访问 | |
| 49 | + * @param {*} orderId | |
| 50 | + * @returns | |
| 51 | + */ | |
| 48 | 52 | export async function queryGuestOrderDetail(orderId) { |
| 49 | 53 | return await request.get(`/order/webDetail/${orderId}`); |
| 50 | 54 | } |
| 55 | + | |
| 56 | +/** | |
| 57 | + * 查询公司下运输驾驶员 | |
| 58 | + * @param {*} companyId | |
| 59 | + */ | |
| 60 | +export async function queryOrderDispatch(orderId) { | |
| 61 | + return await request.get(`/order/queryDispatch/${orderId}`); | |
| 62 | +} | |
| 63 | + | |
| 64 | + | |
| 65 | +export async function dispatchOrders(params,config) { | |
| 66 | + return await request.put('/order/dispatch', params,config); | |
| 67 | +} | |
| 68 | + | |
| 69 | +export async function queryOrderHandlerStatus(orderId, config) { | |
| 70 | + return await request.get(`/order/queryOrderHandlerStatus/${orderId}`, config); | |
| 71 | +} | ... | ... |
garbage-removal/src/components/clash-dispatch/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <next-tree :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" | |
| 3 | + :selectParent="selectParent" :multiple="multiple" :treeData="treeData" @cancel="close" @confirm="onconfirm"> | |
| 4 | + <!-- label插槽示意代码 --> | |
| 5 | + <!-- <template #label="{data: {id, label, iconSrc, prev, post}}"> | |
| 6 | + <view class="line-block"> | |
| 7 | + <image class="img" v-if="iconSrc" :src="iconSrc"></image> | |
| 8 | + <text space="nbsp" v-if="prev">{{prev}} </text><text>{{label}}</text><text space="nbsp" v-if="post"> {{post}}</text> | |
| 9 | + </view> | |
| 10 | + </template> --> | |
| 11 | + <!-- <template #topBar> | |
| 12 | + <view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view> | |
| 13 | + <view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;"> | |
| 14 | + <button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button> | |
| 15 | + <button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button> | |
| 16 | + <button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button> | |
| 17 | + </view> | |
| 18 | + </template> --> | |
| 19 | + </next-tree> | |
| 20 | +</template> | |
| 21 | + | |
| 22 | +<script setup > | |
| 23 | +import { nextTick, ref, unref } from 'vue'; | |
| 24 | +// @ts-ignore | |
| 25 | +import nextTree from '../next-tree/next-tree.vue'; | |
| 26 | +const props = defineProps({ | |
| 27 | + dataList: { | |
| 28 | + type: Array, | |
| 29 | + default: [] | |
| 30 | + }, | |
| 31 | + valueKey: { | |
| 32 | + type: String, | |
| 33 | + default: 'id' | |
| 34 | + }, | |
| 35 | + multiple: { | |
| 36 | + type: Boolean, | |
| 37 | + default: true | |
| 38 | + }, | |
| 39 | + selectParent: { | |
| 40 | + type: Boolean, | |
| 41 | + default: false | |
| 42 | + }, | |
| 43 | + checkStrictly: { | |
| 44 | + type: Boolean, | |
| 45 | + default: false | |
| 46 | + }, | |
| 47 | + onconfirm: { | |
| 48 | + type: Function, | |
| 49 | + default: () => { } | |
| 50 | + } | |
| 51 | + | |
| 52 | +}) | |
| 53 | +const treeData = ref([]) | |
| 54 | +const nextTreeRef = ref() | |
| 55 | +function getTitle(checked) { | |
| 56 | + return `已选:${checked.length}位驾驶员` | |
| 57 | +} | |
| 58 | +function changeVerify(current, chooseList) { | |
| 59 | + // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 | |
| 60 | + // 如果函数体不做return返回值,即验证通过,控件正常处理业务 | |
| 61 | + // 限制条件 | |
| 62 | + if (chooseList) { | |
| 63 | + for (let index = 0; index < chooseList.length; index++) { | |
| 64 | + const element = chooseList[index]; | |
| 65 | + if (current.id.indexOf(element.id) === -1 && element.label.indexOf(current.label) != -1) { | |
| 66 | + return "该驾驶员已经被选中了" | |
| 67 | + } | |
| 68 | + } | |
| 69 | + } | |
| 70 | +} | |
| 71 | +function open(dataList) { | |
| 72 | + treeData.value = handlerTreeData(dataList) | |
| 73 | + treeData.value = treeData.value.filter(item => { | |
| 74 | + return item.children[0].id | |
| 75 | + }) | |
| 76 | + setTimeout(() => { | |
| 77 | + nextTick(() => { | |
| 78 | + unref(nextTreeRef).showTree = true | |
| 79 | + }) | |
| 80 | + }, 0) | |
| 81 | +} | |
| 82 | + | |
| 83 | +function handlerTreeData(dataList) { | |
| 84 | + return dataList | |
| 85 | + .map((item, index) => { | |
| 86 | + return { | |
| 87 | + "id": (index + 1), | |
| 88 | + "licensePlateNumber": item.licensePlateNumber, | |
| 89 | + "containerVolume": item.containerVolume + "方车", | |
| 90 | + "label": item.containerVolume + "方车" + '-' + item.licensePlateNumber, | |
| 91 | + "children": item.personnelInfo.map((childrenItem, childrenIndex) => { | |
| 92 | + return { | |
| 93 | + "id": (index + 1) + '-' + (childrenIndex + 1), | |
| 94 | + "tel": childrenItem.tel, | |
| 95 | + "name": childrenItem.name, | |
| 96 | + "label": childrenItem.name + '-' + childrenItem.tel, | |
| 97 | + "checked": childrenItem.checked, | |
| 98 | + "carCode": item.licensePlateNumber, | |
| 99 | + "disabled": childrenItem.checked ? true : childrenItem.tel ? false : true | |
| 100 | + } | |
| 101 | + }) | |
| 102 | + } | |
| 103 | + }) | |
| 104 | +} | |
| 105 | +function cleanTreeData(treeData) { | |
| 106 | + treeData.map(item => { | |
| 107 | + item.checked = false | |
| 108 | + if (item.children && item.children.length) { | |
| 109 | + cleanTreeData(item.children) | |
| 110 | + } | |
| 111 | + }) | |
| 112 | +} | |
| 113 | +function close() { | |
| 114 | + // 清除treeData的选中状态 | |
| 115 | + cleanTreeData(unref(treeData)) | |
| 116 | +} | |
| 117 | +defineExpose({ | |
| 118 | + open, close, nextTreeRef | |
| 119 | +}) | |
| 120 | +</script> | |
| 121 | +<style lang="scss"> | |
| 122 | +.line-block { | |
| 123 | + display: flex; | |
| 124 | + flex-direction: row; | |
| 125 | + justify-content: flex-start; | |
| 126 | + align-items: center; | |
| 127 | + | |
| 128 | + .img { | |
| 129 | + width: 40rpx; | |
| 130 | + height: 40rpx; | |
| 131 | + border-radius: 10rpx; | |
| 132 | + margin: 0 20rpx; | |
| 133 | + } | |
| 134 | +} | |
| 135 | +</style> | ... | ... |
garbage-removal/src/components/liu-delivery-time/liu-delivery-time.vue
| ... | ... | @@ -103,11 +103,21 @@ const getFutureDays = () => { |
| 103 | 103 | const year = date.getFullYear(); |
| 104 | 104 | const month = (date.getMonth() + 1).toString().padStart(2, '0'); |
| 105 | 105 | const day = date.getDate().toString().padStart(2, '0'); |
| 106 | - | |
| 107 | - days.push({ | |
| 108 | - day: `${year}-${month}-${day}`, | |
| 109 | - timeList: getTimeList() | |
| 110 | - }); | |
| 106 | + if (i === 0) { | |
| 107 | + let hours = new Date().getHours(); | |
| 108 | + if (hours >= 13) { | |
| 109 | + continue; | |
| 110 | + } | |
| 111 | + days.push({ | |
| 112 | + day: `${year}-${month}-${day}`, | |
| 113 | + timeList: getCurrentDayTimeList(9, hours, 3) | |
| 114 | + }); | |
| 115 | + } else { | |
| 116 | + days.push({ | |
| 117 | + day: `${year}-${month}-${day}`, | |
| 118 | + timeList: getTimeList() | |
| 119 | + }); | |
| 120 | + } | |
| 111 | 121 | } |
| 112 | 122 | return days; |
| 113 | 123 | } |
| ... | ... | @@ -115,47 +125,58 @@ const getFutureDays = () => { |
| 115 | 125 | |
| 116 | 126 | const getTimeList = () => { |
| 117 | 127 | const timeList = [{ |
| 118 | - time: '06:00-08:00', | |
| 119 | - start: '06:00', | |
| 120 | - end: '08:00' | |
| 121 | - }, { | |
| 122 | - time: '08:00-10:00', | |
| 123 | - start: '08:00', | |
| 128 | + time: '09:00-10:00', | |
| 129 | + start: '09:00', | |
| 124 | 130 | end: '10:00' |
| 125 | 131 | }, |
| 126 | 132 | { |
| 127 | - time: '10:00-12:00', | |
| 133 | + time: '10:00-11:00', | |
| 128 | 134 | start: '10:00', |
| 129 | - end: '12:00' | |
| 135 | + end: '11:00' | |
| 130 | 136 | }, |
| 131 | 137 | { |
| 132 | - time: '12:00-14:00', | |
| 133 | - start: '12:00', | |
| 134 | - end: '14:00' | |
| 138 | + time: '11:00-12:00', | |
| 139 | + start: '11:00', | |
| 140 | + end: '12:00' | |
| 135 | 141 | }, |
| 136 | 142 | { |
| 137 | - time: '14:00-16:00', | |
| 138 | - start: '14:00', | |
| 139 | - end: '16:00' | |
| 143 | + time: '12:00-13:00', | |
| 144 | + start: '12:00', | |
| 145 | + end: '13:00' | |
| 140 | 146 | }, |
| 141 | 147 | { |
| 142 | - time: '16:00-18:00', | |
| 143 | - start: '16:00', | |
| 144 | - end: '18:00' | |
| 148 | + time: '13:00-14:00', | |
| 149 | + start: '13:00', | |
| 150 | + end: '14:00' | |
| 145 | 151 | }, |
| 146 | 152 | { |
| 147 | - time: '18:00-20:00', | |
| 148 | - start: '18:00', | |
| 149 | - end: '20:00' | |
| 153 | + time: '14:00-15:00', | |
| 154 | + start: '14:00', | |
| 155 | + end: '15:00' | |
| 150 | 156 | }, |
| 151 | 157 | { |
| 152 | - time: '20:00-22:00', | |
| 153 | - start: '20:00', | |
| 154 | - end: '22:00' | |
| 158 | + time: '15:00-16:00', | |
| 159 | + start: '15:00', | |
| 160 | + end: '16:00' | |
| 155 | 161 | } |
| 156 | 162 | ]; |
| 157 | 163 | return timeList |
| 158 | 164 | } |
| 165 | + | |
| 166 | +/** | |
| 167 | + * | |
| 168 | + * @param {*} startTime 从几点开始 | |
| 169 | + * @param {*} hours 当前几点 | |
| 170 | + * @param {*} skip 跳过几个 | |
| 171 | + */ | |
| 172 | +const getCurrentDayTimeList = (startTime, hours, skip) => { | |
| 173 | + const timeList = getTimeList(); | |
| 174 | + // 因为从9点开始所以从9点开始截取 | |
| 175 | + // let startIndex = startTime + skip; | |
| 176 | + let abs = startTime > hours ? 1 : -1; | |
| 177 | + let index = startTime - hours >= skip ? 0 : (startTime - hours) * abs + skip; | |
| 178 | + return timeList.slice(index, timeList.length + 1) | |
| 179 | +} | |
| 159 | 180 | const open = () => { |
| 160 | 181 | isShow.value = true; |
| 161 | 182 | init(); |
| ... | ... | @@ -163,7 +184,7 @@ const open = () => { |
| 163 | 184 | const handleDateClick = (index) => { |
| 164 | 185 | selectedIndex.value = index; |
| 165 | 186 | selectedDay.value = days.value[index]; |
| 166 | - selectedTimeIndex.value = 999; | |
| 187 | + selectedTimeIndex.value = 10075; | |
| 167 | 188 | |
| 168 | 189 | } |
| 169 | 190 | const handleTimeClick = (index) => { |
| ... | ... | @@ -387,7 +408,7 @@ defineExpose({ open }) |
| 387 | 408 | } |
| 388 | 409 | |
| 389 | 410 | .scroll-animation { |
| 390 | - transition: all 0.25s linear; | |
| 411 | + transition: all 0.4s linear; | |
| 391 | 412 | } |
| 392 | 413 | |
| 393 | 414 | .scroll-temp { |
| ... | ... | @@ -402,7 +423,8 @@ defineExpose({ open }) |
| 402 | 423 | right: 0; |
| 403 | 424 | bottom: 0; |
| 404 | 425 | background: rgba(0, 0, 0, 0.3); |
| 405 | - z-index: 998; | |
| 426 | + z-index: 10075; | |
| 427 | + transition-property: opacity; | |
| 406 | 428 | } |
| 407 | 429 | |
| 408 | 430 | .time-picker { |
| ... | ... | @@ -469,7 +491,7 @@ defineExpose({ open }) |
| 469 | 491 | .date.active { |
| 470 | 492 | font-size: 30rpx; |
| 471 | 493 | font-weight: bold; |
| 472 | - color: #007aff; | |
| 494 | + color: #a9e08f; | |
| 473 | 495 | } |
| 474 | 496 | |
| 475 | 497 | .time-scroll { |
| ... | ... | @@ -492,6 +514,6 @@ defineExpose({ open }) |
| 492 | 514 | .time.active { |
| 493 | 515 | font-size: 30rpx; |
| 494 | 516 | font-weight: bold; |
| 495 | - color: #007aff; | |
| 517 | + color: #a9e08f; | |
| 496 | 518 | } |
| 497 | 519 | </style> | ... | ... |
garbage-removal/src/components/next-tree/next-tree.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view class="next-tree"> | |
| 3 | + <view class="next-tree-mask" :class="{ 'show': showTree }" @tap="_cancel"></view> | |
| 4 | + <view class="next-tree-cnt" :style="'top:' + top" | |
| 5 | + :class="{ 'show': showTree, 'next-tree-cnt-page': uiMode === 'page' }"> | |
| 6 | + <view v-if="_showTreeBar" class="next-tree-bar"> | |
| 7 | + <view class="next-tree-bar-cancel" :style="{ 'color': cancelColor }" hover-class="hover-c" @tap="_cancel">取消 | |
| 8 | + </view> | |
| 9 | + <view class="next-tree-bar-title" :style="{ 'color': titleColor }">{{ customTitle }}</view> | |
| 10 | + <view class="next-tree-bar-btns"> | |
| 11 | + <view class="next-tree-bar-cancel" :style="{ 'color': cancelColor }" hover-class="hover-c" @tap="_clear">清空 | |
| 12 | + </view> | |
| 13 | + <view class="btn-divid"></view> | |
| 14 | + <view class="next-tree-bar-confirm" :style="{ 'color': _themeColor }" hover-class="hover-c" @tap="_confirm">确定 | |
| 15 | + </view> | |
| 16 | + </view> | |
| 17 | + </view> | |
| 18 | + <view class="next-tree-view" :style="'top:' + (_showTreeBar ? '72rpx' : '0rpx')"> | |
| 19 | + <next-search-more v-if="ifSearch" @search="onSearch" mode="center" placeholder="请输入关键字" | |
| 20 | + :isFixedSearchBtn="false" /> | |
| 21 | + <slot name="topBar"></slot> | |
| 22 | + <scroll-view class="next-tree-view-sc" :scroll-y="true"> | |
| 23 | + <view v-show="_treeList.length"> | |
| 24 | + <block v-for="(item, index) in _treeList" :key="index"> | |
| 25 | + <view class="next-tree-item-block" v-if="item.show"> | |
| 26 | + <view class="next-tree-item" :style="[{ | |
| 27 | + paddingLeft: item.rank * 15 + 'px', | |
| 28 | + zIndex: item.rank * -1 + 50 | |
| 29 | + }]" :class="{ | |
| 30 | + border: border === true, | |
| 31 | + show: item.show, | |
| 32 | + last: item.lastRank, | |
| 33 | + showchild: item.showChild, | |
| 34 | + open: item.open, | |
| 35 | + disabled: item.disabled === true | |
| 36 | +}"> | |
| 37 | + <block v-if="showAuxiliaryLine"> | |
| 38 | + <template v-if="item.rank > 1"> | |
| 39 | + <view :key="i" v-for="i in (item.rank - 1)" | |
| 40 | + :style="{ left: (6 * (2 * i - 1) + 3 * (i - 1)) + 'px' }" class="parent-horizontal-line"></view> | |
| 41 | + </template> | |
| 42 | + <view class="left-line"> | |
| 43 | + <view v-if="item.lastRank" class="horizontal-line"></view> | |
| 44 | + </view> | |
| 45 | + </block> | |
| 46 | + <view class="next-tree-label" @tap.stop="_treeItemTap(item, index)"> | |
| 47 | + <image class="next-tree-icon" | |
| 48 | + :src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon"></image> | |
| 49 | + <rich-text :nodes="getNodes(item.ouputText)" :selectable="false" | |
| 50 | + v-if="ifSearch && searchModel === 'depHighlight' && keywords"></rich-text> | |
| 51 | + <slot v-else-if="$slots.label" name="label" :data="_getLabelSlotData(item)"></slot> | |
| 52 | + <rich-text v-else-if="item.checked && !item.disabled" :nodes="getThemeNodes(item.name)"></rich-text> | |
| 53 | + <text v-else>{{ item.name }}</text> | |
| 54 | + </view> | |
| 55 | + <view class="next-tree-check" @tap.stop="_treeItemSelect(item, index)" | |
| 56 | + v-if="selectParent ? true : item.lastRank"> | |
| 57 | + <view class="next-tree-check-yes" v-if="item.checked" :class="{ 'radio': !multiple }" | |
| 58 | + :style="{ 'border-color': item.disabled ? '#ccc' : _themeColor, 'background-color': item.disabled ? '#ccc' : _themeColor }"> | |
| 59 | + <view class="next-tree-check-yes-b" | |
| 60 | + :style="{ 'background-color': item.disabled ? '#ccc' : _themeColor }"> | |
| 61 | + <text v-if="item.checked" class="icon-text">✔</text> | |
| 62 | + </view> | |
| 63 | + </view> | |
| 64 | + <view class="next-tree-check-no" v-else :class="{ 'radio': !multiple }" | |
| 65 | + :style="{ 'border-color': item.disabled ? '#ccc' : _themeColor }"> | |
| 66 | + <text v-if="showHalfChecked(item) && showHalfCheckedTips" | |
| 67 | + :style="{ 'color': item.disabled ? '#ccc' : _themeColor, 'font-weight': 'blod', 'font-size': '10px' }" | |
| 68 | + class="icon-text">一</text> | |
| 69 | + </view> | |
| 70 | + </view> | |
| 71 | + </view> | |
| 72 | + </view> | |
| 73 | + </block> | |
| 74 | + </view> | |
| 75 | + <view v-show="!_treeList.length"> | |
| 76 | + <slot v-if="$slots.empty" name="empty"></slot> | |
| 77 | + <view class="empty" v-else><text>暂无数据</text></view> | |
| 78 | + </view> | |
| 79 | + <view v-if="ifSearch" style="height: 80rpx"></view> | |
| 80 | + <slot name="bottomBar"></slot> | |
| 81 | + </scroll-view> | |
| 82 | + </view> | |
| 83 | + </view> | |
| 84 | + <view class="fixed-bottom-bar"> | |
| 85 | + <slot name="fixedBottomBar"></slot> | |
| 86 | + </view> | |
| 87 | + </view> | |
| 88 | +</template> | |
| 89 | + | |
| 90 | +<script> | |
| 91 | +export default { | |
| 92 | + name: "next-tree", | |
| 93 | + props: { | |
| 94 | + uiMode: { | |
| 95 | + type: String, | |
| 96 | + default: 'popup' // popup(弹窗), page(页面) | |
| 97 | + }, | |
| 98 | + treeData: { | |
| 99 | + type: Array, | |
| 100 | + default: function () { | |
| 101 | + return [] | |
| 102 | + } | |
| 103 | + }, | |
| 104 | + valueKey: { | |
| 105 | + type: String, | |
| 106 | + default: 'id' | |
| 107 | + }, | |
| 108 | + labelKey: { | |
| 109 | + type: String, | |
| 110 | + default: 'label' | |
| 111 | + }, | |
| 112 | + disabledKey: { | |
| 113 | + type: String, | |
| 114 | + default: 'disabled' | |
| 115 | + }, | |
| 116 | + childrenKey: { | |
| 117 | + type: String, | |
| 118 | + default: 'children' | |
| 119 | + }, | |
| 120 | + title: { | |
| 121 | + type: [String, Function], | |
| 122 | + default: '' | |
| 123 | + }, | |
| 124 | + multiple: { // 是否可以多选 | |
| 125 | + type: Boolean, | |
| 126 | + default: false | |
| 127 | + // default: true | |
| 128 | + }, | |
| 129 | + selectParent: { //是否可以选父级 | |
| 130 | + type: Boolean, | |
| 131 | + default: false | |
| 132 | + }, | |
| 133 | + foldAll: { //折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开 | |
| 134 | + type: Boolean, | |
| 135 | + default: false | |
| 136 | + }, | |
| 137 | + themeColor: { // 主题颜色 | |
| 138 | + type: String, | |
| 139 | + default: '#53C21D' // #f9ae3d | |
| 140 | + }, | |
| 141 | + cancelColor: { // 取消按钮颜色 | |
| 142 | + type: String, | |
| 143 | + default: '' // #757575 | |
| 144 | + }, | |
| 145 | + titleColor: { // 标题颜色 | |
| 146 | + type: String, | |
| 147 | + default: '' // #757575 | |
| 148 | + }, | |
| 149 | + currentIcon: { // 展开时候的ic | |
| 150 | + type: String, | |
| 151 | + default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MEQ0QTM0MzQ1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MEQ0QTM0MzU1Q0RBMTFFOUE0MjY4NzI1Njc1RjI1ODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowRDRBMzQzMjVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowRDRBMzQzMzVDREExMUU5QTQyNjg3MjU2NzVGMjU4MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PidwepsAAAK0SURBVHja7JxbTsJAFIYHww7ciStgCeoGvGxAiOsgURegoL5720AXYLiIr0aJviq3Zx3PhIEnKG3ndtr+f3KixrSUj/ZjzjClIqUUiFm2gAAQAREQEUAEREAERAQQAREQAREBREAEREBEEqa67h9RFDWllDv0awWYlqlQHmu1WjMRRMoV1QFttA12y3xRtdNczq8EsE4/f8FumX2q77ROvNXk8UGMEKdUz6tYJHljaZAbuyUH+UR1to5BEohTuqwPCeS4pAA/qY6o/kyHOAMCeRK3owJnj+rH1jjxhqpVsstaebCz6TmnHWyXyY+xHjSBWBY/bvSgadtXBj9u9KCN3rnIfkzkQVsTEEX0Y2IP2oKo/HhMICcFAThUcwVZNGU6FdbX/XURzkbVF4+ybGhjPrFdgP66QdXNurGtSdk6Xdb9nAJ8oDo3OQlsQZzkdPw41ONBo6vI5scDefRjZg+6gpg3Pxp50CXEvPjR2IOuIXL3oxUPuobI3Y9WPOgDIlc/WvOgL4iL/vqFCcD7LH0xB4hj7cfQ/fWH9qCT+FhG0tN+DBk1PzjOM0SVllixcsBT1AvYc/kAPhc0hRg/3uvxoCgKRN9+dOrBUBB9+9GpB0NC9OVH5x4MDdG1H714kANEV3705kEOEBf9dcPi/lQnsuvLg1wgSu3Ha0v7Uh4MMgUXeuG71H407a+VBy9CPQkOdw+MtB+nGbd/D+FBbhBNxo9SjwcngJjNj0E9yBFiFj8G9SBXiGn8GNyDnCEm8SMLD3KHGOdHNh7kDjHOj2w8mAeIi/5arX+c6b/fxHz9oADEdGdjR/fXCw/OOB5oVfCOgnepz8IB14PMw03jCmTE+QBx5z0gAmKSqK9OUF+hcAeIhu/QYr4Qie8rjW83hhMBERARQAREQAREBBABERCLnH8BBgA+TQI7U4t53AAAAABJRU5ErkJggg==' | |
| 152 | + }, | |
| 153 | + defaultIcon: { // 折叠时候的ic | |
| 154 | + type: String, | |
| 155 | + default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAACE0lEQVR4Xu3c200DMRCF4XEltJAOkEugA+ggpUAHoQMqiFMCdEAJUMEiS4mEELlIO7bPOeN9i6K1rG/952myyea1WiCtXmEuYBPR4RBMxInoIOCwhOtJLKVszWyXc/5y2BvNEq6I+/3+kFK6M7OHnPM7jcLKjbZAvD/uaZtzflm5P4rbWyJWgDcze1LPuzVihfxUz7sH4ilJ2bx7Isrm3RtRMu8RiHJ5j0SUyXs0okTeCIj0eSMh0uaNhkiZNyIiXd7IiDR5oyNS5M2ACJ83EyJs3myIkHkzIsLlzYwIkzc7IkTeCojD81ZCHJa3GuKQvBURu+etjNgtb3XELnlHQGyedyTEZnlHQ2ySd0RE97wjI7rlHR3RJe+JeIrbLOecD6ePpZQ6W1kn2epo4MUrPOKyLN8ppYq1+y1VStncOjIdGnFZlo+U0uOtWOeOY2TE12Ouq//pEA7xXL7XfvcufR8K0Svfv6CREN3yDYfYIt9QiK3yjYTYLF95xB75SiP2ylcZsVu+cogj8pVCHJWvEuKwfOkREfKlRkTJlxkRJl86RMR8qRBR82VChM0XHpEhX2hElnyREWnyhUNkzBcKkTVfJETafIcjKuQ7FFEl35GIMvl2R1TMtyuiar49EWXzbY5oZpv/hibXTF2h3+s60FRKeT6+3TjMS3nrA3ZFRD8xrfY3ER1kJ+JEdBBwWGKeRAfEH1wS5WFZSDB/AAAAAElFTkSuQmCC' | |
| 156 | + }, | |
| 157 | + lastIcon: { // 没有子集的ic | |
| 158 | + type: String, | |
| 159 | + default: '' | |
| 160 | + }, | |
| 161 | + border: { // 是否有分割线 | |
| 162 | + type: Boolean, | |
| 163 | + default: false | |
| 164 | + }, | |
| 165 | + checkStrictly: { // 只有在multiple为true状态下生效; 状态下节点选择完全受控(父子节点选中状态不再关联) | |
| 166 | + type: Boolean, | |
| 167 | + default: false | |
| 168 | + }, | |
| 169 | + checkStrictlyModel: { // 关联模式 weak: 弱关联;strong: 强关联 | |
| 170 | + type: String, | |
| 171 | + default: 'weak' | |
| 172 | + }, | |
| 173 | + showHalfCheckedTips: { // 只有在multiple为true, checkStrictly为false状态下生效; 父子节点选中状态不再关联,显示半选提示 | |
| 174 | + type: Boolean, | |
| 175 | + default: true | |
| 176 | + }, | |
| 177 | + ifSearch: { // 是否开启search模式 | |
| 178 | + type: Boolean, | |
| 179 | + default: true | |
| 180 | + }, | |
| 181 | + searchModel: { // 搜索模式配置 | |
| 182 | + type: String, | |
| 183 | + default: 'common' // depHighlight: 从属高亮;common: 一般 | |
| 184 | + }, | |
| 185 | + showAuxiliaryLine: { // 辅助线模式 | |
| 186 | + type: Boolean, | |
| 187 | + default: false | |
| 188 | + }, | |
| 189 | + loadData: { | |
| 190 | + type: Function | |
| 191 | + }, | |
| 192 | + height: { | |
| 193 | + type: Number, | |
| 194 | + default: 500 | |
| 195 | + }, | |
| 196 | + changeVerify: { | |
| 197 | + type: Function | |
| 198 | + } | |
| 199 | + }, | |
| 200 | + data() { | |
| 201 | + return { | |
| 202 | + showTree: false, | |
| 203 | + treeList: [], | |
| 204 | + currentTreeData: [], | |
| 205 | + selectIndex: -1, | |
| 206 | + keywords: '', | |
| 207 | + nodeInitContrl: {}, | |
| 208 | + top: '' | |
| 209 | + } | |
| 210 | + }, | |
| 211 | + computed: { | |
| 212 | + _showTreeBar() { | |
| 213 | + return this.uiMode === 'popup' | |
| 214 | + }, | |
| 215 | + _themeColor() { | |
| 216 | + return this.themeColor || '#53C21D' | |
| 217 | + }, | |
| 218 | + _treeList() { | |
| 219 | + if (this.ifSearch && this.keywords) { | |
| 220 | + return this.treeList.filter(item => { | |
| 221 | + return (item.name && item.name.indexOf(this.keywords) !== -1) | |
| 222 | + }).map(item => { | |
| 223 | + const o = JSON.parse(JSON.stringify(item)); | |
| 224 | + if (o.showChild === false) { | |
| 225 | + o.showChild = true; | |
| 226 | + } | |
| 227 | + if (o.show === false) { | |
| 228 | + o.show = true; | |
| 229 | + } | |
| 230 | + return o | |
| 231 | + }) | |
| 232 | + } else { | |
| 233 | + return this.treeList | |
| 234 | + } | |
| 235 | + }, | |
| 236 | + customTitle() { | |
| 237 | + if (typeof this.title === 'function') { | |
| 238 | + return this.title(this._getCheckedParams()); | |
| 239 | + } else { | |
| 240 | + return this.title | |
| 241 | + } | |
| 242 | + } | |
| 243 | + }, | |
| 244 | + methods: { | |
| 245 | + _show() { | |
| 246 | + this.showTree = true | |
| 247 | + }, | |
| 248 | + _hide() { | |
| 249 | + this.showTree = false | |
| 250 | + }, | |
| 251 | + _cancel() { | |
| 252 | + this._hide() | |
| 253 | + this.$emit("cancel", ''); | |
| 254 | + }, | |
| 255 | + _confirm() { | |
| 256 | + // 处理所选数据 | |
| 257 | + let rt = this._getCheckedParams(); | |
| 258 | + this._hide() | |
| 259 | + this.$emit("confirm", rt); | |
| 260 | + }, | |
| 261 | + _getLabelSlotData(item) { | |
| 262 | + const _it = this.getItemFromTreeData(this.currentTreeData, item.id); | |
| 263 | + const it = Object.assign({}, _it); | |
| 264 | + delete it[this.childrenKey]; | |
| 265 | + return it | |
| 266 | + }, | |
| 267 | + _getCheckedParams() { | |
| 268 | + // 处理所选数据 | |
| 269 | + let rt = [], | |
| 270 | + obj = {}; | |
| 271 | + this.treeList.forEach((v, i) => { | |
| 272 | + if (this.treeList[i].checked) { | |
| 273 | + obj = {} | |
| 274 | + obj.parents = this.treeList[i].parents | |
| 275 | + obj = Object.assign(obj, this.treeList[i].source) | |
| 276 | + // 移除子元素 | |
| 277 | + delete obj.children | |
| 278 | + rt.push(obj) | |
| 279 | + } | |
| 280 | + }); | |
| 281 | + return rt; | |
| 282 | + }, | |
| 283 | + checkedFunc(values, state = true) { | |
| 284 | + if (values instanceof Array) { | |
| 285 | + values.map(id => { | |
| 286 | + const item = this.treeList.find(it => it.id === id); | |
| 287 | + if (item) { | |
| 288 | + item.checked = !!state | |
| 289 | + } | |
| 290 | + }) | |
| 291 | + } else { | |
| 292 | + const _item = this.treeList.find(it => it.id === values); | |
| 293 | + if (_item) { | |
| 294 | + _item.checked = !!state | |
| 295 | + } | |
| 296 | + } | |
| 297 | + }, | |
| 298 | + getRenderTreeList(list = [], rank = 0, parentId = [], parents = []) { | |
| 299 | + const treeList = []; | |
| 300 | + list.forEach(item => { | |
| 301 | + const halfChecked = this.getHalfCheckedFormTreeData(item); | |
| 302 | + let ouputText = ''; | |
| 303 | + if (this.searchModel === 'depHighlight') { | |
| 304 | + if (parents && parents.length) { | |
| 305 | + ouputText = parents.map(item => item[this.labelKey]).join(' > '); | |
| 306 | + ouputText = ouputText + ' > ' + item[this.labelKey]; | |
| 307 | + } else { | |
| 308 | + ouputText = item[this.labelKey]; | |
| 309 | + } | |
| 310 | + } | |
| 311 | + treeList.push({ | |
| 312 | + id: item[this.valueKey], | |
| 313 | + name: item[this.labelKey], | |
| 314 | + source: item, | |
| 315 | + parentId, // 父级id数组 | |
| 316 | + parents, // 父级id数组 | |
| 317 | + rank, // 层级 | |
| 318 | + showChild: false, //子级是否显示 | |
| 319 | + open: false, //是否打开 | |
| 320 | + show: rank === 0, // 自身是否显示 | |
| 321 | + hideArr: [], | |
| 322 | + ouputText, | |
| 323 | + orChecked: item.checked ? item.checked : false, | |
| 324 | + checked: item.checked ? item.checked : false, | |
| 325 | + halfChecked, | |
| 326 | + disabled: this.disabledKey && item[this.disabledKey] === true | |
| 327 | + }) | |
| 328 | + if ( | |
| 329 | + (Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length > 0) || | |
| 330 | + (this.loadData && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length === 0) | |
| 331 | + ) { | |
| 332 | + let parentid = [...parentId], | |
| 333 | + parentArr = [...parents], | |
| 334 | + childrenid = []; | |
| 335 | + delete parentArr.children | |
| 336 | + parentid.push(item[this.valueKey]); | |
| 337 | + parentArr.push({ | |
| 338 | + [this.valueKey]: item[this.valueKey], | |
| 339 | + [this.labelKey]: item[this.labelKey], | |
| 340 | + }) | |
| 341 | + // this._renderTreeList(item[this.childrenKey], rank + 1, parentid, parentArr); | |
| 342 | + } else { | |
| 343 | + treeList[treeList.length - 1].lastRank = true; | |
| 344 | + } | |
| 345 | + }) | |
| 346 | + return treeList; | |
| 347 | + }, | |
| 348 | + //扁平化树结构 | |
| 349 | + _renderTreeList(list = [], rank = 0, parentId = [], parents = []) { | |
| 350 | + list.forEach(item => { | |
| 351 | + const halfChecked = this.getHalfCheckedFormTreeData(item); | |
| 352 | + let ouputText = ''; | |
| 353 | + if (this.searchModel === 'depHighlight') { | |
| 354 | + if (parents && parents.length) { | |
| 355 | + ouputText = parents.map(item => item[this.labelKey]).join(' > '); | |
| 356 | + ouputText = ouputText + ' > ' + item[this.labelKey]; | |
| 357 | + } else { | |
| 358 | + ouputText = item[this.labelKey]; | |
| 359 | + } | |
| 360 | + } | |
| 361 | + this.treeList.push({ | |
| 362 | + id: item[this.valueKey], | |
| 363 | + name: item[this.labelKey], | |
| 364 | + source: item, | |
| 365 | + parentId, // 父级id数组 | |
| 366 | + parents, // 父级id数组 | |
| 367 | + rank, // 层级 | |
| 368 | + showChild: false, //子级是否显示 | |
| 369 | + open: false, //是否打开 | |
| 370 | + show: rank === 0, // 自身是否显示 | |
| 371 | + hideArr: [], | |
| 372 | + ouputText, | |
| 373 | + orChecked: item.checked ? item.checked : false, | |
| 374 | + checked: item.checked ? item.checked : false, | |
| 375 | + halfChecked, | |
| 376 | + disabled: this.disabledKey && item[this.disabledKey] === true | |
| 377 | + }) | |
| 378 | + if ( | |
| 379 | + (Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length > 0) || | |
| 380 | + (this.loadData && Array.isArray(item[this.childrenKey]) && item[this.childrenKey].length === 0) | |
| 381 | + ) { | |
| 382 | + let parentid = [...parentId], | |
| 383 | + parentArr = [...parents], | |
| 384 | + childrenid = []; | |
| 385 | + delete parentArr.children | |
| 386 | + parentid.push(item[this.valueKey]); | |
| 387 | + parentArr.push({ | |
| 388 | + [this.valueKey]: item[this.valueKey], | |
| 389 | + [this.labelKey]: item[this.labelKey], | |
| 390 | + "data": item | |
| 391 | + }) | |
| 392 | + this._renderTreeList(item[this.childrenKey], rank + 1, parentid, parentArr); | |
| 393 | + } else { | |
| 394 | + this.treeList[this.treeList.length - 1].lastRank = true; | |
| 395 | + } | |
| 396 | + }) | |
| 397 | + }, | |
| 398 | + // 处理默认选择 | |
| 399 | + _defaultSelect() { | |
| 400 | + this.treeList.forEach((v, i) => { | |
| 401 | + if (v.checked) { | |
| 402 | + this.treeList.forEach((v2, i2) => { | |
| 403 | + if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) { | |
| 404 | + v2.show = true | |
| 405 | + if (v.parentId.includes(v2.id)) { | |
| 406 | + v2.showChild = true; | |
| 407 | + v2.open = true; | |
| 408 | + } | |
| 409 | + } | |
| 410 | + }) | |
| 411 | + } | |
| 412 | + }) | |
| 413 | + }, | |
| 414 | + // 点击 | |
| 415 | + async _treeItemTap(item, _index) { | |
| 416 | + const index = this.treeList.findIndex(it => it.id === item.id); | |
| 417 | + if (item.lastRank === true) { | |
| 418 | + if (item.disabled === true) return | |
| 419 | + //点击最后一级时触发事件 | |
| 420 | + this.treeList[index].checked = !this.treeList[index].checked; | |
| 421 | + if (this.changeVerify && (typeof this.changeVerify === 'function')) { | |
| 422 | + const current = Object.assign({}, item.source); | |
| 423 | + current.checked = item.checked; | |
| 424 | + const tip = this.changeVerify(current, this.multiple ? this._getCheckedParams() : [current]); | |
| 425 | + if (tip) { | |
| 426 | + this.treeList[index].checked = !this.treeList[index].checked; | |
| 427 | + uni.showToast({ | |
| 428 | + title: tip, | |
| 429 | + icon: 'none' | |
| 430 | + }); | |
| 431 | + return | |
| 432 | + } | |
| 433 | + }; | |
| 434 | + this.treeList[index].halfChecked = false; | |
| 435 | + if (this.multiple && !this.checkStrictly && this.showHalfCheckedTips) { | |
| 436 | + this.updateHalfChecked(index); | |
| 437 | + } else if (this.multiple && this.checkStrictly) { | |
| 438 | + this.updateParentChecked(index); | |
| 439 | + } | |
| 440 | + this._fixMultiple(index) | |
| 441 | + return; | |
| 442 | + } | |
| 443 | + // loadData实现 | |
| 444 | + const isLoadData = this.loadData && !this.nodeInitContrl[item.id]; | |
| 445 | + if (isLoadData) { | |
| 446 | + uni && uni.showLoading({ title: "请稍后..." }); | |
| 447 | + const newChild = await this.loadData(this.treeList[index].source); | |
| 448 | + // 为了保证treeData数据的完整性,异步加载的数据需要添加到treeData上; | |
| 449 | + const treeItem = this.getItemFromTreeData(this.currentTreeData, item.id); | |
| 450 | + treeItem[this.childrenKey] = newChild && newChild.length ? newChild : undefined; | |
| 451 | + const parentId = item.parentId || []; | |
| 452 | + const lists = this.getRenderTreeList(newChild || [], item.rank + 1, parentId.concat([item.id]), [{ [this.valueKey]: item[this.valueKey], [this.labelKey]: item[this.labelKey] }]); | |
| 453 | + this.nodeInitContrl[item.id] = true; | |
| 454 | + this.treeList.splice(index + 1, 0, ...lists); | |
| 455 | + } | |
| 456 | + const childLen = this.treeList.filter(it => it.parentId.includes(item.id)).length; | |
| 457 | + if (!isLoadData && childLen > 50) { | |
| 458 | + uni && uni.showLoading({ title: "请稍后..." }); | |
| 459 | + } | |
| 460 | + let list = this.treeList; | |
| 461 | + let id = item.id; | |
| 462 | + item.showChild = !item.showChild; | |
| 463 | + item.open = item.showChild ? true : !item.open; | |
| 464 | + list.forEach((childItem, i) => { | |
| 465 | + if (item.showChild === false) { | |
| 466 | + //隐藏所有子级 | |
| 467 | + if (!childItem.parentId.includes(id)) { | |
| 468 | + return; | |
| 469 | + } | |
| 470 | + if (!this.foldAll) { | |
| 471 | + if (childItem.lastRank !== true && !childItem.open) { | |
| 472 | + childItem.showChild = false; | |
| 473 | + } | |
| 474 | + // 为隐藏的内容添加一个标记 | |
| 475 | + if (childItem.show) { | |
| 476 | + childItem.hideArr[item.rank] = id | |
| 477 | + } | |
| 478 | + } else { | |
| 479 | + if (childItem.lastRank !== true) { | |
| 480 | + childItem.showChild = false; | |
| 481 | + } | |
| 482 | + } | |
| 483 | + childItem.show = false; | |
| 484 | + } else { | |
| 485 | + // 打开子集 | |
| 486 | + if (childItem.parentId[childItem.parentId.length - 1] === id) { | |
| 487 | + childItem.show = true; | |
| 488 | + } | |
| 489 | + // 打开被隐藏的子集 | |
| 490 | + if (childItem.parentId.includes(id) && !this.foldAll) { | |
| 491 | + // console.log(childItem.hideArr) | |
| 492 | + if (childItem.hideArr[item.rank] === id) { | |
| 493 | + childItem.show = true; | |
| 494 | + if (childItem.open && childItem.showChild) { | |
| 495 | + childItem.showChild = true | |
| 496 | + } else { | |
| 497 | + childItem.showChild = false | |
| 498 | + } | |
| 499 | + childItem.hideArr[item.rank] = null | |
| 500 | + } | |
| 501 | + } | |
| 502 | + } | |
| 503 | + }); | |
| 504 | + setTimeout(() => { | |
| 505 | + uni && uni.hideLoading() | |
| 506 | + }) | |
| 507 | + }, | |
| 508 | + getThemeNodes(text) { | |
| 509 | + const regex = new RegExp(`(${text || ''})`, 'gi'); | |
| 510 | + return text ? text.replace(regex, `<span style="color: ${this._themeColor}">$1</span>`) : ''; | |
| 511 | + }, | |
| 512 | + getNodes(ouputText) { | |
| 513 | + if (this.keywords && ouputText) { | |
| 514 | + const regex = new RegExp(`(${this.keywords})`, 'gi'); | |
| 515 | + return ouputText.replace(regex, `<span style="color: ${this._themeColor}">$1</span>`); | |
| 516 | + } | |
| 517 | + return ouputText | |
| 518 | + }, | |
| 519 | + getHalfCheckedFormTreeData(item) { | |
| 520 | + if (this.checkStrictly) { | |
| 521 | + return false; | |
| 522 | + } else if (!this.showHalfCheckedTips) { | |
| 523 | + return false | |
| 524 | + } else { | |
| 525 | + if (item[this.childrenKey] && item[this.childrenKey].length) { | |
| 526 | + return item[this.childrenKey].some(it => { | |
| 527 | + if (it.checked === true) { | |
| 528 | + return true; | |
| 529 | + } else if (it[this.childrenKey] && it[this.childrenKey].length) { | |
| 530 | + return this.getHalfCheckedFormTreeData(it); | |
| 531 | + } else { | |
| 532 | + return false; | |
| 533 | + }; | |
| 534 | + }); | |
| 535 | + } else { | |
| 536 | + return false; | |
| 537 | + } | |
| 538 | + } | |
| 539 | + }, | |
| 540 | + getItemFromTreeData(treeData, id) { | |
| 541 | + if (id) { | |
| 542 | + let item = null; | |
| 543 | + (treeData || []).some(it => { | |
| 544 | + if (it[this.valueKey] === id) { | |
| 545 | + item = it | |
| 546 | + return true | |
| 547 | + } else if (it[this.childrenKey] && it[this.childrenKey].length) { | |
| 548 | + item = this.getItemFromTreeData(it[this.childrenKey], id) | |
| 549 | + return !!item | |
| 550 | + } else { | |
| 551 | + return false | |
| 552 | + } | |
| 553 | + }); | |
| 554 | + return item | |
| 555 | + }; | |
| 556 | + return null | |
| 557 | + }, | |
| 558 | + _treeItemSelect(item, _index) { | |
| 559 | + const index = this.treeList.findIndex(it => it.id === item.id); | |
| 560 | + if (item.disabled === true) return | |
| 561 | + this.treeList[index].checked = !this.treeList[index].checked; | |
| 562 | + // console.log(index) | |
| 563 | + if (this.changeVerify && (typeof this.changeVerify === 'function')) { | |
| 564 | + const current = Object.assign({}, item.source); | |
| 565 | + current.checked = item.checked; | |
| 566 | + const tip = this.changeVerify(current, this.multiple ? this._getCheckedParams() : [current]); | |
| 567 | + if (tip) { | |
| 568 | + this.treeList[index].checked = !this.treeList[index].checked; | |
| 569 | + uni.showToast({ | |
| 570 | + title: tip, | |
| 571 | + icon: 'none' | |
| 572 | + }); | |
| 573 | + return | |
| 574 | + } | |
| 575 | + }; | |
| 576 | + this.treeList[index].halfChecked = false; | |
| 577 | + if (this.multiple && this.checkStrictly) { | |
| 578 | + if (!item.lastRank) { | |
| 579 | + const source = item.source || {}; | |
| 580 | + const children = source[this.childrenKey] || []; | |
| 581 | + const checkedKeyList = this.getChildrenKeys(children); | |
| 582 | + this.treeList.forEach((v, i) => { | |
| 583 | + if (checkedKeyList.indexOf(v.id) !== -1) { | |
| 584 | + if (this.checkStrictlyModel === 'weak') { | |
| 585 | + if (!this.treeList[i].disabled) { | |
| 586 | + this.treeList[i].checked = this.treeList[index].checked | |
| 587 | + } | |
| 588 | + } else if (this.checkStrictlyModel === 'strong') { | |
| 589 | + this.treeList[i].checked = this.treeList[index].checked | |
| 590 | + } | |
| 591 | + } | |
| 592 | + }) | |
| 593 | + } | |
| 594 | + this.updateParentChecked(index) | |
| 595 | + } else if (this.multiple && !this.checkStrictly && this.showHalfCheckedTips) { | |
| 596 | + this.updateHalfChecked(index); | |
| 597 | + } else { | |
| 598 | + this._fixMultiple(index); | |
| 599 | + } | |
| 600 | + }, | |
| 601 | + updateParentChecked(index) { | |
| 602 | + const parentId = (this.treeList[index].parentId || []).concat([]).reverse(); | |
| 603 | + if (parentId && parentId.length) { | |
| 604 | + parentId.map(id => { | |
| 605 | + const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | |
| 606 | + const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map(item => item[this.valueKey]); | |
| 607 | + const bool = this.treeList | |
| 608 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | |
| 609 | + .every(it => it.checked === true); | |
| 610 | + | |
| 611 | + const _bool = this.treeList | |
| 612 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | |
| 613 | + .every(it => it.checked === false); | |
| 614 | + | |
| 615 | + const parentItem = this.treeList.find(it => it.id === id); | |
| 616 | + if (parentItem) { | |
| 617 | + if (this.checkStrictlyModel === 'weak') { | |
| 618 | + if (bool && !parentItem.disabled) { | |
| 619 | + parentItem.checked = true; | |
| 620 | + } else if (_bool && !parentItem.disabled) { | |
| 621 | + parentItem.checked = false; | |
| 622 | + } | |
| 623 | + } else if (this.checkStrictlyModel === 'strong') { | |
| 624 | + if (bool) { | |
| 625 | + parentItem.checked = true; | |
| 626 | + } else { | |
| 627 | + parentItem.checked = false; | |
| 628 | + } | |
| 629 | + } | |
| 630 | + } | |
| 631 | + }) | |
| 632 | + } | |
| 633 | + }, | |
| 634 | + updateHalfChecked(index) { | |
| 635 | + const _parentId = this.treeList[index].parentId || []; | |
| 636 | + const parentId = _parentId.concat([]).reverse(); | |
| 637 | + if (parentId && parentId.length) { | |
| 638 | + parentId.map(id => { | |
| 639 | + const parentTreeDataItem = this.getItemFromTreeData(this.currentTreeData, id); | |
| 640 | + const childrenIds = (parentTreeDataItem[this.childrenKey] || []).map(item => item[this.valueKey]); | |
| 641 | + | |
| 642 | + const bool = this.treeList | |
| 643 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | |
| 644 | + .every(it => it.checked === false && it.halfChecked === false); | |
| 645 | + | |
| 646 | + const _bool = this.treeList | |
| 647 | + .filter(it => childrenIds.indexOf(it.id) !== -1) | |
| 648 | + .some(it => it.checked === true || it.halfChecked === true); | |
| 649 | + | |
| 650 | + const parentItem = this.treeList.find(it => it.id === id); | |
| 651 | + if (parentItem) { | |
| 652 | + if (!parentItem.checked) { | |
| 653 | + if (bool) { | |
| 654 | + parentItem.halfChecked = false | |
| 655 | + } else if (_bool) { | |
| 656 | + parentItem.halfChecked = true | |
| 657 | + } else { | |
| 658 | + parentItem.halfChecked = false | |
| 659 | + } | |
| 660 | + } | |
| 661 | + } | |
| 662 | + }) | |
| 663 | + } | |
| 664 | + if (this.treeList[index].checked == false) { | |
| 665 | + const source = this.treeList[index].source || {}; | |
| 666 | + const children = source[this.childrenKey] || []; | |
| 667 | + const checkedKeyList = this.getChildrenKeys(children); | |
| 668 | + const bool = this.treeList.filter(item => checkedKeyList.indexOf(item.id) !== -1).some(item => item.checked); | |
| 669 | + if (bool) { | |
| 670 | + this.treeList[index].halfChecked = true; | |
| 671 | + } | |
| 672 | + } | |
| 673 | + }, | |
| 674 | + showHalfChecked(item) { | |
| 675 | + if (this.multiple && !this.checkStrictly && item.halfChecked === true) { | |
| 676 | + return true | |
| 677 | + } else { | |
| 678 | + return false | |
| 679 | + } | |
| 680 | + }, | |
| 681 | + getChildrenKeys(children) { | |
| 682 | + let keys = []; | |
| 683 | + (children || []).map(item => { | |
| 684 | + keys.push(item[this.valueKey]) | |
| 685 | + if (item[this.childrenKey] && item[this.childrenKey].length) { | |
| 686 | + keys = keys.concat(this.getChildrenKeys(item[this.childrenKey])) | |
| 687 | + } | |
| 688 | + }) | |
| 689 | + return keys | |
| 690 | + }, | |
| 691 | + // 处理单选多选 | |
| 692 | + _fixMultiple(index) { | |
| 693 | + if (!this.multiple) { | |
| 694 | + // 如果是单选 | |
| 695 | + this.treeList.forEach((v, i) => { | |
| 696 | + if (i != index) { | |
| 697 | + this.treeList[i].checked = false | |
| 698 | + } else { | |
| 699 | + this.treeList[i].checked = true | |
| 700 | + } | |
| 701 | + }) | |
| 702 | + } | |
| 703 | + }, | |
| 704 | + // 重置数据 | |
| 705 | + _reTreeList() { | |
| 706 | + this.treeList.forEach((v, i) => { | |
| 707 | + this.treeList[i].checked = v.orChecked | |
| 708 | + }) | |
| 709 | + }, | |
| 710 | + _initTree() { | |
| 711 | + this.treeList.length = 0; | |
| 712 | + if (this.loadData) { | |
| 713 | + this.currentTreeData = JSON.parse(JSON.stringify(this.treeData)); | |
| 714 | + } else { | |
| 715 | + this.currentTreeData = this.treeData; | |
| 716 | + } | |
| 717 | + this._renderTreeList(this.currentTreeData); | |
| 718 | + this.$nextTick(() => { | |
| 719 | + this._defaultSelect(this.currentTreeData); | |
| 720 | + }) | |
| 721 | + }, | |
| 722 | + _clear() { | |
| 723 | + this.treeList.map(item => { | |
| 724 | + if (this.multiple && this.checkStrictly) { | |
| 725 | + if (this.checkStrictlyModel === 'strong') { | |
| 726 | + item.checked = false; | |
| 727 | + } else if (this.checkStrictlyModel === 'weak') { | |
| 728 | + if (!item.disabled) { | |
| 729 | + item.checked = false; | |
| 730 | + }; | |
| 731 | + } else { | |
| 732 | + item.checked = false; | |
| 733 | + } | |
| 734 | + } else { | |
| 735 | + if (!item.disabled) { | |
| 736 | + item.checked = false; | |
| 737 | + } | |
| 738 | + }; | |
| 739 | + | |
| 740 | + item.halfChecked = false; | |
| 741 | + }) | |
| 742 | + this.$emit("clear"); | |
| 743 | + }, | |
| 744 | + onSearch(val) { | |
| 745 | + this.keywords = val; | |
| 746 | + }, | |
| 747 | + initUiModePopup(watched) { | |
| 748 | + uni.getSystemInfo({ | |
| 749 | + success: (res) => { | |
| 750 | + this.top = (res.windowHeight - this.height) + 'px'; | |
| 751 | + } | |
| 752 | + }); | |
| 753 | + watched && watched(); | |
| 754 | + watched = this.$watch(() => this.showTree, (bool) => { | |
| 755 | + if (bool) { | |
| 756 | + this._initTree(); | |
| 757 | + } else { | |
| 758 | + this.treeList.length = 0; | |
| 759 | + this.nodeInitContrl = {}; | |
| 760 | + } | |
| 761 | + }, { immediate: true }); | |
| 762 | + }, | |
| 763 | + initUiModePage(watched) { | |
| 764 | + this.top = '0px'; | |
| 765 | + watched && watched(); | |
| 766 | + watched = this.$watch(() => this.treeData, () => { | |
| 767 | + this.treeList.length = 0; | |
| 768 | + this.nodeInitContrl = {}; | |
| 769 | + this.$nextTick(() => { | |
| 770 | + this._initTree(); | |
| 771 | + }); | |
| 772 | + }, { immediate: true, deep: true }) | |
| 773 | + this.$nextTick(() => { | |
| 774 | + this.showTree = true; | |
| 775 | + }); | |
| 776 | + }, | |
| 777 | + uiModeInit() { | |
| 778 | + let watched = null; | |
| 779 | + if (this.uiMode === 'popup') { | |
| 780 | + this.initUiModePopup(watched); | |
| 781 | + } else if (this.uiMode === 'page') { | |
| 782 | + this.initUiModePage(watched); | |
| 783 | + } else { | |
| 784 | + this.initUiModePopup(watched); | |
| 785 | + } | |
| 786 | + } | |
| 787 | + }, | |
| 788 | + mounted() { | |
| 789 | + this.uiModeInit(); | |
| 790 | + } | |
| 791 | +} | |
| 792 | +</script> | |
| 793 | + | |
| 794 | +<style scoped> | |
| 795 | +@import "./style.css"; | |
| 796 | +</style> | ... | ... |
garbage-removal/src/components/next-tree/readme/changelog.md
0 → 100644
| 1 | +## 1.6.7(2024-01-04) | |
| 2 | +修复异步加载节点搜索展示bug | |
| 3 | +## 1.6.6(2023-12-29) | |
| 4 | +修复next-tree异步加载节点关闭bug | |
| 5 | +## 1.6.5(2023-12-21) | |
| 6 | +fix bug | |
| 7 | +## 1.6.4(2023-12-21) | |
| 8 | +fix bug | |
| 9 | +## 1.6.3(2023-12-21) | |
| 10 | +更新vue2版本说明文档 | |
| 11 | +## 1.6.2(2023-12-21) | |
| 12 | +修复说明文档 | |
| 13 | +## 1.6.1(2023-12-18) | |
| 14 | +增加empty插槽 | |
| 15 | +## 1.6.0(2023-12-18) | |
| 16 | +增加empty插槽 | |
| 17 | +## 1.5.9(2023-12-15) | |
| 18 | +修改说明文件 | |
| 19 | +## 1.5.8(2023-12-15) | |
| 20 | +修复changeVerify函数单选时,返回参数bug | |
| 21 | +## 1.5.7(2023-12-14) | |
| 22 | +修复checkStrictlyModel === 'strong'的bug | |
| 23 | +## 1.5.6(2023-12-13) | |
| 24 | +代码优化 | |
| 25 | +## 1.5.5(2023-12-13) | |
| 26 | +优化changeVerify的使用 | |
| 27 | +## 1.5.4(2023-12-12) | |
| 28 | +修复提示层级问题 | |
| 29 | +## 1.5.3(2023-12-12) | |
| 30 | +优化uiMode=page模式下的使用 | |
| 31 | +## 1.5.2(2023-12-11) | |
| 32 | +增加uiMode配置,实现页面模式展示 | |
| 33 | +## 1.5.1(2023-12-06) | |
| 34 | +更新说明 | |
| 35 | +## 1.5.0(2023-12-06) | |
| 36 | +更新插件使用注意事项 | |
| 37 | +## 1.4.9(2023-12-01) | |
| 38 | +增加topBar插槽 | |
| 39 | +## 1.4.8(2023-11-30) | |
| 40 | +增加changeVerify验证函数,实现change的各种控制 | |
| 41 | +## 1.4.7(2023-11-30) | |
| 42 | +增加弹层容器高度可配置 | |
| 43 | +## 1.4.6(2023-11-28) | |
| 44 | +修复bug | |
| 45 | +## 1.4.5(2023-11-28) | |
| 46 | +修复disabled是,需要显示灰色不可操作 | |
| 47 | +## 1.4.4(2023-11-28) | |
| 48 | +增加说明 | |
| 49 | +## 1.4.3(2023-11-28) | |
| 50 | +增加主题配置 | |
| 51 | +## 1.4.2(2023-11-28) | |
| 52 | +增加异步加载时,子节点说明 | |
| 53 | +## 1.4.1(2023-11-27) | |
| 54 | +修复说明bug | |
| 55 | +## 1.4.0(2023-11-27) | |
| 56 | +next-tree 全面说明文档 | |
| 57 | +## 1.3.6(2023-11-27) | |
| 58 | +增加远程加载loadData,全面实现全功能覆盖 | |
| 59 | +## 1.3.5(2023-11-27) | |
| 60 | +增加title的定义 | |
| 61 | +## 1.3.4(2023-11-27) | |
| 62 | +增加title支持自定义定制 | |
| 63 | +## 1.3.3(2023-11-21) | |
| 64 | +增加搜索模式searchModel=depHighlight模式,从属高亮显示模式 | |
| 65 | +## 1.3.2(2023-11-20) | |
| 66 | +修复valueKey设置bug | |
| 67 | +## 1.3.1(2023-11-17) | |
| 68 | +增加说明文件,和demo | |
| 69 | +## 1.3.0(2023-11-17) | |
| 70 | +修复clear时不支持关联模式的设置 | |
| 71 | +## 1.2.9(2023-11-17) | |
| 72 | +增加checkStrictlyModel模式设置,强关联,和弱关联 | |
| 73 | +## 1.2.8(2023-11-16) | |
| 74 | +增加next-tree的辅助线模式 | |
| 75 | +## 1.2.7(2023-11-16) | |
| 76 | +优化next-tree | |
| 77 | +## 1.2.6(2023-11-16) | |
| 78 | +修复搜索时,隐藏未打开的数据 | |
| 79 | +## 1.2.5(2023-11-16) | |
| 80 | +修复搜索无法点击,和级联半选不生效问题 | |
| 81 | +## 1.2.4(2023-11-16) | |
| 82 | +更新新功能插件使用说明 | |
| 83 | +## 1.2.3(2023-11-16) | |
| 84 | +增加插槽模式,只是高ui要求定制 | |
| 85 | +## 1.2.2(2023-11-15) | |
| 86 | +修复checkStrictly配置下,子关联父的选择状态 | |
| 87 | +## 1.2.1(2023-11-15) | |
| 88 | +增加半选提示功能配置showHalfCheckedTips | |
| 89 | +## 1.2.0(2023-11-14) | |
| 90 | +修复disabled配置状态下,父子级联,不需要改变disabled设置项的选择状态 | |
| 91 | +## 1.1.9(2023-11-13) | |
| 92 | +增强大数据量体验交互,增加筛选搜索模式 | |
| 93 | +## 1.1.8(2023-11-13) | |
| 94 | +增加清除clear和取消cancel事件 | |
| 95 | +## 1.1.7(2023-11-08) | |
| 96 | +更新next-tree插件功能清单说明 | |
| 97 | +## 1.1.6(2023-11-07) | |
| 98 | +update说明文档 | |
| 99 | +## 1.1.5(2023-11-07) | |
| 100 | +update | |
| 101 | +## 1.1.4(2023-11-07) | |
| 102 | +更新readme.md说明 | |
| 103 | +## 1.1.3(2023-11-07) | |
| 104 | +更新说明demo | |
| 105 | +## 1.1.2(2023-11-07) | |
| 106 | +增加子节点按需渲染演示demo | |
| 107 | +## 1.1.1(2023-11-07) | |
| 108 | +增加清空功能 | |
| 109 | +## 1.1.0(2023-11-07) | |
| 110 | +增加子孙节点按需渲染,扩展本插件支持大数据量渲染; | |
| 111 | +## 1.0.9(2023-10-26) | |
| 112 | +增加文件说明 | |
| 113 | +## 1.0.8(2023-09-14) | |
| 114 | +增加禁用节点属性配置disabledKey | |
| 115 | +## 1.0.7(2023-09-06) | |
| 116 | +增加checkStrictly,实现父子节点关联 | |
| 117 | +## 1.0.6(2023-09-06) | |
| 118 | +更新vue2使用过程视图不更新的技术说明 | |
| 119 | +## 1.0.5(2023-09-06) | |
| 120 | +修复说明文档 | |
| 121 | +## 1.0.4(2023-06-19) | |
| 122 | +修改demo | |
| 123 | +## 1.0.3(2023-06-19) | |
| 124 | +更新vue2的使用demo | |
| 125 | +## 1.0.2(2023-06-19) | |
| 126 | +修复说明文档 | |
| 127 | + | |
| 128 | +## 1.0.1(2023-05-10) | |
| 129 | +更新说明文件 | |
| 130 | +## 1.0.0(2023-05-09) | |
| 131 | +初始化项目 | ... | ... |
garbage-removal/src/components/next-tree/readme/package.json
0 → 100644
| 1 | +{ | |
| 2 | + "id": "next-tree", | |
| 3 | + "displayName": "next-tree(超强树选择器、树组件、树插件、无限级联树、单选树、多选树、自定义样式树、树形选择器)", | |
| 4 | + "version": "1.6.7", | |
| 5 | + "description": "next-tree 弹窗树形选择器,支持多选,支持大数据, 无限级联,单选,父子级级联,远程/ajax加载,子节点增量/异步渲染,自定义样式定制,具名插槽等;支持h5/小程序/APP,全端通用", | |
| 6 | + "keywords": [ | |
| 7 | + "树选择", | |
| 8 | + "tree", | |
| 9 | + "弹窗树选择器", | |
| 10 | + "多选树", | |
| 11 | + "单选树" | |
| 12 | +], | |
| 13 | +"engines": { | |
| 14 | + }, | |
| 15 | +"dcloudext": { | |
| 16 | + "sale": { | |
| 17 | + "regular": { | |
| 18 | + "price": "0.00" | |
| 19 | + }, | |
| 20 | + "sourcecode": { | |
| 21 | + "price": "0.00" | |
| 22 | + } | |
| 23 | + }, | |
| 24 | + "contact": { | |
| 25 | + "qq": "" | |
| 26 | + }, | |
| 27 | + "declaration": { | |
| 28 | + "ads": "无", | |
| 29 | + "data": "修改版本说明", | |
| 30 | + "permissions": "无" | |
| 31 | + }, | |
| 32 | + "npmurl": "", | |
| 33 | + "type": "component-vue" | |
| 34 | + }, | |
| 35 | + "uni_modules": { | |
| 36 | + "dependencies": ["next-search-more"], | |
| 37 | + "encrypt": [], | |
| 38 | + "platforms": { | |
| 39 | + "cloud": { | |
| 40 | + "tcb": "y", | |
| 41 | + "aliyun": "y" | |
| 42 | + }, | |
| 43 | + "client": { | |
| 44 | + "Vue": { | |
| 45 | + "vue2": "y", | |
| 46 | + "vue3": "y" | |
| 47 | + }, | |
| 48 | + "App": { | |
| 49 | + "app-vue": "y", | |
| 50 | + "app-nvue": "u" | |
| 51 | + }, | |
| 52 | + "H5-mobile": { | |
| 53 | + "Safari": "y", | |
| 54 | + "Android Browser": "y", | |
| 55 | + "微信浏览器(Android)": "y", | |
| 56 | + "QQ浏览器(Android)": "y" | |
| 57 | + }, | |
| 58 | + "H5-pc": { | |
| 59 | + "Chrome": "y", | |
| 60 | + "IE": "n", | |
| 61 | + "Edge": "y", | |
| 62 | + "Firefox": "y", | |
| 63 | + "Safari": "u" | |
| 64 | + }, | |
| 65 | + "小程序": { | |
| 66 | + "微信": "y", | |
| 67 | + "阿里": "y", | |
| 68 | + "百度": "y", | |
| 69 | + "字节跳动": "u", | |
| 70 | + "QQ": "y", | |
| 71 | + "钉钉": "y", | |
| 72 | + "快手": "u", | |
| 73 | + "飞书": "u", | |
| 74 | + "京东": "u" | |
| 75 | + }, | |
| 76 | + "快应用": { | |
| 77 | + "华为": "u", | |
| 78 | + "联盟": "u" | |
| 79 | + } | |
| 80 | + } | |
| 81 | + } | |
| 82 | + } | |
| 83 | +} | |
| 0 | 84 | \ No newline at end of file | ... | ... |
garbage-removal/src/components/next-tree/readme/readme.md
0 → 100644
| 1 | + | |
| 2 | +## next-tree --下拉树 | |
| 3 | + | |
| 4 | +> 遇到问题或有建议可以加入QQ群(<font color=#f00>455948571</font>)反馈 | |
| 5 | +> 如果觉得组件不错,<font color=#f00>给五星鼓励鼓励</font>咯! | |
| 6 | + | |
| 7 | +## 亮点功能说明(打造你不得不用的好插件) | |
| 8 | + | |
| 9 | +### 本插件自1.5.0版本后支持一下功能 | |
| 10 | + | |
| 11 | + > 1.大数据量渲染(本插件智能判断,如果子孙集数据量大于50时,会响应等待渲染视图;) | |
| 12 | + > 2.子节点按需渲染(自动启用,无需配置) | |
| 13 | + > 3.父子级联选择设置 | |
| 14 | + > 4.单选多选设置 | |
| 15 | + > 5.父节点是否可选设置 | |
| 16 | + > 6.回显默认选中值 | |
| 17 | + > 7.不可选项disabled设置 | |
| 18 | + > 8.增强大数据量体验交互,增加筛选搜索模式 | |
| 19 | + > 9.增强样式定制,提供自定插槽,实现高要求样式定制 | |
| 20 | + > 10.增加辅助线模式,外观更加精美 | |
| 21 | + > 11.支持动态配置title | |
| 22 | + > 12.支持搜索模式searchModel=depHighlight模式,从属高亮显示模式 | |
| 23 | + > 13.支持异步加载子节点,ajax加载子节点 | |
| 24 | + > 14.增加可配置主题,自由定制插件主题颜色 | |
| 25 | + > 15.支持动态校验,可以进行提示控制校验 | |
| 26 | + > 16.支持页面模式,可以进行单页面展示 | |
| 27 | + > 17.支持半选提示状态显示 | |
| 28 | + | |
| 29 | +## 注意 | |
| 30 | + | |
| 31 | +### 作者不介意你对组件源码进行改造使用,为了开源更加高效,谢谢你的配合;为了节省不必要的沟通浪费,以下情况请不要再反馈给作者,请自行解决; | |
| 32 | +### 在这感各位的理解,我支持开源,但是作者时间有限;谢谢各位的配合;在这里期望我写的小小插件能为你提供便捷; | |
| 33 | + | |
| 34 | + > 1.如果你对源码进行了修改使用,请不需要对作者做任何的反馈,作者确实没有空陪你做技术分析解答; | |
| 35 | + > 2.如果你引入插件,连插件是否有正常被uniapp框架识别解析都不清楚,请你换个插件使用; | |
| 36 | + > 3.如果你引入插件,针对自己项目进行功能改造的,请自行仔细阅读源码并了解其原理,自行改造;这里作者不愿意浪费过多时间进行技术解答; | |
| 37 | + > 4.如果你不想进行全局加载next-tree,需要按需加载;next-tree中有相关依赖的组件,需要你自行在组件内部单独引入;依赖组件可以在package.json中找到; | |
| 38 | + > 5.理论上作者不再解决由于本地开发环境问题所导致的插件使用问题,请自行到uniapp官网学习解决; | |
| 39 | + | |
| 40 | +## 使用 | |
| 41 | + | |
| 42 | +>[从uniapp插件市场导入](https://ext.dcloud.net.cn/plugin?name=next-tree) | |
| 43 | + | |
| 44 | +## 关注作者其他开源 | |
| 45 | + | |
| 46 | +npm开源包:[npm](https://www.npmjs.com/~lixueshiaa); | |
| 47 | +github开源项目:[github](https://github.com/lixueshiaa); | |
| 48 | + | |
| 49 | + | |
| 50 | +```html | |
| 51 | +<template> | |
| 52 | + <view style="padding:10px;color: #333;font-weight: 500;"> | |
| 53 | + <view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view> | |
| 54 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button> | |
| 55 | + <view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view> | |
| 56 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button> | |
| 57 | + <view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view> | |
| 58 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button> | |
| 59 | + <view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view> | |
| 60 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button> | |
| 61 | + <view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view> | |
| 62 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button> | |
| 63 | + <view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view> | |
| 64 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button> | |
| 65 | + <!-- 异步加载demo --> | |
| 66 | + <view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view> | |
| 67 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button> | |
| 68 | + </view> | |
| 69 | + | |
| 70 | + <!-- 异步加载demo --> | |
| 71 | + <next-tree :selectParent="false" :checkStrictly="true" :multiple="true" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" /> | |
| 72 | + | |
| 73 | + <next-tree :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :multiple="multiple" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm"> | |
| 74 | + <!-- label插槽示意代码 --> | |
| 75 | + <!-- <template #label="{data: {id, label, iconSrc, prev, post}}"> | |
| 76 | + <view class="line-block"> | |
| 77 | + <image class="img" v-if="iconSrc" :src="iconSrc"></image> | |
| 78 | + <text space="nbsp" v-if="prev">{{prev}} </text><text>{{label}}</text><text space="nbsp" v-if="post"> {{post}}</text> | |
| 79 | + </view> | |
| 80 | + </template> --> | |
| 81 | + <!-- <template #topBar> | |
| 82 | + <view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view> | |
| 83 | + <view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;"> | |
| 84 | + <button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button> | |
| 85 | + <button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button> | |
| 86 | + <button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button> | |
| 87 | + </view> | |
| 88 | + </template> --> | |
| 89 | + </next-tree> | |
| 90 | +</template> | |
| 91 | +``` | |
| 92 | + | |
| 93 | +### vue3 + ts 使用 | |
| 94 | + | |
| 95 | +```ts | |
| 96 | +<script setup lang="ts"> | |
| 97 | +import { ref, unref } from 'vue' | |
| 98 | +import nextTree from '@/components/next-tree/next-tree.vue' | |
| 99 | + | |
| 100 | +const multiple = ref(false) | |
| 101 | +const selectParent = ref(false) | |
| 102 | +const nextTreeRef = ref() | |
| 103 | +const nextTreeAsyncRef = ref() | |
| 104 | +const activeId = ref('') | |
| 105 | + | |
| 106 | +const localData: any = { | |
| 107 | + 'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}], | |
| 108 | + 'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}], | |
| 109 | + 'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}], | |
| 110 | + 'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}], | |
| 111 | + 'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}], | |
| 112 | + 'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}] | |
| 113 | +} | |
| 114 | + | |
| 115 | +const checkStrictly = ref(false) | |
| 116 | +const asyncTreeData = ref([{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}]) | |
| 117 | +const treeData = ref([ | |
| 118 | + {id: '1', label: '北京'}, | |
| 119 | + {id: '2', label: '上海', children: [ | |
| 120 | + {id: '2-1', label: '上海-1'}, | |
| 121 | + {id: '2-2', label: '上海-2'}, | |
| 122 | + {id: '2-3', label: '上海-3'}, | |
| 123 | + ] }, | |
| 124 | + {id: '3', label: '广州', children: [ | |
| 125 | + {id: '3-1', label: '海珠区', children: [ | |
| 126 | + {id: '3-1-1', label: '海珠区-1'}, | |
| 127 | + {id: '3-1-2', label: '海珠区-2'}, | |
| 128 | + {id: '3-1-4', label: '海珠区-3'}, | |
| 129 | + {id: '3-1-5', label: '海珠区-4'}, | |
| 130 | + {id: '3-1-6', label: '海珠区-5'}, | |
| 131 | + {id: '3-1-7', label: '海珠区-6'}, | |
| 132 | + {id: '3-1-8', label: '海珠区-7'}, | |
| 133 | + {id: '3-1-9', label: '海珠区-8'}, | |
| 134 | + {id: '3-1-10', label: '海珠区-9'}, | |
| 135 | + {id: '3-1-11', label: '海珠区-10'}, | |
| 136 | + ]}, | |
| 137 | + {id: '3-2', label: '番禺区', children: [ | |
| 138 | + {id: '3-2-1', label: '番禺区-1'}, | |
| 139 | + {id: '3-2-2', label: '番禺区-2'}, | |
| 140 | + {id: '3-2-4', label: '番禺区-3'}, | |
| 141 | + {id: '3-2-5', label: '番禺区-4'}, | |
| 142 | + {id: '3-2-6', label: '番禺区-5'}, | |
| 143 | + {id: '3-2-7', label: '番禺区-6'}, | |
| 144 | + {id: '3-2-8', label: '番禺区-7'}, | |
| 145 | + {id: '3-2-9', label: '番禺区-8'}, | |
| 146 | + {id: '3-2-10', label: '番禺区-9'}, | |
| 147 | + {id: '3-2-11', label: '番禺区-10'}, | |
| 148 | + ]}, | |
| 149 | + {id: '3-3', label: '黄埔区', children: [ | |
| 150 | + {id: '3-3-1', label: '黄埔区-1'}, | |
| 151 | + {id: '3-3-2', label: '黄埔区-2'}, | |
| 152 | + {id: '3-3-3', label: '黄埔区-3'}, | |
| 153 | + {id: '3-3-4', label: '黄埔区-4'}, | |
| 154 | + {id: '3-3-5', label: '黄埔区-5'}, | |
| 155 | + {id: '3-3-6', label: '黄埔区-6'}, | |
| 156 | + {id: '3-3-7', label: '黄埔区-7'}, | |
| 157 | + {id: '3-3-8', label: '黄埔区-8'}, | |
| 158 | + {id: '3-3-9', label: '黄埔区-9'}, | |
| 159 | + {id: '3-3-10', label: '黄埔区-10'}, | |
| 160 | + {id: '3-3-12', label: '黄埔区-11'}, | |
| 161 | + {id: '3-3-13', label: '黄埔区-12'}, | |
| 162 | + {id: '3-3-13', label: '黄埔区-13'}, | |
| 163 | + {id: '3-3-14', label: '黄埔区-14'}, | |
| 164 | + {id: '3-3-15', label: '黄埔区-15'}, | |
| 165 | + {id: '3-3-16', label: '黄埔区-16'}, | |
| 166 | + {id: '3-3-17', label: '黄埔区-17'}, | |
| 167 | + {id: '3-3-18', label: '黄埔区-18'}, | |
| 168 | + {id: '3-3-19', label: '黄埔区-19'}, | |
| 169 | + {id: '3-3-20', label: '黄埔区-20'}, | |
| 170 | + {id: '3-3-21', label: '黄埔区-21'}, | |
| 171 | + {id: '3-3-22', label: '黄埔区-22'}, | |
| 172 | + {id: '3-3-23', label: '黄埔区-23'}, | |
| 173 | + {id: '3-3-24', label: '黄埔区-24'}, | |
| 174 | + {id: '3-3-25', label: '黄埔区-25'}, | |
| 175 | + {id: '3-3-26', label: '黄埔区-26'}, | |
| 176 | + {id: '3-3-27', label: '黄埔区-27'}, | |
| 177 | + {id: '3-3-28', label: '黄埔区-28'}, | |
| 178 | + {id: '3-3-29', label: '黄埔区-29'}, | |
| 179 | + {id: '3-3-30', label: '黄埔区-30'}, | |
| 180 | + {id: '3-3-31', label: '黄埔区-31'}, | |
| 181 | + {id: '3-3-32', label: '黄埔区-32'}, | |
| 182 | + {id: '3-3-33', label: '黄埔区-33'}, | |
| 183 | + {id: '3-3-34', label: '黄埔区-34'}, | |
| 184 | + {id: '3-3-35', label: '黄埔区-35'}, | |
| 185 | + {id: '3-3-36', label: '黄埔区-36'}, | |
| 186 | + | |
| 187 | + ]}, | |
| 188 | + ], | |
| 189 | + }]) | |
| 190 | +function getTitle(checked) { | |
| 191 | + return `已选:${checked.length}项` | |
| 192 | +} | |
| 193 | +function itemclick (_multiple, _selectParent, _checkStrictly = false) { | |
| 194 | + multiple.value = _multiple | |
| 195 | + selectParent.value = _selectParent | |
| 196 | + checkStrictly.value = _checkStrictly | |
| 197 | + unref(nextTreeRef).showTree = true | |
| 198 | +} | |
| 199 | +function checkedFunc(id) { | |
| 200 | + if(unref(activeId) === id) { | |
| 201 | + activeId.value = ''; | |
| 202 | + unref(nextTreeRef).checkedFunc(id, false) | |
| 203 | + } else { | |
| 204 | + activeId.value = id; | |
| 205 | + unref(nextTreeRef).checkedFunc(id) | |
| 206 | + } | |
| 207 | +} | |
| 208 | +function changeVerify(current, chooseList) { | |
| 209 | + // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 | |
| 210 | + // 如果函数体不做return返回值,即验证通过,控件正常处理业务 | |
| 211 | + console.log('当前变化的数据', current) | |
| 212 | + console.log('已选择的数据', chooseList) | |
| 213 | + if(chooseList && chooseList.length > 4) { | |
| 214 | + | |
| 215 | + return '最多可以选择4个节点' | |
| 216 | + } | |
| 217 | +} | |
| 218 | +function openTree() { | |
| 219 | + unref(nextTreeAsyncRef).showTree = true | |
| 220 | +} | |
| 221 | +function echoDefault () { | |
| 222 | + const selectIds = ['2-1','3-3-35'] | |
| 223 | + checkedTreeData(unref(treeData), selectIds) | |
| 224 | + console.log('treeData的数据:', unref(treeData)) | |
| 225 | + multiple.value = true | |
| 226 | + unref(nextTreeRef).showTree = true | |
| 227 | +} | |
| 228 | +function loadData(nodeItem) { | |
| 229 | + // 同步实现的代码处理方式 | |
| 230 | + // 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []} | |
| 231 | + | |
| 232 | + // if(nodeItem && localData[nodeItem.id]) { | |
| 233 | + // return localData[nodeItem.id] | |
| 234 | + // } else { | |
| 235 | + // return [] | |
| 236 | + // } | |
| 237 | + | |
| 238 | + // 异步的代码实现方式 | |
| 239 | + // 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []} | |
| 240 | + | |
| 241 | + return new Promise((resolve, reject) => { | |
| 242 | + setTimeout(() => { | |
| 243 | + if(nodeItem && localData[nodeItem.id]) { | |
| 244 | + return resolve(localData[nodeItem.id]) | |
| 245 | + } else { | |
| 246 | + return resolve([]) | |
| 247 | + } | |
| 248 | + }, 1000) | |
| 249 | + }) | |
| 250 | +} | |
| 251 | +function checkedTreeData (treeData, selectIds) { | |
| 252 | + treeData.map(item => { | |
| 253 | + if (selectIds.indexOf(item.id) !== -1) { | |
| 254 | + item.checked = true | |
| 255 | + } else { | |
| 256 | + item.checked = false | |
| 257 | + } | |
| 258 | + if (item.children && item.children.length) { | |
| 259 | + checkedTreeData(item.children, selectIds) | |
| 260 | + } | |
| 261 | + }) | |
| 262 | +} | |
| 263 | +function oncancel() { | |
| 264 | + // 清除treeData的选中状态 | |
| 265 | + checkedTreeData(unref(treeData), []) | |
| 266 | +} | |
| 267 | +function onconfirm(list) { | |
| 268 | + console.log('选中项的数量列表list:', list) | |
| 269 | +} | |
| 270 | +</script> | |
| 271 | +<style lang="scss"> | |
| 272 | + .line-block { | |
| 273 | + display: flex; | |
| 274 | + flex-direction: row; | |
| 275 | + justify-content: flex-start; | |
| 276 | + align-items: center; | |
| 277 | + .img { | |
| 278 | + width: 40rpx; | |
| 279 | + height: 40rpx; | |
| 280 | + border-radius: 10rpx; | |
| 281 | + margin: 0 20rpx; | |
| 282 | + } | |
| 283 | + } | |
| 284 | +</style> | |
| 285 | + | |
| 286 | +``` | |
| 287 | + | |
| 288 | +### vue2 使用 | |
| 289 | +```html | |
| 290 | +<template> | |
| 291 | + <view> | |
| 292 | + <view style="padding:10px;color: #333;font-weight: 500;"> | |
| 293 | + <view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view> | |
| 294 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button> | |
| 295 | + <view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view> | |
| 296 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button> | |
| 297 | + <view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view> | |
| 298 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button> | |
| 299 | + <view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view> | |
| 300 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button> | |
| 301 | + <view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view> | |
| 302 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button> | |
| 303 | + <view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view> | |
| 304 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button> | |
| 305 | + <!-- 异步加载demo --> | |
| 306 | + <view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view> | |
| 307 | + <button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button> | |
| 308 | + </view> | |
| 309 | + <!-- 异步加载demo --> | |
| 310 | + <next-tree :selectParent="false" :checkStrictly="true" :multiple="true" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" /> | |
| 311 | + | |
| 312 | + <next-tree :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :multiple="multiple" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm"> | |
| 313 | + <!-- label插槽示意代码 --> | |
| 314 | + <!-- <template v-slot:label="{data: {id, label, iconSrc, prev, post}}"> | |
| 315 | + <view class="line-block"> | |
| 316 | + <image class="img" v-if="iconSrc" :src="iconSrc"></image> | |
| 317 | + <text space="nbsp" v-if="prev">{{prev}} </text><text>{{label}}</text><text space="nbsp" v-if="post"> {{post}}</text> | |
| 318 | + </view> | |
| 319 | + </template> --> | |
| 320 | + <!-- <template #topBar> | |
| 321 | + <view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view> | |
| 322 | + <view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;"> | |
| 323 | + <button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button> | |
| 324 | + <button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button> | |
| 325 | + <button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button> | |
| 326 | + </view> | |
| 327 | + </template> --> | |
| 328 | + </next-tree> | |
| 329 | + </view> | |
| 330 | +</template> | |
| 331 | +``` | |
| 332 | + | |
| 333 | +```js | |
| 334 | +<script> | |
| 335 | +let self = null; | |
| 336 | +export default { | |
| 337 | + data () { | |
| 338 | + return { | |
| 339 | + multiple: false, | |
| 340 | + selectParent: false, | |
| 341 | + checkStrictly: false, | |
| 342 | + activeId: '', | |
| 343 | + localData:{ | |
| 344 | + 'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}], | |
| 345 | + 'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}], | |
| 346 | + 'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}], | |
| 347 | + 'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}], | |
| 348 | + 'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}], | |
| 349 | + 'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}] | |
| 350 | + }, | |
| 351 | + asyncTreeData: [{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}], | |
| 352 | + treeData: [ | |
| 353 | + {id: '1', label: '北京', checked: false}, | |
| 354 | + {id: '2', label: '上海', checked: false, children: [ | |
| 355 | + {id: '2-1', label: '上海-1', checked: false}, | |
| 356 | + {id: '2-2', label: '上海-2', checked: false}, | |
| 357 | + {id: '2-3', label: '上海-3', checked: false}, | |
| 358 | + ] }, | |
| 359 | + {id: '3', label: '广州', children: [ | |
| 360 | + {id: '3-1', label: '海珠区', checked: false, children: [ | |
| 361 | + {id: '3-1-1', label: '海珠区-1', checked: false, disabled: true}, | |
| 362 | + {id: '3-1-2', label: '海珠区-2', checked: false}, | |
| 363 | + {id: '3-1-4', label: '海珠区-3', checked: false}, | |
| 364 | + {id: '3-1-5', label: '海珠区-4', checked: false}, | |
| 365 | + {id: '3-1-6', label: '海珠区-5', checked: false}, | |
| 366 | + {id: '3-1-7', label: '海珠区-6', checked: false}, | |
| 367 | + {id: '3-1-8', label: '海珠区-7', checked: false}, | |
| 368 | + {id: '3-1-9', label: '海珠区-8', checked: false}, | |
| 369 | + {id: '3-1-10', label: '海珠区-9', checked: false}, | |
| 370 | + {id: '3-1-11', label: '海珠区-10', checked: false}, | |
| 371 | + ]}, | |
| 372 | + {id: '3-2', label: '番禺区', checked: false, children: [ | |
| 373 | + {id: '3-2-1', label: '番禺区-1', checked: false}, | |
| 374 | + {id: '3-2-2', label: '番禺区-2', checked: false}, | |
| 375 | + {id: '3-2-4', label: '番禺区-3', checked: false}, | |
| 376 | + {id: '3-2-5', label: '番禺区-4', checked: false}, | |
| 377 | + {id: '3-2-6', label: '番禺区-5', checked: false}, | |
| 378 | + {id: '3-2-7', label: '番禺区-6', checked: false}, | |
| 379 | + {id: '3-2-8', label: '番禺区-7', checked: false}, | |
| 380 | + {id: '3-2-9', label: '番禺区-8', checked: false}, | |
| 381 | + {id: '3-2-10', label: '番禺区-9', checked: false}, | |
| 382 | + {id: '3-2-11', label: '番禺区-10', checked: false}, | |
| 383 | + ]}, | |
| 384 | + {id: '3-3', label: '黄埔区', checked: false, children: [ | |
| 385 | + {id: '3-3-1', label: '黄埔区-1', checked: false}, | |
| 386 | + {id: '3-3-2', label: '黄埔区-2', checked: false}, | |
| 387 | + {id: '3-3-3', label: '黄埔区-3', checked: false}, | |
| 388 | + {id: '3-3-4', label: '黄埔区-4', checked: false}, | |
| 389 | + {id: '3-3-5', label: '黄埔区-5', checked: false}, | |
| 390 | + {id: '3-3-6', label: '黄埔区-6', checked: false}, | |
| 391 | + {id: '3-3-7', label: '黄埔区-7', checked: false}, | |
| 392 | + {id: '3-3-8', label: '黄埔区-8', checked: false}, | |
| 393 | + {id: '3-3-9', label: '黄埔区-9', checked: false}, | |
| 394 | + {id: '3-3-10', label: '黄埔区-10', checked: false}, | |
| 395 | + {id: '3-3-12', label: '黄埔区-11', checked: false}, | |
| 396 | + {id: '3-3-13', label: '黄埔区-12', checked: false}, | |
| 397 | + {id: '3-3-13', label: '黄埔区-13', checked: false}, | |
| 398 | + {id: '3-3-14', label: '黄埔区-14', checked: false}, | |
| 399 | + {id: '3-3-15', label: '黄埔区-15', checked: false}, | |
| 400 | + {id: '3-3-16', label: '黄埔区-16', checked: false}, | |
| 401 | + {id: '3-3-17', label: '黄埔区-17', checked: false}, | |
| 402 | + {id: '3-3-18', label: '黄埔区-18', checked: false}, | |
| 403 | + {id: '3-3-19', label: '黄埔区-19', checked: false}, | |
| 404 | + {id: '3-3-20', label: '黄埔区-20', checked: false}, | |
| 405 | + {id: '3-3-21', label: '黄埔区-21', checked: false}, | |
| 406 | + {id: '3-3-22', label: '黄埔区-22', checked: false}, | |
| 407 | + {id: '3-3-23', label: '黄埔区-23', checked: false}, | |
| 408 | + {id: '3-3-24', label: '黄埔区-24', checked: false}, | |
| 409 | + {id: '3-3-25', label: '黄埔区-25', checked: false}, | |
| 410 | + {id: '3-3-26', label: '黄埔区-26', checked: false}, | |
| 411 | + {id: '3-3-27', label: '黄埔区-27', checked: false}, | |
| 412 | + {id: '3-3-28', label: '黄埔区-28', checked: false}, | |
| 413 | + {id: '3-3-29', label: '黄埔区-29', checked: false}, | |
| 414 | + {id: '3-3-30', label: '黄埔区-30', checked: false}, | |
| 415 | + {id: '3-3-31', label: '黄埔区-31', checked: false}, | |
| 416 | + {id: '3-3-32', label: '黄埔区-32', checked: false}, | |
| 417 | + {id: '3-3-33', label: '黄埔区-33', checked: false}, | |
| 418 | + {id: '3-3-34', label: '黄埔区-34', checked: false}, | |
| 419 | + {id: '3-3-35', label: '黄埔区-35', checked: false}, | |
| 420 | + {id: '3-3-36', label: '黄埔区-36', checked: false}, | |
| 421 | + ]}, | |
| 422 | + ], | |
| 423 | + }] | |
| 424 | + } | |
| 425 | + }, | |
| 426 | + methods: { | |
| 427 | + openTree: function() { | |
| 428 | + this.$refs.nextTreeAsyncRef.showTree = true | |
| 429 | + }, | |
| 430 | + changeVerify: function(current, chooseList) { | |
| 431 | + // 注意:返回非空字符串会阻止原有行为,并提示返回的字符串 | |
| 432 | + // 如果函数体不做return返回值,即验证通过,控件正常处理业务 | |
| 433 | + console.log('当前变化的数据', current) | |
| 434 | + console.log('已选择的数据', chooseList) | |
| 435 | + if(chooseList && chooseList.length > 4) { | |
| 436 | + | |
| 437 | + return '最多可以选择4个节点' | |
| 438 | + } | |
| 439 | + }, | |
| 440 | + checkedFunc: function(id) { | |
| 441 | + if(this.activeId === id) { | |
| 442 | + this.activeId = ''; | |
| 443 | + this.$refs.nextTreeRef.checkedFunc(id, false) | |
| 444 | + } else { | |
| 445 | + this.activeId = id; | |
| 446 | + this.$refs.nextTreeRef.checkedFunc(id) | |
| 447 | + } | |
| 448 | + }, | |
| 449 | + loadData(nodeItem) { | |
| 450 | + // 同步实现的代码处理方式 可以返回单个子节点的集合也可以返回子孙节点的集合 | |
| 451 | + // 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []} | |
| 452 | + | |
| 453 | + // if(nodeItem && this.localData[nodeItem.id]) { | |
| 454 | + // return this.localData[nodeItem.id] | |
| 455 | + // } else { | |
| 456 | + // return [] | |
| 457 | + // } | |
| 458 | + // 异步的代码实现方式 可以返回单个子节点的集合也可以返回子孙节点的集合 | |
| 459 | + // 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []} | |
| 460 | + return new Promise((resolve, reject) => { | |
| 461 | + setTimeout(() => { | |
| 462 | + if(nodeItem && self.localData[nodeItem.id]) { | |
| 463 | + return resolve(self.localData[nodeItem.id]) | |
| 464 | + } else { | |
| 465 | + return resolve([]) | |
| 466 | + } | |
| 467 | + }, 1000) | |
| 468 | + }) | |
| 469 | + }, | |
| 470 | + getTitle: function(checked) { | |
| 471 | + return `已选:${checked.length}项` | |
| 472 | + }, | |
| 473 | + echoDefault: function() { | |
| 474 | + const selectIds = ['2-1','3-3-35'] | |
| 475 | + this.checkedTreeData(this.treeData, selectIds) | |
| 476 | + console.log('treeData的数据:', this.treeData) | |
| 477 | + this.multiple = true | |
| 478 | + this.$refs.nextTreeRef.showTree = true | |
| 479 | + }, | |
| 480 | + itemclick: function(_multiple, _selectParent, _checkStrictly = false) { | |
| 481 | + this.multiple = _multiple | |
| 482 | + this.selectParent = _selectParent | |
| 483 | + this.checkStrictly = _checkStrictly | |
| 484 | + this.$refs.nextTreeRef.showTree = true | |
| 485 | + }, | |
| 486 | + checkedTreeData: function(treeData, selectIds) { | |
| 487 | + // 注意 vue2当数据深嵌套时,如果没有在treeData里面初始化checked属性,那在改变数据的时候直接将checked属性赋值为true,这时候ui界面有可能不会更新, | |
| 488 | + // 这时候建议使用this.$set去更新checked属性值,或者在初始化this.treeData的时候初始化checked属性 | |
| 489 | + (treeData || []).map(item => { | |
| 490 | + if (selectIds.indexOf(item.id) !== -1) { | |
| 491 | + item.checked = true | |
| 492 | + } else { | |
| 493 | + item.checked = false | |
| 494 | + } | |
| 495 | + if (item.children && item.children.length) { | |
| 496 | + this.checkedTreeData(item.children, selectIds) | |
| 497 | + } | |
| 498 | + }) | |
| 499 | + }, | |
| 500 | + onconfirm: function(list) { | |
| 501 | + console.log('选中项的数量列表list:', list) | |
| 502 | + }, | |
| 503 | + oncancel: function() { | |
| 504 | + // 清除treeData的选中状态 | |
| 505 | + this.checkedTreeData(this.treeData, []) | |
| 506 | + } | |
| 507 | + }, | |
| 508 | + created() { | |
| 509 | + self = this | |
| 510 | + } | |
| 511 | +} | |
| 512 | +</script> | |
| 513 | +<style lang="scss"> | |
| 514 | + .line-block { | |
| 515 | + display: flex; | |
| 516 | + flex-direction: row; | |
| 517 | + justify-content: flex-start; | |
| 518 | + align-items: center; | |
| 519 | + .img { | |
| 520 | + width: 40rpx; | |
| 521 | + height: 40rpx; | |
| 522 | + border-radius: 10rpx; | |
| 523 | + margin: 0 20rpx; | |
| 524 | + } | |
| 525 | + } | |
| 526 | +</style> | |
| 527 | + | |
| 528 | +``` | |
| 529 | + | |
| 530 | +### 个性化自定义样式渲染 | |
| 531 | + | |
| 532 | +如果你的需求对样式需求比较高,请使用插槽模式渲染,本组件提供label插槽供你自定义定制; | |
| 533 | + | |
| 534 | +```js | |
| 535 | +<script> | |
| 536 | +// 提供参考一组自定义渲染数据demo,treeData如下; | |
| 537 | +const treeData = [ | |
| 538 | + {id: '1', label: '北京', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/03/fg/hj.jpg%21/fh/300', children: [ | |
| 539 | + {id: '1-3-3-1', label: '北京区-1', prev: '前置-'}, | |
| 540 | + {id: '1-3-3-2', label: '北京区-2', post: '-后置'}, | |
| 541 | + {id: '1-3-3-3', label: '北京区-3', post: '-后置', prev: '前置-'}, | |
| 542 | + {id: '1-3-3-4', label: '北京区-4'}, | |
| 543 | + {id: '1-3-3-5', label: '北京区-5'}, | |
| 544 | + {id: '1-3-3-6', label: '北京区-6'}, | |
| 545 | + {id: '1-3-3-7', label: '北京区-7'}, | |
| 546 | + {id: '1-3-3-8', label: '北京区-8'}, | |
| 547 | + {id: '1-3-3-9', label: '北京区-9'}, | |
| 548 | + {id: '1-3-3-10', label: '北京区-10'}, | |
| 549 | + {id: '1-3-3-12', label: '北京区-11'}, | |
| 550 | + {id: '1-3-3-13', label: '北京区-12'}, | |
| 551 | + {id: '1-3-3-13', label: '北京区-13'}, | |
| 552 | + {id: '1-3-3-14', label: '北京区-14'}, | |
| 553 | + {id: '1-3-3-15', label: '北京区-15'}, | |
| 554 | + {id: '1-3-3-16', label: '北京区-16'}, | |
| 555 | + {id: '1-3-3-17', label: '北京区-17'}, | |
| 556 | + {id: '1-3-3-18', label: '北京区-18'}, | |
| 557 | + {id: '1-3-3-19', label: '北京区-19'}, | |
| 558 | + {id: '1-3-3-20', label: '北京区-20'}, | |
| 559 | + {id: '1-3-3-21', label: '北京区-21'}, | |
| 560 | + {id: '1-3-3-22', label: '北京区-22'}, | |
| 561 | + {id: '1-3-3-23', label: '北京区-23'}, | |
| 562 | + {id: '1-3-3-24', label: '北京区-24'}, | |
| 563 | + {id: '1-3-3-25', label: '北京区-25'}, | |
| 564 | + {id: '1-3-3-26', label: '北京区-26'}, | |
| 565 | + {id: '1-3-3-27', label: '北京区-27'}, | |
| 566 | + {id: '1-3-3-28', label: '北京区-28'}, | |
| 567 | + {id: '1-3-3-29', label: '北京区-29'}, | |
| 568 | + {id: '1-1-3-3-30', label: '北京区-30'}, | |
| 569 | + {id: '1-3-3-31', label: '北京区-31'}, | |
| 570 | + {id: '1-3-3-32', label: '北京区-32'}, | |
| 571 | + {id: '1-3-3-33', label: '北京区-33'}, | |
| 572 | + {id: '1-3-3-34', label: '北京区-34'}, | |
| 573 | + {id: '1-3-3-35', label: '北京区-35'}, | |
| 574 | + {id: '1-3-3-36', label: '北京区-36'}, | |
| 575 | + {id: '1-3-3-37', label: '北京区-37'}, | |
| 576 | + {id: '1-3-3-38', label: '北京区-38'}, | |
| 577 | + {id: '1-3-3-39', label: '北京区-39'}, | |
| 578 | + {id: '1-3-3-40', label: '北京区-40'}, | |
| 579 | + {id: '1-3-3-41', label: '北京区-41'}, | |
| 580 | + {id: '1-3-3-42', label: '北京区-42'}, | |
| 581 | + {id: '1-3-3-43', label: '北京区-43'}, | |
| 582 | + {id: '1-3-3-44', label: '北京区-44'}, | |
| 583 | + {id: '1-3-3-45', label: '北京区-45'}, | |
| 584 | + {id: '1-3-3-46', label: '北京区-46'}, | |
| 585 | + {id: '1-3-3-47', label: '北京区-47'}, | |
| 586 | + {id: '1-3-3-48', label: '北京区-48'}, | |
| 587 | + {id: '1-3-3-49', label: '北京区-49'}, | |
| 588 | + {id: '1-3-3-50', label: '北京区-50'}, | |
| 589 | + {id: '1-3-3-51', label: '北京区-51'}, | |
| 590 | + {id: '1-3-3-52', label: '北京区-52'}, | |
| 591 | + {id: '1-3-3-53', label: '北京区-53'}, | |
| 592 | + {id: '1-3-3-54', label: '北京区-54'}, | |
| 593 | + ]}, | |
| 594 | + {id: '2', label: '上海', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/0g/hb/tc.jpg%21/fh/300', children: [ | |
| 595 | + {id: '2-1', label: '上海-1', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'}, | |
| 596 | + {id: '2-2', label: '上海-2', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'}, | |
| 597 | + {id: '2-3', label: '上海-3', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'}, | |
| 598 | + ] }, | |
| 599 | + {id: '3', label: '广州', prev: 'PonderNext-', iconSrc: 'https://storage-public.zhaopin.cn/user/avatar/1589350028141684980/d00a1afa-e3ec-40a5-a68e-aef1f684b189.jpg', children: [ | |
| 600 | + {id: '3-1', label: '海珠区', iconSrc: 'https://img95.699pic.com/xsj/0u/f3/5h.jpg%21/fh/300', children: [ | |
| 601 | + {id: '3-1-1', label: '海珠区-1', disabled: true}, | |
| 602 | + {id: '3-1-2', label: '海珠区-2', post: '-后置', prev: '前置-'}, | |
| 603 | + {id: '3-1-4', label: '海珠区-3', post: '-后置',}, | |
| 604 | + {id: '3-1-5', label: '海珠区-4'}, | |
| 605 | + {id: '3-1-6', label: '海珠区-5'}, | |
| 606 | + {id: '3-1-7', label: '海珠区-6'}, | |
| 607 | + {id: '3-1-8', label: '海珠区-7', post: '-后置',}, | |
| 608 | + {id: '3-1-9', label: '海珠区-8'}, | |
| 609 | + {id: '3-1-10', label: '海珠区-9'}, | |
| 610 | + {id: '3-1-11', label: '海珠区-10'}, | |
| 611 | + {id: '3-1-1', label: '海珠区-11', disabled: true}, | |
| 612 | + {id: '3-1-2', label: '海珠区-12'}, | |
| 613 | + {id: '3-1-4', label: '海珠区-13'}, | |
| 614 | + {id: '3-1-5', label: '海珠区-14'}, | |
| 615 | + {id: '3-1-6', label: '海珠区-15'}, | |
| 616 | + {id: '3-1-7', label: '海珠区-16'}, | |
| 617 | + {id: '3-1-8', label: '海珠区-17'}, | |
| 618 | + {id: '3-1-9', label: '海珠区-18'}, | |
| 619 | + {id: '3-1-10', label: '海珠区-19', prev: '前置-'}, | |
| 620 | + {id: '3-1-11', label: '海珠区-20'}, | |
| 621 | + {id: '3-1-1', label: '海珠区-21', disabled: true}, | |
| 622 | + {id: '3-1-2', label: '海珠区-22'}, | |
| 623 | + {id: '3-1-4', label: '海珠区-23'}, | |
| 624 | + {id: '3-1-5', label: '海珠区-24'}, | |
| 625 | + {id: '3-1-6', label: '海珠区-25'}, | |
| 626 | + {id: '3-1-7', label: '海珠区-26'}, | |
| 627 | + {id: '3-1-8', label: '海珠区-27'}, | |
| 628 | + {id: '3-1-9', label: '海珠区-28'}, | |
| 629 | + {id: '3-1-10', label: '海珠区-29'}, | |
| 630 | + {id: '3-1-11', label: '海珠区-30'}, | |
| 631 | + {id: '3-1-1', label: '海珠区-31', disabled: true}, | |
| 632 | + {id: '3-1-2', label: '海珠区-32'}, | |
| 633 | + {id: '3-1-4', label: '海珠区-33'}, | |
| 634 | + {id: '3-1-5', label: '海珠区-34'}, | |
| 635 | + {id: '3-1-6', label: '海珠区-35'}, | |
| 636 | + {id: '3-1-7', label: '海珠区-36'}, | |
| 637 | + {id: '3-1-8', label: '海珠区-37'}, | |
| 638 | + {id: '3-1-9', label: '海珠区-38'}, | |
| 639 | + {id: '3-1-10', label: '海珠区-39'}, | |
| 640 | + {id: '3-1-11', label: '海珠区-40'}, | |
| 641 | + {id: '3-1-1', label: '海珠区-41', disabled: true}, | |
| 642 | + {id: '3-1-2', label: '海珠区-42'}, | |
| 643 | + {id: '3-1-4', label: '海珠区-43'}, | |
| 644 | + {id: '3-1-5', label: '海珠区-44'}, | |
| 645 | + {id: '3-1-6', label: '海珠区-45'}, | |
| 646 | + {id: '3-1-7', label: '海珠区-46'}, | |
| 647 | + {id: '3-1-8', label: '海珠区-47'}, | |
| 648 | + {id: '3-1-9', label: '海珠区-48'}, | |
| 649 | + {id: '3-1-10', label: '海珠区-49'}, | |
| 650 | + {id: '3-1-11', label: '海珠区-50'}, | |
| 651 | + {id: '3-1-11', label: '海珠区-51'}, | |
| 652 | + ]}, | |
| 653 | + {id: '3-2', label: '番禺区', iconSrc: 'https://img1.baidu.com/it/u=931648192,3196263841&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285', disabled: true, checked: true, children: [ | |
| 654 | + {id: '3-2-1', label: '番禺区-1'}, | |
| 655 | + {id: '3-2-2', label: '番禺区-2'}, | |
| 656 | + {id: '3-2-4', label: '番禺区-3'}, | |
| 657 | + {id: '3-2-5', label: '番禺区-4'}, | |
| 658 | + {id: '3-2-6', label: '番禺区-5'}, | |
| 659 | + {id: '3-2-7', label: '番禺区-6'}, | |
| 660 | + {id: '3-2-8', label: '番禺区-7'}, | |
| 661 | + {id: '3-2-9', label: '番禺区-8'}, | |
| 662 | + {id: '3-2-10', label: '番禺区-9'}, | |
| 663 | + {id: '3-2-11', label: '番禺区-10'}, | |
| 664 | + ]}, | |
| 665 | + {id: '3-3', label: '黄埔区', iconSrc: 'https://img.jiaoyubao.cn/43423/20210423113959473-20210423114005024.jpeg', children: [ | |
| 666 | + {id: '3-3-1', label: '黄埔区-1'}, | |
| 667 | + {id: '3-3-2', label: '黄埔区-2'}, | |
| 668 | + {id: '3-3-3', label: '黄埔区-3'}, | |
| 669 | + {id: '3-3-4', label: '黄埔区-4'}, | |
| 670 | + {id: '3-3-5', label: '黄埔区-5'}, | |
| 671 | + {id: '3-3-6', label: '黄埔区-6'}, | |
| 672 | + {id: '3-3-7', label: '黄埔区-7'}, | |
| 673 | + {id: '3-3-8', label: '黄埔区-8'}, | |
| 674 | + {id: '3-3-9', label: '黄埔区-9'}, | |
| 675 | + {id: '3-3-10', label: '黄埔区-10'}, | |
| 676 | + {id: '3-3-12', label: '黄埔区-11'}, | |
| 677 | + {id: '3-3-13', label: '黄埔区-12'}, | |
| 678 | + {id: '3-3-13', label: '黄埔区-13'}, | |
| 679 | + {id: '3-3-14', label: '黄埔区-14'}, | |
| 680 | + {id: '3-3-15', label: '黄埔区-15'}, | |
| 681 | + {id: '3-3-16', label: '黄埔区-16'}, | |
| 682 | + {id: '3-3-17', label: '黄埔区-17'}, | |
| 683 | + {id: '3-3-18', label: '黄埔区-18'}, | |
| 684 | + {id: '3-3-19', label: '黄埔区-19'}, | |
| 685 | + {id: '3-3-20', label: '黄埔区-20'}, | |
| 686 | + {id: '3-3-21', label: '黄埔区-21'}, | |
| 687 | + {id: '3-3-22', label: '黄埔区-22'}, | |
| 688 | + {id: '3-3-23', label: '黄埔区-23'}, | |
| 689 | + {id: '3-3-24', label: '黄埔区-24'}, | |
| 690 | + {id: '3-3-25', label: '黄埔区-25'}, | |
| 691 | + {id: '3-3-26', label: '黄埔区-26'}, | |
| 692 | + {id: '3-3-27', label: '黄埔区-27'}, | |
| 693 | + {id: '3-3-28', label: '黄埔区-28'}, | |
| 694 | + {id: '3-3-29', label: '黄埔区-29'}, | |
| 695 | + {id: '3-3-30', label: '黄埔区-30'}, | |
| 696 | + {id: '3-3-31', label: '黄埔区-31'}, | |
| 697 | + {id: '3-3-32', label: '黄埔区-32'}, | |
| 698 | + {id: '3-3-33', label: '黄埔区-33'}, | |
| 699 | + {id: '3-3-34', label: '黄埔区-34'}, | |
| 700 | + {id: '3-3-35', label: '黄埔区-35'}, | |
| 701 | + {id: '3-3-36', label: '黄埔区-36'}, | |
| 702 | + {id: '3-3-37', label: '黄埔区-37'}, | |
| 703 | + {id: '3-3-38', label: '黄埔区-38'}, | |
| 704 | + {id: '3-3-39', label: '黄埔区-39'}, | |
| 705 | + {id: '3-3-40', label: '黄埔区-40'}, | |
| 706 | + {id: '3-3-41', label: '黄埔区-41'}, | |
| 707 | + {id: '3-3-42', label: '黄埔区-42'}, | |
| 708 | + {id: '3-3-43', label: '黄埔区-43'}, | |
| 709 | + {id: '3-3-44', label: '黄埔区-44'}, | |
| 710 | + {id: '3-3-45', label: '黄埔区-45'}, | |
| 711 | + {id: '3-3-46', label: '黄埔区-46'}, | |
| 712 | + {id: '3-3-47', label: '黄埔区-47'}, | |
| 713 | + {id: '3-3-48', label: '黄埔区-48'}, | |
| 714 | + {id: '3-3-49', label: '黄埔区-49'}, | |
| 715 | + {id: '3-3-50', label: '黄埔区-50'}, | |
| 716 | + {id: '3-3-51', label: '黄埔区-51'}, | |
| 717 | + {id: '3-3-52', label: '黄埔区-52'}, | |
| 718 | + {id: '3-3-53', label: '黄埔区-53'}, | |
| 719 | + {id: '3-3-54', label: '黄埔区-54'}, | |
| 720 | + ]}, | |
| 721 | + ], | |
| 722 | + }] | |
| 723 | +</script> | |
| 724 | +``` | |
| 725 | + | |
| 726 | +### 预览 | |
| 727 | +### | |
| 728 | +*** | |
| 729 | + | |
| 730 | +| 功能预览 | 父子级关联演示 | 全面支持大数据量,子孙节点ui按需渲染(按需渲染数据) | | |
| 731 | +| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: | | |
| 732 | +|  |  |  | | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | +| 增强控件交互能力,增加筛选search模式,全面支持大数据量交互 | 超强的样式定制能力,满足你高精美组件的需求 | 打开精美的辅助线模式,让你的控件更加友好 | | |
| 737 | +| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: | | |
| 738 | +|  |  |  | | |
| 739 | + | |
| 740 | + | |
| 741 | +| 增加搜索模式searchModel=depHighlight模式,从属高亮显示模式 | 支持异步加载子节点,子树集,ajax远程加载数据等 | 支持不同主题的切换,ui定制更简单 | | |
| 742 | +| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: | | |
| 743 | +|  |  |  | | |
| 744 | + | |
| 745 | +| 增加验证函数和topBar插槽使得更加容易和组件进行交互 | 增加页面模式,支持整页ui展示模式 | | |
| 746 | +| :------------------------------------------------------------------: | :------------------------------------------------------------------: | | |
| 747 | +| | | | |
| 748 | +## 参数 | |
| 749 | +可选参数属性列表 | |
| 750 | + | |
| 751 | +|参数名 |说明 |类型 |是否必填 |默认值 |可选值 | | |
| 752 | +|---- |---- |---- |---- |---- |---- | | |
| 753 | +|uiMode |ui表现方式;popup<弹窗>, page<页面>;默认是 popup |String |是 |popup |page | | |
| 754 | +|treeData |树源数据列表 |Array |是 |[] |- | | |
| 755 | +|valueKey |绑定value的键属性(项的唯一key标识) |String |否 |id |- | | |
| 756 | +|labelKey |用于显示的字段 |String |否 |label |- | | |
| 757 | +|disabledKey |禁用节点绑定属性 |String |否 |disabled |- | | |
| 758 | +|childrenKey |子节点绑定属性 |String |否 |children |- | | |
| 759 | +|title | 弹出标题(如果是函数时会返回所选项的值作为回调参数如;title: (checked):String => {}) |String, Function |否 |'' |- | | |
| 760 | +|multiple |是否可以多选 |Boolean |否 |false |true | | |
| 761 | +|selectParent |是否可以选父级 |Boolean |否 |false |true | | |
| 762 | +|foldAll| 折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开 |Boolean |否 |false |true | | |
| 763 | +|themeColor |主题颜色 |String |否 |#f9ae3d |- | | |
| 764 | +|cancelColor |取消按钮颜色 |String |否 |#757575 |- | | |
| 765 | +|titleColor |标题颜色 |String |否 |#757575 |- | | |
| 766 | +|border |是否有分割线 |Boolean |否 |false |true | | |
| 767 | +|checkStrictly|只有在multiple为true状态下生效; 状态下节点选择完全受控(父子节点选中状态不再关联) |Boolean |否 |false |true | | |
| 768 | +|checkStrictlyModel|只有在multiple为true状态下生效;父子节点关联模式:strong:强关联(不再受限节点的disabled控制),weak:弱关联(节点关联受disabled控制) |String |是 |weak |strong | | |
| 769 | +|showHalfCheckedTips|半选提示;只有在multiple为true, checkStrictly为false的状态下生效;父子节点选中状态不再关联,是否展示半选提示; |Boolean |否 |false |true | | |
| 770 | +|ifSearch| 筛选search模式 |Boolean |否 |true |false | | |
| 771 | +|searchModel| 搜索模式配置 depHighlight: 从属高亮(显示层级并高亮显示);common: 一般 |String |否 |common |depHighlight | | |
| 772 | +|showAuxiliaryLine| 是否打开辅助线 |Boolean |否 |false |true | | |
| 773 | +|loadData| 异步加载函数 (node):Promise([childData]) => {} // demo有说明 |Function |否 |- |- | | |
| 774 | +|height| 只在uiMode=popup时生效;弹层容器的高度,默认是500 |Number |否 |500 |- | | |
| 775 | +|changeVerify| 验证函数 (current as any, chooseList as any []):String => {} // 验证函数会把当前控件的选择值作为参数返给函数体,demo有说明 |Function |否 |- |- | | |
| 776 | + | |
| 777 | + | |
| 778 | +# Event 事件 | |
| 779 | +|事件名 |说明 |类型 |回调参数 | | |
| 780 | +|---- |---- |---- |---- | | |
| 781 | +|confirm|菜单收起时返回的筛选结果 |emit |array | | |
| 782 | +|clear|点击清除按钮时触发 |emit |- | | |
| 783 | +|cancel|关闭弹层和点击取消时触发 |emit |- | | |
| 784 | + | |
| 785 | +## Slot 插槽 | |
| 786 | + | |
| 787 | +|名称 |说明 |参数 | | |
| 788 | +|---- |---- |---- | | |
| 789 | +|label |label插槽 |data(当前项对于treeData里面的数据) | | |
| 790 | +|topBar |topBar插槽 |----滚动区域顶部topBar插槽 | | |
| 791 | +|bottomBar |bottomBar插槽 |----滚动区域底部bottomBar插槽 | | |
| 792 | +|fixedBottomBar |fixedBottomBar插槽 |----固定在页面的底部,使用fixed进行定位 | | |
| 793 | +|empty |empty插槽 |----数据为空的插槽 | | |
| 794 | + | ... | ... |
garbage-removal/src/components/next-tree/style.css
0 → 100644
| 1 | +.next-tree-mask { | |
| 2 | + position: fixed; | |
| 3 | + top: 0rpx; | |
| 4 | + right: 0rpx; | |
| 5 | + bottom: 0rpx; | |
| 6 | + left: 0rpx; | |
| 7 | + z-index: 997; | |
| 8 | + background-color: rgba(0, 0, 0, 0.6); | |
| 9 | + opacity: 0; | |
| 10 | + transition: all 0.3s ease; | |
| 11 | + visibility: hidden; | |
| 12 | +} | |
| 13 | +.next-tree-mask.show { | |
| 14 | + visibility: visible; | |
| 15 | + opacity: 1; | |
| 16 | +} | |
| 17 | +.next-tree-cnt { | |
| 18 | + position: fixed; | |
| 19 | + top: 0rpx; | |
| 20 | + right: 0rpx; | |
| 21 | + bottom: 0rpx; | |
| 22 | + left: 0rpx; | |
| 23 | + z-index: 997; | |
| 24 | + top: 360rpx; | |
| 25 | + transition: all 0.3s ease; | |
| 26 | + transform: translateY(100%); | |
| 27 | +} | |
| 28 | +.next-tree-cnt.next-tree-cnt-page { | |
| 29 | + transition: none; | |
| 30 | +} | |
| 31 | +.next-tree-cnt.show { | |
| 32 | + transform: translateY(0); | |
| 33 | +} | |
| 34 | +.next-tree-bar { | |
| 35 | + background-color: #fff; | |
| 36 | + height: 72rpx; | |
| 37 | + padding-left: 20rpx; | |
| 38 | + padding-right: 20rpx; | |
| 39 | + display: flex; | |
| 40 | + justify-content: space-between; | |
| 41 | + align-items: center; | |
| 42 | + box-sizing: border-box; | |
| 43 | + border-bottom-width: 1rpx !important; | |
| 44 | + border-bottom-style: solid; | |
| 45 | + border-bottom-color: #f5f5f5; | |
| 46 | + font-size: 32rpx; | |
| 47 | + color: #757575; | |
| 48 | + line-height: 1; | |
| 49 | +} | |
| 50 | +.next-tree-bar-btns { | |
| 51 | + display: inline-block; | |
| 52 | + display: flex; | |
| 53 | + flex-direction: row; | |
| 54 | +} | |
| 55 | +.btn-divid { | |
| 56 | + display: inline-block; | |
| 57 | + width: 1px; | |
| 58 | + margin: 0 10px; | |
| 59 | + background-color: #ccc; | |
| 60 | +} | |
| 61 | +.next-tree-bar-confirm { | |
| 62 | + color: #f9ae3d; | |
| 63 | +} | |
| 64 | +.next-tree-view { | |
| 65 | + position: absolute; | |
| 66 | + top: 0rpx; | |
| 67 | + right: 0rpx; | |
| 68 | + bottom: 0rpx; | |
| 69 | + left: 0rpx; | |
| 70 | + top: 72rpx; | |
| 71 | + background-color: #fff; | |
| 72 | + padding-top: 20rpx; | |
| 73 | + padding-right: 20rpx; | |
| 74 | + padding-bottom: 20rpx; | |
| 75 | + padding-left: 20rpx; | |
| 76 | +} | |
| 77 | +.next-tree-view-sc { | |
| 78 | + height: 100%; | |
| 79 | + overflow: hidden; | |
| 80 | +} | |
| 81 | +.next-tree-view-sc .empty { | |
| 82 | + text-align: center; | |
| 83 | + color: #757575; | |
| 84 | + padding: 30rpx; | |
| 85 | +} | |
| 86 | +.next-tree-item-block { | |
| 87 | + | |
| 88 | +} | |
| 89 | +.next-tree-item { | |
| 90 | + display: flex; | |
| 91 | + justify-content: space-between; | |
| 92 | + align-items: center; | |
| 93 | + font-size: 26rpx; | |
| 94 | + color: #757575; | |
| 95 | + line-height: 1; | |
| 96 | + height: 0; | |
| 97 | + opacity: 0; | |
| 98 | + transition: 0.2s; | |
| 99 | + position: relative; | |
| 100 | + overflow: hidden; | |
| 101 | +} | |
| 102 | +.next-tree-item .left-line { | |
| 103 | + position: relative; | |
| 104 | + width: 1rpx; | |
| 105 | + height: 100%; | |
| 106 | + box-sizing: border-box; | |
| 107 | +} | |
| 108 | +.next-tree-item .left-line::before { | |
| 109 | + position: absolute; | |
| 110 | + content: ""; | |
| 111 | + width: 1rpx; | |
| 112 | + height: 100%; | |
| 113 | + background-color: rgba(204,204,204,0.9); | |
| 114 | + box-sizing: border-box; | |
| 115 | + | |
| 116 | + left: -18rpx; | |
| 117 | +} | |
| 118 | +.next-tree-item .parent-horizontal-line { | |
| 119 | + width: 1rpx; | |
| 120 | + height: 100%; | |
| 121 | + position: absolute; | |
| 122 | + top: 0; | |
| 123 | + left: 0rpx; | |
| 124 | + box-sizing: border-box; | |
| 125 | + background-color: rgba(204,204,204,0.9); | |
| 126 | +} | |
| 127 | +.next-tree-item .left-line .horizontal-line { | |
| 128 | + width: 20rpx; | |
| 129 | + height: 1rpx; | |
| 130 | + position: absolute; | |
| 131 | + top: 40rpx; | |
| 132 | + left: 0rpx; | |
| 133 | + background-color: rgba(204,204,204,0.9); | |
| 134 | + box-sizing: border-box; | |
| 135 | +} | |
| 136 | + | |
| 137 | +.next-tree-item.show { | |
| 138 | + height: 80rpx; | |
| 139 | + opacity: 1; | |
| 140 | +} | |
| 141 | +.next-tree-item.showchild:before { | |
| 142 | + transform: rotate(90deg); | |
| 143 | +} | |
| 144 | +.next-tree-item.border { | |
| 145 | + border-bottom: 1rpx solid rgba(204,204,204,0.2); | |
| 146 | +} | |
| 147 | +.next-tree-item.last:before { | |
| 148 | + opacity: 0; | |
| 149 | +} | |
| 150 | +.next-tree-item.disabled { | |
| 151 | + color: #ccc!important; | |
| 152 | +} | |
| 153 | + | |
| 154 | +.next-tree-icon { | |
| 155 | + width: 26rpx; | |
| 156 | + height: 26rpx; | |
| 157 | + margin-right: 8rpx; | |
| 158 | +} | |
| 159 | +.next-tree-label { | |
| 160 | + flex: 1; | |
| 161 | + display: flex; | |
| 162 | + align-items: center; | |
| 163 | + height: 100%; | |
| 164 | + line-height: 1.2; | |
| 165 | +} | |
| 166 | +.next-tree-check { | |
| 167 | + width: 40px; | |
| 168 | + height: 40px; | |
| 169 | + display: flex; | |
| 170 | + justify-content: center; | |
| 171 | + align-items: center; | |
| 172 | +} | |
| 173 | +.next-tree-check-yes, | |
| 174 | +.next-tree-check-no { | |
| 175 | + width: 20px; | |
| 176 | + height: 20px; | |
| 177 | + border-top-left-radius: 20%; | |
| 178 | + border-top-right-radius: 20%; | |
| 179 | + border-bottom-right-radius: 20%; | |
| 180 | + border-bottom-left-radius: 20%; | |
| 181 | + border-top-width: 1rpx; | |
| 182 | + border-left-width: 1rpx; | |
| 183 | + border-bottom-width: 1rpx; | |
| 184 | + border-right-width: 1rpx; | |
| 185 | + border-style: solid; | |
| 186 | + border-color: #f9ae3d; | |
| 187 | + display: flex; | |
| 188 | + justify-content: center; | |
| 189 | + align-items: center; | |
| 190 | + box-sizing: border-box; | |
| 191 | +} | |
| 192 | +.next-tree-check-yes-b { | |
| 193 | + border-top-left-radius: 20%; | |
| 194 | + border-top-right-radius: 20%; | |
| 195 | + border-bottom-right-radius: 20%; | |
| 196 | + border-bottom-left-radius: 20%; | |
| 197 | + background-color: #f9ae3d; | |
| 198 | + color: #fff; | |
| 199 | +} | |
| 200 | +.next-tree-check-yes-b .icon-text { | |
| 201 | + font-size: 14px; | |
| 202 | + font-weight: normal; | |
| 203 | + font-family: uicon-iconfont; | |
| 204 | + display: flex; | |
| 205 | + flex-direction: row; | |
| 206 | + align-items: center; | |
| 207 | +} | |
| 208 | +.next-tree-check .radio { | |
| 209 | + border-top-left-radius: 50%; | |
| 210 | + border-top-right-radius: 50%; | |
| 211 | + border-bottom-right-radius: 50%; | |
| 212 | + border-bottom-left-radius: 50%; | |
| 213 | +} | |
| 214 | +.next-tree-check .radio .next-tree-check-yes-b { | |
| 215 | + border-top-left-radius: 50%; | |
| 216 | + border-top-right-radius: 50%; | |
| 217 | + border-bottom-right-radius: 50%; | |
| 218 | + border-bottom-left-radius: 50%; | |
| 219 | +} | |
| 220 | + | |
| 221 | +.next-tree-item.disabled .next-tree-check-no { | |
| 222 | + color: #ccc!important; | |
| 223 | +} | |
| 224 | +.next-tree-item.disabled .next-tree-check-yes-b { | |
| 225 | + background-color: #ccc!important; | |
| 226 | +} | |
| 227 | +.hover-c { | |
| 228 | + opacity: 0.6; | |
| 229 | +} | |
| 230 | + | |
| 231 | +.fixed-bottom-bar { | |
| 232 | + position: fixed; | |
| 233 | + bottom: 0rpx; | |
| 234 | + left: 0rpx; | |
| 235 | + right: 0rpx; | |
| 236 | + z-index: 998; | |
| 237 | +} | |
| 238 | + | |
| 239 | + | ... | ... |
garbage-removal/src/main.js
| ... | ... | @@ -9,11 +9,9 @@ import App from "./App.vue"; |
| 9 | 9 | // 拦截器 |
| 10 | 10 | let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]; |
| 11 | 11 | list.forEach(item => { //用遍历的方式分别为,uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab这4个路由方法添加拦截器 |
| 12 | - console.log(item, 'router list item') | |
| 13 | 12 | uni.addInterceptor(item, { |
| 14 | 13 | invoke(e) { // 调用前拦截 |
| 15 | 14 | //获取用户的token |
| 16 | - console.log(e, 'routerjs invoke') | |
| 17 | 15 | const flag = uni.getStorageSync('cancelFlag'); |
| 18 | 16 | //获取当前页面路径(即url去掉"?"和"?"后的参数) |
| 19 | 17 | if (flag) { | ... | ... |
garbage-removal/src/pages.json
| ... | ... | @@ -52,6 +52,14 @@ |
| 52 | 52 | "enablePullDownRefresh": false |
| 53 | 53 | } |
| 54 | 54 | },{ |
| 55 | + "path": "pages/order/success/index", | |
| 56 | + "style": { | |
| 57 | + "navigationBarTitleText": "完成派单", | |
| 58 | + "navigationBarTextStyle": "white", | |
| 59 | + "navigationBarBackgroundColor": "#53c21d", | |
| 60 | + "enablePullDownRefresh": false | |
| 61 | + } | |
| 62 | + },{ | |
| 55 | 63 | "path": "pages/order/guest/index", |
| 56 | 64 | "style": { |
| 57 | 65 | "navigationBarTitleText": "详情", | ... | ... |
garbage-removal/src/pages/home/address/addSite.vue
| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | <u--form :labelStyle="{ color: '#909399' }" labelPosition="left" labelWidth="140" :model="addressInfo" |
| 6 | 6 | ref="addressFrom"> |
| 7 | 7 | <u-form-item :required="true" label="所在地区" prop="addressArea" borderBottom> |
| 8 | - <view @click="showRegionPicker" class="input-box"> | |
| 8 | + <view @click.stop="showRegionPicker" hover-class="click-box"> | |
| 9 | 9 | <u--input border="none" readonly style="pointer-events:none" type="text" v-model="addressInfo.addressArea" |
| 10 | 10 | placeholder-class="line" placeholder="省市区县、乡镇等"></u--input> |
| 11 | 11 | </view> |
| ... | ... | @@ -38,10 +38,10 @@ |
| 38 | 38 | </view> |
| 39 | 39 | </view> |
| 40 | 40 | <view class="submit-button"> |
| 41 | - <view v-if="addFlag" @click="submit" class="add">新增地址</view> | |
| 41 | + <view v-if="addFlag" @click="submit" class="add" hover-class="click-box">新增地址</view> | |
| 42 | 42 | <view v-else class="update-box"> |
| 43 | - <view class="del" @click="handleDeleteClick">删除地址</view> | |
| 44 | - <view class="update" @click="handleUpdateClick">保存地址</view> | |
| 43 | + <view class="del" @click="handleDeleteClick" hover-class="click-box">删除地址</view> | |
| 44 | + <view class="update" @click="handleUpdateClick" hover-class="click-box">保存地址</view> | |
| 45 | 45 | </view> |
| 46 | 46 | </view> |
| 47 | 47 | </view> |
| ... | ... | @@ -239,9 +239,7 @@ const reset = () => { |
| 239 | 239 | } |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | - .input-box { | |
| 243 | - @include handleClick; | |
| 244 | - } | |
| 242 | + | |
| 245 | 243 | |
| 246 | 244 | |
| 247 | 245 | .submit-button { |
| ... | ... | @@ -291,7 +289,9 @@ const reset = () => { |
| 291 | 289 | |
| 292 | 290 | } |
| 293 | 291 | } |
| 292 | +} | |
| 294 | 293 | |
| 295 | - | |
| 294 | +.click-box { | |
| 295 | + @include handleClick; | |
| 296 | 296 | } |
| 297 | 297 | </style> | ... | ... |
garbage-removal/src/pages/home/address/index.vue
| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | </view> |
| 19 | 19 | |
| 20 | 20 | </view> |
| 21 | - <view class="addSite" @tap="toAddSite"> | |
| 21 | + <view class="addSite" @click.stop="toAddSite" hover-class="click-box"> | |
| 22 | 22 | <view class="add">添加地址</view> |
| 23 | 23 | </view> |
| 24 | 24 | </view> |
| ... | ... | @@ -166,4 +166,8 @@ onShow(() => { |
| 166 | 166 | } |
| 167 | 167 | } |
| 168 | 168 | } |
| 169 | + | |
| 170 | +.click-box { | |
| 171 | + @include handleClick; | |
| 172 | +} | |
| 169 | 173 | </style> | ... | ... |
garbage-removal/src/pages/home/clean/index.vue
| 1 | 1 | <template> |
| 2 | - <liu-delivery-time :isMask="true" :change="changeTime" ref="chooseTime" title="请选择预约时间"></liu-delivery-time> | |
| 2 | + <view class="mask-box"> | |
| 3 | + <liu-delivery-time :isMask="true" :change="changeTime" ref="chooseTime" title="请选择预约时间"></liu-delivery-time> | |
| 4 | + <u-picker closeOnClickOverlay :show="carTypeShowFlag" :columns="candidates" :itemHeight="100" | |
| 5 | + @confirm="handlePickerCarInfoConfirm" @cancel="handleCarInfoClick(false)" | |
| 6 | + @close="handleCarInfoClick(false)"></u-picker> | |
| 7 | + <u-picker closeOnClickOverlay :show="garbageTypeShowFlag" :columns="garbageTypeList" :itemHeight="100" | |
| 8 | + @confirm="handlePickerGarbageTypeConfirm" @close="handleGarbageTypeClick(false)" | |
| 9 | + @cancel="handleGarbageTypeClick(false)"></u-picker> | |
| 10 | + <u-popup :zIndex="10074" closeOnClickOverlay :show="carPopupShowFlag" :round="10" @close="handlePopupClick(false)" | |
| 11 | + @open="handlePopupClick(true)"> | |
| 12 | + <view class="company-clean-container-car-popup"> | |
| 13 | + <!-- 主要内容 --> | |
| 14 | + <view class="company-clean-container-car-popup-content"> | |
| 15 | + <view class="company-clean-container-car-popup-content-title"> | |
| 16 | + <view style="text-align: center;"> | |
| 17 | + 车辆类型 | |
| 18 | + </view> | |
| 19 | + </view> | |
| 20 | + <view class="company-clean-container-car-popup-content-box"> | |
| 21 | + <view class="company-clean-container-car-popup-content-box-item" v-for="(item, index) in garCarInfoList" | |
| 22 | + :key="index"> | |
| 23 | + <view class="company-clean-container-car-popup-content-box-item-text"> | |
| 24 | + {{ item.garOrderCarType }} | |
| 25 | + </view> | |
| 26 | + <view class="company-clean-container-car-popup-content-box-item-number" hover-class="hoverClickStyle"> | |
| 27 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 28 | + v-model="garCarInfoList[item.garOrderCarType].garOrderCarNumber"></u-number-box> | |
| 29 | + </view> | |
| 30 | + </view> | |
| 31 | + | |
| 32 | + </view> | |
| 33 | + </view> | |
| 34 | + <!-- 占位盒子 --> | |
| 35 | + <view class="company-clean-container-car-popup-button-safe"> | |
| 36 | + | |
| 37 | + </view> | |
| 38 | + </view> | |
| 39 | + </u-popup> | |
| 40 | + </view> | |
| 3 | 41 | <view class="company-clean-container"> |
| 4 | 42 | <view class="company-clean-container-box"> |
| 5 | 43 | <view class="company-clean-container-header"> |
| ... | ... | @@ -21,34 +59,42 @@ |
| 21 | 59 | </view> |
| 22 | 60 | <view class="company-clean-container-car-main"> |
| 23 | 61 | <view class="company-clean-container-car-main-content"> |
| 62 | + <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-type"> | |
| 63 | + <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 64 | + style="color: red;">*</text>车辆类型:</text> | |
| 65 | + <!-- <uni-combox label="" :candidates="candidates" placeholder="请选择运输车辆类型" | |
| 66 | + v-model="paramFrom.carType"></uni-combox> --> | |
| 67 | + <view class="" hover-class="hoverClickStyle" @click.stop="handleCarInfoClick(true)"> | |
| 68 | + <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.carType" | |
| 69 | + type="text" placeholder-class="line" readonly /> | |
| 70 | + </view> | |
| 71 | + </view> | |
| 24 | 72 | <view class="company-clean-container-car-main-content-type"> |
| 25 | 73 | <text class="company-clean-container-car-main-content-type-price-area"><text |
| 26 | 74 | style="color: red;">*</text>垃圾类型:</text> |
| 27 | - <uni-combox label="" :candidates="garbageTypeList" placeholder="请选择垃圾类型" | |
| 28 | - v-model="paramFrom.garbageType"></uni-combox> | |
| 75 | + <view hover-class="hoverClickStyle" @click.stop="handleGarbageTypeClick(true)"> | |
| 76 | + <u--input color="#909399" border="none" style="pointer-events:none" :modelValue="paramFrom.garbageType" | |
| 77 | + type="text" placeholder-class="line" readonly /> | |
| 78 | + </view> | |
| 29 | 79 | </view> |
| 30 | - <!-- <view class="company-clean-container-car-main-content-img"> | |
| 31 | - <image class="company-clean-container-car-main-content-img" /> | |
| 80 | + <view class="company-clean-container-car-main-content-img"> | |
| 81 | + <image class="company-clean-container-car-main-content-img" :src="carFront" /> | |
| 32 | 82 | </view> |
| 33 | 83 | <view class="company-clean-container-car-main-content-remark"> |
| 34 | - 箱体长4.2m宽1.1,高0.7,最多课容纳约110袋袋装修垃圾(75cm*45每袋) | |
| 35 | - </view> --> | |
| 36 | - <view class="company-clean-container-car-main-content-type"> | |
| 37 | - <text class="company-clean-container-car-main-content-type-price-area"><text | |
| 38 | - style="color: red;">*</text>车辆类型:</text> | |
| 39 | - <uni-combox label="" :candidates="candidates" placeholder="请选择运输车辆类型" | |
| 40 | - v-model="paramFrom.carType"></uni-combox> | |
| 84 | + {{ garCarTransportInfo }} | |
| 41 | 85 | </view> |
| 42 | - <view class="company-clean-container-car-main-content-number"> | |
| 86 | + | |
| 87 | + <view v-if="paramFrom.carType" class="company-clean-container-car-main-content-number"> | |
| 43 | 88 | <view class="company-clean-container-car-main-content-number-txt"> |
| 44 | 89 | <text style="color: red;">*</text>添加车辆数量 |
| 45 | 90 | </view> |
| 46 | 91 | <view class="company-clean-container-car-main-content-number-button"> |
| 47 | - <u-number-box :min="1" integer buttonSize="46" v-model="paramFrom.carNumber"></u-number-box> | |
| 92 | + <u-number-box :min="0" :max="9999" integer buttonSize="46" :inputWidth="100" | |
| 93 | + v-model="garCarInfoList[paramFrom.carType].garOrderCarNumber"></u-number-box> | |
| 48 | 94 | </view> |
| 49 | 95 | </view> |
| 50 | 96 | <view class="company-clean-container-car-main-content-prompt"> |
| 51 | - 温馨提示:垃圾类型不符合,有权拒绝清运。 | |
| 97 | + 温馨提示:垃圾类型不符合,企业有权拒绝清运。 | |
| 52 | 98 | </view> |
| 53 | 99 | </view> |
| 54 | 100 | </view> |
| ... | ... | @@ -77,8 +123,8 @@ |
| 77 | 123 | </view> |
| 78 | 124 | </view> |
| 79 | 125 | </view> |
| 80 | - <view class="company-clean-bottom"> | |
| 81 | - <movable-area ref="movableAreaElement" class="movableArea"> | |
| 126 | + <view class="company-clean-bottom" style="z-index: 10074;"> | |
| 127 | + <movable-area v-if="!carPopupShowFlag" ref="movableAreaElement" class="movableArea"> | |
| 82 | 128 | <movable-view class="movableView" :x="x" :y="y" direction="all" @change="onChange"> |
| 83 | 129 | <view class="company-clean-call-box-container"> |
| 84 | 130 | <u-icon @click="handleContactClick(tel)" name="phone-fill" color="#ffffff" size="50"></u-icon> |
| ... | ... | @@ -87,7 +133,12 @@ |
| 87 | 133 | </movable-area> |
| 88 | 134 | <view class="company-clean-bottom-box"> |
| 89 | 135 | <view class="company-clean-bottom-left"> |
| 90 | - <u-icon @click="handleCarInfo" :stop="true" size="50" name="car-fill"></u-icon> | |
| 136 | + <view class="company-clean-bottom-left-icon"> | |
| 137 | + <u-icon @click="carPopupShowFlag = true" :stop="true" size="50" name="car-fill"></u-icon> | |
| 138 | + </view> | |
| 139 | + <view class="company-clean-bottom-left-number"> | |
| 140 | + <up-badge :type="type" max="99" :value="garCarNumberCount"></up-badge> | |
| 141 | + </view> | |
| 91 | 142 | </view> |
| 92 | 143 | <view class="company-clean-bottom-right"> |
| 93 | 144 | <u-button @click="handleOderSure" shape="circle" color="#a9e08f" text="立即派单"></u-button> |
| ... | ... | @@ -102,24 +153,66 @@ import { queryCarList } from '@/apis/carinfo.js'; |
| 102 | 153 | import { uploadFilePromise } from '@/apis/common.js'; |
| 103 | 154 | import { saveOrder } from '@/apis/order.js'; |
| 104 | 155 | import liuDeliveryTime from "@/components/liu-delivery-time/liu-delivery-time.vue"; |
| 105 | -import uniCombox from "@/components/uni-combox/index.vue"; | |
| 156 | +import { useMainStore } from '@/stores/index.js'; | |
| 106 | 157 | import { onLoad } from '@dcloudio/uni-app'; |
| 107 | -import { getCurrentInstance, onMounted, ref } from 'vue'; | |
| 158 | +import { computed, getCurrentInstance, nextTick, ref, watch } from 'vue'; | |
| 108 | 159 | const { proxy } = getCurrentInstance(); |
| 160 | + | |
| 161 | +const store = useMainStore(); | |
| 162 | +const userType = computed(() => store.userType) | |
| 109 | 163 | const x = ref(5) |
| 110 | 164 | const y = ref() |
| 111 | 165 | const movableAreaElement = ref() |
| 112 | 166 | const companyObj = ref() |
| 113 | 167 | const tel = ref() |
| 168 | +const carTypeShowFlag = ref(false) | |
| 169 | +const garbageTypeShowFlag = ref(false) | |
| 170 | +const carPopupShowFlag = ref(false) | |
| 114 | 171 | const userAddress = ref({ |
| 115 | 172 | garUserContactName: "", |
| 116 | 173 | garUserContactTel: "", |
| 117 | 174 | garRemark: "", |
| 118 | 175 | garUserAddress: "" |
| 119 | 176 | }) |
| 120 | -const garbageTypeList = ref(["建筑垃圾", "装修垃圾"]) | |
| 177 | +// 车辆信息 | |
| 178 | +const garCarInfoList = ref({}) | |
| 179 | +const garCarLabelInfoList = ref({}) | |
| 180 | +const garCarLabelInfoNow = ref() | |
| 181 | +const garCarTransportInfo = computed(() => { | |
| 182 | + try { | |
| 183 | + let carInfo = garCarLabelInfoNow.value | |
| 184 | + let lengthWidthHeight = carInfo.lengthWidthHeight.split(";"); | |
| 185 | + let boxLength = lengthWidthHeight[0]; // 箱子的长度(单位:米) | |
| 186 | + let boxWidth = lengthWidthHeight[1]; // 箱子的宽度(单位:米) | |
| 187 | + let boxHeight = lengthWidthHeight[2]; // 箱子的高度(单位:米) | |
| 188 | + | |
| 189 | + let bagLength = 0.75; // 袋子的长度(单位:米) | |
| 190 | + let bagWidth = 0.45; // 袋子的宽度(单位:米) | |
| 191 | + let bagHeight = 0.22; // 袋子的高度(单位:米) | |
| 192 | + | |
| 193 | + let boxVolume = boxLength * boxWidth * boxHeight; // 箱子的体积(单位:立方米) | |
| 194 | + let bagVolume = bagLength * bagWidth * bagHeight; // 袋子的体积(单位:立方米) | |
| 195 | + | |
| 196 | + let bagCount = Math.floor(boxVolume / bagVolume); // 箱子可以容纳的袋子数量(向下取整) | |
| 197 | + | |
| 198 | + return `箱体长${boxLength}m宽${boxWidth}m高${boxHeight}m,最多课容纳约${bagCount}袋袋装修垃圾(75cm * 45cm每袋)。` | |
| 199 | + } catch (error) { | |
| 200 | + return "符合装修垃圾运输管理规范的新型环保智能装修垃圾运输车。" | |
| 201 | + } | |
| 202 | + | |
| 203 | +}) | |
| 204 | +// 车辆数量 | |
| 205 | +const garCarNumberCount = computed(() => { | |
| 206 | + let count = 0; | |
| 207 | + for (const key in garCarInfoList.value) { | |
| 208 | + const element = garCarInfoList.value[key]; | |
| 209 | + count += element.garOrderCarNumber; | |
| 210 | + } | |
| 211 | + return count; | |
| 212 | +}) | |
| 213 | +const garbageTypeList = ref([["装修垃圾", "建筑垃圾"]]) | |
| 121 | 214 | const paramFrom = ref({ |
| 122 | - carNumber: 1, | |
| 215 | + carNumber: 0, | |
| 123 | 216 | remark: "", |
| 124 | 217 | sureReadFlag: [], |
| 125 | 218 | carType: "", |
| ... | ... | @@ -143,18 +236,48 @@ const changeAgree = (e) => { |
| 143 | 236 | const onChange = (e) => { |
| 144 | 237 | // console.log(e); |
| 145 | 238 | } |
| 239 | + | |
| 240 | +const handlePopupClick = (val) => { | |
| 241 | + carPopupShowFlag.value = val | |
| 242 | +} | |
| 243 | + | |
| 146 | 244 | /** |
| 147 | 245 | * 初始化信息 |
| 148 | 246 | */ |
| 149 | 247 | onLoad((options) => { |
| 248 | + | |
| 150 | 249 | companyObj.value = JSON.parse(options.companyObj); |
| 151 | 250 | tel.value = options.tel; |
| 152 | 251 | userAddress.value = JSON.parse(options.userAddress); |
| 153 | 252 | queryCarList({ companyId: companyObj.value.id }).then(res => { |
| 154 | - candidates.value = [...new Set(res.data.rows.map(item => item.carType))]; | |
| 253 | + // 设置车辆类型 | |
| 254 | + candidates.value = [[...new Set(res.data.rows | |
| 255 | + .filter(item => item.containerVolume) | |
| 256 | + .map(item => { | |
| 257 | + garCarLabelInfoList.value[item.containerVolume + "方车"] = item | |
| 258 | + return item.containerVolume + "方车" | |
| 259 | + })) | |
| 260 | + ]]; | |
| 261 | + // 设置初始车辆数量 | |
| 262 | + candidates.value[0].forEach((item, index) => { | |
| 263 | + garCarInfoList.value[item] = { | |
| 264 | + garOrderCarNumber: 0, | |
| 265 | + garOrderCarType: item | |
| 266 | + } | |
| 267 | + }) | |
| 268 | + // 设置默认车辆 | |
| 269 | + paramFrom.value.carType = candidates.value[0][0]; | |
| 270 | + garCarLabelInfoNow.value = garCarLabelInfoList.value[paramFrom.value.carType] | |
| 155 | 271 | }) |
| 156 | 272 | }) |
| 157 | 273 | |
| 274 | + | |
| 275 | +const handleCarInfoClick = (val) => { | |
| 276 | + carTypeShowFlag.value = val | |
| 277 | +} | |
| 278 | +const handleGarbageTypeClick = (val) => { | |
| 279 | + garbageTypeShowFlag.value = val | |
| 280 | +} | |
| 158 | 281 | /** |
| 159 | 282 | * 拨打电话回调 |
| 160 | 283 | */ |
| ... | ... | @@ -195,18 +318,26 @@ const afterRead = async (event) => { |
| 195 | 318 | }; |
| 196 | 319 | |
| 197 | 320 | |
| 198 | - | |
| 199 | -/** | |
| 200 | - * 处理车子数量 | |
| 201 | - */ | |
| 202 | -const handleCarInfo = () => { | |
| 203 | - | |
| 321 | +const handlePickerGarbageTypeConfirm = (e) => { | |
| 322 | + paramFrom.value.garbageType = e.value | |
| 323 | + garbageTypeShowFlag.value = false | |
| 324 | +} | |
| 325 | +const handlePickerCarInfoConfirm = (e) => { | |
| 326 | + paramFrom.value.carType = e.value | |
| 327 | + garCarLabelInfoNow.value = garCarLabelInfoList.value[paramFrom.value.carType] | |
| 328 | + carTypeShowFlag.value = false | |
| 329 | + console.log(garCarLabelInfoNow.value); | |
| 204 | 330 | } |
| 205 | 331 | |
| 206 | 332 | /** |
| 207 | 333 | * 处理下单 |
| 208 | 334 | */ |
| 209 | 335 | const handleOderSure = () => { |
| 336 | + let garCarInfos = []; | |
| 337 | + for (const key in garCarInfoList.value) { | |
| 338 | + garCarInfos.push(garCarInfoList.value[key]) | |
| 339 | + } | |
| 340 | + | |
| 210 | 341 | let params = { |
| 211 | 342 | /** |
| 212 | 343 | * 派单地址 |
| ... | ... | @@ -222,8 +353,7 @@ const handleOderSure = () => { |
| 222 | 353 | * 派单姓名 |
| 223 | 354 | */ |
| 224 | 355 | garOrderContactName: userAddress.value.garUserContactName, |
| 225 | - garOrderCarNumber: paramFrom.value.carNumber, | |
| 226 | - garOrderCarType: paramFrom.value.carType, | |
| 356 | + garCarInfoList: garCarInfos, | |
| 227 | 357 | |
| 228 | 358 | /** |
| 229 | 359 | * 垃圾类型 |
| ... | ... | @@ -248,7 +378,7 @@ const handleOderSure = () => { |
| 248 | 378 | /** |
| 249 | 379 | * 公司负责人电话 |
| 250 | 380 | */ |
| 251 | - garOrderCompanyTel: companyObj.value.safetyManagerPhone, | |
| 381 | + garOrderCompanyTel: companyObj.value.servicePhone, | |
| 252 | 382 | |
| 253 | 383 | /** |
| 254 | 384 | * 约定时间 |
| ... | ... | @@ -266,34 +396,32 @@ const handleOderSure = () => { |
| 266 | 396 | if (!validateParams(params)) { |
| 267 | 397 | return; |
| 268 | 398 | } |
| 399 | + | |
| 269 | 400 | saveOrder(params).then(res => { |
| 270 | 401 | // TODO 派单详情 |
| 271 | 402 | if (res.data.success) { |
| 272 | - uni.$u.route({ | |
| 273 | - type: "redirect", | |
| 274 | - url: `pages/order/detail/index`, | |
| 275 | - params: { | |
| 276 | - orderId: res.data.data | |
| 277 | - } | |
| 278 | - }) | |
| 403 | + if (userType.value === "运输驾驶员") { | |
| 404 | + uni.$u.toast("派单成功,请切换成且角色查看订单详情") | |
| 405 | + setTimeout(() => { | |
| 406 | + uni.navigateBack({ | |
| 407 | + delta: 1, | |
| 408 | + }) | |
| 409 | + }, 50) | |
| 410 | + } else { | |
| 411 | + uni.$u.route({ | |
| 412 | + type: "redirect", | |
| 413 | + url: `pages/order/detail/index`, | |
| 414 | + params: { | |
| 415 | + orderId: res.data.data | |
| 416 | + } | |
| 417 | + }) | |
| 418 | + uni.$u.toast(res.data.msg) | |
| 419 | + } | |
| 420 | + | |
| 279 | 421 | } |
| 280 | - uni.$u.toast(res.data.msg) | |
| 281 | 422 | }) |
| 282 | - | |
| 283 | 423 | } |
| 284 | 424 | |
| 285 | -onMounted(() => { | |
| 286 | - let areaHeight; | |
| 287 | - // select中的参数就如css选择器一样选择元素 | |
| 288 | - let movableArea = uni.createSelectorQuery().in(proxy).select(".movableArea"); | |
| 289 | - movableArea.boundingClientRect(function (data) { | |
| 290 | - // data - 包含元素的高度等信息 | |
| 291 | - areaHeight = data.height; | |
| 292 | - y.value = areaHeight > 20 ? (areaHeight - 20) : areaHeight; | |
| 293 | - }).exec(function (res) { | |
| 294 | - // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据 | |
| 295 | - }) | |
| 296 | -}) | |
| 297 | 425 | |
| 298 | 426 | /** |
| 299 | 427 | * 校验参数 |
| ... | ... | @@ -310,15 +438,21 @@ const validateParams = (params) => { |
| 310 | 438 | case "garOrderAgreementTime": |
| 311 | 439 | jumpPrompt('请选择预约时间') |
| 312 | 440 | break; |
| 313 | - case "garOrderTrashType": | |
| 314 | - jumpPrompt('请选择垃圾类型') | |
| 315 | - break; | |
| 316 | - case "garOrderCarType": | |
| 317 | - jumpPrompt('请选择车辆类型') | |
| 318 | - break; | |
| 441 | + | |
| 319 | 442 | } |
| 320 | 443 | return false; |
| 321 | 444 | } |
| 445 | + if (key === "garCarInfoList") { | |
| 446 | + let count = 0; | |
| 447 | + params[key].forEach(item => { | |
| 448 | + count += item.garOrderCarNumber; | |
| 449 | + }) | |
| 450 | + if (count === 0) { | |
| 451 | + jumpPrompt('请添加车辆数量') | |
| 452 | + return false; | |
| 453 | + } | |
| 454 | + } | |
| 455 | + | |
| 322 | 456 | if (key == "imageUrls") { |
| 323 | 457 | if (params[key].length == 0) { |
| 324 | 458 | jumpPrompt('请上传现场图片') |
| ... | ... | @@ -355,6 +489,31 @@ const validateImage = (fileList) => { |
| 355 | 489 | return true; |
| 356 | 490 | } |
| 357 | 491 | |
| 492 | + | |
| 493 | +// 开始执行一次 | |
| 494 | +watch(carPopupShowFlag, (val) => { | |
| 495 | + // console.log(val); | |
| 496 | + // carPopupShowFlag.value = val | |
| 497 | + if (!val) { | |
| 498 | + setTimeout(() => { | |
| 499 | + nextTick(() => { | |
| 500 | + let areaHeight; | |
| 501 | + // select中的参数就如css选择器一样选择元素 | |
| 502 | + let movableArea = uni.createSelectorQuery().in(proxy).select(".movableArea"); | |
| 503 | + movableArea.boundingClientRect(function (data) { | |
| 504 | + // data - 包含元素的高度等信息 | |
| 505 | + areaHeight = data.height; | |
| 506 | + y.value = areaHeight > 40 ? (areaHeight - 40) : areaHeight; | |
| 507 | + }).exec(function (res) { | |
| 508 | + // 注意:exec方法必须执行,即便什么也不做,否则不会获取到任何数据 | |
| 509 | + }) | |
| 510 | + }) | |
| 511 | + }, 0); | |
| 512 | + } | |
| 513 | +}, { | |
| 514 | + immediate: true | |
| 515 | +}) | |
| 516 | + | |
| 358 | 517 | </script> |
| 359 | 518 | |
| 360 | 519 | <style lang="scss" scoped> |
| ... | ... | @@ -363,6 +522,7 @@ $custom-page-padding: 20rpx; |
| 363 | 522 | $custom-border-radio: 20rpx; |
| 364 | 523 | $custom-bottom-height: 200rpx; |
| 365 | 524 | |
| 525 | + | |
| 366 | 526 | .company-clean-container { |
| 367 | 527 | height: 100%; |
| 368 | 528 | width: 100%; |
| ... | ... | @@ -546,6 +706,8 @@ $custom-bottom-height: 200rpx; |
| 546 | 706 | // height: 100%; |
| 547 | 707 | bottom: 0; |
| 548 | 708 | left: 0; |
| 709 | + // 阴影 | |
| 710 | + box-shadow: 0 0 10rpx 0 rgba(0, 0, 0, 0.1); | |
| 549 | 711 | |
| 550 | 712 | .movableArea { |
| 551 | 713 | pointer-events: none; |
| ... | ... | @@ -583,7 +745,12 @@ $custom-bottom-height: 200rpx; |
| 583 | 745 | align-items: center; |
| 584 | 746 | |
| 585 | 747 | .company-clean-bottom-left { |
| 586 | - transform: rotateY(180deg); | |
| 748 | + display: flex; | |
| 749 | + | |
| 750 | + .company-clean-bottom-left-icon { | |
| 751 | + transform: rotateY(180deg); | |
| 752 | + } | |
| 753 | + | |
| 587 | 754 | } |
| 588 | 755 | |
| 589 | 756 | .company-clean-bottom-right { |
| ... | ... | @@ -594,5 +761,53 @@ $custom-bottom-height: 200rpx; |
| 594 | 761 | } |
| 595 | 762 | |
| 596 | 763 | |
| 764 | + | |
| 765 | +} | |
| 766 | + | |
| 767 | +.hoverClickStyle { | |
| 768 | + @include handleClick; | |
| 769 | +} | |
| 770 | + | |
| 771 | +// 弹出框 | |
| 772 | +.company-clean-container-car-popup { | |
| 773 | + min-height: 450rpx; | |
| 774 | + padding: $custom-page-padding; | |
| 775 | + box-sizing: border-box; | |
| 776 | + | |
| 777 | + .company-clean-container-car-popup-content { | |
| 778 | + font-size: 28rpx; | |
| 779 | + | |
| 780 | + .company-clean-container-car-popup-content-box { | |
| 781 | + box-sizing: border-box; | |
| 782 | + padding: $custom-page-padding; | |
| 783 | + border: 2rpx solid #a9e08f; | |
| 784 | + border-radius: 10rpx; | |
| 785 | + | |
| 786 | + .company-clean-container-car-popup-content-box-item { | |
| 787 | + display: flex; | |
| 788 | + align-items: center; | |
| 789 | + justify-content: space-between; | |
| 790 | + margin: 20rpx 0; | |
| 791 | + box-sizing: border-box; | |
| 792 | + | |
| 793 | + .company-clean-container-car-popup-content-box-item-text {} | |
| 794 | + | |
| 795 | + .company-clean-container-car-popup-content-box-item-number {} | |
| 796 | + } | |
| 797 | + } | |
| 798 | + | |
| 799 | + .company-clean-container-car-popup-content-title { | |
| 800 | + color: $u-main-color; | |
| 801 | + box-sizing: border-box; | |
| 802 | + margin-bottom: 20rpx; | |
| 803 | + font-size: 30rpx; | |
| 804 | + font-weight: bold; | |
| 805 | + } | |
| 806 | + } | |
| 807 | + | |
| 808 | + .company-clean-container-car-popup-button-safe { | |
| 809 | + width: 100%; | |
| 810 | + height: $custom-bottom-height; | |
| 811 | + } | |
| 597 | 812 | } |
| 598 | 813 | </style> | ... | ... |
garbage-removal/src/pages/home/index.vue
| ... | ... | @@ -47,24 +47,25 @@ |
| 47 | 47 | :src="item.carParkPanorama ? item.carParkPanorama : 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png'" /> |
| 48 | 48 | </view> |
| 49 | 49 | <view class="company-list-item-main-right" |
| 50 | - @click="handleDetailClick(item, item.legalRepresentativePhone, userAddress)"> | |
| 50 | + @click="handleDetailClick(item, item.service_phone, userAddress)"> | |
| 51 | 51 | <view class="company-list-item-main-right-name"> |
| 52 | 52 | {{ item.name }} |
| 53 | 53 | </view> |
| 54 | 54 | <view class="company-list-item-main-right-score"> |
| 55 | 55 | <text class="company-list-item-main-right-text">评分:</text> |
| 56 | 56 | <view v-if="item.score != 0" class="company-list-item-main-right-score-start"> |
| 57 | - <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" :key="todo" | |
| 58 | - color="#f9ae3d" size="28"></u-icon> | |
| 57 | + <!-- <u-icon v-for="todo in maxStar" :name="item.score > todo ? 'star-fill' : 'star'" :key="todo" | |
| 58 | + color="#f9ae3d" size="28"></u-icon> --> | |
| 59 | + <u-rate activeColor="#f9ae3d" inactive-color="#f9ae3d" size="28" :modelValue="item.score" | |
| 60 | + allowHalf readonly></u-rate> | |
| 59 | 61 | </view> |
| 60 | 62 | <text v-if="item.score > 0" class="company-list-item-main-right-text" style="color: #fd5d00;">{{ |
| 61 | 63 | item.score }}分</text> |
| 62 | 64 | <text v-else class="company-list-item-main-right-text" style="color: #fd5d00;">最近一月暂无评分</text> |
| 63 | 65 | </view> |
| 64 | 66 | <view class="company-list-item-main-right-price-number"> |
| 65 | - <view class="company-list-item-main-right-price">公司类型:{{ item.companyType == 0 ? "经营单位" : | |
| 66 | - "运输公司" | |
| 67 | - }} </view> | |
| 67 | + <view class="company-list-item-main-right-price">报价:<text | |
| 68 | + style="color: #fd5d00;">¥400起 </text></view> | |
| 68 | 69 | <view class="company-list-item-main-right-number"> |
| 69 | 70 | 清运数:<text class="company-list-item-main-right-number-text">{{ item.cleanNumber }}</text> |
| 70 | 71 | </view> |
| ... | ... | @@ -76,12 +77,12 @@ |
| 76 | 77 | </view> |
| 77 | 78 | <view class="company-list-item-bottom"> |
| 78 | 79 | <view class="company-list-item-bottom-contact-company"> |
| 79 | - <u-button @click="handleContactClick(item.legalRepresentativePhone)" color="#a9e08f" size="normal" | |
| 80 | + <u-button @click="handleContactClick(item.service_phone)" color="#a9e08f" size="normal" | |
| 80 | 81 | type="success" :hairline="true" shape="circle" text="联系公司"></u-button> |
| 81 | 82 | </view> |
| 82 | 83 | <view class="company-list-item-bottom-button-clean"> |
| 83 | - <u-button @click="handleCleanGarbage(item, item.legalRepresentativePhone, userAddress)" | |
| 84 | - type="success" :hairline="true" size="normal" shape="circle" text="垃圾清运"></u-button> | |
| 84 | + <u-button @click="handleCleanGarbage(item, item.service_phone, userAddress)" type="success" | |
| 85 | + :hairline="true" size="normal" shape="circle" text="垃圾清运"></u-button> | |
| 85 | 86 | </view> |
| 86 | 87 | </view> |
| 87 | 88 | </view> |
| ... | ... | @@ -281,7 +282,7 @@ const initData = () => { |
| 281 | 282 | } |
| 282 | 283 | const queryList = (pageNo, pageSize) => { |
| 283 | 284 | // 查询公司信息 |
| 284 | - queryEnterpriseList({ companyType: 0, pageNum: pageNo, pageSize }).then(res => { | |
| 285 | + queryEnterpriseList({ companyType: 1, pageNum: pageNo, pageSize }).then(res => { | |
| 285 | 286 | paging.value.complete(res.data.data.list); |
| 286 | 287 | }) |
| 287 | 288 | } |
| ... | ... | @@ -510,6 +511,7 @@ const queryList = (pageNo, pageSize) => { |
| 510 | 511 | } |
| 511 | 512 | |
| 512 | 513 | .company-list-item-main-right { |
| 514 | + flex: auto; | |
| 513 | 515 | display: flex; |
| 514 | 516 | flex-direction: column; |
| 515 | 517 | flex-wrap: wrap; |
| ... | ... | @@ -543,14 +545,16 @@ const queryList = (pageNo, pageSize) => { |
| 543 | 545 | |
| 544 | 546 | .company-list-item-main-right-price-number { |
| 545 | 547 | display: flex; |
| 546 | - justify-content: space-around; | |
| 548 | + justify-content: space-between; | |
| 547 | 549 | align-items: center; |
| 548 | 550 | |
| 549 | 551 | .company-list-item-main-right-price {} |
| 550 | 552 | |
| 551 | 553 | .company-list-item-main-right-number { |
| 554 | + flex: auto; | |
| 552 | 555 | font-size: small; |
| 553 | 556 | |
| 557 | + | |
| 554 | 558 | .company-list-item-main-right-number-text { |
| 555 | 559 | color: $u-main-color; |
| 556 | 560 | } | ... | ... |
garbage-removal/src/pages/login/index.vue
garbage-removal/src/pages/order/detail/index.vue
| 1 | 1 | <template> |
| 2 | + <clashDispatch ref="clashDispatchRef" :valueKey="'licensePlateNumber'" :onconfirm="handleDispatchConfirm" | |
| 3 | + :dataList="personnelList"> | |
| 4 | + </clashDispatch> | |
| 2 | 5 | <view class="order-detail-container" v-if="dataGram != null || dataGram != undefined"> |
| 3 | 6 | <view class="order-detail-container-box"> |
| 4 | 7 | <view class="order-detail-top"> |
| ... | ... | @@ -46,12 +49,6 @@ |
| 46 | 49 | </view> |
| 47 | 50 | </view> |
| 48 | 51 | <view class="order-detail-container-header-item"> |
| 49 | - <text class="order-detail-container-header-title">车辆类型:</text> | |
| 50 | - <view class="order-detail-container-header-content"> | |
| 51 | - {{ dataGram.garOrderCarType }}({{ dataGram.garOrderCarNumber }}辆) | |
| 52 | - </view> | |
| 53 | - </view> | |
| 54 | - <view class="order-detail-container-header-item"> | |
| 55 | 52 | <text class="order-detail-container-header-title">垃圾类型:</text> |
| 56 | 53 | <view class="order-detail-container-header-content"> |
| 57 | 54 | {{ dataGram.garOrderTrashType }} |
| ... | ... | @@ -67,7 +64,23 @@ |
| 67 | 64 | <view @click="handleQrCodeClick(orderId)" class="iconfont icon-erweima-xian"></view> |
| 68 | 65 | </view> |
| 69 | 66 | </view> |
| 70 | - | |
| 67 | + </view> | |
| 68 | + <!-- 车辆信息 --> | |
| 69 | + <view class="order-detail-container-box-card"> | |
| 70 | + <view class="order-detail-container-header-card-title"> | |
| 71 | + <view class="order-detail-container-header-card-uicon"></view> | |
| 72 | + 车辆信息 | |
| 73 | + </view> | |
| 74 | + <view class="order-detail-container-header-item" style="justify-content: space-between;" | |
| 75 | + v-for="(item) in dataGram.garCarInfoList" :key="item.garId"> | |
| 76 | + <text class="order-detail-container-header-title" style="color: #303133;">{{ item.garOrderCarType }} | |
| 77 | + </text> | |
| 78 | + <view class="order-detail-container-header-content"> | |
| 79 | + <text class="order-detail-container-header-title"> | |
| 80 | + {{ cleanStatus(dataGram.garOrderHandlerStatus) }} | |
| 81 | + </text> | |
| 82 | + </view> | |
| 83 | + </view> | |
| 71 | 84 | </view> |
| 72 | 85 | <!-- 派单记录 --> |
| 73 | 86 | <view class="order-detail-container-box-card"> |
| ... | ... | @@ -82,7 +95,7 @@ |
| 82 | 95 | </view> |
| 83 | 96 | </view> --> |
| 84 | 97 | <view class="order-detail-container-header-item"> |
| 85 | - <text class="order-detail-container-header-title">约定时间:</text> | |
| 98 | + <text class="order-detail-container-header-title">预约时间:</text> | |
| 86 | 99 | <view class="order-detail-container-header-content"> |
| 87 | 100 | {{ dataGram.garOrderAgreementTime }} |
| 88 | 101 | </view> |
| ... | ... | @@ -117,27 +130,27 @@ |
| 117 | 130 | 处理信息 |
| 118 | 131 | </view> |
| 119 | 132 | <view v-if="dataGram.garOrderHandlerId" style="width: 100%;"> |
| 120 | - <view class="order-detail-container-header-item"> | |
| 133 | + <!-- <view class="order-detail-container-header-item"> | |
| 121 | 134 | <text class="order-detail-container-header-title">负责人:</text> |
| 122 | 135 | <view class="order-detail-container-header-content"> |
| 123 | 136 | {{ dataGram.garOrderHandleName }} |
| 124 | 137 | </view> |
| 125 | - </view> | |
| 138 | + </view> --> | |
| 126 | 139 | <view class="order-detail-container-header-item"> |
| 127 | - <text class="order-detail-container-header-title">联系方式:</text> | |
| 140 | + <text class="order-detail-container-header-title">服务电话:</text> | |
| 128 | 141 | <view class="order-detail-container-header-content"> |
| 129 | - {{ dataGram.garOrderHandleTel }} | |
| 142 | + {{ dataGram.garOrderCompanyTel }} | |
| 130 | 143 | </view> |
| 131 | 144 | </view> |
| 132 | 145 | <view class="order-detail-container-header-item"> |
| 133 | - <text class="order-detail-container-header-title">装车照片:</text> | |
| 146 | + <text class=" order-detail-container-header-title">装车照片:</text> | |
| 134 | 147 | <view class="order-detail-container-header-content"> |
| 135 | 148 | <u-upload width="180" height="130" :fileList="putOnImages" name="3" multiple :maxCount="20" |
| 136 | 149 | :previewFullImage="true" :isReadOnly="true"></u-upload> |
| 137 | 150 | </view> |
| 138 | 151 | </view> |
| 139 | 152 | <view class="order-detail-container-header-item"> |
| 140 | - <text class="order-detail-container-header-title">卸车照片:</text> | |
| 153 | + <text class=" order-detail-container-header-title">卸车照片:</text> | |
| 141 | 154 | <view class="order-detail-container-header-content"> |
| 142 | 155 | <u-upload width="180" height="130" :fileList="putDownImages" name="3" multiple :maxCount="20" |
| 143 | 156 | :previewFullImage="true" :isReadOnly="true"></u-upload> |
| ... | ... | @@ -150,38 +163,55 @@ |
| 150 | 163 | </view> |
| 151 | 164 | </view> |
| 152 | 165 | <view class="space-box">{{ spaceStr }}</view> |
| 153 | - | |
| 154 | 166 | </view> |
| 155 | 167 | <!-- 占位符 --> |
| 156 | 168 | <view class="order-detail-bottom"> |
| 157 | 169 | <view class="order-detail-bottom-box"> |
| 158 | 170 | <view class=" order-detail-bottom-left"> |
| 159 | - <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '司机'" @click="handleOderCancelClick()" | |
| 160 | - shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 171 | + <u-button v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" | |
| 172 | + @click="handleSubmitSuccess(orderId)" shape="circle" color="#a9e08f" text="完成派单"></u-button> | |
| 173 | + <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '企业负责人' && dataGram.garCancelFlag === 0" | |
| 174 | + @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 175 | + <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '运输驾驶员' && dataGram.garCancelFlag === 0" | |
| 176 | + @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> | |
| 177 | + <u-button v-if="dataGram.garOrderHandlerStatus === 1 && userType == '企业负责人'" | |
| 178 | + @click="handleOrderDispatchClick(orderId)" shape="circle" color="#a9e08f" | |
| 179 | + :text="dataGram.garOrderMatchFlag === 0 ? '派单下发' : '继续下发'"></u-button> | |
| 161 | 180 | </view> |
| 162 | 181 | <view class="order-detail-bottom-right"> |
| 163 | 182 | <u-button v-if="dataGram.garOrderHandlerStatus === 0 && userType == '居民用户' && dataGram.garCancelFlag === 0" |
| 164 | 183 | @click="handleOderCancelClick()" shape="circle" color="#a9e08f" text="取消派单"></u-button> |
| 184 | + <u-button @click="driverHandleOrder(orderId)" | |
| 185 | + v-if="dataGram.garOrderHandlerStatus === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" | |
| 186 | + shape="circle" color="#a9e08f" text="处理派单"></u-button> | |
| 165 | 187 | <u-button @click="handleOrder(orderId)" |
| 166 | - v-if="dataGram.garOrderHandlerStatus === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0" | |
| 188 | + v-if="dataGram.garOrderHandlerStatus === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '企业负责人'" | |
| 167 | 189 | shape="circle" color="#a9e08f" text="处理派单"></u-button> |
| 168 | 190 | <u-button @click="handleUploadImage(orderId, 'putOnImages')" |
| 169 | - v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putOnImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0" | |
| 191 | + v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" | |
| 192 | + shape="circle" color="#a9e08f" text="上传图片"></u-button> | |
| 193 | + <!-- <u-button @click="handleUploadImage(orderId, 'putOnImages')" | |
| 194 | + v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putOnImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" | |
| 170 | 195 | shape="circle" color="#a9e08f" text="装车照片"></u-button> |
| 171 | 196 | <u-button @click="handleUploadImage(orderId, 'putDownImages')" |
| 172 | - v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0" | |
| 173 | - shape="circle" color="#a9e08f" text="卸车照片"></u-button> | |
| 197 | + v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '运输驾驶员'" | |
| 198 | + shape="circle" color="#a9e08f" text="卸车照片"></u-button> --> | |
| 199 | + <!-- <u-button @click="handleUploadImage(orderId, 'putDownImages')" | |
| 200 | + v-else-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putDownImages.length === 0 && dataGram.handleFlag && dataGram.garCancelFlag === 0 && userType === '企业负责人'" | |
| 201 | + shape="circle" color="#a9e08f" text="上传照片"></u-button> --> | |
| 174 | 202 | <u-button @click="handleEvaluate(orderId, userType)" |
| 175 | 203 | v-if="dataGram.garEvaluateFlag === 0 && userType === '居民用户'" shape="circle" color="#a9e08f" |
| 176 | 204 | text="去评价"></u-button> |
| 177 | 205 | <u-button @click="handleEvaluate(orderId, userType)" |
| 178 | - v-if="dataGram.garHandlerEvaluateFlag === 0 && userType === '司机'" shape="circle" color="#a9e08f" | |
| 206 | + v-if="dataGram.garHandlerEvaluateFlag === 0 && userType === '企业负责人'" shape="circle" color="#a9e08f" | |
| 179 | 207 | text="去评价"></u-button> |
| 180 | 208 | <u-button @click="handleEvaluateDetail(orderId, userType)" |
| 181 | - v-if="dataGram.garHandlerEvaluateFlag === 1 && userType === '司机'" shape="circle" color="#a9e08f" | |
| 209 | + v-if="dataGram.garHandlerEvaluateFlag === 1 && userType === '企业负责人'" shape="circle" color="#a9e08f" | |
| 182 | 210 | text="查看评价"></u-button> |
| 183 | - <u-button | |
| 184 | - v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.putOnImages.length != 0 && dataGram.putDownImages.length != 0 && dataGram.garCancelFlag === 0" | |
| 211 | + <u-button @click="handleEvaluateDetail(orderId, userType)" | |
| 212 | + v-if="dataGram.garEvaluateFlag === 1 && userType === '居民用户'" shape="circle" color="#a9e08f" | |
| 213 | + text="查看评价"></u-button> | |
| 214 | + <u-button v-if="dataGram.garOrderHandlerStatus === 1 && dataGram.garCancelFlag === 0 && userType != '运输驾驶员'" | |
| 185 | 215 | @click="handleSubmitSuccess(orderId)" shape="circle" color="#a9e08f" text="完成派单"></u-button> |
| 186 | 216 | </view> |
| 187 | 217 | </view> |
| ... | ... | @@ -197,13 +227,16 @@ |
| 197 | 227 | </template> |
| 198 | 228 | |
| 199 | 229 | <script setup> |
| 200 | -import { queryOrderDetail, updateOrder } from "@/apis/order.js"; | |
| 230 | +import { dispatchOrders, queryOrderDetail, queryOrderDispatch, updateOrder } from "@/apis/order.js"; | |
| 201 | 231 | import { createQrCode } from '@/apis/qrcode.js'; |
| 202 | 232 | import uqrcode from '@/components/Sansnn-uQRCode_4.0.6/components/uqrcode/uqrcode.vue'; |
| 233 | +import clashDispatch from '@/components/clash-dispatch/index.vue'; | |
| 203 | 234 | import zStatic from '@/components/z-paging/js/z-paging-static'; |
| 204 | 235 | import { useMainStore } from '@/stores/index.js'; |
| 205 | -import { onLoad, onReady } from '@dcloudio/uni-app'; | |
| 206 | -import { computed, nextTick, ref } from 'vue'; | |
| 236 | +import { onLoad } from '@dcloudio/uni-app'; | |
| 237 | +import { computed, ref } from 'vue'; | |
| 238 | +const clashDispatchRef = ref() | |
| 239 | +const personnelList = ref([]) | |
| 207 | 240 | const store = useMainStore(); |
| 208 | 241 | const userType = computed(() => store.userType) |
| 209 | 242 | const dataGram = ref(); |
| ... | ... | @@ -248,16 +281,8 @@ const createQrCodeLocal = (orderId) => { |
| 248 | 281 | const protocol = window.location.protocol; |
| 249 | 282 | const localAddress = `${protocol}//${hostname}:${port}`; |
| 250 | 283 | // const localAddress = `http://localhost:5173`; |
| 251 | - qrCodeText.value = localAddress + "/pages/order/detail/index?orderId=" + orderId; | |
| 252 | - console.log(qrCodeText.value); | |
| 253 | - qrCodeRef.value.remake({ | |
| 254 | - success: () => { | |
| 255 | - console.log('生成成功'); | |
| 256 | - }, | |
| 257 | - fail: err => { | |
| 258 | - console.log(err) | |
| 259 | - } | |
| 260 | - }); | |
| 284 | + qrCodeText.value = localAddress + "/pages/order/guest/index?orderId=" + orderId; | |
| 285 | + console.log(qrCodeRef.value); | |
| 261 | 286 | } |
| 262 | 287 | // 获取二维码 |
| 263 | 288 | const handleQrCodeClick = (orderId) => { |
| ... | ... | @@ -286,6 +311,21 @@ const handleQrCodeClick = (orderId) => { |
| 286 | 311 | // #endif |
| 287 | 312 | } |
| 288 | 313 | |
| 314 | +const handleOrderDispatchClick = (orderId) => { | |
| 315 | + // 获取派单人员 | |
| 316 | + queryOrderDispatch(orderId).then(res => { | |
| 317 | + if (res.data.success) { | |
| 318 | + personnelList.value = res.data.data | |
| 319 | + clashDispatchRef.value.open(res.data.data) | |
| 320 | + | |
| 321 | + handleOrderDetail(orderId) | |
| 322 | + } else { | |
| 323 | + uni.$u.toast(res.data.message) | |
| 324 | + } | |
| 325 | + }) | |
| 326 | +} | |
| 327 | + | |
| 328 | + | |
| 289 | 329 | const handleClose = (e) => { |
| 290 | 330 | cancelShow.value = false |
| 291 | 331 | } |
| ... | ... | @@ -371,6 +411,8 @@ const handleSubmitSuccess = (orderId) => { |
| 371 | 411 | } |
| 372 | 412 | } |
| 373 | 413 | }); |
| 414 | + // uni.$u.route(`pages/order/success/index?orderId=${orderId}`) | |
| 415 | + | |
| 374 | 416 | } |
| 375 | 417 | const handleEvaluate = (orderId, userType) => { |
| 376 | 418 | uni.$u.route(`pages/order/evaluate/index?orderId=${orderId}&userType=${userType}`) |
| ... | ... | @@ -394,6 +436,24 @@ const handleOrder = (orderId) => { |
| 394 | 436 | }) |
| 395 | 437 | } |
| 396 | 438 | |
| 439 | +// 接收派单 | |
| 440 | +const driverHandleOrder = (orderId) => { | |
| 441 | + updateOrder({ garOrderId: orderId, handleType: 0 }).then(res => { | |
| 442 | + if (res.data.success) { | |
| 443 | + if (res.data.data === "派单已经被别人接受啦") { | |
| 444 | + uni.$u.toast(res.data.data) | |
| 445 | + uni.$u.route({ | |
| 446 | + type: "reLaunch", | |
| 447 | + url: `pages/order/index`, | |
| 448 | + }) | |
| 449 | + } else { | |
| 450 | + uni.$u.toast(res.data.data) | |
| 451 | + handleOrderDetail(orderId) | |
| 452 | + } | |
| 453 | + } | |
| 454 | + }) | |
| 455 | +} | |
| 456 | + | |
| 397 | 457 | |
| 398 | 458 | const currentStep = (step) => { |
| 399 | 459 | if (step > 2) { |
| ... | ... | @@ -403,12 +463,65 @@ const currentStep = (step) => { |
| 403 | 463 | } |
| 404 | 464 | |
| 405 | 465 | /** |
| 466 | + * 清运状态 | |
| 467 | + * @param {*} status | |
| 468 | + */ | |
| 469 | +const cleanStatus = (status) => { | |
| 470 | + if (dataGram.garCancelFlag === 1) { | |
| 471 | + return '取消清运'; | |
| 472 | + } | |
| 473 | + switch (status) { | |
| 474 | + case 0: | |
| 475 | + return '准备清运'; | |
| 476 | + case 1: | |
| 477 | + return '正在清运'; | |
| 478 | + case 3: | |
| 479 | + return '清运完成'; | |
| 480 | + } | |
| 481 | +} | |
| 482 | + | |
| 483 | +// /** | |
| 484 | +// * 上传图片 | |
| 485 | +// * @param {string} orderId | |
| 486 | +// * @param {string} putType | |
| 487 | +// */ | |
| 488 | +// const handleUploadImage = (orderId, putType) => { | |
| 489 | +// uni.$u.route(`pages/order/upload/index?orderId=${orderId}&putType=${putType}`) | |
| 490 | +// } | |
| 491 | + | |
| 492 | +/** | |
| 406 | 493 | * 上传图片 |
| 407 | 494 | * @param {string} orderId |
| 408 | 495 | * @param {string} putType |
| 409 | 496 | */ |
| 410 | 497 | const handleUploadImage = (orderId, putType) => { |
| 411 | - uni.$u.route(`pages/order/upload/index?orderId=${orderId}&putType=${putType}`) | |
| 498 | + uni.$u.route(`pages/order/upload/index?orderId=${orderId}`) | |
| 499 | +} | |
| 500 | + | |
| 501 | + | |
| 502 | +const handleDispatchConfirm = (val) => { | |
| 503 | + console.log(val); | |
| 504 | + if (!val) { | |
| 505 | + return | |
| 506 | + } | |
| 507 | + let data = { | |
| 508 | + garOrderId: orderId.value, | |
| 509 | + dispatchList: [] | |
| 510 | + } | |
| 511 | + for (const key in val) { | |
| 512 | + data.dispatchList.push({ | |
| 513 | + ...val[key] | |
| 514 | + }); | |
| 515 | + } | |
| 516 | + console.log(data); | |
| 517 | + dispatchOrders(data).then(res => { | |
| 518 | + if (res.data.success) { | |
| 519 | + uni.$u.toast(res.data.msg) | |
| 520 | + } else { | |
| 521 | + uni.$u.toast("派单下发失败,请重试") | |
| 522 | + } | |
| 523 | + clashDispatchRef.value.close() | |
| 524 | + }) | |
| 412 | 525 | } |
| 413 | 526 | |
| 414 | 527 | /** |
| ... | ... | @@ -418,14 +531,21 @@ onLoad((options) => { |
| 418 | 531 | orderId.value = options.orderId |
| 419 | 532 | handleOrderDetail(orderId.value) |
| 420 | 533 | }) |
| 421 | -onReady(() => { | |
| 422 | - // 生成二维码 | |
| 423 | - nextTick(() => { | |
| 424 | - | |
| 425 | - }) | |
| 426 | -}) | |
| 427 | - | |
| 428 | 534 | |
| 535 | +// onShow(() => { | |
| 536 | +// try { | |
| 537 | +// let pages = getCurrentPages(); | |
| 538 | +// let currPage = pages[pages.length - 1]; | |
| 539 | +// if (currPage.__data__.isRefresh) { | |
| 540 | +// // 重新获取数据 | |
| 541 | +// this.getData(true)//获取列表数据 | |
| 542 | +// // 每一次需要清除,否则会参数会缓存 | |
| 543 | +// currPage.__data__.isRefresh = false | |
| 544 | +// } | |
| 545 | +// } catch (error) { | |
| 546 | +// console.log(error); | |
| 547 | +// } | |
| 548 | +// }) | |
| 429 | 549 | </script> |
| 430 | 550 | |
| 431 | 551 | <style lang="scss" scoped> | ... | ... |
garbage-removal/src/pages/order/evaluate-info/index.vue
| ... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 | <view class="user-info-title"> |
| 25 | 25 | <u-avatar :src="pic" size="70"></u-avatar> |
| 26 | 26 | <view class="user-name"> |
| 27 | - 司机 | |
| 27 | + 企业负责人 | |
| 28 | 28 | </view> |
| 29 | 29 | </view> |
| 30 | 30 | <view v-if="evaluateManager" class="evaluate-content"> |
| ... | ... | @@ -55,7 +55,7 @@ const maxStar = ref([]) |
| 55 | 55 | |
| 56 | 56 | // 用户评价对象 |
| 57 | 57 | const evaluateUser = ref() |
| 58 | -// 司机评价 | |
| 58 | +// 企业负责人评价 | |
| 59 | 59 | const evaluateManager = ref() |
| 60 | 60 | onLoad((options) => { |
| 61 | 61 | for (let index = 0; index < maxScore; index++) { | ... | ... |
garbage-removal/src/pages/order/success/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <view> | |
| 3 | + 完成界面{{ orderId }} | |
| 4 | + </view> | |
| 5 | +</template> | |
| 6 | + | |
| 7 | +<script setup> | |
| 8 | +import { | |
| 9 | + onLoad | |
| 10 | +} from '@dcloudio/uni-app'; | |
| 11 | +import { ref } from 'vue'; | |
| 12 | +const orderId = ref() | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | +onLoad((options) => { | |
| 17 | + orderId.value = options.orderId | |
| 18 | +}) | |
| 19 | +</script> | |
| 20 | + | |
| 21 | +<style lang="scss" scoped> | |
| 22 | +</style> | ... | ... |
garbage-removal/src/pages/order/swiper-list-item/index.vue
| ... | ... | @@ -10,16 +10,21 @@ |
| 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 && 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> | |
| 13 | + <view style="display: flex;align-items: center;"> | |
| 14 | + <text v-if="item.garOrderHandlerStatus != 3 && item.garOrderStatus === 3 && userType === '运输驾驶员'" | |
| 15 | + style="font-size: small;color: #f56c6c;">派单已经完成了。</text> | |
| 16 | + <view v-if="item.garOrderHandlerStatus === 0 && item.garCancelFlag === 0" class="right">待清运 </view> | |
| 17 | + <view v-if="item.garCancelFlag === 1" class="right">已取消 </view> | |
| 18 | + <view v-if="item.garOrderHandlerStatus === 1 && item.garCancelFlag === 0" class="right">清运中 </view> | |
| 19 | + <view v-if="item.garOrderHandlerStatus === 3 && userType === '运输驾驶员'" class="right">已完成 </view> | |
| 20 | + </view> | |
| 16 | 21 | <view v-if="item.garEvaluateFlag === 0 && userType === '居民用户'" class="right">待评价 |
| 17 | 22 | </view> |
| 18 | - <view v-if="item.garHandlerEvaluateFlag === 0 && userType === '司机'" class="right">待评价 | |
| 23 | + <view v-if="item.garHandlerEvaluateFlag === 0 && userType === '企业负责人'" class="right">待评价 | |
| 19 | 24 | </view> |
| 20 | 25 | <view v-if="item.garEvaluateFlag === 1 && userType === '居民用户'" class="right">已评价 |
| 21 | 26 | </view> |
| 22 | - <view v-if="item.garHandlerEvaluateFlag === 1 && userType === '司机'" class="right">已评价 | |
| 27 | + <view v-if="item.garHandlerEvaluateFlag === 1 && userType === '企业负责人'" class="right">已评价 | |
| 23 | 28 | </view> |
| 24 | 29 | </view> |
| 25 | 30 | <view class="item" @click="handleClick(item.garOrderId)"> |
| ... | ... | @@ -49,7 +54,7 @@ |
| 49 | 54 | </view> |
| 50 | 55 | <!-- 公司对用户评价 --> |
| 51 | 56 | <view class="bottom" |
| 52 | - v-if="item.garHandlerEvaluateFlag === 0 && item.garOrderHandlerStatus === 3 && userType === '司机'"> | |
| 57 | + v-if="item.garHandlerEvaluateFlag === 0 && item.garOrderHandlerStatus === 3 && userType === '企业负责人'"> | |
| 53 | 58 | <view class="more"> |
| 54 | 59 | <!-- <u-icon name="more-dot-fill" color="rgb(203,203,203)"></u-icon> --> |
| 55 | 60 | </view> | ... | ... |
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">请上传{{ putType }}图片类型:</text> | |
| 4 | + <text class="upload-image-box-choose-txt">请选着上传图片类型:</text> | |
| 5 | 5 | <view class="upload-image-box-choose-type"> |
| 6 | - | |
| 6 | + <u-radio-group v-model="putType" @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> | |
| 7 | 11 | </view> |
| 8 | 12 | </view> |
| 9 | 13 | <view class="upload-image-box-bottom"> |
| ... | ... | @@ -27,10 +31,11 @@ |
| 27 | 31 | import { uploadFilePromise } from '@/apis/common.js'; |
| 28 | 32 | import { uploadImageUrlByType } from '@/apis/order.js'; |
| 29 | 33 | import { onLoad } from '@dcloudio/uni-app'; |
| 30 | -import { ref } from 'vue'; | |
| 31 | -const putType = ref("") | |
| 34 | +import { reactive, ref } from 'vue'; | |
| 35 | +const putType = ref("装车图片") | |
| 32 | 36 | const orderId = ref(); |
| 33 | 37 | const fileList = ref([]) |
| 38 | +const chooseList = reactive([{ name: "装车图片" }, { name: "卸车图片" }]) | |
| 34 | 39 | // 删除图片 |
| 35 | 40 | const deletePic = (event) => { |
| 36 | 41 | fileList.value.splice(event.index, 1); |
| ... | ... | @@ -71,15 +76,20 @@ const handleSubmit = (id, type) => { |
| 71 | 76 | } |
| 72 | 77 | let params = { |
| 73 | 78 | garOrderId: id, |
| 74 | - type: type == "装车照片" ? 1 : 2, | |
| 79 | + type: type == "装车图片" ? 1 : 2, | |
| 75 | 80 | imageUrls: fileList.value.map(item => item.url) |
| 76 | 81 | } |
| 77 | 82 | uploadImageUrlByType(params).then(res => { |
| 78 | 83 | if (res.data.success) { |
| 79 | 84 | uni.$u.toast("图片上传完毕!"); |
| 80 | - uni.$u.route({ | |
| 81 | - type: "navigateBack", | |
| 82 | - url: "pages/order/detail/index" | |
| 85 | + let pages = getCurrentPages(); | |
| 86 | + console.log(pages); | |
| 87 | + uni.navigateBack({ | |
| 88 | + delta: 1, | |
| 89 | + success() { | |
| 90 | + //pages.length-1 即最后一个为当前页,所以取当前页面的上一级 | |
| 91 | + pages[pages.length - 2].$vm.handleOrderDetail(id); // init 是上一个页面的方法名称 | |
| 92 | + } | |
| 83 | 93 | }) |
| 84 | 94 | } |
| 85 | 95 | }) |
| ... | ... | @@ -97,7 +107,8 @@ const validateImage = () => { |
| 97 | 107 | |
| 98 | 108 | onLoad((options) => { |
| 99 | 109 | orderId.value = options.orderId; |
| 100 | - putType.value = options.putType === "putOnImages" ? "装车照片" : "卸车照片"; | |
| 110 | + // putType.value = options.putType === "putOnImages" ? "装车图片" : "卸车图片"; | |
| 111 | + | |
| 101 | 112 | }) |
| 102 | 113 | </script> |
| 103 | 114 | ... | ... |
garbage-removal/src/pages/wode/choose/index.vue
| ... | ... | @@ -2,21 +2,34 @@ |
| 2 | 2 | <view class="wrap"> |
| 3 | 3 | <u-radio-group v-model="userType" placement="row" @change="groupChange"> |
| 4 | 4 | <view class="choose-type" v-for="(item, index) in typeList"> |
| 5 | - <u-radio :customStyle="{ marginBottom: '8px' }" size="28" labelSize="28" :key="index" :label="item.name" | |
| 6 | - :name="item.name" @change="radioChange"> | |
| 5 | + <u-radio size="28" labelSize="28" :key="index" :label="item.name" :name="item.name" @change="radioChange"> | |
| 7 | 6 | </u-radio> |
| 8 | - <view class="manager-info" v-if="item.name === '司机' && unitInfo.companyFlag"> | |
| 9 | - <view class="manager-info-parent-company-name"> | |
| 10 | - <text style="margin-right: 20rpx;">经营公司:</text> | |
| 11 | - <text>{{ unitInfo.parentCompanyName }}</text> | |
| 12 | - </view> | |
| 13 | - <view class="manager-info-transport-company-name"> | |
| 14 | - <text style="margin-right: 20rpx;">运输公司:</text> | |
| 15 | - <text>{{ unitInfo.transportCompanyName }}</text> | |
| 16 | - </view> | |
| 17 | - </view> | |
| 18 | 7 | </view> |
| 19 | 8 | </u-radio-group> |
| 9 | + <!-- 角色信息匹配 --> | |
| 10 | + <view class="rule-label-info-box"> | |
| 11 | + <view class="manager-info" v-if="userType === '居民用户'"> | |
| 12 | + <view class="manager-info-parent-company-name"> | |
| 13 | + 派单前请输先完善地址信息~ | |
| 14 | + </view> | |
| 15 | + </view> | |
| 16 | + <view class="manager-info" v-if="userType === '运输驾驶员'"> | |
| 17 | + <view class="manager-info-parent-company-name"> | |
| 18 | + 长沙有限运输运输公司-运输驾驶员-李伟 | |
| 19 | + </view> | |
| 20 | + <view class="manager-info-parent-company-name"> | |
| 21 | + 未匹配到该手机号绑定的运输公司! | |
| 22 | + </view> | |
| 23 | + </view> | |
| 24 | + <view class="manager-info" v-if="userType === '企业负责人'"> | |
| 25 | + <view class="manager-info-parent-company-name"> | |
| 26 | + 长沙有限运输运输公司公司服务账号! | |
| 27 | + </view> | |
| 28 | + <view class="manager-info-parent-company-name"> | |
| 29 | + 未匹配到该手机号绑定运输公司公司服务账号! | |
| 30 | + </view> | |
| 31 | + </view> | |
| 32 | + </view> | |
| 20 | 33 | <view class="choose-button"> |
| 21 | 34 | <u-button shape="circle" color="#a9e08f" @click="submit(userType)">确定</u-button> |
| 22 | 35 | </view> |
| ... | ... | @@ -31,12 +44,13 @@ import { onLoad } from "@dcloudio/uni-app"; |
| 31 | 44 | import { ref } from 'vue'; |
| 32 | 45 | const store = useMainStore(); |
| 33 | 46 | const userType = ref("居民用户") |
| 34 | -const typeList = ref([{ name: "居民用户" }, { name: "司机" }]) | |
| 47 | +const typeList = ref([{ name: "居民用户" }, { name: "运输驾驶员" }, { name: "企业负责人" }]) | |
| 35 | 48 | const unitInfo = ref({}) |
| 36 | 49 | const radioChange = (e) => { |
| 37 | 50 | } |
| 38 | 51 | const groupChange = (e) => { |
| 39 | 52 | } |
| 53 | + | |
| 40 | 54 | const submit = (userType) => { |
| 41 | 55 | setRequestToken(store.tempToken) |
| 42 | 56 | updateUserInfo({ garUserType: userType }).then(res => { |
| ... | ... | @@ -56,10 +70,8 @@ const submit = (userType) => { |
| 56 | 70 | } |
| 57 | 71 | onLoad((options) => { |
| 58 | 72 | unitInfo.value = options |
| 59 | - unitInfo.value.companyFlag = JSON.parse(options.companyFlag) | |
| 60 | - if (unitInfo.value.companyFlag) { | |
| 61 | - userType.value = "司机" | |
| 62 | - } | |
| 73 | + userType.value = options.userType | |
| 74 | + // submit(options.userType) | |
| 63 | 75 | }) |
| 64 | 76 | </script> |
| 65 | 77 | |
| ... | ... | @@ -72,36 +84,39 @@ onLoad((options) => { |
| 72 | 84 | background-color: $u-info-light; |
| 73 | 85 | |
| 74 | 86 | .choose-type { |
| 75 | - width: 100%; | |
| 87 | + // width: 100%; | |
| 76 | 88 | box-sizing: border-box; |
| 77 | - padding: 30rpx; | |
| 89 | + padding: 20rpx; | |
| 78 | 90 | background-color: #ffffff; |
| 79 | 91 | border-radius: 20rpx; |
| 92 | + margin-right: 20rpx; | |
| 93 | + display: flex; | |
| 94 | + align-items: center; | |
| 95 | + justify-content: center; | |
| 80 | 96 | |
| 81 | - &:first-child { | |
| 97 | + &:last-child { | |
| 82 | 98 | margin-right: 20rpx; |
| 83 | 99 | } |
| 84 | 100 | |
| 101 | + | |
| 102 | + } | |
| 103 | + | |
| 104 | + .rule-label-info-box { | |
| 105 | + box-sizing: border-box; | |
| 106 | + margin-top: 20rpx; | |
| 107 | + | |
| 85 | 108 | .manager-info { |
| 86 | 109 | font-size: 25rpx; |
| 87 | 110 | color: $u-main-color; |
| 88 | 111 | box-sizing: border-box; |
| 89 | 112 | |
| 90 | 113 | .manager-info-parent-company-name { |
| 91 | - | |
| 92 | - text { | |
| 93 | - color: $u-info; | |
| 94 | - } | |
| 95 | - } | |
| 96 | - | |
| 97 | - .manager-info-transport-company-name { | |
| 98 | - text { | |
| 99 | - color: $u-info; | |
| 100 | - } | |
| 114 | + color: $u-info; | |
| 101 | 115 | } |
| 102 | 116 | } |
| 103 | 117 | } |
| 104 | 118 | |
| 119 | + | |
| 105 | 120 | .choose-button { |
| 106 | 121 | position: relative; |
| 107 | 122 | width: 100%; | ... | ... |
garbage-removal/src/pages/wode/index.vue
| ... | ... | @@ -6,13 +6,15 @@ |
| 6 | 6 | </view> |
| 7 | 7 | <view class="u-flex-1"> |
| 8 | 8 | <view class="u-font-18 u-p-b-20">{{ userInfo.userType }}</view> |
| 9 | - <view class="manager-info" v-if="userInfo.companyFlag"> | |
| 10 | - <view class="manager-info-parent-company-name"> | |
| 11 | - <text style="margin-right: 20rpx;">经营公司:</text> | |
| 12 | - <text>{{ userInfo.parentCompanyName }}</text> | |
| 9 | + <view class="manager-info" v-if="userInfo.userType === '运输驾驶员'"> | |
| 10 | + <view class="manager-info-transport-company-name"> | |
| 11 | + <text style="margin-right: 20rpx;">所属运输公司:</text> | |
| 12 | + <text>{{ userInfo.transportCompanyName }}</text> | |
| 13 | 13 | </view> |
| 14 | + </view> | |
| 15 | + <view class="manager-info" v-if="userInfo.userType === '企业负责人'"> | |
| 14 | 16 | <view class="manager-info-transport-company-name"> |
| 15 | - <text style="margin-right: 20rpx;">运输公司:</text> | |
| 17 | + <text style="margin-right: 20rpx;">所属运输公司:</text> | |
| 16 | 18 | <text>{{ userInfo.transportCompanyName }}</text> |
| 17 | 19 | </view> |
| 18 | 20 | </view> | ... | ... |
garbage-removal/src/utils/request/request.js
garbage-removal/src/uview-plus/components/u-action-sheet/u-action-sheet.vue
| ... | ... | @@ -39,7 +39,7 @@ |
| 39 | 39 | <!-- #endif --> |
| 40 | 40 | <view v-if="item.name == '其他'" class="u-action-sheet__item-wrap__item" :hover-stay-time="150"> |
| 41 | 41 | <view class="parent-box"> |
| 42 | - <u-collapse> | |
| 42 | + <u-collapse @open="handleOpenMethod" @close="handleCloseMethod"> | |
| 43 | 43 | <u-collapse-item @selectHandler="selectHandler" :index="index" :name="item.name" ref="childRef" |
| 44 | 44 | title="其他" name="其他"> |
| 45 | 45 | <view class="u-collapse-content" style="width: 97vw;text-align: left;"> |
| ... | ... | @@ -151,6 +151,14 @@ export default { |
| 151 | 151 | }, |
| 152 | 152 | }, |
| 153 | 153 | methods: { |
| 154 | + handleOpenMethod(e) { | |
| 155 | + // console.log("开启", e); | |
| 156 | + this.accordion = true; | |
| 157 | + }, | |
| 158 | + handleCloseMethod(e) { | |
| 159 | + // console.log("关闭", e); | |
| 160 | + this.accordion = false; | |
| 161 | + }, | |
| 154 | 162 | closeHandler() { |
| 155 | 163 | // 允许点击遮罩关闭时,才发出close事件 |
| 156 | 164 | if (this.closeOnClickOverlay) { |
| ... | ... | @@ -162,6 +170,7 @@ export default { |
| 162 | 170 | this.$emit('actionSheetClose') |
| 163 | 171 | }, |
| 164 | 172 | selectHandler(index, name) { |
| 173 | + console.log(index, name); | |
| 165 | 174 | if (name != "其他") { |
| 166 | 175 | if (this.accordion) { |
| 167 | 176 | this.$refs.childRef[0].clickHandler("抽屉"); |
| ... | ... | @@ -169,9 +178,6 @@ export default { |
| 169 | 178 | } |
| 170 | 179 | this.otherReason = '' |
| 171 | 180 | } |
| 172 | - if (name == "其他") { | |
| 173 | - this.accordion = true; | |
| 174 | - } | |
| 175 | 181 | this.currentSelect = index; |
| 176 | 182 | const item = this.actions[index] |
| 177 | 183 | if (item && !item.disabled && !item.loading) { | ... | ... |
garbage-removal/src/uview-plus/components/u-checkbox-group/u-checkbox-group.vue
garbage-removal/src/uview-plus/components/u-number-box/u-number-box.vue
| 1 | 1 | <template> |
| 2 | 2 | <view class="u-number-box"> |
| 3 | - <view | |
| 4 | - class="u-number-box__slot" | |
| 5 | - @tap.stop="clickHandler('minus')" | |
| 6 | - @touchstart="onTouchStart('minus')" | |
| 7 | - @touchend.stop="clearTimeout" | |
| 8 | - v-if="showMinus && $slots.minus" | |
| 9 | - > | |
| 3 | + <view class="u-number-box__slot" @tap.stop="clickHandler('minus')" @touchstart="onTouchStart('minus')" | |
| 4 | + @touchend.stop="clearTimeout" v-if="showMinus && $slots.minus"> | |
| 10 | 5 | <slot name="minus" /> |
| 11 | 6 | </view> |
| 12 | - <view | |
| 13 | - v-else-if="showMinus" | |
| 14 | - class="u-number-box__minus" | |
| 15 | - @tap.stop="clickHandler('minus')" | |
| 16 | - @touchstart="onTouchStart('minus')" | |
| 17 | - @touchend.stop="clearTimeout" | |
| 18 | - hover-class="u-number-box__minus--hover" | |
| 19 | - hover-stay-time="150" | |
| 20 | - :class="{ 'u-number-box__minus--disabled': isDisabled('minus') }" | |
| 21 | - :style="[buttonStyle('minus')]" | |
| 22 | - > | |
| 23 | - <u-icon | |
| 24 | - name="minus" | |
| 25 | - :color="isDisabled('minus') ? '#c8c9cc' : '#323233'" | |
| 26 | - size="15" | |
| 27 | - bold | |
| 28 | - :customStyle="iconStyle" | |
| 29 | - ></u-icon> | |
| 7 | + <view v-else-if="showMinus" class="u-number-box__minus" @tap.stop="clickHandler('minus')" | |
| 8 | + @touchstart="onTouchStart('minus')" @touchend.stop="clearTimeout" hover-class="u-number-box__minus--hover" | |
| 9 | + hover-stay-time="150" :class="{ 'u-number-box__minus--disabled': isDisabled('minus') }" | |
| 10 | + :style="[buttonStyle('minus')]"> | |
| 11 | + <u-icon name="minus" :color="isDisabled('minus') ? '#c8c9cc' : '#323233'" size="15" bold | |
| 12 | + :customStyle="iconStyle"></u-icon> | |
| 30 | 13 | </view> |
| 31 | 14 | |
| 32 | 15 | <slot name="input"> |
| 33 | - <input | |
| 34 | - :disabled="disabledInput || disabled" | |
| 35 | - :cursor-spacing="getCursorSpacing" | |
| 36 | - :class="{ 'u-number-box__input--disabled': disabled || disabledInput }" | |
| 37 | - v-model="currentValue" | |
| 38 | - class="u-number-box__input" | |
| 39 | - @blur="onBlur" | |
| 40 | - @focus="onFocus" | |
| 41 | - @input="onInput" | |
| 42 | - type="number" | |
| 43 | - :style="[inputStyle]" | |
| 44 | - /> | |
| 16 | + <input :disabled="disabledInput || disabled" :cursor-spacing="getCursorSpacing" | |
| 17 | + :class="{ 'u-number-box__input--disabled': disabled || disabledInput }" v-model="currentValue" | |
| 18 | + class="u-number-box__input" @blur="onBlur" @focus="onFocus" @input="onInput" type="number" | |
| 19 | + :style="[inputStyle]" /> | |
| 45 | 20 | </slot> |
| 46 | - <view | |
| 47 | - class="u-number-box__slot" | |
| 48 | - @tap.stop="clickHandler('plus')" | |
| 49 | - @touchstart="onTouchStart('plus')" | |
| 50 | - @touchend.stop="clearTimeout" | |
| 51 | - v-if="showPlus && $slots.plus" | |
| 52 | - > | |
| 21 | + <view class="u-number-box__slot" @tap.stop="clickHandler('plus')" @touchstart="onTouchStart('plus')" | |
| 22 | + @touchend.stop="clearTimeout" v-if="showPlus && $slots.plus"> | |
| 53 | 23 | <slot name="plus" /> |
| 54 | 24 | </view> |
| 55 | - <view | |
| 56 | - v-else-if="showPlus" | |
| 57 | - class="u-number-box__plus" | |
| 58 | - @tap.stop="clickHandler('plus')" | |
| 59 | - @touchstart="onTouchStart('plus')" | |
| 60 | - @touchend.stop="clearTimeout" | |
| 61 | - hover-class="u-number-box__plus--hover" | |
| 62 | - hover-stay-time="150" | |
| 63 | - :class="{ 'u-number-box__minus--disabled': isDisabled('plus') }" | |
| 64 | - :style="[buttonStyle('plus')]" | |
| 65 | - > | |
| 66 | - <u-icon | |
| 67 | - name="plus" | |
| 68 | - :color="isDisabled('plus') ? '#c8c9cc' : '#323233'" | |
| 69 | - size="15" | |
| 70 | - bold | |
| 71 | - :customStyle="iconStyle" | |
| 72 | - ></u-icon> | |
| 25 | + <view v-else-if="showPlus" class="u-number-box__plus" @tap.stop="clickHandler('plus')" | |
| 26 | + @touchstart="onTouchStart('plus')" @touchend.stop="clearTimeout" hover-class="u-number-box__plus--hover" | |
| 27 | + hover-stay-time="150" :class="{ 'u-number-box__minus--disabled': isDisabled('plus') }" | |
| 28 | + :style="[buttonStyle('plus')]"> | |
| 29 | + <u-icon name="plus" :color="isDisabled('plus') ? '#c8c9cc' : '#323233'" size="15" bold | |
| 30 | + :customStyle="iconStyle"></u-icon> | |
| 73 | 31 | </view> |
| 74 | 32 | </view> |
| 75 | 33 | </template> |
| 76 | 34 | |
| 77 | 35 | <script> |
| 78 | - import props from './props.js'; | |
| 79 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 80 | - import mixin from '../../libs/mixin/mixin.js'; | |
| 81 | - /** | |
| 82 | - * numberBox 步进器 | |
| 83 | - * @description 该组件一般用于商城购物选择物品数量的场景。 | |
| 84 | - * @tutorial https://uviewui.com/components/numberBox.html | |
| 85 | - * @property {String | Number} name 步进器标识符,在change回调返回 | |
| 86 | - * @property {String | Number} value 用于双向绑定的值,初始化时设置设为默认min值(最小值) (默认 0 ) | |
| 87 | - * @property {String | Number} min 最小值 (默认 1 ) | |
| 88 | - * @property {String | Number} max 最大值 (默认 Number.MAX_SAFE_INTEGER ) | |
| 89 | - * @property {String | Number} step 加减的步长,可为小数 (默认 1 ) | |
| 90 | - * @property {Boolean} integer 是否只允许输入整数 (默认 false ) | |
| 91 | - * @property {Boolean} disabled 是否禁用,包括输入框,加减按钮 (默认 false ) | |
| 92 | - * @property {Boolean} disabledInput 是否禁用输入框 (默认 false ) | |
| 93 | - * @property {Boolean} asyncChange 是否开启异步变更,开启后需要手动控制输入值 (默认 false ) | |
| 94 | - * @property {String | Number} inputWidth 输入框宽度,单位为px (默认 35 ) | |
| 95 | - * @property {Boolean} showMinus 是否显示减少按钮 (默认 true ) | |
| 96 | - * @property {Boolean} showPlus 是否显示增加按钮 (默认 true ) | |
| 97 | - * @property {String | Number} decimalLength 显示的小数位数 | |
| 98 | - * @property {Boolean} longPress 是否开启长按加减手势 (默认 true ) | |
| 99 | - * @property {String} color 输入框文字和加减按钮图标的颜色 (默认 '#323233' ) | |
| 100 | - * @property {String | Number} buttonSize 按钮大小,宽高等于此值,单位px,输入框高度和此值保持一致 (默认 30 ) | |
| 101 | - * @property {String} bgColor 输入框和按钮的背景颜色 (默认 '#EBECEE' ) | |
| 102 | - * @property {String | Number} cursorSpacing 指定光标于键盘的距离,避免键盘遮挡输入框,单位px (默认 100 ) | |
| 103 | - * @property {Boolean} disablePlus 是否禁用增加按钮 (默认 false ) | |
| 104 | - * @property {Boolean} disableMinus 是否禁用减少按钮 (默认 false ) | |
| 105 | - * @property {Object | String} iconStyle 加减按钮图标的样式 | |
| 106 | - * | |
| 107 | - * @event {Function} onFocus 输入框活动焦点 | |
| 108 | - * @event {Function} onBlur 输入框失去焦点 | |
| 109 | - * @event {Function} onInput 输入框值发生变化 | |
| 110 | - * @event {Function} onChange | |
| 111 | - * @example <u-number-box v-model="value" @change="valChange"></u-number-box> | |
| 112 | - */ | |
| 113 | - export default { | |
| 114 | - name: 'u-number-box', | |
| 115 | - mixins: [mpMixin, mixin, props], | |
| 116 | - data() { | |
| 117 | - return { | |
| 118 | - // 输入框实际操作的值 | |
| 119 | - currentValue: '', | |
| 120 | - // 定时器 | |
| 121 | - longPressTimer: null | |
| 122 | - } | |
| 36 | +import mixin from '../../libs/mixin/mixin.js'; | |
| 37 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | |
| 38 | +import props from './props.js'; | |
| 39 | +/** | |
| 40 | + * numberBox 步进器 | |
| 41 | + * @description 该组件一般用于商城购物选择物品数量的场景。 | |
| 42 | + * @tutorial https://uviewui.com/components/numberBox.html | |
| 43 | + * @property {String | Number} name 步进器标识符,在change回调返回 | |
| 44 | + * @property {String | Number} value 用于双向绑定的值,初始化时设置设为默认min值(最小值) (默认 0 ) | |
| 45 | + * @property {String | Number} min 最小值 (默认 1 ) | |
| 46 | + * @property {String | Number} max 最大值 (默认 Number.MAX_SAFE_INTEGER ) | |
| 47 | + * @property {String | Number} step 加减的步长,可为小数 (默认 1 ) | |
| 48 | + * @property {Boolean} integer 是否只允许输入整数 (默认 false ) | |
| 49 | + * @property {Boolean} disabled 是否禁用,包括输入框,加减按钮 (默认 false ) | |
| 50 | + * @property {Boolean} disabledInput 是否禁用输入框 (默认 false ) | |
| 51 | + * @property {Boolean} asyncChange 是否开启异步变更,开启后需要手动控制输入值 (默认 false ) | |
| 52 | + * @property {String | Number} inputWidth 输入框宽度,单位为px (默认 35 ) | |
| 53 | + * @property {Boolean} showMinus 是否显示减少按钮 (默认 true ) | |
| 54 | + * @property {Boolean} showPlus 是否显示增加按钮 (默认 true ) | |
| 55 | + * @property {String | Number} decimalLength 显示的小数位数 | |
| 56 | + * @property {Boolean} longPress 是否开启长按加减手势 (默认 true ) | |
| 57 | + * @property {String} color 输入框文字和加减按钮图标的颜色 (默认 '#323233' ) | |
| 58 | + * @property {String | Number} buttonSize 按钮大小,宽高等于此值,单位px,输入框高度和此值保持一致 (默认 30 ) | |
| 59 | + * @property {String} bgColor 输入框和按钮的背景颜色 (默认 '#EBECEE' ) | |
| 60 | + * @property {String | Number} cursorSpacing 指定光标于键盘的距离,避免键盘遮挡输入框,单位px (默认 100 ) | |
| 61 | + * @property {Boolean} disablePlus 是否禁用增加按钮 (默认 false ) | |
| 62 | + * @property {Boolean} disableMinus 是否禁用减少按钮 (默认 false ) | |
| 63 | + * @property {Object | String} iconStyle 加减按钮图标的样式 | |
| 64 | + * | |
| 65 | + * @event {Function} onFocus 输入框活动焦点 | |
| 66 | + * @event {Function} onBlur 输入框失去焦点 | |
| 67 | + * @event {Function} onInput 输入框值发生变化 | |
| 68 | + * @event {Function} onChange | |
| 69 | + * @example <u-number-box v-model="value" @change="valChange"></u-number-box> | |
| 70 | + */ | |
| 71 | +export default { | |
| 72 | + name: 'u-number-box', | |
| 73 | + mixins: [mpMixin, mixin, props], | |
| 74 | + data() { | |
| 75 | + return { | |
| 76 | + // 输入框实际操作的值 | |
| 77 | + currentValue: '', | |
| 78 | + // 定时器 | |
| 79 | + longPressTimer: null | |
| 80 | + } | |
| 81 | + }, | |
| 82 | + watch: { | |
| 83 | + // 多个值之间,只要一个值发生变化,都要重新检查check()函数 | |
| 84 | + watchChange(n) { | |
| 85 | + this.check() | |
| 123 | 86 | }, |
| 124 | - watch: { | |
| 125 | - // 多个值之间,只要一个值发生变化,都要重新检查check()函数 | |
| 126 | - watchChange(n) { | |
| 127 | - this.check() | |
| 128 | - }, | |
| 129 | - // #ifdef VUE2 | |
| 130 | - // 监听v-mode的变化,重新初始化内部的值 | |
| 131 | - value(n) { | |
| 132 | - if (n !== this.currentValue) { | |
| 133 | - this.currentValue = this.format(this.value) | |
| 134 | - } | |
| 135 | - }, | |
| 136 | - // #endif | |
| 137 | - // #ifdef VUE3 | |
| 138 | - // 监听v-mode的变化,重新初始化内部的值 | |
| 139 | - modelValue(n) { | |
| 140 | - if (n !== this.currentValue) { | |
| 141 | - this.currentValue = this.format(this.modelValue) | |
| 142 | - } | |
| 87 | + // #ifdef VUE2 | |
| 88 | + // 监听v-mode的变化,重新初始化内部的值 | |
| 89 | + value(n) { | |
| 90 | + if (n !== this.currentValue) { | |
| 91 | + this.currentValue = this.format(this.value) | |
| 143 | 92 | } |
| 144 | - // #endif | |
| 145 | 93 | }, |
| 146 | - computed: { | |
| 147 | - getCursorSpacing() { | |
| 148 | - // 判断传入的单位,如果为px单位,需要转成px | |
| 149 | - return uni.$u.getPx(this.cursorSpacing) | |
| 150 | - }, | |
| 151 | - // 按钮的样式 | |
| 152 | - buttonStyle() { | |
| 153 | - return (type) => { | |
| 154 | - const style = { | |
| 155 | - backgroundColor: this.bgColor, | |
| 156 | - height: uni.$u.addUnit(this.buttonSize), | |
| 157 | - color: this.color | |
| 158 | - } | |
| 159 | - if (this.isDisabled(type)) { | |
| 160 | - style.backgroundColor = '#f7f8fa' | |
| 161 | - } | |
| 162 | - return style | |
| 94 | + // #endif | |
| 95 | + // 监听v-mode的变化,重新初始化内部的值 | |
| 96 | + | |
| 97 | + // #ifdef VUE3 | |
| 98 | + // modelValue(n) { | |
| 99 | + // console.log("n", n); | |
| 100 | + // console.log("this.currentValue", this.currentValue); | |
| 101 | + // if (n !== this.currentValue) { | |
| 102 | + // this.currentValue = this.format(this.modelValue) | |
| 103 | + // } | |
| 104 | + // }, | |
| 105 | + modelValue: { | |
| 106 | + handler: function (newV, oldV) { | |
| 107 | + if (newV !== this.currentValue) { | |
| 108 | + this.currentValue = this.format(this.modelValue) | |
| 163 | 109 | } |
| 164 | 110 | }, |
| 165 | - // 输入框的样式 | |
| 166 | - inputStyle() { | |
| 167 | - const disabled = this.disabled || this.disabledInput | |
| 111 | + immediate: true | |
| 112 | + } | |
| 113 | + // #endif | |
| 114 | + }, | |
| 115 | + computed: { | |
| 116 | + getCursorSpacing() { | |
| 117 | + // 判断传入的单位,如果为px单位,需要转成px | |
| 118 | + return uni.$u.getPx(this.cursorSpacing) | |
| 119 | + }, | |
| 120 | + // 按钮的样式 | |
| 121 | + buttonStyle() { | |
| 122 | + return (type) => { | |
| 168 | 123 | const style = { |
| 169 | - color: this.color, | |
| 170 | 124 | backgroundColor: this.bgColor, |
| 171 | 125 | height: uni.$u.addUnit(this.buttonSize), |
| 172 | - width: uni.$u.addUnit(this.inputWidth) | |
| 126 | + color: this.color | |
| 127 | + } | |
| 128 | + if (this.isDisabled(type)) { | |
| 129 | + style.backgroundColor = '#f7f8fa' | |
| 173 | 130 | } |
| 174 | 131 | return style |
| 175 | - }, | |
| 176 | - // 用于监听多个值发生变化 | |
| 177 | - watchChange() { | |
| 178 | - return [this.integer, this.decimalLength, this.min, this.max] | |
| 179 | - }, | |
| 180 | - isDisabled() { | |
| 181 | - return (type) => { | |
| 182 | - if (type === 'plus') { | |
| 183 | - // 在点击增加按钮情况下,判断整体的disabled,是否单独禁用增加按钮,以及当前值是否大于最大的允许值 | |
| 184 | - return ( | |
| 185 | - this.disabled || | |
| 186 | - this.disablePlus || | |
| 187 | - this.currentValue >= this.max | |
| 188 | - ) | |
| 189 | - } | |
| 190 | - // 点击减少按钮同理 | |
| 132 | + } | |
| 133 | + }, | |
| 134 | + // 输入框的样式 | |
| 135 | + inputStyle() { | |
| 136 | + const disabled = this.disabled || this.disabledInput | |
| 137 | + const style = { | |
| 138 | + color: this.color, | |
| 139 | + backgroundColor: this.bgColor, | |
| 140 | + height: uni.$u.addUnit(this.buttonSize), | |
| 141 | + width: uni.$u.addUnit(this.inputWidth) | |
| 142 | + } | |
| 143 | + return style | |
| 144 | + }, | |
| 145 | + // 用于监听多个值发生变化 | |
| 146 | + watchChange() { | |
| 147 | + return [this.integer, this.decimalLength, this.min, this.max] | |
| 148 | + }, | |
| 149 | + isDisabled() { | |
| 150 | + return (type) => { | |
| 151 | + if (type === 'plus') { | |
| 152 | + // 在点击增加按钮情况下,判断整体的disabled,是否单独禁用增加按钮,以及当前值是否大于最大的允许值 | |
| 191 | 153 | return ( |
| 192 | 154 | this.disabled || |
| 193 | - this.disableMinus || | |
| 194 | - this.currentValue <= this.min | |
| 155 | + this.disablePlus || | |
| 156 | + this.currentValue >= this.max | |
| 195 | 157 | ) |
| 196 | 158 | } |
| 197 | - }, | |
| 159 | + // 点击减少按钮同理 | |
| 160 | + return ( | |
| 161 | + this.disabled || | |
| 162 | + this.disableMinus || | |
| 163 | + this.currentValue <= this.min | |
| 164 | + ) | |
| 165 | + } | |
| 198 | 166 | }, |
| 199 | - mounted() { | |
| 200 | - this.init() | |
| 167 | + }, | |
| 168 | + mounted() { | |
| 169 | + this.init() | |
| 170 | + }, | |
| 171 | + // #ifdef VUE3 | |
| 172 | + emits: ['update:modelValue', 'focus', 'blur', 'overlimit', 'change', 'plus', 'minus'], | |
| 173 | + // #endif | |
| 174 | + methods: { | |
| 175 | + init() { | |
| 176 | + // #ifdef VUE3 | |
| 177 | + this.currentValue = this.format(this.modelValue) | |
| 178 | + // #endif | |
| 179 | + // #ifdef VUE2 | |
| 180 | + this.currentValue = this.format(this.value) | |
| 181 | + // #endif | |
| 201 | 182 | }, |
| 202 | - // #ifdef VUE3 | |
| 203 | - emits: ['update:modelValue', 'focus', 'blur', 'overlimit', 'change', 'plus', 'minus'], | |
| 204 | - // #endif | |
| 205 | - methods: { | |
| 206 | - init() { | |
| 207 | - // #ifdef VUE3 | |
| 208 | - this.currentValue = this.format(this.modelValue) | |
| 209 | - // #endif | |
| 210 | - // #ifdef VUE2 | |
| 211 | - this.currentValue = this.format(this.value) | |
| 212 | - // #endif | |
| 213 | - }, | |
| 214 | - // 格式化整理数据,限制范围 | |
| 215 | - format(value) { | |
| 216 | - value = this.filter(value) | |
| 217 | - // 如果为空字符串,那么设置为0,同时将值转为Number类型 | |
| 218 | - value = value === '' ? 0 : +value | |
| 219 | - // 对比最大最小值,取在min和max之间的值 | |
| 220 | - value = Math.max(Math.min(this.max, value), this.min) | |
| 221 | - // 如果设定了最大的小数位数,使用toFixed去进行格式化 | |
| 222 | - if (this.decimalLength !== null) { | |
| 223 | - value = value.toFixed(this.decimalLength) | |
| 224 | - } | |
| 225 | - return value | |
| 226 | - }, | |
| 227 | - // 过滤非法的字符 | |
| 228 | - filter(value) { | |
| 229 | - // 只允许0-9之间的数字,"."为小数点,"-"为负数时候使用 | |
| 230 | - value = String(value).replace(/[^0-9.-]/g, '') | |
| 231 | - // 如果只允许输入整数,则过滤掉小数点后的部分 | |
| 232 | - if (this.integer && value.indexOf('.') !== -1) { | |
| 233 | - value = value.split('.')[0] | |
| 234 | - } | |
| 235 | - return value; | |
| 236 | - }, | |
| 237 | - check() { | |
| 238 | - // 格式化了之后,如果前后的值不相等,那么设置为格式化后的值 | |
| 239 | - const val = this.format(this.currentValue); | |
| 240 | - if (val !== this.currentValue) { | |
| 241 | - this.currentValue = val | |
| 242 | - } | |
| 243 | - }, | |
| 244 | - // 判断是否出于禁止操作状态 | |
| 245 | - // isDisabled(type) { | |
| 246 | - // if (type === 'plus') { | |
| 247 | - // // 在点击增加按钮情况下,判断整体的disabled,是否单独禁用增加按钮,以及当前值是否大于最大的允许值 | |
| 248 | - // return ( | |
| 249 | - // this.disabled || | |
| 250 | - // this.disablePlus || | |
| 251 | - // this.currentValue >= this.max | |
| 252 | - // ) | |
| 253 | - // } | |
| 254 | - // // 点击减少按钮同理 | |
| 255 | - // return ( | |
| 256 | - // this.disabled || | |
| 257 | - // this.disableMinus || | |
| 258 | - // this.currentValue <= this.min | |
| 259 | - // ) | |
| 260 | - // }, | |
| 261 | - // 输入框活动焦点 | |
| 262 | - onFocus(event) { | |
| 263 | - this.$emit('focus', { | |
| 264 | - ...event.detail, | |
| 265 | - name: this.name, | |
| 183 | + // 格式化整理数据,限制范围 | |
| 184 | + format(value) { | |
| 185 | + value = this.filter(value) | |
| 186 | + // 如果为空字符串,那么设置为0,同时将值转为Number类型 | |
| 187 | + value = value === '' ? 0 : +value | |
| 188 | + // 对比最大最小值,取在min和max之间的值 | |
| 189 | + value = Math.max(Math.min(this.max, value), this.min) | |
| 190 | + // 如果设定了最大的小数位数,使用toFixed去进行格式化 | |
| 191 | + if (this.decimalLength !== null) { | |
| 192 | + value = value.toFixed(this.decimalLength) | |
| 193 | + } | |
| 194 | + return value | |
| 195 | + }, | |
| 196 | + // 过滤非法的字符 | |
| 197 | + filter(value) { | |
| 198 | + // 只允许0-9之间的数字,"."为小数点,"-"为负数时候使用 | |
| 199 | + value = String(value).replace(/[^0-9.-]/g, '') | |
| 200 | + // 如果只允许输入整数,则过滤掉小数点后的部分 | |
| 201 | + if (this.integer && value.indexOf('.') !== -1) { | |
| 202 | + value = value.split('.')[0] | |
| 203 | + } | |
| 204 | + return value; | |
| 205 | + }, | |
| 206 | + check() { | |
| 207 | + // 格式化了之后,如果前后的值不相等,那么设置为格式化后的值 | |
| 208 | + const val = this.format(this.currentValue); | |
| 209 | + if (val !== this.currentValue) { | |
| 210 | + this.currentValue = val | |
| 211 | + } | |
| 212 | + }, | |
| 213 | + // 判断是否出于禁止操作状态 | |
| 214 | + // isDisabled(type) { | |
| 215 | + // if (type === 'plus') { | |
| 216 | + // // 在点击增加按钮情况下,判断整体的disabled,是否单独禁用增加按钮,以及当前值是否大于最大的允许值 | |
| 217 | + // return ( | |
| 218 | + // this.disabled || | |
| 219 | + // this.disablePlus || | |
| 220 | + // this.currentValue >= this.max | |
| 221 | + // ) | |
| 222 | + // } | |
| 223 | + // // 点击减少按钮同理 | |
| 224 | + // return ( | |
| 225 | + // this.disabled || | |
| 226 | + // this.disableMinus || | |
| 227 | + // this.currentValue <= this.min | |
| 228 | + // ) | |
| 229 | + // }, | |
| 230 | + // 输入框活动焦点 | |
| 231 | + onFocus(event) { | |
| 232 | + this.$emit('focus', { | |
| 233 | + ...event.detail, | |
| 234 | + name: this.name, | |
| 235 | + }) | |
| 236 | + }, | |
| 237 | + // 输入框失去焦点 | |
| 238 | + onBlur(event) { | |
| 239 | + // 对输入值进行格式化 | |
| 240 | + const value = this.format(event.detail.value) | |
| 241 | + // 发出blur事件 | |
| 242 | + this.$emit( | |
| 243 | + 'blur', { | |
| 244 | + ...event.detail, | |
| 245 | + name: this.name, | |
| 246 | + } | |
| 247 | + ) | |
| 248 | + }, | |
| 249 | + // 输入框值发生变化 | |
| 250 | + onInput(e) { | |
| 251 | + const { | |
| 252 | + value = '' | |
| 253 | + } = e.detail || {} | |
| 254 | + // 为空返回 | |
| 255 | + if (value === '') return | |
| 256 | + let formatted = this.filter(value) | |
| 257 | + // 最大允许的小数长度 | |
| 258 | + if (this.decimalLength !== null && formatted.indexOf('.') !== -1) { | |
| 259 | + const pair = formatted.split('.'); | |
| 260 | + formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}` | |
| 261 | + } | |
| 262 | + formatted = this.format(formatted) | |
| 263 | + this.emitChange(formatted); | |
| 264 | + }, | |
| 265 | + // 发出change事件 | |
| 266 | + emitChange(value) { | |
| 267 | + // 如果开启了异步变更值,则不修改内部的值,需要用户手动在外部通过v-model变更 | |
| 268 | + if (!this.asyncChange) { | |
| 269 | + this.$nextTick(() => { | |
| 270 | + // #ifdef VUE3 | |
| 271 | + this.$emit('update:modelValue', value) | |
| 272 | + // #endif | |
| 273 | + // #ifdef VUE2 | |
| 274 | + this.$emit('input', value) | |
| 275 | + // #endif | |
| 276 | + this.currentValue = value | |
| 277 | + this.$forceUpdate() | |
| 266 | 278 | }) |
| 267 | - }, | |
| 268 | - // 输入框失去焦点 | |
| 269 | - onBlur(event) { | |
| 270 | - // 对输入值进行格式化 | |
| 271 | - const value = this.format(event.detail.value) | |
| 272 | - // 发出blur事件 | |
| 273 | - this.$emit( | |
| 274 | - 'blur',{ | |
| 275 | - ...event.detail, | |
| 276 | - name: this.name, | |
| 277 | - } | |
| 278 | - ) | |
| 279 | - }, | |
| 280 | - // 输入框值发生变化 | |
| 281 | - onInput(e) { | |
| 282 | - const { | |
| 283 | - value = '' | |
| 284 | - } = e.detail || {} | |
| 285 | - // 为空返回 | |
| 286 | - if (value === '') return | |
| 287 | - let formatted = this.filter(value) | |
| 288 | - // 最大允许的小数长度 | |
| 289 | - if (this.decimalLength !== null && formatted.indexOf('.') !== -1) { | |
| 290 | - const pair = formatted.split('.'); | |
| 291 | - formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}` | |
| 292 | - } | |
| 293 | - formatted = this.format(formatted) | |
| 294 | - this.emitChange(formatted); | |
| 295 | - }, | |
| 296 | - // 发出change事件 | |
| 297 | - emitChange(value) { | |
| 298 | - // 如果开启了异步变更值,则不修改内部的值,需要用户手动在外部通过v-model变更 | |
| 299 | - if (!this.asyncChange) { | |
| 300 | - this.$nextTick(() => { | |
| 301 | - // #ifdef VUE3 | |
| 302 | - this.$emit('update:modelValue', value) | |
| 303 | - // #endif | |
| 304 | - // #ifdef VUE2 | |
| 305 | - this.$emit('input', value) | |
| 306 | - // #endif | |
| 307 | - this.currentValue = value | |
| 308 | - this.$forceUpdate() | |
| 309 | - }) | |
| 310 | - } | |
| 311 | - this.$emit('change', { | |
| 312 | - value, | |
| 313 | - name: this.name, | |
| 314 | - }); | |
| 315 | - }, | |
| 316 | - onChange() { | |
| 317 | - const { | |
| 318 | - type | |
| 319 | - } = this | |
| 320 | - if (this.isDisabled(type)) { | |
| 321 | - return this.$emit('overlimit', type) | |
| 322 | - } | |
| 323 | - const diff = type === 'minus' ? -this.step : +this.step | |
| 324 | - const value = this.format(this.add(+this.currentValue, diff)) | |
| 325 | - this.emitChange(value) | |
| 326 | - this.$emit(type) | |
| 327 | - }, | |
| 328 | - // 对值扩大后进行四舍五入,再除以扩大因子,避免出现浮点数操作的精度问题 | |
| 329 | - add(num1, num2) { | |
| 330 | - const cardinal = Math.pow(10, 10); | |
| 331 | - return Math.round((num1 + num2) * cardinal) / cardinal | |
| 332 | - }, | |
| 333 | - // 点击加减按钮 | |
| 334 | - clickHandler(type) { | |
| 335 | - this.type = type | |
| 336 | - this.onChange() | |
| 337 | - }, | |
| 338 | - longPressStep() { | |
| 339 | - // 每隔一段时间,重新调用longPressStep方法,实现长按加减 | |
| 340 | - this.clearTimeout() | |
| 341 | - this.longPressTimer = setTimeout(() => { | |
| 342 | - this.onChange() | |
| 343 | - this.longPressStep() | |
| 344 | - }, 250); | |
| 345 | - }, | |
| 346 | - onTouchStart(type) { | |
| 347 | - if (!this.longPress) return | |
| 348 | - this.clearTimeout() | |
| 349 | - this.type = type | |
| 350 | - // 一定时间后,默认达到长按状态 | |
| 351 | - this.longPressTimer = setTimeout(() => { | |
| 352 | - this.onChange() | |
| 353 | - this.longPressStep() | |
| 354 | - }, 600) | |
| 355 | - }, | |
| 356 | - // 触摸结束,清除定时器,停止长按加减 | |
| 357 | - onTouchEnd() { | |
| 358 | - if (!this.longPress) return | |
| 359 | - this.clearTimeout() | |
| 360 | - }, | |
| 361 | - // 清除定时器 | |
| 362 | - clearTimeout() { | |
| 363 | - clearTimeout(this.longPressTimer) | |
| 364 | - this.longPressTimer = null | |
| 365 | 279 | } |
| 280 | + this.$emit('change', { | |
| 281 | + value, | |
| 282 | + name: this.name, | |
| 283 | + }); | |
| 284 | + }, | |
| 285 | + onChange() { | |
| 286 | + const { | |
| 287 | + type | |
| 288 | + } = this | |
| 289 | + if (this.isDisabled(type)) { | |
| 290 | + return this.$emit('overlimit', type) | |
| 291 | + } | |
| 292 | + const diff = type === 'minus' ? -this.step : +this.step | |
| 293 | + const value = this.format(this.add(+this.currentValue, diff)) | |
| 294 | + this.emitChange(value) | |
| 295 | + this.$emit(type) | |
| 296 | + }, | |
| 297 | + // 对值扩大后进行四舍五入,再除以扩大因子,避免出现浮点数操作的精度问题 | |
| 298 | + add(num1, num2) { | |
| 299 | + const cardinal = Math.pow(10, 10); | |
| 300 | + return Math.round((num1 + num2) * cardinal) / cardinal | |
| 301 | + }, | |
| 302 | + // 点击加减按钮 | |
| 303 | + clickHandler(type) { | |
| 304 | + this.type = type | |
| 305 | + this.onChange() | |
| 306 | + }, | |
| 307 | + longPressStep() { | |
| 308 | + // 每隔一段时间,重新调用longPressStep方法,实现长按加减 | |
| 309 | + this.clearTimeout() | |
| 310 | + this.longPressTimer = setTimeout(() => { | |
| 311 | + this.onChange() | |
| 312 | + this.longPressStep() | |
| 313 | + }, 250); | |
| 314 | + }, | |
| 315 | + onTouchStart(type) { | |
| 316 | + if (!this.longPress) return | |
| 317 | + this.clearTimeout() | |
| 318 | + this.type = type | |
| 319 | + // 一定时间后,默认达到长按状态 | |
| 320 | + this.longPressTimer = setTimeout(() => { | |
| 321 | + this.onChange() | |
| 322 | + this.longPressStep() | |
| 323 | + }, 600) | |
| 324 | + }, | |
| 325 | + // 触摸结束,清除定时器,停止长按加减 | |
| 326 | + onTouchEnd() { | |
| 327 | + if (!this.longPress) return | |
| 328 | + this.clearTimeout() | |
| 329 | + }, | |
| 330 | + // 清除定时器 | |
| 331 | + clearTimeout() { | |
| 332 | + clearTimeout(this.longPressTimer) | |
| 333 | + this.longPressTimer = null | |
| 366 | 334 | } |
| 367 | 335 | } |
| 336 | +} | |
| 368 | 337 | </script> |
| 369 | 338 | |
| 370 | 339 | <style lang="scss" scoped> |
| 371 | - @import '../../libs/css/components.scss'; | |
| 372 | - | |
| 373 | - $u-numberBox-hover-bgColor: #E6E6E6 !default; | |
| 374 | - $u-numberBox-disabled-color: #c8c9cc !default; | |
| 375 | - $u-numberBox-disabled-bgColor: #f7f8fa !default; | |
| 376 | - $u-numberBox-plus-radius: 4px !default; | |
| 377 | - $u-numberBox-minus-radius: 4px !default; | |
| 378 | - $u-numberBox-input-text-align: center !default; | |
| 379 | - $u-numberBox-input-font-size: 15px !default; | |
| 380 | - $u-numberBox-input-padding: 0 !default; | |
| 381 | - $u-numberBox-input-margin: 0 2px !default; | |
| 382 | - $u-numberBox-input-disabled-color: #c8c9cc !default; | |
| 383 | - $u-numberBox-input-disabled-bgColor: #f2f3f5 !default; | |
| 340 | +@import '../../libs/css/components.scss'; | |
| 384 | 341 | |
| 385 | - .u-number-box { | |
| 386 | - @include flex(row); | |
| 387 | - align-items: center; | |
| 342 | +$u-numberBox-hover-bgColor: #E6E6E6 !default; | |
| 343 | +$u-numberBox-disabled-color: #c8c9cc !default; | |
| 344 | +$u-numberBox-disabled-bgColor: #f7f8fa !default; | |
| 345 | +$u-numberBox-plus-radius: 4px !default; | |
| 346 | +$u-numberBox-minus-radius: 4px !default; | |
| 347 | +$u-numberBox-input-text-align: center !default; | |
| 348 | +$u-numberBox-input-font-size: 15px !default; | |
| 349 | +$u-numberBox-input-padding: 0 !default; | |
| 350 | +$u-numberBox-input-margin: 0 2px !default; | |
| 351 | +$u-numberBox-input-disabled-color: #c8c9cc !default; | |
| 352 | +$u-numberBox-input-disabled-bgColor: #f2f3f5 !default; | |
| 388 | 353 | |
| 389 | - &__slot { | |
| 390 | - /* #ifndef APP-NVUE */ | |
| 391 | - touch-action: none; | |
| 392 | - /* #endif */ | |
| 393 | - } | |
| 354 | +.u-number-box { | |
| 355 | + @include flex(row); | |
| 356 | + align-items: center; | |
| 394 | 357 | |
| 395 | - &__plus, | |
| 396 | - &__minus { | |
| 397 | - width: 35px; | |
| 398 | - @include flex; | |
| 399 | - justify-content: center; | |
| 400 | - align-items: center; | |
| 401 | - /* #ifndef APP-NVUE */ | |
| 402 | - touch-action: none; | |
| 403 | - /* #endif */ | |
| 358 | + &__slot { | |
| 359 | + /* #ifndef APP-NVUE */ | |
| 360 | + touch-action: none; | |
| 361 | + /* #endif */ | |
| 362 | + } | |
| 404 | 363 | |
| 405 | - &--hover { | |
| 406 | - background-color: $u-numberBox-hover-bgColor !important; | |
| 407 | - } | |
| 364 | + &__plus, | |
| 365 | + &__minus { | |
| 366 | + width: 35px; | |
| 367 | + @include flex; | |
| 368 | + justify-content: center; | |
| 369 | + align-items: center; | |
| 370 | + /* #ifndef APP-NVUE */ | |
| 371 | + touch-action: none; | |
| 372 | + /* #endif */ | |
| 408 | 373 | |
| 409 | - &--disabled { | |
| 410 | - color: $u-numberBox-disabled-color; | |
| 411 | - background-color: $u-numberBox-disabled-bgColor; | |
| 412 | - } | |
| 374 | + &--hover { | |
| 375 | + background-color: $u-numberBox-hover-bgColor !important; | |
| 413 | 376 | } |
| 414 | 377 | |
| 415 | - &__plus { | |
| 416 | - border-top-right-radius: $u-numberBox-plus-radius; | |
| 417 | - border-bottom-right-radius: $u-numberBox-plus-radius; | |
| 378 | + &--disabled { | |
| 379 | + color: $u-numberBox-disabled-color; | |
| 380 | + background-color: $u-numberBox-disabled-bgColor; | |
| 418 | 381 | } |
| 382 | + } | |
| 419 | 383 | |
| 420 | - &__minus { | |
| 421 | - border-top-left-radius: $u-numberBox-minus-radius; | |
| 422 | - border-bottom-left-radius: $u-numberBox-minus-radius; | |
| 423 | - } | |
| 384 | + &__plus { | |
| 385 | + border-top-right-radius: $u-numberBox-plus-radius; | |
| 386 | + border-bottom-right-radius: $u-numberBox-plus-radius; | |
| 387 | + } | |
| 388 | + | |
| 389 | + &__minus { | |
| 390 | + border-top-left-radius: $u-numberBox-minus-radius; | |
| 391 | + border-bottom-left-radius: $u-numberBox-minus-radius; | |
| 392 | + } | |
| 424 | 393 | |
| 425 | - &__input { | |
| 426 | - position: relative; | |
| 427 | - text-align: $u-numberBox-input-text-align; | |
| 428 | - font-size: $u-numberBox-input-font-size; | |
| 429 | - padding: $u-numberBox-input-padding; | |
| 430 | - margin: $u-numberBox-input-margin; | |
| 431 | - @include flex; | |
| 432 | - align-items: center; | |
| 433 | - justify-content: center; | |
| 394 | + &__input { | |
| 395 | + position: relative; | |
| 396 | + text-align: $u-numberBox-input-text-align; | |
| 397 | + font-size: $u-numberBox-input-font-size; | |
| 398 | + padding: $u-numberBox-input-padding; | |
| 399 | + margin: $u-numberBox-input-margin; | |
| 400 | + @include flex; | |
| 401 | + align-items: center; | |
| 402 | + justify-content: center; | |
| 434 | 403 | |
| 435 | - &--disabled { | |
| 436 | - color: $u-numberBox-input-disabled-color; | |
| 437 | - background-color: $u-numberBox-input-disabled-bgColor; | |
| 438 | - } | |
| 404 | + &--disabled { | |
| 405 | + color: $u-numberBox-input-disabled-color; | |
| 406 | + background-color: $u-numberBox-input-disabled-bgColor; | |
| 439 | 407 | } |
| 440 | 408 | } |
| 409 | +} | |
| 441 | 410 | </style> | ... | ... |
garbage-removal/src/uview-plus/components/u-picker/u-picker.vue
| ... | ... | @@ -133,7 +133,6 @@ export default { |
| 133 | 133 | // 将当前的各项变化索引,设置为"上一次"的索引变化值 |
| 134 | 134 | this.setLastIndex(value) |
| 135 | 135 | this.setIndexs(value) |
| 136 | - | |
| 137 | 136 | this.$emit('change', { |
| 138 | 137 | // #ifndef MP-WEIXIN || MP-LARK |
| 139 | 138 | // 微信小程序不能传递this,会因为循环引用而报错 |
| ... | ... | @@ -213,13 +212,17 @@ export default { |
| 213 | 212 | |
| 214 | 213 | .u-picker { |
| 215 | 214 | position: relative; |
| 215 | + box-sizing: border-box; | |
| 216 | 216 | |
| 217 | 217 | &__view { |
| 218 | 218 | |
| 219 | + box-sizing: border-box; | |
| 220 | + | |
| 219 | 221 | &__column { |
| 220 | 222 | @include flex; |
| 221 | 223 | flex: 1; |
| 222 | 224 | justify-content: center; |
| 225 | + box-sizing: border-box; | |
| 223 | 226 | |
| 224 | 227 | &__item { |
| 225 | 228 | @include flex; |
| ... | ... | @@ -231,12 +234,14 @@ export default { |
| 231 | 234 | display: block; |
| 232 | 235 | /* #endif */ |
| 233 | 236 | color: $u-main-color; |
| 237 | + box-sizing: border-box; | |
| 234 | 238 | |
| 235 | 239 | &--disabled { |
| 236 | 240 | /* #ifndef APP-NVUE */ |
| 237 | 241 | cursor: not-allowed; |
| 238 | 242 | /* #endif */ |
| 239 | 243 | opacity: 0.35; |
| 244 | + box-sizing: border-box; | |
| 240 | 245 | } |
| 241 | 246 | } |
| 242 | 247 | } |
| ... | ... | @@ -253,6 +258,7 @@ export default { |
| 253 | 258 | align-items: center; |
| 254 | 259 | background-color: rgba(255, 255, 255, 0.87); |
| 255 | 260 | z-index: 1000; |
| 261 | + box-sizing: border-box; | |
| 256 | 262 | } |
| 257 | 263 | } |
| 258 | 264 | </style> | ... | ... |