父组件表格页面代码:
<template> <div class="wrapper"> <div class="overview-box"> <div class="box-name"> <div class="flag" /> 标的事件 </div> <p class="con-txt"> {{ similarEventDate }}{{ queryInfo.symbol }}{{ queryInfo.shortname }}{{ queryInfo.eventtypename }}{{ pilesNum }}万股 </p> </div> <div class="box-name"> <div class="flag" /> 事件表格 </div> <Table :heads="columns" :data="tableData" :maxheight="500" :haspage="false" class="table-item" @sortChange="sortChange" @goToSimilarDetail="goToSimilarDetail" /> </div> </template> <script> import Table from '@/components/TableDynamic/index.vue' // 引入table组件 import { querySimilarEventData } from '@/api/queryEvent' // 后端接口 import { mapState } from 'vuex' export default { name: 'EventDeatil', components: { Table }, data() { return { queryInfo: {}, code: '', // 代码 eventType: '', // 事件类型 eventDate: '', // 事件时间 similarEventDate: '', // 事件时间 pilesNum: '', // 股数 detailInfo: {}, // 明细概述信息 columns: [ { label: '事件名称', width: 160, sortable: true, prop: 'eventname' }, { label: '代码', width: 93, sortable: true, prop: 'symbol' }, { label: '事后1日涨跌幅', type: 'percent', sortable: true, prop: 'onedayratio' }, { label: '事后3日涨跌幅', sortable: true, type: 'percent', prop: 'threedayratio' }, { label: '事后5日涨跌幅', sortable: true, type: 'percent', prop: 'fivedayratio' }, { label: '事件偏向', sortable: true, prop: 'eventbias', type: 'deviation' }, { label: '相似度', sortable: true, prop: 'similarvalue' } ], tableData: [], sortBackupData: [] } }, computed: { ...mapState({ eventDisplayInfo: (state) => state.event.eventDisplayInfo }) }, watch: { eventDisplayInfo: { handler(newObj) { this.code = newObj.symbol || '' this.eventType = newObj.eventtype || '' this.eventDate = newObj.eventdate || '' this.queryInfo = newObj || {} this.getSimilarEventData() }, deep: true } }, created() {}, mounted() { // 页面路径所传参数 this.code = this.$route.query.symbol || '' this.eventType = this.$route.query.eventtype || '' this.eventDate = this.$route.query.eventdate || '' this.queryInfo = this.$route.query || {} this.similarEventDate = this.getDate(this.$route.query.eventdate.split(' ')[0]) this.getSimilarEventData() // 获取表格数据 }, methods: { // 获取表格数据 getSimilarEventData() { const date = this.eventDate.split(' ')[0] if (!date) { this.tableData = [] return } const params = { symbol: this.code, eventdate: date, size: 10 } querySimilarEventData(params).then((res) => { const data = res.similarItems || [] const arr = [] this.pilesNum = res.Listedshares data.forEach(el => { el.similarvalue = this.toDecimal(this.numMul(el.similarvalue, 100)) + '%' arr.push(el) }) this.tableData = arr Object.assign(this, { tableData: this.tableData, sortBackupData: this.tableData }) sessionStorage.setItem('tableData', JSON.stringify(this.tableData)) }) }, // 格式化日期 getDate(date) { const date1 = new Date(date) // 获取年份、月份和日期 const year = date1.getFullYear() const month = date1.getMonth() + 1 // 注意月份从0开始计数,所以需要加上1得到真正的月份(12) const day = date1.getDate() return `${year}年${month}月${day}日` }, // 排序 sortChange({ column, prop, order }) { if (column.sortable === 'custom') { if (order) { const { tableData } = this this.tableData = this.customSortBuyProp(order, tableData, prop) } else { this.tableData = this.sortBackupData } } }, /** * 根据选定prop排序(无效值排最后) * @param {String} order 排序顺序ascending/descending * @param {Array} data 数据 * @param {String} prop 排序属性 * @param {Array} invalidList 无效值定义 */ customSortBuyProp(order, data, prop, invalidList) { if (!order) { return data } invalidList = invalidList || [null, undefined, '', '/'] const isAsc = order === 'ascending' const effectiveArr = [] // 参与排序的数据 const invalidArr = [] // 不参与排序的数据 data.forEach((item) => { const value = item[prop] if (invalidList.includes(value)) { invalidArr.push(item) } else { effectiveArr.unshift(item) } }) effectiveArr.sort((a, b) => { const aValue = a[prop] const bValue = b[prop] if (aValue > bValue) { return isAsc ? 1 : -1 } else if (aValue < bValue) { return isAsc ? -1 : 1 } else { return 0 } }) return effectiveArr.concat(invalidArr) }, // 跳转详情页面 goToSimilarDetail(row) { let arr = [] arr = [ { event_date: this.eventDate.substring(0, 10), event_type: Number(this.eventType), shortname: this.queryInfo.shortname, symbol: this.code }, { event_date: row.eventdate.substring(0, 10), event_type: row.eventtype, shortname: row.shortname, symbol: row.symbol } ] sessionStorage.setItem('similarParams', JSON.stringify(arr)) const routeUrl = this.$router.resolve({ path: '/similarDetail/index', query: row }) window.open(routeUrl.href, '_blank') } } } </script> <style lang="scss"> .baseDataPopper { .content-box { max-width: 500px; max-height: 400px; overflow-y: auto; white-space: pre-line; } } </style> <style lang="scss" scoped> .wrapper { padding: 0 16px 20px; background: #ffffff; box-sizing: border-box; -webkit-box-sizing: border-box; .table-item { padding: 0; /deep/.table-box { padding: 0; } } .overview-box { margin-bottom: 16px; border: 1px solid #e6e6e6; border-top: none; .con-txt { padding: 0px 17px 10px; margin: 0; line-height: 24px; font-size: 14px; color: #666666; .spec { font-weight: bold; color: #f33030; cursor: pointer; border-bottom: 1px dashed #f33030; &:hover { color: #1e81ff; border-bottom: 1px dashed #1e81ff; } } } } .box-name { padding: 0 16px; display: flex; align-items: center; height: 44px; font-size: 14px; font-weight: bold; color: #333333; box-sizing: border-box; -webkit-box-sizing: border-box; .flag { margin-right: 8px; width: 5px; height: 14px; background: #1e81ff; border-radius: 0px 2px 2px 0px; } } .item-title { margin: 26px 0 16px; padding-left: 14px; height: 28px; line-height: 28px; font-size: 14px; font-weight: 600; color: #333333; background: url("~@/assets/images/title_bg.png") no-repeat; background-size: 130px 100%; position: relative; &::before { position: absolute; content: ""; top: 5px; left: 0; width: 3px; height: 18px; background: #1e81ff; } } .pagin-box { margin-top: 20px; padding-top: 20px; text-align: center; position: relative; &::before { position: absolute; content: ""; top: 0; left: -16px; right: -16px; height: 1px; background: #eeeff1; } } /deep/.pub-pagin-box { .el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li { font-size: 12px; font-weight: normal; color: #666666; background: #f6f6f6; border-radius: 3px; } .el-pagination.is-background .el-pager li:not(.disabled).active { color: #ffffff; background-color: #1e81ff; } .el-pagination.is-background .btn-next.disabled, .el-pagination.is-background .btn-next:disabled, .el-pagination.is-background .btn-prev.disabled, .el-pagination.is-background .btn-prev:disabled, .el-pagination.is-background .el-pager li.disabled { color: #c0c4cc; } .el-pagination__jump, .el-input__inner { font-size: 12px; color: #666666; } } .chart-area { margin-top: 26px; padding: 10px 0; width: 100%; height: 380px; background: #ffffff; border: 1px solid #e6e6e6; box-sizing: border-box; -webkit-box-sizing: border-box; } /deep/.detail-dialog { .el-dialog__header { padding-top: 15px; padding-bottom: 15px; border-bottom: 1px solid #f3f3f3; } .title-box { font-size: 16px; position: relative; .iconfont { position: absolute; right: 0; cursor: pointer; } } .el-dialog__body { max-height: 350px; min-height: 200px; overflow-y: auto; } .content-box { display: flex; flex-wrap: wrap; .item { margin-bottom: 20px; display: flex; flex-shrink: 0; width: 50%; padding-right: 10px; box-sizing: border-box; &:nth-of-type(2n) { padding-right: 0; padding-left: 10px; } .name { width: 120px; font-weight: bold; } .con { margin-left: 10px; flex: 1; } } } } } </style> table组件代码: <template> <!-- table-wrapper 具体页面可能也用了该类名控制表格特殊样式 --> <div :class="'table-wrapper ' + headbg"> <div class="table-box"> <el-table ref="table" :data="data" :height="height === 0 ? undefined : height" :max-height="maxheight === 0 ? undefined : maxheight" :highlight-current-row="highlightCurrentRow" :empty-text="emptyText" :span-method="spanMethod" :size="size" :row-class-name="rowclassname" :tree-props="treeProps" :row-key="rowKey" :row-style="size == 'small' ? { height: '30px' } : {}" :cell-style="size == 'small' ? { padding: '0px' } : {}" :stripe="stripe" style="width: 100%" tooltip-effect="dark" border @cell-dblclick="cellDblclick" @row-click="rowClick" @current-change="handleRowChange" @selection-change="handleSelectionChange" @sort-change="sortChange" > <el-table-column v-if="hasselection" :reserve-selection="reserveSelection" type="selection" header-align="center" align="center" width="40" /> <el-table-column v-if="hasindex && data.length > 0" :index="indexMethod" label="序号" type="index" header-align="center" align="center" class-name="rw-table-index" width="80" /> <el-table-column v-for="h in heads" :key="'col' + h.prop" :prop="h.prop" :fixed="h.hasFixed" :align="h.align ? h.align : 'center'" :header-align="h.hAlign ? h.hAlign : 'center'" :min-width="h.minWidth ? h.minWidth : '128'" :width="h.width ? h.width: 'auto'" :sortable="h.sortable ? 'custom' : false" :label-class-name="h.hasWrap ? 'hasWrap' : ''" > <template #header> <el-tooltip :content="h.label" overflow effect="dark" placement="top-start" > <div class="dialog-box-title"> {{ h.label }} </div> </el-tooltip> <div v-if="h.label === '相似度'"> <span style="margin-right:8px;" /> <el-popover placement="top-start" width="250" trigger="hover" content="针对付费订单,使用截止时间来源于合同,可能和最终实施的使用截止日期存在差异。" > <i slot="reference" class="tips-icon el-icon-question" /> </el-popover> </div> </template> <template slot-scope="scope"> <div v-if="h.type === 'starIcon'" class="star-icon-box"> <i v-for="(item, i) in 5" :key="'icon' + i" :style="{ color: scope.row[h.prop] > i ? '#F7BA2A' : '#DAE0E7', }" :class=" scope.row[h.prop] > i ? 'iconxingxing-tianchong' : 'iconxingxing' " class="iconfont star-icon" /> </div> <template v-else-if="h.type === 'largeText'"> <el-tooltip popper-class="baseDataPopper" effect="dark" placement="bottom-start"> <div :style="scope.row[h.prop + 'Style']">{{ scope.row[h.prop] }}</div> <template slot="content"> <div class="content-box">{{ scope.row[h.prop] }}</div> </template> </el-tooltip> </template> <template v-else-if="h.prop === 'similarvalue'"> <div class="similarText" @click="goToSimilarDetail(scope.row)">{{ scope.row[h.prop] }}</div> </template> <template v-else-if="h.type === 'date'"> <div >{{ formatDate(new Date(scope.row[h.prop])) }}</div> </template> <div v-else :class="h.type == 'price' || h.type == 'percent' ? (scope.row[h.prop] == 0 || scope.row[h.prop] == null) ? 'zero' : scope.row[h.prop] > 0 ? 'up' : 'down' : '' " :style="scope.row[h.prop + 'Style']" > {{ scope.row[h.prop] === "" ? '' : (h.type == "price" ? toDecimal(scope.row[h.prop], 4) : h.type == "percent" ? ( scope.row[h.prop] ? toDecimal(numMul(scope.row[h.prop], 100)) + '%' : '-') : h.type == "date" ? scope.row[h.prop].split(' ')[0].replace(/\-/g, "") : h.type == "deviation"? eventBiasClick(scope.row[h.prop]): scope.row[h.prop]) }} </div> </template> </el-table-column><slot /> <div slot="empty">暂无数据</div> </el-table> </div> <div v-if="haspage" class="table-pagination"> <el-pagination :total="total" :current-page="pageindex" :page-size="pagesize" background layout="prev, pager, next, jumper" @current-change="pageChange" @size-change="pageSizeChange" /> </div> </div> </template>
<script> import { eventBiasHandle } from '@/utils/business' import common from '@/utils/common' export default { name: 'CsTable', props: { heads: { type: Array, required: true }, // 表格的数据 data: { type: Array, required: true }, stripe: { type: Boolean, default: true }, rowKey: { type: String, default: '' }, emptydata: { type: String, default: '' }, height: { type: [Number, String], default: 0 }, maxheight: { type: [Number, String], default: 0 }, total: { type: Number, default: 0 }, url: { type: String, default: '' }, pagesize: { type: Number, default: 0 }, pageindex: { type: Number, default: 1 }, hasindex: { type: Boolean, default: false }, hasselection: { type: Boolean, default: false }, reserveSelection: { type: Boolean, default: false }, haspage: { type: Boolean, default: true }, highlightCurrentRow: { // 是否有点击选中效果 type: Boolean, default: false }, size: { type: String, default: 'medium' }, headbg: { type: String, default: '' }, spanMethod: { type: Function, default: function({ row, column, rowIndex, columnIndex }) {} }, // eslint-disable-next-line vue/require-default-prop rowclassname: [String, Function], treeProps: { type: Object, default: () => { return { children: 'children', hasChildren: 'hasChildren' } } } }, data() { return { emptyText: '暂无数据' } }, mounted() { if (this.emptydata !== '') { this.emptyText = this.emptydata } }, methods: { goToSimilarDetail(row) { this.$emit('goToSimilarDetail', row) }, eventBiasClick(val) { return eventBiasHandle(val) }, pageChange(val) { this.$emit('pageChange', this.pagesize, val) }, pageSizeChange(val) { if (val * (this.pageindex - 1) <= this.total) { this.$emit('pageChange', val, this.pageindex) } else { this.$emit('pageChange', val, 1) } }, sortChange(column, prop, order) { this.$emit('sortChange', column) }, indexMethod(index) { return this.pagesize * (this.pageindex - 1) + index + 1 }, handleSelectionChange(val) { this.$emit('selection-change', val) }, cellDblclick(row, column, cell, event) { this.$emit('cell-dblclick', row, column, cell, event) }, rowClick(row, column, event) { this.$emit('rowClick', row, column, event) }, clearSelection() { this.$refs.table.clearSelection() }, toggleAllSelection() { this.$refs.table.toggleAllSelection() }, toggleRowSelection(row) { this.$refs.table.toggleRowSelection(row) }, handleRowChange(row) { if (this.highlightCurrentRow) { this.$emit('handleCurRow', row) } }, doLayout() { this.$refs.table.doLayout() }, formatDate(date, format = 'YYYY-MM-dd') { return common.formatDate(date, format) } } } </script> <style lang="scss"> .baseDataPopper { .content-box { max-width: 500px; max-height: 400px; overflow-y: auto; white-space: pre-line; } } </style> <style scoped lang="scss"> .el-icon-question { color: #1e81ff; margin-right: 8px; } .similarText { text-decoration: underline; color: #1e81ff; cursor: pointer; } .table-wrapper { padding: 17px 0 20px; .table-box { padding: 0 16px; } } .el-table { /deep/thead { tr, th { padding-top: 0; padding-bottom: 0; font-size: 14px; color: #333333; font-weight: normal; background: #fcfcfc; } th { .cell { display: flex; justify-content: center; align-items: center; line-height: 16px; white-space: pre; .dialog-box-title{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } .hasWrap { display: flex; justify-content: center; } } .caret-wrapper { width: 14px; .sort-caret { left: 2px; } } } /deep/tr { height: 44px !important; td { padding-top: 4px; padding-bottom: 4px; color: #666666; font-size: 14px; } &.el-table__row--striped td { background: #fcfcfc !important; } } /deep/.el-table__body tr.current-row > td { background-color: #eff4f9; } .star-icon-box { .star-icon { margin-right: 6px; font-size: 14px; &:nth-last-of-type(1) { margin-right: 0; } } } } /deep/.table-pagination { margin-top: 20px; padding-top: 20px; text-align: center; border-top: 1px solid #eeeff1; .el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li { font-size: 12px; font-weight: normal; color: #666666; background: #f6f6f6; border-radius: 3px; } .el-pagination.is-background .el-pager li:not(.disabled).active { color: #ffffff; background-color: #1e81ff; } .el-pagination.is-background .btn-next.disabled, .el-pagination.is-background .btn-next:disabled, .el-pagination.is-background .btn-prev.disabled, .el-pagination.is-background .btn-prev:disabled, .el-pagination.is-background .el-pager li.disabled { color: #c0c4cc; } .el-pagination__jump, .el-input__inner { font-size: 12px; color: #666666; } } .up { color: #ed5959; }
.down { color: #33ad34; }
.zero { color: #333; }
</style> 父组件详情页面代码: <template> <div> <div v-loading="loading" class="main-wrapper"> <div class="main-box"> <el-card class="box-card"> <div class="title">详情</div> <div class="tab-box"> <div v-for="(item, index) in tabList" :key="index" class="item-tab" @click="handleClick(item, index)"> <div :class="activeIndex === index ? 'color' : ''" class="tab" >{{ item }}</div> <div v-if="activeIndex === index" class="line-box"/> </div> </div> <div class="table"> <ColumnTable ref="columnTable" :header-list="headerList" :table-data="tableData" :active-index="activeIndex" @addRow ="addRow" @delRow ="delRow" /> </div> </el-card> </div> </div> <!-- 添加事件表格 --> <el-dialog v-if="dialogVisible" :visible.sync="dialogVisible" title="选择事件" width="60%" class="dialog" @close="cancelSelect"> <el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="100px" class="demo-ruleForm"> <el-form-item label="事件" prop="similarVal"> <el-select v-model="ruleForm.similarVal" :multiple-limit="2" placeholder="请选择" multiple collapse-tags> <el-option v-for="item in similarOptions" :key="`${getDate(item.eventdate.substring(0, 10))}${item.symbol}${item.shortname}解禁`" :label="`${getDate(item.eventdate.substring(0, 10))}${item.symbol}${item.shortname}解禁`" :value="`${getDate(item.eventdate.substring(0, 10))}${item.symbol}${item.shortname}解禁`"/> </el-select> </el-form-item> <el-form-item class="btnOptions"> <el-button @click="cancelSelect">取消</el-button> <el-button type="primary" style="margin-left:20px" @click="submitForm('ruleForm')">确定</el-button> </el-form-item> </el-form> </el-dialog> </div> </template> <script> import ColumnTable from '@/components/ColumnTable' // 引入父组件表格 import { querySimilarTableData } from '@/api/queryEvent' // 后端接口 export default { components: { ColumnTable }, data() { return { tabList: ['基本信息', '财务信息', '行情走势', '分类业务'], activeIndex: 0, headerList: [ { label: '', value: 'class', headerAlign: 'left', minWidth: '110', align: 'center' }, { label: '基本信息', value: 'baseInfo', headerAlign: 'left', minWidth: '80', align: 'center' }, { label: '公司规模', value: 'CirculatedMarketValue', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '公司性质', value: 'OwnshipID', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '注册地址', value: 'RegisterAddress', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '注册资本(元)', value: 'RegisterCapital', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '办公地址', value: 'OfficeAddress', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '上市日期', value: 'IPODate', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '主营业务', value: 'MainBusiness', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '所属行业', value: 'IndustryCode', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '总股本(万股)', value: 'TotalShare', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '流通股本(万股)', value: 'CirculatedShare', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '财务信息', value: 'financialInfo', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '净资产收益率(%)', value: 'ROEA', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '净利润率(%)', value: 'ROA2A', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '营业成本率(%)', value: 'OperatingCostRatio', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '营业利润率(%)', value: 'OperatingProfiToRevenue', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '销售期间费用率(%)', value: 'PeriodExpenseRate', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '投资收益率(%)', value: 'ReturnOnInvestment', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '应收账款周转率(%)', value: 'ReceivableTurnoverA', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '总资产周转率(%)', value: 'AssetTurnoverA', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '股东权益周转率(%)', value: 'EequityTurnoverA', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '行情走势', value: 'marketTrend', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '个股事后1日涨跌幅(%)', value: 'onedayratio', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '个股事后3日涨跌幅(%)', value: 'threedayratio', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '个股事后5日涨跌幅(%)', value: 'fivedayratio', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '大盘收益率(%)', value: 'marketreturn', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '行业收益率(%)', value: 'industryreturn', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '分类业务', value: 'age', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '解禁占比(%)', value: 'Proportion2', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '总限售股数(万股)', value: 'TotalLockShares', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '剩余限售股数量(万股)', value: 'RemainedLockShares', headerAlign: 'left', minWidth: '90', align: 'center' }, { label: '解禁股东数', value: 'HolderNumber', headerAlign: 'left', minWidth: '90', align: 'center' } ], ruleForm: { similarVal: [] // 下拉框选中值 }, rules: { similarVal: [ { required: true, message: '请选择相似事件', trigger: 'change' } ] }, tableData: [], // 表格数据 queryParams: [], // 请求参数 queryParams1: [], // 请求参数 loading: false, // 加载状态 dialogVisible: false, // 是否显示添加事件弹框 similarOptions: [] // 下拉框选项数据 } }, mounted() { let arr = [] arr = sessionStorage.getItem('similarParams') this.queryParams = JSON.parse(arr) this.queryParams.forEach(i => { const tableList = sessionStorage.getItem('tableData') this.similarOptions = JSON.parse(tableList).filter((item) => item.symbol !== i.symbol) }) this.getSimilarTableData(this.queryParams) }, methods: { // tab栏切换点击(滚动条锚点定位) handleClick(item, index) { this.activeIndex = index if (this.activeIndex == 0) { document.documentElement.scrollTop = 0 } else { // 获取需要滚动到的元素 const targetElement = document.getElementById('title') // 将页面滚动至目标元素处 targetElement.scrollIntoView({ behavior: 'smooth' }) } }, // 获取表格数据 getSimilarTableData(params) { this.loading = true this.tableData = [] querySimilarTableData(params).then(res => { this.loading = false res.forEach((item, index) => { params.forEach((i, idx) => { if (index === idx) { const title = this.getDate(i.event_date) item.RegisterCapital = this.money(item.RegisterCapital) item.ROEA = this.toDecimal(item.ROEA, 4) item.ROA2A = this.toDecimal(item.ROA2A, 4) item.OperatingCostRatio = this.toDecimal(item.OperatingCostRatio, 4) item.OperatingProfiToRevenue = this.toDecimal(item.OperatingProfiToRevenue, 4) item.PeriodExpenseRate = this.toDecimal(item.PeriodExpenseRate, 4) item.ReturnOnInvestment = this.toDecimal(item.ReturnOnInvestment, 4) item.ReceivableTurnoverA = this.toDecimal(item.ReceivableTurnoverA, 4) item.AssetTurnoverA = this.toDecimal(item.AssetTurnoverA, 4) item.EequityTurnoverA = this.toDecimal(item.EequityTurnoverA, 4) item.onedayratio = this.toDecimal(item.onedayratio, 2) item.threedayratio = this.toDecimal(item.threedayratio, 2) item.fivedayratio = this.toDecimal(item.fivedayratio, 2) item.marketreturn = this.toDecimal(item.marketreturn, 2) item.industryreturn = this.toDecimal(item.industryreturn, 2) item.Proportion2 = this.toDecimal(item.Proportion2, 4) const obj = { class: `${title}${i.symbol}${i.shortname}解禁`, ...item } this.tableData.push(obj) } }) }) const obj1 = { class: '添加其他事件', AssetTurnoverA: '', CirculatedMarketValue: '', CirculatedShare: null, EequityTurnoverA: '', HolderNumber: null, IPODate: '', IndustryCode: '', MainBusiness: '', OfficeAddress: '', OperatingCostRatio: '', OperatingProfiToRevenue: '', OwnshipID: '', PeriodExpenseRate: '', Proportion2: '', ROA2A: '', ROEA: '', ReceivableTurnoverA: '', RegisterAddress: '', RegisterCapital: '', RemainedLockShares: null, ReturnOnInvestment: '', Symbol: '', TotalLockShares: null, TotalShare: null, fivedayratio: '', industryreturn: '', marketreturn: '', onedayratio: '', threedayratio: '' } this.tableData.push(obj1) }) }, // 格式化日期 getDate(date) { const date1 = new Date(date) // 获取年份、月份和日期 const year = date1.getFullYear() const month = date1.getMonth() + 1 // 注意月份从0开始计数,所以需要加上1得到真正的月份(12) const day = date1.getDate() return `${year}年${month}月${day}日` }, // 新增事件 addRow() { this.ruleForm.similarVal = [] this.tableData.forEach(res => { this.similarOptions.forEach(i => { if (res.class === `${this.getDate(i.eventdate.substring(0, 10))}${i.symbol}${i.shortname}解禁`) { this.ruleForm.similarVal.push(res.class) } }) }) this.dialogVisible = true }, // 删除事件 delRow(label) { const index = this.tableData.findIndex(item => item.class === label) const selectItem = this.tableData.splice(index, 1) const arr = this.ruleForm.similarVal.filter(i => i !== selectItem[0].class) this.ruleForm.similarVal = arr }, // 取消选择事件 cancelSelect() { this.dialogVisible = false }, // 点击确定添加事件 submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { this.queryParams1 = [] let queryParams2 = [] let tableParams = [] this.ruleForm.similarVal.forEach(i => { queryParams2 = this.similarOptions.filter((item) => `${this.getDate(item.eventdate.substring(0, 10))}${item.symbol}${item.shortname}解禁` === i) queryParams2.forEach(item => { const obj = { event_date: item.eventdate.substring(0, 10), event_type: Number(item.eventtype), shortname: item.shortname, symbol: item.symbol } this.queryParams1.push(obj) tableParams = this.queryParams.concat(this.queryParams1) }) }) this.getSimilarTableData(tableParams) this.dialogVisible = false } else { console.log('error submit!!') return false } }) } } } </script> <style lang="scss" scoped> /deep/ .el-select { width: 320px !important; } /deep/ .el-select > .el-input { width: 350px; } /deep/ .el-dialog { height: 50%; position: relative; } /deep/ .el-dialog__footer { position: absolute; bottom: 20px; right: 20px; } .select-title { margin-left: 100px; } .main-wrapper { margin: 77px auto 0; max-width: 1200px; box-sizing: border-box; .main-box { display: flex; .box-card { width: 100%; .title { font-size: 14px; font-family: Noto Sans S Chinese; font-weight: bold; color: #333333; } .tab-box { display: flex; align-items: center; margin: 35px 57px 37px 57px; .item-tab { margin-right: 36px; width: 67px; display: flex; justify-content: center; align-items: center; flex-direction: column; cursor: pointer; position: relative; .tab { font-size: 14px; font-family: Noto Sans S Chinese; font-weight: 400; color: #333333; } .color { color: #1E81FF; } } .line-box { width: 67px; height: 1px; background: #1E81FF; position: absolute; content: ""; bottom: -3px; left: 0; } } .table { margin: 33px 57px 56px; } } } } .btnOptions { position: absolute; right: 20px; bottom: 20px; } </style> 加减表格子组件代码:
<!-- 表格行列转换 --> <template> <el-table ref="table" :data="getTableData[0]" border style="width: 100%;" > <template v-for="(item, index) in getTableData[1]"> <el-table-column :key="index" :label="item.label" :prop="item.value" :header-align="item.headerAlign || 'center'" :min-width="item.minWidth || 80" :align="item.align || 'center'" > <template slot-scope="scope"> <!-- {{ tableFormatter(item.value, scope.row) }}-{{ index }}-{{ scope.$index }} index代表表格列索引,scope.$index代表表格行索引 --> <div :class="(scope.$index === 0 && activeIndex == 0) || (scope.$index === 11 && activeIndex == 1) || (scope.$index === 21 && activeIndex == 2) || (scope.$index === 27 && activeIndex == 3) ? 'title-text' : ''" :style="{textAlign: (scope.$index === 4 || scope.$index > 8) && index > 0 ? 'right' : (index === 0 ? 'center' : 'left')}" :id="(scope.$index === 0 && activeIndex == 0) || (scope.$index === 11 && activeIndex == 1) || (scope.$index === 21 && activeIndex == 2) || (scope.$index === 27 && activeIndex == 3) ? 'title' : ''"> {{ tableFormatter(item.value, scope.row) }} </div> </template> <template slot="header" slot-scope="scope"> <div v-if="scope.$index == tableData.length" class="ceil"> {{ scope.column.label }} <i class="el-icon-circle-plus-outline" @click="addRow()" /> </div> <div v-else-if="scope.$index>2&&scope.$index<tableData.length" class="ceil"> {{ scope.column.label }} <i class="el-icon-remove-outline" @click="delRow(scope.column.label)"/> </div> <span v-else>{{ scope.column.label }}</span> </template> </el-table-column> </template> </el-table> </template>
<script>
export default { props: { headerList: { type: Array, default: () => [] }, tableData: { type: Array, default: () => [] }, activeIndex: { type: Number, default: 0 } }, data() { return { } }, computed: { getTableData() { return this.fotmatterTableData(this.tableData, this.headerList) } }, methods: { fotmatterTableData(data, header) { const enddata = [] const endheader = [] header.forEach((item, index) => { if (index === 0) { endheader.push({ label: header[index].label, value: 'mainIndex', headerAlign: header[index].headerAlign, minWidth: header[index].minWidth, align: header[index].align }) data.forEach((ele, idx) => { endheader.push({ label: ele[header[index].value], value: `type${idx}` }) }) } else { const obj = { mainIndex: header[index].label } data.forEach((ele, ind) => { obj[`type${ind}`] = ele[header[index].value] }) enddata.push(obj) } }) console.log('end===', enddata, endheader) return [enddata, endheader] },
// 列表格式化 tableFormatter(prop, row) { if (row[prop] || row[prop] == 0) { if (prop === 'mainIndex') { if (row.unit) { return `${row[prop]}(${row.unit})` } return row[prop] } return row[prop] }
return '' }, randomStr() { return Math.random().toString().slice(3, 8) }, addRow() { this.$emit('addRow') }, delRow(label) { this.$emit('delRow', label) } } } </script> <style scoped> .title-text { background: rgba(30,129,255,0.1); color: #1E81FF; width: 100%; height: 24px; } /deep/ .el-table th > .cell { padding-left: 0 !important; padding-right: 0 !important; } /deep/ .cell { padding-left: 0 !important; padding-right: 0 !important; height: 100%; } /deep/ td { padding: 0; } .el-icon-circle-plus-outline { cursor: pointer; color: #1E81FF; font-size: 16px; } .el-icon-remove-outline { cursor: pointer; color: #707070; font-size: 16px; } </style> 标签:el,center,align,label,item,ui,锚点,element,left From: https://www.cnblogs.com/xiaofang234/p/17920790.html