This commit is contained in:
ktianc 2022-10-07 23:33:30 +08:00
parent deaa9de232
commit 35076338be
13 changed files with 213 additions and 40 deletions

View File

@ -20,6 +20,10 @@ export const getDictTypeApi = (dataId: number): Promise<IResponse> => {
return request.get({ url: `/vadmin/system/dict/types/${dataId}/` }) return request.get({ url: `/vadmin/system/dict/types/${dataId}/` })
} }
export const getDictTypeOptionsApi = (): Promise<IResponse> => {
return request.get({ url: `/vadmin/system/dict/types/options/` })
}
export const getDictDetailsListApi = (params: any): Promise<IResponse> => { export const getDictDetailsListApi = (params: any): Promise<IResponse> => {
return request.get({ url: '/vadmin/system/dict/details/', params }) return request.get({ url: '/vadmin/system/dict/details/', params })
} }

View File

@ -104,11 +104,11 @@ const setVisible = () => {
> >
<template #action> <template #action>
<div v-if="layout === 'inline'"> <div v-if="layout === 'inline'">
<ElButton v-if="showSearch" type="primary" @click="search"> <ElButton v-if="showSearch" type="primary" size="small" @click="search">
<Icon icon="ep:search" class="mr-5px" /> <Icon icon="ep:search" class="mr-5px" />
{{ t('common.query') }} {{ t('common.query') }}
</ElButton> </ElButton>
<ElButton v-if="showReset" @click="reset"> <ElButton v-if="showReset" size="small" @click="reset">
<Icon icon="ep:refresh-right" class="mr-5px" /> <Icon icon="ep:refresh-right" class="mr-5px" />
{{ t('common.reset') }} {{ t('common.reset') }}
</ElButton> </ElButton>

View File

@ -136,10 +136,9 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
}, },
// 与Search组件结合 // 与Search组件结合
setSearchParams: (data: Recordable) => { setSearchParams: (data: Recordable) => {
tableObject.page = 1
tableObject.params = Object.assign(tableObject.params, { tableObject.params = Object.assign(tableObject.params, {
limit: tableObject.limit, limit: tableObject.limit,
pageIndex: tableObject.page, page: tableObject.page,
...data ...data
}) })
methods.getList() methods.getList()

View File

@ -1,7 +1,7 @@
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw } from 'vue-router'
import type { App } from 'vue' import type { App } from 'vue'
import { Layout, getParentLayout } from '@/utils/routerHelper' import { Layout } from '@/utils/routerHelper'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n() const { t } = useI18n()

View File

@ -0,0 +1,50 @@
<script setup lang="ts">
import { Form } from '@/components/Form'
import { useForm } from '@/hooks/web/useForm'
import { PropType, reactive, watch } from 'vue'
import { useValidator } from '@/hooks/web/useValidator'
import { schema } from './detail.data'
const { required } = useValidator()
const props = defineProps({
currentRow: {
type: Object as PropType<Nullable<any>>,
default: () => null
}
})
const rules = reactive({
label: [required()],
value: [required()],
order: [required()],
is_default: [required()],
disabled: [required()]
})
const { register, methods, elFormRef } = useForm({
schema: schema
})
watch(
() => props.currentRow,
(currentRow) => {
if (!currentRow) return
const { setValues } = methods
setValues(currentRow)
},
{
deep: true,
immediate: true
}
)
defineExpose({
elFormRef,
getFormData: methods.getFormData
})
</script>
<template>
<Form :rules="rules" @register="register" />
</template>

View File

@ -1,4 +1,6 @@
import { reactive } from 'vue' import { ElTag } from 'element-plus'
import { h, reactive } from 'vue'
import { getDictTypeOptionsApi } from '@/api/vadmin/system/dict'
export const columns = reactive<TableColumn[]>([ export const columns = reactive<TableColumn[]>([
{ {
@ -19,7 +21,16 @@ export const columns = reactive<TableColumn[]>([
}, },
{ {
field: 'disabled', field: 'disabled',
label: '是否禁用' label: '是否禁用',
formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
return h(
ElTag,
{
type: cellValue ? 'danger' : ''
},
() => (cellValue ? '禁用' : '启用')
)
}
}, },
{ {
field: 'remark', field: 'remark',
@ -38,21 +49,58 @@ export const columns = reactive<TableColumn[]>([
export const schema = reactive<FormSchema[]>([ export const schema = reactive<FormSchema[]>([
{ {
field: 'dict_name', field: 'label',
label: '字典名称', label: '字典标签',
colProps: { colProps: {
span: 24 span: 24
}, },
component: 'Input' component: 'Input'
}, },
{ {
field: 'dict_type', field: 'value',
label: '字典类型', label: '字典键值',
colProps: { colProps: {
span: 24 span: 24
}, },
component: 'Input' component: 'Input'
}, },
{
field: 'order',
label: '排序',
colProps: {
span: 24
},
component: 'InputNumber',
componentProps: {
style: {
width: '50%'
}
}
},
{
field: 'is_default',
label: '是否默认',
colProps: {
span: 24
},
component: 'Radio',
componentProps: {
style: {
width: '100%'
},
options: [
{
label: '是',
value: true
},
{
label: '否',
value: false
}
]
},
value: false
},
{ {
field: 'disabled', field: 'disabled',
label: '是否禁用', label: '是否禁用',
@ -86,3 +134,30 @@ export const schema = reactive<FormSchema[]>([
component: 'Input' component: 'Input'
} }
]) ])
const res = await getDictTypeOptionsApi()
const data = res.data
export const searchSchema = reactive<FormSchema[]>([
{
field: 'label',
label: '字典标签',
component: 'Input',
componentProps: {
clearable: false
}
},
{
field: 'dict_type_id',
label: '字典类型',
component: 'Select',
componentProps: {
options: data,
optionsAlias: {
labelField: 'dict_name',
valueField: 'id'
},
clearable: false
}
}
])

View File

@ -1,4 +1,5 @@
import { reactive } from 'vue' import { ElTag } from 'element-plus'
import { h, reactive } from 'vue'
export const columns = reactive<TableColumn[]>([ export const columns = reactive<TableColumn[]>([
{ {
@ -15,7 +16,16 @@ export const columns = reactive<TableColumn[]>([
}, },
{ {
field: 'disabled', field: 'disabled',
label: '是否禁用' label: '是否禁用',
formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
return h(
ElTag,
{
type: cellValue ? 'danger' : ''
},
() => (cellValue ? '禁用' : '启用')
)
}
}, },
{ {
field: 'remark', field: 'remark',

View File

@ -9,15 +9,21 @@ import {
getDictDetailsApi getDictDetailsApi
} from '@/api/vadmin/system/dict' } from '@/api/vadmin/system/dict'
import { useTable } from '@/hooks/web/useTable' import { useTable } from '@/hooks/web/useTable'
import { columns } from './components/detail.data' import { columns, searchSchema } from './components/detail.data'
import { ref, unref } from 'vue' import { ref, unref } from 'vue'
import Write from './components/Write.vue' import Write from './components/DetailWrite.vue'
import { Dialog } from '@/components/Dialog' import { Dialog } from '@/components/Dialog'
import { ElButton, ElMessage } from 'element-plus' import { ElButton, ElMessage } from 'element-plus'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useRouter } from 'vue-router'
import { Search } from '@/components/Search'
const { currentRoute } = useRouter()
const { t } = useI18n() const { t } = useI18n()
let dictType = currentRoute.value.query.dictType
const { register, tableObject, methods } = useTable({ const { register, tableObject, methods } = useTable({
getListApi: getDictDetailsListApi, getListApi: getDictDetailsListApi,
delListApi: delDictDetailsListApi, delListApi: delDictDetailsListApi,
@ -29,6 +35,7 @@ const { register, tableObject, methods } = useTable({
columns columns
} }
}) })
tableObject.params = { dict_type_id: dictType }
const dialogVisible = ref(false) const dialogVisible = ref(false)
const dialogTitle = ref('') const dialogTitle = ref('')
@ -74,6 +81,7 @@ const save = async () => {
loading.value = false loading.value = false
return ElMessage.error('未获取到数据') return ElMessage.error('未获取到数据')
} }
data.dict_type_id = dictType
const res = ref({}) const res = ref({})
if (actionType.value === 'add') { if (actionType.value === 'add') {
res.value = await addDictDetailsListApi(data) res.value = await addDictDetailsListApi(data)
@ -89,13 +97,15 @@ const save = async () => {
}) })
} }
const { getList } = methods const { getList, setSearchParams } = methods
getList() getList()
</script> </script>
<template> <template>
<ContentWrap> <ContentWrap>
<Search :schema="searchSchema" @search="setSearchParams" @reset="setSearchParams" />
<div class="mb-10px"> <div class="mb-10px">
<ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton> <ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
</div> </div>
@ -121,7 +131,7 @@ getList()
</template> </template>
</Table> </Table>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px"> <Dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
<Write ref="writeRef" :current-row="tableObject.currentRow" /> <Write ref="writeRef" :current-row="tableObject.currentRow" />
<template #footer> <template #footer>

View File

@ -15,6 +15,9 @@ import Write from './components/Write.vue'
import { Dialog } from '@/components/Dialog' import { Dialog } from '@/components/Dialog'
import { ElButton, ElMessage } from 'element-plus' import { ElButton, ElMessage } from 'element-plus'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useRouter } from 'vue-router'
const { push } = useRouter()
const { t } = useI18n() const { t } = useI18n()
@ -62,6 +65,11 @@ const delData = async (row: any) => {
}) })
} }
//
const toDetail = (row: any) => {
push(`/system/dict/detail?dictType=${row.id}`)
}
const writeRef = ref<ComponentRef<typeof Write>>() const writeRef = ref<ComponentRef<typeof Write>>()
const save = async () => { const save = async () => {
@ -112,13 +120,19 @@ getList()
@register="register" @register="register"
> >
<template #action="{ row }"> <template #action="{ row }">
<ElButton type="primary" text size="small" @click="updateAction(row)"> <ElButton type="primary" link size="small" @click="updateAction(row)">
{{ t('exampleDemo.edit') }} {{ t('exampleDemo.edit') }}
</ElButton> </ElButton>
<ElButton type="danger" text size="small" @click="delData(row)"> <ElButton type="danger" link size="small" @click="delData(row)">
{{ t('exampleDemo.del') }} {{ t('exampleDemo.del') }}
</ElButton> </ElButton>
</template> </template>
<template #dict_type="{ row }">
<ElButton type="primary" link @click="toDetail(row)">
{{ row.dict_type }}
</ElButton>
</template>
</Table> </Table>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px"> <Dialog v-model="dialogVisible" :title="dialogTitle" width="700px">

View File

@ -10,6 +10,8 @@
# sqlalchemy 关联查询https://www.jianshu.com/p/dfad7c08c57a # sqlalchemy 关联查询https://www.jianshu.com/p/dfad7c08c57a
# sqlalchemy 关联查询详细https://blog.csdn.net/u012324798/article/details/103940527 # sqlalchemy 关联查询详细https://blog.csdn.net/u012324798/article/details/103940527
from typing import List from typing import List
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from . import models, schemas from . import models, schemas
from core.crud import DalBase from core.crud import DalBase
@ -35,6 +37,12 @@ class DictTypeDal(DalBase):
data[dict_type] = [schemas.DictDetailsSimpleOut.from_orm(i).dict() for i in dict_data.details] data[dict_type] = [schemas.DictDetailsSimpleOut.from_orm(i).dict() for i in dict_data.details]
return data return data
async def get_select_datas(self):
"""获取选择数据,全部数据"""
sql = select(self.model)
queryset = await self.db.execute(sql)
return [schemas.DictTypeSelectOut.from_orm(i).dict() for i in queryset.scalars().all()]
class DictDetailsDal(DalBase): class DictDetailsDal(DalBase):

View File

@ -1 +1 @@
from .dict import DictType, DictDetails, DictTypeSimpleOut, DictDetailsSimpleOut from .dict import DictType, DictDetails, DictTypeSimpleOut, DictDetailsSimpleOut, DictTypeSelectOut

View File

@ -20,17 +20,6 @@ class DictType(BaseModel):
disabled: Optional[bool] = False disabled: Optional[bool] = False
remark: Optional[str] = None remark: Optional[str] = None
class Config:
# 示例参数值会默认显示在接口文档中example为固定写法
schema_extra = {
"example": {
"dict_name": "用户性别",
"dict_type": "sys_user_sex",
"disabled": False,
"remark": "性别选择"
}
}
class DictTypeSimpleOut(DictType): class DictTypeSimpleOut(DictType):
id: int id: int
@ -41,14 +30,23 @@ class DictTypeSimpleOut(DictType):
orm_mode = True orm_mode = True
class DictTypeSelectOut(BaseModel):
id: int
dict_name: str
disabled: bool
class Config:
orm_mode = True
class DictDetails(BaseModel): class DictDetails(BaseModel):
label: str label: str
value: str value: str
disabled: Optional[bool] = False disabled: Optional[bool] = False
is_default: Optional[bool] = False is_default: Optional[bool] = False
remark: Optional[str] = None remark: Optional[str] = None
order: Optional[str] = None order: Optional[int] = None
dict_data: int dict_type_id: int
class DictDetailsSimpleOut(DictDetails): class DictDetailsSimpleOut(DictDetails):

View File

@ -44,6 +44,12 @@ async def post_dicts_details(auth: Auth = Depends(login_auth),
return SuccessResponse(datas) return SuccessResponse(datas)
@app.get("/dict/types/options/", summary="获取字典类型选择项")
async def get_dicts_options(auth: Auth = Depends(login_auth)):
datas = await crud.DictTypeDal(auth.db).get_select_datas()
return SuccessResponse(datas)
@app.put("/dict/types/{data_id}/", summary="更新字典类型") @app.put("/dict/types/{data_id}/", summary="更新字典类型")
async def put_dict_types(data_id: int, data: schemas.DictType, auth: Auth = Depends(login_auth)): async def put_dict_types(data_id: int, data: schemas.DictType, auth: Auth = Depends(login_auth)):
return SuccessResponse(await crud.DictTypeDal(auth.db).put_data(data_id, data)) return SuccessResponse(await crud.DictTypeDal(auth.db).put_data(data_id, data))
@ -65,14 +71,13 @@ async def create_dict_details(data: schemas.DictDetails, auth: Auth = Depends(lo
@app.get("/dict/details/", summary="获取单个字典类型下的字典元素列表,分页") @app.get("/dict/details/", summary="获取单个字典类型下的字典元素列表,分页")
async def get_dict_details(params: Params = Depends(paging), auth: Auth = Depends(login_auth), async def get_dict_details(params: Params = Depends(paging), auth: Auth = Depends(login_auth),
dict_type_id: Optional[str] = Query(..., title="查询字典类型", description="查询字典类型"), dict_type_id: Optional[int] = Query(None, title="查询字典类型", description="查询字典类型"),
dict_label: Optional[str] = Query(None, title="查询字典标签", description="查询字典标签")): label: Optional[str] = Query(None, title="查询字典标签", description="查询字典标签")):
type_obj = await crud.DictTypeDal(auth.db).get_data(dict_type_id=dict_type_id, return_none=True) if not dict_type_id:
if not type_obj: return ErrorResponse(msg="未获取到字典类型!")
return ErrorResponse(msg="未找到字典类型!")
datas = await crud.DictDetailsDal(auth.db).\ datas = await crud.DictDetailsDal(auth.db).\
get_datas(params.page, params.limit, dict_label=dict_label, dict_type_id=type_obj.id) get_datas(params.page, params.limit, label=label, dict_type_id=dict_type_id)
count = await crud.DictDetailsDal(auth.db).get_count(dict_label=dict_label, dict_type_id=type_obj.id) count = await crud.DictDetailsDal(auth.db).get_count(label=label, dict_type_id=dict_type_id)
return SuccessResponse(datas, count=count) return SuccessResponse(datas, count=count)