Default Changelist

feature/qzw
秦泽旺 1 month ago
parent 4d9202bace
commit 449117fb99

@ -1,121 +1,166 @@
<template> <template>
<!-- 创建一个 div 元素通过动态绑定 class 属性根据组件的不同属性状态来添加相应的类名prefixClslastClsblockClsgridCls 这些类名会根据组件内部的计算属性和传入的属性值来确定是否添加 -->
<div :class="[prefixCls, lastCls, blockCls, gridCls]"> <div :class="[prefixCls, lastCls, blockCls, gridCls]">
<!-- 通过 v-if 指令判断 title 属性是否有值如果有值则创建一个带有 antd-pro-components-standard-form-row-index-label 类名的 div 容器用于展示标题内容 -->
<div v-if="title" class="antd-pro-components-standard-form-row-index-label"> <div v-if="title" class="antd-pro-components-standard-form-row-index-label">
<!-- span 元素内使用双括号插值语法展示 title 属性的值用于在页面上显示对应的标题文字 -->
<span>{{ title }}</span> <span>{{ title }}</span>
</div> </div>
<!-- 创建一个带有 antd-pro-components-standard-form-row-index-content 类名的 div 容器用于放置通过插槽传入的内容 -->
<div class="antd-pro-components-standard-form-row-index-content"> <div class="antd-pro-components-standard-form-row-index-content">
<!-- 使用默认插槽<slot>允许外部组件在使用该组件时插入自定义的内容增强组件的复用性和灵活性 -->
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
// classes
const classes = [ const classes = [
'antd-pro-components-standard-form-row-index-standardFormRowBlock', 'antd-pro-components-standard-form-row-index-standardFormRowBlock',
'antd-pro-components-standard-form-row-index-standardFormRowGrid', 'antd-pro-components-standard-form-row-index-standardFormRowGrid',
'antd-pro-components-standard-form-row-index-standardFormRowLast' 'antd-pro-components-standard-form-row-index-standardFormRowLast'
] ];
export default { export default {
name: 'StandardFormRow', name: 'StandardFormRow',
props: { props: {
// prefixCls 'antd-pro-components-standard-form-row-index-standardFormRow'
prefixCls: { prefixCls: {
type: String, type: String,
default: 'antd-pro-components-standard-form-row-index-standardFormRow' default: 'antd-pro-components-standard-form-row-index-standardFormRow'
}, },
// title undefined v-if
title: { title: {
type: String, type: String,
default: undefined default: undefined
}, },
// last true false
last: { last: {
type: Boolean type: Boolean
}, },
// block
block: { block: {
type: Boolean type: Boolean
}, },
// grid
grid: { grid: {
type: Boolean type: Boolean
} }
}, },
computed: { computed: {
// lastCls this.last last true classes null
lastCls () { lastCls () {
return this.last ? classes[2] : null return this.last? classes[2] : null;
}, },
// blockCls this.block classes true null
blockCls () { blockCls () {
return this.block ? classes[0] : null return this.block? classes[0] : null;
}, },
// gridCls this.grid classes true null
gridCls () { gridCls () {
return this.grid ? classes[1] : null return this.grid? classes[1] : null;
} }
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// index.less mixin便
@import '../index.less'; @import '../index.less';
// antd-pro-components-standard-form-row-index-standardFormRow
.antd-pro-components-standard-form-row-index-standardFormRow { .antd-pro-components-standard-form-row-index-standardFormRow {
// flexbox便
display: flex; display: flex;
// 16px
margin-bottom: 16px; margin-bottom: 16px;
// 16px
padding-bottom: 16px; padding-bottom: 16px;
// 1px 线 @border-color-split index.less
border-bottom: 1px dashed @border-color-split; border-bottom: 1px dashed @border-color-split;
/deep/ .ant-form-item { // 使 /deep/ 穿 Vue .ant-form-item 24px
/deep/.ant-form-item {
margin-right: 24px; margin-right: 24px;
} }
/deep/ .ant-form-item-label label { // 使 /deep/ .ant-form-item-label label 0 @text-color
/deep/.ant-form-item-label label {
margin-right: 0; margin-right: 0;
color: @text-color; color: @text-color;
} }
/deep/ .ant-form-item-label, // .ant-form-item-label .ant-form-item-control 0 32px使
/deep/.ant-form-item-label,
.ant-form-item-control { .ant-form-item-control {
padding: 0; padding: 0;
line-height: 32px; line-height: 32px;
} }
// antd-pro-components-standard-form-row-index-label
.antd-pro-components-standard-form-row-index-label { .antd-pro-components-standard-form-row-index-label {
//
flex: 0 0 auto; flex: 0 0 auto;
// 24px
margin-right: 24px; margin-right: 24px;
// @heading-color
color: @heading-color; color: @heading-color;
// @font-size-base
font-size: @font-size-base; font-size: @font-size-base;
//
text-align: right; text-align: right;
& > span { & > span {
// span 使
display: inline-block; display: inline-block;
// 32px
height: 32px; height: 32px;
// 32px使
line-height: 32px; line-height: 32px;
&::after { &::after {
// 使 ::after span
content: ''; content: '';
} }
} }
} }
// antd-pro-components-standard-form-row-index-content
.antd-pro-components-standard-form-row-index-content { .antd-pro-components-standard-form-row-index-content {
// 0
flex: 1 1 0; flex: 1 1 0;
/deep/ .ant-form-item:last-child { // 使 /deep/ .ant-form-item:last-child 0
/deep/.ant-form-item:last-child {
margin-right: 0; margin-right: 0;
} }
} }
// antd-pro-components-standard-form-row-index-standardFormRowLast last
&.antd-pro-components-standard-form-row-index-standardFormRowLast { &.antd-pro-components-standard-form-row-index-standardFormRowLast {
// 使
margin-bottom: 0; margin-bottom: 0;
//
padding-bottom: 0; padding-bottom: 0;
//
border: none; border: none;
} }
// antd-pro-components-standard-form-row-index-standardFormRowBlock blockCls block
&.antd-pro-components-standard-form-row-index-standardFormRowBlock { &.antd-pro-components-standard-form-row-index-standardFormRowBlock {
/deep/ .ant-form-item, // 使 /deep/ .ant-form-item div.ant-form-item-control-wrapper
/deep/.ant-form-item,
div.ant-form-item-control-wrapper { div.ant-form-item-control-wrapper {
display: block; display: block;
} }
} }
// antd-pro-components-standard-form-row-index-standardFormRowGrid gridCls grid
&.antd-pro-components-standard-form-row-index-standardFormRowGrid { &.antd-pro-components-standard-form-row-index-standardFormRowGrid {
/deep/ .ant-form-item, // 使 /deep/ .ant-form-item div.ant-form-item-control-wrapper
div.ant-form-item-control-wrapper { /deep/.ant-form-item,
display: block; div.ant-form-item-control-wrapper {
} display: block;
/deep/ .ant-form-item-label { }
float: left; // 使 /deep/ .ant-form-item-label
} /deep/.ant-form-item-label {
float: left;
}
} }
} }

@ -1,3 +1,6 @@
import StandardFormRow from './StandardFormRow' // 从当前目录下的“StandardFormRow”文件在Vue项目等环境里通常这个文件会定义一个相关的组件、模块比如是一个.vue文件或者.js文件等中导入名为“StandardFormRow”的模块。
// 具体这个模块代表的是一个组件、函数或者类等取决于“StandardFormRow”文件内部的定义情况。
import StandardFormRow from './StandardFormRow';
export default StandardFormRow // 将导入的“StandardFormRow”模块原样导出这样在其他的模块或者文件中就可以通过相应的导入语句引入这个“StandardFormRow”方便复用其内部所定义的功能、组件等相关内容。
export default StandardFormRow;

@ -1,75 +1,81 @@
import T from 'ant-design-vue/es/table/Table' // 从 'ant-design-vue/es/table/Table' 模块中导入名为 'T' 的对象(推测这里的 'T' 很可能是 Ant Design Vue 框架中 Table 组件相关的定义或者配置对象,后续代码中会基于它进行一些扩展和功能整合)
import get from 'lodash.get' import T from 'ant-design-vue/es/table/Table';
// 从 'lodash.get' 模块中导入名为 'get' 的函数lodash.get 常用于从嵌套的对象结构中安全地获取指定路径的值,在代码中可能用于获取表格行数据中特定字段的值等操作)
import get from 'lodash.get';
export default { export default {
data () { data() {
return { return {
// 定义一个数组 needTotalList用于存储需要进行总计统计的列相关信息可能后续会根据表格数据来计算每列的合计值等具体要看相关方法的使用
needTotalList: [], needTotalList: [],
// 定义一个数组 selectedRows用于存储当前选中的表格行数据当表格支持行选择功能时会用到
selectedRows: [], selectedRows: [],
// 定义一个数组 selectedRowKeys用于存储当前选中的表格行对应的唯一标识通常是每行数据的一个特定字段作为键值方便进行行的选中状态管理等操作
selectedRowKeys: [], selectedRowKeys: [],
// 定义一个布尔值 localLoading用于标记表格数据是否正在加载中初始化为 false表示初始状态下没有正在加载数据
localLoading: false, localLoading: false,
// 定义一个数组 localDataSource用于存储表格实际展示的数据初始为空数组后续会通过加载数据的方法来填充真实数据
localDataSource: [], localDataSource: [],
// 定义一个对象 localPagination通过复制 this.pagination可能是从父组件传入的分页相关配置对象来初始化用于管理表格的分页相关信息如当前页码、每页显示数量等在组件内部进行分页相关操作时会基于这个对象进行修改和维护
localPagination: Object.assign({}, this.pagination) localPagination: Object.assign({}, this.pagination)
} }
}, },
props: Object.assign({}, T.props, { props: Object.assign({}, T.props, {
// 定义 rowKey 属性,类型可以是字符串或者函数,用于指定表格每行数据的唯一标识字段或生成唯一标识的函数,默认值为 'key',意味着如果外部没有传入该属性指定的标识方式,默认以每行数据中的 'key' 字段作为唯一标识
rowKey: { rowKey: {
type: [String, Function], type: [String, Function],
default: 'key' default: 'key'
}, },
// 定义 data 属性类型为函数且是必需属性required: true这个函数用于获取表格的数据外部组件需要传入一个符合要求的函数该函数接收一些参数比如分页、筛选、排序等条件参数并返回相应的数据通常是包含数据数组以及分页相关信息等的对象
data: { data: {
type: Function, type: Function,
required: true required: true
}, },
// 定义 pageNum 属性,类型为数字,用于指定表格初始的页码,默认值为 1表示默认显示第一页数据
pageNum: { pageNum: {
type: Number, type: Number,
default: 1 default: 1
}, },
// 定义 pageSize 属性,类型为数字,用于指定每页显示的数据条数,默认值为 10即每页默认展示 10 条数据
pageSize: { pageSize: {
type: Number, type: Number,
default: 10 default: 10
}, },
// 定义 showSizeChanger 属性,类型为布尔值,用于控制是否显示每页显示数量的切换组件(例如可以切换每页显示 10 条、20 条等不同数量),默认值为 true表示默认显示该切换组件
showSizeChanger: { showSizeChanger: {
type: Boolean, type: Boolean,
default: true default: true
}, },
// 定义 size 属性,类型为字符串,可能用于控制表格的尺寸大小等样式相关属性,默认值为 'default',具体的尺寸样式对应关系要看 Ant Design Vue 框架中 Table 组件的实现
size: { size: {
type: String, type: String,
default: 'default' default: 'default'
}, },
/** /**
* alert: { * 定义 alert 属性类型可以是对象或者布尔值默认值为 null当为对象时可能包含一些与表格数据提示相关的配置比如是否显示提示信息清除提示相关的回调函数等从注释中的示例结构来看当为布尔值时可能用于简单地控制提示功能的开启或关闭
* show: true,
* clear: Function
* }
*/ */
alert: { alert: {
type: [Object, Boolean], type: [Object, Boolean],
default: null default: null
}, },
// 定义 rowSelection 属性,类型为对象,默认值为 null用于配置表格行的选择功能相关设置比如可以设置是否支持多选、单选等选择模式以及相关的回调函数等具体取决于 Ant Design Vue 框架的 Table 组件支持的配置项)
rowSelection: { rowSelection: {
type: Object, type: Object,
default: null default: null
}, },
/** @Deprecated */ /** @Deprecated 表示该属性已被弃用,建议后续不再使用此属性,这里的 showAlertInfo 用于控制是否显示某种提示信息(具体要看之前的业务逻辑,但既然被标记弃用,应该有替代的实现方式或者不再需要此功能了) */
showAlertInfo: { showAlertInfo: {
type: Boolean, type: Boolean,
default: false default: false
}, },
// 定义 showPagination 属性,类型可以是字符串或者布尔值,用于控制是否显示分页组件以及分页相关的显示策略,默认值为 'auto',可能意味着会根据数据情况自动判断是否显示分页(比如数据条数是否超过每页显示数量等情况来决定)
showPagination: { showPagination: {
type: String | Boolean, type: String | Boolean,
default: 'auto' default: 'auto'
}, },
/** /**
* enable page URI mode * 定义 pageURI 属性类型为布尔值用于控制是否启用基于页面 URI统一资源标识符比如 URL 中的路径部分的分页模式默认值为 false开启后可能会根据页面 URL 中的参数来确定当前页码等分页信息例如不同的页码对应不同的 URL 路径 /users/1/users/2 等这种形式来表示不同页码的数据访问
*
* e.g:
* /users/1
* /users/2
* /users/3?queryParam=test
* ...
*/ */
pageURI: { pageURI: {
type: Boolean, type: Boolean,
@ -77,7 +83,8 @@ export default {
} }
}), }),
watch: { watch: {
'localPagination.current' (val) { // 监听 localPagination 对象的 current 属性变化(通常 current 表示当前页码),当页码发生变化时,如果 pageURI 为 true即启用了基于页面 URI 的分页模式),则通过 $router.push 方法来更新页面路由,将当前页码信息添加到路由参数中,实现页面 URL 与分页页码的同步更新
'localPagination.current'(val) {
this.pageURI && this.$router.push({ this.pageURI && this.$router.push({
...this.$route, ...this.$route,
name: this.$route.name, name: this.$route.name,
@ -86,166 +93,216 @@ export default {
}) })
}) })
}, },
pageNum (val) { // 监听 pageNum 属性变化,当 pageNum 改变时,将 localPagination 对象中的 current 属性更新为新的 pageNum 值,保持组件内部的分页相关数据的一致性
pageNum(val) {
Object.assign(this.localPagination, { Object.assign(this.localPagination, {
current: val current: val
}) })
}, },
pageSize (val) { // 监听 pageSize 属性变化,当 pageSize 改变时,相应地更新 localPagination 对象中的 pageSize 属性值,以适配每页显示数量的改变
pageSize(val) {
Object.assign(this.localPagination, { Object.assign(this.localPagination, {
pageSize: val pageSize: val
}) })
}, },
showSizeChanger (val) { // 监听 showSizeChanger 属性变化,根据其值来更新 localPagination 对象中的 showSizeChanger 属性,用于控制每页显示数量切换组件的显示隐藏状态
showSizeChanger(val) {
Object.assign(this.localPagination, { Object.assign(this.localPagination, {
showSizeChanger: val showSizeChanger: val
}) })
} }
}, },
created () { created() {
const { pageNo } = this.$route.params // 从当前页面路由的参数中获取 pageNo 参数值(前提是基于页面 URI 的分页模式启用且路由参数中有该值),并将其转换为整数(如果存在的话),否则使用传入的 pageNum 属性值作为初始页码
const localPageNum = this.pageURI && (pageNo && parseInt(pageNo)) || this.pageNum const {pageNo} = this.$route.params;
const localPageNum = this.pageURI && (pageNo && parseInt(pageNo)) || this.pageNum;
// 根据 showPagination 属性的值判断是否需要初始化 localPagination 对象,如果 showPagination 的值在 ['auto', true] 数组中(表示需要显示分页或者自动根据情况判断显示分页),则将 localPagination 对象更新为包含当前页码、每页显示数量以及每页显示数量切换组件显示状态等相关信息的对象
this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, { this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, {
current: localPageNum, current: localPageNum,
pageSize: this.pageSize, pageSize: this.pageSize,
showSizeChanger: this.showSizeChanger showSizeChanger: this.showSizeChanger
}) });
this.needTotalList = this.initTotalList(this.columns) // 调用 initTotalList 方法传入表格的列信息this.columns可能从父组件传入或者在组件内部其他地方定义初始化需要进行总计统计的列信息列表并将结果赋值给 needTotalList 属性
this.loadData() this.needTotalList = this.initTotalList(this.columns);
// 调用 loadData 方法开始加载表格数据,触发数据获取的流程
this.loadData();
}, },
methods: { methods: {
/** /**
* 表格重新加载方法 * 表格重新加载方法
* 如果参数为 true, 则强制刷新到第一页 * 如果参数为 true则强制刷新到第一页重新获取数据进行展示
* @param Boolean bool * @param Boolean bool 一个布尔类型的参数默认值为 false用于控制是否强制刷新到第一页
*/ */
refresh (bool = false) { refresh(bool = false) {
// 如果传入的 bool 参数为 true就重置 localPagination 对象中的当前页码current为 1同时保持每页显示数量pageSize为组件当前设定的值this.pageSize
// 这里使用 Object.assign 进行对象属性的合并赋值,确保只更新需要改变的属性,而不影响 localPagination 中的其他属性。
bool && (this.localPagination = Object.assign({}, { bool && (this.localPagination = Object.assign({}, {
current: 1, pageSize: this.pageSize current: 1,
})) pageSize: this.pageSize
this.loadData() }));
// 调用 loadData 方法,触发数据加载流程,根据更新后的分页设置(如果有强制刷新到第一页的操作)获取最新的数据并更新表格展示内容。
this.loadData();
}, },
/** /**
* 加载数据方法 * 加载数据方法
* @param {Object} pagination 分页选项器 * 此方法用于根据传入的分页过滤排序等条件参数向数据源请求数据并处理返回的数据更新组件内部相关的数据状态如分页信息表格数据源等
* @param {Object} filters 过滤条件 * @param {Object} pagination 分页选项器包含分页相关的参数比如当前页码每页显示数量等信息由表格组件的分页交互操作产生
* @param {Object} sorter 排序条件 * @param {Object} filters 过滤条件包含用户设置的筛选条件信息用于从数据源筛选出符合条件的数据
* @param {Object} sorter 排序条件包含用户对表格列进行排序操作产生的相关条件比如排序字段排序顺序等信息
*/ */
loadData (pagination, filters, sorter) { loadData(pagination, filters, sorter) {
this.localLoading = true // 将 localLoading 属性设置为 true表示数据开始加载通常可以在页面上通过显示加载动画等方式提示用户正在获取数据。
this.localLoading = true;
// 构建一个 parameter 对象用于整合传递给获取数据的函数this.data的参数。
// 从 pagination 参数(如果存在)、组件内部的 localPagination 对象或者默认的 pageNum 和 pageSize 属性中获取当前页码和每页显示数量相关信息。
// 同时,根据 sorter 参数(如果存在排序相关信息)获取排序字段和排序顺序信息,以及合并 filters 参数中的过滤条件信息。
const parameter = Object.assign({ const parameter = Object.assign({
pageNo: (pagination && pagination.current) || pageNo: (pagination && pagination.current) ||
this.localPagination.current || this.pageNum, this.localPagination.current || this.pageNum,
pageSize: (pagination && pagination.pageSize) || pageSize: (pagination && pagination.pageSize) ||
this.localPagination.pageSize || this.pageSize this.localPagination.pageSize || this.pageSize
}, },
(sorter && sorter.field && { (sorter && sorter.field && {
sortField: sorter.field sortField: sorter.field
}) || {}, }) || {},
(sorter && sorter.order && { (sorter && sorter.order && {
sortOrder: sorter.order sortOrder: sorter.order
}) || {}, { }) || {}, {
...filters ...filters
} }
) );
const result = this.data(parameter) // 调用 this.data 函数(外部传入的用于获取表格数据的函数),传入构建好的 parameter 参数,获取数据结果。返回的结果通常是一个包含数据数组以及分页相关信息(如总记录数、当前页码等)的对象(具体结构取决于数据接口的返回约定)。
// 对接自己的通用数据接口需要修改下方代码中的 r.pageNo, r.totalCount, r.data const result = this.data(parameter);
// eslint-disable-next-line // 以下代码用于处理异步数据获取的情况(当返回结果是一个 Promise 对象时,说明是异步获取数据,比如通过网络请求获取后端接口返回的数据),需要对返回的 Promise 进行 then 操作来处理成功获取数据后的逻辑。
// eslint-disable-next-line这行注释是用于告诉 ESLint 代码检查工具忽略下一行代码可能存在的相关规则检查(可能是因为下一行代码的写法不符合某些 ESLint 默认规则,但此处是有意为之)。
if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') { if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
result.then(r => { result.then(r => {
// 根据从接口返回的数据r 对象)更新 localPagination 对象中的相关分页信息,包括当前页码、总记录数、每页显示数量切换组件的显示状态以及每页显示数量等,保持组件内部的分页相关数据与接口返回的数据一致。
this.localPagination = Object.assign({}, this.localPagination, { this.localPagination = Object.assign({}, this.localPagination, {
current: r.pageNo, // 返回结果中的当前分页数 current: r.pageNo, // 返回结果中的当前分页数
total: r.totalCount, // 返回结果中的总记录数 total: r.totalCount, // 返回结果中的总记录数
showSizeChanger: this.showSizeChanger, showSizeChanger: this.showSizeChanger,
pageSize: (pagination && pagination.pageSize) || pageSize: (pagination && pagination.pageSize) ||
this.localPagination.pageSize this.localPagination.pageSize
}) });
// 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页 // 如果返回的数据数组长度为 0表示没有数据了可能是因为删除了所有数据等情况且当前页码大于 1则自动将当前页码减 1并再次调用 loadData 方法重新加载数据,避免出现空页面的情况,确保页面始终有数据展示(如果有上一页数据的话)。
if (r.data.length === 0 && this.localPagination.current > 1) { if (r.data.length === 0 && this.localPagination.current > 1) {
this.localPagination.current-- this.localPagination.current--;
this.loadData() this.loadData();
return return;
} }
// 这里用于判断接口是否有返回 r.totalCount 或 this.showPagination = false // 这里用于判断接口是否有返回 r.totalCount总记录数或 this.showPagination = false 的情况。
// 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能 // 当满足这些情况时,表示数据不满足分页大小(比如总记录数小于每页显示数量或者明确不需要分页显示),则将 localPagination 对象的 hideOnSinglePage 属性设置为 true关闭 table 分页功能(可能是隐藏分页组件等相关操作,具体要看组件中对该属性的使用方式)。
(!this.showPagination || !r.totalCount && this.showPagination === 'auto') && (this.localPagination.hideOnSinglePage = true);
(!this.showPagination || !r.totalCount && this.showPagination === 'auto') && (this.localPagination.hideOnSinglePage = true) // 将返回结果中的数据数组赋值给 localDataSource 属性,用于更新表格实际展示的数据,使得表格展示最新获取到的数据内容。
this.localDataSource = r.data // 返回结果中的数组数据 this.localDataSource = r.data; // 返回结果中的数组数据
this.localLoading = false // 将 localLoading 属性设置为 false表示数据加载完成通常可以相应地隐藏加载提示比如停止显示加载动画告知用户数据已加载完毕。
this.localLoading = false;
}) })
} }
}, },
initTotalList (columns) { /**
const totalList = [] * 初始化用于总计统计的列信息列表方法
* 遍历传入的表格列信息columns找出需要进行总计统计通过列对象中的 needTotal 属性判断的列为这些列创建新的对象添加一个初始值为 0 total 属性用于后续统计每列数据的总和最后返回包含这些需要统计列信息的数组
* @param columns 表格的列信息数组每个元素是一个列对象包含列的相关配置和属性
* @returns {Array} 返回一个数组数组元素为需要进行总计统计的列对象每个对象包含原列的信息以及新增的 total 属性初始值为 0
*/
initTotalList(columns) {
const totalList = [];
// 先判断 columns 是否存在且是一个数组类型,然后遍历 columns 数组中的每个列对象。
columns && columns instanceof Array && columns.forEach(column => { columns && columns instanceof Array && columns.forEach(column => {
// 如果列对象中有 needTotal 属性为 true表示该列需要进行总计统计就将该列信息复制一份并添加一个 total 属性初始化为 0放入 totalList 数组中。
if (column.needTotal) { if (column.needTotal) {
totalList.push({ totalList.push({
...column, ...column,
total: 0 total: 0
}) });
} }
}) });
return totalList return totalList;
}, },
/** /**
* 用于更新已选中的列表数据 total 统计 * 用于更新已选中的列表数据 total 统计方法
* @param selectedRowKeys * 根据传入的已选中的行键值数组selectedRowKeys和选中的行数据数组selectedRows更新组件内部记录选中信息的属性selectedRows selectedRowKeys然后遍历需要总计统计的列信息列表needTotalList计算每列在选中行中的数据总和更新每列对应的 total 属性值
* @param selectedRows * @param selectedRowKeys 已选中的表格行对应的唯一标识键值数组通常是每行数据的一个特定字段作为键值方便进行行的选中状态管理等操作
* @param selectedRows 已选中的表格行数据数组包含每行的详细数据内容
*/ */
updateSelect (selectedRowKeys, selectedRows) { updateSelect(selectedRowKeys, selectedRows) {
this.selectedRows = selectedRows // 更新组件内部记录选中行数据的属性 selectedRows将传入的 selectedRows 参数赋值给它,保持数据的一致性。
this.selectedRowKeys = selectedRowKeys this.selectedRows = selectedRows;
const list = this.needTotalList // 同样,更新组件内部记录选中行键值的属性 selectedRowKeys将传入的 selectedRowKeys 参数赋值给它,用于后续操作能准确获取选中行的相关信息。
this.selectedRowKeys = selectedRowKeys;
const list = this.needTotalList;
// 遍历 needTotalList 数组(之前初始化的需要总计统计的列信息列表),对于每个需要总计统计的列,执行以下操作来更新 total 属性值。
this.needTotalList = list.map(item => { this.needTotalList = list.map(item => {
return { return {
...item, ...item,
// 使用 reduce 方法遍历选中的行数据数组selectedRows从每行数据中获取对应列的数据通过 lodash.get 函数安全获取,防止数据结构异常等情况)并累加起来,计算每列在选中行中的数据总和,作为该列的 total 值。
// 如果获取到的值无法转换为数字(通过 parseInt 转换失败,返回 NaN则将 total 值设置为 0确保数据的合理性。
total: selectedRows.reduce((sum, val) => { total: selectedRows.reduce((sum, val) => {
const total = sum + parseInt(get(val, item.dataIndex)) const total = sum + parseInt(get(val, item.dataIndex));
return isNaN(total) ? 0 : total return isNaN(total) ? 0 : total;
}, 0) }, 0)
} };
}) });
}, },
/** /**
* 清空 table 已选中项 * 清空 table 已选中项方法
* 如果组件启用了行选择功能通过判断 rowSelection 属性是否存在则调用 rowSelection onChange 方法传入空数组同时调用 updateSelect 方法传入空数组来清空选中的行相关数据以及总计统计信息实现清空选中项的功能
*/ */
clearSelected () { clearSelected() {
if (this.rowSelection) { if (this.rowSelection) {
this.rowSelection.onChange([], []) // 调用 rowSelection 的 onChange 方法,传入空的选中行键值数组和空的选中行数据数组,通知相关的逻辑(可能是外部监听行选择变化的代码)选中项已被清空,触发相应的处理逻辑(比如更新界面上显示的选中数量等)。
this.updateSelect([], []) this.rowSelection.onChange([], []);
// 调用 updateSelect 方法,传入空数组,清空组件内部记录的选中行相关数据以及总计统计信息,使组件状态回到未选中任何行的初始状态。
this.updateSelect([], []);
} }
}, },
/** /**
* 处理交给 table 使用者去处理 clear 事件时内部选中统计同时调用 * 处理交给 table 使用者去处理 clear 事件时内部选中统计同时调用的方法
* @param callback * 根据是否存在选中项以及传入的回调函数callback决定是否返回一个带有清空按钮的虚拟 DOM 元素 Vue 中使用类似 JSX 的语法点击该按钮会先执行传入的 callback 函数然后调用 clearSelected 方法清空选中项相关数据
* @returns {*} * @param callback 一个回调函数通常由 table 使用者传入用于在点击清空按钮时执行额外的自定义逻辑比如可能涉及到外部状态的更新数据的保存等操作
* @returns {*} 如果没有选中项selectedRowKeys 长度小于等于 0则返回 null表示不渲染清空按钮否则返回包含清空按钮及相应点击事件处理逻辑的虚拟 DOM 元素
*/ */
renderClear (callback) { renderClear(callback) {
if (this.selectedRowKeys.length <= 0) return null if (this.selectedRowKeys.length <= 0) return null;
return ( return (
<a style="margin-left: 24px" onClick={() => { <a style="margin-left: 24px" onClick={() => {
callback() // 点击“清空”按钮时,先执行传入的 callback 函数,让 table 使用者有机会处理自己的业务逻辑(比如保存当前选中状态等操作)。
this.clearSelected() callback();
// 然后调用 clearSelected 方法,清空组件内部选中项相关的数据以及统计信息,更新组件状态。
this.clearSelected();
}}>清空</a> }}>清空</a>
) );
}, },
renderAlert () { /**
* 绘制包含表格相关统计信息清空按钮等内容的 alert 组件方法
* 此方法用于构建一个带有统计信息和操作按钮的提示组件a-alert展示已选择的行数各统计列的总计信息以及清空按钮根据相关条件判断是否显示方便用户直观了解表格的选中状态和相关统计数据并提供操作入口来清空选中项
*/
renderAlert() {
// 绘制统计列数据 // 绘制统计列数据
// 遍历 needTotalList 数组(包含需要进行总计统计的列信息),为每个列创建一个包含列标题和对应总计数据的 <span> 元素,用于展示每列的总计信息,最后返回一个包含这些 <span> 元素的数组(在 Vue 中使用类似 JSX 的语法构建虚拟 DOM 元素)。
const needTotalItems = this.needTotalList.map((item) => { const needTotalItems = this.needTotalList.map((item) => {
return (<span style="margin-right: 12px"> return (<span style="margin-right: 12px">
{item.title}总计 <a style="font-weight: 600">{!item.customRender ? item.total : item.customRender(item.total)}</a> {item.title}总计 <a
</span>) style="font-weight: 600">{!item.customRender ? item.total : item.customRender(item.total)}</a>
}) </span>)
});
// 绘制 清空 按钮 // 绘制 清空 按钮
// 根据 alert 属性的不同情况来决定是否显示以及如何显示“清空”按钮。
// 如果 alert.clear 是一个布尔值且为 true表示需要显示“清空”按钮调用 renderClear 方法传入 clearSelected 函数(用于清空选中项)来获取对应的虚拟 DOM 元素(即带有点击事件处理逻辑的“清空”按钮)。
// 如果 alert 属性不为 null 且 alert.clear 是一个函数,表示用户自定义了清除逻辑,同样调用 renderClear 方法传入自定义的清除函数来获取“清空”按钮对应的虚拟 DOM 元素。
// 如果不满足以上条件,则将 clearItem 设置为 null表示不显示“清空”按钮。
const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? ( const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? (
this.renderClear(this.clearSelected) this.renderClear(this.clearSelected)
) : (this.alert !== null && typeof this.alert.clear === 'function') ? ( ) : (this.alert !== null && typeof this.alert.clear === 'function') ? (
this.renderClear(this.alert.clear) this.renderClear(this.alert.clear)
) : null ) : null;
// 绘制 alert 组件 // 绘制 alert 组件
// 使用 a-alert 组件构建一个提示框设置显示图标showIcon={true}并添加底部外边距style="margin-bottom: 16px"),在提示框的 message 插槽中放入已选择的行数信息、统计列的总计信息以及“清空”按钮(如果存在)的虚拟 DOM 元素,最后返回构建好的 a-alert 组件对应的虚拟 DOM 元素,用于在页面上展示表格相关的统计提示信息和操作按钮。
return ( return (
<a-alert showIcon={true} style="margin-bottom: 16px"> <a-alert showIcon={true} style="margin-bottom: 16px">
<template slot="message"> <template slot="message">
@ -254,52 +311,68 @@ export default {
{clearItem} {clearItem}
</template> </template>
</a-alert> </a-alert>
) );
} }
}, },
render () { render() {
// 创建一个空对象来存储将要传递给表格的属性
const props = {} const props = {}
// 获取当前组件data中的所有键名
const localKeys = Object.keys(this.$data) const localKeys = Object.keys(this.$data)
// 判断是否显示alert条件包括alert对象存在且show属性为真同时rowSelection的selectedRowKeys已定义或者无条件显示alert
const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert
// 遍历T.props中的每个键
Object.keys(T.props).forEach(k => { Object.keys(T.props).forEach(k => {
// 根据T.props中的键名生成对应的本地键名首字母大写
const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}` const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
// 如果本地数据中存在这个键名则将其值赋给props对象中的对应键
if (localKeys.includes(localKey)) { if (localKeys.includes(localKey)) {
props[k] = this[localKey] props[k] = this[localKey]
return props[k] return props[k]
} }
// 如果当前键是'rowSelection'
if (k === 'rowSelection') { if (k === 'rowSelection') {
// 如果需要显示alert且rowSelection已定义
if (showAlert && this.rowSelection) { if (showAlert && this.rowSelection) {
// 如果需要使用alert重新绑定 rowSelection 事件 // 重新绑定rowSelection事件包括selectedRows, selectedRowKeys和onChange事件处理函数
props[k] = { props[k] = {
selectedRows: this.selectedRows, selectedRows: this.selectedRows,
selectedRowKeys: this.selectedRowKeys, selectedRowKeys: this.selectedRowKeys,
onChange: (selectedRowKeys, selectedRows) => { onChange: (selectedRowKeys, selectedRows) => {
// 更新组件内部状态
this.updateSelect(selectedRowKeys, selectedRows) this.updateSelect(selectedRowKeys, selectedRows)
// 如果原rowSelection中有onChange方法则调用它
typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows) typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
} }
} }
return props[k] return props[k]
} else if (!this.rowSelection) { } else if (!this.rowSelection) {
// 如果没打算开启 rowSelection 则清空默认的选择项 // 如果没有定义rowSelection则将其置为null
props[k] = null props[k] = null
return props[k] return props[k]
} }
} }
// 如果当前组件中有这个属性则将其添加到props对象中
this[k] && (props[k] = this[k]) this[k] && (props[k] = this[k])
return props[k] return props[k]
}) })
// 使用JSX语法渲染<a-table>组件并传入props和scopedSlots
const table = ( const table = (
<a-table {...{ props, scopedSlots: { ...this.$scopedSlots } }} onChange={this.loadData}> <a-table {...{props, scopedSlots: {...this.$scopedSlots}}} onChange={this.loadData}>
{ Object.keys(this.$slots).map(name => (<template slot={name}>{this.$slots[name]}</template>)) } { // 遍历组件的插槽,并渲染它们
Object.keys(this.$slots).map(name => (<template slot={name}>{this.$slots[name]}</template>))
}
</a-table> </a-table>
) )
// 返回最终的渲染结果包括可能显示的alert和表格
return ( return (
<div class="table-wrapper"> <div class="table-wrapper">
{ showAlert ? this.renderAlert() : null } {showAlert ? this.renderAlert() : null} // 如果需要显示alert则调用renderAlert方法渲染alert
{ table } {table} // 渲染表格
</div> </div>
) )
} }

Loading…
Cancel
Save