Explorar o código

Merge remote-tracking branch 'origin/master'

xu hai 2 meses
pai
achega
963b0cc3c9

+ 1 - 1
server/api/v1/vehicle/shortlist.go

@@ -72,7 +72,7 @@ func (sa *ShortlistApi) UpdateShortlist(c *gin.Context) {
 }
 
 func (sa *ShortlistApi) DeleteShortlist(c *gin.Context) {
-	id, err := strconv.Atoi(c.Param("id"))
+	id, err := strconv.Atoi(c.Query("id"))
 	if err != nil {
 		response.FailWithMessage("参数错误", c)
 		return

+ 27 - 27
web/src/api/carOwner.js

@@ -1,51 +1,51 @@
 import service from '@/utils/request'
 // 新增车主
 export const addCarOwner = (data) => {
-    return service({
-        url: '/owner/create',
-        method: 'post',
-        data
-    })
+  return service({
+    url: '/owner/create',
+    method: 'post',
+    data
+  })
 }
 
 // 编辑车主
 export const editCarOwner = (data) => {
-    return service({
-        url: '/owner/update',
-        method: 'put',
-        data
-    })
+  return service({
+    url: '/owner/update',
+    method: 'put',
+    data
+  })
 }
 
 // 根据id获取车主信息
 export const carOwnerInfoId = (id) => {
-    return service({
-        url: '/owner/get?id=' + id,
-        method: 'get'
-    })
+  return service({
+    url: '/owner/get?id=' + id,
+    method: 'get'
+  })
 }
 
 // 根据手机号获取车主信息
 export const carOwnerInfoPhone = (phone) => {
-    return service({
-        url: '/owner/get-by-phone?phone=' + phone,
-        method: 'get'
-    })
+  return service({
+    url: '/owner/get-by-phone?phone=' + phone,
+    method: 'get'
+  })
 }
 
 // 获取车主列表
 export const obtainCarOwnerList = (params) => {
-    return service({
-        url: '/owner/list',
-        method: 'get',
-        params
-    })
+  return service({
+    url: '/owner/list',
+    method: 'get',
+    params
+  })
 }
 
 // 删除车主
 export const removeCarOwner = (id) => {
-    return service({
-        url: '/owner/delete?id=' + id,
-        method: 'delete',
-    })
+  return service({
+    url: '/owner/delete?id=' + id,
+    method: 'delete',
+  })
 }

+ 27 - 27
web/src/api/channel.js

@@ -2,51 +2,51 @@ import service from '@/utils/request'
 
 // 创建通道
 export const addChannel = (data) => {
-    return service({
-        url: '/parking/channel/create',
-        method: 'post',
-        data
-    })
+  return service({
+    url: '/parking/channel/create',
+    method: 'post',
+    data
+  })
 }
 
 // 更新通道
 export const editChannel = (data) => {
-    return service({
-        url: '/parking/channel/update',
-        method: 'put',
-        data
-    })
+  return service({
+    url: '/parking/channel/update',
+    method: 'put',
+    data
+  })
 }
 
 // 根据ID获取通道
 export const obtainChannelId = (id) => {
-    return service({
-        url: '/parking/channel/get?id=' + id,
-        method: 'get'
-    })
+  return service({
+    url: '/parking/channel/get?id=' + id,
+    method: 'get'
+  })
 }
 
 // 根据编码获取通道
 export const obtainChannelCode = (code) => {
-    return service({
-        url: '/parking/channel/get-by-code?code=' + code,
-        method: 'get'
-    })
+  return service({
+    url: '/parking/channel/get-by-code?code=' + code,
+    method: 'get'
+  })
 }
 
 // 获取通道列表
 export const obtainChannelList = (params) => {
-    return service({
-        url: '/parking/channel/list',
-        method: 'get',
-        params
-    })
+  return service({
+    url: '/parking/channel/list',
+    method: 'get',
+    params
+  })
 }
 
 // 删除通道
 export const deleteChannel = (id) => {
-    return service({
-        url: '/parking/channel/delete?id=' + id,
-        method: 'delete'
-    })
+  return service({
+    url: '/parking/channel/delete?id=' + id,
+    method: 'delete'
+  })
 }

+ 190 - 6
web/src/lang/en.js

@@ -2,10 +2,194 @@ export default {
   park: 'Parking Area',
   booth: 'Guard Booth',
   access: 'Passage',
-  device: 'Equipment',
-  modify: 'edit',
-  remove: 'delete',
-  new: 'add',
-  reload: 'refresh',
-  coding: 'code'
+  device: 'Device',
+  modify: 'Edit',
+  remove: 'Delete',
+  new: 'Add',
+  reload: 'Refresh',
+  coding: 'Code',
+  Name: 'Name',
+  IpAddress: 'IP Address',
+  Remarks: 'Remarks',
+  Action: 'Operation',
+  Direction: 'In/Out Direction',
+  Allow: 'Allow temporary vehicles entry and exit',
+  Type: 'Category',
+  Port: 'Port',
+  Enable: 'Enable',
+  Connect: 'Connect',
+  ConnectSuccess: 'Connect Success',
+  GuardAdd: 'Add Guard Booth',
+  GuardEdit: 'Edit Guard Booth',
+  BoothCode: 'Booth Code',
+  BoothName: 'Booth Name',
+  Passage_Booth: 'Passage Booth',
+  Passage_Code: 'Channel Code',
+  Passage_Name: 'Channel Name',
+  Entry_Exit: 'Entry Exit Direction',
+  advance: 'advance',
+  out: 'out',
+  yes: 'yes',
+  no: 'no',
+  Cancel: 'Cancel',
+  Confirm: 'Confirm',
+  Device_Channel: 'Device Channel',
+  Device_Name: 'Device Name',
+  Device_Code: 'Device Code',
+  Connection_Mode: 'Connection Mode',
+  Area_Code: 'Area Code',
+  Surname: 'Surname',
+  Mobile_Phone: 'Mobile Phone',
+  Email: 'Email',
+  Expire_Time: 'Expire Time',
+  roster: 'Black & White List',
+  Search: 'Search',
+  LicensePlateNo: 'License Plate No',
+  RFID_Tag: 'RFID Tag',
+  List_Type: 'List Type',
+  Reset: 'Reset',
+  WhiteList: 'White List',
+  BlackList: 'Black List',
+  SelectVehicle: 'Select Vehicle',
+  CarOwner: 'Car Owner',
+  AddCarOwner: 'Add Car Owner',
+  ElectronicTag: 'Electronic Tag',
+  VehicleType: 'Vehicle Type',
+  VehicleBrand: 'Vehicle Brand',
+  VehicleColor: 'Vehicle Color',
+  ManageVehicleType: 'Manage Vehicle Type',
+  AddNewType: 'Add New Type',
+  BindOwner: 'Bind Owner',
+  InitialFee: 'Initial Fee',
+  UnitFee: 'Unit Fee',
+  IsVipFree: 'VIP Free',
+  DailyMaxFee: 'Daily Max Fee',
+  VipDiscount: 'VIP Discount',
+  FreeDuration: 'Free Duration (Min)',
+  StartFee: 'Start Fee',
+  UnitTime: 'Unit Time (Min)',
+  AddChargeConfig: 'Add Charge Config',
+  EditChargeConfig: 'Edit Charge Config',
+  EntryTime: 'Entry Time',
+  ExitTime: 'Exit Time',
+  StayDuration: 'Stay Duration',
+  Fee: 'Fee',
+  PayStatus: 'Payment Status',
+  ExitBooth: 'Exit Booth',
+  ExitPassage: 'Exit Passage',
+  ParkManage: 'Parking Lot Manage',
+  ParkInfoManage: 'Parking Info Manage',
+  OwnerManage: 'Owner Manage',
+  BlackWhiteList: 'Black White List',
+  VehicleInfo: 'Vehicle Info',
+  ChargeConfig: 'Charge Config',
+  ReportInfoQuery: 'Report Info Query',
+  InOutRecord: 'In Out Record',
+  AbnormalReport: 'Abnormal Report',
+  StatisticsQuery: 'Statistics Query',
+  OnlineVehicleStats: 'Online Vehicle Statistics',
+  deleteBoothTip: 'Are you sure you want to delete this booth?',
+  deletePassageTip: 'Are you sure you want to delete this access?',
+  deleteDeviceTip: 'Are you sure you want to delete this device?',
+  delOwnerTip: 'Are you sure to delete this car owner information?',
+  tip: 'Prompt',
+  deleteSuccess: 'Deleted successfully',
+  deleteFailed: 'Deletion failed',
+  cancelDelete: 'Delete canceled',
+  editSuccess: 'Edit successfully',
+  editFailed: 'Edit failed',
+  isVip: 'Become VIP',
+  noVip: 'Not VIP',
+  carPlateInput: 'Please enter license plate number',
+  carTypeSelect: 'Please select vehicle type',
+  ownerSelect: 'Please select owner',
+  manageCarType: 'Manage Vehicle Types',
+  typeName: 'Type Name',
+  confirmDeleteCar: 'Are you sure you want to delete this vehicle?',
+  rfidLabel: 'RFID Tag (For UHF)',
+  placeholderPorsche: 'e.g. Porsche',
+  placeholderBlack: 'e.g. Black',
+  tempCarOptional: 'Optional for temporary vehicles',
+  parkTip: 'e.g. Monthly Rental Car',
+  licensePlate: 'License Plate',
+  view: 'View',
+  vehicleNumber: 'Vehicle Identification Number',
+  ownerName: 'Owner Name',
+  blackWhiteList: 'Blacklist & Whitelist Management',
+  expireTime: 'Expiration Time',
+  pleaseSelectVehicle: 'Please select a vehicle',
+  permanentValidity: 'No selection means permanent valid',
+  saveFail: 'Save failed',
+  addSuccess: 'Added successfully',
+  confirmDelete: 'Confirm delete?',
+  parking: 'ParkingManage', // 车场管理
+  parkingInfo: 'ParkingInfoManage', // 车场信息管理
+  carOwner: 'OwnerManage', // 车主管理
+  carInfo: 'VehicleInfo', // 车辆信息
+  pricing: 'FeeConfig', // 收费配置
+  report: 'ReportQuery', // 报表查询
+  enter: 'AccessRecord', // 进出记录
+  sheet: 'ExceptionReport', // 异常报表
+  statistics: 'StatQuery', // 统计查询
+  vehicle: 'VehicleStat', // 场内车辆统计
+  dashboard: 'Dashboard', // 数据看板
+  superAdmin: 'SuperAdmin', // 超级管理员
+  authority: 'RoleManage', // 角色管理
+  menu: 'MenuManage', // 菜单管理
+  api: 'APIManage', // 接口管理
+  user: 'UserManage', // 用户管理
+  dictionary: 'DictManage', // 字典管理
+  operation: 'OperHistory', // 操作日志
+  person: 'PersonalInformation',
+  areaName: 'Area Name',
+  areaCapacity: 'Area Capacity',
+  createArea: 'Create Area',
+  editArea: 'Edit Area',
+  addPassage: 'Add Passage',
+  editPassage: 'Edit Passage',
+  addDevice: 'Add Device',
+  editDevice: 'Edit Device',
+  smartBarrier: 'SmartBarrier',
+  language: 'Language',
+  currRole: 'CurrentRole',
+  menuCmd: 'MenuCommand',
+  personalInfo: 'PersonalInfo',
+  logout: 'Logout',
+  barrierSystem: 'Smart Barrier System',
+  placeholderUser: 'Please enter username',
+  placeholderPwd: 'Please enter password',
+  placeholderCode: 'Please enter verification code',
+  login: 'Login',
+  selectParkArea: 'Please select parking area',
+  pleaseSelect: 'Please select',
+  serialName: 'Serial Port Name',
+  baudRate: 'Baud Rate',
+  inputPhone: 'Please enter phone number',
+  inputOwnerName: 'Please enter owner name',
+  editOwner: 'Edit Owner',
+  selectPavilion: 'Please select booth',
+  fillCompleteInfo: 'Please fill in all info except remarks',
+  allow: 'Allow',
+  disallow: 'Disallow',
+  enable: 'Enable',
+  disable: 'Disable',
+  currentDate: 'Current Date',
+  addFail: 'Add Failed',
+  vipFree: 'VIP Free',
+  vipNotFree: 'VIP Not Free',
+  noLabel: 'No Label',
+  permanentValid: 'Permanent Valid',
+  addCar: 'Add Vehicle',
+  editCar: 'Edit Vehicle',
+  unknown: 'Unknown',
+  tempCar: 'Temporary Vehicle',
+  getListFail: 'Failed to get list',
+  inputTypeName: 'Please enter type name',
+  notOut: 'Not Exit',
+  unpaid: 'Unpaid',
+  paid: 'Paid',
+  minute: 'Minute',
+  entryImg: 'Entry Image',
+  exitImg: 'Exit Image',
+  recordDetail: 'Access Record Details'
 }

+ 28 - 12
web/src/lang/index.js

@@ -1,17 +1,33 @@
-import { createI18n } from 'vue-i18n'
-import zh from './zh-CN'
+import { reactive, computed } from 'vue'
+import zhCN from './zh-CN'
+import zhHK from './zh-HK'
+import zhTW from './zh-TW'
 import en from './en'
 
-// 从本地缓存获取语言,默认中文
-const savedLang = localStorage.getItem('lang') || 'zh'
+// 语言包
+const messages = {
+  'zh-CN': zhCN,
+  'zh-HK': zhHK,
+  'zh-TW': zhTW,
+  'en': en
+}
 
-const i18n = createI18n({
-  legacy: false, // Vue3 组合式API必须关闭
-  locale: savedLang, // 当前语言
-  messages: {
-    zh,
-    en
-  }
+// 当前语言(持久化到本地)
+const locale = reactive({
+  lang: localStorage.getItem('lang') || 'zh-CN'
 })
 
-export default i18n
+// 切换语言
+const setLang = (lang) => {
+  locale.lang = lang
+  localStorage.setItem('lang', lang)
+}
+
+// 当前使用的翻译文本
+const t = computed(() => messages[locale.lang])
+
+export {
+  locale,
+  t,
+  setLang
+}

+ 184 - 31
web/src/lang/zh-CN.js

@@ -8,35 +8,188 @@ export default {
   new: '新增',
   reload: '刷新',
   coding: '编码',
-  Name: '名称', // 名稱 名稱 name
-  IpAddress: 'ip地址', // ip地址 ip地址 ipAddress
-  Remarks: '备注', // 備註 備註 remark
-  Action: '操作', // 操作 備註 action
-  Direction: '进出方向', // 進出方向 進出方向 InOutDirection
-  Allow: '是否允许临时车进出', // 是否容許臨時車輛進出 是否容許臨時車輛進出 Allow temporary vehicles entry and exit
-  Type: '类别', // 類別 類別 Category
-  Port: '端口', // 埠口 連接埠 port
-  Enable: '是否启用', // 是否啟用 是否啟用 Enable or not
-  Connect: '连接', // 連接 連線 Connect
-  GuardAdd: '岗亭新增', // 崗亭新增 崗亭新增 Add Guard booth,
-  GuardEdit: '岗亭编辑', // 編輯崗亭 編輯崗亭 Edit Guard Booth
-  BoothCode: '岗亭编码', // 崗亭編碼 崗亭編碼 Booth Code
-  BoothName: '岗亭名称', // 崗亭名稱 崗亭名稱 Guard Booth Name
-  ip_address: 'ip地址', // IP 位址 IP 位址 IP Address
-  Passage_Booth: '通道岗亭', // 通道崗亭 通道崗亭 Passage Guard Booth
-  Passage_Code: '通道编码', // 通道編碼 通道編碼 Channel Code
-  Passage_Name: '通道名称', // 通道名稱 通道名稱 Channel Name
-  Entry_Exit: '进出方向', // 進出方向 進出方向 Entry Exit Direction
-  Cancel: '取消', // 取消 取消 Cancel
-  Confirm: '确认', // 確認 確認 Confirm
-  Device_Channel: '设备通道', // 裝置通道 裝置通道 Device Channel
-  Device_Name: '设备名称', // 裝置名稱 裝置名稱 Device Name
-  Device_Code: '设备编码', // 裝置編碼 裝置編號 Device Code
-  Connection_Mode: '连接方式', // 連接方式 連線方式 Connection Mode
-  Area_Code: '区域编码', // 區域編碼 區域代碼 Area Code
-  Surname: '姓氏', // 姓氏 姓氏 Surname
-  Mobile_Phone: '手机', // 手提電話 行動電話
-  Email: '邮箱', // 電郵 電子信箱 email
-  Expire_Time: '过期时间', // 過期時間 到期時間 Expire Time
-  Black_White: '黑白名单', // 黑白名單 黑白名單 Black and White List
+  Name: '名称',
+  IpAddress: 'ip地址',
+  Remarks: '备注',
+  Action: '操作',
+  Direction: '进出方向',
+  advance: '进',
+  out: '出',
+  yes: '是',
+  no: '否',
+  Allow: '是否允许临时车进出',
+  Type: '类别',
+  Port: '端口',
+  Enable: '是否启用',
+  Connect: '连接',
+  ConnectSuccess: '连接成功',
+  GuardAdd: '岗亭新增',
+  GuardEdit: '岗亭编辑',
+  BoothCode: '岗亭编码',
+  BoothName: '岗亭名称',
+  Passage_Booth: '通道岗亭',
+  Passage_Code: '通道编码',
+  Passage_Name: '通道名称',
+  Entry_Exit: '进出方向',
+  Cancel: '取消',
+  Confirm: '确认',
+  Device_Channel: '设备通道',
+  Device_Name: '设备名称',
+  Device_Code: '设备编码',
+  Connection_Mode: '连接方式',
+  Area_Code: '区域编码',
+  Surname: '姓氏',
+  Mobile_Phone: '手机',
+  Email: '邮箱',
+  Expire_Time: '过期时间',
+  roster: '黑白名单',
+  Search: '搜索',
+  LicensePlateNo: '车牌号码',
+  licensePlate: '车牌',
+  RFID_Tag: 'RFID标签',
+  List_Type: '名单类型',
+  Reset: '重置',
+  WhiteList: '白名单',
+  BlackList: '黑名单',
+  SelectVehicle: '选择车辆',
+  CarOwner: '车主',
+  AddCarOwner: '新增车主',
+  ElectronicTag: '电子标签',
+  VehicleType: '车辆类型',
+  VehicleBrand: '车辆品牌',
+  VehicleColor: '车辆颜色',
+  ManageVehicleType: '管理车辆类型',
+  AddNewType: '新增类型',
+  BindOwner: '绑定车主',
+  InitialFee: '初始费用',
+  UnitFee: '单位费用',
+  IsVipFree: '是否为VIP免费',
+  DailyMaxFee: '每日最大费用',
+  VipDiscount: 'vip折扣',
+  FreeDuration: '免费时长(分钟)',
+  StartFee: '起步费用',
+  UnitTime: '单位时间(分钟)',
+  AddChargeConfig: '新增收费配置',
+  EditChargeConfig: '编辑收费配置',
+  EntryTime: '入场时间',
+  ExitTime: '出场时间',
+  StayDuration: '停留时长',
+  Fee: '费用',
+  PayStatus: '支付状态',
+  ExitBooth: '出场岗亭',
+  ExitPassage: '出场通道',
+  ParkManage: '停车场管理',
+  ParkInfoManage: '停车信息管理',
+  OwnerManage: '车主管理',
+  BlackWhiteList: '黑白名单',
+  VehicleInfo: '车辆信息',
+  ChargeConfig: '收费配置',
+  ReportInfoQuery: '报表信息查询',
+  InOutRecord: '进出记录',
+  AbnormalReport: '异常报表',
+  StatisticsQuery: '统计信息查询',
+  OnlineVehicleStats: '在线车辆统计',
+  deleteBoothTip: '确定要删除该岗亭吗?',
+  deletePassageTip: '确定删除该通道吗?',
+  deleteDeviceTip: '确定要删除该设备吗?',
+  delOwnerTip: '确定要删除该车主信息吗',
+  tip: '提示',
+  deleteSuccess: '删除成功',
+  deleteFailed: '删除失败',
+  cancelDelete: '取消删除',
+  editSuccess: '编辑成功',
+  editFailed: '编辑失败',
+  isVip: '已成为VIP',
+  noVip: '未成为VIP',
+  carPlateInput: '请输入车牌号',
+  carTypeSelect: '请选择车辆类型',
+  ownerSelect: '请选择车主',
+  manageCarType: '管理车辆类型',
+  typeName: '类型名称',
+  confirmDeleteCar: '确定删除该车辆吗',
+  rfidLabel: 'RFID标签(UHF用)',
+  placeholderPorsche: '如:保时捷',
+  placeholderBlack: '如:黑色',
+  tempCarOptional: '临时车可不选',
+  parkTip: '如:月租车',
+  view: '查看',
+  vehicleNumber: '车辆识别号码',
+  ownerName: '车主名称',
+  blackWhiteList: '黑白名单管理',
+  expireTime: '到期时间',
+  pleaseSelectVehicle: '请选择车辆',
+  permanentValidity: '不选则永久有效',
+  saveFail: '保存失败',
+  addSuccess: '新增成功',
+  confirmDelete: '确定删除?',
+  parking: '停车场管理',
+  parkingInfo: '停车信息管理',
+  carOwner: '车主管理',
+  carInfo: '车辆信息',
+  pricing: '收费配置',
+  report: '报表信息查询',
+  enter: '进出记录',
+  sheet: '异常报表',
+  statistics: '统计信息查询',
+  vehicle: '在场车辆统计',
+  dashboard: '仪表盘',
+  superAdmin: '超级管理员',
+  authority: '角色管理',
+  menu: '菜单管理',
+  api: 'API管理',
+  user: '用户管理',
+  dictionary: '字典管理',
+  operation: '操作历史',
+  person: '个人信息',
+  areaName: '区域名称',
+  areaCapacity: '区域容量',
+  createArea: '创建区域',
+  editArea: '编辑区域',
+  addPassage: '通道新增',
+  editPassage: '通道编辑',
+  addDevice: '新增设备',
+  editDevice: '编辑设备',
+  smartBarrier: '智慧道闸',
+  language: '语言',
+  currRole: '当前角色',
+  menuCmd: '菜单指令',
+  personalInfo: '个人信息',
+  logout: '登出',
+  barrierSystem: '智慧道闸系统',
+  placeholderUser: '请输入用户名',
+  placeholderPwd: '请输入密码',
+  placeholderCode: '请输入验证码',
+  login: '登录',
+  selectParkArea: '请选择停车区域',
+  pleaseSelect: '请选择',
+  serialName: '串口名称',
+  baudRate: '串口波特率',
+  inputPhone: '请输入手机号',
+  inputOwnerName: '请输入车主名称',
+  editOwner: '编辑车主',
+  selectPavilion: '请选择岗亭',
+  fillCompleteInfo: '请将除备注以外的信息填写完整',
+  allow: '允许',
+  disallow: '不允许',
+  enable: '启用',
+  disable: '不启用',
+  currentDate: '当前日期',
+  addFail: '新增失败',
+  vipFree: 'VIP免费',
+  vipNotFree: 'VIP不免费',
+  noLabel: '无标签',
+  permanentValid: '永久有效',
+  addCar: '新增车辆',
+  editCar: '编辑车辆',
+  unknown: '未知',
+  tempCar: '临时车辆',
+  getListFail: '获取列表失败',
+  inputTypeName: '请输入类型名称',
+  notOut: '未出场',
+  unpaid: '未支付',
+  paid: '已支付',
+  minute: '分钟',
+  entryImg: '入场图片',
+  exitImg: '出场图片',
+  recordDetail: '进出记录详情'
 }

+ 186 - 2
web/src/lang/zh-HK.js

@@ -6,6 +6,190 @@ export default {
   modify: '編輯',
   remove: '刪除',
   new: '新增',
-  reload: '刷新',
-  coding: '編碼'
+  reload: '重新整理',
+  coding: '編碼',
+  Name: '名稱',
+  IpAddress: 'IP位址',
+  Remarks: '備註',
+  Action: '操作',
+  Direction: '進出方向',
+  advance: '進',
+  out: '出',
+  yes: '是',
+  no: '否',
+  Allow: '是否容許臨時車輛進出',
+  Type: '類別',
+  Port: '埠口',
+  Enable: '是否啟用',
+  Connect: '連接',
+  ConnectSuccess: '連接成功',
+  GuardAdd: '崗亭新增',
+  GuardEdit: '編輯崗亭',
+  BoothCode: '崗亭編碼',
+  BoothName: '崗亭名稱',
+  Passage_Booth: '通道崗亭',
+  Passage_Code: '通道編碼',
+  Passage_Name: '通道名稱',
+  Entry_Exit: '進出方向',
+  Cancel: '取消',
+  Confirm: '確認',
+  Device_Channel: '裝置通道',
+  Device_Name: '裝置名稱',
+  Device_Code: '裝置編碼',
+  Connection_Mode: '連接方式',
+  Area_Code: '區域編碼',
+  Surname: '姓氏',
+  Mobile_Phone: '手提電話',
+  Email: '電郵',
+  Expire_Time: '過期時間',
+  roster: '黑白名單',
+  Search: '搜尋',
+  LicensePlateNo: '車牌號碼',
+  RFID_Tag: 'RFID標籤',
+  List_Type: '名單類型',
+  Reset: '重設',
+  WhiteList: '白名單',
+  BlackList: '黑名單',
+  SelectVehicle: '選擇車輛',
+  CarOwner: '車主',
+  AddCarOwner: '新增車主',
+  ElectronicTag: '電子標籤',
+  VehicleType: '車輛類型',
+  VehicleBrand: '車輛品牌',
+  VehicleColor: '車輛顏色',
+  ManageVehicleType: '管理車輛類型',
+  AddNewType: '新增類型',
+  BindOwner: '綁定車主',
+  InitialFee: '初始費用',
+  UnitFee: '單位費用',
+  IsVipFree: '是否為VIP免費',
+  DailyMaxFee: '每日最大費用',
+  VipDiscount: 'VIP折扣',
+  FreeDuration: '免費時長(分鐘)',
+  StartFee: '起步費用',
+  UnitTime: '單位時間(分鐘)',
+  AddChargeConfig: '新增收費配置',
+  EditChargeConfig: '編輯收費配置',
+  EntryTime: '入場時間',
+  ExitTime: '出場時間',
+  StayDuration: '停留時長',
+  Fee: '費用',
+  PayStatus: '支付狀態',
+  ExitBooth: '出場崗亭',
+  ExitPassage: '出場通道',
+  ParkManage: '停車場管理',
+  ParkInfoManage: '停車資訊管理',
+  OwnerManage: '車主管理',
+  BlackWhiteList: '黑白名單',
+  VehicleInfo: '車輛資訊',
+  ChargeConfig: '收費配置',
+  ReportInfoQuery: '報表資訊查詢',
+  InOutRecord: '進出紀錄',
+  AbnormalReport: '異常報表',
+  StatisticsQuery: '統計資訊查詢',
+  OnlineVehicleStats: '線上車輛統計',
+  deleteBoothTip: '確定要刪除此崗亭嗎?',
+  deletePassageTip: '確定刪除此通道嗎?',
+  deleteDeviceTip: '確定要刪除此設備嗎?',
+  delOwnerTip: '確定要刪除該車主資訊嗎',
+  tip: '提示',
+  deleteSuccess: '刪除成功',
+  deleteFailed: '刪除失敗',
+  cancelDelete: '取消刪除',
+  editSuccess: '編輯成功',
+  editFailed: '编辑失敗',
+  isVip: '已成為VIP',
+  noVip: '未成為VIP',
+  carPlateInput: '請輸入車牌號碼',
+  carTypeSelect: '請選擇車輛類型',
+  ownerSelect: '請選擇車主',
+  manageCarType: '管理車輛類型',
+  typeName: '類型名稱',
+  confirmDeleteCar: '確定刪除該車輛嗎',
+  rfidLabel: 'RFID標籤(UHF用)',
+  placeholderPorsche: '如:保時捷',
+  placeholderBlack: '如:黑色',
+  tempCarOptional: '臨時車可唔選擇',
+  parkTip: '如:月租車',
+  licensePlate: '車牌',
+  view: '查看',
+  vehicleNumber: '車輛識別號碼',
+  ownerName: '車主名稱',
+  blackWhiteList: '黑白名單管理',
+  expireTime: '到期時間',
+  pleaseSelectVehicle: '請選擇車輛',
+  permanentValidity: '唔揀就永久有效',
+  saveFail: '儲存失敗',
+  addSuccess: '新增成功',
+  confirmDelete: '確定刪除?',
+  parking: '停車場管理',
+  parkingInfo: '停車資訊管理',
+  carOwner: '車主管理',
+  carInfo: '車輛資訊',
+  pricing: '收費設定',
+  report: '報表資訊查詢',
+  enter: '出入記錄',
+  sheet: '異常報表',
+  statistics: '統計資訊查詢',
+  vehicle: '在場車輛統計',
+  dashboard: '儀表板',
+  superAdmin: '超級管理員',
+  authority: '角色管理',
+  menu: '選單管理',
+  api: 'API管理',
+  user: '用戶管理',
+  dictionary: '字典管理',
+  operation: '操作記錄',
+  person: '個人資訊',
+  areaName: '區域名稱',
+  areaCapacity: '區域容量',
+  createArea: '建立區域',
+  editArea: '編輯區域',
+  addPassage: '通道新增',
+  editPassage: '通道編輯',
+  addDevice: '新增設備',
+  editDevice: '編輯設備',
+  smartBarrier: '智慧閘機',
+  language: '語言',
+  currRole: '當前角色',
+  menuCmd: '選單指令',
+  personalInfo: '個人資訊',
+  logout: '登出',
+  barrierSystem: '智慧閘機系統',
+  placeholderUser: '請輸入用戶名',
+  placeholderPwd: '請輸入密碼',
+  placeholderCode: '請輸入驗證碼',
+  login: '登入',
+  selectParkArea: '請選擇停車區域',
+  pleaseSelect: '請選擇',
+  serialName: '串口名稱',
+  baudRate: '串口波特率',
+  inputPhone: '請輸入手機號',
+  inputOwnerName: '請輸入車主名稱',
+  editOwner: '編輯車主',
+  selectPavilion: '請選擇崗亭',
+  fillCompleteInfo: '請填妥備註以外所有資料',
+  allow: '允許',
+  disallow: '不允許',
+  enable: '啟用',
+  disable: '不啟用',
+  currentDate: '當前日期',
+  addFail: '新增失敗',
+  vipFree: 'VIP免費',
+  vipNotFree: 'VIP不免費',
+  noLabel: '無標籤',
+  permanentValid: '永久有效',
+  addCar: '新增車輛',
+  editCar: '編輯車輛',
+  unknown: '未知',
+  tempCar: '臨時車輛',
+  getListFail: '獲取列表失敗',
+  inputTypeName: '請輸入類型名稱',
+  notOut: '未出場',
+  unpaid: '未支付',
+  paid: '已支付',
+  minute: '分鐘',
+  entryImg: '入場圖片',
+  exitImg: '出場圖片',
+  recordDetail: '進出記錄詳情'
 }

+ 187 - 3
web/src/lang/zh-TW.js

@@ -2,10 +2,194 @@ export default {
   park: '停車區域',
   booth: '崗亭',
   access: '通道',
-  device: '設備',
+  device: '裝置',
   modify: '編輯',
-  remove: '除',
+  remove: '除',
   new: '新增',
-  reload: '刷新',
+  reload: '重新整理',
   coding: '編碼',
+  Name: '名稱',
+  IpAddress: 'IP位址',
+  Remarks: '備註',
+  Action: '操作',
+  Direction: '進出方向',
+  Allow: '是否允許臨時車輛進出',
+  Type: '類別',
+  Port: '連接埠',
+  Enable: '是否啟用',
+  Connect: '連線',
+  ConnectSuccess: '連線成功',
+  GuardAdd: '崗亭新增',
+  GuardEdit: '編輯崗亭',
+  BoothCode: '崗亭編號',
+  BoothName: '崗亭名稱',
+  Passage_Booth: '通道崗亭',
+  Passage_Code: '通道代碼',
+  Passage_Name: '通道名稱',
+  Entry_Exit: '進出方向',
+  advance: '進',
+  out: '出',
+  yes: '是',
+  no: '否',
+  Cancel: '取消',
+  Confirm: '確認',
+  Device_Channel: '裝置通道',
+  Device_Name: '裝置名稱',
+  Device_Code: '裝置編號',
+  Connection_Mode: '連線方式',
+  Area_Code: '區域代碼',
+  Surname: '姓氏',
+  Mobile_Phone: '行動電話',
+  Email: '電子信箱',
+  Expire_Time: '到期時間',
+  Black_White: '黑白名單',
+  Search: '搜尋',
+  LicensePlateNo: '車牌號碼',
+  RFID_Tag: 'RFID標籤',
+  List_Type: '名單類型',
+  Reset: '重設',
+  WhiteList: '白名單',
+  BlackList: '黑名單',
+  SelectVehicle: '選擇車輛',
+  CarOwner: '車主',
+  AddCarOwner: '新增車主',
+  ElectronicTag: '電子標籤',
+  VehicleType: '車輛類型',
+  VehicleBrand: '車輛品牌',
+  VehicleColor: '車輛顏色',
+  ManageVehicleType: '管理車輛類型',
+  AddNewType: '新增類型',
+  BindOwner: '綁定車主',
+  InitialFee: '初始費用',
+  UnitFee: '單位費用',
+  IsVipFree: '是否為VIP免費',
+  DailyMaxFee: '每日最大費用',
+  VipDiscount: 'VIP折扣',
+  FreeDuration: '免費時長(分鐘)',
+  StartFee: '起步費用',
+  UnitTime: '單位時間(分鐘)',
+  AddChargeConfig: '新增收費設定',
+  EditChargeConfig: '編輯收費設定',
+  EntryTime: '入場時間',
+  ExitTime: '出場時間',
+  StayDuration: '停留時長',
+  Fee: '費用',
+  PayStatus: '付款狀態',
+  ExitBooth: '出場崗亭',
+  ExitPassage: '出場通道',
+  ParkManage: '停車場管理',
+  ParkInfoManage: '停車資訊管理',
+  OwnerManage: '車主管理',
+  roster: '黑白名單',
+  VehicleInfo: '車輛資訊',
+  ChargeConfig: '收費設定',
+  ReportInfoQuery: '報表資訊查詢',
+  InOutRecord: '進出紀錄',
+  AbnormalReport: '異常報表',
+  StatisticsQuery: '統計資訊查詢',
+  OnlineVehicleStats: '線上車輛統計',
+  deleteBoothTip: '確定要刪除此崗亭嗎?',
+  deletePassageTip: '確定刪除此通道嗎?',
+  deleteDeviceTip: '確定要刪除此設備嗎?',
+  delOwnerTip: '確定要刪除該車主資訊嗎',
+  tip: '提示',
+  deleteSuccess: '刪除成功',
+  deleteFailed: '刪除失敗',
+  cancelDelete: '取消刪除',
+  editSuccess: '編輯成功',
+  editFailed: '編輯失敗',
+  isVip: '已成為VIP',
+  noVip: '未成為VIP',
+  carPlateInput: '請輸入車牌號碼',
+  carTypeSelect: '請選擇車輛類別',
+  ownerSelect: '請選擇車主',
+  manageCarType: '管理車輛類別',
+  typeName: '類別名稱',
+  confirmDeleteCar: '確定刪除該車輛嗎',
+  rfidLabel: 'RFID標籤(UHF用)',
+  placeholderPorsche: '如:保時捷',
+  placeholderBlack: '如:黑色',
+  tempCarOptional: '臨時車可不選',
+  parkTip: '如:月租車',
+  licensePlate: '車牌',
+  view: '檢視',
+  vehicleNumber: '車輛識別號碼',
+  ownerName: '車主名稱',
+  blackWhiteList: '黑白名單管理',
+  expireTime: '到期時間',
+  pleaseSelectVehicle: '請選擇車輛',
+  permanentValidity: '未選取則永久有效',
+  saveFail: '儲存失敗',
+  addSuccess: '新增成功',
+  confirmDelete: '確定刪除?',
+  parking: '停車場管理',
+  parkingInfo: '停車資訊管理',
+  carOwner: '車主管理',
+  carInfo: '車輛資訊',
+  pricing: '收費設定',
+  report: '報表查詢',
+  enter: '進出紀錄',
+  sheet: '異常報表',
+  statistics: '統計查詢',
+  vehicle: '場內車輛統計',
+  dashboard: '儀表板',
+  superAdmin: '超級管理員',
+  authority: '角色管理',
+  menu: '選單管理',
+  api: 'API管理',
+  user: '使用者管理',
+  dictionary: '字典管理',
+  operation: '操作紀錄',
+  person: '個人資訊',
+  areaName: '區域名稱',
+  areaCapacity: '區域容量',
+  createArea: '建立區域',
+  editArea: '編輯區域',
+  addPassage: '通道新增',
+  editPassage: '通道編輯',
+  addDevice: '新增設備',
+  editDevice: '編輯設備',
+  smartBarrier: '智慧閘門',
+  language: '語言',
+  currRole: '目前角色',
+  menuCmd: '選單指令',
+  personalInfo: '個人資訊',
+  logout: '登出',
+  barrierSystem: '智慧閘門系統',
+  placeholderUser: '請輸入使用者名稱',
+  placeholderPwd: '請輸入密碼',
+  placeholderCode: '請輸入驗證碼',
+  login: '登入',
+  selectParkArea: '請選擇停車區域',
+  pleaseSelect: '請選擇',
+  serialName: '串列埠名稱',
+  baudRate: '串列埠鮑率',
+  inputPhone: '請輸入手機號',
+  inputOwnerName: '請輸入車主名稱',
+  editOwner: '編輯車主',
+  selectPavilion: '請選擇崗亭',
+  fillCompleteInfo: '請填寫備註以外之完整資訊',
+  allow: '允許',
+  disallow: '不允許',
+  enable: '啟用',
+  disable: '不啟用',
+  currentDate: '目前日期',
+  addFail: '新增失敗',
+  vipFree: 'VIP免費',
+  vipNotFree: 'VIP不免費',
+  noLabel: '無標籤',
+  permanentValid: '永久有效',
+  addCar: '新增車輛',
+  editCar: '編輯車輛',
+  unknown: '未知',
+  tempCar: '臨時車輛',
+  getListFail: '獲取列表失敗',
+  inputTypeName: '請輸入類型名稱',
+  notOut: '未出場',
+  unpaid: '未付款',
+  paid: '已付款',
+  minute: '分鐘',
+  entryImg: '入場圖片',
+  exitImg: '出場圖片',
+  recordDetail: '進出記錄詳情'
 }

+ 5 - 3
web/src/main.js

@@ -14,7 +14,7 @@ import auth from '@/directive/auth'
 import { store } from '@/pinia'
 import App from './App.vue'
 import { initDom } from './utils/positionToCode'
-import i18n from './lang'
+import { t, setLang, locale } from './lang'
 // import en from 'element-plus/es/locale/lang/en'
 initDom()
 /**
@@ -32,12 +32,14 @@ Nprogress.start()
 
 const app = createApp(App)
 app.config.productionTip = false
-
+app.config.globalProperties.$t = t
+app.config.globalProperties.$setLang = setLang
+app.config.globalProperties.$locale = locale
 app
   .use(run)
   .use(store)
   .use(auth)
-  .use(router).use(i18n)
+  .use(router)
   .mount('#app')
 
 export default app

+ 6 - 1
web/src/utils/fmtRouterTitle.js

@@ -1,3 +1,5 @@
+import {t} from "@/lang";
+
 export const fmtTitle = (title, now) => {
   const reg = /\$\{(.+?)\}/
   const reg_g = /\$\{(.+?)\}/g
@@ -9,5 +11,8 @@ export const fmtTitle = (title, now) => {
       title = title.replace(item, value)
     })
   }
-  return title
+  console.log('面包屑', title, now)
+  if (!title) return ''
+  // 从语言包找,找不到就返回原来的中文(不报错、不空白)
+  return t.value[title] || title
 }

+ 9 - 3
web/src/view/layout/aside/asideComponent/asyncSubmenu.vue

@@ -12,13 +12,13 @@
         <el-icon v-if="routerInfo.meta.icon">
           <component :is="routerInfo.meta.icon" />
         </el-icon>
-        <span>{{ routerInfo.meta.title }}</span>
+        <span>{{ getText(routerInfo.name) }}</span>
       </div>
       <template v-else>
         <el-icon v-if="routerInfo.meta.icon">
           <component :is="routerInfo.meta.icon" />
         </el-icon>
-        <span>{{ routerInfo.meta.title }}</span>
+        <span>{{ getText(routerInfo.name) }}</span>
       </template>
     </template>
     <slot />
@@ -27,7 +27,7 @@
 
 <script setup>
 import { ref, watch } from 'vue'
-
+import { t } from '@/lang/index.js'
 defineOptions({
   name: 'AsyncSubmenu',
 })
@@ -67,6 +67,12 @@ watch(() => props.theme, () => {
   // hoverText.value = props.theme.hoverText
 })
 
+const getText = (title) => {
+  if (!title) return ''
+  // 从语言包找,找不到就返回原来的中文(不报错、不空白)
+  return t.value[title] || title
+}
+
 </script>
 
 <style lang="scss" scoped>

+ 5 - 0
web/src/view/layout/aside/asideComponent/index.vue

@@ -54,5 +54,10 @@ const menuComponent = computed(() => {
   }
 })
 
+// onMounted(() => {
+//   setTimeout(function() {
+//     console.log('数据', props.routerInfo)
+//   }, 2000)
+// })
 </script>
 

+ 9 - 2
web/src/view/layout/aside/asideComponent/menuItem.vue

@@ -4,7 +4,7 @@
       <el-tooltip
         class="box-item"
         effect="light"
-        :content="routerInfo.meta.title"
+        :content="getText(routerInfo.name)"
         placement="right"
       >
         <el-icon v-if="routerInfo.meta.icon">
@@ -17,7 +17,7 @@
         <el-icon v-if="routerInfo.meta.icon">
           <component :is="routerInfo.meta.icon" />
         </el-icon>
-        <span class="gva-menu-item-title">{{ routerInfo.meta.title }}</span>
+        <span class="gva-menu-item-title">{{ getText(routerInfo.name) }}</span>
       </div>
     </template>
   </el-menu-item>
@@ -25,6 +25,7 @@
 
 <script setup>
 import { ref, watch } from 'vue'
+import { t } from '@/lang/index.js'
 
 defineOptions({
   name: 'MenuItem',
@@ -65,6 +66,12 @@ watch(() => props.theme, () => {
   hoverText.value = props.theme.hoverText
 })
 
+const getText = (title) => {
+  if (!title) return ''
+  // 从语言包找,找不到就返回原来的中文(不报错、不空白)
+  return t.value[title] || title
+}
+
 </script>
 
 <style lang="scss" scoped>

+ 9 - 3
web/src/view/layout/aside/historyComponent/history.vue

@@ -29,11 +29,11 @@
                  activeValue === getFmtString(item) ? userStore.activeColor : '#ddd',
              }"
            />
-            {{ fmtTitle(item.meta.title,item) }}</span>
+            {{ getText(item.name) }}</span>
         </template>
       </el-tab-pane>
     </el-tabs>
-
+<!--    {{ fmtTitle(item.meta.title,item) }}-->
     <!--自定义右键菜单html代码-->
     <ul
       v-show="contextMenuVisible"
@@ -53,7 +53,8 @@ import { emitter } from '@/utils/bus.js'
 import { computed, onUnmounted, ref, watch, nextTick } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { useUserStore } from '@/pinia/modules/user'
-import { fmtTitle } from '@/utils/fmtRouterTitle'
+// import { fmtTitle } from '@/utils/fmtRouterTitle'
+import { t } from '@/lang/index.js'
 
 defineOptions({
   name: 'HistoryComponent',
@@ -340,6 +341,11 @@ const initPage = () => {
 }
 initPage()
 
+const getText = (title) => {
+  if (!title) return ''
+  // 从语言包找,找不到就返回原来的中文(不报错、不空白)
+  return t.value[title] || title
+}
 onUnmounted(() => {
   emitter.off('collapse')
   emitter.off('mobile')

+ 7 - 6
web/src/view/layout/index.vue

@@ -22,7 +22,7 @@
             v-if="isSider"
             class="inline-flex font-bold text-2xl"
             :style="{color:textColor}"
-          >{{ $GIN_VUE_ADMIN.appName }}</div>
+          >{{ $t.value.smartBarrier }}</div>
         </div>
         <Aside class="aside" />
       </el-aside>
@@ -80,7 +80,7 @@
                         <el-breadcrumb-item
                           v-for="item in matched.slice(1,matched.length)"
                           :key="item.path"
-                        >{{ fmtTitle(item.meta.title,route) }}</el-breadcrumb-item>
+                        >{{ fmtTitle(item.name,route) }}</el-breadcrumb-item>
                       </el-breadcrumb>
                     </el-col>
                     <el-col
@@ -110,7 +110,7 @@
                             <el-dropdown-menu>
                               <el-dropdown-item>
                                 <span class="font-bold">
-                                  当前角色:{{ userStore.userInfo.authority.authorityName }}
+                                  {{ $t.value.currRole }}:{{ userStore.userInfo.authority.authorityName }}
                                 </span>
                               </el-dropdown-item>
                               <template v-if="userStore.userInfo.authorities">
@@ -130,7 +130,7 @@
                                   style="display: flex"
                                   @click="handleCommand"
                                 >
-                                  <div>指令菜单</div>
+                                  <div>{{ $t.value.menuCmd }}</div>
                                   <div style="margin-left: 8px">
                                     <span class="button">{{ first }}</span>
                                     +
@@ -141,11 +141,11 @@
                               <el-dropdown-item
                                 icon="avatar"
                                 @click="toPerson"
-                              >个人信息</el-dropdown-item>
+                              >{{ $t.value.personalInfo }}</el-dropdown-item>
                               <el-dropdown-item
                                 icon="reading-lamp"
                                 @click="userStore.LoginOut"
-                              >登 出</el-dropdown-item>
+                              >{{ $t.value.logout }}</el-dropdown-item>
                             </el-dropdown-menu>
                           </template>
                         </el-dropdown>
@@ -202,6 +202,7 @@ import { useRouter, useRoute } from 'vue-router'
 import { useRouterStore } from '@/pinia/modules/router'
 import { fmtTitle } from '@/utils/fmtRouterTitle'
 import { useUserStore } from '@/pinia/modules/user'
+import { t } from '@/lang/index.js'
 
 defineOptions({
   name: 'Layout',

+ 17 - 12
web/src/view/layout/search/search.vue

@@ -4,10 +4,19 @@
       <el-select
         v-model="languageType"
         @change="changeLanguageType"
+        :placeholder="$t.value.language"
       >
         <el-option
-          label="zh"
-          value="zh"
+          label="zh-CN"
+          value="zh-CN"
+        />
+        <el-option
+          label="zh-HK"
+          value="zh-HK"
+        />
+        <el-option
+          label="zh-TW"
+          value="zh-TW"
         />
         <el-option
           label="en"
@@ -32,23 +41,16 @@
 import Screenfull from '@/view/layout/screenfull/index.vue'
 import { emitter } from '@/utils/bus.js'
 import { ref } from 'vue'
-import { useI18n } from 'vue-i18n'
-import zhCn from 'element-plus/es/locale/lang/zh-cn'
-import en from 'element-plus/es/locale/lang/en'
-
+import { setLang } from '@/lang'
 // 导入 i18n 实例
-const { locale } = useI18n()
-
 defineOptions({
   name: 'BtnBox',
 })
 
-const languageType = ref('zh')
+const languageType = ref(localStorage.getItem('lang'))
 
 const changeLanguageType = (val) => {
-  languageType.value = val
-  localStorage.setItem('lang', val) // 持久化
-
+  setLang(val)
 }
 
 const reload = ref(false)
@@ -63,6 +65,9 @@ const toService = () => {
   window.open('https://support.qq.com/product/371961')
 }
 
+// onMounted(() => {
+//   setLang('zh-CN')
+// })
 </script>
 <style scoped lang="scss">
 .search-component {

+ 5 - 5
web/src/view/login/index.vue

@@ -20,7 +20,7 @@
               >
             </div>
             <div class="mb-9">
-              <p class="text-center text-4xl font-bold">智慧道闸系统</p>
+              <p class="text-center text-4xl font-bold">{{ $t.value.barrierSystem }}</p>
             </div>
             <el-form
               ref="loginForm"
@@ -36,7 +36,7 @@
                 <el-input
                   v-model="loginFormData.username"
                   size="large"
-                  placeholder="请输入用户名"
+                  :placeholder="$t.value.placeholderUser"
                   suffix-icon="user"
                 />
               </el-form-item>
@@ -49,7 +49,7 @@
                   show-password
                   size="large"
                   type="password"
-                  placeholder="请输入密码"
+                  :placeholder="$t.value.placeholderPwd"
                 />
               </el-form-item>
               <el-form-item
@@ -60,7 +60,7 @@
                 <div class="flex w-full justify-between">
                   <el-input
                     v-model="loginFormData.captcha"
-                    placeholder="请输入验证码"
+                    :placeholder="$t.value.placeholderCode"
                     size="large"
                     class="flex-1 mr-5"
                   />
@@ -81,7 +81,7 @@
                   type="primary"
                   size="large"
                   @click="submitForm"
-                >登 录</el-button>
+                >{{ $t.value.login }}</el-button>
               </el-form-item>
             </el-form>
           </div>

+ 96 - 79
web/src/view/parking/carInfo.vue

@@ -2,17 +2,17 @@
   <div>
     <!-- 搜索表单 -->
     <el-form inline>
-      <el-form-item label="车牌号">
+      <el-form-item :label="$t.value.LicensePlateNo">
         <el-input
           v-model="queryForm.plate_number"
-          placeholder="请输入车牌号"
+          :placeholder="$t.value.carPlateInput"
           clearable
         />
       </el-form-item>
-      <el-form-item label="车辆类型">
+      <el-form-item :label="$t.value.VehicleType">
         <el-select
           v-model="queryForm.vehicle_type_id"
-          placeholder="全部"
+          :placeholder="$t.value.carTypeSelect"
           clearable
           style="width:160px"
         >
@@ -24,11 +24,11 @@
           />
         </el-select>
       </el-form-item>
-      <el-form-item label="车主">
+      <el-form-item :label="$t.value.CarOwner">
         <el-select
           v-model="queryForm.owner_id"
           clearable
-          placeholder="请选择车主"
+          :placeholder="$t.value.ownerSelect"
           style="width: 180px"
         >
           <el-option
@@ -45,22 +45,22 @@
           icon="Search"
           type="primary"
           @click="getVehicleList"
-        >搜索</el-button>
+        >{{ $t.value.Search }}</el-button>
         <el-button
           icon="Refresh"
           @click="resetQuery"
-        >重置</el-button>
+        >{{ $t.value.Reset }}</el-button>
       </el-form-item>
       <el-form-item>
         <el-button
           icon="Plus"
           type="primary"
-          @click="openDialog('新增车辆', null)"
-        >新增</el-button>
+          @click="openDialog($t.value.addCar, null)"
+        >{{ $t.value.new }}</el-button>
         <el-button
           type="warning"
           @click="openTypeDrawer"
-        >管理车辆类型</el-button>
+        >{{ $t.value.manageCarType }}</el-button>
       </el-form-item>
     </el-form>
 
@@ -77,45 +77,45 @@
         width="80"
       />
       <el-table-column
-        label="车牌号"
+        :label="$t.value.LicensePlateNo"
         align="center"
         prop="plate_number"
       />
       <el-table-column
-        label="电子标签"
+        :label="$t.value.ElectronicTag"
         align="center"
         prop="rfid_tag"
       />
       <el-table-column
-        label="车辆类型"
+        :label="$t.value.VehicleType"
         align="center"
       >
         <template #default="scope">
           <el-tag type="primary">
-            {{ scope.row.vehicle_type?.name || "未知" }}
+            {{ scope.row.vehicle_type?.name || $t.value.unknown }}
           </el-tag>
         </template>
       </el-table-column>
       <el-table-column
-        label="品牌"
+        :label="$t.value.VehicleBrand"
         align="center"
         prop="vehicle_brand"
       />
       <el-table-column
-        label="颜色"
+        :label="$t.value.VehicleColor"
         align="center"
         prop="vehicle_color"
       />
       <el-table-column
-        label="车主"
+        :label="$t.value.CarOwner"
         align="center"
       >
         <template #default="scope">
-          {{ scope.row.owner?.owner_name || "临时车辆" }}
+          {{ scope.row.owner?.owner_name || $t.value.tempCar }}
         </template>
       </el-table-column>
       <el-table-column
-        label="操作"
+        :label="$t.value.Action"
         align="center"
         width="180"
       >
@@ -124,14 +124,14 @@
             icon="Edit"
             type="primary"
             text
-            @click="openDialog('编辑车辆', scope.row)"
-          >编辑</el-button>
+            @click="openDialog($t.value.editCar, scope.row)"
+          >{{ $t.value.modify }}</el-button>
           <el-button
             icon="Delete"
             type="danger"
             text
             @click="deleteVehicle(scope.row.ID)"
-          >删除</el-button>
+          >{{ $t.value.remove }}</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -156,25 +156,26 @@
       width="520px"
     >
       <el-form
-        label-width="100px"
+        label-width="120px"
         :model="formData"
       >
-        <el-form-item label="车牌号:">
+        <el-form-item :label="$t.value.LicensePlateNo">
           <el-input
             v-model="formData.plate_number"
-            placeholder="请输入车牌号"
+            :placeholder="$t.value.carPlateInput"
           />
         </el-form-item>
-        <el-form-item label="电子标签:">
+        <el-form-item :label="$t.value.ElectronicTag">
           <el-input
             v-model="formData.rfid_tag"
-            placeholder="RFID标签(UHF用)"
+            :placeholder="$t.value.rfidLabel"
           />
         </el-form-item>
-        <el-form-item label="车辆类型:">
+        <el-form-item :label="$t.value.VehicleType">
           <el-select
             v-model="formData.vehicle_type_id"
-            placeholder="请选择"
+
+            placeholder=""
             style="width:100%"
           >
             <el-option
@@ -185,22 +186,22 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="车辆品牌:">
+        <el-form-item :label="$t.value.VehicleBrand">
           <el-input
             v-model="formData.vehicle_brand"
-            placeholder="如:保时捷"
+            :placeholder="$t.value.placeholderPorsche"
           />
         </el-form-item>
-        <el-form-item label="车辆颜色">
+        <el-form-item :label="$t.value.VehicleColor">
           <el-input
             v-model="formData.vehicle_color"
-            placeholder="如:黑色"
+            :placeholder="$t.value.placeholderBlack"
           />
         </el-form-item>
-        <el-form-item label="绑定车主:">
+        <el-form-item :label="$t.value.BindOwner">
           <el-select
             v-model="formData.owner_id"
-            placeholder="临时车可不选"
+            :placeholder="$t.value.tempCarOptional"
             clearable
             style="width: 100%"
           >
@@ -214,33 +215,35 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button @click="dialogVisible = false">{{ $t.value.Cancel }}</el-button>
         <el-button
           type="primary"
           @click="submitForm"
-        >确认保存</el-button>
+        >{{ $t.value.Confirm }}</el-button>
       </template>
     </el-dialog>
 
     <!-- ===================== 车辆类型抽屉(Drawer)===================== -->
     <el-drawer
       v-model="typeDrawerVisible"
-      title="车辆类型管理"
+      :title="$t.value.manageCarType"
       size="700px"
     >
       <div style="display:flex; justify-content:space-between; margin-bottom:10px">
-        <el-input
-          v-model="typeQuery.name"
-          placeholder="搜索类型名称"
-          clearable
-          style="width:200px"
-          @input="getTypeList"
-        />
+        <el-form-item :label="$t.value.typeName">
+          <el-input
+            v-model="typeQuery.name"
+            placeholder=""
+            clearable
+            style="width:200px"
+            @input="getTypeList"
+          />
+        </el-form-item>
         <el-button
           type="primary"
           icon="Plus"
-          @click="openTypeForm('新增')"
-        >新增类型</el-button>
+          @click="openTypeForm($t.value.new)"
+        >{{ $t.value.AddNewType }}</el-button>
       </div>
 
       <el-table
@@ -252,25 +255,25 @@
           prop="ID"
         />
         <el-table-column
-          label="类型名称"
+          :label="$t.value.typeName"
           prop="name"
         />
         <el-table-column
-          label="备注"
+          :label="$t.value.Remarks"
           prop="remarks"
         />
-        <el-table-column label="操作">
+        <el-table-column :label="$t.value.Action">
           <template #default="scope">
             <el-button
               text
               type="primary"
-              @click="openTypeForm('编辑', scope.row)"
-            >编辑</el-button>
+              @click="openTypeForm($t.value.modify, scope.row)"
+            >{{ $t.value.modify }}</el-button>
             <el-button
               text
               type="danger"
               @click="deleteType(scope.row.ID)"
-            >删除</el-button>
+            >{{ $t.value.remove }}</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -292,16 +295,16 @@
       width="450px"
     >
       <el-form
-        label-width="80px"
+        label-width="100px"
         :model="typeForm"
       >
-        <el-form-item label="类型名称">
+        <el-form-item :label="$t.value.typeName">
           <el-input
             v-model="typeForm.name"
-            placeholder="如:月租车、VIP车"
+            :placeholder="$t.value.parkTip"
           />
         </el-form-item>
-        <el-form-item label="备注">
+        <el-form-item :label="$t.value.Remarks">
           <el-input
             v-model="typeForm.remarks"
             type="textarea"
@@ -310,11 +313,11 @@
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button @click="typeDialogVisible = false">取消</el-button>
+        <el-button @click="typeDialogVisible = false">{{ $t.value.Cancel }}</el-button>
         <el-button
           type="primary"
           @click="saveType"
-        >保存</el-button>
+        >{{ $t.value.Confirm }}</el-button>
       </template>
     </el-dialog>
   </div>
@@ -323,6 +326,7 @@
 <script setup>
 import { ref, reactive, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { t } from '@/lang/index.js'
 
 import {
   obtainVehicleList,
@@ -374,7 +378,7 @@ const getVehicleList = async() => {
       total.value = res.data.total
     }
   } catch (err) {
-    ElMessage.error('获取列表失败')
+    ElMessage.error(t.value.getListFail)
   }
 }
 
@@ -391,9 +395,9 @@ const openDialog = (title, row) => {
   dialogVisible.value = true
   if (!row) {
     Object.assign(formData, {
-      ID: 0, plate_number: '', rfid_tag: '',
-      vehicle_type_id: null, vehicle_brand: '',
-      vehicle_color: '', owner_id: null
+      ID: 0, plate_number: '湘F:8964a', rfid_tag: '',
+      vehicle_type_id: null, vehicle_brand: '宾利',
+      vehicle_color: '白色', owner_id: null
     })
     return
   }
@@ -402,32 +406,45 @@ const openDialog = (title, row) => {
 
 const submitForm = async() => {
   if (!formData.plate_number) {
-    ElMessage.warning('请输入车牌号')
+    ElMessage.warning(t.value.carPlateInput)
     return
   }
   try {
     if (formData.ID > 0) {
-      await editVehicle(formData)
-      ElMessage.success('编辑成功')
+      await editVehicle(formData).then(res => {
+        if (res.code === 0) {
+          ElMessage.success(t.value.editSuccess)
+        } else {
+          console.log(res.data)
+        }
+      })
     } else {
-      await addVehicle(formData)
-      ElMessage.success('新增成功')
+      console.log('新增', formData)
+      await addVehicle(formData).then(res => {
+        if (res.code === 0) {
+          ElMessage.success(t.value.addSuccess)
+        } else {
+          console.log(res.data)
+        }
+      })
     }
     dialogVisible.value = false
     getVehicleList()
   } catch (err) {
-    ElMessage.error('保存失败')
+    ElMessage.error(t.value.saveFail)
   }
 }
 
 const deleteVehicle = async(id) => {
-  await ElMessageBox.confirm('确定删除该车辆?', '提示', { type: 'warning' })
+  await ElMessageBox.confirm(t.value.confirmDeleteCar, t.value.tip,
+    { type: 'warning', confirmButtonText: t.value.Confirm,
+      cancelButtonText: t.value.Cancel })
   try {
     await removeVehicleList({ id })
-    ElMessage.success('删除成功')
+    ElMessage.success(t.value.deleteSuccess)
     getVehicleList()
   } catch (err) {
-    ElMessage.error('删除失败')
+    ElMessage.error(t.value.deleteFailed)
   }
 }
 
@@ -488,30 +505,30 @@ const openTypeForm = (title, row = null) => {
 // 保存
 const saveType = async() => {
   if (!typeForm.name) {
-    ElMessage.warning('请输入类型名称')
+    ElMessage.warning(t.value.inputTypeName)
     return
   }
   try {
     if (typeForm.ID > 0) {
       await editVehicleType(typeForm)
-      ElMessage.success('编辑成功')
+      ElMessage.success(t.value.editSuccess)
     } else {
       await createVehicleType(typeForm)
-      ElMessage.success('新增成功')
+      ElMessage.success(t.value.addSuccess)
     }
     typeDialogVisible.value = false
     getTypeList()
     loadAllTypes()
   } catch (e) {
-    ElMessage.error('保存失败')
+    ElMessage.error(t.value.saveFail)
   }
 }
 
 // 删除
 const deleteType = async(id) => {
-  await ElMessageBox.confirm('确定删除?')
+  await ElMessageBox.confirm(t.value.confirmDelete)
   await removeVehicleType(id)
-  ElMessage.success('删除成功')
+  ElMessage.success(t.value.deleteSuccess)
   getTypeList()
   loadAllTypes()
 }

+ 42 - 60
web/src/view/parking/carOwner.vue

@@ -4,28 +4,27 @@
       <el-form-item>
         <el-input
           v-model="obtainData.owner_phone"
-          placeholder="请输入手机号"
+          :placeholder="$t.value.inputPhone"
         />
       </el-form-item>
       <el-form-item>
         <el-input
           v-model="obtainData.owner_name"
-          placeholder="请输入车主名称"
+          :placeholder="$t.value.inputOwnerName"
         />
       </el-form-item>
       <el-form-item>
         <el-select
           v-model="obtainData.is_vip"
-          placeholder="是否是vip"
           clearable
           @change="changeVip"
         >
           <el-option
-            label="未成为vip"
+            :label="$t.value.noVip"
             :value="false"
           />
           <el-option
-            label="已成为vip"
+            :label="$t.value.isVip"
             :value="true"
           />
         </el-select>
@@ -35,31 +34,13 @@
           type="primary"
           icon="Search"
           @click="getCarOwnerList"
-        >搜索</el-button>
+        >{{ $t.value.Search }}</el-button>
       </el-form-item>
       <el-form-item>
         <el-button
           icon="Plus"
-          @click="openCarOwner('新增车主','')"
-        >新增</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="Delete">删除</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="Download">导入</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="Download">导入模板</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="Upload">导出</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="Memo">操作记录</el-button>
-      </el-form-item>
-      <el-form-item>
-        <el-button icon="ChatLineRound">其他</el-button>
+          @click="openCarOwner($t.value.AddCarOwner,'')"
+        >{{ $t.value.new }}</el-button>
       </el-form-item>
     </el-form>
     <el-table
@@ -67,24 +48,24 @@
       height="605"
     >
       <el-table-column
-        label="名字"
+        :label="$t.value.Name"
         align="center"
         width="180"
         prop="owner_name"
       />
       <el-table-column
-        label="姓氏"
+        :label="$t.value.Surname"
         align="center"
         width="180"
         prop="owner_surname"
       />
       <el-table-column
-        label="手机"
+        :label="$t.value.Mobile_Phone"
         align="center"
         prop="owner_phone"
       />
       <el-table-column
-        label="邮箱"
+        :label="$t.value.Email"
         align="center"
       />
       <el-table-column
@@ -96,12 +77,12 @@
             :type="scope.row.is_vip ? 'success' : 'danger'"
             plain
           >
-            {{ scope.row.is_vip ? '已成为vip' : '未成为vip' }}
+            {{ scope.row.is_vip ? $t.value.isVip : $t.value.noVip }}
           </el-button>
         </template>
       </el-table-column>
       <el-table-column
-        label="操作"
+        :label="$t.value.Action"
         align="center"
       >
         <template #default="scope">
@@ -112,19 +93,19 @@
             text
             type="primary"
             icon="MessageBox"
-          >备注</el-button>
+          >{{ $t.value.Remarks }}</el-button>
           <el-button
             icon="edit"
             text
             type="primary"
-            @click="openCarOwner('编辑车主', scope.row)"
-          >编辑</el-button>
+            @click="openCarOwner($t.value.editOwner, scope.row)"
+          >{{ $t.value.modify }}</el-button>
           <el-button
             icon="delete"
             text
             type="primary"
             @click="deleteCarOwner(scope.row)"
-          >删除</el-button>
+          >{{ $t.value.remove }}</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -146,16 +127,16 @@
       width="650"
     >
       <el-form
-        label-width="100"
+        label-width="120"
         size="large"
       >
-        <el-form-item label="名称:">
+        <el-form-item :label="$t.value.Name + ':'">
           <el-input v-model="carOwnerData.owner_name" />
         </el-form-item>
-        <el-form-item label="姓氏:">
+        <el-form-item :label="$t.value.Surname + ':'">
           <el-input v-model="carOwnerData.owner_surname" />
         </el-form-item>
-        <el-form-item label="手机:">
+        <el-form-item :label="$t.value.Mobile_Phone + ':'">
           <el-input v-model="carOwnerData.owner_phone" />
         </el-form-item>
         <el-form-item label="vip:">
@@ -165,20 +146,20 @@
             fill="#409eff"
           >
             <el-radio-button
-              label="否"
+              :label="$t.value.no"
               :value="false"
             />
             <el-radio-button
-              label="是"
+              :label="$t.value.yes"
               :value="true"
             />
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="vip过期时间:">
+        <el-form-item :label="'vip' + $t.value.Expire_Time + ':'">
           <el-date-picker
             v-model="carOwnerData.vip_expire_time"
             type="date"
-            placeholder="当前日期"
+            :placeholder="$t.value.currentDate"
           />
         </el-form-item>
       </el-form>
@@ -186,12 +167,12 @@
         <el-button
           size="large"
           @click="carOwnerShow = false"
-        >取消</el-button>
+        >{{$t.value.Confirm}}</el-button>
         <el-button
           type="primary"
           size="large"
           @click="carOwnerOperation"
-        >确认</el-button>
+        >{{$t.value.Cancel}}</el-button>
       </template>
     </el-dialog>
   </div>
@@ -201,6 +182,7 @@
 import { obtainCarOwnerList, addCarOwner, editCarOwner, removeCarOwner } from '@/api/carOwner'
 import { onMounted, reactive, ref } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { t } from '@/lang/index.js'
 const carOwnerList = reactive([1])
 const carOwnerShow = ref(false)
 const carOwnerTitle = ref('')
@@ -219,7 +201,7 @@ const changeVip = (val) => {
 const obtainData = reactive({
   owner_name: '',
   owner_phone: '',
-  is_vip: false,
+  is_vip: true,
   page: 1,
   pageSize: 10
 })
@@ -248,11 +230,11 @@ const getCarOwnerList = () => {
 
 const deleteCarOwner = (data) => {
   ElMessageBox.confirm(
-    '确定要删除该车主信息吗?',
-    '提示',
+    t.value.delOwnerTip,
+    t.value.tip,
     {
-      confirmButtonText: '确认',
-      cancelButtonText: '取消',
+      confirmButtonText: t.value.Confirm,
+      cancelButtonText: t.value.Cancel,
       type: 'warning',
     }
   )
@@ -261,13 +243,13 @@ const deleteCarOwner = (data) => {
         if (res.code === 0) {
           ElMessage({
             type: 'success',
-            message: '删除成功',
+            message: t.value.deleteSuccess,
           })
           getCarOwnerList()
         } else {
           ElMessage({
             type: 'error',
-            message: '删除失败',
+            message: t.value.deleteFailed,
           })
         }
       })
@@ -275,7 +257,7 @@ const deleteCarOwner = (data) => {
     .catch(() => {
       ElMessage({
         type: 'info',
-        message: '取消删除',
+        message: t.value.cancelDelete,
       })
     })
 }
@@ -283,7 +265,7 @@ const deleteCarOwner = (data) => {
 const openCarOwner = (head, data) => {
   carOwnerShow.value = true
   carOwnerTitle.value = head
-  if (head === '新增车主') {
+  if (head === t.value.AddCarOwner) {
     carOwnerData.is_vip = false
     carOwnerData.owner_surname = ''
     carOwnerData.owner_name = ''
@@ -300,24 +282,24 @@ const openCarOwner = (head, data) => {
 }
 
 const carOwnerOperation = async() => {
-  if (carOwnerTitle.value === '新增车主') {
+  if (carOwnerTitle.value === t.value.AddCarOwner) {
     await addCarOwner(carOwnerData).then(res => {
       if (res.code === 0) {
-        ElMessage.success('添加成功')
+        ElMessage.success(t.value.addSuccess)
         carOwnerShow.value = false
         getCarOwnerList()
       } else {
-        ElMessage.error('添加失败')
+        ElMessage.error(t.value.addFail)
       }
     })
   } else {
     await editCarOwner(carOwnerData).then(res => {
       if (res.code === 0) {
-        ElMessage.success('更新成功')
+        ElMessage.success(t.value.editSuccess)
         carOwnerShow.value = false
         getCarOwnerList()
       } else {
-        ElMessage.error('更新失败')
+        ElMessage.error(t.value.editFailed)
       }
     })
   }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 187 - 148
web/src/view/parking/parkingInfo.vue


+ 41 - 39
web/src/view/parking/pricing.vue

@@ -1,10 +1,10 @@
 <template>
   <div>
     <el-form inline>
-      <el-form-item label="车辆类型">
+      <el-form-item :label="$t.value.VehicleType">
         <el-select
           v-model="getPricingData.vehicle_type_id"
-          placeholder="全部"
+          :placeholder="$t.value.carTypeSelect"
           clearable
           style="width: 180px"
         >
@@ -21,14 +21,14 @@
           type="primary"
           icon="Search"
           @click="getPricingList"
-        >搜索</el-button>
+        >{{ $t.value.Search }}</el-button>
       </el-form-item>
       <el-form-item>
         <el-button
           type="primary"
           icon="Plus"
-          @click="openPricing('新增收费配置','')"
-        >新增</el-button>
+          @click="openPricing($t.value.AddChargeConfig,'')"
+        >{{ $t.value.new }}</el-button>
       </el-form-item>
     </el-form>
 
@@ -37,25 +37,25 @@
       height="605"
     >
       <el-table-column
-        label="车辆类型"
+        :label="$t.value.VehicleType"
         align="center"
         width="180"
         prop="vehicle_type.name"
       />
       <el-table-column
-        label="初始费用"
+        :label="$t.value.StartFee"
         align="center"
         width="180"
         prop="start_fee"
       />
       <el-table-column
-        label="单位费用"
+        :label="$t.value.UnitFee"
         align="center"
         width="180"
         prop="unit_fee"
       />
       <el-table-column
-        label="是否为VIP免费"
+        :label="$t.value.IsVipFree"
         align="center"
         width="180"
       >
@@ -64,24 +64,24 @@
             :type="scope.row.is_vip_free ? 'success' : 'danger'"
             plain
           >
-            {{ scope.row.is_vip_free ? 'VIP免费' : 'VIP不免费' }}
+            {{ scope.row.is_vip_free ? $t.value.vipFree : $t.value.vipNotFree }}
           </el-button>
         </template>
       </el-table-column>
       <el-table-column
-        label="每日最大费用"
+        :label="$t.value.DailyMaxFee"
         align="center"
         width="180"
         prop="daily_max_fee"
       />
       <el-table-column
-        label="vip折扣"
+        :label="$t.value.VipDiscount"
         align="center"
         width="180"
         prop="vip_discount"
       />
       <el-table-column
-        label="操作"
+        :label="$t.value.Action"
         align="center"
       >
         <template #default="scope">
@@ -94,20 +94,20 @@
               text
               type="primary"
               icon="MessageBox"
-            >备注</el-button>
+            >{{ $t.value.Remarks }}</el-button>
           </el-tooltip>
           <el-button
             icon="edit"
             text
             type="primary"
-            @click="openPricing('编辑收费配置', scope.row)"
-          >编辑</el-button>
+            @click="openPricing($t.value.EditChargeConfig, scope.row)"
+          >{{ $t.value.modify }}</el-button>
           <el-button
             icon="delete"
             text
             type="primary"
             @click="deletePricing(scope.row)"
-          >删除</el-button>
+          >{{ $t.value.remove }}</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -131,13 +131,13 @@
       width="650"
     >
       <el-form
-        label-width="120"
+        label-width="150"
         size="large"
       >
-        <el-form-item label="车辆类型:">
+        <el-form-item :label="$t.value.VehicleType + ':'">
           <el-select
             v-model="pricingData.vehicle_type_id"
-            placeholder="请选择车辆类型"
+            :placeholder="$t.value.carTypeSelect"
           >
             <el-option
               v-for="item in vehicleTypeList"
@@ -147,49 +147,49 @@
             />
           </el-select>
         </el-form-item>
-        <el-form-item label="免费时长(分钟):">
+        <el-form-item :label="$t.value.FreeDuration + ':'">
           <el-input
             v-model.number="pricingData.start_time"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="起步费用:">
+        <el-form-item :label="$t.value.StartFee + ':'">
           <el-input
             v-model.number="pricingData.start_fee"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="单位时间(分钟):">
+        <el-form-item :label="$t.value.UnitTime + ':'">
           <el-input
             v-model.number="pricingData.unit_time"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="单位费用:">
+        <el-form-item :label="$t.value.UnitFee + ':'">
           <el-input
             v-model.number="pricingData.unit_fee"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="每日最大费用:">
+        <el-form-item :label="$t.value.DailyMaxFee + ':'">
           <el-input
             v-model.number="pricingData.daily_max_fee"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="是否vip免费:">
+        <el-form-item :label="$t.value.IsVipFree + ':'">
           <el-radio-group v-model="pricingData.is_vip_free">
-            <el-radio-button :label="false"></el-radio-button>
-            <el-radio-button :label="true"></el-radio-button>
+            <el-radio-button :label="false">{{ $t.value.no }}</el-radio-button>
+            <el-radio-button :label="true">{{ $t.value.yes }}</el-radio-button>
           </el-radio-group>
         </el-form-item>
-        <el-form-item label="vip折扣:">
+        <el-form-item :label="$t.value.VipDiscount + ':'">
           <el-input
             v-model.number="pricingData.vip_discount"
             type="number"
           />
         </el-form-item>
-        <el-form-item label="描述:">
+        <el-form-item :label="$t.value.Remarks + ':'">
           <el-input
             v-model="pricingData.description"
             type="textarea"
@@ -201,12 +201,12 @@
         <el-button
           size="large"
           @click="pricingShow = false"
-        >取消</el-button>
+        >{{ $t.value.Cancel }}</el-button>
         <el-button
           type="primary"
           size="large"
           @click="pricingOperation"
-        >确认</el-button>
+        >{{ $t.value.Confirm }}</el-button>
       </template>
     </el-dialog>
   </div>
@@ -217,6 +217,7 @@ import { obtainPricingList, addPricing, editPricing, removePricing } from '@/api
 import { getAllVehicleTypes } from '@/api/vehicle'
 import { onMounted, reactive, ref } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
+import { t } from '@/lang/index.js'
 
 const pricingList = ref([])
 const pricingShow = ref(false)
@@ -265,10 +266,11 @@ const getPricingList = () => {
 
 // 删除
 const deletePricing = (data) => {
-  ElMessageBox.confirm('确定删除?', '提示', { type: 'warning' }).then(() => {
+  ElMessageBox.confirm(t.value.confirmDelete, t.value.tip, { type: 'warning', confirmButtonText: t.value.Confirm,
+    cancelButtonText: t.value.Cancel }).then(() => {
     removePricing(data.ID).then(res => {
       if (res.code === 0) {
-        ElMessage.success('删除成功')
+        ElMessage.success(t.value.deleteSuccess)
         getPricingList()
       }
     })
@@ -279,7 +281,7 @@ const deletePricing = (data) => {
 const openPricing = (title, data) => {
   pricingShow.value = true
   pricingTitle.value = title
-  if (title === '新增收费配置') {
+  if (title === t.value.AddChargeConfig) {
     Object.assign(pricingData, {
       id: 0,
       vehicle_type_id: '',
@@ -300,7 +302,7 @@ const openPricing = (title, data) => {
 // 提交
 const pricingOperation = async() => {
   if (!pricingData.vehicle_type_id) {
-    ElMessage.warning('请选择车辆类型')
+    ElMessage.warning(t.value.carTypeSelect)
     return
   }
 
@@ -318,10 +320,10 @@ const pricingOperation = async() => {
     description: pricingData.description
   }
 
-  if (pricingTitle.value === '新增收费配置') {
+  if (pricingTitle.value === t.value.AddChargeConfig) {
     await addPricing(params).then(res => {
       if (res.code === 0) {
-        ElMessage.success('新增成功')
+        ElMessage.success(t.value.addSuccess)
         pricingShow.value = false
         getPricingList()
       }
@@ -329,7 +331,7 @@ const pricingOperation = async() => {
   } else {
     await editPricing(params).then(res => {
       if (res.code === 0) {
-        ElMessage.success('修改成功')
+        ElMessage.success(t.value.editSuccess)
         pricingShow.value = false
         getPricingList()
       }

+ 65 - 40
web/src/view/parking/roster.vue

@@ -5,15 +5,15 @@
       inline
       :model="queryForm"
     >
-      <el-form-item label="车牌号码">
+      <el-form-item :label="$t.value.LicensePlateNo">
         <el-input
           v-model="queryForm.plate_number"
-          placeholder="车牌"
+          :placeholder="$t.value.licensePlate"
           clearable
         />
       </el-form-item>
 
-      <el-form-item label="RFID标签">
+      <el-form-item :label="$t.value.RFID_Tag">
         <el-input
           v-model="queryForm.rfid_tag"
           placeholder="RFID"
@@ -21,18 +21,18 @@
         />
       </el-form-item>
 
-      <el-form-item label="名单类型">
+      <el-form-item :label="$t.value.List_Type">
         <el-select
           v-model="queryForm.list_type"
-          placeholder="全部"
+          placeholder=""
           clearable
         >
           <el-option
-            label="白名单"
+            :label="$t.value.WhiteList"
             value="白名单"
           />
           <el-option
-            label="黑名单"
+            :label="$t.value.BlackList"
             value="黑名单"
           />
         </el-select>
@@ -42,13 +42,13 @@
         <el-button
           type="primary"
           @click="getList"
-        >搜索</el-button>
-        <el-button @click="resetQuery">重置</el-button>
+        >{{ $t.value.Search }}</el-button>
+        <el-button @click="resetQuery">{{ $t.value.Reset }}</el-button>
         <el-button
           type="success"
           icon="Plus"
           @click="add"
-        >新增</el-button>
+        >{{ $t.value.new }}</el-button>
       </el-form-item>
     </el-form>
 
@@ -66,18 +66,18 @@
       />
       <el-table-column
         prop="list_type"
-        label="名单类型"
+        :label="$t.value.List_Type"
         align="center"
         width="120"
       >
         <template #default="scope">
           <el-tag :type="scope.row.list_type === '白名单' ? 'success' : 'danger'">
-            {{ scope.row.list_type }}
+            {{ scope.row.list_type === '白名单' ? $t.value.WhiteList : $t.value.BlackList }}
           </el-tag>
         </template>
       </el-table-column>
       <el-table-column
-        label="车牌"
+        :label="$t.value.licensePlate"
         align="center"
         prop="vehicle.plate_number"
       />
@@ -87,12 +87,12 @@
         prop="vehicle.rfid_tag"
       />
       <el-table-column
-        label="车辆类型"
+        :label="$t.value.VehicleType"
         align="center"
         prop="vehicle.vehicle_type.name"
       />
       <el-table-column
-        label="到期时间"
+        :label="$t.value.Action"
         align="center"
         width="200"
       >
@@ -101,7 +101,7 @@
         </template>
       </el-table-column>
       <el-table-column
-        label="操作"
+        :label="$t.value.Action"
         align="center"
         width="180"
       >
@@ -110,12 +110,12 @@
             link
             type="primary"
             @click="edit(scope.row)"
-          >编辑</el-button>
+          >{{ $t.value.modify }}</el-button>
           <el-button
             link
             type="danger"
             @click="del(scope.row.ID)"
-          >删除</el-button>
+          >{{ $t.value.remove }}</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -133,7 +133,7 @@
     <!-- 新增/编辑弹窗 → 车辆下拉选择 -->
     <el-dialog
       v-model="dialogVisible"
-      title="黑白名单管理"
+      :title="$t.value.blackWhiteList"
       width="550px"
     >
       <el-form
@@ -141,49 +141,49 @@
         label-width="120px"
       >
         <el-form-item
-          label="名单类型"
+          :label="$t.value.List_Type"
           required
         >
           <el-radio-group v-model="form.list_type">
-            <el-radio value="白名单">白名单</el-radio>
-            <el-radio value="黑名单">黑名单</el-radio>
+            <el-radio value="白名单">{{ $t.value.WhiteList }}</el-radio>
+            <el-radio value="黑名单">{{ $t.value.BlackList }}</el-radio>
           </el-radio-group>
         </el-form-item>
 
         <el-form-item
-          label="选择车辆"
+          :label="$t.value.SelectVehicle"
           required
         >
           <el-select
             v-model="form.vehicle_id"
-            placeholder="请选择车辆"
+            :placeholder="$t.value.pleaseSelectVehicle"
             style="width:100%"
           >
             <el-option
               v-for="v in vehicleList"
               :key="v.ID"
-              :label="`${v.plate_number} | ${v.rfid_tag || '无标签'}`"
+              :label="`${v.plate_number} | ${v.rfid_tag || $t.value.noLabel}`"
               :value="v.ID"
             />
           </el-select>
         </el-form-item>
 
-        <el-form-item label="到期时间">
+        <el-form-item :label="$t.value.expireTime">
           <el-date-picker
             v-model="form.expiration_time"
             type="datetime"
-            placeholder="不选则永久有效"
+            :placeholder="$t.value.permanentValidity"
             style="width:100%"
           />
         </el-form-item>
       </el-form>
 
       <template #footer>
-        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button @click="dialogVisible = false">{{ $t.value.Cancel }}</el-button>
         <el-button
           type="primary"
           @click="submit"
-        >确认保存</el-button>
+        >{{ $t.value.Confirm }}</el-button>
       </template>
     </el-dialog>
   </div>
@@ -194,6 +194,7 @@ import { ref, reactive, onMounted } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { queryShortlistList, addShortlist, updateShortlist, deleteShortlist } from '@/api/shortlist'
 import { queryAllVehicles } from '@/api/vehicle' // 你现有的车辆接口
+import { t } from '@/lang/index.js'
 
 // 数据列表
 const list = ref([])
@@ -215,14 +216,14 @@ const vehicleList = ref([])
 const dialogVisible = ref(false)
 const form = reactive({
   ID: 0,
-  list_type: '白名单',
+  list_type: t.value.WhiteList,
   vehicle_id: '',
   expiration_time: null
 })
 
 // 时间格式化
 const formatTime = (time) => {
-  if (!time) return '永久有效'
+  if (!time) return t.value.permanentValid
   return time.replace('T', ' ').split('+')[0]
 }
 
@@ -266,37 +267,61 @@ const edit = (row) => {
   form.ID = row.ID
   form.list_type = row.list_type
   form.vehicle_id = row.vehicle_id
-  form.expiration_time = row.expiration_time ? formatTime(row.expiration_time) : ''
+  form.expiration_time = row.expiration_time ? formatTime(row.expiration_time) : null
   dialogVisible.value = true
 }
 
 // 提交
 const submit = async() => {
   if (!form.vehicle_id) {
-    ElMessage.warning('请选择车辆')
+    ElMessage.warning(t.value.pleaseSelectVehicle)
     return
   }
   try {
     if (form.ID > 0) {
       await updateShortlist(form)
-      ElMessage.success('修改成功')
+      ElMessage.success(t.value.editSuccess)
     } else {
       await addShortlist(form)
-      ElMessage.success('新增成功')
+      ElMessage.success(t.value.addSuccess)
     }
     dialogVisible.value = false
     getList()
   } catch (e) {
-    ElMessage.error('保存失败')
+    ElMessage.error(t.value.saveFail)
   }
 }
 
 // 删除
 const del = async(id) => {
-  await ElMessageBox.confirm('确定删除?')
-  await deleteShortlist(id)
-  ElMessage.success('删除成功')
-  getList()
+  await ElMessageBox.confirm(
+    t.value.confirmDelete,
+    t.value.tip,
+    {
+      confirmButtonText: t.value.confirm,
+      cancelButtonText: t.value.Cancel,
+      type: 'warning',
+    }
+  )
+    .then(() => {
+      deleteShortlist(id).then(res => {
+        if (res.code === 0) {
+          ElMessage.success(t.value.deleteSuccess)
+          getList()
+        } else {
+          ElMessage({
+            type: 'error',
+            message: t.value.deleteFailed,
+          })
+        }
+      })
+    })
+    .catch(() => {
+      ElMessage({
+        type: 'info',
+        message: t.value.cancelDelete,
+      })
+    })
 }
 
 // 初始化

+ 31 - 31
web/src/view/report/enter.vue

@@ -2,18 +2,18 @@
   <div>
     <!-- 搜索表单 -->
     <el-form inline>
-      <el-form-item label="车牌号码">
+      <el-form-item :label="$t.value.LicensePlateNo">
         <el-input
           v-model="queryForm.plate_number"
-          placeholder="请输入车牌"
+          :placeholder="$t.value.carPlateInput"
           clearable
         />
       </el-form-item>
 
-      <el-form-item label="RFID标签">
+      <el-form-item :label="$t.value.RFID_Tag">
         <el-input
           v-model="queryForm.rfid_tag"
-          placeholder="请输入RFID"
+          placeholder="RFID"
           clearable
         />
       </el-form-item>
@@ -22,8 +22,8 @@
         <el-button
           type="primary"
           @click="getRecordList"
-        >搜索</el-button>
-        <el-button @click="resetQuery">重置</el-button>
+        >{{ $t.value.Search }}</el-button>
+        <el-button @click="resetQuery">{{ $t.value.Reset }}</el-button>
       </el-form-item>
     </el-form>
 
@@ -34,18 +34,18 @@
       border
     >
       <el-table-column
-        label="车牌"
+        :label="$t.value.licensePlate"
         prop="plate_number"
         align="center"
       />
       <el-table-column
-        label="RFID标签"
+        :label="$t.value.RFID_Tag"
         prop="rfid_tag"
         align="center"
       />
 
       <el-table-column
-        label="入场时间"
+        :label="$t.value.EntryTime"
         align="center"
       >
         <template #default="scope">
@@ -54,25 +54,25 @@
       </el-table-column>
 
       <el-table-column
-        label="出场时间"
+        :label="$t.value.ExitTime"
         align="center"
       >
         <template #default="scope">
-          {{ formatTime(scope.row.exit_time) || '未出场' }}
+          {{ formatTime(scope.row.exit_time) || $t.value.notOut }}
         </template>
       </el-table-column>
 
       <el-table-column
-        label="停留时长"
+        :label="$t.value.ExitTime"
         align="center"
       >
         <template #default="scope">
-          {{ scope.row.stay_time || 0 }} 分钟
+          {{ scope.row.stay_time || 0 }} {{ $t.value.minute }}
         </template>
       </el-table-column>
 
       <el-table-column
-        label="费用"
+        :label="$t.value.Fee"
         align="center"
       >
         <template #default="scope">
@@ -81,18 +81,18 @@
       </el-table-column>
 
       <el-table-column
-        label="支付状态"
+        :label="$t.value.PayStatus"
         align="center"
       >
         <template #default="scope">
           <el-tag :type="scope.row.payment_status === 'paid' ? 'success' : 'warning'">
-            {{ scope.row.payment_status === 'paid' ? '已支付' : '未支付' }}
+            {{ scope.row.payment_status === 'paid' ? $t.value.paid : $t.value.unpaid }}
           </el-tag>
         </template>
       </el-table-column>
 
       <el-table-column
-        label="操作"
+        :label="$t.value.Action"
         align="center"
         width="100"
       >
@@ -103,7 +103,7 @@
             icon="View"
             @click="openDetail(scope.row)"
           >
-            查看
+            {{ $t.value.view }}
           </el-button>
         </template>
       </el-table-column>
@@ -123,38 +123,38 @@
     <!-- 查看详情弹窗 -->
     <el-dialog
       v-model="detailShow"
-      title="进出记录详情"
+      :title="$t.value.recordDetail"
       width="700px"
     >
       <el-form label-width="100px">
-        <el-form-item label="车牌">{{ detail.plate_number }}</el-form-item>
+        <el-form-item :label="$t.value.licensePlate">{{ detail.plate_number }}</el-form-item>
         <el-form-item label="RFID">{{ detail.rfid_tag }}</el-form-item>
-        <el-form-item label="入场时间">{{ formatTime(detail.entry_time) }}</el-form-item>
-        <el-form-item label="出场时间">{{ formatTime(detail.exit_time) || '未出场' }}</el-form-item>
-        <el-form-item label="停留时长">{{ detail.stay_time || 0 }} 分钟</el-form-item>
-        <el-form-item label="费用">¥ {{ detail.fee || 0 }}</el-form-item>
-        <el-form-item label="支付状态">
-          {{ detail.payment_status === 'paid' ? '已支付' : '未支付' }}
+        <el-form-item :label="$t.value.EntryTime">{{ formatTime(detail.entry_time) }}</el-form-item>
+        <el-form-item :label="$t.value.ExitTime">{{ formatTime(detail.exit_time) || $t.value.notOut }}</el-form-item>
+        <el-form-item :label="$t.value.StayDuration">{{ detail.stay_time || 0 }} {{ $t.value.minute }}</el-form-item>
+        <el-form-item :label="$t.value.Fee">¥ {{ detail.fee || 0 }}</el-form-item>
+        <el-form-item :label="$t.value.PayStatus">
+          {{ detail.payment_status === 'paid' ? $t.value.paid : $t.value.unpaid }}
         </el-form-item>
       </el-form>
 
       <!-- 图片展示 -->
       <div style="display: flex; gap:10px; margin-top:10px">
-        <el-form-item label="入场图片">
+        <el-form-item :label="$t.value.entryImg">
           <el-image
             style="width: 200px; height:120px; object-fit:cover"
             :src="detail.entry_image"
             fit="cover"
-            alt="入场图片"
+            :alt="$t.value.entryImg"
           />
         </el-form-item>
 
-        <el-form-item label="出场图片">
+        <el-form-item :label="$t.value.exitImg">
           <el-image
             style="width: 200px; height:120px; object-fit:cover"
             :src="detail.exit_image"
             fit="cover"
-            alt="出场图片"
+            :alt="$t.value.exitImg"
           />
         </el-form-item>
       </div>
@@ -195,7 +195,7 @@ const getRecordList = async() => {
       total.value = res.data.total
     }
   } catch (e) {
-    ElMessage.error('获取记录失败')
+    ElMessage.error(t.value.getListFail)
   }
 }
 

+ 10 - 10
web/src/view/report/sheet.vue

@@ -1,21 +1,21 @@
 <template>
   <div>
     <el-form inline>
-      <el-form-item label="车牌">
-        <el-input></el-input>
+      <el-form-item :label="$t.value.licensePlate">
+        <el-input />
       </el-form-item>
       <el-form-item>
-        <el-button type="primary">搜索</el-button>
+        <el-button type="primary">{{ $t.value.Search }}</el-button>
       </el-form-item>
     </el-form>
     <el-table>
-      <el-table-column label="车牌"></el-table-column>
-      <el-table-column label="车辆识别号码"></el-table-column>
-      <el-table-column label="出场时间"></el-table-column>
-      <el-table-column label="出场岗亭"></el-table-column>
-      <el-table-column label="出场通道"></el-table-column>
-      <el-table-column label="车主名称"></el-table-column>
-      <el-table-column label="到期日期"></el-table-column>
+      <el-table-column :label="$t.value.licensePlate" />
+      <el-table-column :label="$t.value.ExitTime" />
+      <el-table-column :label="$t.value.ExitTime" />
+      <el-table-column :label="$t.value.ExitBooth" />
+      <el-table-column :label="$t.value.ExitPassage" />
+      <el-table-column :label="$t.value.vehicleNumber" />
+      <el-table-column :label="$t.value.ownerName" />
     </el-table>
   </div>
 </template>