Commit 89352c3f4f2250b55354a4d7044de162c90d5cf8
1 parent
7399632e
feat: 新增地址,切换请求地址url,修改请求逻辑,修改u-tabs组件
Showing
17 changed files
with
727 additions
and
564 deletions
garbage-removal/.env.preview
garbage-removal/.env.production
garbage-removal/src/App.vue
| 1 | -<script> | ||
| 2 | -export default { | ||
| 3 | - onLaunch: function () { | ||
| 4 | - console.log('App Launch') | ||
| 5 | - }, | ||
| 6 | - onShow: function () { | ||
| 7 | - console.log('App Show') | ||
| 8 | - }, | ||
| 9 | - onHide: function () { | ||
| 10 | - console.log('App Hide') | ||
| 11 | - }, | ||
| 12 | -} | 1 | +<script setup> |
| 2 | +import { onLaunch } from "@dcloudio/uni-app"; | ||
| 3 | +import { useMainStore } from "./stores/index.js"; | ||
| 4 | +import { setRequestToken } from "./utils/request/request.js"; | ||
| 5 | +const store = useMainStore(); | ||
| 6 | + | ||
| 7 | +onLaunch(async () => { | ||
| 8 | + console.log("store::==>", store); | ||
| 9 | + if (store.token) { | ||
| 10 | + setRequestToken(store.token); | ||
| 11 | + // store.userInfo = (await getUserInfo()).data.data; | ||
| 12 | + uni.switchTab({ | ||
| 13 | + url: "/pages/home/index", | ||
| 14 | + }); | ||
| 15 | + } else { | ||
| 16 | + uni.reLaunch({ | ||
| 17 | + url: "/pages/login/index", | ||
| 18 | + }); | ||
| 19 | + } | ||
| 20 | +}); | ||
| 13 | </script> | 21 | </script> |
| 14 | 22 | ||
| 15 | <style lang="scss"> | 23 | <style lang="scss"> |
| @@ -17,18 +25,6 @@ export default { | @@ -17,18 +25,6 @@ export default { | ||
| 17 | @import "./uview-plus/index.scss"; | 25 | @import "./uview-plus/index.scss"; |
| 18 | @import "./static/icon/iconfont/iconfont.css"; | 26 | @import "./static/icon/iconfont/iconfont.css"; |
| 19 | 27 | ||
| 20 | -html { | ||
| 21 | - font-family: '黑体'; | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -.body { | ||
| 25 | - font-family: '黑体'; | ||
| 26 | -} | ||
| 27 | - | ||
| 28 | -.container { | ||
| 29 | - font-family: '黑体'; | ||
| 30 | -} | ||
| 31 | - | ||
| 32 | page { | 28 | page { |
| 33 | box-sizing: border-box; | 29 | box-sizing: border-box; |
| 34 | min-height: 100%; | 30 | min-height: 100%; |
garbage-removal/src/apis/address.js
0 → 100644
| 1 | + | ||
| 2 | +import { request } from "@/utils/request"; | ||
| 3 | +/** | ||
| 4 | + * @method 新增用户地址 | ||
| 5 | + */ | ||
| 6 | +export async function addAddress( params, config) { | ||
| 7 | + return await request.post( | ||
| 8 | + `/user/save/address`, | ||
| 9 | + params, | ||
| 10 | + config | ||
| 11 | + ); | ||
| 12 | +} | ||
| 13 | +/** | ||
| 14 | + * @method 获取用户地址 | ||
| 15 | + */ | ||
| 16 | +export async function queryAddress( type) { | ||
| 17 | + return await request.get( | ||
| 18 | + `/user/query/address/${type}` | ||
| 19 | + ); | ||
| 20 | +} | ||
| 21 | +/** | ||
| 22 | + * @method 编辑用户地址 | ||
| 23 | + */ | ||
| 24 | +export async function updateAddress( params,config) { | ||
| 25 | + return await request.post( | ||
| 26 | + `/user/update/address`, | ||
| 27 | + params, | ||
| 28 | + config | ||
| 29 | + ); | ||
| 30 | +} | ||
| 31 | +/** | ||
| 32 | + * @method 编辑用户地址 | ||
| 33 | + */ | ||
| 34 | +export async function deleteAddress( id) { | ||
| 35 | + return await request.delete( | ||
| 36 | + `/user/delete/address/${id}` | ||
| 37 | + ); | ||
| 38 | +} |
garbage-removal/src/apis/company.js
0 → 100644
garbage-removal/src/apis/index.js deleted
100644 → 0
| 1 | -export * from "./user"; |
garbage-removal/src/apis/user.js
| @@ -6,10 +6,7 @@ const prefix = "/user"; | @@ -6,10 +6,7 @@ const prefix = "/user"; | ||
| 6 | /** | 6 | /** |
| 7 | * @method 用户登录 | 7 | * @method 用户登录 |
| 8 | */ | 8 | */ |
| 9 | -export async function userLogin( | ||
| 10 | - params, | ||
| 11 | - config | ||
| 12 | -) { | 9 | +export async function userLogin( params, config) { |
| 13 | return await request.post( | 10 | return await request.post( |
| 14 | `${prefix}/login`, | 11 | `${prefix}/login`, |
| 15 | params, | 12 | params, |
| @@ -27,6 +24,8 @@ export async function getUserInfo(config) { | @@ -27,6 +24,8 @@ export async function getUserInfo(config) { | ||
| 27 | /** | 24 | /** |
| 28 | * @method 发送验证码 | 25 | * @method 发送验证码 |
| 29 | */ | 26 | */ |
| 30 | -export function sendCode() { | ||
| 31 | - return request.get(`${prefix}/sendCode`); | 27 | +export async function sendCode(params) { |
| 28 | + return await request.get( | ||
| 29 | + `${prefix}/send/verify?tel=${params}` | ||
| 30 | + ); | ||
| 32 | } | 31 | } |
garbage-removal/src/pages.json
| @@ -8,6 +8,17 @@ | @@ -8,6 +8,17 @@ | ||
| 8 | }, | 8 | }, |
| 9 | "pages": [ | 9 | "pages": [ |
| 10 | { | 10 | { |
| 11 | + "path": "pages/login/index", | ||
| 12 | + "style": { | ||
| 13 | + "navigationBarTitleText": "装饰装修垃圾智慧功能模块登录" | ||
| 14 | + } | ||
| 15 | + },{ | ||
| 16 | + "path": "pages/login/code", | ||
| 17 | + "style": { | ||
| 18 | + "navigationBarTitleText": "输入验证码" | ||
| 19 | + } | ||
| 20 | + }, | ||
| 21 | + { | ||
| 11 | "path": "pages/home/index", | 22 | "path": "pages/home/index", |
| 12 | "style": { | 23 | "style": { |
| 13 | "navigationBarTitleText": "", | 24 | "navigationBarTitleText": "", |
| @@ -40,13 +51,17 @@ | @@ -40,13 +51,17 @@ | ||
| 40 | { | 51 | { |
| 41 | "path": "pages/home/address/index", | 52 | "path": "pages/home/address/index", |
| 42 | "style": { | 53 | "style": { |
| 43 | - "navigationBarTitleText": "清运地址" | 54 | + "navigationBarTitleText": "清运地址", |
| 55 | + "navigationBarTextStyle":"white", | ||
| 56 | + "navigationBarBackgroundColor":"#53c21d" | ||
| 44 | } | 57 | } |
| 45 | }, | 58 | }, |
| 46 | { | 59 | { |
| 47 | "path": "pages/home/address/addSite", | 60 | "path": "pages/home/address/addSite", |
| 48 | "style": { | 61 | "style": { |
| 49 | - "navigationBarTitleText": "清运地址" | 62 | + "navigationBarTitleText": "清运地址", |
| 63 | + "navigationBarTextStyle":"white", | ||
| 64 | + "navigationBarBackgroundColor":"#53c21d" | ||
| 50 | } | 65 | } |
| 51 | },{ | 66 | },{ |
| 52 | "path": "pages/order/index", | 67 | "path": "pages/order/index", |
| @@ -60,17 +75,6 @@ | @@ -60,17 +75,6 @@ | ||
| 60 | "style": { | 75 | "style": { |
| 61 | "navigationBarTitleText": "" | 76 | "navigationBarTitleText": "" |
| 62 | } | 77 | } |
| 63 | - }, | ||
| 64 | - { | ||
| 65 | - "path": "pages/login/index", | ||
| 66 | - "style": { | ||
| 67 | - "navigationBarTitleText": "装饰装修垃圾智慧功能模块登录" | ||
| 68 | - } | ||
| 69 | - },{ | ||
| 70 | - "path": "pages/login/code", | ||
| 71 | - "style": { | ||
| 72 | - "navigationBarTitleText": "装饰装修垃圾智慧功能模块登录" | ||
| 73 | - } | ||
| 74 | } | 78 | } |
| 75 | ], | 79 | ], |
| 76 | "tabBar": { | 80 | "tabBar": { |
garbage-removal/src/pages/home/address/addSite.vue
| @@ -9,8 +9,11 @@ | @@ -9,8 +9,11 @@ | ||
| 9 | placeholder="省市区县、乡镇等"></u--input> | 9 | placeholder="省市区县、乡镇等"></u--input> |
| 10 | </u-form-item> | 10 | </u-form-item> |
| 11 | <u-form-item :required="true" label="详细地址" prop="addressDetail" borderBottom> | 11 | <u-form-item :required="true" label="详细地址" prop="addressDetail" borderBottom> |
| 12 | - <u--input border="none" type="text" v-model="addressInfo.addressDetail" placeholder-class="line" | ||
| 13 | - placeholder="请填写收货人姓名详细地址"></u--input> | 12 | + <view class="wrap-from-container-address-details" style="display: flex;"> |
| 13 | + <u--input border="none" type="text" v-model="addressInfo.addressDetail" placeholder-class="line" | ||
| 14 | + placeholder="请填写详细地址"></u--input> | ||
| 15 | + <u-icon name="map" size="40" @click="chooseAddressDetail"></u-icon> | ||
| 16 | + </view> | ||
| 14 | </u-form-item> | 17 | </u-form-item> |
| 15 | <u-form-item :required="true" label="联系人" prop="contactPerson" borderBottom> | 18 | <u-form-item :required="true" label="联系人" prop="contactPerson" borderBottom> |
| 16 | <u--input border="none" type="text" v-model="addressInfo.contactPerson" placeholder-class="line" | 19 | <u--input border="none" type="text" v-model="addressInfo.contactPerson" placeholder-class="line" |
| @@ -25,24 +28,31 @@ | @@ -25,24 +28,31 @@ | ||
| 25 | <view class="bottom"> | 28 | <view class="bottom"> |
| 26 | <view class="default"> | 29 | <view class="default"> |
| 27 | <view class="left"> | 30 | <view class="left"> |
| 28 | - <view class="set">设置默认地址</view> | 31 | + <view class="set">当前选中地址</view> |
| 29 | </view> | 32 | </view> |
| 30 | <view class="right"> | 33 | <view class="right"> |
| 31 | <u-switch v-model="addressInfo.defaultFlag" size="40" activeColor="#a9e08f"></u-switch> | 34 | <u-switch v-model="addressInfo.defaultFlag" size="40" activeColor="#a9e08f"></u-switch> |
| 32 | </view> | 35 | </view> |
| 33 | </view> | 36 | </view> |
| 34 | </view> | 37 | </view> |
| 35 | - <view class="submit-button" @click="submit"> | ||
| 36 | - <view class="add">新增地址</view> | 38 | + <view class="submit-button"> |
| 39 | + <view v-if="addFlag" @click="submit" class="add">新增地址</view> | ||
| 40 | + <view v-else class="update-box"> | ||
| 41 | + <view class="del" @click="handleDeleteClick">删除地址</view> | ||
| 42 | + <view class="update" @click="handleUpdateClick">保存地址</view> | ||
| 43 | + </view> | ||
| 37 | </view> | 44 | </view> |
| 38 | </view> | 45 | </view> |
| 39 | </template> | 46 | </template> |
| 40 | 47 | ||
| 41 | <script setup> | 48 | <script setup> |
| 49 | +import { addAddress, deleteAddress, updateAddress } from '@/apis/address.js'; | ||
| 50 | +import { onLoad } from '@dcloudio/uni-app'; | ||
| 42 | import { getCurrentInstance, onMounted, reactive, ref } from 'vue'; | 51 | import { getCurrentInstance, onMounted, reactive, ref } from 'vue'; |
| 43 | import citySelect from './citySelect/u-city-select.vue'; | 52 | import citySelect from './citySelect/u-city-select.vue'; |
| 44 | const { proxy } = getCurrentInstance(); | 53 | const { proxy } = getCurrentInstance(); |
| 45 | const cityPikerShowFlag = ref(false) | 54 | const cityPikerShowFlag = ref(false) |
| 55 | +const addFlag = ref(true) | ||
| 46 | const addressInfo = reactive({ | 56 | const addressInfo = reactive({ |
| 47 | addressArea: "", | 57 | addressArea: "", |
| 48 | addressDetail: "", | 58 | addressDetail: "", |
| @@ -84,23 +94,105 @@ const rules = reactive({ | @@ -84,23 +94,105 @@ const rules = reactive({ | ||
| 84 | trigger: ['change', 'blur'], | 94 | trigger: ['change', 'blur'], |
| 85 | }] | 95 | }] |
| 86 | }) | 96 | }) |
| 97 | + | ||
| 87 | const showRegionPicker = () => { | 98 | const showRegionPicker = () => { |
| 88 | cityPikerShowFlag.value = true; | 99 | cityPikerShowFlag.value = true; |
| 89 | } | 100 | } |
| 101 | + | ||
| 90 | const handleCityChange = (e) => { | 102 | const handleCityChange = (e) => { |
| 91 | addressInfo.addressArea = e.province.label + '-' + e.city.label + '-' + e.area.label; | 103 | addressInfo.addressArea = e.province.label + '-' + e.city.label + '-' + e.area.label; |
| 92 | } | 104 | } |
| 105 | + | ||
| 106 | +const handleDeleteClick = () => { | ||
| 107 | + uni.showModal({ | ||
| 108 | + title: '', | ||
| 109 | + content: '是否确认删除这个地址', | ||
| 110 | + success: function (res) { | ||
| 111 | + if (res.confirm) { | ||
| 112 | + deleteAddress(addressInfo.garAddressId).then(res => { | ||
| 113 | + if (res.data.success) { | ||
| 114 | + uni.$u.toast(res.data.msg) | ||
| 115 | + jumpAddressList() | ||
| 116 | + } | ||
| 117 | + }) | ||
| 118 | + } else if (res.cancel) { | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + }); | ||
| 122 | + | ||
| 123 | +} | ||
| 124 | + | ||
| 125 | +const handleUpdateClick = () => { | ||
| 126 | + updateAddress(addressInfo).then(res => { | ||
| 127 | + console.log(res); | ||
| 128 | + uni.$u.toast(res.data.msg) | ||
| 129 | + if (res.data.success) { | ||
| 130 | + setTimeout(() => { | ||
| 131 | + jumpAddressList(); | ||
| 132 | + }, 200); | ||
| 133 | + } | ||
| 134 | + }) | ||
| 135 | +} | ||
| 136 | + | ||
| 137 | +const jumpAddressList = () => { | ||
| 138 | + reset(); | ||
| 139 | + uni.$u.route({ | ||
| 140 | + type: 'navigateBack', | ||
| 141 | + url: `pages/home/address/index`, | ||
| 142 | + }) | ||
| 143 | +} | ||
| 144 | + | ||
| 93 | const submit = () => { | 145 | const submit = () => { |
| 94 | - console.log(addressInfo); | ||
| 95 | proxy.$refs.addressFrom.validate().then(res => { | 146 | proxy.$refs.addressFrom.validate().then(res => { |
| 96 | - uni.$u.toast('新增成功') | 147 | + addAddress(addressInfo).then(res => { |
| 148 | + uni.$u.toast(res.data.msg) | ||
| 149 | + if (res.data.success) { | ||
| 150 | + setTimeout(() => { | ||
| 151 | + jumpAddressList(); | ||
| 152 | + }, 200); | ||
| 153 | + } | ||
| 154 | + }) | ||
| 97 | }).catch(errors => { | 155 | }).catch(errors => { |
| 98 | - uni.$u.toast('校验失败') | 156 | + uni.$u.toast('请填写正确信息!') |
| 99 | }) | 157 | }) |
| 100 | } | 158 | } |
| 159 | +/** | ||
| 160 | + * 打开地图选择地址 | ||
| 161 | + */ | ||
| 162 | +const chooseAddressDetail = () => { | ||
| 163 | + console.log("sss"); | ||
| 164 | + uni.chooseLocation({ | ||
| 165 | + success: function (res) { | ||
| 166 | + addressInfo.addressDetail = res.address + res.name; | ||
| 167 | + } | ||
| 168 | + }); | ||
| 169 | +} | ||
| 170 | + | ||
| 101 | onMounted(() => { | 171 | onMounted(() => { |
| 102 | proxy.$refs.addressFrom.setRules(rules) | 172 | proxy.$refs.addressFrom.setRules(rules) |
| 103 | }) | 173 | }) |
| 174 | + | ||
| 175 | +onLoad((options) => { | ||
| 176 | + if (options.addressObj) { | ||
| 177 | + let addressObj = JSON.parse(options.addressObj); | ||
| 178 | + addressInfo.addressArea = addressObj.garUserAddress; | ||
| 179 | + addressInfo.contactPerson = addressObj.garUserContactName; | ||
| 180 | + addressInfo.contactIphoneNumber = addressObj.garUserContactTel; | ||
| 181 | + addressInfo.defaultFlag = addressObj.garUserDefault == 1 ? true : false; | ||
| 182 | + addressInfo.addressDetail = addressObj.garRemark; | ||
| 183 | + addressInfo.garAddressId = addressObj.garAddressId | ||
| 184 | + addFlag.value = false; | ||
| 185 | + } | ||
| 186 | +}) | ||
| 187 | +const reset = () => { | ||
| 188 | + addressInfo.addressArea = '' | ||
| 189 | + addressInfo.contactPerson = '' | ||
| 190 | + addressInfo.contactIphoneNumber = '' | ||
| 191 | + addressInfo.defaultFlag = false | ||
| 192 | + addressInfo.addressDetail = '' | ||
| 193 | + addressInfo.garAddressId = '' | ||
| 194 | + addFlag.value = true | ||
| 195 | +} | ||
| 104 | </script> | 196 | </script> |
| 105 | 197 | ||
| 106 | <style lang="scss" scoped> | 198 | <style lang="scss" scoped> |
| @@ -110,7 +202,7 @@ onMounted(() => { | @@ -110,7 +202,7 @@ onMounted(() => { | ||
| 110 | // background-color: $u-info-light; | 202 | // background-color: $u-info-light; |
| 111 | height: 100%; | 203 | height: 100%; |
| 112 | width: 100%; | 204 | width: 100%; |
| 113 | - background: linear-gradient(to bottom, $u-success-disabled, $u-info-light, $u-info-light, $u-info-light); | 205 | + background: linear-gradient(to bottom, $u-success-dark, $u-info-light, $u-info-light, $u-info-light); |
| 114 | 206 | ||
| 115 | .wrap-from-container { | 207 | .wrap-from-container { |
| 116 | width: 100%; | 208 | width: 100%; |
| @@ -148,21 +240,51 @@ onMounted(() => { | @@ -148,21 +240,51 @@ onMounted(() => { | ||
| 148 | 240 | ||
| 149 | .submit-button { | 241 | .submit-button { |
| 150 | display: flex; | 242 | display: flex; |
| 151 | - justify-content: space-around; | ||
| 152 | width: 600rpx; | 243 | width: 600rpx; |
| 153 | line-height: 100rpx; | 244 | line-height: 100rpx; |
| 154 | position: absolute; | 245 | position: absolute; |
| 155 | bottom: 30rpx; | 246 | bottom: 30rpx; |
| 156 | left: 80rpx; | 247 | left: 80rpx; |
| 157 | - background-color: #a9e08f; | ||
| 158 | - border-radius: 60rpx; | ||
| 159 | font-size: 30rpx; | 248 | font-size: 30rpx; |
| 249 | + color: #ffffff; | ||
| 160 | 250 | ||
| 161 | .add { | 251 | .add { |
| 252 | + background-color: #a9e08f; | ||
| 253 | + border-radius: 60rpx; | ||
| 254 | + width: 100%; | ||
| 162 | display: flex; | 255 | display: flex; |
| 163 | align-items: center; | 256 | align-items: center; |
| 164 | - color: #ffffff; | 257 | + justify-content: center; |
| 258 | + } | ||
| 259 | + | ||
| 260 | + .update-box { | ||
| 261 | + width: 100%; | ||
| 262 | + display: flex; | ||
| 263 | + justify-content: space-around; | ||
| 264 | + | ||
| 265 | + .del { | ||
| 266 | + width: 100%; | ||
| 267 | + display: flex; | ||
| 268 | + align-items: center; | ||
| 269 | + justify-content: center; | ||
| 270 | + border-radius: 60rpx; | ||
| 271 | + background-color: $u-error-disabled; | ||
| 272 | + margin-right: 30rpx; | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + .update { | ||
| 276 | + width: 100%; | ||
| 277 | + background-color: $u-success-dark; | ||
| 278 | + border-radius: 60rpx; | ||
| 279 | + display: flex; | ||
| 280 | + align-items: center; | ||
| 281 | + justify-content: center; | ||
| 282 | + } | ||
| 283 | + | ||
| 284 | + | ||
| 165 | } | 285 | } |
| 166 | } | 286 | } |
| 287 | + | ||
| 288 | + | ||
| 167 | } | 289 | } |
| 168 | </style> | 290 | </style> |
garbage-removal/src/pages/home/address/index.vue
| @@ -2,16 +2,18 @@ | @@ -2,16 +2,18 @@ | ||
| 2 | <view class="address-container"> | 2 | <view class="address-container"> |
| 3 | <view class="address-box"> | 3 | <view class="address-box"> |
| 4 | <view class="item" v-for="(res, index) in siteList" :key="res.id"> | 4 | <view class="item" v-for="(res, index) in siteList" :key="res.id"> |
| 5 | - <view class="top"> | ||
| 6 | - <view class="name">{{ res.name }}</view> | ||
| 7 | - <view class="phone">{{ res.phone }}</view> | 5 | + <view class="top" @click="handleClickChangeCurrentAddress(res)"> |
| 6 | + <view class="name">{{ res.garUserContactName }}</view> | ||
| 7 | + <view class="phone">{{ res.garUserContactTel }}</view> | ||
| 8 | <view class="tag"> | 8 | <view class="tag"> |
| 9 | - <text v-if="res.tag" :class="{ red: res.tag == '默认' }">{{ res.tag }}</text> | 9 | + <text v-if="res.garUserDefault == 1" :class="{ red: res.garUserDefault == 1 }"> |
| 10 | + {{ res.garUserDefault == 1 ? "当前选中" : "" }} | ||
| 11 | + </text> | ||
| 10 | </view> | 12 | </view> |
| 11 | </view> | 13 | </view> |
| 12 | <view class="bottom"> | 14 | <view class="bottom"> |
| 13 | - 广东省深圳市宝安区 自由路66号 | ||
| 14 | - <u-icon name="edit-pen" :size="40" color="#999999"></u-icon> | 15 | + {{ res.garUserAddress + res.garRemark }} |
| 16 | + <u-icon name="edit-pen" @click="handleUpdateAddress(res)" :size="40" color="#999999"></u-icon> | ||
| 15 | </view> | 17 | </view> |
| 16 | </view> | 18 | </view> |
| 17 | 19 | ||
| @@ -23,68 +25,44 @@ | @@ -23,68 +25,44 @@ | ||
| 23 | </template> | 25 | </template> |
| 24 | 26 | ||
| 25 | <script setup> | 27 | <script setup> |
| 26 | -import { onLoad } from '@dcloudio/uni-app'; | 28 | +import { queryAddress, updateAddress } from "@/apis/address.js"; |
| 29 | +import { onShow } from '@dcloudio/uni-app'; | ||
| 27 | import { ref } from 'vue'; | 30 | import { ref } from 'vue'; |
| 28 | const siteList = ref([]); | 31 | const siteList = ref([]); |
| 32 | + | ||
| 33 | + | ||
| 34 | +/** | ||
| 35 | + * 初始话数据 | ||
| 36 | + */ | ||
| 29 | const getData = () => { | 37 | const getData = () => { |
| 30 | - siteList.value = [ | ||
| 31 | - { | ||
| 32 | - id: 1, | ||
| 33 | - name: '游X', | ||
| 34 | - phone: '183****5523', | ||
| 35 | - tag: '默认', | ||
| 36 | - site: '广东省深圳市宝安区 自由路66号' | ||
| 37 | - }, | ||
| 38 | - { | ||
| 39 | - id: 2, | ||
| 40 | - name: '李XX', | ||
| 41 | - phone: '183****5555', | ||
| 42 | - tag: '', | ||
| 43 | - site: '广东省深圳市宝安区 翻身路xx号' | ||
| 44 | - }, | ||
| 45 | - { | ||
| 46 | - id: 3, | ||
| 47 | - name: '王YY', | ||
| 48 | - phone: '153****5555', | ||
| 49 | - tag: '', | ||
| 50 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 51 | - }, | ||
| 52 | - { | ||
| 53 | - id: 4, | ||
| 54 | - name: '王YY', | ||
| 55 | - phone: '153****5555', | ||
| 56 | - tag: '', | ||
| 57 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 58 | - }, | ||
| 59 | - { | ||
| 60 | - id: 5, | ||
| 61 | - name: '王YY', | ||
| 62 | - phone: '153****5555', | ||
| 63 | - tag: '', | ||
| 64 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 65 | - }, | ||
| 66 | - { | ||
| 67 | - id: 6, | ||
| 68 | - name: '王YY', | ||
| 69 | - phone: '153****5555', | ||
| 70 | - tag: '', | ||
| 71 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 72 | - }, | ||
| 73 | - { | ||
| 74 | - id: 7, | ||
| 75 | - name: '王YY', | ||
| 76 | - phone: '153****5555', | ||
| 77 | - tag: '', | ||
| 78 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 79 | - }, | ||
| 80 | - { | ||
| 81 | - id: 8, | ||
| 82 | - name: '王YY', | ||
| 83 | - phone: '153****5555', | ||
| 84 | - tag: '', | ||
| 85 | - site: '广东省深圳市宝安区 平安路13号' | ||
| 86 | - } | ||
| 87 | - ]; | 38 | + queryAddress("ALL").then(res => { |
| 39 | + siteList.value = res.data.data; | ||
| 40 | + }) | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +// 编辑地址 | ||
| 44 | +const handleUpdateAddress = (res) => { | ||
| 45 | + let addressObj = JSON.stringify(res); | ||
| 46 | + uni.navigateTo({ | ||
| 47 | + url: `/pages/home/address/addSite?addressObj=${addressObj}` | ||
| 48 | + }); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +const handleClickChangeCurrentAddress = (res) => { | ||
| 52 | + if (res.garUserDefault == 1) { | ||
| 53 | + return | ||
| 54 | + } | ||
| 55 | + updateAddress({ | ||
| 56 | + addressArea: res.garUserAddress, | ||
| 57 | + contactPerson: res.garUserContactName, | ||
| 58 | + contactIphoneNumber: res.garUserContactTel, | ||
| 59 | + defaultFlag: true, | ||
| 60 | + addressDetail: res.garRemark, | ||
| 61 | + garAddressId: res.garAddressId | ||
| 62 | + }).then(res => { | ||
| 63 | + getData(); | ||
| 64 | + uni.$u.toast(res.data.msg) | ||
| 65 | + }) | ||
| 88 | } | 66 | } |
| 89 | 67 | ||
| 90 | const toAddSite = () => { | 68 | const toAddSite = () => { |
| @@ -92,8 +70,9 @@ const toAddSite = () => { | @@ -92,8 +70,9 @@ const toAddSite = () => { | ||
| 92 | url: '/pages/home/address/addSite' | 70 | url: '/pages/home/address/addSite' |
| 93 | }); | 71 | }); |
| 94 | } | 72 | } |
| 95 | -onLoad(() => { | 73 | +onShow(() => { |
| 96 | getData(); | 74 | getData(); |
| 75 | + | ||
| 97 | }) | 76 | }) |
| 98 | </script> | 77 | </script> |
| 99 | 78 | ||
| @@ -101,7 +80,7 @@ onLoad(() => { | @@ -101,7 +80,7 @@ onLoad(() => { | ||
| 101 | .address-container { | 80 | .address-container { |
| 102 | height: 100%; | 81 | height: 100%; |
| 103 | width: 100%; | 82 | width: 100%; |
| 104 | - background: linear-gradient(to bottom, $u-success-disabled, $u-info-light, $u-info-light, $u-info-light); | 83 | + background: linear-gradient(to bottom, $u-success-dark, $u-info-light, $u-info-light, $u-info-light, $u-info-light, $u-info-light, #ffffff); |
| 105 | padding: 20rpx; | 84 | padding: 20rpx; |
| 106 | box-sizing: border-box; | 85 | box-sizing: border-box; |
| 107 | display: flex; | 86 | display: flex; |
| @@ -138,7 +117,7 @@ onLoad(() => { | @@ -138,7 +117,7 @@ onLoad(() => { | ||
| 138 | 117 | ||
| 139 | text { | 118 | text { |
| 140 | display: block; | 119 | display: block; |
| 141 | - width: 60rpx; | 120 | + width: auto; |
| 142 | height: 34rpx; | 121 | height: 34rpx; |
| 143 | line-height: 34rpx; | 122 | line-height: 34rpx; |
| 144 | color: #ffffff; | 123 | color: #ffffff; |
garbage-removal/src/pages/home/index.vue
| @@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
| 9 | }" class="top-address"> | 9 | }" class="top-address"> |
| 10 | <view class="address-icon-image"><u-icon name="map" color="#fff" size="28"></u-icon></view> | 10 | <view class="address-icon-image"><u-icon name="map" color="#fff" size="28"></u-icon></view> |
| 11 | <view class="address-text" @click="handleAddressInfo"> | 11 | <view class="address-text" @click="handleAddressInfo"> |
| 12 | - 浙江省-宁波市-海曙区-鼓楼街道南站东xxxx | 12 | + {{ userAddress ? userAddress : "请设置清运地址" }} |
| 13 | </view> | 13 | </view> |
| 14 | <view class="address-icon-label"> | 14 | <view class="address-icon-label"> |
| 15 | <u-icon name="arrow-right" color="#fff" size="28"></u-icon> | 15 | <u-icon name="arrow-right" color="#fff" size="28"></u-icon> |
| @@ -88,7 +88,9 @@ | @@ -88,7 +88,9 @@ | ||
| 88 | </template> | 88 | </template> |
| 89 | 89 | ||
| 90 | <script setup > | 90 | <script setup > |
| 91 | -import { onLoad } from '@dcloudio/uni-app'; | 91 | +import { queryAddress } from '@/apis/address.js'; |
| 92 | +import { queryDisposalSiteList } from '@/apis/company.js'; | ||
| 93 | +import { onLoad, onShow } from '@dcloudio/uni-app'; | ||
| 92 | import { ref } from 'vue'; | 94 | import { ref } from 'vue'; |
| 93 | // 定义最大积分 | 95 | // 定义最大积分 |
| 94 | let maxScore = 5 | 96 | let maxScore = 5 |
| @@ -104,6 +106,7 @@ const swiperImageList = ref([{ | @@ -104,6 +106,7 @@ const swiperImageList = ref([{ | ||
| 104 | image: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', | 106 | image: 'https://cdn.uviewui.com/uview/swiper/swiper3.png', |
| 105 | }]) | 107 | }]) |
| 106 | 108 | ||
| 109 | +const userAddress = ref() | ||
| 107 | 110 | ||
| 108 | 111 | ||
| 109 | // 信息指南 | 112 | // 信息指南 |
| @@ -133,26 +136,26 @@ const companyList = ref([ | @@ -133,26 +136,26 @@ const companyList = ref([ | ||
| 133 | remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', | 136 | remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', |
| 134 | tel: '18980249130', | 137 | tel: '18980249130', |
| 135 | } | 138 | } |
| 136 | - // , { | ||
| 137 | - // companyId: '2', | ||
| 138 | - // score: 4, | ||
| 139 | - // image: 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png', | ||
| 140 | - // companyName: '宁波垃圾回收公司', | ||
| 141 | - // startPrice: '500', | ||
| 142 | - // cleanNumber: '1996', | ||
| 143 | - // remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', | ||
| 144 | - // tel: '18980249130', | ||
| 145 | - // }, | ||
| 146 | - // { | ||
| 147 | - // companyId: '3', | ||
| 148 | - // score: 4, | ||
| 149 | - // image: 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png', | ||
| 150 | - // companyName: '宁波垃圾回收公司', | ||
| 151 | - // startPrice: '500', | ||
| 152 | - // cleanNumber: '1996', | ||
| 153 | - // remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', | ||
| 154 | - // tel: '18980249130', | ||
| 155 | - // }, | 139 | + , { |
| 140 | + companyId: '2', | ||
| 141 | + score: 4, | ||
| 142 | + image: 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png', | ||
| 143 | + companyName: '宁波垃圾回收公司', | ||
| 144 | + startPrice: '500', | ||
| 145 | + cleanNumber: '1996', | ||
| 146 | + remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', | ||
| 147 | + tel: '18980249130', | ||
| 148 | + }, | ||
| 149 | + { | ||
| 150 | + companyId: '3', | ||
| 151 | + score: 4, | ||
| 152 | + image: 'https://ijry.github.io/uview-plus/h5/assets/logo-8d54bbeb.png', | ||
| 153 | + companyName: '宁波垃圾回收公司', | ||
| 154 | + startPrice: '500', | ||
| 155 | + cleanNumber: '1996', | ||
| 156 | + remark: '我司专业拆除清运,装修大件垃圾的环保科技企业。', | ||
| 157 | + tel: '18980249130', | ||
| 158 | + }, | ||
| 156 | // { | 159 | // { |
| 157 | // companyId: '1', | 160 | // companyId: '1', |
| 158 | // score: 4, | 161 | // score: 4, |
| @@ -215,29 +218,36 @@ const handleSearchClick = () => { | @@ -215,29 +218,36 @@ const handleSearchClick = () => { | ||
| 215 | * 计算胶囊高度 | 218 | * 计算胶囊高度 |
| 216 | */ | 219 | */ |
| 217 | onLoad(() => { | 220 | onLoad(() => { |
| 218 | - console.log("计算胶囊高度"); | 221 | + // 积分初始化 |
| 222 | + for (let index = 0; index < maxScore; index++) { | ||
| 223 | + maxStar.value.push(index); | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + // 获取胶囊按钮信息(width、height、top等) | ||
| 219 | try { | 227 | try { |
| 220 | - if (topMargin.value) { | ||
| 221 | - console.log("计算完毕"); | ||
| 222 | - } | ||
| 223 | const { height, top } = uni.getMenuButtonBoundingClientRect(); | 228 | const { height, top } = uni.getMenuButtonBoundingClientRect(); |
| 224 | topMargin.value = top + "px"; | 229 | topMargin.value = top + "px"; |
| 225 | - // 获取胶囊按钮信息(width、height、top等) | ||
| 226 | lightHeight.value = height + 'px' | 230 | lightHeight.value = height + 'px' |
| 227 | - console.log("计算完毕"); | ||
| 228 | } catch (error) { | 231 | } catch (error) { |
| 229 | topMargin.value = "60rpx"; | 232 | topMargin.value = "60rpx"; |
| 230 | musicheadHeight.value = "40rpx" | 233 | musicheadHeight.value = "40rpx" |
| 231 | console.log("There is no menu because the current app is not a small program"); | 234 | console.log("There is no menu because the current app is not a small program"); |
| 232 | } | 235 | } |
| 233 | - // 初始化评分 | 236 | +}) |
| 237 | +onShow(() => { | ||
| 238 | + // 初始化数据 | ||
| 234 | initData() | 239 | initData() |
| 235 | }) | 240 | }) |
| 236 | - | ||
| 237 | const initData = () => { | 241 | const initData = () => { |
| 238 | - for (let index = 0; index < maxScore; index++) { | ||
| 239 | - maxStar.value.push(index); | ||
| 240 | - } | 242 | + userAddress.value = null; |
| 243 | + // 查询用户当前地址 | ||
| 244 | + queryAddress('CURRENT').then(res => { | ||
| 245 | + userAddress.value = res.data.data[0].garUserAddress + res.data.data[0].garRemark | ||
| 246 | + }) | ||
| 247 | + // 查询公司信息 | ||
| 248 | + queryDisposalSiteList().then(res => { | ||
| 249 | + console.log("company====>", res); | ||
| 250 | + }) | ||
| 241 | } | 251 | } |
| 242 | </script> | 252 | </script> |
| 243 | 253 | ||
| @@ -284,6 +294,7 @@ const initData = () => { | @@ -284,6 +294,7 @@ const initData = () => { | ||
| 284 | width: 525rpx; | 294 | width: 525rpx; |
| 285 | display: flex; | 295 | display: flex; |
| 286 | align-items: center; | 296 | align-items: center; |
| 297 | + padding-left: 20rpx; | ||
| 287 | color: white; | 298 | color: white; |
| 288 | font-size: 30rpx; | 299 | font-size: 30rpx; |
| 289 | font-family: '圆体', '黑体'; | 300 | font-family: '圆体', '黑体'; |
| @@ -395,16 +406,16 @@ const initData = () => { | @@ -395,16 +406,16 @@ const initData = () => { | ||
| 395 | } | 406 | } |
| 396 | 407 | ||
| 397 | .company-list-content { | 408 | .company-list-content { |
| 398 | - flex: 1; | 409 | + flex: 1 0 auto; |
| 410 | + height: 0; | ||
| 399 | box-sizing: border-box; | 411 | box-sizing: border-box; |
| 400 | margin-top: 20rpx; | 412 | margin-top: 20rpx; |
| 401 | flex-shrink: 0; | 413 | flex-shrink: 0; |
| 402 | - height: 0; | ||
| 403 | margin-bottom: 20rpx; | 414 | margin-bottom: 20rpx; |
| 404 | width: 100%; | 415 | width: 100%; |
| 405 | 416 | ||
| 406 | .company-list-content-box { | 417 | .company-list-content-box { |
| 407 | - height: 99%; | 418 | + height: 100%; |
| 408 | width: 100%; | 419 | width: 100%; |
| 409 | box-sizing: border-box; | 420 | box-sizing: border-box; |
| 410 | overflow: scroll; | 421 | overflow: scroll; |
garbage-removal/src/pages/login/code.vue
| @@ -14,77 +14,94 @@ | @@ -14,77 +14,94 @@ | ||
| 14 | </view> | 14 | </view> |
| 15 | </template> | 15 | </template> |
| 16 | 16 | ||
| 17 | -<script> | ||
| 18 | -export default { | ||
| 19 | - data() { | ||
| 20 | - return { | ||
| 21 | - verifyFlag: false, | ||
| 22 | - iphoneNumber: "", | ||
| 23 | - startIphoneNumber: "", | ||
| 24 | - maxlength: 4, | ||
| 25 | - value: '', | ||
| 26 | - second: 10, | ||
| 27 | - show: false | ||
| 28 | - }; | ||
| 29 | - }, | ||
| 30 | - computed: {}, | ||
| 31 | - onLoad(options) { | ||
| 32 | - this.iphoneNumber = options.iphoneNumber; | ||
| 33 | - this.startIphoneNumber = this.handleIphoneNumber("" + options.iphoneNumber); | ||
| 34 | - this.getCaptcha(this.iphoneNumber) | ||
| 35 | - let interval = setInterval(() => { | ||
| 36 | - this.second--; | ||
| 37 | - if (this.second <= 0) { | ||
| 38 | - this.show = true; | ||
| 39 | - if (this.value.length != 4) { | ||
| 40 | - this.verifyFlag = true; | ||
| 41 | - } | ||
| 42 | - clearInterval(interval); | ||
| 43 | - } | ||
| 44 | - }, 1000); | ||
| 45 | - }, | ||
| 46 | - methods: { | ||
| 47 | - handleIphoneNumber(tel) { | ||
| 48 | - return tel.replace(tel.substring(3, 7), "****"); | ||
| 49 | - }, | ||
| 50 | - getCaptcha(iphoneNumber) { | ||
| 51 | - console.log("获取验证码:", iphoneNumber); | ||
| 52 | - }, | ||
| 53 | - // 收不到验证码选择时的选择 | ||
| 54 | - noCaptcha() { | ||
| 55 | - uni.showActionSheet({ | ||
| 56 | - itemList: ['重新获取验证码'], | ||
| 57 | - success: function (res) { | ||
| 58 | - this.getCaptcha(this.iphoneNumber) | ||
| 59 | - }, | ||
| 60 | - fail: function (res) { | ||
| 61 | - | ||
| 62 | - } | ||
| 63 | - }); | ||
| 64 | - }, | ||
| 65 | - // 校验验证码 | ||
| 66 | - checkVerifyNum(code) { | 17 | +<script setup> |
| 18 | +import { sendCode, userLogin } from "@/apis/user.js"; | ||
| 19 | +import { useMainStore } from '@/stores/index.js'; | ||
| 20 | +import { setRequestToken } from '@/utils/request/request.js'; | ||
| 21 | +import { onLoad } from "@dcloudio/uni-app"; | ||
| 22 | +import { ref } from "vue"; | ||
| 23 | +const store = useMainStore(); | ||
| 24 | +const verifyFlag = ref(false) | ||
| 25 | +const iphoneNumber = ref("") | ||
| 26 | +const startIphoneNumber = ref("") | ||
| 27 | +const maxlength = ref(4) | ||
| 28 | +const value = ref("") | ||
| 29 | +const second = ref(10); | ||
| 30 | +const show = ref(false) | ||
| 67 | 31 | ||
| 32 | +onLoad((options) => { | ||
| 33 | + iphoneNumber.value = options.iphoneNumber; | ||
| 34 | + startIphoneNumber.value = handleIphoneNumber("" + options.iphoneNumber); | ||
| 35 | + getCaptcha(iphoneNumber.value) | ||
| 36 | + let interval = setInterval(() => { | ||
| 37 | + second.value--; | ||
| 38 | + if (second.value <= 0) { | ||
| 39 | + show.value = true | ||
| 40 | + clearInterval(interval); | ||
| 41 | + } | ||
| 42 | + }, 1000); | ||
| 43 | +}) | ||
| 44 | + | ||
| 45 | +const handleIphoneNumber = (tel) => { | ||
| 46 | + return tel.replace(tel.substring(3, 7), "****"); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +const getCaptcha = (iphoneNumber) => { | ||
| 50 | + value.value = '' | ||
| 51 | + second.value = 10 | ||
| 52 | + show.value = false; | ||
| 53 | + let interval = setInterval(() => { | ||
| 54 | + second.value--; | ||
| 55 | + if (second.value <= 0) { | ||
| 56 | + show.value = true | ||
| 57 | + clearInterval(interval); | ||
| 58 | + } | ||
| 59 | + }, 1000); | ||
| 60 | + sendCode(iphoneNumber).then(res => { | ||
| 61 | + console.log(res); | ||
| 62 | + }) | ||
| 63 | +} | ||
| 64 | +// 收不到验证码选择时的选择 | ||
| 65 | +const noCaptcha = () => { | ||
| 66 | + uni.showActionSheet({ | ||
| 67 | + itemList: ['重新获取验证码'], | ||
| 68 | + success: function (res) { | ||
| 69 | + getCaptcha(iphoneNumber.value) | ||
| 68 | }, | 70 | }, |
| 69 | - // change事件侦听 | ||
| 70 | - change(value) { | ||
| 71 | - if (value.length != 4) { | ||
| 72 | - this.verifyFlag = true; | ||
| 73 | - } | ||
| 74 | - }, | ||
| 75 | - // 输入完验证码最后一位执行 | ||
| 76 | - finish(value) { | ||
| 77 | - if (value.length == 4) { | ||
| 78 | - // TODO 到首页 | ||
| 79 | - this.verifyFlag = false; | ||
| 80 | - this.$u.route({ | ||
| 81 | - type: "switchTab", | ||
| 82 | - url: `pages/home/index`, | ||
| 83 | - }) | ||
| 84 | - } | 71 | + fail: function (res) { |
| 72 | + | ||
| 85 | } | 73 | } |
| 74 | + }); | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +// 校验验证码 | ||
| 78 | +const checkVerifyNum = (code) => { | ||
| 79 | + userLogin({ loginType: 0, tel: iphoneNumber.value, code: code }).then(res => { | ||
| 80 | + // 登录成功 | ||
| 81 | + if (res.data.success) { | ||
| 82 | + verifyFlag.value = false; | ||
| 83 | + setRequestToken(res.data.data) | ||
| 84 | + store.token = res.data.data | ||
| 85 | + uni.$u.route({ | ||
| 86 | + type: "switchTab", | ||
| 87 | + url: `pages/home/index`, | ||
| 88 | + }) | ||
| 89 | + } else { | ||
| 90 | + verifyFlag.value = true; | ||
| 91 | + } | ||
| 92 | + }) | ||
| 93 | +} | ||
| 94 | + | ||
| 95 | +// change事件侦听 | ||
| 96 | +const change = (value) => { | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +// 输入完验证码最后一位执行 | ||
| 100 | +const finish = (value) => { | ||
| 101 | + if (value.length == 4) { | ||
| 102 | + checkVerifyNum(value); | ||
| 86 | } | 103 | } |
| 87 | -}; | 104 | +} |
| 88 | </script> | 105 | </script> |
| 89 | 106 | ||
| 90 | <style lang="scss" scoped> | 107 | <style lang="scss" scoped> |
garbage-removal/src/pages/login/index.vue
| @@ -12,9 +12,12 @@ | @@ -12,9 +12,12 @@ | ||
| 12 | </view> | 12 | </view> |
| 13 | <view class="buttom"> | 13 | <view class="buttom"> |
| 14 | <view class="loginType"> | 14 | <view class="loginType"> |
| 15 | - <view class="wechat item" @click="handleWeixinLogin"> | ||
| 16 | - <view class="icon"><u-icon size="40" name="weixin-fill" color="rgb(83,194,64)"></u-icon></view> | ||
| 17 | - 微信 | 15 | + <view class="wechat item"> |
| 16 | + <button class="box" open-type="getPhoneNumber" @getphonenumber="handleWeixinLogin"> | ||
| 17 | + <view class="icon"><u-icon size="60" name="weixin-fill" color="rgb(83,194,64)"></u-icon> | ||
| 18 | + </view> | ||
| 19 | + 微信登录 | ||
| 20 | + </button> | ||
| 18 | </view> | 21 | </view> |
| 19 | </view> | 22 | </view> |
| 20 | <view class="hint"> | 23 | <view class="hint"> |
| @@ -27,10 +30,11 @@ | @@ -27,10 +30,11 @@ | ||
| 27 | </template> | 30 | </template> |
| 28 | 31 | ||
| 29 | <script> | 32 | <script> |
| 33 | +import { userLogin } from "@/apis/user.js"; | ||
| 30 | export default { | 34 | export default { |
| 31 | data() { | 35 | data() { |
| 32 | return { | 36 | return { |
| 33 | - tel: '' | 37 | + tel: '18980249160' |
| 34 | } | 38 | } |
| 35 | }, | 39 | }, |
| 36 | computed: { | 40 | computed: { |
| @@ -63,18 +67,17 @@ export default { | @@ -63,18 +67,17 @@ export default { | ||
| 63 | handleUserAgreement() { | 67 | handleUserAgreement() { |
| 64 | console.log("user click agreement"); | 68 | console.log("user click agreement"); |
| 65 | }, | 69 | }, |
| 66 | - handleWeixinLogin() { | 70 | + handleWeixinLogin(wxInfo) { |
| 67 | uni.login({ | 71 | uni.login({ |
| 68 | provider: 'weixin', | 72 | provider: 'weixin', |
| 69 | - success: (res) => { | ||
| 70 | - this.code = res.code; | ||
| 71 | - console.log('code', res.code); | ||
| 72 | - if (res.errMsg == 'login:ok') { | ||
| 73 | - //TODO 获取code 携带code参数调用后端接口} | ||
| 74 | - | ||
| 75 | - } | 73 | + success: res => { |
| 74 | + userLogin({ loginType: type, encryptedData: wxInfo.detail.encryptedData, iv: wxInfo.detail.iv, wxCode: res.code }) | ||
| 75 | + .then(res => { | ||
| 76 | + console.log(res); | ||
| 77 | + }) | ||
| 76 | } | 78 | } |
| 77 | - }) | 79 | + |
| 80 | + }); | ||
| 78 | } | 81 | } |
| 79 | } | 82 | } |
| 80 | } | 83 | } |
| @@ -110,7 +113,7 @@ export default { | @@ -110,7 +113,7 @@ export default { | ||
| 110 | 113 | ||
| 111 | .getCaptcha { | 114 | .getCaptcha { |
| 112 | background-color: #5ac725; | 115 | background-color: #5ac725; |
| 113 | - color: $u-tips-color; | 116 | + color: #ffffff; |
| 114 | border: none; | 117 | border: none; |
| 115 | font-size: 30rpx; | 118 | font-size: 30rpx; |
| 116 | padding: 12rpx 0; | 119 | padding: 12rpx 0; |
| @@ -135,12 +138,27 @@ export default { | @@ -135,12 +138,27 @@ export default { | ||
| 135 | justify-content: center; | 138 | justify-content: center; |
| 136 | 139 | ||
| 137 | .item { | 140 | .item { |
| 138 | - display: flex; | ||
| 139 | - flex-direction: column; | ||
| 140 | - align-items: center; | ||
| 141 | - color: $u-content-color; | ||
| 142 | - font-size: 28rpx; | 141 | + .box { |
| 142 | + display: flex; | ||
| 143 | + flex-direction: column; | ||
| 144 | + align-items: center; | ||
| 145 | + color: $u-content-color; | ||
| 146 | + justify-content: center; | ||
| 147 | + font-size: 28rpx; | ||
| 148 | + background-color: #ffffff00; | ||
| 149 | + border-radius: 0 !important; | ||
| 150 | + border: 0 solid #ffffff00 !important; | ||
| 151 | + padding: 0 !important; | ||
| 152 | + margin: 0 !important; | ||
| 153 | + | ||
| 154 | + &::after { | ||
| 155 | + border: none; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + } | ||
| 159 | + | ||
| 143 | } | 160 | } |
| 161 | + | ||
| 144 | } | 162 | } |
| 145 | 163 | ||
| 146 | .hint { | 164 | .hint { |
garbage-removal/src/pages/order/swiper-list-item/index.vue
| 1 | <template> | 1 | <template> |
| 2 | <view class="content-container"> | 2 | <view class="content-container"> |
| 3 | - <z-paging ref="paging" v-model="dataList" @query="queryList"> | 3 | + <z-paging ref="paging" :fixed="false" v-model="dataList" @query="queryList"> |
| 4 | <empty-view slot:empty></empty-view> | 4 | <empty-view slot:empty></empty-view> |
| 5 | - <view class="item" v-for="(item, index) in dataList"> | ||
| 6 | - <view class="item-title">{{ item }}</view> | 5 | + <view class="content-container-item-box" v-for="(item, index) in dataList"> |
| 6 | + <view class="content-container-item-box-title">{{ item }}</view> | ||
| 7 | </view> | 7 | </view> |
| 8 | </z-paging> | 8 | </z-paging> |
| 9 | </view> | 9 | </view> |
| @@ -23,6 +23,7 @@ const props = defineProps({ | @@ -23,6 +23,7 @@ const props = defineProps({ | ||
| 23 | const paging = ref(null) | 23 | const paging = ref(null) |
| 24 | const dataList = ref([]) | 24 | const dataList = ref([]) |
| 25 | const count = ref(0) | 25 | const count = ref(0) |
| 26 | +const timer = ref() | ||
| 26 | const queryList = (pageNo, pageSize) => { | 27 | const queryList = (pageNo, pageSize) => { |
| 27 | //这里的pageNo和pageSize会自动计算好,直接传给服务器即可 | 28 | //这里的pageNo和pageSize会自动计算好,直接传给服务器即可 |
| 28 | //这里的请求只是演示,请替换成自己的项目的网络请求,并在网络请求回调中通过paging.value.complete(请求回来的数组)将请求结果传给z-paging | 29 | //这里的请求只是演示,请替换成自己的项目的网络请求,并在网络请求回调中通过paging.value.complete(请求回来的数组)将请求结果传给z-paging |
| @@ -33,12 +34,13 @@ const queryList = (pageNo, pageSize) => { | @@ -33,12 +34,13 @@ const queryList = (pageNo, pageSize) => { | ||
| 33 | return | 34 | return |
| 34 | } | 35 | } |
| 35 | if (++count.value < 3) { | 36 | if (++count.value < 3) { |
| 36 | - | 37 | + clearTimeout(timer.value) |
| 38 | + timer.value = setTimeout(() => { | ||
| 39 | + console.log("hhhh"); | ||
| 40 | + paging.value.complete([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | ||
| 41 | + }, 500); | ||
| 37 | } | 42 | } |
| 38 | - setInterval(() => { | ||
| 39 | - paging.value.complete([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | ||
| 40 | - }, 500); | ||
| 41 | - paging.value.complete([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); | 43 | + |
| 42 | // }).catch(res => { | 44 | // }).catch(res => { |
| 43 | // //如果请求失败写paging.value.complete(false),会自动展示错误页面 | 45 | // //如果请求失败写paging.value.complete(false),会自动展示错误页面 |
| 44 | // //注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理 | 46 | // //注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理 |
garbage-removal/src/stores/main.js
| @@ -12,7 +12,7 @@ export const useMainStore = defineStore( | @@ -12,7 +12,7 @@ export const useMainStore = defineStore( | ||
| 12 | persist: { | 12 | persist: { |
| 13 | enabled: true, | 13 | enabled: true, |
| 14 | H5Storage: localStorage, | 14 | H5Storage: localStorage, |
| 15 | - // 调整为兼容多端的API | 15 | + // 调整为兼容多端的API |
| 16 | storage: { | 16 | storage: { |
| 17 | setItem(key, value) { | 17 | setItem(key, value) { |
| 18 | uni.setStorageSync(key, value) | 18 | uni.setStorageSync(key, value) |
garbage-removal/src/utils/request/request.js
| @@ -54,34 +54,32 @@ const instance = axios.create({ | @@ -54,34 +54,32 @@ const instance = axios.create({ | ||
| 54 | }); | 54 | }); |
| 55 | // 请求拦截器 | 55 | // 请求拦截器 |
| 56 | instance.interceptors.request.use((config) => { | 56 | instance.interceptors.request.use((config) => { |
| 57 | - console.log("请求拦截器", config); | ||
| 58 | - | ||
| 59 | return config; | 57 | return config; |
| 60 | }); | 58 | }); |
| 61 | // 响应拦截器 | 59 | // 响应拦截器 |
| 62 | instance.interceptors.response.use((response) => { | 60 | instance.interceptors.response.use((response) => { |
| 63 | - console.log("响应拦截器", response); | ||
| 64 | if (response.data.code != 200) { | 61 | if (response.data.code != 200) { |
| 65 | uni.showToast({ | 62 | uni.showToast({ |
| 66 | title: response.data.message, | 63 | title: response.data.message, |
| 67 | icon: "none", | 64 | icon: "none", |
| 68 | }); | 65 | }); |
| 69 | if (response.data.code == 401) { | 66 | if (response.data.code == 401) { |
| 70 | - uni.navigateTo({ | ||
| 71 | - url: "/pages/login/index", | ||
| 72 | - }); | 67 | + reSetLoginStatus(); |
| 73 | } | 68 | } |
| 74 | } | 69 | } |
| 75 | return response; | 70 | return response; |
| 76 | -},(error) => { | 71 | +}, (error) => { |
| 77 | if (error.response.status) { | 72 | if (error.response.status) { |
| 78 | switch (error.response.status) { | 73 | switch (error.response.status) { |
| 79 | - case 401: | 74 | + case 401: |
| 75 | + case 403: | ||
| 76 | + setRequestToken(null); | ||
| 80 | break; | 77 | break; |
| 81 | default: | 78 | default: |
| 82 | break; | 79 | break; |
| 83 | } | 80 | } |
| 84 | - } | 81 | + } |
| 82 | + uni.$u.toast("网络波动请再试~") | ||
| 85 | return Promise.reject(error) | 83 | return Promise.reject(error) |
| 86 | }); | 84 | }); |
| 87 | export default instance; | 85 | export default instance; |
| @@ -89,3 +87,10 @@ export default instance; | @@ -89,3 +87,10 @@ export default instance; | ||
| 89 | export function setRequestToken(token) { | 87 | export function setRequestToken(token) { |
| 90 | instance.defaults.headers.common["Authorization"] = `${token}`; | 88 | instance.defaults.headers.common["Authorization"] = `${token}`; |
| 91 | } | 89 | } |
| 90 | + | ||
| 91 | +const reSetLoginStatus = () => { | ||
| 92 | + uni.navigateTo({ | ||
| 93 | + type: "reLaunch", | ||
| 94 | + url: "/pages/login/index", | ||
| 95 | + }); | ||
| 96 | +} |
garbage-removal/src/uview-plus/components/u-tabs/u-tabs.vue
| @@ -3,34 +3,16 @@ | @@ -3,34 +3,16 @@ | ||
| 3 | <view class="u-tabs__wrapper"> | 3 | <view class="u-tabs__wrapper"> |
| 4 | <slot name="left" /> | 4 | <slot name="left" /> |
| 5 | <view class="u-tabs__wrapper__scroll-view-wrapper"> | 5 | <view class="u-tabs__wrapper__scroll-view-wrapper"> |
| 6 | - <scroll-view | ||
| 7 | - :scroll-x="scrollable" | ||
| 8 | - :scroll-left="scrollLeft" | ||
| 9 | - scroll-with-animation | ||
| 10 | - class="u-tabs__wrapper__scroll-view" | ||
| 11 | - :show-scrollbar="false" | ||
| 12 | - ref="u-tabs__wrapper__scroll-view" | ||
| 13 | - > | ||
| 14 | - <view | ||
| 15 | - class="u-tabs__wrapper__nav" | ||
| 16 | - ref="u-tabs__wrapper__nav" | ||
| 17 | - > | ||
| 18 | - <view | ||
| 19 | - class="u-tabs__wrapper__nav__item" | ||
| 20 | - v-for="(item, index) in list" | ||
| 21 | - :key="index" | ||
| 22 | - @tap="clickHandler(item, index)" | ||
| 23 | - :ref="`u-tabs__wrapper__nav__item-${index}`" | ||
| 24 | - :style="[$u.addStyle(itemStyle), {flex: scrollable ? '' : 1}]" | ||
| 25 | - :class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']" | ||
| 26 | - > | ||
| 27 | - <text | ||
| 28 | - :class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']" | ||
| 29 | - class="u-tabs__wrapper__nav__item__text" | ||
| 30 | - :style="[textStyle(index)]" | ||
| 31 | - >{{ item[keyName] }}</text> | ||
| 32 | - <u-badge | ||
| 33 | - :show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))" | 6 | + <scroll-view :scroll-x="scrollable" :scroll-left="scrollLeft" scroll-with-animation |
| 7 | + class="u-tabs__wrapper__scroll-view" :show-scrollbar="false" ref="u-tabs__wrapper__scroll-view"> | ||
| 8 | + <view class="u-tabs__wrapper__nav" ref="u-tabs__wrapper__nav"> | ||
| 9 | + <view class="u-tabs__wrapper__nav__item" v-for="(item, index) in list" :key="index" | ||
| 10 | + @tap="clickHandler(item, index)" :ref="`u-tabs__wrapper__nav__item-${index}`" | ||
| 11 | + :style="[$u.addStyle(itemStyle), { flex: scrollable ? '' : 1 }]" | ||
| 12 | + :class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']"> | ||
| 13 | + <text :class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']" | ||
| 14 | + class="u-tabs__wrapper__nav__item__text" :style="[textStyle(index)]">{{ item[keyName] }}</text> | ||
| 15 | + <u-badge :show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))" | ||
| 34 | :isDot="item.badge && item.badge.isDot || propsBadge.isDot" | 16 | :isDot="item.badge && item.badge.isDot || propsBadge.isDot" |
| 35 | :value="item.badge && item.badge.value || propsBadge.value" | 17 | :value="item.badge && item.badge.value || propsBadge.value" |
| 36 | :max="item.badge && item.badge.max || propsBadge.max" | 18 | :max="item.badge && item.badge.max || propsBadge.max" |
| @@ -41,35 +23,26 @@ | @@ -41,35 +23,26 @@ | ||
| 41 | :shape="item.badge && item.badge.shape || propsBadge.shape" | 23 | :shape="item.badge && item.badge.shape || propsBadge.shape" |
| 42 | :numberType="item.badge && item.badge.numberType || propsBadge.numberType" | 24 | :numberType="item.badge && item.badge.numberType || propsBadge.numberType" |
| 43 | :inverted="item.badge && item.badge.inverted || propsBadge.inverted" | 25 | :inverted="item.badge && item.badge.inverted || propsBadge.inverted" |
| 44 | - customStyle="margin-left: 4px;" | ||
| 45 | - ></u-badge> | 26 | + customStyle="margin-left: 4px;"></u-badge> |
| 46 | </view> | 27 | </view> |
| 47 | <!-- #ifdef APP-NVUE --> | 28 | <!-- #ifdef APP-NVUE --> |
| 48 | - <view | ||
| 49 | - class="u-tabs__wrapper__nav__line" | ||
| 50 | - ref="u-tabs__wrapper__nav__line" | ||
| 51 | - :style="[{ | ||
| 52 | - width: $u.addUnit(lineWidth), | ||
| 53 | - height: $u.addUnit(lineHeight), | ||
| 54 | - background: lineColor, | ||
| 55 | - backgroundSize: lineBgSize, | ||
| 56 | - }]" | ||
| 57 | - > | 29 | + <view class="u-tabs__wrapper__nav__line" ref="u-tabs__wrapper__nav__line" :style="[{ |
| 30 | + width: $u.addUnit(lineWidth), | ||
| 31 | + height: $u.addUnit(lineHeight), | ||
| 32 | + background: lineColor, | ||
| 33 | + backgroundSize: lineBgSize, | ||
| 34 | + }]"> | ||
| 58 | </view> | 35 | </view> |
| 59 | <!-- #endif --> | 36 | <!-- #endif --> |
| 60 | <!-- #ifndef APP-NVUE --> | 37 | <!-- #ifndef APP-NVUE --> |
| 61 | - <view | ||
| 62 | - class="u-tabs__wrapper__nav__line" | ||
| 63 | - ref="u-tabs__wrapper__nav__line" | ||
| 64 | - :style="[{ | ||
| 65 | - width: $u.addUnit(lineWidth), | ||
| 66 | - transform: `translate(${lineOffsetLeft}px)`, | ||
| 67 | - transitionDuration: `${firstTime ? 0 : duration}ms`, | ||
| 68 | - height: $u.addUnit(lineHeight), | ||
| 69 | - background: lineColor, | ||
| 70 | - backgroundSize: lineBgSize, | ||
| 71 | - }]" | ||
| 72 | - > | 38 | + <view class="u-tabs__wrapper__nav__line" ref="u-tabs__wrapper__nav__line" :style="[{ |
| 39 | + width: $u.addUnit(lineWidth), | ||
| 40 | + transform: `translate(${lineOffsetLeft}px)`, | ||
| 41 | + transitionDuration: `${firstTime ? 0 : duration}ms`, | ||
| 42 | + height: $u.addUnit(lineHeight), | ||
| 43 | + background: lineColor, | ||
| 44 | + backgroundSize: lineBgSize, | ||
| 45 | + }]"> | ||
| 73 | </view> | 46 | </view> |
| 74 | <!-- #endif --> | 47 | <!-- #endif --> |
| 75 | </view> | 48 | </view> |
| @@ -81,278 +54,268 @@ | @@ -81,278 +54,268 @@ | ||
| 81 | </template> | 54 | </template> |
| 82 | 55 | ||
| 83 | <script> | 56 | <script> |
| 84 | - // #ifdef APP-NVUE | ||
| 85 | - const animation = uni.requireNativePlugin('animation') | ||
| 86 | - const dom = uni.requireNativePlugin('dom') | ||
| 87 | - // #endif | ||
| 88 | - import props from './props.js'; | ||
| 89 | - import mpMixin from '../../libs/mixin/mpMixin.js'; | ||
| 90 | - import mixin from '../../libs/mixin/mixin.js'; | ||
| 91 | - /** | ||
| 92 | - * Tabs 标签 | ||
| 93 | - * @description tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。 | ||
| 94 | - * @tutorial https://ijry.github.io/uview-plus/components/tabs.html | ||
| 95 | - * @property {String | Number} duration 滑块移动一次所需的时间,单位秒(默认 200 ) | ||
| 96 | - * @property {String | Number} swierWidth swiper的宽度(默认 '750rpx' ) | ||
| 97 | - * @property {String} keyName 从`list`元素对象中读取的键名(默认 'name' ) | ||
| 98 | - * @event {Function(index)} change 标签改变时触发 index: 点击了第几个tab,索引从0开始 | ||
| 99 | - * @event {Function(index)} click 点击标签时触发 index: 点击了第几个tab,索引从0开始 | ||
| 100 | - * @example <u-tabs :list="list" :is-scroll="false" :current="current" @change="change"></u-tabs> | ||
| 101 | - */ | ||
| 102 | - export default { | ||
| 103 | - name: 'u-tabs', | ||
| 104 | - mixins: [mpMixin, mixin, props], | ||
| 105 | - data() { | ||
| 106 | - return { | ||
| 107 | - firstTime: true, | ||
| 108 | - scrollLeft: 0, | ||
| 109 | - scrollViewWidth: 0, | ||
| 110 | - lineOffsetLeft: 0, | ||
| 111 | - tabsRect: { | ||
| 112 | - left: 0 | ||
| 113 | - }, | ||
| 114 | - innerCurrent: 0, | ||
| 115 | - moving: false, | 57 | +// #ifdef APP-NVUE |
| 58 | +const animation = uni.requireNativePlugin('animation') | ||
| 59 | +const dom = uni.requireNativePlugin('dom') | ||
| 60 | +// #endif | ||
| 61 | +import mixin from '../../libs/mixin/mixin.js'; | ||
| 62 | +import mpMixin from '../../libs/mixin/mpMixin.js'; | ||
| 63 | +import props from './props.js'; | ||
| 64 | +/** | ||
| 65 | + * Tabs 标签 | ||
| 66 | + * @description tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。 | ||
| 67 | + * @tutorial https://ijry.github.io/uview-plus/components/tabs.html | ||
| 68 | + * @property {String | Number} duration 滑块移动一次所需的时间,单位秒(默认 200 ) | ||
| 69 | + * @property {String | Number} swierWidth swiper的宽度(默认 '750rpx' ) | ||
| 70 | + * @property {String} keyName 从`list`元素对象中读取的键名(默认 'name' ) | ||
| 71 | + * @event {Function(index)} change 标签改变时触发 index: 点击了第几个tab,索引从0开始 | ||
| 72 | + * @event {Function(index)} click 点击标签时触发 index: 点击了第几个tab,索引从0开始 | ||
| 73 | + * @example <u-tabs :list="list" :is-scroll="false" :current="current" @change="change"></u-tabs> | ||
| 74 | + */ | ||
| 75 | +export default { | ||
| 76 | + name: 'u-tabs', | ||
| 77 | + mixins: [mpMixin, mixin, props], | ||
| 78 | + data() { | ||
| 79 | + return { | ||
| 80 | + firstTime: true, | ||
| 81 | + scrollLeft: 0, | ||
| 82 | + scrollViewWidth: 0, | ||
| 83 | + lineOffsetLeft: 0, | ||
| 84 | + tabsRect: { | ||
| 85 | + left: 0 | ||
| 86 | + }, | ||
| 87 | + innerCurrent: 0, | ||
| 88 | + moving: false, | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + watch: { | ||
| 92 | + current: { | ||
| 93 | + immediate: true, | ||
| 94 | + handler(newValue, oldValue) { | ||
| 95 | + // 内外部值不相等时,才尝试移动滑块 | ||
| 96 | + if (newValue !== this.innerCurrent) { | ||
| 97 | + this.innerCurrent = newValue | ||
| 98 | + this.$nextTick(() => { | ||
| 99 | + this.resize() | ||
| 100 | + }) | ||
| 101 | + } | ||
| 116 | } | 102 | } |
| 117 | }, | 103 | }, |
| 118 | - watch: { | ||
| 119 | - current: { | ||
| 120 | - immediate: true, | ||
| 121 | - handler (newValue, oldValue) { | ||
| 122 | - // 内外部值不相等时,才尝试移动滑块 | ||
| 123 | - if (newValue !== this.innerCurrent) { | ||
| 124 | - this.innerCurrent = newValue | ||
| 125 | - this.$nextTick(() => { | ||
| 126 | - this.resize() | ||
| 127 | - }) | ||
| 128 | - } | 104 | + // list变化时,重新渲染list各项信息 |
| 105 | + list() { | ||
| 106 | + this.$nextTick(() => { | ||
| 107 | + this.resize() | ||
| 108 | + }) | ||
| 109 | + } | ||
| 110 | + }, | ||
| 111 | + computed: { | ||
| 112 | + textStyle() { | ||
| 113 | + return index => { | ||
| 114 | + const style = {} | ||
| 115 | + // 取当期是否激活的样式 | ||
| 116 | + const customeStyle = index === this.innerCurrent ? uni.$u.addStyle(this.activeStyle) : uni.$u | ||
| 117 | + .addStyle( | ||
| 118 | + this.inactiveStyle) | ||
| 119 | + // 如果当前菜单被禁用,则加上对应颜色,需要在此做处理,是因为nvue下,无法在style样式中通过!import覆盖标签的内联样式 | ||
| 120 | + if (this.list[index].disabled) { | ||
| 121 | + style.color = '#c8c9cc' | ||
| 129 | } | 122 | } |
| 130 | - }, | ||
| 131 | - // list变化时,重新渲染list各项信息 | ||
| 132 | - list() { | ||
| 133 | - this.$nextTick(() => { | ||
| 134 | - this.resize() | ||
| 135 | - }) | 123 | + return uni.$u.deepMerge(customeStyle, style) |
| 136 | } | 124 | } |
| 137 | }, | 125 | }, |
| 138 | - computed: { | ||
| 139 | - textStyle() { | ||
| 140 | - return index => { | ||
| 141 | - const style = {} | ||
| 142 | - // 取当期是否激活的样式 | ||
| 143 | - const customeStyle = index === this.innerCurrent ? uni.$u.addStyle(this.activeStyle) : uni.$u | ||
| 144 | - .addStyle( | ||
| 145 | - this.inactiveStyle) | ||
| 146 | - // 如果当前菜单被禁用,则加上对应颜色,需要在此做处理,是因为nvue下,无法在style样式中通过!import覆盖标签的内联样式 | ||
| 147 | - if (this.list[index].disabled) { | ||
| 148 | - style.color = '#c8c9cc' | ||
| 149 | - } | ||
| 150 | - return uni.$u.deepMerge(customeStyle, style) | ||
| 151 | - } | ||
| 152 | - }, | ||
| 153 | - propsBadge() { | ||
| 154 | - return uni.$u.props.badge | 126 | + propsBadge() { |
| 127 | + return uni.$u.props.badge | ||
| 128 | + } | ||
| 129 | + }, | ||
| 130 | + async mounted() { | ||
| 131 | + this.init() | ||
| 132 | + }, | ||
| 133 | + emits: ['click', 'change'], | ||
| 134 | + methods: { | ||
| 135 | + setLineLeft() { | ||
| 136 | + const tabItem = this.list[this.innerCurrent]; | ||
| 137 | + if (!tabItem) { | ||
| 138 | + return; | ||
| 139 | + } | ||
| 140 | + // 获取滑块该移动的位置 | ||
| 141 | + let lineOffsetLeft = this.list | ||
| 142 | + .slice(0, this.innerCurrent) | ||
| 143 | + .reduce((total, curr) => total + curr.rect.width, 0); | ||
| 144 | + // 获取下划线的数值px表示法 | ||
| 145 | + const lineWidth = uni.$u.getPx(this.lineWidth); | ||
| 146 | + this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2 | ||
| 147 | + // #ifdef APP-NVUE | ||
| 148 | + // 第一次移动滑块,无需过渡时间 | ||
| 149 | + this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration)) | ||
| 150 | + // #endif | ||
| 151 | + | ||
| 152 | + // 如果是第一次执行此方法,让滑块在初始化时,瞬间滑动到第一个tab item的中间 | ||
| 153 | + // 这里需要一个定时器,因为在非nvue下,是直接通过style绑定过渡时间,需要等其过渡完成后,再设置为false(非第一次移动滑块) | ||
| 154 | + if (this.firstTime) { | ||
| 155 | + setTimeout(() => { | ||
| 156 | + this.firstTime = false | ||
| 157 | + }, 10); | ||
| 155 | } | 158 | } |
| 156 | }, | 159 | }, |
| 157 | - async mounted() { | ||
| 158 | - this.init() | 160 | + // nvue下设置滑块的位置 |
| 161 | + animation(x, duration = 0) { | ||
| 162 | + // #ifdef APP-NVUE | ||
| 163 | + const ref = this.$refs['u-tabs__wrapper__nav__line'] | ||
| 164 | + animation.transition(ref, { | ||
| 165 | + styles: { | ||
| 166 | + transform: `translateX(${x}px)` | ||
| 167 | + }, | ||
| 168 | + duration | ||
| 169 | + }) | ||
| 170 | + // #endif | ||
| 159 | }, | 171 | }, |
| 160 | - emits: ['click', 'change'], | ||
| 161 | - methods: { | ||
| 162 | - setLineLeft() { | ||
| 163 | - const tabItem = this.list[this.innerCurrent]; | ||
| 164 | - if (!tabItem) { | ||
| 165 | - return; | ||
| 166 | - } | ||
| 167 | - // 获取滑块该移动的位置 | ||
| 168 | - let lineOffsetLeft = this.list | ||
| 169 | - .slice(0, this.innerCurrent) | ||
| 170 | - .reduce((total, curr) => total + curr.rect.width, 0); | ||
| 171 | - // 获取下划线的数值px表示法 | ||
| 172 | - const lineWidth = uni.$u.getPx(this.lineWidth); | ||
| 173 | - this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2 | ||
| 174 | - // #ifdef APP-NVUE | ||
| 175 | - // 第一次移动滑块,无需过渡时间 | ||
| 176 | - this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration)) | ||
| 177 | - // #endif | ||
| 178 | - | ||
| 179 | - // 如果是第一次执行此方法,让滑块在初始化时,瞬间滑动到第一个tab item的中间 | ||
| 180 | - // 这里需要一个定时器,因为在非nvue下,是直接通过style绑定过渡时间,需要等其过渡完成后,再设置为false(非第一次移动滑块) | ||
| 181 | - if (this.firstTime) { | ||
| 182 | - setTimeout(() => { | ||
| 183 | - this.firstTime = false | ||
| 184 | - }, 10); | ||
| 185 | - } | ||
| 186 | - }, | ||
| 187 | - // nvue下设置滑块的位置 | ||
| 188 | - animation(x, duration = 0) { | ||
| 189 | - // #ifdef APP-NVUE | ||
| 190 | - const ref = this.$refs['u-tabs__wrapper__nav__line'] | ||
| 191 | - animation.transition(ref, { | ||
| 192 | - styles: { | ||
| 193 | - transform: `translateX(${x}px)` | ||
| 194 | - }, | ||
| 195 | - duration | ||
| 196 | - }) | ||
| 197 | - // #endif | ||
| 198 | - }, | ||
| 199 | - // 点击某一个标签 | ||
| 200 | - clickHandler(item, index) { | ||
| 201 | - // 因为标签可能为disabled状态,所以click是一定会发出的,但是change事件是需要可用的状态才发出 | ||
| 202 | - this.$emit('click', { | ||
| 203 | - ...item, | ||
| 204 | - index | ||
| 205 | - }) | ||
| 206 | - // 如果disabled状态,返回 | ||
| 207 | - if (item.disabled) return | ||
| 208 | - this.innerCurrent = index | 172 | + // 点击某一个标签 |
| 173 | + clickHandler(item, index) { | ||
| 174 | + // 因为标签可能为disabled状态,所以click是一定会发出的,但是change事件是需要可用的状态才发出 | ||
| 175 | + this.$emit('click', { | ||
| 176 | + ...item, | ||
| 177 | + index | ||
| 178 | + }) | ||
| 179 | + // 如果disabled状态,返回 | ||
| 180 | + if (item.disabled) return | ||
| 181 | + this.innerCurrent = index | ||
| 182 | + this.resize() | ||
| 183 | + this.$emit('change', { | ||
| 184 | + ...item, | ||
| 185 | + index | ||
| 186 | + }) | ||
| 187 | + }, | ||
| 188 | + init() { | ||
| 189 | + uni.$u.sleep().then(() => { | ||
| 209 | this.resize() | 190 | this.resize() |
| 210 | - this.$emit('change', { | ||
| 211 | - ...item, | ||
| 212 | - index | ||
| 213 | - }) | ||
| 214 | - }, | ||
| 215 | - init() { | ||
| 216 | - uni.$u.sleep().then(() => { | ||
| 217 | - this.resize() | ||
| 218 | - }) | ||
| 219 | - }, | ||
| 220 | - setScrollLeft() { | ||
| 221 | - // 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息 | ||
| 222 | - const tabRect = this.list[this.innerCurrent] | ||
| 223 | - // 累加得到当前item到左边的距离 | ||
| 224 | - const offsetLeft = this.list | ||
| 225 | - .slice(0, this.innerCurrent) | ||
| 226 | - .reduce((total, curr) => { | ||
| 227 | - return total + curr.rect.width | ||
| 228 | - }, 0) | ||
| 229 | - // 此处为屏幕宽度 | ||
| 230 | - const windowWidth = uni.$u.sys().windowWidth | ||
| 231 | - // 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动 | ||
| 232 | - let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect | ||
| 233 | - .right) / 2 + this.tabsRect.left / 2 | ||
| 234 | - // 这里做一个限制,限制scrollLeft的最大值为整个scroll-view宽度减去tabs组件的宽度 | ||
| 235 | - scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width) | ||
| 236 | - this.scrollLeft = Math.max(0, scrollLeft) | ||
| 237 | - }, | ||
| 238 | - // 获取所有标签的尺寸 | ||
| 239 | - resize() { | ||
| 240 | - // 如果不存在list,则不处理 | ||
| 241 | - if(this.list.length === 0) { | ||
| 242 | - return | ||
| 243 | - } | ||
| 244 | - Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => { | ||
| 245 | - this.tabsRect = tabsRect | ||
| 246 | - this.scrollViewWidth = 0 | ||
| 247 | - itemRect.map((item, index) => { | ||
| 248 | - // 计算scroll-view的宽度,这里 | ||
| 249 | - this.scrollViewWidth += item.width | ||
| 250 | - // 另外计算每一个item的中心点X轴坐标 | ||
| 251 | - this.list[index].rect = item | ||
| 252 | - }) | ||
| 253 | - // 获取了tabs的尺寸之后,设置滑块的位置 | ||
| 254 | - this.setLineLeft() | ||
| 255 | - this.setScrollLeft() | ||
| 256 | - }) | ||
| 257 | - }, | ||
| 258 | - // 获取导航菜单的尺寸 | ||
| 259 | - getTabsRect() { | ||
| 260 | - return new Promise(resolve => { | ||
| 261 | - this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size)) | ||
| 262 | - }) | ||
| 263 | - }, | ||
| 264 | - // 获取所有标签的尺寸 | ||
| 265 | - getAllItemRect() { | ||
| 266 | - return new Promise(resolve => { | ||
| 267 | - const promiseAllArr = this.list.map((item, index) => this.queryRect( | ||
| 268 | - `u-tabs__wrapper__nav__item-${index}`, true)) | ||
| 269 | - Promise.all(promiseAllArr).then(sizes => resolve(sizes)) | ||
| 270 | - }) | ||
| 271 | - }, | ||
| 272 | - // 获取各个标签的尺寸 | ||
| 273 | - queryRect(el, item) { | ||
| 274 | - // #ifndef APP-NVUE | ||
| 275 | - // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://ijry.github.io/uview-plus/js/getRect.html | ||
| 276 | - // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同 | ||
| 277 | - return new Promise(resolve => { | ||
| 278 | - this.$uGetRect(`.${el}`).then(size => { | ||
| 279 | - resolve(size) | ||
| 280 | - }) | 191 | + }) |
| 192 | + }, | ||
| 193 | + setScrollLeft() { | ||
| 194 | + // 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息 | ||
| 195 | + const tabRect = this.list[this.innerCurrent] | ||
| 196 | + // 累加得到当前item到左边的距离 | ||
| 197 | + const offsetLeft = this.list | ||
| 198 | + .slice(0, this.innerCurrent) | ||
| 199 | + .reduce((total, curr) => { | ||
| 200 | + return total + curr.rect.width | ||
| 201 | + }, 0) | ||
| 202 | + // 此处为屏幕宽度 | ||
| 203 | + const windowWidth = uni.$u.sys().windowWidth | ||
| 204 | + // 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动 | ||
| 205 | + let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect | ||
| 206 | + .right) / 2 + this.tabsRect.left / 2 | ||
| 207 | + // 这里做一个限制,限制scrollLeft的最大值为整个scroll-view宽度减去tabs组件的宽度 | ||
| 208 | + scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width) | ||
| 209 | + this.scrollLeft = Math.max(0, scrollLeft) | ||
| 210 | + }, | ||
| 211 | + // 获取所有标签的尺寸 | ||
| 212 | + resize() { | ||
| 213 | + // 如果不存在list,则不处理 | ||
| 214 | + if (this.list.length === 0) { | ||
| 215 | + return | ||
| 216 | + } | ||
| 217 | + Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => { | ||
| 218 | + this.tabsRect = tabsRect | ||
| 219 | + this.scrollViewWidth = 0 | ||
| 220 | + itemRect.map((item, index) => { | ||
| 221 | + // 计算scroll-view的宽度,这里 | ||
| 222 | + this.scrollViewWidth += item.width | ||
| 223 | + // 另外计算每一个item的中心点X轴坐标 | ||
| 224 | + this.list[index].rect = item | ||
| 281 | }) | 225 | }) |
| 282 | - // #endif | ||
| 283 | - | ||
| 284 | - // #ifdef APP-NVUE | ||
| 285 | - // nvue下,使用dom模块查询元素高度 | ||
| 286 | - // 返回一个promise,让调用此方法的主体能使用then回调 | ||
| 287 | - return new Promise(resolve => { | ||
| 288 | - dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => { | ||
| 289 | - resolve(res.size) | ||
| 290 | - }) | 226 | + // 获取了tabs的尺寸之后,设置滑块的位置 |
| 227 | + this.setLineLeft() | ||
| 228 | + this.setScrollLeft() | ||
| 229 | + }) | ||
| 230 | + }, | ||
| 231 | + // 获取导航菜单的尺寸 | ||
| 232 | + getTabsRect() { | ||
| 233 | + return new Promise(resolve => { | ||
| 234 | + this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size)) | ||
| 235 | + }) | ||
| 236 | + }, | ||
| 237 | + // 获取所有标签的尺寸 | ||
| 238 | + getAllItemRect() { | ||
| 239 | + return new Promise(resolve => { | ||
| 240 | + const promiseAllArr = this.list.map((item, index) => this.queryRect( | ||
| 241 | + `u-tabs__wrapper__nav__item-${index}`, true)) | ||
| 242 | + Promise.all(promiseAllArr).then(sizes => resolve(sizes)) | ||
| 243 | + }) | ||
| 244 | + }, | ||
| 245 | + // 获取各个标签的尺寸 | ||
| 246 | + queryRect(el, item) { | ||
| 247 | + // #ifndef APP-NVUE | ||
| 248 | + // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://ijry.github.io/uview-plus/js/getRect.html | ||
| 249 | + // 组件内部一般用this.$uGetRect,对外的为uni.$u.getRect,二者功能一致,名称不同 | ||
| 250 | + return new Promise(resolve => { | ||
| 251 | + this.$uGetRect(`.${el}`).then(size => { | ||
| 252 | + resolve(size) | ||
| 291 | }) | 253 | }) |
| 292 | - // #endif | ||
| 293 | - }, | 254 | + }) |
| 255 | + // #endif | ||
| 294 | }, | 256 | }, |
| 295 | - } | 257 | + }, |
| 258 | +} | ||
| 296 | </script> | 259 | </script> |
| 297 | 260 | ||
| 298 | <style lang="scss" scoped> | 261 | <style lang="scss" scoped> |
| 299 | - @import "../../libs/css/components.scss"; | 262 | +@import "../../libs/css/components.scss"; |
| 263 | + | ||
| 264 | +.u-tabs { | ||
| 300 | 265 | ||
| 301 | - .u-tabs { | 266 | + &__wrapper { |
| 267 | + @include flex; | ||
| 268 | + align-items: center; | ||
| 269 | + | ||
| 270 | + &__scroll-view-wrapper { | ||
| 271 | + flex: 1; | ||
| 272 | + /* #ifndef APP-NVUE */ | ||
| 273 | + overflow: auto hidden; | ||
| 274 | + /* #endif */ | ||
| 275 | + } | ||
| 302 | 276 | ||
| 303 | - &__wrapper { | 277 | + &__scroll-view { |
| 304 | @include flex; | 278 | @include flex; |
| 305 | - align-items: center; | 279 | + flex: 1; |
| 280 | + } | ||
| 306 | 281 | ||
| 307 | - &__scroll-view-wrapper { | ||
| 308 | - flex: 1; | ||
| 309 | - /* #ifndef APP-NVUE */ | ||
| 310 | - overflow: auto hidden; | ||
| 311 | - /* #endif */ | ||
| 312 | - } | 282 | + &__nav { |
| 283 | + @include flex; | ||
| 284 | + position: relative; | ||
| 313 | 285 | ||
| 314 | - &__scroll-view { | 286 | + &__item { |
| 287 | + padding: 0 11px; | ||
| 315 | @include flex; | 288 | @include flex; |
| 316 | - flex: 1; | ||
| 317 | - } | 289 | + align-items: center; |
| 290 | + justify-content: center; | ||
| 318 | 291 | ||
| 319 | - &__nav { | ||
| 320 | - @include flex; | ||
| 321 | - position: relative; | 292 | + &--disabled { |
| 293 | + /* #ifndef APP-NVUE */ | ||
| 294 | + cursor: not-allowed; | ||
| 295 | + /* #endif */ | ||
| 296 | + } | ||
| 322 | 297 | ||
| 323 | - &__item { | ||
| 324 | - padding: 0 11px; | ||
| 325 | - @include flex; | ||
| 326 | - align-items: center; | ||
| 327 | - justify-content: center; | 298 | + &__text { |
| 299 | + font-size: 15px; | ||
| 300 | + color: $u-content-color; | ||
| 328 | 301 | ||
| 329 | &--disabled { | 302 | &--disabled { |
| 330 | - /* #ifndef APP-NVUE */ | ||
| 331 | - cursor: not-allowed; | ||
| 332 | - /* #endif */ | ||
| 333 | - } | ||
| 334 | - | ||
| 335 | - &__text { | ||
| 336 | - font-size: 15px; | ||
| 337 | - color: $u-content-color; | ||
| 338 | - | ||
| 339 | - &--disabled { | ||
| 340 | - color: $u-disabled-color !important; | ||
| 341 | - } | 303 | + color: $u-disabled-color !important; |
| 342 | } | 304 | } |
| 343 | } | 305 | } |
| 306 | + } | ||
| 344 | 307 | ||
| 345 | - &__line { | ||
| 346 | - height: 3px; | ||
| 347 | - background: $u-primary; | ||
| 348 | - width: 30px; | ||
| 349 | - position: absolute; | ||
| 350 | - bottom: 2px; | ||
| 351 | - border-radius: 100px; | ||
| 352 | - transition-property: transform; | ||
| 353 | - transition-duration: 300ms; | ||
| 354 | - } | 308 | + &__line { |
| 309 | + height: 3px; | ||
| 310 | + background: $u-primary; | ||
| 311 | + width: 30px; | ||
| 312 | + position: absolute; | ||
| 313 | + bottom: 2px; | ||
| 314 | + border-radius: 100px; | ||
| 315 | + transition-property: transform; | ||
| 316 | + transition-duration: 300ms; | ||
| 355 | } | 317 | } |
| 356 | } | 318 | } |
| 357 | } | 319 | } |
| 320 | +} | ||
| 358 | </style> | 321 | </style> |