index.vue 5.95 KB
<!--
 * @Date: 2024-01-15 16:35:10
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2026-01-07 22:54:19
 * @FilePath: /xyxBooking-weapp/src/pages/addVisitor/index.vue
 * @Description: 添加参观者
-->
<template>
    <view class="add-visitor-page">
        <view class="content">
            <view class="form-card">
                <view class="form-row">
                    <view class="label">姓名</view>
                    <nut-input v-model="name" class="field-input" placeholder="请输入参观者真实姓名" type="text" input-align="right" :border="false" />
                </view>
                <view class="form-row">
                    <view class="label">证件类型</view>
                    <view class="field-value picker-value" @tap="open_id_type_picker">
                        <text>{{ id_type_label }}</text>
                        <text class="picker-arrow">›</text>
                    </view>
                </view>
                <view class="form-row">
                    <view class="label">证件号码</view>
                    <nut-input v-model="id_number" class="field-input" placeholder="请输入证件号码" :type="id_number_type" input-align="right" :border="false" />
                </view>
            </view>

            <view class="tip">
                <IconFont name="tips" size="14" color="#C7A46D" />
                <text class="tip-text">温馨提示:账号实名认证信息一经填写将无法修改</text>
            </view>
        </view>

        <view class="footer">
            <view class="save-btn" @tap="save">保存</view>
        </view>

        <nut-popup v-model:visible="show_id_type_picker" position="bottom" safe-area-inset-bottom>
            <nut-picker
                v-model="id_type_picker_value"
                :columns="id_type_columns"
                title="选择证件类型"
                @confirm="on_id_type_confirm"
                @cancel="show_id_type_picker = false"
            ></nut-picker>
        </nut-popup>
    </view>
</template>

<script setup>
import { ref, computed } from 'vue'
import Taro from '@tarojs/taro'
import { addPersonAPI } from '@/api/index'
import { IconFont } from '@nutui/icons-vue-taro'

const name = ref('');
const id_number = ref('');
const show_id_type_picker = ref(false);
const id_type_options = [
    { label: '身份证', value: 1 },
    { label: '其他', value: 3 }
];
const id_type = ref(id_type_options[0].value);
const id_type_picker_value = ref([String(id_type.value)]);

const id_type_columns = computed(() => {
    return id_type_options.map(item => ({
        text: item.label,
        value: String(item.value)
    }));
});
const id_type_label = computed(() => {
    return id_type_options.find(item => item.value === id_type.value)?.label || id_type_options[0].label;
});
const id_number_type = computed(() => (id_type.value === 1 ? 'idcard' : 'text'));

const open_id_type_picker = () => {
    id_type_picker_value.value = [String(id_type.value)];
    show_id_type_picker.value = true;
}

const on_id_type_confirm = ({ selectedValue }) => {
    const value = selectedValue?.[0];
    id_type.value = Number(value) || 1;
    show_id_type_picker.value = false;
}

// 身份证校验
const checkIDCard = (idcode) => {
    // 简单校验
    return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(idcode);
}

const save = async () => {
    if (!name.value) {
        Taro.showToast({ title: '请输入姓名', icon: 'none' });
        return;
    }
    if (!id_number.value) {
        Taro.showToast({ title: '请输入证件号码', icon: 'none' });
        return;
    }
    if (id_type.value === 1 && !checkIDCard(id_number.value)) {
        Taro.showToast({ title: '请输入正确的身份证号', icon: 'none' });
        return;
    }

    Taro.showLoading({ title: '保存中' });
    const { code, msg } = await addPersonAPI({
        name: name.value,
        id_type: id_type.value,
        id_number: id_number.value
    });
    Taro.hideLoading();

    if (code) {
        Taro.showToast({ title: '添加成功' });
        name.value = '';
        id_number.value = '';
        Taro.navigateBack();
    } else {
        Taro.showToast({ title: msg || '添加失败', icon: 'none' });
    }
}
</script>

<style lang="less">
.add-visitor-page {
    min-height: 100vh;
    background-color: #F6F6F6;
    padding-top: 2rpx;

    .content {
        padding: 32rpx;
        padding-bottom: 220rpx;
    }

    .form-card {
        background-color: #FFF;
        border-radius: 16rpx;
        overflow: hidden;
    }

    .form-row {
        display: flex;
        align-items: center;
        padding: 0 32rpx;
        height: 112rpx;

        &:not(:last-child) {
            border-bottom: 2rpx solid #F2F2F2;
        }

        .label {
            width: 160rpx;
            color: #333;
            font-size: 30rpx;
        }

        .field-value {
            flex: 1;
            text-align: right;
            color: #333;
            font-size: 30rpx;
        }

        .field-input {
            flex: 1;
        }

        .picker-value {
            display: flex;
            align-items: center;
            justify-content: flex-end;
        }

        .picker-arrow {
            margin-left: 10rpx;
            color: #BBB;
            font-size: 28rpx;
        }
    }

    .tip {
        margin-top: 28rpx;
        display: flex;
        align-items: center;
        color: #C7A46D;
        font-size: 24rpx;

        .tip-text {
            margin-left: 10rpx;
        }
    }

    .footer {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
        background-color: #F6F6F6;
    }

    .save-btn {
        width: 686rpx;
        height: 96rpx;
        background-color: #A67939;
        border-radius: 12rpx;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #FFF;
        font-size: 34rpx;
        font-weight: 600;
    }
}
</style>