Commit 6f57f1c1 authored by 何远江's avatar 何远江

添加资源库前端,对接

parent a520c450
import { ContentTypeEnum } from '@/enums/httpEnums'
import { defHttp } from '@/utils/axios/index'
import type { DictDetailResultDto, DictListParamsDto } from './model/dictModel'
import type { DictDetailResultDto, DictListParamsDto, DictListResultDto } from './model/dictModel'
import type { ApiResult, ApiResultRecord } from '../model/baseModel'
enum Api {
......@@ -30,7 +30,7 @@ export const apiGetDictList = (params: DictListParamsDto) => {
* @returns
*/
export const apiGetDictByCode = (dictCode: string) => {
return defHttp.get<ApiResult<DictListParamsDto[]>>({
return defHttp.get<ApiResult<DictListResultDto[]>>({
url: Api.DICT_FINDBYCODE,
headers: {
'Content-Type': ContentTypeEnum.FORM_URLENCODED
......
export type ResourceRepositoryTreeDto = {
/*资源库类型ID */
resourceTypeId: string
/*资源库类型表名 */
resourceTableName: string
/*资源库类型表名称 */
resourceTableTitle: string
/*父类表名 */
parentTableName: string
/*父类显示名 */
parentTableTitle: string
/*超类表名 */
superTableName: string
/*超类显示名 */
superTableTitle: string
pid?: string
resourceFileds?: ResourceFieldDto[]
childNode: ResourceRepositoryTreeDto[]
}
export type ResourceFieldDto = {
/*资源字段ID */
resourceFieldId: string
/*所属资源类型ID */
resourceTypeId: string
/*字段名 */
resourceFieldName: string
/*字段显示名 */
resourceFiledTitle: string
/*字段类型,码表(resourceFieldType)) */
resourceFieldType: string
/*是否可见,码表(resourceFieldShow)) */
resourceFieldShow: string
/*字段大小 */
resourceFieldSize: number
/*整型长度 */
integerLength: number
/*小数点位数 */
decimalPrecision: number
/*序号 */
sortNum: number
/*选择的资源类型 */
dictTable: string
/*对应码表的编码 */
dictCode: string
/*显示选择对应的表的字段值 */
dictText: string
/*假删除标记(-1已删除,0正常) */
deleted: number
}
import { ContentTypeEnum } from '@/enums/httpEnums'
import { defHttp } from '@/utils/axios/index'
import type { ApiResult } from '../model/baseModel'
import type { ResourceFieldDto, ResourceRepositoryTreeDto } from './model/repositoryModel'
enum Api {
REPOSITORY_LIST = '/resource/findList',
GET_RESOURCE_FIELD = '/resourceField/getResourceField',
GET_RESOURCE_FIELD_VALUE = '/resourceField/getResourceFieldValue',
FIND_PARENT_RESOURCE = '/resource/findParentResourceTypeAndFields'
}
export const apiGetRepositoryList = () => {
return defHttp.get<ApiResult<ResourceRepositoryTreeDto[]>>({
url: Api.REPOSITORY_LIST,
headers: {
'Content-Type': ContentTypeEnum.FORM_URLENCODED
}
})
}
export const apiGetResourceField = (resourceTypeId: string) => {
return defHttp.get<ApiResult<ResourceFieldDto[]>>({
url: Api.GET_RESOURCE_FIELD,
params: { resourceTypeId },
headers: {
'Content-Type': ContentTypeEnum.FORM_URLENCODED
}
})
}
export const apiGetResourceFieldValue = (resourceTypeId: string) => {
return defHttp.get<ApiResult<Recordable[]>>({
url: Api.GET_RESOURCE_FIELD_VALUE,
params: { resourceTypeId },
headers: {
'Content-Type': ContentTypeEnum.FORM_URLENCODED
}
})
}
export const apiFindParentResource = (tableName: string) => {
return defHttp.get<ApiResult<ResourceRepositoryTreeDto>>({
url: Api.FIND_PARENT_RESOURCE,
params: { tableName },
headers: {
'Content-Type': ContentTypeEnum.FORM_URLENCODED
}
})
}
export function useIcons() {
const getIcons = () => {
const svgs = import.meta.glob('../../icons/*.svg')
const iconMap: Recordable = {}
for (const name in svgs) {
iconMap[name.substring(12, name.length - 4)] = svgs[name]
}
console.log(iconMap)
}
return {
getIcons
}
}
<template>
<Modal v-bind="getBindValue" @cancel="handleCancel">
<!-- 模态框内容 -->
<Form ref="formRef" :model="formState" :label-col="{ style: { width: '5em' } }">
<Row :gutter="24">
<Col :span="12">
<FormItem label="资源名称" name="resourceTableTitle">
<Input v-model:value="formState.resourceTableTitle" />
</FormItem>
</Col>
<Col :span="12">
<FormItem label="资源表" name="resourceTableName">
<Input v-model:value="formState.resourceTableName" disabled />
</FormItem>
</Col>
<Col :span="12">
<FormItem label="超类名称" name="superTableTitle">
<Input v-model:value="formState.superTableTitle" disabled />
</FormItem>
</Col>
<Col :span="12">
<FormItem label="超类表" name="superTableName">
<Input v-model:value="formState.superTableName" disabled />
</FormItem>
</Col>
<Col :span="12">
<FormItem label="父类名称" name="parentTableTitle">
<Input v-model:value="formState.parentTableTitle" disabled />
</FormItem>
</Col>
<Col :span="12">
<FormItem label="父类表" name="parentTableName">
<Input v-model:value="formState.parentTableName" disabled />
</FormItem>
</Col>
</Row>
</Form>
<vxe-grid ref="xGrid" v-bind="gridOptions">
<template #toolbar>
<Button type="primary" @click="addFieldRow">新增</Button>
</template>
<template #resourceFiledTitle="{ row }">
<Input placeholder="输入字段名" size="small" v-model:value="row.resourceFiledTitle" />
</template>
<template #resourceFieldType="{ row }">
<Select
v-bind="selectOptions"
placeholder="请选择类型"
:options="dictOptions['resourceFieldType']"
v-model:value="row.resourceFieldType"
/>
</template>
<template #dictCode="{ row }">
<Select
style="display: block"
size="small"
:field-names="{
label: 'dictName',
value: 'dictCode'
}"
allowClear
placeholder="请选择字典"
:options="dictOptions['dict']"
show-search
@search="handleSearch"
v-model:value="row.dictCode"
/>
</template>
<template #resourceFieldShow="{ row }">
<Select
placeholder="是否可见"
v-bind="selectOptions"
:options="dictOptions['resourceFieldShow']"
v-model:value="row.resourceFieldShow"
/>
</template>
<template #action="{ row, $rowIndex }">
<Tooltip title="删除">
<Button
v-if="!row.resourceFieldId"
danger
size="small"
@click="removeRow($rowIndex)"
shape="circle"
><DeleteOutlined
/></Button>
</Tooltip>
</template>
</vxe-grid>
</Modal>
</template>
<script lang="ts">
import { apiDictFindById, apiGetDictByCode, apiGetDictList } from '@/api/common/dict'
import { apiFindParentResource } from '@/api/resource/repository'
import { Row, Col, Modal, Form, FormItem, Input, Select, Button, Tooltip } from 'ant-design-vue'
import { onMounted, reactive } from 'vue'
import { watch } from 'vue'
import { DeleteOutlined } from '@ant-design/icons-vue'
import { computed, defineComponent, ref, unref, watchEffect } from 'vue'
import type { VxeGridProps } from 'vxe-table'
export default defineComponent({
name: 'RepositoryModal',
components: {
Modal,
Form,
FormItem,
Button,
Input,
Select,
Row,
Col,
DeleteOutlined,
Tooltip
},
props: {
open: {
type: Boolean,
default: false
},
title: {
type: String,
default: '添加资源分类'
},
resNode: {
type: Object,
default: () => ({})
}
},
emits: ['update:open'],
setup(props, { emit }) {
const xGrid = ref()
const formRef = ref()
const visibleRef = ref(false)
const formState = reactive({
resourceTableTitle: '',
resourceTableName: '',
parentTableName: '',
parentTableTitle: '',
superTableName: '',
superTableTitle: ''
})
const dictOptions = reactive<Recordable>({
dict: []
})
const selectOptions = reactive<Recordable>({
size: 'small',
allowClear: true,
style: 'display: block',
fieldNames: {
label: 'dictItemText',
value: 'dictItemValue'
}
})
const gridOptions = reactive<VxeGridProps>({
border: 'inner',
height: '400px',
size: 'small',
columns: [
{
type: 'seq',
field: 'seq',
title: '序号',
width: 50
},
{
field: 'resourceFiledTitle',
title: '字段名',
slots: {
default: 'resourceFiledTitle'
}
},
{
field: 'resourceFieldType',
title: '类型',
slots: {
default: 'resourceFieldType'
}
},
{
field: 'dictCode',
title: '字典',
slots: {
default: 'dictCode'
}
},
{
field: 'resourceFieldShow',
title: '是否可见',
slots: {
default: 'resourceFieldShow'
}
},
{
field: 'action',
title: '操作',
width: 80,
slots: {
default: 'action'
}
}
],
data: []
})
const getBindValue = computed(() => {
return {
...props,
open: unref(visibleRef)
}
})
watch(
() => props.open,
(val) => {
if (val) {
// 请求超类和父类数据
getResourceDetail()
}
visibleRef.value = val
}
)
const getResourceDetail = async () => {
const { result } = await apiFindParentResource(props.resNode.resourceTableName)
formState.parentTableName = result.parentTableName
formState.parentTableTitle = result.parentTableTitle
formState.superTableName = result.superTableName
formState.superTableTitle = result.superTableTitle
gridOptions.data?.unshift(...(result?.resourceFileds || []))
}
const addFieldRow = () => {
gridOptions.data?.push({
resourceFiledTitle: '',
resourceFieldShow: '',
dictCode: '',
resourceFieldType: ''
})
}
const removeRow = (index: number) => gridOptions.data?.splice(index, 1)
const handleSearch = async (dictCode: string) => {
const { result } = await apiGetDictByCode(dictCode)
if (result !== null) {
dictOptions['dict'] = [result]
} else {
dictOptions['dict'] = []
}
}
const getDict = async (code: string) => {
const { result } = await apiDictFindById(code)
dictOptions[code] = result
}
const resetModalState = () => {
Object.assign(unref(formState), {
resourceTableTitle: '',
resourceTableName: '',
parentTableName: '',
parentTableTitle: '',
superTableName: '',
superTableTitle: ''
})
gridOptions.data = []
}
const handleCancel = () => {
resetModalState()
visibleRef.value = false
emit('update:open', false)
}
onMounted(() => {
getDict('resourceFieldType')
getDict('resourceFieldShow')
})
return {
xGrid,
formRef,
formState,
gridOptions,
dictOptions,
selectOptions,
getBindValue,
removeRow,
addFieldRow,
handleSearch,
handleCancel
}
}
})
</script>
<style lang="scss" scoped></style>
<template>
<Tree
v-if="treeList.length"
defaultExpandAll
:treeData="treeList"
:fieldNames="fieldNames"
:selectedKeys="selectedKeys"
@select="onSelect"
>
<template #title="node">
<Dropdown :trigger="['contextmenu']">
<span>{{ node.resourceTableTitle }}</span>
<template #overlay>
<Menu @click="({key}) => onContextMenuClick(key, node)">
<MenuItem key="add">添加资源分类</MenuItem>
<MenuItem key="modify">修改资源分类</MenuItem>
<MenuItem key="delete">删除资源分类</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
</Tree>
<RepositoryModal v-model:open="open" width="700px" :res-node="openNode" title="添加资源分类" />
</template>
<script lang="ts">
import { Tree, Dropdown, Menu, MenuItem } from 'ant-design-vue'
import RepositoryModal from './RepositoryModal.vue'
import { defineComponent, ref } from 'vue'
import { useRepositoryTree } from './useRepositoryTree'
export default defineComponent({
components: {
Tree,Menu,
MenuItem,
Dropdown,
RepositoryModal
},
setup() {
const repositoryState = useRepositoryTree()
return {
...repositoryState
}
}
})
</script>
<style lang="scss" scoped></style>
import type { ResourceRepositoryTreeDto } from '@/api/resource/model/repositoryModel'
import { apiGetRepositoryList } from '@/api/resource/repository'
import { onMounted, reactive, ref, unref } from 'vue'
import mitter from '@/utils/eventBus'
export function useRepositoryTree() {
const fieldNames = reactive({
children: 'childNode',
title: 'resourceTableTitle',
key: 'resourceTypeId'
})
const selectedNodeData = reactive<Recordable>({})
const openNode = reactive<Recordable>({})
const selectedKeys = ref<(string | number)[]>([])
const treeList = ref<ResourceRepositoryTreeDto[]>([])
const open = ref(false)
const getTreeList = async () => {
const { result } = await apiGetRepositoryList()
treeList.value = result
// 设置默认选中第一个
onSelect([result[0].resourceTypeId])
}
const onSelect = (keys: (string | number)[], e?: any) => {
e && Object.assign(selectedNodeData, e.node.data)
selectedKeys.value = keys
// 触发 表格 查询
mitter.emit('treeSelect', unref(selectedKeys))
}
const onContextMenuClick = (key: any, node: any) => {
Object.assign(openNode, node)
open.value = true
}
onMounted(async () => {
await getTreeList()
})
return {
open,
openNode,
fieldNames,
treeList,
selectedKeys,
onSelect,
onContextMenuClick
}
}
<template>
<vxe-table
border="none"
ref="tableRef"
:data="tableData"
size="small"
:loading="loading"
row-class-name="query-table-row"
header-row-class-name="query-table-header"
>
<template v-for="item in tableColumns" :key="item.resourceFieldId">
<vxe-column :field="item.resourceFieldName" :title="item.resourceFiledTitle"></vxe-column>
</template>
<vxe-column field="action" title="操作" key="action" fixed="right">
<template #default="{ row }">
<Space>
<span><FormOutlined />授权</span>
<span><FormOutlined />修改</span>
<span><DeleteOutlined />删除</span>
</Space>
</template>
</vxe-column>
</vxe-table>
</template>
<script lang="ts">
import { Space } from 'ant-design-vue'
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue'
import { defineComponent } from 'vue'
import { useResourceFieldsTable } from './useResourceFieldsTable'
export default defineComponent({
name: 'ResourceFieldsTable',
components: {
Space,
FormOutlined,
DeleteOutlined
},
setup() {
const state = useResourceFieldsTable()
return {
...state
}
}
})
</script>
<style lang="scss" scoped></style>
import { onBeforeUnmount, ref } from 'vue'
import mitter from '@/utils/eventBus'
import { apiGetResourceField, apiGetResourceFieldValue } from '@/api/resource/repository'
import type { ResourceFieldDto } from '@/api/resource/model/repositoryModel'
export function useResourceFieldsTable() {
const tableData = ref<Recordable[]>([])
const tableColumns = ref<ResourceFieldDto[]>([])
const loading = ref(false)
mitter.on('treeSelect', async ([key]: any) => {
if (key) {
loading.value = true
try {
await getColumn(key)
await getTableData(key)
} catch {}
loading.value = false
}
})
/**
* 获取表格动态列
* @param key
*/
const getColumn = async (key: any) => {
const { result } = await apiGetResourceField(key)
tableColumns.value = result
}
/**
* 获取表格数据
*/
const getTableData = async (key: any) => {
const {result } =await apiGetResourceFieldValue(key)
tableData.value = result
}
onBeforeUnmount(() => {
mitter.off('treeSelect')
})
return {
loading,
tableData,
tableColumns
}
}
<template>
<div class="page-search">
<PageTitle title="资源库" />
<div class="page-search-wrap">
<Row>
<Col span="6">
<RepositoryTree />
</Col>
<Col :span="18">
<ResourceFieldsTable />
</Col>
</Row>
</div>
</div>
</template>
<script lang="ts" setup>
import { Row, Col } from 'ant-design-vue'
import PageTitle from '@/layouts/page/PageTitle.vue'
import RepositoryTree from './components/RepositoryTree/index.vue'
import ResourceFieldsTable from './components/ResourceFieldsTable/index.vue'
</script>
<style lang="less" scoped>
.page-search-wrap {
height: 100%;
}
</style>
......@@ -84,7 +84,6 @@
childrenField: 'childNode',
expandAll: true
}"
header-row-class-name="query-table-header"
>
<vxe-column field="permissionName" title="菜单名称" tree-node></vxe-column>
......@@ -97,8 +96,12 @@
<vxe-column field="action" title="操作">
<template #default="{ row }">
<Space>
<span @click="modifyMenu(row.permissionId)"><FormOutlined />修改</span>
<span @click="deleteRoleById(row.permissionId)"><DeleteOutlined />删除</span>
<Tooltip title="修改">
<Button size="small" @click="modifyMenu(row.permissionId)" shape="circle"><FormOutlined /></Button>
</Tooltip>
<Tooltip title="删除">
<Button size="small" @click="deleteRoleById(row.permissionId)" shape="circle"><DeleteOutlined /></Button>
</Tooltip>
</Space>
</template>
</vxe-column>
......@@ -240,6 +243,7 @@ import {
Space,
Radio,
Modal,
Tooltip,
InputNumber,
TreeSelect
} from 'ant-design-vue'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment