IkPageFull
通过一个js文件生成搜索表单、表格、分页、表格字段筛选、新增修改弹窗页面及新UI的标准页面
props说明
除了以下列举的props,IkPageFull组件支持el-table的所有属性
例:<IkPageFull border stripe highlight-current-row />
const defaultProps = {
// iking-global-mainapp@1.1.19.1以上支持 是否启用默认的新增、编辑功能
isEdit: {
type: Boolean,
default: false
},
// 左侧标题
headerTitle: {
type: String,
default: ''
},
// 是否需要底部边框
headerBorder: {
type: Boolean,
default: false
},
// tabs
tabs: {
type: Array as PropType<Array<{ label: string; id: string | number; }>>,
default: () => []
},
// 字段名列表
fields: {
required: true,
type: Array as PropType<ISearchForm[]>,
default: () => []
},
// 表格数据
tableData: {
type: Array as PropType<Array<any>>,
default: () => []
},
// 初始首次查询
immediate: {
type: Boolean,
default: true
},
// 表格数据总条数
total: {
type: Number,
default: 0
},
// 查询方法
search: {
type: Function,
default: null
},
// 显示表格复选框
selection: {
type: Boolean,
default: false
},
// 序号
serial: {
type: Boolean,
default: true
},
loading: {
type: Boolean,
default: false
},
// tab页id,用于保存用户配置
tabId: {
type: Number || String,
default: 0
},
// 显示导出按钮
exportBtn: {
type: Boolean,
default: false
},
// 显示刷新按钮
refreshBtn: {
type: Boolean,
default: true
},
// 显示设置按钮
settingBtn: {
type: Boolean,
default: true
},
// 选中项数量
chooseLen: {
type: Number,
default: 0
},
// 当前页
current: {
type: Number,
default: 1
},
// 是否默认展开搜索条件
defaultShow: {
type: Boolean,
default: false
},
// 新增弹框的尺寸 sl l xl
dialogSize: {
type: String,
default: 'l'
},
// 弹框标题(不传的话,默认为“新增”/“修改”)
title: {
type: String,
default: ''
},
// 按钮权限
role: {
type: String,
default: ''
},
// formKey
formKey: {
type: Object,
default: () => {
return {}
}
},
// 新增修改弹框的默认属性
dialogProp: {
type: Object as PropType<any>,
default: () => { }
}
}
fields<ISearchForm>
字段说明
iking-global-mainapp
>= V1.0.15 为新版
1.0.15版本以上对字段做了修改,更容易配置;兼容旧版本写法,可以放心升级
export interface ISearchForm {
// iking-global-mainapp@1.1.19.1以上支持 是否做为新增、编辑的字段
isEdit?: boolean
/**
* @description: 支持element组件的所有属性
* @return {
* 默认类型为el-input,如果是el-input可以不传type字段
* 例:element组件支持的所有属性都可以写在formProp这个对象中
* 例如描述el-input:
* formProp: {
* type: 'el-input',
* clearable: true,
* maxlength: 15,
* placeholder: '请输入内容'
* }
* }
*/
formProp?: {
[key: string]: any,
// 使用el-radio-group或el-checkbox-group时,使用button形式
radioType?: 'button'
}
// 必填校验
rules?: Array<{
required: Boolean
message: string
trigger: any
}>
// 字段名称
label: string
// 绑定的字段名
key: string
// 特殊组件左侧select的key值(一个组件由左侧下拉,右侧input框组成的情况)或是用于选人组件的input值回显
// 展现如下图
selectKey?: string
// 人员选择组件用户存放/回显选中的人
handList?: Array<any>
// 渲染类型 当为特殊组件(可输入可下拉)时 type应当传递'select-input'
type?: string // element组件名称;如:el-input, el-select等等
// 默认值
value?: any
// 是否做为查询项 默认false
search?: boolean
// 是否作为新增修改的字段 默认false
isEdit?: boolean
// 在表格列中 是否默认显示
show?: boolean
// 搜索条件插槽
formSlot?: string
// 表格插槽
tableSlot?: string
// 下拉选项 select treeselect radio checkbox等
options?: Array<{
label: string
value: any
}>
emptyText?: string
// 占得列数 默认 1
col?: number
// 任意字段
[key: string]: any
// ************************************以下参数是为了兼容之前版本**************************************
placeholder?: string
// 最大输入长度
maxlength?: number
// 最大输入长度
minlength?: number
// 最多多少行, 超出后显示省略号
maxline?: number
// 输入状态 默认 false
disabled?: boolean
// number checkbox
// 最大值
max?: number
// 最小值
min?: number
// ===========================input-number=============================================
// 步长 默认 1
step?: number
// 数值精度 小数位数 默认0
precision?: number
// ===========================input-number end=============================================
// ===========================select treeselect=============================================
// 多选 默认false
multiple?: boolean
// 过滤 默认true
filterable?: boolean
// ===========================select treeselect end=============================================
// ==============================================treeselect==================================
// 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
nodeKey?: string
// 配置选项
props?: {
// 指定节点标签为节点对象的某个属性值
label?: string | Function
// 指定子树为节点对象的某个属性值
children?: string
// 指定节点选择框是否禁用为节点对象的某个属性值
disabled?: string | Function
// 自定义节点类名
class?: string | Function
}
// 是否高亮当前选中节点,默认值是 true
highlightCurrent?: boolean
// 是否默认展开所有节点 默认值是 false
defaultExpandAll?: boolean
// 是否在点击节点的时候展开或者收缩节点 如果为 false,则只有点箭头图标的时候才会展开或者收缩节点 默认值是 false
expandOnClickNode?: boolean
// 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
checkOnClickNode?: boolean
// 默认展开的节点的 key 的数组
defaultExpandedKeys?: Array<string>
// 节点是否可被选择 默认值是 true
showCheckbox?: boolean
// 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 true
checkStrictly?: boolean
// 默认勾选的节点的 key 的数组
defaultCheckedKeys?: Array<string>
// 当前选中的节点
currentNodeKey?: string | number
// 是否每次只打开一个同级树节点展开 默认false
accordion?: boolean
// ==============================================treeselect end==================================
// ============================================= 日期选择 Date Picker================================
// 文本框可输入
editable?: boolean
// 范围选择时开始日期的占位内容
startPlaceholder?: string
// 范围选择时结束日期的占位内容
endplaceholder?: string
// 显示类型
dateType?: EDateType
// 显示在输入框中的格式
format?: string
// DatePicker 下拉框的类名
popperclass?: string
// 选择范围时的分隔符
rangeSeparator?: string
// 可选,选择器打开时默认显示的时间
defaultValue?: Date | [Date, Date]
// 范围选择时选中日期所使用的当日内具体时刻
defaultTime?: Date | [Date, Date]
// 可选,绑定值的格式。 不指定则绑定值为 Date 对象
valueFormat?: string
// 一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参数。 应该返回一个 Boolean 值
disabledDate?: (time: Date) => boolean
typeOption?: Object
_list?: Array<any>
// ============================================= 日期选择 Date Picker end================================
// ============================================= 表格中的配置================================
// 支持el-table所有属性配置 直接在组件中使用即可 例:<IkPageFull stripe border />
// 表格 列宽度
width?: number
// 表格 列最小宽度
minWidth?: number
// 表格内容位置
align?: keyof typeof EAlign
}
// 组件类型
export enum EFormType {
// 输入框
'input' = 'input',
// text area
'area' = 'area',
// 数字输入框
'number' = 'number',
// 下拉
'select' = 'select',
// 日期选择
'date' = 'date',
// 日期时间选择
'datetime' = 'datetime',
// 多选checkbox
'checkbox' = 'checkbox',
// 单选radio
'radio' = 'radio',
// 树形下拉
'treeselect' = 'treeselect',
'choosePerson' = 'choosePerson' // 选择人员和部门
}
// 日期类型
export enum EDateType {
// 年
'year' = 'year',
// 月
'month' = 'month',
// 日
'date' = 'date',
// 多个日期
'dates' = 'dates',
// 日期时间
'datetime' = 'datetime',
// 周
'week' = 'week',
// 日期时间区间
'datetimerange' = 'datetimerange',
// 日期区间
'daterange' = 'daterange',
// 月区间
'monthrange' = 'monthrange'
}
export interface ISearchForm {
// 字段
key: string
// 字段名称
label: string
// 渲染类型
type?: keyof typeof EFormType // element组件名称;如:el-input, el-select等等
// 默认值
value?: any
// 是否做为查询项 默认false
search?: boolean
// 在表格列中 是否默认显示
show?: boolean
// 搜索条件插槽
formSlot?: string
// 表格插槽
tableSlot?: string
// 下拉选项 select treeselect radio checkbox等
options?: Array<{
label: string
value: any
}>
emptyText?: string
// 占得列数 默认 1
col?: number
placeholder?: string
// 最大输入长度
maxlength?: number
// 最大输入长度
minlength?: number
// 最多多少行, 超出后显示省略号
maxline?: number
// 输入状态 默认 false
disabled?: boolean
// number checkbox
// 最大值
max?: number
// 最小值
min?: number
// ===========================input-number=============================================
// 步长 默认 1
step?: number
// 数值精度 小数位数 默认0
precision?: number
// ===========================input-number end=============================================
// ===========================select treeselect=============================================
// 多选 默认false
multiple?: boolean
// 过滤 默认true
filterable?: boolean
// ===========================select treeselect end=============================================
// ==============================================treeselect==================================
// 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
nodeKey?: string
// 配置选项
props?: {
// 指定节点标签为节点对象的某个属性值
label?: string | Function
// 指定子树为节点对象的某个属性值
children?: string
// 指定节点选择框是否禁用为节点对象的某个属性值
disabled?: string | Function
// 自定义节点类名
class?: string | Function
}
// 是否高亮当前选中节点,默认值是 true
highlightCurrent?: boolean
// 是否默认展开所有节点 默认值是 false
defaultExpandAll?: boolean
// 是否在点击节点的时候展开或者收缩节点 如果为 false,则只有点箭头图标的时候才会展开或者收缩节点 默认值是 false
expandOnClickNode?: boolean
// 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
checkOnClickNode?: boolean
// 默认展开的节点的 key 的数组
defaultExpandedKeys?: Array<string>
// 节点是否可被选择 默认值是 true
showCheckbox?: boolean
// 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 true
checkStrictly?: boolean
// 默认勾选的节点的 key 的数组
defaultCheckedKeys?: Array<string>
// 当前选中的节点
currentNodeKey?: string | number
// 是否每次只打开一个同级树节点展开 默认false
accordion?: boolean
// ==============================================treeselect end==================================
// ============================================= 日期选择 Date Picker================================
// 文本框可输入
editable?: boolean
// 范围选择时开始日期的占位内容
startPlaceholder?: string
// 范围选择时结束日期的占位内容
endplaceholder?: string
// 显示类型
dateType?: EDateType
// 显示在输入框中的格式
format?: string
// DatePicker 下拉框的类名
popperclass?: string
// 选择范围时的分隔符
rangeSeparator?: string
// 可选,选择器打开时默认显示的时间
defaultValue?: Date | [Date, Date]
// 范围选择时选中日期所使用的当日内具体时刻
defaultTime?: Date | [Date, Date]
// 可选,绑定值的格式。 不指定则绑定值为 Date 对象
valueFormat?: string
// 一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参数。 应该返回一个 Boolean 值
disabledDate?: (time: Date) => boolean
typeOption?: Object
_list?: Array<any>
// ============================================= 日期选择 Date Picker end================================
// ============================================= 表格中的配置================================
// 支持el-table所有属性配置 直接在组件中使用即可 例:<IkPageFull stripe border />
// 表格 列宽度
width?: number
// 表格 列最小宽度
minWidth?: number
// 表格内容位置
align?: keyof typeof EAlign
type为select-input
时 左侧为下拉框+右侧输入框 type为choosePerson
时 点击input框,弹出人员组件。key
绑定的值为传给后端的人员数组,selectKey
用于input回显逸已选人员姓名,handList
用于存放/回显选中的人员数组
新增/修改功能具体代码示例
默认“新增”是button,支持插槽(#headerRight)。如果使用按钮,则不需要插槽#headerRight,如果采用自定义图标,“新增”调用的方法同修改一样,传参为null即可。
例:
主页面配置
IkPageFull使用时,无需传入is-edit:true,只需要在配置fields时传入。
fields页面配置
配置fields时,如果需要展示在新增修改页面的字段,则需要设置isEdit:true
,然后声明组件类型(例如type: 'el-input'
)。formProp
支持element组件的所有属性,表单校验可添加rules
。(下图为输入框,人员选择组件的示例代码)
solt插槽说明
固定插槽
headerLeft
:左侧内容,如果props传递了header-title的同时使用了此插槽,header-title将失效headerRight
:右侧内容,使用此插槽自定义右侧内容,搜索、刷新、设置按钮不会消失,只能通过props传值隐藏
插槽页面位置如下图:
table
:表格插槽,使用此插槽时,表格内容将完全有开发自定义。 插槽页面位置如下图:
注意
当使用自定义table插槽时,选中项数据应该由开发自己获取,同时需要通过props将chooseLen传递给组件
selectionRight
:选中项右侧插槽,页面默认放置删除(事件名delete)、下载(事件名download)两个按钮,点击会触发相应事件并返回选中数据
插槽页面位置如下图:
动态插槽
动态插槽
在定义字段列表时,我们可以针对每一个字段自定义它在form和table中的插槽
注意
自定义form和table中的插槽时,同一个IkPageFull组件不能有重复的slot名称
表格slot会通过插槽传递当前行的所有信息
示例
<script lang="ts" setup name="ManageUser">
const fieldList: Ref<ISearchForm[]> = ref([
{
key: 'name',
label: '姓名',
show: true,
width: 160,
// 自定义表格slot
tableSlot: 'name',
// 自定义form的slot, 名称不可与tableSlot相同
formSlot: 'formname'
search: true,
formProp: {
clearable: true,
placeholder: '请输入姓名',
maxlength: 12
}
}
])
<template>
<IkPageFull
v-model="pageData"
header-title="用户列表"
:fields="fieldList"
:table-data="userData"
:total="tadaTotal"
:loading="loading"
:search="queryUser"
>
// 表单slot
<template #formname>
</template>
// 表格slot
<template #name="{ data }">
</template>
</IkPageFull>
</template>
</script>
完整示例
<script lang="ts" setup name="ManageUser">
// 当fieldList字段很多时,建议单独放在一个ts文件内
const fieldList: Ref<ISearchForm[]> = ref([
{
key: 'name',
label: '姓名',
show: true,
width: 160,
tableSlot: 'name',
search: true,
formProp: {
clearable: true,
placeholder: '请输入姓名',
maxlength: 5
}
},
{
key: 'postId',
label: '岗位',
type: 'el-select',
options: postIdList,
show: true,
tableSlot: 'post',
search: true
},
// input
{
key: 'appId',
label: 'AppId',
show: true,
minWidth: 100,
search: true,
isEdit: true,
type: 'el-input',
formProp: {
clearable: true
},
rules: [{
required: true,
message: '请输入AppId',
trigger: 'blur'
}]
},
{
key: 'appId0',
label: '人员',
show: true,
minWidth: 100,
search: true,
isEdit: true,
type: 'choosePerson',
selectKey: 'personName',
handList: [],
formProp: {
clearable: true,
readonly: true
},
rules: [{
required: true,
message: '请选择人员',
trigger: 'blur'
}]
},
{
key: '',
label: '操作',
show: true,
width: 148,
tableSlot: 'operate',
fixed: 'right'
}
])
// 用户数据
const userData = ref([])
// 查询状态
const loading = ref(false)
// 总条数
const tadaTotal = ref(0)
// 组件返回的查询参数,包含分页和查询字段
const pageData = ref()
const pageFullRef = ref()
// 查询方法
const queryUser = async () => {
loading.value = true
const param = {
...pageData.value
}
const { success, data, total, msg } = await userApi.getUserList(param)
tadaTotal.value = total ?? 0
if (success) {
userData.value = success ? data : []
loading.value = false
}
else {
msgError(msg)
}
}
/**
* @description: 表单提交数据
* @param {*} form
* @return {*}
*/
const handleAdd = async (form: any) => {
const { msg, success, data } = form.id ? await msgApi.updateWechatMsg(form) : await msgApi.addWechatMsg(form)
if (success)
queryUser()
else
msgError(msg)
}
/**
* @description: 修改
* @param {*} row
* @return {*}
*/
const handleUpdate = (row: any) => {
pageFullRef.value?.handAdd(row)
}
</script>
<template>
<!-- IkPageMain容器组件,见后面单独说明 -->
<IkPageMain fixed>
<!-- 页面组件 -->
<IkPageFull
ref="pageFullRef"
v-model="pageData"
header-title="用户列表"
:fields="fieldList"
:table-data="userData"
:total="tadaTotal"
:loading="loading"
:search="queryUser"
dialog-size="sl"
role="$ADD-WECHAT"
:form-key="formKey"
@addFunction="handleAdd"
>
<!-- 搜索slot -->
<template #headerRight>
<el-button v-role="'$ADD-USER'" type="primary" @click="handAddUser">{{ t('user.add') }}</el-button>
</template>
<!-- 表格solt -->
<template #name="{ data }">
<IkSideText
:avatar="data.row.avatar"
:name="data.row.name"
:text="data.row.name"
:sub-text="ikArray.listToString(data?.row.departments, 'deptName', ',') "
/>
</template>
<template #role="{ data }">
{{ ikArray.listToString(data.row?.roles, 'roleName', ', ') }}
</template>
<template #locked="{ data }">
<el-switch
v-model="data.row.locked"
:loading="lockLoading && lockKey === data.row.id"
inline-prompt
:active-value="false"
:inactive-value="true"
@change="handLock(data.row)"
/>
</template>
<template #operate="{ data }">
<IkBtnContent :num="4">
<IkSvgIcon
v-role="'UPDATE-USER'"
name="icon-bianji"
show-bg
size="big"
/>
</IkBtnContent>
</template>
</IkPageFull>
</IkPageMain>
含Tab页的完整示例
Tab页
含Tab页时,可以借助IkPageTabs实现
<script lang="ts" setup name="ManageLog">
import { useFields } from './fields'
import { logApi } from '@/MainApp/apis/log'
const { operationFieldList, loginFields, systemFieldList } = useFields()
const router = useRouter()
const route = useRoute()
// 组件返回的查询参数,包含分页和查询字段
const pageData = reactive({
login: undefined,
operate: null,
system: null
})
const logData = reactive({
login: [],
operate: [],
system: []
})
const countTotal = ref(0)
const loading = ref(false)
const activeLog = ref('login')
// 查询方法
const queryLogs = async () => {
await nextTick()
const ACTIVE = activeLog.value
loading.value = true
const log = { ...(pageData as any)[ACTIVE] }
const { success, data, total }
= ACTIVE === 'login'
? await logApi.getPageLogs(log)
: ACTIVE === 'operate'
? await logApi.getOperateLogs(log)
: await logApi.getSystemLogs(log);
(logData as any)[ACTIVE] = success ? data : []
countTotal.value = Number(total)
loading.value = false
}
const handleDetail = (row: any) => {
router.push({ path: `${route.path}/log-detail`, query: { id: row.id } })
}
const tabs = [{ id: 'login', label: '登录日志' }, { id: 'operate', label: '操作日志' }, { id: 'system', label: '系统日志' }]
</script>
<template>
<IkPageMain fixed>
<IkPageTabs v-model="activeLog" :tabs="tabs" @tab-click="queryLogs">
<template #login>
<IkPageFull
v-model="pageData.login"
tab-id="login"
:fields="loginFields"
:table-data="logData.login"
:total="countTotal"
:loading="loading"
:search="queryLogs"
>
<template #success="{ data }">
<IkStatu :type="data.row.success ? 'success' : 'warning'" :title="data.row.success ? '成功' : '失败'" />
</template>
</IkPageFull>
</template>
<template #operate>
<IkPageFull
v-model="pageData.operate"
:immediate="false"
tab-id="operate"
:fields="operationFieldList"
:table-data="logData.operate"
:total="countTotal"
:loading="loading"
:search="queryLogs"
>
<template #success="{ data }">
<IkStatu :type="data.row.success ? 'success' : 'warning'" :title="data.row.success ? '成功' : '失败'" />
</template>
</IkPageFull>
</template>
<template #system>
<IkPageFull
v-model="pageData.system"
:immediate="false"
tab-id="system"
:fields="systemFieldList"
:table-data="logData.system"
:total="countTotal"
:loading="loading"
:search="queryLogs"
>
<template #operate="{ data }">
<IkSvgIcon
show-bg
size="small"
name="icon-ziyuanliebiao"
@click="handleDetail(data.row)"
/>
</template>
</IkPageFull>
</template>
</IkPageTabs>
</IkPageMain>
</template>