Merge branch 'develop' of gitee.com:huge-dream/django-vue3-admin into develop
This commit is contained in:
@@ -19,6 +19,20 @@ class UsersInitSerializer(CustomModelSerializer):
|
|||||||
"""
|
"""
|
||||||
初始化获取数信息(用于生成初始化json文件)
|
初始化获取数信息(用于生成初始化json文件)
|
||||||
"""
|
"""
|
||||||
|
role_key = serializers.SerializerMethodField()
|
||||||
|
dept_key = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_dept_key(self, obj):
|
||||||
|
if obj.dept:
|
||||||
|
return obj.dept.key
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_role_key(self, obj):
|
||||||
|
if obj.role.all():
|
||||||
|
return [role.key for role in obj.role.all()]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
instance = super().save(**kwargs)
|
instance = super().save(**kwargs)
|
||||||
@@ -35,7 +49,7 @@ class UsersInitSerializer(CustomModelSerializer):
|
|||||||
model = Users
|
model = Users
|
||||||
fields = ["username", "email", 'mobile', 'avatar', "name", 'gender', 'user_type', "dept", 'user_type',
|
fields = ["username", "email", 'mobile', 'avatar', "name", 'gender', 'user_type', "dept", 'user_type',
|
||||||
'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'creator', 'dept_belong_id',
|
'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'creator', 'dept_belong_id',
|
||||||
'password', 'last_login', 'is_superuser']
|
'password', 'last_login', 'is_superuser', 'role_key' ,'dept_key']
|
||||||
read_only_fields = ['id']
|
read_only_fields = ['id']
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'creator': {'write_only': True},
|
'creator': {'write_only': True},
|
||||||
@@ -175,15 +189,21 @@ class RoleMenuInitSerializer(CustomModelSerializer):
|
|||||||
"""
|
"""
|
||||||
初始化角色菜单(用于生成初始化json文件)
|
初始化角色菜单(用于生成初始化json文件)
|
||||||
"""
|
"""
|
||||||
role__key = serializers.CharField(max_length=100, required=True)
|
role__key = serializers.CharField(source='role.key')
|
||||||
menu__web_path = serializers.CharField(max_length=100, required=True)
|
menu__web_path = serializers.CharField(source='menu.web_path')
|
||||||
menu__component_name = serializers.CharField(max_length=100, required=True, allow_blank=True)
|
menu__component_name = serializers.CharField(source='menu.component_name', allow_blank=True)
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
init_data = self.initial_data
|
||||||
|
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||||
|
menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first()
|
||||||
|
validated_data['role'] = role_id
|
||||||
|
validated_data['menu'] = menu_id
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
init_data = self.initial_data
|
init_data = self.initial_data
|
||||||
validated_data.pop('menu__web_path')
|
|
||||||
validated_data.pop('menu__component_name')
|
|
||||||
validated_data.pop('role__key')
|
|
||||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||||
menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first()
|
menu_id = Menu.objects.filter(web_path=init_data['menu__web_path'], component_name=init_data['menu__component_name']).first()
|
||||||
validated_data['role'] = role_id
|
validated_data['role'] = role_id
|
||||||
@@ -192,7 +212,7 @@ class RoleMenuInitSerializer(CustomModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RoleMenuPermission
|
model = RoleMenuPermission
|
||||||
fields = ['role__key', 'menu__web_path', 'menu__component_name', 'creator', 'dept_belong_id']
|
fields = ['role__key', 'menu__web_path', 'menu__component_name','creator', 'dept_belong_id']
|
||||||
read_only_fields = ["id"]
|
read_only_fields = ["id"]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'role': {'required': False},
|
'role': {'required': False},
|
||||||
@@ -206,14 +226,22 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer):
|
|||||||
"""
|
"""
|
||||||
初始化角色菜单按钮(用于生成初始化json文件)
|
初始化角色菜单按钮(用于生成初始化json文件)
|
||||||
"""
|
"""
|
||||||
role__key = serializers.CharField(max_length=100, required=True)
|
role__key = serializers.CharField(source='role.key')
|
||||||
menu_button__value = serializers.CharField(max_length=100, required=True)
|
menu_button__value = serializers.CharField(source='menu_button.value')
|
||||||
data_range = serializers.CharField(max_length=100, required=False)
|
data_range = serializers.CharField(max_length=100, required=False)
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
init_data = self.initial_data
|
||||||
|
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||||
|
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first()
|
||||||
|
validated_data['role'] = role_id
|
||||||
|
validated_data['menu_button'] = menu_button_id
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
instance.dept.set([])
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
init_data = self.initial_data
|
init_data = self.initial_data
|
||||||
validated_data.pop('menu_button__value')
|
|
||||||
validated_data.pop('role__key')
|
|
||||||
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
role_id = Role.objects.filter(key=init_data['role__key']).first()
|
||||||
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first()
|
menu_button_id = MenuButton.objects.filter(value=init_data['menu_button__value']).first()
|
||||||
validated_data['role'] = role_id
|
validated_data['role'] = role_id
|
||||||
@@ -223,7 +251,7 @@ class RoleMenuButtonInitSerializer(CustomModelSerializer):
|
|||||||
return instance
|
return instance
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
if self.instance and self.initial_data.get('reset'):
|
if not self.instance or self.initial_data.get('reset'):
|
||||||
return super().save(**kwargs)
|
return super().save(**kwargs)
|
||||||
return self.instance
|
return self.instance
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ django.setup()
|
|||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
from application.settings import BASE_DIR
|
from application.settings import BASE_DIR
|
||||||
from dvadmin.system.models import Menu, Users, Dept, Role, ApiWhiteList, Dictionary, SystemConfig
|
from dvadmin.system.models import Menu, Users, Dept, Role, ApiWhiteList, Dictionary, SystemConfig, RoleMenuButtonPermission, RoleMenuPermission
|
||||||
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
|
from dvadmin.system.fixtures.initSerializer import UsersInitSerializer, DeptInitSerializer, RoleInitSerializer, \
|
||||||
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
|
MenuInitSerializer, ApiWhiteListInitSerializer, DictionaryInitSerializer, SystemConfigInitSerializer, \
|
||||||
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
|
RoleMenuInitSerializer, RoleMenuButtonInitSerializer
|
||||||
@@ -57,6 +57,12 @@ class Command(BaseCommand):
|
|||||||
def generate_system_config(self):
|
def generate_system_config(self):
|
||||||
self.serializer_data(SystemConfigInitSerializer, SystemConfig.objects.filter(parent_id__isnull=True))
|
self.serializer_data(SystemConfigInitSerializer, SystemConfig.objects.filter(parent_id__isnull=True))
|
||||||
|
|
||||||
|
def generate_role_menu(self):
|
||||||
|
self.serializer_data(RoleMenuInitSerializer, RoleMenuPermission.objects.all())
|
||||||
|
|
||||||
|
def generate_role_menu_button(self):
|
||||||
|
self.serializer_data(RoleMenuButtonInitSerializer, RoleMenuButtonPermission.objects.all())
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
generate_name = options.get('generate_name')
|
generate_name = options.get('generate_name')
|
||||||
generate_name_dict = {
|
generate_name_dict = {
|
||||||
@@ -67,6 +73,8 @@ class Command(BaseCommand):
|
|||||||
"api_white_list": self.generate_api_white_list,
|
"api_white_list": self.generate_api_white_list,
|
||||||
"dictionary": self.generate_dictionary,
|
"dictionary": self.generate_dictionary,
|
||||||
"system_config": self.generate_system_config,
|
"system_config": self.generate_system_config,
|
||||||
|
"role_menu": self.generate_role_menu,
|
||||||
|
"role_menu_button": self.generate_role_menu_button,
|
||||||
}
|
}
|
||||||
if not generate_name:
|
if not generate_name:
|
||||||
for ele in generate_name_dict.keys():
|
for ele in generate_name_dict.keys():
|
||||||
|
|||||||
87
crud-gen.sh
Normal file
87
crud-gen.sh
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
if ! [ -f ".env" ];then
|
||||||
|
echo ".env file not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$3" ]; then
|
||||||
|
echo "Use: $0 <app_name> <view_name> <table_name>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
DIR=./web/src/views/$1/$2
|
||||||
|
|
||||||
|
|
||||||
|
# 设置数据库连接信息
|
||||||
|
HOST="177.10.0.13"
|
||||||
|
USER="root"
|
||||||
|
PASSWORD=$(cat .env | grep MYSQL_PASSWORD | sed 's/^.*MYSQL_PASSWORD=//g')
|
||||||
|
DATABASE="django-vue3-admin"
|
||||||
|
TABLE=$3
|
||||||
|
TARGET_FILE="./web/src/views/$1/$2/crud.tsx"
|
||||||
|
|
||||||
|
|
||||||
|
# 表是否存在
|
||||||
|
TABLE_EXISTS=$(mysql -h $HOST -u $USER -p$PASSWORD -D $DATABASE -e "SHOW TABLES LIKE '$TABLE';" -N | grep "$TABLE" | wc -l)
|
||||||
|
|
||||||
|
if [ "$TABLE_EXISTS" -eq 0 ]; then
|
||||||
|
echo "Table $TABLE does not exist in database $DATABASE."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $DIR
|
||||||
|
cp -r ./web/src/views/template/* $DIR
|
||||||
|
sed -i "s/VIEWSETNAME/$2/g" $DIR/*
|
||||||
|
|
||||||
|
sed -n -e :a -e '1,5!{P;N;D;};N;ba' -i $TARGET_FILE
|
||||||
|
|
||||||
|
# 查询表结构
|
||||||
|
QUERY="SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '$DATABASE' AND TABLE_NAME = '$TABLE' ORDER BY ORDINAL_POSITION;"
|
||||||
|
|
||||||
|
# 使用 MySQL 查询获取字段信息,并生成 fast-crud 配置
|
||||||
|
mysql -h $HOST -u $USER -p$PASSWORD -D $DATABASE -e "$QUERY" -N | while read COLUMN_NAME DATA_TYPE COLUMN_COMMENT IS_NULLABLE; do
|
||||||
|
# 映射 MySQL 数据类型到 fast-crud 类型
|
||||||
|
case "$DATA_TYPE" in
|
||||||
|
"int"|"bigint"|"smallint"|"mediumint"|"tinyint"|"decimal"|"float"|"double")
|
||||||
|
TYPE="number"
|
||||||
|
;;
|
||||||
|
"date"|"datetime"|"timestamp")
|
||||||
|
TYPE="date"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
TYPE="text"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo " $COLUMN_NAME: {
|
||||||
|
title: '$COLUMN_NAME',
|
||||||
|
type: '$TYPE',
|
||||||
|
search: { show: true },
|
||||||
|
column: {
|
||||||
|
minWidth: 120,
|
||||||
|
sortable: 'custom',
|
||||||
|
},
|
||||||
|
form: {" >> $TARGET_FILE
|
||||||
|
|
||||||
|
if [ "$IS_NULLABLE" = "NO" ]; then
|
||||||
|
echo " helper: {
|
||||||
|
render() {
|
||||||
|
return <div style={"color:blue"}>$COLUMN_NAME 是必填的</div>;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rules: [{
|
||||||
|
required: true, message: '$COLUMN_NAME 是必填的'
|
||||||
|
}]," >> $TARGET_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " component: {
|
||||||
|
placeholder: '请输入 $COLUMN_NAME',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}," >> $TARGET_FILE
|
||||||
|
done
|
||||||
|
|
||||||
|
echo " },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}" >> $TARGET_FILE
|
||||||
50
web/src/views/template/api.ts
Normal file
50
web/src/views/template/api.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { request,downloadFile } from '/@/utils/service';
|
||||||
|
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
|
export const apiPrefix = '/api/VIEWSETNAME/';
|
||||||
|
|
||||||
|
export function GetList(query: PageQuery) {
|
||||||
|
return request({
|
||||||
|
url: apiPrefix,
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function GetObj(id: InfoReq) {
|
||||||
|
return request({
|
||||||
|
url: apiPrefix + id,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AddObj(obj: AddReq) {
|
||||||
|
return request({
|
||||||
|
url: apiPrefix,
|
||||||
|
method: 'post',
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UpdateObj(obj: EditReq) {
|
||||||
|
return request({
|
||||||
|
url: apiPrefix + obj.id + '/',
|
||||||
|
method: 'put',
|
||||||
|
data: obj,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DelObj(id: DelReq) {
|
||||||
|
return request({
|
||||||
|
url: apiPrefix + id + '/',
|
||||||
|
method: 'delete',
|
||||||
|
data: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportData(params:any){
|
||||||
|
return downloadFile({
|
||||||
|
url: apiPrefix + 'export_data/',
|
||||||
|
params: params,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
86
web/src/views/template/crud.tsx
Normal file
86
web/src/views/template/crud.tsx
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { CrudOptions, AddReq, DelReq, EditReq, dict, CrudExpose, UserPageQuery, CreateCrudOptionsRet } from '@fast-crud/fast-crud';
|
||||||
|
import _ from 'lodash-es';
|
||||||
|
import * as api from './api';
|
||||||
|
import { request } from '/@/utils/service';
|
||||||
|
import { auth } from "/@/utils/authFunction";
|
||||||
|
|
||||||
|
//此处为crudOptions配置
|
||||||
|
export default function ({ crudExpose }: { crudExpose: CrudExpose }): CreateCrudOptionsRet {
|
||||||
|
const pageRequest = async (query: any) => {
|
||||||
|
return await api.GetList(query);
|
||||||
|
};
|
||||||
|
const editRequest = async ({ form, row }: EditReq) => {
|
||||||
|
if (row.id) {
|
||||||
|
form.id = row.id;
|
||||||
|
}
|
||||||
|
return await api.UpdateObj(form);
|
||||||
|
};
|
||||||
|
const delRequest = async ({ row }: DelReq) => {
|
||||||
|
return await api.DelObj(row.id);
|
||||||
|
};
|
||||||
|
const addRequest = async ({ form }: AddReq) => {
|
||||||
|
return await api.AddObj(form);
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportRequest = async (query: UserPageQuery) => {
|
||||||
|
return await api.exportData(query)
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
crudOptions: {
|
||||||
|
request: {
|
||||||
|
pageRequest,
|
||||||
|
addRequest,
|
||||||
|
editRequest,
|
||||||
|
delRequest,
|
||||||
|
},
|
||||||
|
actionbar: {
|
||||||
|
buttons: {
|
||||||
|
export: {
|
||||||
|
// 注释编号:django-vue3-admin-crud210716:注意这个auth里面的值,最好是使用index.vue文件里面的name值并加上请求动作的单词
|
||||||
|
show: auth('VIEWSETNAME:Export'),
|
||||||
|
text: "导出",//按钮文字
|
||||||
|
title: "导出",//鼠标停留显示的信息
|
||||||
|
click() {
|
||||||
|
return exportRequest(crudExpose.getSearchFormData())
|
||||||
|
// return exportRequest(crudExpose!.getSearchFormData()) // 注意这个crudExpose!.getSearchFormData(),一些低版本的环境是需要添加!的
|
||||||
|
}
|
||||||
|
},
|
||||||
|
add: {
|
||||||
|
show: auth('VIEWSETNAME:Create'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowHandle: {
|
||||||
|
//固定右侧
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
buttons: {
|
||||||
|
view: {
|
||||||
|
type: 'text',
|
||||||
|
order: 1,
|
||||||
|
show: auth('VIEWSETNAME:Retrieve')
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
type: 'text',
|
||||||
|
order: 2,
|
||||||
|
show: auth('VIEWSETNAME:Update')
|
||||||
|
},
|
||||||
|
copy: {
|
||||||
|
type: 'text',
|
||||||
|
order: 3,
|
||||||
|
show: auth('VIEWSETNAME:Copy')
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
type: 'text',
|
||||||
|
order: 4,
|
||||||
|
show: auth('VIEWSETNAME:Delete')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
// COLUMNS_CONFIG
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
56
web/src/views/template/index.vue
Normal file
56
web/src/views/template/index.vue
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<fs-page class="PageFeatureSearchMulti">
|
||||||
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
<template #cell_url="scope">
|
||||||
|
<el-tag size="small">{{ scope.row.url }}</el-tag>
|
||||||
|
</template>
|
||||||
|
<!-- 注释编号: django-vue3-admin-index442216: -->
|
||||||
|
<!-- 注释编号:django-vue3-admin-index39263917:代码开始行-->
|
||||||
|
<!-- 功能说明:使用导入组件,并且修改api地址为当前对应的api,当前是demo的api="api/CarModelViewSet/"-->
|
||||||
|
<template #actionbar-right>
|
||||||
|
<importExcel api="api/VIEWSETNAME/" v-auth="'user:Import'">导入</importExcel>
|
||||||
|
</template>
|
||||||
|
<!-- 注释编号:django-vue3-admin-index263917:代码结束行-->
|
||||||
|
|
||||||
|
</fs-crud>
|
||||||
|
</fs-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMounted, getCurrentInstance, defineComponent} from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
|
import createCrudOptions from './crud';
|
||||||
|
|
||||||
|
// 注释编号: django-vue3-admin-index192316:导入组件
|
||||||
|
import importExcel from '/@/components/importExcel/index.vue'
|
||||||
|
|
||||||
|
|
||||||
|
export default defineComponent({ //这里配置defineComponent
|
||||||
|
name: "VIEWSETNAME", //把name放在这里进行配置了
|
||||||
|
components: {importExcel}, //注释编号: django-vue3-admin-index552416: 注册组件,把importExcel组件放在这里,这样<template></template>中才能正确的引用到组件
|
||||||
|
setup() { //这里配置了setup()
|
||||||
|
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
|
||||||
|
const context: any = {
|
||||||
|
componentName: instance?.type.name
|
||||||
|
};
|
||||||
|
|
||||||
|
const { crudBinding, crudRef, crudExpose, resetCrudOptions } = useFs({ createCrudOptions, context});
|
||||||
|
|
||||||
|
|
||||||
|
// 页面打开后获取列表数据
|
||||||
|
onMounted(() => {
|
||||||
|
crudExpose.doRefresh();
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
//增加了return把需要给上面<template>内调用的<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
|
crudBinding,
|
||||||
|
crudRef,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} //这里关闭setup()
|
||||||
|
}); //关闭defineComponent
|
||||||
|
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user