关联表
概述
这个表单和另外的表单的关联关系配置,配置后可以在表单中以子表形式展示关联的表单项,列表不受影响
之前的关联表配置及效果
配置
效果
现在关联表配置及效果
说明
因为对 online 进行拆分, 并关联表进行了一次升级, 新的关联表使用的也是 online, 有一些新的功能和不同点.
- 整体
- 关联字段控制现在不在 关联表配置 tab 页 配置了, 需要到具体的关联表表单中去配置字段隐藏,只读, 并且配置关联字段隐藏的时候, 一对多关联表还需要到外键 tab 页 配置一下, 不然保存不上数据
-
一对多关联表
- 列表操作列按钮
- JS 增强
- 自定义按钮
- 支持分页
- 打开一对多关联表打开表单, 新增和编辑会保留列表的操作列(还会再根据权限过滤),查询项,选择框. 对于详情,默认是保留查询项,保留操作列(但是只有详情按钮)
-
一对一关联表虽然使用的也是 online,但是获取数据方式还是使用的之前关联表获取数据的,并且一对一关联表只渲染字段部分,隐藏按钮,所以一对一关联表功能没有什么变化
-
支持关联表指定一个自定义组件路径,之后的页面展示和数据提交逻辑由自定义组件负责.
- 关联表 配置可以为一个 online 表,这样提交数据会自动插入到 online 表, 可以只是一个唯一标识,到时数据提交自己单独调用接口
- 关联表 配置为一个 online 表时, 对应定义的 JS 增强生效
- 对于配置的一对一的关联表的自定义组件, 不需要提交按钮, 只需要定义几个方法,供主表调用即可. 示例文件:src/views/onlineDemo/customLinkTable1.vue
- add/edit/detail : 这几个方法需要手动调用接口取值(根据关联关系数据 prop)并给表单赋值, return new Promise 或者是个 async 函数,内部的异步操作 都需要使用 await 或者异步操作都完成后使用 resolve()
- getSubmitValues: 这个方法返回这个关联表提交时候需要的所有数据,提交时候会被调用. 如果想要自己单独调用接口保存数据,直接返回 null 就行
- 对于配置的一对多关联表的自定义组件, 需要定义几个方法供主表调用.示例文件:src/views/onlineDemo/customLinkTable2.vue
- initAutoList: 只会在激活时候调用一次, 用于初始化一些数据(比如 online 的 JS 增强),可以是空方法
- clearDataSource: 清空列表数据, add 时候会调用
- loadData/loadDataNoPage: 查询数据方法, 需要 async 或 promise, 异步操作都完成后 resolve. 需要根据关联关系 prop 获取数据.
- 对于列表的新增/编辑/详情操作,如果配置的是 online 表, 可以直接 this.$emit(“add/edit/detail”, {id:xxx,code:xxx}), 否则需要自己开发弹窗和表单页面
配置
效果
示例代码
位于 src/views/onlineDemo/customLinkTable1.vue 和 src/views/onlineDemo/customLinkTable2.vue 文件中
一对一
<template>
<div>
<a-form :form="form">
<a-form-item label="姓名222">
<a-input v-decorator="['fd_name']" :disabled="disabledProp" />
</a-form-item>
<a-form-item label="年龄">
<a-input v-decorator="['fd_age']" :disabled="disabledProp" />
</a-form-item>
</a-form>
</div>
</template>
<script>
// 自定义关联表一对一示例
export default {
name: 'CustomLinkTableOne',
props: {
code: {
type: String,
default: '',
},
inModal: {
type: Boolean,
default: false,
},
// 关联表关联数据
linkTableRelationProp: {
type: Object,
default: null,
},
// 是否展示系统按钮和自定义按钮
hideFormButton: {
type: Boolean,
default: false,
},
// 是否禁用表单字段
disabledProp: {
type: Boolean,
default: false,
},
},
data() {
return {
model: {},
form: this.$form.createForm(this),
}
},
methods: {
async add() {
console.log('自定义一对一 add')
this.model = {
fd_name: '',
fd_age: '',
id: new Date().getTime(),
}
const { id, ...rest } = this.model
this.form.setFieldsValue(rest)
// 通知父表单我已加载完毕,之后切换tab就不会再多次调用了, 可不写:这个方法内部的异步操作都需要使用await, 手动写:需要放在异步操作都完成,
this.$emit('loaded')
},
async edit() {
const { value, linkFieldName } = this.linkTableRelationProp
console.log('自定义一对一 edit: 外键:', linkFieldName, value)
// 模拟请求数据, 因为是一对一关系, 所以只需要根据 外键ID 查询
// this.model = await getAction('/getDataByForeignKey/' + value)
this.model = {
fd_name: '111',
fd_age: 'sss',
id: new Date().getTime(),
}
const { id: _, ...rest } = this.model
this.form.setFieldsValue(rest)
// 通知父表单我已加载完毕,之后切换tab就不会再多次调用了, 可不写:这个方法内部的异步操作都需要使用await, 手动写:需要放在异步操作都完成,
this.$emit('loaded')
},
async detail() {
const { value, linkFieldName } = this.linkTableRelationProp
console.log('自定义一对一 detail: 外键:', linkFieldName, value)
// 模拟请求数据, 因为是一对一关系, 所以只需要根据 外键ID 查询
// this.model = await getAction('/getDataByForeignKey/' + value)
this.model = {
fd_name: '111',
fd_age: 'sss',
id: new Date().getTime(),
}
const { id: _, ...rest } = this.model
this.form.setFieldsValue(rest)
// 通知父表单我已加载完毕,之后切换tab就不会再多次调用了, 可不写:这个方法内部的异步操作都需要使用await, 手动写:需要放在异步操作都完成,
this.$emit('loaded')
},
// 需要返回这个表的所有数据: id, 表单填写数据, 外键ID的值
// 如果自己调用接口提交, 这个函数返回个空对象就好
getSubmitValues() {
// 表单数据
const formValues = this.form.getFieldsValue()
// 赋值关联关系数据
const { value, linkFieldName } = this.linkTableRelationProp
const relationData = {
[linkFieldName]: value,
}
return { ...this.model, ...formValues, ...relationData }
},
},
}
</script>
<style></style>
一对多
<template>
<a-card :bordered="false">
<!-- 查询项 -->
<div class="table-page-search-wrapper" v-if="!hideSearch">
<a-form layout="inline" @keyup.enter.native="onSearch">
<a-row :gutter="24">
<a-col :span="6">
<a-form-item label="请输入姓名">
<a-input v-model="queryParam.fd_name" style="width: 100%"></a-input>
</a-form-item>
</a-col>
<a-col :span="6">
<a-form-item label="请输入年龄">
<a-input v-model="queryParam.fd_age" style="width: 100%"></a-input>
</a-form-item>
</a-col>
<!-- 是否固定在新起的一行的右侧 -->
<a-col :md="6" :sm="8">
<span :style="{ float: 'left', overflow: 'hidden' }" class="table-page-search-submitButtons">
<a-button type="primary" @click="onSearch" icon="search">查询</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<div class="table-page-operator-list">
<!-- 操作按钮区域 -->
<div class="table-operator" v-if="!hideToolbar">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
</div>
<!-- 列表 -->
<div class="list-container">
<div
v-if="!hideTableSelect"
class="ant-alert ant-alert-info"
style="display: flex; align-items: center; margin-bottom: 16px"
>
<i class="anticon anticon-info-circle ant-alert-icon"></i>
已选择 <a style="font-weight: 600">{{ selectedRowKeys.length }}</a
>项
<a style="margin-left: 24px" @click="clearSelect">清空</a>
</div>
<div class="auto-list">
<a-table
ref="cgformAutoList"
bordered
size="middle"
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:loading="loading"
style="min-height: 200px"
>
<!-- 操作列 -->
<a-space slot="action" slot-scope="text, record" v-if="!hideActionColumn || hideActionColumnButShowDetail">
<a @click.prevent="handleDetail(record)">详情</a>
<template v-if="!hideActionColumn">
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record)">
<a style="color: red !important">删除</a>
</a-popconfirm>
<a @click.prevent="handleEdit(record)">编辑</a>
</template>
</a-space>
</a-table>
</div>
</div>
</div>
</a-card>
</template>
<script>
// 自定义关联表一对多示例
export default {
name: 'CustomLinkTableN',
props: {
code: {
type: String,
default: '',
},
// 是否处于弹窗中(用openCustomModal打开的),影响一些样式
inModal: {
type: Boolean,
default: false,
},
// 隐藏表格操作列
hideActionColumn: {
type: Boolean,
default: false,
},
// 隐藏表格操作列但是展示详情按钮
hideActionColumnButShowDetail: {
type: Boolean,
default: false,
},
// 隐藏表格和表格上方的选择列
hideTableSelect: {
type: Boolean,
default: false,
},
// 隐藏查询项
hideSearch: {
type: Boolean,
default: false,
},
// 隐藏表格上方的操作按钮
hideToolbar: {
type: Boolean,
default: false,
},
// 作为关联表的关联数据
linkTableRelationProp: {
type: Object,
default: null,
},
// 自动加载数据
loadDataOnMount: {
type: Boolean,
default: true,
},
},
data() {
return {
queryParam: {},
dataSource: [],
loading: false,
selectedRowKeys: [],
}
},
computed: {
columns() {
const c = [
{
title: '姓名',
dataIndex: 'fd_name',
align: 'center',
},
{
title: '身份证',
dataIndex: 'fd_age',
align: 'center',
},
]
if (this.hideActionColumn && !this.hideActionColumnButShowDetail) return c
return [
...c,
{
title: '操作列',
key: 'action',
align: 'center',
scopedSlots: { customRender: 'action' },
},
]
},
},
methods: {
handleAdd() {
// 可以自己写表单, 自己写的时候记得添加数据的时候需要 根据 linkTableRelationProp 关联关系数据给外键字段赋值
// this.modal.visible=true; xxxx
// 如果是online, 也可以调用内置的online表单
this.$emit('add', {
defaultFormData: null, // 可以添加表单默认值
code: 'da94102aebae4f6db76d3405a32b288b',
})
},
handleEdit(record) {
const dataId = record.id
// 可以自己写表单, 自己写的时候记得添加数据的时候需要 根据 linkTableRelationProp 关联关系数据给外键字段赋值
// this.modal.visible=true; xxxx
// 如果是online, 也可以调用内置的online表单
this.$emit('edit', { id: dataId, code: 'da94102aebae4f6db76d3405a32b288b' })
},
handleDetail(record) {
const dataId = record.id
// 可以自己写表单, 自己写的时候记得添加数据的时候需要 根据 linkTableRelationProp 关联关系数据给外键字段赋值
// this.modal.visible=true; xxxx
// 如果是online, 也可以调用内置的online表单
this.$emit('detail', { id: dataId, code: 'da94102aebae4f6db76d3405a32b288b' })
},
handleDelete() {},
onSearch() {
this.loadData()
},
clearSelect() {},
// 下面四个方法是必须的, 然后在loadData/loadDataNoPage方法中触发loaded事件
async loadData() {
// 模拟请求数据
// 因为是一对多, 查询时候需要根据外键查
const { value, linkFieldName } = this.linkTableRelationProp
// this.dataSource = await getAction(`/getData?${linkFieldName}=${value}`)
console.log('自定义一对多加载数据,查询项:', linkFieldName, '=', value)
this.dataSource = [
{
fd_name: '张三111',
fd_age: '111111xxx',
id: '1607928908487892994',
},
{
fd_name: '李四22222',
fd_age: '22222xxxxx',
id: '1607932603350949890',
},
]
// 通知父表单我已加载完毕,之后切换tab就不会再多次调用了, 可不写:这个方法内部的异步操作都需要使用await, 手动写:需要放在异步操作都完成,
this.$emit('loaded')
},
loadDataNoPage() {
// 模拟请求数据
// 因为是一对多, 查询时候需要根据外键查
const { value, linkFieldName } = this.linkTableRelationProp
// this.dataSource = await getAction(`/getData?${linkFieldName}=${value}`)
console.log('自定义一对多加载数据,查询项:', linkFieldName, '=', value)
this.dataSource = [
{
fd_name: '张三111',
fd_age: '111111xxx',
id: '1607928908487892994',
},
{
fd_name: '李四22222',
fd_age: '22222xxxxx',
id: '1607932603350949890',
},
]
// 通知父表单我已加载完毕,之后切换tab就不会再多次调用了, 可不写:这个方法内部的异步操作都需要使用await, 手动写:需要放在异步操作都完成,
this.$emit('loaded')
},
clearDataSource() {
this.dataSource = []
},
// 只会在激活时候调用一次, 用于初始化一些数据(比如online的JS增强),可以是空方法
async initAutoList() {},
},
}
</script>
<style></style>
感谢您的反馈。如果您有关于如何使用 KubeSphere 的具体问题,请在 Slack 上提问。如果您想报告问题或提出改进建议,请在 GitHub 存储库中打开问题。
页面内容