123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- <template>
- <view class="container">
- <!-- 主要内容 -->
- <view class="content">
- <!-- 基本信息 -->
- <view class="info-section">
- <view class="section-title">基本信息</view>
-
- <!-- 激活类型选择 -->
- <view class="activation-type">
- <view
- :class="['type-item', { active: activationType === 'self' }]"
- @click="activationType = 'self'"
- >
- 本人激活
- </view>
- <view
- :class="['type-item', { active: activationType === 'other' }]"
- @click="activationType = 'other'"
- >
- 非本人激活
- </view>
- </view>
-
- <!-- 表单字段 -->
- <view v-if="activationType === 'other'" class="form-item car-number-row">
- <view class="form-label">车牌号</view>
- <car-number-input
- v-model="formData.carNumber"
- @numberInputResult="carNumberInputResult"
- inputColor="#ECF1F4"
- style="width: 100%;"
- />
- </view>
- <view v-else class="form-item">
- <view class="form-label">车牌号</view>
- <view class="form-input" @click="selectCarNumber">
- <text :class="['input-text', { placeholder: !formData.carNumber }]">
- {{ formData.carNumber || '请选择车牌号' }}
- </text>
- <view class="arrow-down">▼</view>
- </view>
- </view>
-
- <view class="form-item">
- <view class="form-label">车牌颜色</view>
- <view class="form-input" @click="selectCarColor">
- <text :class="['input-text', { placeholder: !formData.carColor }]">
- {{ formData.carColor || '请选择车牌颜色' }}
- </text>
- <view class="arrow-down">▼</view>
- </view>
- </view>
-
- <view class="form-item">
- <view class="form-label">申请手机号</view>
- <input
- class="form-input-text"
- placeholder="请输入手机号码"
- v-model="formData.phoneNumber"
- type="number"
- maxlength="11"
- />
- </view>
- <!-- 非本人激活时显示验证码 -->
- <view v-if="activationType === 'other'" class="form-item">
- <view class="form-label">短信验证码</view>
- <view class="form-input" style="display:flex;align-items:center;">
- <input
- class="form-input-text"
- placeholder="请输入验证码"
- v-model="formData.smsCode"
- maxlength="6"
- style="flex:1;"
- />
- <button class="send-code-btn" @click="sendCode" :disabled="waitTime>0">
- {{ waitTime > 0 ? waitTime + 's后重试' : '发送验证码' }}
- </button>
- </view>
- </view>
- </view>
-
- <!-- 上传照片 -->
- <view class="upload-section">
- <view class="section-title">上传照片</view>
-
- <!-- 车辆45度照 -->
- <view class="picture-wrapper" @click="uploadImage('vehicle')">
- <view class="bg1">
- <view class="">
- <view class="name">上传激活车辆45度照</view>
- <view class="value">上传车辆45度角照片</view>
- <view class="tip">
- <view class="tip-value" @click.stop="showSpec('vehicle')">拍摄规范</view>
- </view>
- </view>
- <image v-if="!formData.vehicleImage" class="icon" :src="`${$imgUrl}issuance/chetou45.png`"
- :style="{'--bgimg':`url(${$imgUrl}issuance/bg-border.png)`}">
- </image>
- <image v-else class="icon" :src="formData.vehicleImage"
- :style="{'--bgimg':`url(${$imgUrl}issuance/bg-border.png)`}"></image>
- </view>
- </view>
-
- <!-- ETC设备安装照 -->
- <view class="picture-wrapper" @click="uploadImage('device')">
- <view class="bg1">
- <view class="">
- <view class="name">上传ETC设备安装照</view>
- <view class="value">上传ETC设备安装位置照片</view>
- <view class="tip">
- <view class="tip-value" @click.stop="showSpec('device')">拍摄规范</view>
- </view>
- </view>
- <image v-if="!formData.deviceImage" class="icon" :src="`${$imgUrl}issuance/device.png`"
- :style="{'--bgimg':`url(${$imgUrl}issuance/bg-border.png)`}">
- </image>
- <image v-else class="icon" :src="formData.deviceImage"
- :style="{'--bgimg':`url(${$imgUrl}issuance/bg-border.png)`}"></image>
- </view>
- </view>
- </view>
- </view>
-
- <!-- 底部按钮 -->
- <view class="bottom-button" @click="nextStep">
- 下一步
- </view>
- </view>
- </template>
-
- <script setup lang="ts">
- import { ref, reactive, onMounted, onUnmounted } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import carNumberInput from './components/car-number-input.vue'
-
- // 响应式数据
- const statusBarHeight = ref(0)
- const barHeight = ref(0)
- const activationType = ref('self') // 'self' 本人激活, 'other' 非本人激活
- const waitTime = ref(0)
- let timer: any = null
-
- const formData = reactive({
- carNumber: '',
- carColor: '',
- phoneNumber: '',
- vehicleImage: '',
- deviceImage: '',
- smsCode: ''
- })
-
- // 页面加载
- onLoad(() => {
- getSystemInfo()
- })
-
- // 获取系统信息
- const getSystemInfo = () => {
- const systemInfo = uni.getSystemInfoSync()
- statusBarHeight.value = systemInfo.statusBarHeight || 0
- const { top, height } = uni.getMenuButtonBoundingClientRect()
- barHeight.value = height ? height + (top - statusBarHeight.value) * 2 : 38
- }
-
- // 返回上一页
- const goBack = () => {
- uni.navigateBack()
- }
-
- // 选择车牌号
- const selectCarNumber = () => {
- // 这里可以调用车牌号选择组件
- uni.showToast({
- title: '车牌号选择功能',
- icon: 'none'
- })
- }
-
- // 选择车牌颜色
- const selectCarColor = () => {
- uni.showActionSheet({
- itemList: ['蓝色', '绿色', '黄色', '白色', '黑色'],
- success: (res) => {
- const colors = ['蓝色', '绿色', '黄色', '白色', '黑色']
- formData.carColor = colors[res.tapIndex]
- }
- })
- }
-
- // 上传图片
- const uploadImage = (type: 'vehicle' | 'device') => {
- uni.chooseImage({
- count: 1, //只能选取一张照片
- sizeType: ["original", "compressed"], //可以指定是原图还是压缩图,默认二者都有
- sourceType: ["camera", "album"], //从相册选择
- success: function (res) {
- // 这里可以添加文件上传逻辑
- const tempFilePath = res.tempFilePaths[0]
- if (type === 'vehicle') {
- formData.vehicleImage = tempFilePath
- } else {
- formData.deviceImage = tempFilePath
- }
- }
- })
- }
-
- // 显示拍摄规范
- const showSpec = (type: 'vehicle' | 'device') => {
- const title = type === 'vehicle' ? '车辆45度照拍摄规范' : 'ETC设备安装照拍摄规范'
- const content = type === 'vehicle'
- ? '请从车辆前45度角拍摄,确保车牌清晰可见,车辆完整入镜。'
- : '请拍摄ETC设备安装位置,确保设备清晰可见,安装牢固。'
-
- uni.showModal({
- title,
- content,
- showCancel: false
- })
- }
-
- // 发送验证码
- const sendCode = () => {
- if (!/^1[3-9]\d{9}$/.test(formData.phoneNumber)) {
- uni.showToast({ title: '请输入正确手机号', icon: 'none' })
- return
- }
- // 这里调用后端发送验证码接口
- uni.showToast({ title: '验证码已发送', icon: 'success' })
- waitTime.value = 60
- timer = setInterval(() => {
- waitTime.value--
- if (waitTime.value <= 0) clearInterval(timer)
- }, 1000)
- }
- onUnmounted(() => { if (timer) clearInterval(timer) })
-
- const carNumberInputResult = (val: string) => {
- formData.carNumber = val;
- };
-
- // 下一步
- const nextStep = () => {
- // 表单验证
- if (!formData.carNumber) {
- uni.showToast({
- title: '请选择车牌号',
- icon: 'none'
- })
- return
- }
-
- if (!formData.carColor) {
- uni.showToast({
- title: '请选择车牌颜色',
- icon: 'none'
- })
- return
- }
-
- if (!formData.phoneNumber) {
- uni.showToast({
- title: '请输入手机号码',
- icon: 'none'
- })
- return
- }
-
- if (!/^1[3-9]\d{9}$/.test(formData.phoneNumber)) {
- uni.showToast({
- title: '请输入正确的手机号码',
- icon: 'none'
- })
- return
- }
-
- if (!formData.vehicleImage) {
- uni.showToast({
- title: '请上传车辆45度照',
- icon: 'none'
- })
- return
- }
-
- if (!formData.deviceImage) {
- uni.showToast({
- title: '请上传ETC设备安装照',
- icon: 'none'
- })
- return
- }
-
- // 提交数据
- console.log('表单数据:', formData)
- uni.showToast({
- title: '提交成功',
- icon: 'success'
- })
- }
- </script>
-
- <style lang="scss" scoped>
- .container {
- min-height: 100vh;
- background-color: #f2f5f7;
- }
-
- .nav-bar {
- background-color: #fff;
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- z-index: 100;
-
- .nav-content {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 0 30rpx;
-
- .nav-left, .nav-right {
- width: 60rpx;
- height: 60rpx;
- display: flex;
- align-items: center;
- justify-content: center;
-
- .back-icon {
- width: 40rpx;
- height: 40rpx;
- }
-
- .more-dots {
- display: flex;
- flex-direction: column;
- gap: 4rpx;
-
- .dot {
- width: 6rpx;
- height: 6rpx;
- background-color: #333;
- border-radius: 50%;
- }
- }
- }
-
- .nav-title {
- font-size: 36rpx;
- font-weight: bold;
- color: #333;
- }
- }
- }
-
- .content {
- padding: 60rpx 30rpx 120rpx;
- }
-
- .info-section, .upload-section {
- background-color: #fff;
- border-radius: 20rpx;
- padding: 30rpx;
- margin-bottom: 30rpx;
-
- .section-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- margin-bottom: 30rpx;
- }
- }
-
- .activation-type {
- display: flex;
- background-color: #f5f5f5;
- border-radius: 10rpx;
- padding: 4rpx;
- margin-bottom: 30rpx;
-
- .type-item {
- flex: 1;
- text-align: center;
- padding: 20rpx 0;
- border-radius: 8rpx;
- font-size: 28rpx;
- color: #666;
- transition: all 0.3s;
-
- &.active {
- background-color: #c2a75f;
- color: #fff;
- }
- }
- }
-
- .form-item {
- display: flex;
- align-items: center;
- margin-bottom: 30rpx;
-
- .form-label {
- width: 160rpx;
- font-size: 28rpx;
- color: #333;
- }
-
- .form-input {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: space-between;
- height: 80rpx;
- padding: 0 20rpx;
- background-color: #f8f8f8;
- border-radius: 10rpx;
-
- .input-text {
- font-size: 28rpx;
- color: #333;
-
- &.placeholder {
- color: #999;
- }
- }
-
- .arrow-down {
- font-size: 20rpx;
- color: #999;
- }
- }
-
- .form-input-text {
- flex: 1;
- height: 80rpx;
- padding: 0 20rpx;
- background-color: #f8f8f8;
- border-radius: 10rpx;
- font-size: 28rpx;
- color: #333;
- }
- }
-
- .car-number-row {
- flex-direction: column;
- align-items: flex-start;
- .form-label {
- margin-bottom: 12rpx;
- }
- :deep(.car-number-input-root) {
- width: 100%;
- justify-content: flex-start;
- }
- }
-
- .picture-wrapper {
- margin-top: 30rpx;
-
- .bg1 {
- background: #F5F9FB;
- border-radius: 10rpx;
- padding: 40rpx 30rpx;
- display: flex;
- justify-content: space-between;
-
- .name {
- padding-top: 30rpx;
- font-size: 32rpx;
- font-family: SourceHanSansSC, SourceHanSansSC;
- font-weight: 500;
- color: #111;
- line-height: 34rpx;
- }
-
- .value {
- margin-top: 20rpx;
- font-size: 22rpx;
- font-family: SourceHanSansSC, SourceHanSansSC;
- font-weight: 400;
- color: #999999;
- line-height: 24rpx;
- }
-
- .tip {
- margin-top: 20rpx;
- text-align: center;
- width: 100rpx;
- height: 30rpx;
- border-radius: 6rpx;
- border: 1rpx solid #CCB375;
-
- .tip-value {
- font-size: 20rpx;
- font-family: Microsoft YaHei;
- font-weight: 400;
- color: #CCB375;
- line-height: 30rpx;
- opacity: 1;
- }
- }
- }
-
- .icon {
- width: 304rpx;
- height: 190rpx;
- background-image: var(--bgimg);
- background-size: 100% 100%;
- background-repeat: no-repeat;
- }
- }
-
- .bottom-button {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- height: 100rpx;
- background-color: #133850;
- color: #fff;
- font-size: 32rpx;
- font-weight: bold;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- .send-code-btn {
- margin-left: 16rpx;
- background: #f8f4e7;
- color: #ccb375;
- border: 1px solid #ccb375;
- border-radius: 10rpx;
- font-size: 24rpx;
- height: 60rpx;
- line-height: 60rpx;
- padding: 0 20rpx;
- }
- </style>
|