Browse Source

修改地区选择组件

yuhongzhe
王泽彦 11 months ago
parent
commit
e62f76eab4
  1. 4
      admin/src/app/api/venue.ts
  2. 8
      admin/src/app/lang/zh-cn/venue.venue.json
  3. 583
      admin/src/app/views/venue/components/venue-edit.vue
  4. 5
      admin/src/components/TencentMapPicker.vue
  5. 4
      niucloud/app/adminapi/controller/venue/Venue.php
  6. 2
      niucloud/app/adminapi/route/venue.php
  7. 4
      niucloud/app/validate/venue/Venue.php

4
admin/src/app/api/venue.ts

@ -2,6 +2,10 @@ import request from '@/utils/request'
// USER_CODE_BEGIN -- venue
/**
*

8
admin/src/app/lang/zh-cn/venue.venue.json

@ -9,12 +9,8 @@
"availabilityStatusPlaceholder":"请输入场地可用状态",
"timeRangeType":"场地可用时间范围类型",
"timeRangeTypePlaceholder":"请输入场地可用时间范围类型",
"timeRangeStart":"范围类型的开始时间",
"timeRangeStartPlaceholder":"请输入范围类型的开始时间",
"timeRangeEnd":"范围类型的结束时间",
"timeRangeEndPlaceholder":"请输入范围类型的结束时间",
"fixedTimeRanges":"固定时间范围类型的可用时间, 存储为JSON数组",
"fixedTimeRangesPlaceholder":"请输入固定时间范围类型的可用时间, 存储为JSON数组",
"fixedTimeRanges":"时间范围",
"fixedTimeRangesPlaceholder":"请输入时间范围",
"createdAt":"创建时间",
"createdAtPlaceholder":"请输入创建时间",
"updatedAt":"修改时间",

583
admin/src/app/views/venue/components/venue-edit.vue

@ -1,267 +1,316 @@
<template>
<el-dialog v-model="showDialog" :title="formData.id ? t('updateVenue') : t('addVenue')" width="50%" class="diy-dialog-wrap" :destroy-on-close="true">
<el-form :model="formData" label-width="120px" ref="formRef" :rules="formRules" class="page-form" v-loading="loading">
<el-form-item :label="t('campusId')" prop="campus_id">
<el-select class="input-width" v-model="formData.campus_id" clearable :placeholder="t('campusIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('venueName')" prop="venue_name">
<el-input v-model="formData.venue_name" clearable :placeholder="t('venueNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('capacity')" prop="capacity">
<el-input-number v-model="formData.capacity" clearable :placeholder="t('capacityPlaceholder')" class="input-width" :min = "1" max = "500" />
</el-form-item>
<el-form-item :label="t('availabilityStatus')" prop="availability_status">
<el-radio-group v-model="formData.availability_status" :placeholder="t('availabilityStatusPlaceholder')">
<el-radio
v-for="(item, index) in availability_statusList"
:key="index" :label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('timeRangeType')" prop="time_range_type">
<el-radio-group v-model="formData.time_range_type" :placeholder="t('timeRangeTypePlaceholder')">
<el-radio
v-for="(item, index) in time_range_typeList"
:key="index" :label="item.value">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('timeRangeStart')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.time_range_start"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('timeRangeStartPlaceholder')">
</el-date-picker>
</el-form-item>
<el-form-item :label="t('timeRangeEnd')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.time_range_end"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('timeRangeEndPlaceholder')">
</el-date-picker>
</el-form-item>
<el-form-item :label="t('fixedTimeRanges')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.fixed_time_ranges"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('fixedTimeRangesPlaceholder')">
</el-date-picker>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button type="primary" :loading="loading" @click="confirm(formRef)">{{
t('confirm')
}}</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import { addVenue, editVenue, getVenueInfo, getWithCampusList } from '@/app/api/venue'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
campus_id: '',
venue_name: '',
capacity: '',
availability_status: '',
time_range_type: '',
time_range_start: '',
time_range_end: '',
fixed_time_ranges: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
campus_id: [
{ required: true, message: t('campusIdPlaceholder'), trigger: 'blur' },
]
,
venue_name: [
{ required: true, message: t('venueNamePlaceholder'), trigger: 'blur' },
]
,
capacity: [
{ required: true, message: t('capacityPlaceholder'), trigger: 'blur' },
{ validator: (rule: any, value: string, callback: any) => { if (value && !/^\d{1,500}$/.test(value)) { callback(new Error(t('generateBetween')))} else { callback() }}},
]
,
availability_status: [
{ required: true, message: t('availabilityStatusPlaceholder'), trigger: 'blur' },
]
,
time_range_type: [
{ required: true, message: t('timeRangeTypePlaceholder'), trigger: 'blur' },
]
,
time_range_start: [
{ required: true, message: t('timeRangeStartPlaceholder'), trigger: 'blur' },
]
,
time_range_end: [
{ required: true, message: t('timeRangeEndPlaceholder'), trigger: 'blur' },
]
,
fixed_time_ranges: [
{ required: true, message: t('fixedTimeRangesPlaceholder'), trigger: 'blur' },
]
,
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editVenue : addVenue
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data).then(res => {
loading.value = false
showDialog.value = false
emit('complete')
}).catch(err => {
loading.value = false
})
}
})
}
//
let availability_statusList = ref([])
const availability_statusDictList = async () => {
availability_statusList.value = await (await useDictionary('SiteStatus')).data.dictionary
}
availability_statusDictList();
watch(() => availability_statusList.value, () => { formData.availability_status = availability_statusList.value[0].value })
let time_range_typeList = ref([])
const time_range_typeDictList = async () => {
time_range_typeList.value = await (await useDictionary('ALLOTTED_TIME')).data.dictionary
}
time_range_typeDictList();
watch(() => time_range_typeList.value, () => { formData.time_range_type = time_range_typeList.value[0].value })
const campusIdList = ref([] as any[])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if(row){
const data = await (await getVenueInfo(row.id)).data
if (data) Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label{
height: auto !important;
}
</style>
<template>
<el-dialog
v-model="showDialog"
:title="formData.id ? t('updateVenue') : t('addVenue')"
width="50%"
class="diy-dialog-wrap"
:destroy-on-close="true"
>
<el-form
:model="formData"
label-width="120px"
ref="formRef"
:rules="formRules"
class="page-form"
v-loading="loading"
>
<el-form-item :label="t('campusId')" prop="campus_id">
<el-select
class="input-width"
v-model="formData.campus_id"
clearable
:placeholder="t('campusIdPlaceholder')"
>
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in campusIdList"
:key="index"
:label="item['campus_name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('venueName')" prop="venue_name">
<el-input
v-model="formData.venue_name"
clearable
:placeholder="t('venueNamePlaceholder')"
class="input-width"
/>
</el-form-item>
<el-form-item :label="t('capacity')" prop="capacity">
<el-input-number
v-model="formData.capacity"
clearable
:placeholder="t('capacityPlaceholder')"
class="input-width"
:min="1"
max="500"
/>
</el-form-item>
<el-form-item :label="t('availabilityStatus')" prop="availability_status">
<el-radio-group
v-model="formData.availability_status"
:placeholder="t('availabilityStatusPlaceholder')"
>
<!-- <el-radio-->
<!-- v-for="(item, index) in availability_statusList"-->
<!-- :key="index"-->
<!-- :label="item.value"-->
<!-- >-->
<!-- {{ item.name }}-->
<!-- </el-radio>-->
<el-radio label="1">可用</el-radio>
<el-radio label="2">不可用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('timeRangeType')" prop="time_range_type">
<el-radio-group
v-model="formData.time_range_type"
:placeholder="t('timeRangeTypePlaceholder')"
>
<el-radio
v-for="(item, index) in time_range_typeList"
:key="index"
:label="item.value"
>
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="t('fixedTimeRanges')" class="input-width">
<el-date-picker
class="flex-1 !flex"
v-model="formData.fixed_time_ranges"
clearable
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:placeholder="t('fixedTimeRangesPlaceholder')"
>
</el-date-picker>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showDialog = false">{{ t('cancel') }}</el-button>
<el-button
type="primary"
:loading="loading"
@click="confirm(formRef)"
>{{ t('confirm') }}</el-button
>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { useDictionary } from '@/app/api/dict'
import { t } from '@/lang'
import type { FormInstance } from 'element-plus'
import {
addVenue,
editVenue,
getVenueInfo,
getWithCampusList,
} from '@/app/api/venue'
let showDialog = ref(false)
const loading = ref(false)
/**
* 表单数据
*/
const initialFormData = {
id: '',
campus_id: '',
venue_name: '',
capacity: '',
availability_status: '',
time_range_type: '',
fixed_time_ranges: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const formRef = ref<FormInstance>()
//
const formRules = computed(() => {
return {
campus_id: [
{ required: true, message: t('campusIdPlaceholder'), trigger: 'blur' },
],
venue_name: [
{ required: true, message: t('venueNamePlaceholder'), trigger: 'blur' },
],
capacity: [
{ required: true, message: t('capacityPlaceholder'), trigger: 'blur' },
{
validator: (rule: any, value: string, callback: any) => {
if (value && !/^\d{1,500}$/.test(value)) {
callback(new Error(t('generateBetween')))
} else {
callback()
}
},
},
],
availability_status: [
{
required: true,
message: t('availabilityStatusPlaceholder'),
trigger: 'blur',
},
],
time_range_type: [
{
required: true,
message: t('timeRangeTypePlaceholder'),
trigger: 'blur',
},
],
fixed_time_ranges: [
{
required: true,
message: t('fixedTimeRangesPlaceholder'),
trigger: 'blur',
},
],
}
})
const emit = defineEmits(['complete'])
/**
* 确认
* @param formEl
*/
const confirm = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
let save = formData.id ? editVenue : addVenue
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
save(data)
.then((res) => {
loading.value = false
showDialog.value = false
emit('complete')
})
.catch((err) => {
loading.value = false
})
}
})
}
//
let availability_statusList = ref([])
const availability_statusDictList = async () => {
availability_statusList.value = await (
await useDictionary('SiteStatus')
).data.dictionary
}
availability_statusDictList()
watch(
() => availability_statusList.value,
() => {
formData.availability_status = availability_statusList.value[0].value
}
)
let time_range_typeList = ref([])
const time_range_typeDictList = async () => {
time_range_typeList.value = await (
await useDictionary('ALLOTTED_TIME')
).data.dictionary
}
time_range_typeDictList()
watch(
() => time_range_typeList.value,
() => {
formData.time_range_type = time_range_typeList.value[0].value
}
)
const campusIdList = ref([] as any[])
const setCampusIdList = async () => {
campusIdList.value = await (await getWithCampusList({})).data
}
setCampusIdList()
const setFormData = async (row: any = null) => {
Object.assign(formData, initialFormData)
loading.value = true
if (row) {
const data = await (await getVenueInfo(row.id)).data
if (data)
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
loading.value = false
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (
value &&
!/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
value
)
) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
defineExpose({
showDialog,
setFormData,
})
</script>
<style lang="scss" scoped></style>
<style lang="scss">
.diy-dialog-wrap .el-form-item__label {
height: auto !important;
}
</style>

5
admin/src/components/TencentMapPicker.vue

@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="dialogVisible"
:title="t('mapPickerTitle')"
title="位置选择"
width="800px"
:before-close="handleClose"
:close-on-click-modal="false"
@ -344,7 +344,7 @@ const initMap = () => {
}
const TMap = (window as any).TMap
const center = new TMap.LatLng(39.90403, 116.407526)
const center = new TMap.LatLng(20.029077, 110.366367)
map = new TMap.Map('container', {
center,
@ -499,5 +499,6 @@ onBeforeUnmount(() => {
.address-search {
display: flex;
gap: 8px;
margin-top: 20px;
}
</style>

4
niucloud/app/adminapi/controller/venue/Venue.php

@ -59,8 +59,6 @@ class Venue extends BaseAdminController
["capacity",0],
["availability_status",0],
["time_range_type",""],
["time_range_start",""],
["time_range_end",""],
["fixed_time_ranges",""],
]);
@ -81,8 +79,6 @@ class Venue extends BaseAdminController
["capacity",0],
["availability_status",0],
["time_range_type",""],
["time_range_start",""],
["time_range_end",""],
["fixed_time_ranges",""],
]);

2
niucloud/app/adminapi/route/venue.php

@ -15,6 +15,8 @@ use app\adminapi\middleware\AdminCheckRole;
use app\adminapi\middleware\AdminCheckToken;
use app\adminapi\middleware\AdminLog;
// USER_CODE_BEGIN -- venue
Route::group('venue', function () {

4
niucloud/app/validate/venue/Venue.php

@ -37,8 +37,8 @@ class Venue extends BaseValidate
];
protected $scene = [
"add" => ['campus_id', 'venue_name', 'capacity', 'availability_status', 'time_range_type', 'time_range_start', 'time_range_end', 'fixed_time_ranges'],
"edit" => ['campus_id', 'venue_name', 'capacity', 'availability_status', 'time_range_type', 'time_range_start', 'time_range_end', 'fixed_time_ranges']
"add" => ['campus_id', 'venue_name', 'capacity', 'availability_status', 'time_range_type', 'fixed_time_ranges'],
"edit" => ['campus_id', 'venue_name', 'capacity', 'availability_status', 'time_range_type', 'fixed_time_ranges']
];
}

Loading…
Cancel
Save