| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- <template>
- <view class="plate-page">
- <uv-navbar title="我的车辆" bgColor="#C6171E" leftIconColor="#FFFFFF" :titleStyle="{ color: '#FFFFFF' }" :autoBack="true" :placeholder="true"></uv-navbar>
- <!-- 车牌输入区域 -->
- <view class="plate-input-section">
- <view class="plate-input-header">
- <text class="plate-label">车牌号码:</text>
- <view class="default-checkbox">
- <uv-checkbox v-model="isDefault" shape="circle"></uv-checkbox>
- <text class="default-text">设为默认车辆</text>
- </view>
- </view>
- <view class="plate-input-hint">
- <text>添加车牌后部分站点可享停车减免权益,临牌减免权益请查看站点详细减免规则</text>
- </view>
- <!-- 车牌输入框 -->
- <view class="plate-input-container">
- <!-- 省份输入 -->
- <input class="plate-item plate-region"
- v-model="plateChars[0]"
- maxlength="1"
- type="text"
- inputmode="none"
- readonly
- @focus="onPlateFocus(0); $event.preventDefault();"
- @click="toggleRegionPicker"
- @touchstart.prevent="toggleRegionPicker"/>
- <!-- 城市输入 -->
- <input class="plate-item plate-region"
- v-model="plateChars[1]"
- maxlength="1"
- type="text"
- inputmode="text"
- @input="onPlateInput"
- @focus="onPlateFocus(1)"/>
- <!-- 分隔符 -->
- <view class="plate-divider">
- <text>·</text>
- </view>
- <!-- 字母数字输入框 -->
- <input v-for="(char, index) in plateChars.slice(2)"
- :key="index + 2"
- class="plate-item"
- :class="{ 'new-energy': index === 5 }"
- v-model="plateChars[index + 2]"
- maxlength="1"
- placeholder-class="placeholder"
- :placeholder="index === 5 ? '新能源' : ''"
- type="text"
- inputmode="text"
- @input="onPlateInput"
- @focus="onPlateFocus(index + 2)"/>
- </view>
- <!-- 保存按钮 -->
- <view class="save-btn-container">
- <uv-button type="primary" color="#C6171E" shape="circle" :disabled="!isPlateValid" @click="savePlate">保存</uv-button>
- </view>
- <!-- 地区选择器 -->
- <view v-if="showRegionPicker" class="region-picker-container">
- <view class="region-picker-header">
- <uv-button type="default" size="small" @click="toggleRegionPicker">完成</uv-button>
- </view>
- <view class="region-grid">
- <view v-for="region in regions" :key="region"
- class="region-item"
- @click="selectRegion(region)">
- <text>{{ region }}</text>
- </view>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script setup>
- import {onLoad, onShow} from "@dcloudio/uni-app";
- import {ref, computed} from "vue";
- import {body} from "@/utils/https";
- const plateNo = ref("未绑定");
- const plateChars = ref(['粤', 'B', '', '', '', '', '', '']);
- const isDefault = ref(false);
- const currentInputIndex = ref(2);
- const showRegionPicker = ref(false);
- const regions = ['京', '津', '渝', '沪', '冀', '晋', '辽', '吉', '黑', '苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤', '琼', '川', '贵', '云', '陕', '甘', '青', '蒙', '桂', '宁', '新', '藏', '使', '领', '警', '学', '港', '澳'];
- const isPlateValid = computed(() => {
- const validChars = plateChars.value.filter(char => char !== '');
- return validChars.length >= 7;
- });
- const onPlateInput = () => {
- for (let i = 0; i < plateChars.value.length; i++) {
- plateChars.value[i] = plateChars.value[i].toUpperCase();
- }
- };
- const onPlateFocus = (index) => {
- currentInputIndex.value = index;
- };
- const toggleRegionPicker = () => {
- showRegionPicker.value = !showRegionPicker.value;
- };
- const selectRegion = (region) => {
- plateChars.value[0] = region;
- toggleRegionPicker();
- if (plateChars.value[1] === '') {
- currentInputIndex.value = 1;
- }
- };
- const savePlate = () => {
- const newPlateNo = plateChars.value.filter(char => char !== '').join('');
- if (newPlateNo.length < 7) {
- uni.showToast({
- title: '请输入完整车牌号',
- icon: 'none'
- });
- return;
- }
- save({
- defaultPlateNo: newPlateNo,
- });
- };
- const save = (form) => {
- uni.showLoading({
- title: "保存中",
- });
- body(`/user/updateUser`, form).then(() => {
- uni.hideLoading();
- getApp().globalData.user.defaultPlateNo = form.defaultPlateNo;
- plateNo.value = form.defaultPlateNo;
- uni.showToast({
- icon: "success",
- title: "保存成功",
- });
- setTimeout(() => {
- uni.navigateBack();
- }, 1500);
- }).catch((err) => {
- uni.hideLoading();
- uni.showToast({
- title: "保存失败",
- icon: "none"
- });
- });
- };
- onLoad(() => {
- if (getApp().globalData.user) {
- const user = getApp().globalData.user;
- plateNo.value = user.defaultPlateNo || "未绑定";
- if (user.defaultPlateNo) {
- const plate = user.defaultPlateNo;
- plateChars.value = ['粤', 'B', '', '', '', '', '', ''];
- for (let i = 0; i < plate.length && i < plateChars.value.length; i++) {
- plateChars.value[i] = plate[i];
- }
- }
- }
- });
- onShow(() => {
- if (getApp().globalData.user) {
- const user = getApp().globalData.user;
- plateNo.value = user.defaultPlateNo || "未绑定";
- }
- });
- </script>
- <style lang="scss" scoped>
- .plate-page {
- background-color: $uni-bg-color-page;
- min-height: 100vh;
- box-sizing: border-box;
- padding-bottom: 200rpx;
- }
- .plate-input-section {
- background-color: $uni-bg-color-card;
- padding: 30rpx;
- box-sizing: border-box;
- margin-bottom: 20rpx;
- }
- .plate-input-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 10rpx;
- }
- .plate-label {
- font-size: 32rpx;
- font-weight: $uni-font-weight-semibold;
- color: $uni-text-color;
- }
- .default-checkbox {
- display: flex;
- align-items: center;
- gap: 8rpx;
- }
- .default-text {
- font-size: 28rpx;
- color: $uni-text-color-secondary;
- }
- .plate-input-hint {
- margin-bottom: 30rpx;
- }
- .plate-input-hint text {
- font-size: 26rpx;
- color: $uni-text-color-tertiary;
- line-height: 1.5;
- }
- .plate-input-container {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 40rpx;
- gap: 4rpx;
- }
- .plate-item {
- width: 64rpx;
- height: 88rpx;
- border: 2rpx solid $uni-border-color;
- border-radius: 4rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 36rpx;
- font-weight: $uni-font-weight-semibold;
- color: $uni-text-color;
- background-color: $uni-bg-color-card;
- transition: all 0.2s ease;
- box-sizing: border-box;
- text-align: center;
- }
- .plate-item.active {
- border-color: $uni-color-primary;
- background-color: rgba($uni-color-primary, 0.04);
- }
- .plate-item.new-energy {
- width: 80rpx;
- border-color: $uni-color-success;
- background-color: rgba($uni-color-success, 0.06);
- }
- .plate-item.new-energy .placeholder {
- color: $uni-color-success;
- font-size: 18rpx;
- text-align: center;
- line-height: 20rpx;
- }
- .plate-region {
- background-color: $uni-bg-color-page;
- cursor: pointer;
- }
- .placeholder {
- text-align: center;
- }
- .plate-divider {
- width: 24rpx;
- height: 88rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 32rpx;
- color: $uni-text-color-secondary;
- }
- .save-btn-container {
- margin-top: 20rpx;
- }
- .save-btn-container :deep(.uv-button) {
- height: 80rpx;
- font-size: 30rpx;
- border-radius: 40rpx;
- background-color: $uni-color-primary;
- }
- .save-btn-container :deep(.uv-button--disabled) {
- background-color: $uni-border-color;
- color: $uni-text-color-hint;
- }
- // 地区选择器
- .region-picker-container {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- background-color: $uni-bg-color-card;
- border-radius: 20rpx 20rpx 0 0;
- padding: 15rpx;
- box-sizing: border-box;
- box-shadow: 0 -4rpx 12rpx rgba(0, 0, 0, 0.05);
- z-index: 1000;
- height: 38vh;
- overflow-y: hidden;
- }
- .region-picker-header {
- display: flex;
- justify-content: flex-end;
- margin-bottom: 5rpx;
- padding: 0 5rpx;
- }
- .region-picker-header :deep(.uv-button) {
- font-size: 30rpx;
- color: $uni-color-primary;
- background-color: transparent;
- border: none;
- padding: 5rpx 15rpx;
- }
- .region-grid {
- display: flex;
- flex-wrap: wrap;
- gap: 6rpx;
- padding: 5rpx;
- height: calc(38vh - 60rpx);
- overflow-y: hidden;
- justify-content: center;
- }
- .region-item {
- width: 85rpx;
- height: 65rpx;
- background-color: $uni-bg-color-page;
- border-radius: 8rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 40rpx;
- font-weight: $uni-font-weight-semibold;
- color: $uni-text-color;
- cursor: pointer;
- transition: all 0.2s ease;
- margin: 0;
- flex-shrink: 0;
- flex-basis: calc(16.66% - 8rpx);
- }
- .region-item:active {
- background-color: $uni-color-primary;
- color: $uni-text-color-inverse;
- transform: scale(0.95);
- }
- </style>
|