記錄一個基本的車輛信息管理頁面,由豆包撰寫完成,只需要微調頁面即可。
主要功能是車輛信息的查詢、新增、編輯,項目用到了uniapp、vue3、ts、uni-ui、z-paging
頁面效果如下:
?
以上界面均由豆包生成,完成度非常高,增、刪、查、改都實現了,加上組件的能力如z-paging、uni-ui組件庫,列表的分頁查詢、彈出窗等為用戶帶來良好的交互體驗。
以下是前端源碼(90%豆包+10%人工)
<template><z-paging ref="zPageRef" @query="fetchVehicleList" v-model="dataList"><!-- 搜索和篩選 --><template #top><!-- 頭部導航 --><view class="header"><view class="search-bar"><uni-search-bar v-model="searchQuery" placeholder="搜索車牌號碼、車主姓名或品牌"@confirm="handleSearch"></uni-search-bar></view><button class="add-btn" @click="showAddModal"><uni-icons type="plusempty" size="24" color="#0f80ff"></uni-icons><text>新增車輛</text></button></view></template><!-- 車輛列表 --><view class="vehicle-management"><view class="vehicle-list"><view class="vehicle-items"><view class="vehicle-item" v-for="(vehicle, index) in dataList" :key="index"><view class="vehicle-info"><view class="plate-number"><text>{{ vehicle.carNum }}</text><uni-tag :type="vehicle.type=='商戶' ? 'primary' : 'success'":text="vehicle.type=='商戶' ? '商戶' : '內部員工'"></uni-tag></view><view class="basic-info"><text class="name">車主: {{ vehicle.name }}</text><text class="tel">電話: {{ vehicle.tel }}</text></view><view class="basic-info"><text class="tel">職務: {{ vehicle.duty }}</text></view><view class="basic-info"><text class="tel">商戶名稱: {{ vehicle.brandName }}</text><text class="tel">展位號: {{ vehicle.boothNum }}</text></view></view><view class="vehicle-actions"><button class="view-btn" @click="viewVehicle(vehicle)"><uni-icons type="info" size="20" color="#0f80ff"></uni-icons></button><button class="edit-btn" @click="editVehicle(vehicle)"><uni-icons type="compose" size="20" color="#0f80ff"></uni-icons></button><button class="delete-btn" @click="confirmDelete(vehicle)"><uni-icons type="trash" size="20" color="#ff4500"></uni-icons></button></view></view></view></view><!-- 車輛表單模態框 --><uni-popup ref="vehicleFormPopup" type="center" :custom-style="popupStyle"><view class="vehicle-form"><view class="form-header"><text class="form-title">{{ isEditing ? '編輯車輛信息' : '新增車輛信息' }}</text><uni-icons type="closeempty" size="24" color="#666" @click="closeFormModal"></uni-icons></view><view class="form-content"><!-- 基本信息 --><view class="form-section"><view class="form-item"><text class="item-label">車牌號碼</text><view class="plate-input"><picker :range="provinces" @change="onProvinceChange"><view class="province-selector"><text>{{ formData.province }}</text><uni-icons type="arrowdown" size="18" color="#999"></uni-icons></view></picker><input v-model="formData.carNum" placeholder="請輸入車牌號碼" maxlength="6" /></view></view><view class="form-item"><text class="item-label">車主姓名</text><input v-model="formData.name" placeholder="請輸入車主姓名" /></view><view class="form-item"><text class="item-label">聯系電話</text><input v-model="formData.tel" placeholder="請輸入聯系電話" type="number" /></view><view class="form-item"><text class="item-label">車輛類型</text><picker :range="types" @change="onTypeChange"><view class="type-selector"><text>{{ formData.type || '請選擇車輛類型' }}</text><uni-icons type="arrowdown" size="18" color="#999"></uni-icons></view></picker></view></view><!-- 商戶 --><view v-if="formData.type=='商戶'" class="form-section"><view class="form-item"><text class="item-label">商戶名稱/品牌:</text><input v-model="formData.brandName" placeholder="商戶名稱/品牌" /></view><view class="form-item"><text class="item-label">展位號</text><input v-model="formData.boothNum" placeholder="請輸入展位號" /></view></view><!-- 內部員工 --><view v-if="formData.type=='內部員工'" class="form-section"><view class="form-item"><text class="item-label">職務</text><input v-model="formData.duty" placeholder="請輸入職務" /></view></view><view class="form-actions"><button class="cancel-btn" @click="closeFormModal">取消</button><button class="save-btn" @click="saveVehicle">保存</button></view></view></view></uni-popup><!-- 車輛詳情模態框 --><uni-popup ref="vehicleDetailPopup" type="bottom" :custom-style="popupStyle"><view class="vehicle-detail"><view class="detail-header"><text class="detail-title">車輛詳情</text><uni-icons type="closeempty" size="24" color="#666" @click="closeDetailModal"></uni-icons></view><view class="detail-content"><view class="detail-info"><view class="plate-number"><text>{{ selectedVehicle.carNum }}</text><uni-tag :type="selectedVehicle.brandName ? 'primary' : 'success'":text="selectedVehicle.brandName ? '商戶' : '內部員工'"></uni-tag></view><view class="info-group"><view class="info-item"><text class="info-label">車主姓名:</text><text class="info-value">{{ selectedVehicle.name }}</text></view><view class="info-item"><text class="info-label">聯系電話:</text><text class="info-value">{{ selectedVehicle.tel }}</text></view><view v-if="selectedVehicle.brandName" class=""><view class="info-item"><text class="info-label">商戶品牌:</text><text class="info-value">{{ selectedVehicle.brand }}</text></view><view class="info-item"><text class="info-label">展位號:</text><text class="info-value">{{ selectedVehicle.boothNum }}</text></view></view><view v-else class=""><view class="info-item"><text class="info-label">職務:</text><text class="info-value">{{ selectedVehicle.duty }}</text></view></view><view class="info-item"><text class="info-label">登記時間:</text><text class="info-value">{{ formatDate(selectedVehicle.inputtime*1000) }}</text></view><view class="info-item"><text class="info-label">違規次數:</text><text class="info-value">{{ selectedVehicle.violationNum || '無' }}</text></view></view></view><!-- 違規記錄 --><view class="violation-records"v-if="selectedVehicle.violations && selectedVehicle.violations.length > 0"><text class="records-title">違規記錄 ({{ selectedVehicle.violations.length }})</text><view class="record-item" v-for="(violation, index) in selectedVehicle.violations":key="index"><view class="record-header"><text class="record-time">{{ violation.time }}</text><textclass="record-type {{ violation.type === '占用多位' ? 'type-multiple' : 'type-forbidden' }}">{{ violation.type }}</text></view><text class="record-location">位置: {{ violation.location }}</text><text class="record-punishment">處理: {{ violation.punishment }}</text></view></view></view><view class="detail-actions"><button class="edit-btn" @click="editFromDetail">編輯信息</button><button class="violation-btn" @click="reportViolation">上報違規</button></view></view></uni-popup><!-- 自定義底部導航 --><CustomTabBar :tabList="tabList" :activeColor="'#409EFF'" :normalColor="'#666'" /></view></z-paging>
</template><script setup lang="ts">import { ref, reactive, onMounted, watch, computed } from 'vue';import { useRouter } from 'vue-router';import CustomTabBar from '@/components/CustomTabBar.vue'import request from '../../../utils/http2';import { formatDate } from '@/utils/date'// 頁面數據const searchQuery = ref('');const selectedVehicleType = ref('');const selectedStatus = ref('');const zPageRef = ref();const vehicleFormPopup = ref(null);const vehicleDetailPopup = ref(null);const popupStyle = ref('height: 60vh; border-radius: 20rpx 20rpx 0 0;');const dataList = ref({})// 數據配置const provinces = ref(['京', '津', '冀', '晉', '蒙', '遼', '吉', '黑','滬', '蘇', '浙', '皖', '閩', '贛', '魯', '豫','鄂', '湘', '粵', '桂', '瓊', '渝', '川', '貴','云', '藏', '陜', '甘', '青', '寧', '新']);const types = ['商戶', '內部員工'];const statusOptions = ref(['全部', '正常', '違規', '黑名單']);// 底部導航配置const tabList = ref([{name: 'record',path: '/pages/ffep/car/car',text: '過夜登記',icon: 'checkbox',activeIcon: 'checkbox-filled'},{name: 'violation',path: 'parkingViolation',text: '違規登記',icon: 'close',activeIcon: 'clear'},{name: 'manager',path: 'manager',text: '車輛管理',icon: 'calendar',activeIcon: 'calendar-filled'},{name: 'statistics',path: '/pages/ffep/car/statistics',text: '統計',icon: 'info',activeIcon: 'info-filled'}])// 表單數據const formData = reactive({id: '',province: '粵',carNum: '',name: '',tel: '',duty: '',brandName: '',boothNum: '',status: '正常',remark: '',registerTime: '',type: ''});// 選中的車輛const selectedVehicle = reactive({id: '',carNum: '',name: '',tel: '',duty: '',brandName: '',boothNum: '',status: '',violations:[]});// 狀態const isEditing = ref(false);const loadingText = ref('加載中...');const onTypeChange = (e) => {formData.type = types[e.detail.value]}// 加載車輛列表const fetchVehicleList = async (pageIndex : number, pageSize : number) => {try {// 構建查詢參數const params = {pageNo: pageIndex,pageSize: pageSize,keyword: searchQuery.value,duty: selectedVehicleType.value || undefined,status: selectedStatus.value || undefined};// 調用API獲取車輛列表const res = await request({url: '/api/ffep/parking/carlist',method: 'GET',data: params});if (res.code === 1) {zPageRef.value.complete(res.data)} else {uni.showToast({title: res.msg || '獲取數據失敗',icon: 'none'});zPageRef.value.complete(false);}} catch (error) {console.error('獲取車輛列表失敗', error);uni.showToast({title: '網絡錯誤,請稍后重試',icon: 'none'});zPageRef.value.complete(false);}};// 刷新列表const onRefresh = () => {zPageRef.value?.refresh();};// 加載更多const onLoadMore = () => {zPageRef.value?.loadMore();};// 處理搜索const handleSearch = () => {onRefresh();};// 顯示新增車輛模態框const showAddModal = () => {// 重置表單resetForm();isEditing.value = false;vehicleFormPopup.value.open();};// 查看車輛詳情const viewVehicle = (vehicle : any) => {// 復制車輛數據到詳情對象Object.assign(selectedVehicle, vehicle);// 獲取車輛違規記錄getVehicleViolations(vehicle.carNum);vehicleDetailPopup.value.open();};// 獲取車輛違規記錄const getVehicleViolations = async (carNum : string) => {const res = await request({url: `/api/ffep/parking/getVehicleViolations`,method: 'POST',data: {carNum: carNum}});if (res.code === 1) {selectedVehicle.violations = res.data || [];} else {selectedVehicle.violations = [];uni.showToast({title: res.msg || '獲取違規記錄失敗',icon: 'none'});}};// 編輯車輛const editVehicle = (vehicle : any) => {// 復制車輛數據到表單Object.assign(formData, vehicle);isEditing.value = true;vehicleFormPopup.value.open();};// 從詳情頁編輯const editFromDetail = () => {// 復制詳情數據到表單Object.assign(formData, selectedVehicle);isEditing.value = true;// 關閉詳情模態框,打開表單模態框vehicleDetailPopup.value.close();setTimeout(() => {vehicleFormPopup.value.open();}, 300);};// 上報違規const reportViolation = () => {// 關閉詳情模態框vehicleDetailPopup.value.close();// 跳轉到違規上報頁面,傳遞車輛IDuni.navigateTo({url: `/pages/violation/report?vehicleId=${selectedVehicle.id}`});};// 表單相關事件處理const onProvinceChange = (e : any) => {formData.province = provinces.value[e.detail.value];};// 重置表單const resetForm = () => {formData.id = '';formData.province = '粵';formData.carNum = '';formData.name = '';formData.tel = '';formData.duty = '';formData.brand = '';formData.color = '';formData.status = '正常';formData.remark = '';formData.registerTime = '';};// 關閉表單模態框const closeFormModal = () => {vehicleFormPopup.value.close();};// 關閉詳情模態框const closeDetailModal = () => {vehicleDetailPopup.value.close();};// 保存車輛信息const saveVehicle = async () => {// 表單驗證if (!formData.carNum.trim()) {uni.showToast({title: '請輸入車牌號碼',icon: 'none'});return;}if (!formData.name.trim()) {uni.showToast({title: '請輸入車主姓名',icon: 'none'});return;}if (!formData.tel.trim()) {uni.showToast({title: '請輸入聯系電話',icon: 'none'});return;}if (!formData.type) {uni.showToast({title: '請選擇車輛類型',icon: 'none'});return;}try {let apiUrl = '';let method = '';if (isEditing.value) {// 編輯apiUrl = `/api/ffep/parking/editcar`;method = 'PUT';} else {// 新增apiUrl = '/api/ffep/parking/addcar';method = 'POST';}// 調用API保存車輛信息const res = await request({url: apiUrl,method,data: formData});if (res.code === 1) {uni.showToast({title: res.msg,icon: 'success'});// 關閉模態框closeFormModal();// 刷新列表onRefresh();} else {uni.showToast({title: res.msg || (isEditing.value ? '更新失敗' : '添加失敗'),icon: 'none'});}} catch (error) {console.error('保存車輛信息失敗', error);uni.showToast({title: '網絡錯誤,請稍后重試',icon: 'none'});}};// 確認刪除車輛const confirmDelete = (vehicle : any) => {uni.showModal({title: '確認刪除',content: `確定要刪除車牌為${vehicle.carNum}的車輛信息嗎?`,success: async (res) => {if (res.confirm) {try {// 調用API刪除車輛const result = await request({url: `/api/ffep/parking/delcar`,method: 'DELETE',data:{id:vehicle.id}});if (result.code === 1) {uni.showToast({title: '刪除成功',icon: 'success'});// 刷新列表onRefresh();} else {uni.showToast({title: result.msg || '刪除失敗',icon: 'none'});}} catch (error) {console.error('刪除車輛失敗', error);uni.showToast({title: '網絡錯誤,請稍后重試',icon: 'none'});}}}});};// 頁面加載時初始化onMounted(() => {zPageRef.value.reload()// 初始化微信JSSDK(如果需要)// initWecomJssdk();});
</script><style lang="scss" scoped>.vehicle-management {min-height: 100vh;background-color: #f5f5f5;}.header {display: flex;align-items: center;justify-content: space-between;height: 100rpx;background-color: #0f80ff;padding: 0 30rpx;.add-btn {display: flex;align-items: center;background-color: #ffffff;color: #0f80ff;border-radius: 20rpx;padding: 8rpx 20rpx;height: 75%;text {margin-left: 10rpx;font-size: 28rpx;}}}.vehicle-list {padding: 0 20rpx;.vehicle-items {.vehicle-item {display: flex;justify-content: space-between;background-color: #fff;border-radius: 16rpx;padding: 20rpx;margin-bottom: 20rpx;box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);.vehicle-info {flex: 1;.plate-number {display: flex;font-size: 32rpx;font-weight: bold;color: #333;margin-bottom: 10rpx;}.basic-info {display: flex;margin-bottom: 10rpx;.name,.tel {font-size: 26rpx;color: #666;margin-right: 20rpx;}}.extra-info {display: flex;flex-wrap: wrap;.type,.brand,.status {font-size: 24rpx;color: #999;margin-right: 20rpx;margin-bottom: 10rpx;}.status-normal {color: #00b42a;}.status-warning {color: #ff7d00;}}}.vehicle-actions {display: flex;flex-direction: column;justify-content: space-around;button {width: 60rpx;height: 60rpx;display: flex;align-items: center;justify-content: center;background-color: #f5f5f5;border-radius: 50%;margin-bottom: 10rpx;}}}}}// 表單模態框樣式.vehicle-form {background-color: #fff;border-radius: 20rpx 20rpx 0 0;height: 100%;overflow: hidden;.form-header {display: flex;align-items: center;justify-content: space-between;padding: 30rpx;border-bottom: 1rpx solid #e5e6eb;.form-title {font-size: 32rpx;font-weight: bold;color: #333;}}.form-content {padding: 20rpx 30rpx;height: calc(100% - 160rpx);overflow-y: auto;.form-section {margin-bottom: 30rpx;.section-title {font-size: 28rpx;font-weight: bold;color: #333;margin-bottom: 20rpx;}.form-item {margin-bottom: 25rpx;.item-label {display: block;font-size: 26rpx;color: #666;margin-bottom: 10rpx;}.plate-input {display: flex;.province-selector {width: 120rpx;height: 80rpx;display: flex;align-items: center;justify-content: center;border: 1rpx solid #e5e6eb;border-radius: 10rpx;margin-right: 20rpx;font-size: 32rpx;}input {flex: 1;border: 1rpx solid #e5e6eb;border-radius: 10rpx;padding: 0 20rpx;font-size: 32rpx;}}input,textarea {width: 100%;border: 1rpx solid #e5e6eb;border-radius: 10rpx;padding: 20rpx;font-size: 28rpx;}.type-selector,.status-selector {display: flex;align-items: center;justify-content: space-between;border: 1rpx solid #e5e6eb;border-radius: 10rpx;padding: 20rpx;font-size: 28rpx;}}}}.form-actions {display: flex;padding: 30rpx;border-top: 1rpx solid #e5e6eb;.cancel-btn,.save-btn {flex: 1;height: 90rpx;border-radius: 50rpx;font-size: 32rpx;display: flex;align-items: center;justify-content: center;}.cancel-btn {color: #666;border: 1rpx solid #e5e6eb;margin-right: 30rpx;}.save-btn {color: #fff;background-color: #0f80ff;}}}// 詳情模態框樣式.vehicle-detail {background-color: #fff;border-radius: 20rpx 20rpx 0 0;height: 100%;overflow: hidden;.detail-header {display: flex;align-items: center;justify-content: space-between;padding: 30rpx;border-bottom: 1rpx solid #e5e6eb;.detail-title {font-size: 32rpx;font-weight: bold;color: #333;width: 200rpx;}}.detail-content {padding: 20rpx 30rpx;height: calc(100% - 160rpx);overflow-y: auto;.detail-info {margin-bottom: 30rpx;.plate-number {display: flex;align-items: center;font-size: 36rpx;font-weight: bold;color: #333;margin-bottom: 20rpx;.status {font-size: 26rpx;font-weight: normal;margin-left: 20rpx;padding: 5rpx 15rpx;border-radius: 50rpx;}.status-normal {color: #00b42a;background-color: #e8fff3;}.status-warning {color: #ff7d00;background-color: #fff7e8;}}.info-group {.info-item {display: flex;align-items: center;margin-bottom: 20rpx;.info-label {width: 200rpx;font-size: 28rpx;color: #666;}.info-value {flex: 1;font-size: 28rpx;color: #333;}}}}.violation-records {.records-title {font-size: 28rpx;font-weight: bold;color: #333;margin-bottom: 20rpx;}.record-item {background-color: #f9f9f9;border-radius: 10rpx;padding: 20rpx;margin-bottom: 20rpx;.record-header {display: flex;align-items: center;justify-content: space-between;margin-bottom: 10rpx;.record-time {font-size: 26rpx;color: #666;}.record-type {font-size: 24rpx;padding: 5rpx 15rpx;border-radius: 50rpx;}.type-multiple {color: #ff7d00;background-color: #fff7e8;}.type-forbidden {color: #f53f3f;background-color: #ffeded;}}.record-location,.record-punishment {font-size: 26rpx;color: #666;margin-bottom: 5rpx;}}}}.detail-actions {display: flex;padding: 30rpx;border-top: 1rpx solid #e5e6eb;.edit-btn,.violation-btn {flex: 1;height: 90rpx;border-radius: 50rpx;font-size: 32rpx;display: flex;align-items: center;justify-content: center;}.edit-btn {color: #0f80ff;border: 1rpx solid #0f80ff;margin-right: 30rpx;}.violation-btn {color: #fff;background-color: #0f80ff;}}}
</style>
生成拿到的代碼只需要根據業務需求,刪改或調整部分字段,完成api接口數據對接,頁面都可以直接投入到業務使用場景了,整個頁面耗時(包括API接口后端開發)不到3小時完成,個人來說已經是非常高效,不得不感慨科技改變生活!!
當然不足也是有的,例如細節的地方需要微調,比如布局、樣式,AI雖然強大但是會耗費非常多的溝通時間,這部分建議手動修改。其次是AI有時候未必了解組件的使用方式,例如z-paging組件標簽的位置,經過多次溝通調整還是沒辦法正常運行,終歸還是得靠自己把控吧!