feat: add CityArea web
This commit is contained in:
@@ -55,8 +55,8 @@ def gen_menu(app_name, model_name, parent_menu_name, creator='admin'):
|
||||
{"name": "Edit", "title": "common.edit", "auth_code": f"{app_name}:{model_lower}:edit"},
|
||||
{"name": "Delete", "title": "common.delete", "auth_code": f"{app_name}:{model_lower}:delete"},
|
||||
{"name": "Query", "title": "common.query", "auth_code": f"{app_name}:{model_lower}:query"},
|
||||
{"name": "Query", "title": "common.query", "auth_code": f"{app_name}:{model_lower}:import"},
|
||||
{"name": "Query", "title": "common.query", "auth_code": f"{app_name}:{model_lower}:export"},
|
||||
{"name": "import", "title": "common.import", "auth_code": f"{app_name}:{model_lower}:import"},
|
||||
{"name": "export", "title": "common.export", "auth_code": f"{app_name}:{model_lower}:export"},
|
||||
]
|
||||
for idx, btn in enumerate(buttons):
|
||||
btn_meta = MenuMeta.objects.create(
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"""
|
||||
自动生成 CRUD 代码的 Django 管理命令
|
||||
使用方法: python manage.py generate_crud <app_name> <model_name>
|
||||
例如: python manage.py generate_crud system Dept
|
||||
例如: python manage.py generate_crud system Dept --frontend
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
@@ -14,6 +14,7 @@ router.register(r'post', views.PostViewSet)
|
||||
router.register(r'user', views.UserViewSet)
|
||||
router.register(r'login_log', views.LoginLogViewSet)
|
||||
router.register(r'config', views.ConfigViewSet)
|
||||
router.register(r'city_area', views.CityAreaViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
|
||||
@@ -9,6 +9,7 @@ __all__ = [
|
||||
'UserViewSet',
|
||||
'ConfigViewSet',
|
||||
'LoginLogViewSet',
|
||||
'CityAreaViewSet',
|
||||
]
|
||||
|
||||
from system.views.dict_data import DictDataViewSet
|
||||
@@ -20,4 +21,5 @@ from system.views.dept import DeptViewSet
|
||||
from system.views.post import PostViewSet
|
||||
from system.views.login_log import LoginLogViewSet
|
||||
from system.views.config import ConfigViewSet
|
||||
from system.views.user import *
|
||||
from system.views.user import *
|
||||
from system.views.city_area import CityAreaViewSet
|
||||
33
backend/system/views/city_area.py
Normal file
33
backend/system/views/city_area.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from system.models import CityArea
|
||||
from utils.serializers import CustomModelSerializer
|
||||
from utils.custom_model_viewSet import CustomModelViewSet
|
||||
from django_filters import rest_framework as filters
|
||||
|
||||
|
||||
class CityAreaSerializer(CustomModelSerializer):
|
||||
"""
|
||||
省市区 序列化器
|
||||
"""
|
||||
class Meta:
|
||||
model = CityArea
|
||||
fields = '__all__'
|
||||
read_only_fields = ['id', 'create_time', 'update_time']
|
||||
|
||||
|
||||
class CityAreaFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = CityArea
|
||||
fields = ['id', 'remark', 'creator', 'modifier', 'is_deleted', 'prov_id', 'prov_name', 'city_id', 'city_name', 'area_id', 'area_name']
|
||||
|
||||
|
||||
class CityAreaViewSet(CustomModelViewSet):
|
||||
"""
|
||||
省市区 视图集
|
||||
"""
|
||||
queryset = CityArea.objects.filter(is_deleted=False).order_by('-id')
|
||||
serializer_class = CityAreaSerializer
|
||||
filterset_class = CityAreaFilter
|
||||
search_fields = ['name'] # 根据实际字段调整
|
||||
ordering_fields = ['create_time', 'id']
|
||||
ordering = ['-create_time']
|
||||
@@ -100,14 +100,18 @@
|
||||
"name": "User",
|
||||
"title": "User Management"
|
||||
},
|
||||
"login_log": {
|
||||
"login_log": {
|
||||
"name": "login log",
|
||||
"title": "login log"
|
||||
},
|
||||
"config": {
|
||||
"config": {
|
||||
"name": "System Config",
|
||||
"title": "System Config"
|
||||
},
|
||||
"city_area": {
|
||||
"name": "Area Information",
|
||||
"title": "Area Information"
|
||||
},
|
||||
"status": "Status",
|
||||
"remark": "Remarks",
|
||||
"creator": "creator",
|
||||
|
||||
@@ -109,6 +109,10 @@
|
||||
"name": "系统配置",
|
||||
"title": "系统配置"
|
||||
},
|
||||
"city_area": {
|
||||
"name": "地区信息",
|
||||
"title": "地区信息"
|
||||
},
|
||||
"status": "状态",
|
||||
"remark": "备注",
|
||||
"creator": "创建人",
|
||||
|
||||
25
web/apps/web-antd/src/models/system/city_area.ts
Normal file
25
web/apps/web-antd/src/models/system/city_area.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { BaseModel } from '#/models/base';
|
||||
|
||||
export namespace SystemCityAreaApi {
|
||||
export interface SystemCityArea {
|
||||
id: number;
|
||||
remark: string;
|
||||
creator: string;
|
||||
modifier: string;
|
||||
update_time: string;
|
||||
create_time: string;
|
||||
is_deleted: boolean;
|
||||
prov_id: number;
|
||||
prov_name: string;
|
||||
city_id: number;
|
||||
city_name: string;
|
||||
area_id: number;
|
||||
area_name: string;
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemCityAreaModel extends BaseModel<SystemCityAreaApi.SystemCityArea> {
|
||||
constructor() {
|
||||
super('/system/city_area/');
|
||||
}
|
||||
}
|
||||
141
web/apps/web-antd/src/views/system/city_area/data.ts
Normal file
141
web/apps/web-antd/src/views/system/city_area/data.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||
|
||||
import type { VbenFormSchema } from '#/adapter/form';
|
||||
import type { SystemCityAreaApi } from '#/models/system/city_area';
|
||||
|
||||
import { z } from '#/adapter/form';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
/**
|
||||
* 获取编辑表单的字段配置
|
||||
*/
|
||||
export function useSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'prov_id',
|
||||
label: '省id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'prov_name',
|
||||
label: '省',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['省']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['省', 100])),
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'city_id',
|
||||
label: '市id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'city_name',
|
||||
label: '市',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['市']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['市', 100])),
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'area_id',
|
||||
label: '区id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'area_name',
|
||||
label: '区',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['区']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['区', 100])),
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'remark',
|
||||
label: '备注',
|
||||
rules: z
|
||||
.string()
|
||||
.min(1, $t('ui.formRules.required', ['备注']))
|
||||
.max(100, $t('ui.formRules.maxLength', ['备注', 100])),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取编辑表单的字段配置
|
||||
*/
|
||||
export function useGridFormSchema(): VbenFormSchema[] {
|
||||
return [
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'prov_id',
|
||||
label: '省id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'prov_name',
|
||||
label: '省',
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'city_id',
|
||||
label: '市id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'city_name',
|
||||
label: '市',
|
||||
},
|
||||
{
|
||||
component: 'InputNumber',
|
||||
fieldName: 'area_id',
|
||||
label: '区id',
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
fieldName: 'area_name',
|
||||
label: '区',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表格列配置
|
||||
* @description 使用函数的形式返回列数据而不是直接export一个Array常量,是为了响应语言切换时重新翻译表头
|
||||
*/
|
||||
export function useColumns(): VxeTableGridOptions<SystemCityAreaApi.SystemCityArea>['columns'] {
|
||||
return [
|
||||
{
|
||||
field: 'id',
|
||||
title: 'ID',
|
||||
},
|
||||
{
|
||||
field: 'prov_id',
|
||||
title: '省id',
|
||||
},
|
||||
{
|
||||
field: 'prov_name',
|
||||
title: '省',
|
||||
},
|
||||
{
|
||||
field: 'city_id',
|
||||
title: '市id',
|
||||
},
|
||||
{
|
||||
field: 'city_name',
|
||||
title: '市',
|
||||
},
|
||||
{
|
||||
field: 'area_id',
|
||||
title: '区id',
|
||||
},
|
||||
{
|
||||
field: 'area_name',
|
||||
title: '区',
|
||||
},
|
||||
];
|
||||
}
|
||||
68
web/apps/web-antd/src/views/system/city_area/list.vue
Normal file
68
web/apps/web-antd/src/views/system/city_area/list.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<script lang="ts" setup>
|
||||
import type {
|
||||
VxeTableGridOptions,
|
||||
} from '#/adapter/vxe-table';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { SystemCityAreaModel } from '#/models/system/city_area';
|
||||
|
||||
import { useColumns, useGridFormSchema } from './data';
|
||||
import Form from './modules/form.vue';
|
||||
|
||||
const formModel = new SystemCityAreaModel();
|
||||
|
||||
const [FormModal] = useVbenModal({
|
||||
connectedComponent: Form,
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
const [Grid, gridApi] = useVbenVxeGrid({
|
||||
formOptions: {
|
||||
schema: useGridFormSchema(),
|
||||
submitOnChange: true,
|
||||
},
|
||||
gridEvents: {},
|
||||
gridOptions: {
|
||||
columns: useColumns(),
|
||||
height: 'auto',
|
||||
keepSource: true,
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
return await formModel.list({
|
||||
page: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...formValues,
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
toolbarConfig: {
|
||||
custom: true,
|
||||
export: false,
|
||||
refresh: { code: 'query' },
|
||||
zoom: true,
|
||||
search: true,
|
||||
},
|
||||
} as VxeTableGridOptions,
|
||||
});
|
||||
|
||||
/**
|
||||
* 刷新表格
|
||||
*/
|
||||
function refreshGrid() {
|
||||
gridApi.query();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<FormModal @success="refreshGrid" />
|
||||
<Grid table-title="地区" />
|
||||
</Page>
|
||||
</template>
|
||||
@@ -0,0 +1,79 @@
|
||||
<script lang="ts" setup>
|
||||
import type { SystemCityAreaApi } from '#/models/system/city_area';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { $t } from '#/locales';
|
||||
import { SystemCityAreaModel } from '#/models/system/city_area';
|
||||
|
||||
import { useSchema } from '../data';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
const formModel = new SystemCityAreaModel();
|
||||
|
||||
const formData = ref<SystemCityAreaApi.SystemCityArea>();
|
||||
const getTitle = computed(() => {
|
||||
return formData.value?.id
|
||||
? $t('ui.actionTitle.edit', [$t('system.city_area.name')])
|
||||
: $t('ui.actionTitle.create', [$t('system.city_area.name')]);
|
||||
});
|
||||
|
||||
const [Form, formApi] = useVbenForm({
|
||||
layout: 'horizontal',
|
||||
schema: useSchema(),
|
||||
showDefaultActions: false,
|
||||
});
|
||||
|
||||
function resetForm() {
|
||||
formApi.resetForm();
|
||||
formApi.setValues(formData.value || {});
|
||||
}
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
const { valid } = await formApi.validate();
|
||||
if (valid) {
|
||||
modalApi.lock();
|
||||
const data = await formApi.getValues();
|
||||
try {
|
||||
await (formData.value?.id
|
||||
? formModel.update(formData.value.id, data)
|
||||
: formModel.create(data));
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
} finally {
|
||||
modalApi.lock(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
onOpenChange(isOpen) {
|
||||
if (isOpen) {
|
||||
const data = modalApi.getData<SystemCityAreaApi.SystemCityArea>();
|
||||
if (data) {
|
||||
formData.value = data;
|
||||
formApi.setValues(formData.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle">
|
||||
<Form />
|
||||
<template #prepend-footer>
|
||||
<div class="flex-auto">
|
||||
<Button type="primary" danger @click="resetForm">
|
||||
{{ $t('common.reset') }}
|
||||
</Button>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
<style lang="css" scoped></style>
|
||||
@@ -14,6 +14,8 @@
|
||||
"search": "Search",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"import": "import",
|
||||
"export": "export",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"create": "Create",
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
"search": "搜索",
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用",
|
||||
"import": "导入",
|
||||
"export": "导出",
|
||||
"edit": "修改",
|
||||
"delete": "删除",
|
||||
"create": "新增",
|
||||
|
||||
Reference in New Issue
Block a user