element ui 表格与锚点定位

父组件表格页面代码:

<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>

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ElementUI 提供了一个 `ElAnchor` 组件用于实现锚点定位。使用 `ElAnchor` 组件需要以下步骤: 1. 在需要设置锚点的位置加上 `ElAnchor` 组件,并设置 `name` 属性为该锚点的名称。 ``` <el-anchor :offset="80"> <el-link href="#section1" :title="$t('section1')"></el-link> <el-link href="#section2" :title="$t('section2')"></el-link> <el-link href="#section3" :title="$t('section3')"></el-link> </el-anchor> <!-- 需要设置锚点的位置 --> <div id="section1"> ... </div> <div id="section2"> ... </div> <div id="section3"> ... </div> ``` 2. 在需要跳转到锚点的位置加上 `ElLink` 组件,并设置 `href` 属性为锚点名称。 ``` <el-link href="#section1" :title="$t('section1')"></el-link> <el-link href="#section2" :title="$t('section2')"></el-link> <el-link href="#section3" :title="$t('section3')"></el-link> ``` 通过以上两步操作,就可以实现 ElementUI锚点定位功能了。其中,`ElAnchor` 组件的 `offset` 属性可以设置距离顶部的偏移量,以便调整视觉效果。 ### 回答2: ElementUI是一套基于Vue.js框架的UI组件库。在ElementUI中,我们可以使用锚点定位来实现页面内部的快速跳转。锚点定位可以帮助用户快速定位到页面的指定区域,提升页面的用户体验。 在ElementUI中,我们可以通过两种方式实现锚点定位。一种是使用`el-button`组件,设置`type`属性为`text`,然后使用`href`属性来指定锚点的目标位置。例如: ``` <el-button type="text" href="#section1">跳转到Section1</el-button> ``` 上述代码中,当用户点击"跳转到Section1"按钮时,页面会自动滚动到id为"section1"的元素位置。 另一种方式是使用`el-menu`组件和锚点。首先我们需要定义一个`el-menu`组件,设置`mode`属性为"vertical"或"horizontal",然后使用`el-menu-item`组件来添加菜单项,并设置`index`属性为指定的锚点位置。例如: ``` <el-menu mode="vertical"> <el-menu-item index="#section1">Section1</el-menu-item> <el-menu-item index="#section2">Section2</el-menu-item> </el-menu> ``` 上述代码中,当用户点击"Section1"菜单项时,页面会自动滚动到id为"section1"的元素位置。 总之,ElementUI提供了强大的锚点定位功能,使得我们在构建页面时能够方便地实现内部快速跳转。无论是使用`el-button`组件还是`el-menu`组件,都能够满足不同的页面需求。 ### 回答3: Element UI 是一个基于 Vue.js 的组件库,它提供了丰富的UI组件和工具,可以帮助我们快速构建漂亮的网页界面。 在 Element UI 中,锚点定位是一种常见的页面内部导航技术。通过添加锚点链接和目标元素,我们可以实现点击链接后页面自动滚动到相应的位置,方便用户快速定位到自己感兴趣的内容。 在 Element UI 中,使用锚点定位非常简单。首先,我们需要在页面中标识出需要定位的目标元素。在目标元素上添加一个具有唯一标识的 id 属性,例如"target"。接下来,我们可以在页面的其他地方添加锚点链接。在链接元素中使用 <el-link> 组件,并添加一个 href 属性指向目标元素的 id 值,如 href="#target"。这样,当用户点击链接时,页面将会自动滚动到目标元素的位置。 除了基本的锚点定位Element UI 还提供了一些额外的功能,例如平滑滚动和偏移设置。我们可以使用 <el-anchor> 组件来包裹锚点链接,从而实现平滑滚动效果。我们也可以通过设置 offset 属性来调整滚动的偏移量,确保目标元素的位置更准确。 总之,Element UI 提供了简单易用的锚点定位功能,可以帮助我们实现页面内部导航。通过添加目标元素和锚点链接,我们可以方便地定位到页面中的特定位置,提升用户的浏览体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值