Commit e18d1bbb13df7f7cdb6a6853bb17091db7fef574

Authored by wuxw
1 parent 32a770b5

开发完成停车场 和停车位功能

src/api/car/listParkingSpaceApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 查询停车位列表
  5 +export function listParkingSpaces(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const communityId = getCommunityId()
  8 + request({
  9 + url: '/parkingSpace.queryParkingSpaces',
  10 + method: 'get',
  11 + params: { ...params, communityId }
  12 + }).then(response => {
  13 + const res = response.data
  14 +
  15 + resolve(res)
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +// 添加停车位
  23 +export function saveParkingSpace(data) {
  24 + return new Promise((resolve, reject) => {
  25 + const communityId = getCommunityId()
  26 + request({
  27 + url: '/parkingSpace.saveParkingSpace',
  28 + method: 'post',
  29 + data: { ...data, communityId }
  30 + }).then(response => {
  31 + const res = response.data
  32 + if (res.code === 0) {
  33 + resolve(res)
  34 + } else {
  35 + reject(new Error(res.msg || '添加停车位失败'))
  36 + }
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +// 编辑停车位
  44 +export function editParkingSpace(data) {
  45 + return new Promise((resolve, reject) => {
  46 + const communityId = getCommunityId()
  47 + request({
  48 + url: '/parkingSpace.editParkingSpace',
  49 + method: 'post',
  50 + data: { ...data, communityId }
  51 + }).then(response => {
  52 + const res = response.data
  53 + if (res.code === 0) {
  54 + resolve(res)
  55 + } else {
  56 + reject(new Error(res.msg || '编辑停车位失败'))
  57 + }
  58 + }).catch(error => {
  59 + reject(error)
  60 + })
  61 + })
  62 +}
  63 +
  64 +// 删除停车位
  65 +export function deleteParkingSpace(data) {
  66 + return new Promise((resolve, reject) => {
  67 + const communityId = getCommunityId()
  68 + request({
  69 + url: '/parkingSpace.deleteParkingSpace',
  70 + method: 'post',
  71 + data: { ...data, communityId }
  72 + }).then(response => {
  73 + const res = response.data
  74 + if (res.code === 0) {
  75 + resolve(res)
  76 + } else {
  77 + reject(new Error(res.msg || '删除停车位失败'))
  78 + }
  79 + }).catch(error => {
  80 + reject(error)
  81 + })
  82 + })
  83 +}
  84 +
  85 +// 查询停车场列表
  86 +export function listParkingAreas(params) {
  87 + return new Promise((resolve, reject) => {
  88 + const communityId = getCommunityId()
  89 + request({
  90 + url: '/parkingArea.listParkingAreas',
  91 + method: 'get',
  92 + params: { ...params, communityId }
  93 + }).then(response => {
  94 + const res = response.data
  95 + resolve(res)
  96 + }).catch(error => {
  97 + reject(error)
  98 + })
  99 + })
  100 +}
  101 +
  102 +// 批量添加停车位
  103 +export function batchSaveParkingSpace(data) {
  104 + return new Promise((resolve, reject) => {
  105 + const communityId = getCommunityId()
  106 + request({
  107 + url: '/parkingSpace.batchSaveParkingSpace',
  108 + method: 'post',
  109 + data: { ...data, communityId }
  110 + }).then(response => {
  111 + const res = response.data
  112 + if (res.code === 0) {
  113 + resolve(res)
  114 + } else {
  115 + reject(new Error(res.msg || '批量添加停车位失败'))
  116 + }
  117 + }).catch(error => {
  118 + reject(error)
  119 + })
  120 + })
  121 +}
0 \ No newline at end of file 122 \ No newline at end of file
src/api/car/parkingAreaManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取停车场列表
  5 +export function getParkingAreaList(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const query = {
  8 + ...params,
  9 + communityId: params.communityId || getCommunityId()
  10 + }
  11 +
  12 + request({
  13 + url: '/parkingArea.listParkingAreas',
  14 + method: 'get',
  15 + params: query
  16 + }).then(response => {
  17 + const res = response.data
  18 + resolve(res)
  19 + }).catch(error => {
  20 + reject(error)
  21 + })
  22 + })
  23 +}
  24 +
  25 +// 添加停车场
  26 +export function saveParkingArea(data) {
  27 + return new Promise((resolve, reject) => {
  28 + const params = {
  29 + ...data,
  30 + communityId: data.communityId || getCommunityId()
  31 + }
  32 +
  33 + request({
  34 + url: '/parkingArea.saveParkingArea',
  35 + method: 'post',
  36 + data: params
  37 + }).then(response => {
  38 + const res = response.data
  39 + if (res.code === 0) {
  40 + resolve(res)
  41 + } else {
  42 + reject(new Error(res.msg || '添加停车场失败'))
  43 + }
  44 + }).catch(error => {
  45 + reject(error)
  46 + })
  47 + })
  48 +}
  49 +
  50 +// 更新停车场
  51 +export function updateParkingArea(data) {
  52 + return new Promise((resolve, reject) => {
  53 + const params = {
  54 + ...data,
  55 + communityId: data.communityId || getCommunityId()
  56 + }
  57 +
  58 + request({
  59 + url: '/parkingArea.updateParkingArea',
  60 + method: 'post',
  61 + data: params
  62 + }).then(response => {
  63 + const res = response.data
  64 + if (res.code === 0) {
  65 + resolve(res)
  66 + } else {
  67 + reject(new Error(res.msg || '更新停车场失败'))
  68 + }
  69 + }).catch(error => {
  70 + reject(error)
  71 + })
  72 + })
  73 +}
  74 +
  75 +// 删除停车场
  76 +export function deleteParkingArea(data) {
  77 + return new Promise((resolve, reject) => {
  78 + const params = {
  79 + ...data,
  80 + communityId: data.communityId || getCommunityId()
  81 + }
  82 +
  83 + request({
  84 + url: '/parkingArea.deleteParkingArea',
  85 + method: 'post',
  86 + data: params
  87 + }).then(response => {
  88 + const res = response.data
  89 + if (res.code === 0) {
  90 + resolve(res)
  91 + } else {
  92 + reject(new Error(res.msg || '删除停车场失败'))
  93 + }
  94 + }).catch(error => {
  95 + reject(error)
  96 + })
  97 + })
  98 +}
0 \ No newline at end of file 99 \ No newline at end of file
src/components/car/addParkingArea.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('parkingAreaManage.addTitle')" :visible.sync="visible" width="50%" @close="closeDialog">
  3 + <el-form ref="form" :model="addParkingAreaInfo" label-width="150px" label-position="left">
  4 + <el-form-item :label="$t('parkingAreaManage.parkingNum')" prop="num"
  5 + :rules="[{ required: true, message: $t('parkingAreaManage.numRequired'), trigger: 'blur' }]">
  6 + <el-input v-model.trim="addParkingAreaInfo.num" :placeholder="$t('parkingAreaManage.inputParkingNum')" />
  7 + </el-form-item>
  8 +
  9 + <el-form-item :label="$t('parkingAreaManage.parkingType')" prop="typeCd"
  10 + :rules="[{ required: true, message: $t('parkingAreaManage.typeRequired'), trigger: 'change' }]">
  11 + <el-select v-model="addParkingAreaInfo.typeCd" :placeholder="$t('parkingAreaManage.selectParkingType')"
  12 + style="width: 100%">
  13 + <el-option v-for="item in parkingTypes" :key="item.value" :label="item.label" :value="item.value" />
  14 + </el-select>
  15 + </el-form-item>
  16 +
  17 + <div v-for="(item, index) in addParkingAreaInfo.attrs" :key="index">
  18 + <el-form-item v-if="item.specType === '2233'" :label="item.specName" :prop="`attrs[${index}].value`"
  19 + :rules="item.required ? [{ required: true, message: $t('common.required'), trigger: 'blur' }] : []">
  20 + <el-input v-model="item.value" :placeholder="item.specHoldplace" />
  21 + </el-form-item>
  22 +
  23 + <el-form-item v-if="item.specType === '3344'" :label="item.specName" :prop="`attrs[${index}].value`"
  24 + :rules="item.required ? [{ required: true, message: $t('common.required'), trigger: 'change' }] : []">
  25 + <el-select v-model="item.value" :placeholder="item.specHoldplace" style="width: 100%">
  26 + <el-option v-for="value in item.values" :key="value.value" :label="value.valueName" :value="value.value" />
  27 + </el-select>
  28 + </el-form-item>
  29 + </div>
  30 +
  31 + <el-form-item :label="$t('parkingAreaManage.remark')">
  32 + <el-input v-model="addParkingAreaInfo.remark" type="textarea" :rows="3"
  33 + :placeholder="$t('parkingAreaManage.remarkPlaceholder')" />
  34 + </el-form-item>
  35 + </el-form>
  36 +
  37 + <div slot="footer" class="dialog-footer">
  38 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  39 + <el-button type="primary" @click="saveParkingAreaInfo" :loading="saving">
  40 + {{ $t('common.save') }}
  41 + </el-button>
  42 + </div>
  43 + </el-dialog>
  44 +</template>
  45 +
  46 +<script>
  47 +import { saveParkingArea } from '@/api/car/parkingAreaManageApi'
  48 +import { getCommunityId } from '@/api/community/communityApi'
  49 +
  50 +export default {
  51 + name: 'AddParkingArea',
  52 + data() {
  53 + return {
  54 + visible: false,
  55 + saving: false,
  56 + addParkingAreaInfo: {
  57 + num: '',
  58 + typeCd: '',
  59 + remark: '',
  60 + attrs: []
  61 + },
  62 + parkingTypes: [
  63 + { value: '1001', label: this.$t('parkingAreaManage.aboveGround') },
  64 + { value: '2001', label: this.$t('parkingAreaManage.underground') }
  65 + ]
  66 + }
  67 + },
  68 + methods: {
  69 + open() {
  70 + this.visible = true
  71 + this.resetForm()
  72 + this._loadParkingAreaAttrSpec()
  73 + },
  74 +
  75 + closeDialog() {
  76 + this.$refs.form.resetFields()
  77 + },
  78 +
  79 + resetForm() {
  80 + this.addParkingAreaInfo = {
  81 + num: '',
  82 + typeCd: '',
  83 + remark: '',
  84 + attrs: []
  85 + }
  86 + },
  87 +
  88 + async saveParkingAreaInfo() {
  89 + this.$refs.form.validate(async valid => {
  90 + if (!valid) return
  91 +
  92 + try {
  93 + this.saving = true
  94 + const params = {
  95 + ...this.addParkingAreaInfo,
  96 + communityId: getCommunityId()
  97 + }
  98 +
  99 + await saveParkingArea(params)
  100 + this.$message.success(this.$t('parkingAreaManage.addSuccess'))
  101 + this.visible = false
  102 + this.$emit('success')
  103 + } catch (error) {
  104 + console.error('添加停车场失败:', error)
  105 + this.$message.error(this.$t('parkingAreaManage.addFailed'))
  106 + } finally {
  107 + this.saving = false
  108 + }
  109 + })
  110 + },
  111 +
  112 + async _loadParkingAreaAttrSpec() {
  113 + try {
  114 + // 实际项目中从API获取属性配置
  115 + // 这里使用模拟数据
  116 + this.addParkingAreaInfo.attrs = [
  117 + ]
  118 + } catch (error) {
  119 + console.error('加载停车场属性失败:', error)
  120 + }
  121 + }
  122 + }
  123 +}
  124 +</script>
0 \ No newline at end of file 125 \ No newline at end of file
src/components/car/addParkingSpace.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('addParkingSpace.title')" :visible.sync="visible" width="50%" @close="closeDialog">
  3 + <el-form :model="form" ref="form" label-width="120px">
  4 + <el-form-item :label="$t('addParkingSpace.parkingSpaceNum')" prop="num"
  5 + :rules="[{ required: true, message: $t('addParkingSpace.parkingSpaceNumPlaceholder'), trigger: 'blur' }]">
  6 + <el-input v-model="form.num" :placeholder="$t('addParkingSpace.parkingSpaceNumPlaceholder')"></el-input>
  7 + </el-form-item>
  8 +
  9 + <el-form-item :label="$t('addParkingSpace.parkingLot')" prop="paId"
  10 + :rules="[{ required: true, message: $t('addParkingSpace.parkingLotPlaceholder'), trigger: 'change' }]">
  11 + <el-select v-model="form.paId" :placeholder="$t('addParkingSpace.parkingLotPlaceholder')" style="width:100%">
  12 + <el-option v-for="item in parkingAreas" :key="item.paId" :label="item.num" :value="item.paId"></el-option>
  13 + </el-select>
  14 + </el-form-item>
  15 +
  16 + <el-form-item :label="$t('addParkingSpace.parkingSpaceType')" prop="parkingType"
  17 + :rules="[{ required: true, message: $t('addParkingSpace.parkingSpaceTypePlaceholder'), trigger: 'change' }]">
  18 + <el-select v-model="form.parkingType" :placeholder="$t('addParkingSpace.parkingSpaceTypePlaceholder')"
  19 + style="width:100%">
  20 + <el-option v-for="item in parkingTypes" :key="item.statusCd" :label="item.name"
  21 + :value="item.statusCd"></el-option>
  22 + </el-select>
  23 + </el-form-item>
  24 +
  25 + <el-form-item :label="$t('addParkingSpace.area')" prop="area" :rules="[
  26 + { required: true, message: $t('addParkingSpace.areaPlaceholder'), trigger: 'blur' },
  27 + { pattern: /^\d+(\.\d{1,2})?$/, message: $t('addParkingSpace.areaPlaceholder'), trigger: 'blur' }
  28 + ]">
  29 + <el-input v-model="form.area" type="number" :placeholder="$t('addParkingSpace.areaPlaceholder')"></el-input>
  30 + </el-form-item>
  31 +
  32 + <el-form-item :label="$t('addParkingSpace.remark')" prop="remark">
  33 + <el-input v-model="form.remark" type="textarea" :placeholder="$t('addParkingSpace.remarkPlaceholder')"></el-input>
  34 + </el-form-item>
  35 + </el-form>
  36 +
  37 + <div slot="footer" class="dialog-footer">
  38 + <el-button @click="visible = false">{{ $t('addParkingSpace.cancel') }}</el-button>
  39 + <el-button type="primary" @click="saveParkingSpace" :loading="saving">
  40 + {{ $t('addParkingSpace.save') }}
  41 + </el-button>
  42 + </div>
  43 + </el-dialog>
  44 +</template>
  45 +
  46 +<script>
  47 +import { saveParkingSpace } from '@/api/car/listParkingSpaceApi'
  48 +import { listParkingAreas } from '@/api/car/listParkingSpaceApi'
  49 +import { getDict } from '@/api/community/communityApi'
  50 +import { getCommunityId } from '@/api/community/communityApi'
  51 +
  52 +export default {
  53 + name: 'AddParkingSpace',
  54 + data() {
  55 + return {
  56 + visible: false,
  57 + saving: false,
  58 + form: {
  59 + num: '',
  60 + paId: '',
  61 + parkingType: '1',
  62 + area: '1',
  63 + remark: '',
  64 + communityId: getCommunityId()
  65 + },
  66 + parkingTypes: [],
  67 + parkingAreas: []
  68 + }
  69 + },
  70 + methods: {
  71 + open() {
  72 + this.visible = true
  73 + this.loadParkingTypes()
  74 + this.loadParkingAreas()
  75 + },
  76 +
  77 + async loadParkingTypes() {
  78 + try {
  79 + const data = await getDict('parking_space', 'parking_type')
  80 + this.parkingTypes = data
  81 + } catch (error) {
  82 + this.$message.error(this.$t('common.loadDictError'))
  83 + }
  84 + },
  85 +
  86 + async loadParkingAreas() {
  87 + try {
  88 + const params = {
  89 + page: 1,
  90 + row: 50,
  91 + communityId: getCommunityId()
  92 + }
  93 + const res = await listParkingAreas(params)
  94 + this.parkingAreas = res.parkingAreas
  95 + } catch (error) {
  96 + this.$message.error(this.$t('common.loadError'))
  97 + }
  98 + },
  99 +
  100 + async saveParkingSpace() {
  101 + try {
  102 + this.saving = true
  103 + await this.$refs.form.validate()
  104 +
  105 + const res = await saveParkingSpace(this.form)
  106 + if (res.code === 0) {
  107 + this.$message.success(this.$t('common.saveSuccess'))
  108 + this.$emit('success')
  109 + this.visible = false
  110 + } else {
  111 + this.$message.error(res.msg || this.$t('common.saveError'))
  112 + }
  113 + } catch (error) {
  114 + console.error('Validation failed:', error)
  115 + } finally {
  116 + this.saving = false
  117 + }
  118 + },
  119 +
  120 + closeDialog() {
  121 + this.$refs.form.resetFields()
  122 + this.form = {
  123 + num: '',
  124 + paId: '',
  125 + parkingType: '1',
  126 + area: '1',
  127 + remark: '',
  128 + communityId: getCommunityId()
  129 + }
  130 + }
  131 + }
  132 +}
  133 +</script>
0 \ No newline at end of file 134 \ No newline at end of file
src/components/car/batchAddParkingSpace.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('batchAddParkingSpace.title')" :visible.sync="visible" width="50%" @close="closeDialog">
  3 + <el-form :model="form" ref="form" label-width="120px">
  4 + <el-form-item :label="$t('batchAddParkingSpace.prefixNum')" prop="preNum">
  5 + <el-input v-model="form.preNum" :placeholder="$t('batchAddParkingSpace.prefixNumPlaceholder')"></el-input>
  6 + </el-form-item>
  7 +
  8 + <el-form-item :label="$t('batchAddParkingSpace.startNum')" prop="startNum"
  9 + :rules="[{ required: true, message: $t('batchAddParkingSpace.startNumPlaceholder'), trigger: 'blur' }]">
  10 + <el-input v-model="form.startNum" type="number"
  11 + :placeholder="$t('batchAddParkingSpace.startNumPlaceholder')"></el-input>
  12 + </el-form-item>
  13 +
  14 + <el-form-item :label="$t('batchAddParkingSpace.endNum')" prop="endNum"
  15 + :rules="[{ required: true, message: $t('batchAddParkingSpace.endNumPlaceholder'), trigger: 'blur' }]">
  16 + <el-input v-model="form.endNum" type="number"
  17 + :placeholder="$t('batchAddParkingSpace.endNumPlaceholder')"></el-input>
  18 + </el-form-item>
  19 +
  20 + <el-form-item :label="$t('batchAddParkingSpace.parkingLot')" prop="paId"
  21 + :rules="[{ required: true, message: $t('batchAddParkingSpace.parkingLotPlaceholder'), trigger: 'change' }]">
  22 + <el-select v-model="form.paId" :placeholder="$t('batchAddParkingSpace.parkingLotPlaceholder')" style="width:100%">
  23 + <el-option v-for="item in parkingAreas" :key="item.paId" :label="item.num" :value="item.paId"></el-option>
  24 + </el-select>
  25 + </el-form-item>
  26 +
  27 + <el-form-item :label="$t('batchAddParkingSpace.parkingSpaceType')" prop="parkingType"
  28 + :rules="[{ required: true, message: $t('batchAddParkingSpace.parkingSpaceTypePlaceholder'), trigger: 'change' }]">
  29 + <el-select v-model="form.parkingType" :placeholder="$t('batchAddParkingSpace.parkingSpaceTypePlaceholder')"
  30 + style="width:100%">
  31 + <template slot="prepend" v-for="item in parkingTypes" >
  32 + <el-option :label="item.name" :key="item.statusCd" :value="item.statusCd" v-if="item.statusCd !== '2'"></el-option>
  33 + </template>
  34 + </el-select>
  35 + </el-form-item>
  36 + </el-form>
  37 +
  38 + <div slot="footer" class="dialog-footer">
  39 + <el-button @click="visible = false">{{ $t('batchAddParkingSpace.cancel') }}</el-button>
  40 + <el-button type="primary" @click="batchSaveParkingSpace" :loading="saving">
  41 + {{ $t('batchAddParkingSpace.save') }}
  42 + </el-button>
  43 + </div>
  44 + </el-dialog>
  45 +</template>
  46 +
  47 +<script>
  48 +import { batchSaveParkingSpace } from '@/api/car/listParkingSpaceApi'
  49 +import { listParkingAreas } from '@/api/car/listParkingSpaceApi'
  50 +import { getDict } from '@/api/community/communityApi'
  51 +import { getCommunityId } from '@/api/community/communityApi'
  52 +
  53 +export default {
  54 + name: 'BatchAddParkingSpace',
  55 + data() {
  56 + return {
  57 + visible: false,
  58 + saving: false,
  59 + form: {
  60 + preNum: '',
  61 + startNum: '',
  62 + endNum: '',
  63 + paId: '',
  64 + parkingType: '1',
  65 + area: '1',
  66 + communityId: getCommunityId()
  67 + },
  68 + parkingTypes: [],
  69 + parkingAreas: []
  70 + }
  71 + },
  72 + methods: {
  73 + open() {
  74 + this.visible = true
  75 + this.loadParkingTypes()
  76 + this.loadParkingAreas()
  77 + },
  78 +
  79 + async loadParkingTypes() {
  80 + try {
  81 + const data = await getDict('parking_space', 'parking_type')
  82 + this.parkingTypes = data
  83 + } catch (error) {
  84 + this.$message.error(this.$t('common.loadDictError'))
  85 + }
  86 + },
  87 +
  88 + async loadParkingAreas() {
  89 + try {
  90 + const params = {
  91 + page: 1,
  92 + row: 50,
  93 + communityId: getCommunityId()
  94 + }
  95 + const res = await listParkingAreas(params)
  96 + this.parkingAreas = res.parkingAreas
  97 + } catch (error) {
  98 + this.$message.error(this.$t('common.loadError'))
  99 + }
  100 + },
  101 +
  102 + async batchSaveParkingSpace() {
  103 + try {
  104 + this.saving = true
  105 + await this.$refs.form.validate()
  106 +
  107 + // 验证结束编号大于开始编号
  108 + if (parseInt(this.form.endNum) < parseInt(this.form.startNum)) {
  109 + this.$message.error(this.$t('batchAddParkingSpace.endNumPlaceholder'))
  110 + return
  111 + }
  112 +
  113 + const res = await batchSaveParkingSpace(this.form)
  114 + if (res.code === 0) {
  115 + this.$message.success(this.$t('common.saveSuccess'))
  116 + this.$emit('success')
  117 + this.visible = false
  118 + } else {
  119 + this.$message.error(res.msg || this.$t('common.saveError'))
  120 + }
  121 + } catch (error) {
  122 + console.error('Validation failed:', error)
  123 + } finally {
  124 + this.saving = false
  125 + }
  126 + },
  127 +
  128 + closeDialog() {
  129 + this.$refs.form.resetFields()
  130 + this.form = {
  131 + preNum: '',
  132 + startNum: '',
  133 + endNum: '',
  134 + paId: '',
  135 + parkingType: '1',
  136 + area: '1',
  137 + communityId: getCommunityId()
  138 + }
  139 + }
  140 + }
  141 +}
  142 +</script>
0 \ No newline at end of file 143 \ No newline at end of file
src/components/car/chooseParkingArea.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('chooseParkingArea.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + >
  7 + <el-card>
  8 + <div slot="header">
  9 + <el-row :gutter="20">
  10 + <el-col :span="18"></el-col>
  11 + <el-col :span="6">
  12 + <el-input-group>
  13 + <el-input
  14 + v-model="searchForm.num"
  15 + :placeholder="$t('chooseParkingArea.parkingLotNumPlaceholder')"
  16 + ></el-input>
  17 + <el-button
  18 + slot="append"
  19 + type="primary"
  20 + @click="queryParkingAreas"
  21 + >
  22 + {{ $t('chooseParkingArea.query') }}
  23 + </el-button>
  24 + <el-button
  25 + type="primary"
  26 + @click="resetParkingAreas"
  27 + >
  28 + {{ $t('chooseParkingArea.reset') }}
  29 + </el-button>
  30 + </el-input-group>
  31 + </el-col>
  32 + </el-row>
  33 + </div>
  34 +
  35 + <el-table :data="parkingAreas" border>
  36 + <el-table-column prop="paId" :label="$t('chooseParkingArea.parkingLotId')" align="center"></el-table-column>
  37 + <el-table-column prop="num" :label="$t('chooseParkingArea.parkingLotNum')" align="center"></el-table-column>
  38 + <el-table-column prop="typeCd" :label="$t('chooseParkingArea.parkingLotType')" align="center"></el-table-column>
  39 + <el-table-column :label="$t('chooseParkingArea.operation')" align="center" width="120">
  40 + <template slot-scope="scope">
  41 + <el-button
  42 + type="primary"
  43 + size="mini"
  44 + @click="selectParkingArea(scope.row)"
  45 + >
  46 + {{ $t('chooseParkingArea.select') }}
  47 + </el-button>
  48 + </template>
  49 + </el-table-column>
  50 + </el-table>
  51 +
  52 + <el-pagination
  53 + @size-change="handleSizeChange"
  54 + @current-change="handlePageChange"
  55 + :current-page="pagination.current"
  56 + :page-sizes="[10, 20, 30, 50]"
  57 + :page-size="pagination.size"
  58 + layout="total, sizes, prev, pager, next, jumper"
  59 + :total="pagination.total"
  60 + style="margin-top:20px;text-align:right"
  61 + ></el-pagination>
  62 + </el-card>
  63 + </el-dialog>
  64 +</template>
  65 +
  66 +<script>
  67 +import { listParkingAreas } from '@/api/car/listParkingSpaceApi'
  68 +import { getCommunityId } from '@/api/community/communityApi'
  69 +
  70 +export default {
  71 + name: 'ChooseParkingArea',
  72 + data() {
  73 + return {
  74 + visible: false,
  75 + searchForm: {
  76 + num: ''
  77 + },
  78 + parkingAreas: [],
  79 + pagination: {
  80 + current: 1,
  81 + size: 10,
  82 + total: 0
  83 + }
  84 + }
  85 + },
  86 + methods: {
  87 + open() {
  88 + this.visible = true
  89 + this.loadParkingAreas()
  90 + },
  91 +
  92 + async loadParkingAreas() {
  93 + try {
  94 + const params = {
  95 + page: this.pagination.current,
  96 + row: this.pagination.size,
  97 + communityId: getCommunityId(),
  98 + num: this.searchForm.num
  99 + }
  100 +
  101 + const res = await listParkingAreas(params)
  102 + this.parkingAreas = res.data.parkingAreas
  103 + this.pagination.total = res.data.total
  104 + } catch (error) {
  105 + this.$message.error(this.$t('common.loadError'))
  106 + }
  107 + },
  108 +
  109 + selectParkingArea(row) {
  110 + this.$emit('choose', row)
  111 + this.visible = false
  112 + },
  113 +
  114 + queryParkingAreas() {
  115 + this.pagination.current = 1
  116 + this.loadParkingAreas()
  117 + },
  118 +
  119 + resetParkingAreas() {
  120 + this.searchForm.num = ''
  121 + this.queryParkingAreas()
  122 + },
  123 +
  124 + handlePageChange(page) {
  125 + this.pagination.current = page
  126 + this.loadParkingAreas()
  127 + },
  128 +
  129 + handleSizeChange(size) {
  130 + this.pagination.size = size
  131 + this.loadParkingAreas()
  132 + }
  133 + }
  134 +}
  135 +</script>
0 \ No newline at end of file 136 \ No newline at end of file
src/components/car/deleteParkingArea.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('parkingAreaManage.deleteTitle')" :visible.sync="visible" width="30%" center>
  3 + <div style="text-align: center">
  4 + <p>{{ $t('parkingAreaManage.deleteConfirm') }}</p>
  5 + <p style="font-weight: bold; color: #e6a23c; margin-top: 10px">
  6 + {{ deleteParkingAreaInfo.num }} ({{ parkingTypeLabel }})
  7 + </p>
  8 + </div>
  9 +
  10 + <div slot="footer" class="dialog-footer">
  11 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  12 + <el-button type="danger" @click="deleteParkingArea" :loading="deleting">
  13 + {{ $t('common.confirm') }}
  14 + </el-button>
  15 + </div>
  16 + </el-dialog>
  17 +</template>
  18 +
  19 +<script>
  20 +import { deleteParkingArea } from '@/api/car/parkingAreaManageApi'
  21 +import { getCommunityId } from '@/api/community/communityApi'
  22 +
  23 +export default {
  24 + name: 'DeleteParkingArea',
  25 + data() {
  26 + return {
  27 + visible: false,
  28 + deleting: false,
  29 + deleteParkingAreaInfo: {}
  30 + }
  31 + },
  32 + computed: {
  33 + parkingTypeLabel() {
  34 + return this.deleteParkingAreaInfo.typeCd === '1001'
  35 + ? this.$t('parkingAreaManage.aboveGround')
  36 + : this.$t('parkingAreaManage.underground')
  37 + }
  38 + },
  39 + methods: {
  40 + open(row) {
  41 + this.visible = true
  42 + this.deleteParkingAreaInfo = { ...row }
  43 + },
  44 +
  45 + async deleteParkingArea() {
  46 + try {
  47 + this.deleting = true
  48 + const params = {
  49 + paId: this.deleteParkingAreaInfo.paId,
  50 + communityId: getCommunityId()
  51 + }
  52 +
  53 + await deleteParkingArea(params)
  54 + this.$message.success(this.$t('parkingAreaManage.deleteSuccess'))
  55 + this.visible = false
  56 + this.$emit('success')
  57 + } catch (error) {
  58 + console.error('删除停车场失败:', error)
  59 + this.$message.error(this.$t('parkingAreaManage.deleteFailed'))
  60 + } finally {
  61 + this.deleting = false
  62 + }
  63 + }
  64 + }
  65 +}
  66 +</script>
0 \ No newline at end of file 67 \ No newline at end of file
src/components/car/deleteParkingSpace.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('deleteParkingSpace.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + center
  7 + >
  8 + <div style="text-align:center">
  9 + <p>{{ $t('deleteParkingSpace.confirmDelete') }}</p>
  10 + </div>
  11 +
  12 + <div slot="footer" class="dialog-footer">
  13 + <el-button @click="visible = false">{{ $t('deleteParkingSpace.cancel') }}</el-button>
  14 + <el-button type="danger" @click="confirmDelete" :loading="deleting">
  15 + {{ $t('deleteParkingSpace.confirm') }}
  16 + </el-button>
  17 + </div>
  18 + </el-dialog>
  19 +</template>
  20 +
  21 +<script>
  22 +import { deleteParkingSpace } from '@/api/car/listParkingSpaceApi'
  23 +import { getCommunityId } from '@/api/community/communityApi'
  24 +
  25 +export default {
  26 + name: 'DeleteParkingSpace',
  27 + data() {
  28 + return {
  29 + visible: false,
  30 + deleting: false,
  31 + currentParkingSpace: null
  32 + }
  33 + },
  34 + methods: {
  35 + open(row) {
  36 + this.currentParkingSpace = { ...row, communityId: getCommunityId() }
  37 + this.visible = true
  38 + },
  39 +
  40 + async confirmDelete() {
  41 + try {
  42 + this.deleting = true
  43 + const res = await deleteParkingSpace(this.currentParkingSpace)
  44 + if (res.code === 0) {
  45 + this.$message.success(this.$t('common.deleteSuccess'))
  46 + this.$emit('success')
  47 + this.visible = false
  48 + } else {
  49 + this.$message.error(res.msg || this.$t('common.deleteError'))
  50 + }
  51 + } catch (error) {
  52 + this.$message.error(this.$t('common.deleteError'))
  53 + } finally {
  54 + this.deleting = false
  55 + }
  56 + }
  57 + }
  58 +}
  59 +</script>
0 \ No newline at end of file 60 \ No newline at end of file
src/components/car/editParkingArea.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('parkingAreaManage.editTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="closeDialog"
  7 + >
  8 + <el-form ref="form" :model="editParkingAreaInfo" label-width="150px" label-position="left">
  9 + <el-form-item
  10 + :label="$t('parkingAreaManage.parkingNum')"
  11 + prop="num"
  12 + :rules="[{ required: true, message: $t('parkingAreaManage.numRequired'), trigger: 'blur' }]"
  13 + >
  14 + <el-input
  15 + v-model.trim="editParkingAreaInfo.num"
  16 + :placeholder="$t('parkingAreaManage.inputParkingNum')"
  17 + />
  18 + </el-form-item>
  19 +
  20 + <el-form-item
  21 + :label="$t('parkingAreaManage.parkingType')"
  22 + prop="typeCd"
  23 + :rules="[{ required: true, message: $t('parkingAreaManage.typeRequired'), trigger: 'change' }]"
  24 + >
  25 + <el-select
  26 + v-model="editParkingAreaInfo.typeCd"
  27 + :placeholder="$t('parkingAreaManage.selectParkingType')"
  28 + style="width: 100%"
  29 + >
  30 + <el-option
  31 + v-for="item in parkingTypes"
  32 + :key="item.value"
  33 + :label="item.label"
  34 + :value="item.value"
  35 + />
  36 + </el-select>
  37 + </el-form-item>
  38 +
  39 + <div v-for="(item, index) in editParkingAreaInfo.attrs" :key="index">
  40 + <el-form-item
  41 + v-if="item.specType === '2233'"
  42 + :label="item.specName"
  43 + :prop="`attrs[${index}].value`"
  44 + :rules="item.required ? [{ required: true, message: $t('common.required'), trigger: 'blur' }] : []"
  45 + >
  46 + <el-input
  47 + v-model="item.value"
  48 + :placeholder="item.specHoldplace"
  49 + />
  50 + </el-form-item>
  51 +
  52 + <el-form-item
  53 + v-if="item.specType === '3344'"
  54 + :label="item.specName"
  55 + :prop="`attrs[${index}].value`"
  56 + :rules="item.required ? [{ required: true, message: $t('common.required'), trigger: 'change' }] : []"
  57 + >
  58 + <el-select
  59 + v-model="item.value"
  60 + :placeholder="item.specHoldplace"
  61 + style="width: 100%"
  62 + >
  63 + <el-option
  64 + v-for="value in item.values"
  65 + :key="value.value"
  66 + :label="value.valueName"
  67 + :value="value.value"
  68 + />
  69 + </el-select>
  70 + </el-form-item>
  71 + </div>
  72 +
  73 + <el-form-item :label="$t('parkingAreaManage.remark')">
  74 + <el-input
  75 + v-model="editParkingAreaInfo.remark"
  76 + type="textarea"
  77 + :rows="3"
  78 + :placeholder="$t('parkingAreaManage.remarkPlaceholder')"
  79 + />
  80 + </el-form-item>
  81 + </el-form>
  82 +
  83 + <div slot="footer" class="dialog-footer">
  84 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  85 + <el-button type="primary" @click="editParkingArea" :loading="saving">
  86 + {{ $t('common.save') }}
  87 + </el-button>
  88 + </div>
  89 + </el-dialog>
  90 +</template>
  91 +
  92 +<script>
  93 +import { updateParkingArea } from '@/api/car/parkingAreaManageApi'
  94 +import { getCommunityId } from '@/api/community/communityApi'
  95 +
  96 +export default {
  97 + name: 'EditParkingArea',
  98 + data() {
  99 + return {
  100 + visible: false,
  101 + saving: false,
  102 + editParkingAreaInfo: {
  103 + paId: '',
  104 + num: '',
  105 + typeCd: '',
  106 + remark: '',
  107 + attrs: []
  108 + },
  109 + parkingTypes: [
  110 + { value: '1001', label: this.$t('parkingAreaManage.aboveGround') },
  111 + { value: '2001', label: this.$t('parkingAreaManage.underground') }
  112 + ]
  113 + }
  114 + },
  115 + methods: {
  116 + open(row) {
  117 + this.visible = true
  118 + this.editParkingAreaInfo = JSON.parse(JSON.stringify(row))
  119 + this.$nextTick(() => {
  120 + this.$refs.form.clearValidate()
  121 + })
  122 + },
  123 +
  124 + closeDialog() {
  125 + this.$refs.form.resetFields()
  126 + },
  127 +
  128 + async editParkingArea() {
  129 + this.$refs.form.validate(async valid => {
  130 + if (!valid) return
  131 +
  132 + try {
  133 + this.saving = true
  134 + const params = {
  135 + ...this.editParkingAreaInfo,
  136 + communityId: getCommunityId()
  137 + }
  138 +
  139 + await updateParkingArea(params)
  140 + this.$message.success(this.$t('parkingAreaManage.editSuccess'))
  141 + this.visible = false
  142 + this.$emit('success')
  143 + } catch (error) {
  144 + console.error('修改停车场失败:', error)
  145 + this.$message.error(this.$t('parkingAreaManage.editFailed'))
  146 + } finally {
  147 + this.saving = false
  148 + }
  149 + })
  150 + }
  151 + }
  152 +}
  153 +</script>
0 \ No newline at end of file 154 \ No newline at end of file
src/components/car/editParkingSpace.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('editParkingSpace.title')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="closeDialog"
  7 + >
  8 + <el-form :model="form" ref="form" label-width="120px">
  9 + <el-form-item :label="$t('editParkingSpace.parkingSpaceNum')" prop="num"
  10 + :rules="[{ required: true, message: $t('editParkingSpace.parkingSpaceNumPlaceholder'), trigger: 'blur' }]"
  11 + >
  12 + <el-input
  13 + v-model="form.num"
  14 + :placeholder="$t('editParkingSpace.parkingSpaceNumPlaceholder')"
  15 + :disabled="form.parkingType === '2'"
  16 + ></el-input>
  17 + </el-form-item>
  18 +
  19 + <el-form-item :label="$t('editParkingSpace.parkingLot')" prop="paId"
  20 + :rules="[{ required: true, message: $t('editParkingSpace.parkingLotPlaceholder'), trigger: 'change' }]"
  21 + >
  22 + <el-select
  23 + v-model="form.paId"
  24 + :placeholder="$t('editParkingSpace.parkingLotPlaceholder')"
  25 + style="width:100%"
  26 + >
  27 + <el-option
  28 + v-for="item in parkingAreas"
  29 + :key="item.paId"
  30 + :label="item.num"
  31 + :value="item.paId"
  32 + ></el-option>
  33 + </el-select>
  34 + </el-form-item>
  35 +
  36 + <el-form-item :label="$t('editParkingSpace.parkingSpaceType')" prop="parkingType"
  37 + :rules="[{ required: true, message: $t('editParkingSpace.parkingSpaceTypePlaceholder'), trigger: 'change' }]"
  38 + >
  39 + <el-select
  40 + v-model="form.parkingType"
  41 + :placeholder="$t('editParkingSpace.parkingSpaceTypePlaceholder')"
  42 + style="width:100%"
  43 + :disabled="form.parkingType === '2'"
  44 + >
  45 + <el-option
  46 + v-for="item in parkingTypes"
  47 + :key="item.statusCd"
  48 + :label="item.name"
  49 + :value="item.statusCd"
  50 + ></el-option>
  51 + </el-select>
  52 + </el-form-item>
  53 +
  54 + <el-form-item :label="$t('editParkingSpace.area')" prop="area"
  55 + :rules="[
  56 + { required: true, message: $t('editParkingSpace.areaPlaceholder'), trigger: 'blur' },
  57 + { pattern: /^\d+(\.\d{1,2})?$/, message: $t('editParkingSpace.areaPlaceholder'), trigger: 'blur' }
  58 + ]"
  59 + >
  60 + <el-input
  61 + v-model="form.area"
  62 + type="number"
  63 + :placeholder="$t('editParkingSpace.areaPlaceholder')"
  64 + ></el-input>
  65 + </el-form-item>
  66 +
  67 + <el-form-item :label="$t('editParkingSpace.remark')" prop="remark">
  68 + <el-input
  69 + v-model="form.remark"
  70 + type="textarea"
  71 + :placeholder="$t('editParkingSpace.remarkPlaceholder')"
  72 + ></el-input>
  73 + </el-form-item>
  74 + </el-form>
  75 +
  76 + <div slot="footer" class="dialog-footer">
  77 + <el-button @click="visible = false">{{ $t('editParkingSpace.cancel') }}</el-button>
  78 + <el-button type="primary" @click="editParkingSpace" :loading="saving">
  79 + {{ $t('editParkingSpace.save') }}
  80 + </el-button>
  81 + </div>
  82 + </el-dialog>
  83 +</template>
  84 +
  85 +<script>
  86 +import { editParkingSpace } from '@/api/car/listParkingSpaceApi'
  87 +import { listParkingAreas } from '@/api/car/listParkingSpaceApi'
  88 +import { getDict } from '@/api/community/communityApi'
  89 +import { getCommunityId } from '@/api/community/communityApi'
  90 +
  91 +export default {
  92 + name: 'EditParkingSpace',
  93 + data() {
  94 + return {
  95 + visible: false,
  96 + saving: false,
  97 + form: {
  98 + psId: '',
  99 + num: '',
  100 + paId: '',
  101 + parkingType: '',
  102 + area: '',
  103 + remark: '',
  104 + communityId: getCommunityId()
  105 + },
  106 + parkingTypes: [],
  107 + parkingAreas: []
  108 + }
  109 + },
  110 + methods: {
  111 + open(row) {
  112 + this.form = { ...row, communityId: getCommunityId() }
  113 + this.visible = true
  114 + this.loadParkingTypes()
  115 + this.loadParkingAreas()
  116 + },
  117 +
  118 + async loadParkingTypes() {
  119 + try {
  120 + const data = await getDict('parking_space', 'parking_type')
  121 + this.parkingTypes = data
  122 + } catch (error) {
  123 + this.$message.error(this.$t('common.loadDictError'))
  124 + }
  125 + },
  126 +
  127 + async loadParkingAreas() {
  128 + try {
  129 + const params = {
  130 + page: 1,
  131 + row: 50,
  132 + communityId: getCommunityId()
  133 + }
  134 + const res = await listParkingAreas(params)
  135 + this.parkingAreas = res.parkingAreas
  136 + } catch (error) {
  137 + this.$message.error(this.$t('common.loadError'))
  138 + }
  139 + },
  140 +
  141 + async editParkingSpace() {
  142 + try {
  143 + this.saving = true
  144 + await this.$refs.form.validate()
  145 +
  146 + const res = await editParkingSpace(this.form)
  147 + if (res.code === 0) {
  148 + this.$message.success(this.$t('common.saveSuccess'))
  149 + this.$emit('success')
  150 + this.visible = false
  151 + } else {
  152 + this.$message.error(res.msg || this.$t('common.saveError'))
  153 + }
  154 + } catch (error) {
  155 + console.error('Validation failed:', error)
  156 + } finally {
  157 + this.saving = false
  158 + }
  159 + },
  160 +
  161 + closeDialog() {
  162 + this.$refs.form.resetFields()
  163 + this.form = {
  164 + psId: '',
  165 + num: '',
  166 + paId: '',
  167 + parkingType: '',
  168 + area: '',
  169 + remark: '',
  170 + communityId: getCommunityId()
  171 + }
  172 + }
  173 + }
  174 +}
  175 +</script>
0 \ No newline at end of file 176 \ No newline at end of file
src/i18n/commonLang.js
@@ -42,6 +42,7 @@ export const messages = { @@ -42,6 +42,7 @@ export const messages = {
42 import: 'Import', 42 import: 'Import',
43 remark: 'Remark', 43 remark: 'Remark',
44 hour:'hour', 44 hour:'hour',
  45 + more:'More',
45 } 46 }
46 }, 47 },
47 zh: { 48 zh: {
@@ -87,6 +88,7 @@ export const messages = { @@ -87,6 +88,7 @@ export const messages = {
87 import: '导入', 88 import: '导入',
88 remark: '备注', 89 remark: '备注',
89 hour:'时', 90 hour:'时',
  91 + more:'更多',
90 } 92 }
91 } 93 }
92 } 94 }
93 \ No newline at end of file 95 \ No newline at end of file
src/i18n/index.js
@@ -144,6 +144,8 @@ import { messages as invoiceApplyMessages } from &#39;../views/fee/invoiceApplyLang&#39; @@ -144,6 +144,8 @@ import { messages as invoiceApplyMessages } from &#39;../views/fee/invoiceApplyLang&#39;
144 import { messages as ownerApplyInvoiceMessages } from '../views/fee/ownerApplyInvoiceLang' 144 import { messages as ownerApplyInvoiceMessages } from '../views/fee/ownerApplyInvoiceLang'
145 import { messages as invoiceApplyDetailMessages } from '../views/fee/invoiceApplyDetailLang' 145 import { messages as invoiceApplyDetailMessages } from '../views/fee/invoiceApplyDetailLang'
146 import { messages as feeConfigDetailMessages } from '../views/fee/feeConfigDetailLang' 146 import { messages as feeConfigDetailMessages } from '../views/fee/feeConfigDetailLang'
  147 +import { messages as parkingAreaManageMessages } from '../views/car/parkingAreaManageLang'
  148 +import { messages as listParkingSpaceMessages } from '../views/car/listParkingSpaceLang'
147 149
148 Vue.use(VueI18n) 150 Vue.use(VueI18n)
149 151
@@ -292,6 +294,8 @@ const messages = { @@ -292,6 +294,8 @@ const messages = {
292 ...ownerApplyInvoiceMessages.en, 294 ...ownerApplyInvoiceMessages.en,
293 ...invoiceApplyDetailMessages.en, 295 ...invoiceApplyDetailMessages.en,
294 ...feeConfigDetailMessages.en, 296 ...feeConfigDetailMessages.en,
  297 + ...parkingAreaManageMessages.en,
  298 + ...listParkingSpaceMessages.en,
295 }, 299 },
296 zh: { 300 zh: {
297 ...loginMessages.zh, 301 ...loginMessages.zh,
@@ -436,6 +440,8 @@ const messages = { @@ -436,6 +440,8 @@ const messages = {
436 ...ownerApplyInvoiceMessages.zh, 440 ...ownerApplyInvoiceMessages.zh,
437 ...invoiceApplyDetailMessages.zh, 441 ...invoiceApplyDetailMessages.zh,
438 ...feeConfigDetailMessages.zh, 442 ...feeConfigDetailMessages.zh,
  443 + ...parkingAreaManageMessages.zh,
  444 + ...listParkingSpaceMessages.zh,
439 } 445 }
440 } 446 }
441 447
src/router/index.js
@@ -716,6 +716,16 @@ const routes = [ @@ -716,6 +716,16 @@ const routes = [
716 name: '/views/fee/feeConfigDetail', 716 name: '/views/fee/feeConfigDetail',
717 component: () => import('@/views/fee/feeConfigDetailList.vue') 717 component: () => import('@/views/fee/feeConfigDetailList.vue')
718 }, 718 },
  719 + {
  720 + path:'/pages/property/parkingAreaManage',
  721 + name:'/pages/property/parkingAreaManage',
  722 + component: () => import('@/views/car/parkingAreaManageList.vue')
  723 + },
  724 + {
  725 + path:'/pages/property/listParkingSpace',
  726 + name:'/pages/property/listParkingSpace',
  727 + component: () => import('@/views/car/listParkingSpaceList.vue')
  728 + },
719 // 其他子路由可以在这里添加 729 // 其他子路由可以在这里添加
720 ] 730 ]
721 }, 731 },
src/views/car/listParkingSpaceLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + listParkingSpace: {
  4 + queryCondition: "Query Conditions",
  5 + parkingLotPlaceholder: "Please select parking lot",
  6 + select: "Select",
  7 + parkingSpaceNumPlaceholder: "Please enter parking space number",
  8 + parkingSpaceStatePlaceholder: "Required, select parking space state",
  9 + forSale: "For Sale",
  10 + forRent: "For Rent",
  11 + free: "Free",
  12 + query: "Query",
  13 + reset: "Reset",
  14 + parkingSpaceIdPlaceholder: "Please enter parking space ID",
  15 + parkingSpaceInfo: "Parking Space Information",
  16 + batchAdd: "Batch Add",
  17 + add: "Add",
  18 + parkingLot: "Parking Lot",
  19 + parkingSpace: "Parking Space",
  20 + parkingSpaceState: "Parking Space State",
  21 + parkingSpaceType: "Parking Space Type",
  22 + area: "Area",
  23 + createTime: "Create Time",
  24 + operation: "Operation",
  25 + modify: "Modify",
  26 + delete: "Delete"
  27 + },
  28 + addParkingSpace: {
  29 + title: "Add",
  30 + parkingSpaceNum: "Parking Space Number",
  31 + parkingSpaceNumPlaceholder: "Required, enter parking space number",
  32 + parkingLot: "Parking Lot",
  33 + parkingLotPlaceholder: "Required, select parking lot",
  34 + parkingSpaceType: "Parking Space Type",
  35 + parkingSpaceTypePlaceholder: "Required, select parking space type",
  36 + area: "Area",
  37 + areaPlaceholder: "Required, enter area, e.g. 30.09",
  38 + remark: "Remark",
  39 + remarkPlaceholder: "Optional, enter remark",
  40 + save: "Save",
  41 + cancel: "Cancel"
  42 + },
  43 + editParkingSpace: {
  44 + title: "Edit Parking Space",
  45 + parkingSpaceNum: "Parking Space Number",
  46 + parkingSpaceNumPlaceholder: "Required, enter parking space number",
  47 + parkingLot: "Parking Lot",
  48 + parkingLotPlaceholder: "Required, select parking lot",
  49 + parkingSpaceType: "Parking Space Type",
  50 + area: "Area",
  51 + areaPlaceholder: "Required, enter area, e.g. 30.09",
  52 + remark: "Remark",
  53 + remarkPlaceholder: "Optional, enter remark",
  54 + save: "Save",
  55 + cancel: "Cancel"
  56 + },
  57 + deleteParkingSpace: {
  58 + title: "Confirm Operation",
  59 + confirmDelete: "Confirm to delete?",
  60 + cancel: "Cancel",
  61 + confirm: "Confirm Delete"
  62 + },
  63 + chooseParkingArea: {
  64 + title: "Select Parking Lot",
  65 + parkingLotNumPlaceholder: "Enter parking lot number",
  66 + query: "Query",
  67 + reset: "Reset",
  68 + parkingLotId: "Parking Lot ID",
  69 + parkingLotNum: "Parking Lot Number",
  70 + parkingLotType: "Parking Lot Type",
  71 + operation: "Operation",
  72 + select: "Select"
  73 + },
  74 + batchAddParkingSpace: {
  75 + title: "Add",
  76 + prefixNum: "Number Prefix",
  77 + prefixNumPlaceholder: "Optional, prefix letters when not pure numbers, e.g. A for A12",
  78 + startNum: "Start Number",
  79 + startNumPlaceholder: "Required, enter starting number",
  80 + endNum: "End Number",
  81 + endNumPlaceholder: "Required, enter ending number",
  82 + parkingLot: "Parking Lot",
  83 + parkingLotPlaceholder: "Required, select parking lot",
  84 + parkingSpaceType: "Parking Space Type",
  85 + parkingSpaceTypePlaceholder: "Required, select parking space type",
  86 + save: "Save",
  87 + cancel: "Cancel"
  88 + }
  89 + },
  90 + zh: {
  91 + listParkingSpace: {
  92 + queryCondition: "查询条件",
  93 + parkingLotPlaceholder: "请选择停车场",
  94 + select: "选择",
  95 + parkingSpaceNumPlaceholder: "请填写车位编号",
  96 + parkingSpaceStatePlaceholder: "必填,请选择车位状态",
  97 + forSale: "出售",
  98 + forRent: "出租",
  99 + free: "空闲",
  100 + query: "查询",
  101 + reset: "重置",
  102 + parkingSpaceIdPlaceholder: "请填写车位ID",
  103 + parkingSpaceInfo: "停车位信息",
  104 + batchAdd: "批量添加",
  105 + add: "添加",
  106 + parkingLot: "停车场",
  107 + parkingSpace: "车位",
  108 + parkingSpaceState: "车位状态",
  109 + parkingSpaceType: "车位类型",
  110 + area: "面积",
  111 + createTime: "创建时间",
  112 + operation: "操作",
  113 + modify: "修改",
  114 + delete: "删除"
  115 + },
  116 + addParkingSpace: {
  117 + title: "添加",
  118 + parkingSpaceNum: "车位编码",
  119 + parkingSpaceNumPlaceholder: "必填,请填写车位编码",
  120 + parkingLot: "停车场",
  121 + parkingLotPlaceholder: "必填,请选择停车场",
  122 + parkingSpaceType: "车位类型",
  123 + parkingSpaceTypePlaceholder: "必填,请选择车位类型",
  124 + area: "面积",
  125 + areaPlaceholder: "必填,请填写面积,如30.09",
  126 + remark: "备注",
  127 + remarkPlaceholder: "可填,请填写备注",
  128 + save: "保存",
  129 + cancel: "取消"
  130 + },
  131 + editParkingSpace: {
  132 + title: "修改车位",
  133 + parkingSpaceNum: "车位编码",
  134 + parkingSpaceNumPlaceholder: "必填,请填写车位编码",
  135 + parkingLot: "停车场",
  136 + parkingLotPlaceholder: "必填,请选择停车场",
  137 + parkingSpaceType: "车位类型",
  138 + area: "面积",
  139 + areaPlaceholder: "必填,请填写面积,如30.09",
  140 + remark: "备注",
  141 + remarkPlaceholder: "可填,请填写备注",
  142 + save: "保存",
  143 + cancel: "取消"
  144 + },
  145 + deleteParkingSpace: {
  146 + title: "请确认您的操作",
  147 + confirmDelete: "确认是否删除!",
  148 + cancel: "点错了",
  149 + confirm: "确认删除"
  150 + },
  151 + chooseParkingArea: {
  152 + title: "选择停车场",
  153 + parkingLotNumPlaceholder: "输入停车场编号",
  154 + query: "查询",
  155 + reset: "重置",
  156 + parkingLotId: "停车场ID",
  157 + parkingLotNum: "停车场编号",
  158 + parkingLotType: "停车场类型",
  159 + operation: "操作",
  160 + select: "选择"
  161 + },
  162 + batchAddParkingSpace: {
  163 + title: "添加",
  164 + prefixNum: "编号前缀",
  165 + prefixNumPlaceholder: "选填,不是纯数字时前面字母 如A12 时填写A",
  166 + startNum: "开始编号",
  167 + startNumPlaceholder: "必填,请填写编码中数字部分开始编号",
  168 + endNum: "结束编号",
  169 + endNumPlaceholder: "必填,请填写编码中数字部分结束编号",
  170 + parkingLot: "停车场",
  171 + parkingLotPlaceholder: "必填,请选择停车场",
  172 + parkingSpaceType: "车位类型",
  173 + parkingSpaceTypePlaceholder: "必填,请选择车位类型",
  174 + save: "保存",
  175 + cancel: "取消"
  176 + }
  177 + }
  178 +}
0 \ No newline at end of file 179 \ No newline at end of file
src/views/car/listParkingSpaceList.vue 0 → 100644
  1 +<template>
  2 + <div class="parking-space-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="24">
  5 + <el-card class="box-card">
  6 + <div slot="header" class=" flex justify-between">
  7 + <span>{{ $t('listParkingSpace.queryCondition') }}</span>
  8 + <div class="ibox-tools" style="">
  9 + <el-button type="text" @click="toggleMoreCondition">
  10 + {{ listParkingSpaceInfo.moreCondition ? $t('common.hide') : $t('common.more') }}
  11 + </el-button>
  12 + </div>
  13 + </div>
  14 + <div class="search-content">
  15 + <el-row :gutter="20">
  16 + <el-col :sm="4">
  17 + <el-input-group>
  18 + <el-input v-model="listParkingSpaceInfo.conditions.areaNum"
  19 + :placeholder="$t('listParkingSpace.parkingLotPlaceholder')"></el-input>
  20 + </el-input-group>
  21 + </el-col>
  22 + <el-col :sm="2">
  23 + <el-input-group>
  24 + <el-button slot="append" type="primary" @click="openChooseParkingArea">
  25 + <i class="el-icon-search"></i>
  26 + {{ $t('listParkingSpace.select') }}
  27 + </el-button>
  28 + </el-input-group>
  29 + </el-col>
  30 + <el-col :sm="6">
  31 + <el-input v-model.trim="listParkingSpaceInfo.num"
  32 + :placeholder="$t('listParkingSpace.parkingSpaceNumPlaceholder')"></el-input>
  33 + </el-col>
  34 + <el-col :sm="6">
  35 + <el-select v-model="listParkingSpaceInfo.conditions.state"
  36 + :placeholder="$t('listParkingSpace.parkingSpaceStatePlaceholder')" style="width:100%">
  37 + <el-option value="" :label="$t('listParkingSpace.parkingSpaceStatePlaceholder')"></el-option>
  38 + <el-option value="S" :label="$t('listParkingSpace.forSale')"></el-option>
  39 + <el-option value="H" :label="$t('listParkingSpace.forRent')"></el-option>
  40 + <el-option value="F" :label="$t('listParkingSpace.free')"></el-option>
  41 + </el-select>
  42 + </el-col>
  43 + <el-col :sm="6">
  44 + <el-button type="primary" @click="queryParkingSpaceMethod">
  45 + <i class="el-icon-search"></i>
  46 + {{ $t('listParkingSpace.query') }}
  47 + </el-button>
  48 + <el-button @click="resetParkingSpaceMethod">
  49 + <i class="el-icon-refresh"></i>
  50 + {{ $t('listParkingSpace.reset') }}
  51 + </el-button>
  52 + </el-col>
  53 + </el-row>
  54 +
  55 + <el-row v-show="listParkingSpaceInfo.moreCondition" :gutter="20" style="margin-top:15px">
  56 + <el-col :sm="6">
  57 + <el-input v-model.trim="listParkingSpaceInfo.conditions.psId"
  58 + :placeholder="$t('listParkingSpace.parkingSpaceIdPlaceholder')"></el-input>
  59 + </el-col>
  60 + </el-row>
  61 + </div>
  62 + </el-card>
  63 + </el-col>
  64 + </el-row>
  65 +
  66 + <el-row :gutter="20" style="margin-top:20px">
  67 + <el-col :span="24">
  68 + <el-card class="box-card">
  69 + <div slot="header" class="flex justify-between">
  70 + <span>{{ $t('listParkingSpace.parkingSpaceInfo') }}</span>
  71 + <div style="float: right;">
  72 + <el-button type="primary" size="small" @click="openBatchAddParkingSpaceModal">
  73 + <i class="el-icon-plus"></i>
  74 + {{ $t('listParkingSpace.batchAdd') }}
  75 + </el-button>
  76 + <el-button type="primary" size="small" @click="openAddParkingSpaceModal">
  77 + <i class="el-icon-plus"></i>
  78 + {{ $t('listParkingSpace.add') }}
  79 + </el-button>
  80 + </div>
  81 + </div>
  82 +
  83 + <el-table :data="listParkingSpaceInfo.parkingSpaces" border style="width: 100%" v-loading="loading">
  84 + <el-table-column prop="areaNum" :label="$t('listParkingSpace.parkingLot')" align="center"></el-table-column>
  85 + <el-table-column prop="num" :label="$t('listParkingSpace.parkingSpace')" align="center"></el-table-column>
  86 + <el-table-column :label="$t('listParkingSpace.parkingSpaceState')" align="center">
  87 + <template slot-scope="scope">
  88 + {{ viewParkingSpaceState(scope.row.state) }}
  89 + </template>
  90 + </el-table-column>
  91 + <el-table-column prop="parkingTypeName" :label="$t('listParkingSpace.parkingSpaceType')"
  92 + align="center"></el-table-column>
  93 + <el-table-column prop="area" :label="$t('listParkingSpace.area')" align="center"></el-table-column>
  94 + <el-table-column prop="createTime" :label="$t('listParkingSpace.createTime')"
  95 + align="center"></el-table-column>
  96 + <el-table-column :label="$t('listParkingSpace.operation')" align="center" width="200">
  97 + <template slot-scope="scope">
  98 + <el-button-group>
  99 + <el-button size="mini" type="primary" @click="openEditParkingSpaceModel(scope.row)">
  100 + {{ $t('listParkingSpace.modify') }}
  101 + </el-button>
  102 + <el-button size="mini" type="danger" @click="openDelParkingSpaceModel(scope.row)">
  103 + {{ $t('listParkingSpace.delete') }}
  104 + </el-button>
  105 + </el-button-group>
  106 + </template>
  107 + </el-table-column>
  108 + </el-table>
  109 +
  110 + <el-pagination @size-change="handleSizeChange" @current-change="handlePageChange"
  111 + :current-page="listParkingSpaceInfo.currentPage" :page-sizes="[10, 20, 30, 50]"
  112 + :page-size="listParkingSpaceInfo.pageSize" layout="total, sizes, prev, pager, next, jumper"
  113 + :total="listParkingSpaceInfo.total" style="margin-top:20px;text-align:right"></el-pagination>
  114 + </el-card>
  115 + </el-col>
  116 + </el-row>
  117 +
  118 + <!-- 子组件 -->
  119 + <add-parking-space ref="addParkingSpace" @success="handleAddSuccess" />
  120 + <edit-parking-space ref="editParkingSpace" @success="handleEditSuccess" />
  121 + <delete-parking-space ref="deleteParkingSpace" @success="handleDeleteSuccess" />
  122 + <choose-parking-area ref="chooseParkingArea" @choose="handleChooseParkingArea" />
  123 + <batch-add-parking-space ref="batchAddParkingSpace" @success="handleBatchAddSuccess" />
  124 + </div>
  125 +</template>
  126 +
  127 +<script>
  128 +import { listParkingSpaces } from '@/api/car/listParkingSpaceApi'
  129 +import { getCommunityId } from '@/api/community/communityApi'
  130 +import AddParkingSpace from '@/components/car/addParkingSpace'
  131 +import EditParkingSpace from '@/components/car/editParkingSpace'
  132 +import DeleteParkingSpace from '@/components/car/deleteParkingSpace'
  133 +import ChooseParkingArea from '@/components/car/chooseParkingArea'
  134 +import BatchAddParkingSpace from '@/components/car/batchAddParkingSpace'
  135 +
  136 +export default {
  137 + name: 'ListParkingSpace',
  138 + components: {
  139 + AddParkingSpace,
  140 + EditParkingSpace,
  141 + DeleteParkingSpace,
  142 + ChooseParkingArea,
  143 + BatchAddParkingSpace
  144 + },
  145 + data() {
  146 + return {
  147 + loading: false,
  148 + listParkingSpaceInfo: {
  149 + parkingSpaces: [],
  150 + total: 0,
  151 + currentPage: 1,
  152 + pageSize: 10,
  153 + num: '',
  154 + moreCondition: false,
  155 + conditions: {
  156 + psId: '',
  157 + area: '',
  158 + paId: '',
  159 + areaNum: '',
  160 + state: ''
  161 + }
  162 + }
  163 + }
  164 + },
  165 + created() {
  166 + this.loadParkingSpaceData()
  167 + },
  168 + methods: {
  169 + async loadParkingSpaceData() {
  170 + try {
  171 + this.loading = true
  172 + const params = {
  173 + page: this.listParkingSpaceInfo.currentPage,
  174 + row: this.listParkingSpaceInfo.pageSize,
  175 + communityId: getCommunityId(),
  176 + num: this.listParkingSpaceInfo.num,
  177 + psId: this.listParkingSpaceInfo.conditions.psId,
  178 + area: this.listParkingSpaceInfo.conditions.area,
  179 + paId: this.listParkingSpaceInfo.conditions.paId,
  180 + state: this.listParkingSpaceInfo.conditions.state
  181 + }
  182 +
  183 + const res = await listParkingSpaces(params)
  184 + this.listParkingSpaceInfo.parkingSpaces = res.parkingSpaces
  185 + this.listParkingSpaceInfo.total = res.total
  186 + } catch (error) {
  187 + this.$message.error(this.$t('common.loadError'))
  188 + } finally {
  189 + this.loading = false
  190 + }
  191 + },
  192 +
  193 + viewParkingSpaceState(state) {
  194 + if (state === 'S') return this.$t('listParkingSpace.forSale')
  195 + if (state === 'H') return this.$t('listParkingSpace.forRent')
  196 + if (state === 'F') return this.$t('listParkingSpace.free')
  197 + return 'Unknown'
  198 + },
  199 +
  200 + toggleMoreCondition() {
  201 + this.listParkingSpaceInfo.moreCondition = !this.listParkingSpaceInfo.moreCondition
  202 + },
  203 +
  204 + queryParkingSpaceMethod() {
  205 + this.listParkingSpaceInfo.currentPage = 1
  206 + this.loadParkingSpaceData()
  207 + },
  208 +
  209 + resetParkingSpaceMethod() {
  210 + this.listParkingSpaceInfo.conditions = {
  211 + psId: '',
  212 + area: '',
  213 + paId: '',
  214 + areaNum: '',
  215 + state: ''
  216 + }
  217 + this.listParkingSpaceInfo.num = ''
  218 + this.loadParkingSpaceData()
  219 + },
  220 +
  221 + openChooseParkingArea() {
  222 + this.$refs.chooseParkingArea.open()
  223 + },
  224 +
  225 + openAddParkingSpaceModal() {
  226 + this.$refs.addParkingSpace.open()
  227 + },
  228 +
  229 + openEditParkingSpaceModel(row) {
  230 + this.$refs.editParkingSpace.open(row)
  231 + },
  232 +
  233 + openDelParkingSpaceModel(row) {
  234 + this.$refs.deleteParkingSpace.open(row)
  235 + },
  236 +
  237 + openBatchAddParkingSpaceModal() {
  238 + this.$refs.batchAddParkingSpace.open()
  239 + },
  240 +
  241 + handleChooseParkingArea(parkingArea) {
  242 + this.listParkingSpaceInfo.conditions.paId = parkingArea.paId
  243 + this.listParkingSpaceInfo.conditions.areaNum = parkingArea.num
  244 + },
  245 +
  246 + handleAddSuccess() {
  247 + this.loadParkingSpaceData()
  248 + },
  249 +
  250 + handleEditSuccess() {
  251 + this.loadParkingSpaceData()
  252 + },
  253 +
  254 + handleDeleteSuccess() {
  255 + this.loadParkingSpaceData()
  256 + },
  257 +
  258 + handleBatchAddSuccess() {
  259 + this.loadParkingSpaceData()
  260 + },
  261 +
  262 + handlePageChange(page) {
  263 + this.listParkingSpaceInfo.currentPage = page
  264 + this.loadParkingSpaceData()
  265 + },
  266 +
  267 + handleSizeChange(size) {
  268 + this.listParkingSpaceInfo.pageSize = size
  269 + this.loadParkingSpaceData()
  270 + }
  271 + }
  272 +}
  273 +</script>
  274 +
  275 +<style scoped>
  276 +.parking-space-container {
  277 + padding: 20px;
  278 +}
  279 +
  280 +.search-content {
  281 + padding: 10px 0;
  282 +}
  283 +
  284 +.ibox-tools {
  285 + display: inline-block;
  286 + float: right;
  287 + margin-top: 0;
  288 + position: relative;
  289 + padding: 0;
  290 +}
  291 +
  292 +.el-input-group {
  293 + display: flex;
  294 +}
  295 +</style>
0 \ No newline at end of file 296 \ No newline at end of file
src/views/car/parkingAreaManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + parkingAreaManage: {
  4 + queryTitle: 'Query Conditions',
  5 + parkingInfo: 'Parking Area Information',
  6 + parkingId: 'Parking ID',
  7 + parkingNum: 'Parking Number',
  8 + parkingType: 'Parking Type',
  9 + inputParkingNum: 'Please enter parking number',
  10 + selectParkingType: 'Please select parking type',
  11 + aboveGround: 'Above Ground Parking',
  12 + underground: 'Underground Parking',
  13 + remark: 'Remark',
  14 + createTime: 'Create Time',
  15 + operation: 'Operation',
  16 + controlPanel: 'Control Panel',
  17 + addTitle: 'Add Parking Area',
  18 + editTitle: 'Edit Parking Area',
  19 + deleteTitle: 'Confirm Operation',
  20 + deleteConfirm: 'Are you sure to delete this parking area?',
  21 + numRequired: 'Parking number is required',
  22 + typeRequired: 'Parking type is required',
  23 + remarkPlaceholder: 'Optional, please enter remark',
  24 + attr1: 'Area Size',
  25 + attr1Placeholder: 'Please enter area size',
  26 + attr2: 'Parking Type',
  27 + selectAttr2: 'Please select parking type',
  28 + option1: 'Standard',
  29 + option2: 'VIP',
  30 + column1: 'Capacity',
  31 + column2: 'Available',
  32 + addSuccess: 'Parking area added successfully',
  33 + addFailed: 'Failed to add parking area',
  34 + editSuccess: 'Parking area updated successfully',
  35 + editFailed: 'Failed to update parking area',
  36 + deleteSuccess: 'Parking area deleted successfully',
  37 + deleteFailed: 'Failed to delete parking area',
  38 + fetchError: 'Failed to fetch parking area data'
  39 + }
  40 + },
  41 + zh: {
  42 + parkingAreaManage: {
  43 + queryTitle: '查询条件',
  44 + parkingInfo: '停车场信息',
  45 + parkingId: '停车场ID',
  46 + parkingNum: '停车场编号',
  47 + parkingType: '停车场类型',
  48 + inputParkingNum: '请输入停车场编号',
  49 + selectParkingType: '请选择停车场类型',
  50 + aboveGround: '地上停车场',
  51 + underground: '地下停车场',
  52 + remark: '备注',
  53 + createTime: '创建时间',
  54 + operation: '操作',
  55 + controlPanel: '控制台',
  56 + addTitle: '添加停车场',
  57 + editTitle: '修改停车场',
  58 + deleteTitle: '确认操作',
  59 + deleteConfirm: '是否确定删除该停车场?',
  60 + numRequired: '停车场编号不能为空',
  61 + typeRequired: '停车场类型不能为空',
  62 + remarkPlaceholder: '可选,请填写备注',
  63 + attr1: '区域大小',
  64 + attr1Placeholder: '请输入区域大小',
  65 + attr2: '停车类型',
  66 + selectAttr2: '请选择停车类型',
  67 + option1: '标准',
  68 + option2: 'VIP',
  69 + column1: '容量',
  70 + column2: '可用',
  71 + addSuccess: '停车场添加成功',
  72 + addFailed: '停车场添加失败',
  73 + editSuccess: '停车场修改成功',
  74 + editFailed: '停车场修改失败',
  75 + deleteSuccess: '停车场删除成功',
  76 + deleteFailed: '停车场删除失败',
  77 + fetchError: '获取停车场数据失败'
  78 + }
  79 + }
  80 +}
0 \ No newline at end of file 81 \ No newline at end of file
src/views/car/parkingAreaManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="parking-area-manage animated fadeInRight">
  3 + <el-row :gutter="20">
  4 + <el-col :span="24">
  5 + <el-card>
  6 + <div slot="header" class="text-left">
  7 + <span>{{ $t('parkingAreaManage.queryTitle') }}</span>
  8 + </div>
  9 + <el-form :inline="true" :model="parkingAreaManageInfo.conditions" class="text-left">
  10 + <el-form-item :label="$t('parkingAreaManage.parkingNum')">
  11 + <el-input v-model.trim="parkingAreaManageInfo.conditions.num"
  12 + :placeholder="$t('parkingAreaManage.inputParkingNum')" clearable />
  13 + </el-form-item>
  14 + <el-form-item :label="$t('parkingAreaManage.parkingType')">
  15 + <el-select v-model="parkingAreaManageInfo.conditions.typeCd"
  16 + :placeholder="$t('parkingAreaManage.selectParkingType')" clearable style="width: 100%">
  17 + <el-option v-for="item in parkingTypes" :key="item.value" :label="item.label" :value="item.value" />
  18 + </el-select>
  19 + </el-form-item>
  20 + <el-form-item>
  21 + <el-button type="primary" @click="_queryParkingAreaMethod">
  22 + {{ $t('common.search') }}
  23 + </el-button>
  24 + <el-button @click="_resetParkingAreaMethod">
  25 + {{ $t('common.reset') }}
  26 + </el-button>
  27 + </el-form-item>
  28 + </el-form>
  29 + </el-card>
  30 + </el-col>
  31 + </el-row>
  32 +
  33 + <el-row :gutter="20" style="margin-top: 20px">
  34 + <el-col :span="24">
  35 + <el-card>
  36 + <div slot="header" class="flex justify-between">
  37 + <span>{{ $t('parkingAreaManage.parkingInfo') }}</span>
  38 + <el-button v-if="hasPrivilege('502022100147030003')" type="primary" size="small" class="float-right"
  39 + @click="_openAddParkingAreaModal">
  40 + {{ $t('common.add') }}
  41 + </el-button>
  42 + </div>
  43 +
  44 + <el-table :data="parkingAreaManageInfo.parkingAreas" border style="width: 100%" v-loading="loading">
  45 + <el-table-column prop="paId" :label="$t('parkingAreaManage.parkingId')" align="center" />
  46 + <el-table-column prop="num" :label="$t('parkingAreaManage.parkingNum')" align="center" />
  47 + <el-table-column :label="$t('parkingAreaManage.parkingType')" align="center">
  48 + <template slot-scope="scope">
  49 + {{ scope.row.typeCd === '1001' ? $t('parkingAreaManage.aboveGround') : $t('parkingAreaManage.underground')
  50 + }}
  51 + </template>
  52 + </el-table-column>
  53 + <el-table-column v-for="(item, index) in parkingAreaManageInfo.listColumns" :key="index"
  54 + :label="item.specName" align="center">
  55 + <template slot-scope="scope">
  56 + {{ scope.row.listValues[index] }}
  57 + </template>
  58 + </el-table-column>
  59 + <el-table-column prop="remark" :label="$t('parkingAreaManage.remark')" align="center" />
  60 + <el-table-column prop="createTime" :label="$t('parkingAreaManage.createTime')" align="center" />
  61 + <el-table-column :label="$t('common.operation')" align="center" width="250">
  62 + <template slot-scope="scope">
  63 + <el-button v-if="hasPrivilege('502022100103010004')" size="mini"
  64 + @click="_openEditParkingAreaModel(scope.row)">
  65 + {{ $t('common.edit') }}
  66 + </el-button>
  67 + <el-button v-if="hasPrivilege('502022100117490005')" size="mini" type="danger"
  68 + @click="_openDeleteParkingAreaModel(scope.row)">
  69 + {{ $t('common.delete') }}
  70 + </el-button>
  71 + <el-button v-if="hasPrivilege('502022100112510006')" size="mini" type="success"
  72 + @click="_openParkingAreaTotalControl(scope.row)">
  73 + {{ $t('parkingAreaManage.controlPanel') }}
  74 + </el-button>
  75 + </template>
  76 + </el-table-column>
  77 + </el-table>
  78 +
  79 + <el-pagination :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]"
  80 + :page-size="pagination.size" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
  81 + @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  82 + </el-card>
  83 + </el-col>
  84 + </el-row>
  85 +
  86 + <add-parking-area ref="addModal" @success="handleAddSuccess" />
  87 + <edit-parking-area ref="editModal" @success="handleEditSuccess" />
  88 + <delete-parking-area ref="deleteModal" @success="handleDeleteSuccess" />
  89 + </div>
  90 +</template>
  91 +
  92 +<script>
  93 +import { getParkingAreaList } from '@/api/car/parkingAreaManageApi'
  94 +import AddParkingArea from '@/components/car/addParkingArea'
  95 +import EditParkingArea from '@/components/car/editParkingArea'
  96 +import DeleteParkingArea from '@/components/car/deleteParkingArea'
  97 +import { getCommunityId } from '@/api/community/communityApi'
  98 +
  99 +export default {
  100 + name: 'ParkingAreaManageList',
  101 + components: {
  102 + AddParkingArea,
  103 + EditParkingArea,
  104 + DeleteParkingArea
  105 + },
  106 + data() {
  107 + return {
  108 + loading: false,
  109 + parkingAreaManageInfo: {
  110 + parkingAreas: [],
  111 + listColumns: [],
  112 + conditions: {
  113 + num: '',
  114 + typeCd: '',
  115 + paId: ''
  116 + }
  117 + },
  118 + pagination: {
  119 + current: 1,
  120 + size: 10,
  121 + total: 0
  122 + },
  123 + parkingTypes: [
  124 + { value: '1001', label: this.$t('parkingAreaManage.aboveGround') },
  125 + { value: '2001', label: this.$t('parkingAreaManage.underground') }
  126 + ]
  127 + }
  128 + },
  129 + created() {
  130 + this._getColumns()
  131 + this._listParkingAreas()
  132 + },
  133 + methods: {
  134 + async _listParkingAreas() {
  135 + this.loading = true
  136 + try {
  137 + const params = {
  138 + page: this.pagination.current,
  139 + row: this.pagination.size,
  140 + ...this.parkingAreaManageInfo.conditions,
  141 + communityId: getCommunityId()
  142 + }
  143 +
  144 + const res = await getParkingAreaList(params)
  145 + this.parkingAreaManageInfo.parkingAreas = res.parkingAreas
  146 + this.pagination.total = res.total
  147 + this.dealParkingAreaAttr(res.parkingAreas)
  148 + } catch (error) {
  149 + console.error('获取停车场列表失败:', error)
  150 + this.$message.error(this.$t('parkingAreaManage.fetchError'))
  151 + } finally {
  152 + this.loading = false
  153 + }
  154 + },
  155 +
  156 + _queryParkingAreaMethod() {
  157 + this.pagination.current = 1
  158 + this._listParkingAreas()
  159 + },
  160 +
  161 + _resetParkingAreaMethod() {
  162 + this.parkingAreaManageInfo.conditions = {
  163 + num: '',
  164 + typeCd: '',
  165 + paId: ''
  166 + }
  167 + this._listParkingAreas()
  168 + },
  169 +
  170 + _openAddParkingAreaModal() {
  171 + this.$refs.addModal.open()
  172 + },
  173 +
  174 + _openEditParkingAreaModel(row) {
  175 + this.$refs.editModal.open(row)
  176 + },
  177 +
  178 + _openDeleteParkingAreaModel(row) {
  179 + this.$refs.deleteModal.open(row)
  180 + },
  181 +
  182 + handleAddSuccess() {
  183 + this._listParkingAreas()
  184 + },
  185 +
  186 + handleEditSuccess() {
  187 + this._listParkingAreas()
  188 + },
  189 +
  190 + handleDeleteSuccess() {
  191 + this._listParkingAreas()
  192 + },
  193 +
  194 + handleSizeChange(size) {
  195 + this.pagination.size = size
  196 + this._listParkingAreas()
  197 + },
  198 +
  199 + handleCurrentChange(current) {
  200 + this.pagination.current = current
  201 + this._listParkingAreas()
  202 + },
  203 +
  204 + dealParkingAreaAttr(parkingAreas) {
  205 + parkingAreas.forEach(item => {
  206 + this._getColumnsValue(item)
  207 + })
  208 + },
  209 +
  210 + _getColumnsValue(parkingArea) {
  211 + parkingArea.listValues = []
  212 + if (!parkingArea.attrs || parkingArea.attrs.length === 0) {
  213 + this.parkingAreaManageInfo.listColumns.forEach(() => {
  214 + parkingArea.listValues.push('')
  215 + })
  216 + return
  217 + }
  218 +
  219 + this.parkingAreaManageInfo.listColumns.forEach(column => {
  220 + const attr = parkingArea.attrs.find(a => a.specCd === column.specCd)
  221 + parkingArea.listValues.push(attr ? attr.value : '')
  222 + })
  223 + },
  224 +
  225 + async _getColumns() {
  226 + try {
  227 + // 这里需要根据实际接口获取列配置
  228 + // 示例代码,实际需要替换为API调用
  229 + this.parkingAreaManageInfo.listColumns = [
  230 + ]
  231 + } catch (error) {
  232 + console.error('获取列配置失败:', error)
  233 + }
  234 + },
  235 +
  236 + _openParkingAreaTotalControl(parkingArea) {
  237 + // 跳转到控制台逻辑
  238 + console.log('打开控制台', parkingArea)
  239 + }
  240 + }
  241 +}
  242 +</script>
  243 +
  244 +<style scoped>
  245 +.parking-area-manage {
  246 + padding: 20px;
  247 +}
  248 +
  249 +.float-right {
  250 + float: right;
  251 +}
  252 +</style>
0 \ No newline at end of file 253 \ No newline at end of file