vue+element-ui后臺系統(tǒng)實現(xiàn)可配置報表組件

背景:

目前在做的一個后臺系統(tǒng)穗酥,因為投入市場使用,開始有很多數(shù)據(jù)報表需求框仔。頁面結構大同小異舀武,所以想將其模塊化,開發(fā)一個可復用的報表組件离斩。因為是后臺系統(tǒng)银舱,樣式只要求簡介不亂就行。

組件主要分三個模塊:

  • 條件查詢區(qū) + 按鈕
  • 表格數(shù)據(jù)顯示區(qū)
  • 分頁條區(qū)域

查詢條件和表格的列名通過配置傳入跛梗,頁面初始化時塞入配置寻馏。
表格具體動態(tài)數(shù)據(jù)一般是通過請求,如需二次封裝在對應頁面進行處理

組件代碼

<!-- 可配置的動態(tài)報表頁面 -->
<!--
  三個功能塊:條件查詢區(qū),列表數(shù)據(jù)區(qū)核偿,數(shù)據(jù)分頁區(qū)
 -->
<template>
 <div class="dynamic-report-mod">
   <el-card :body-style="{ padding: '10px' }">
     <el-row>
       <!--條件查詢區(qū)域 -->
       <el-col class="dynamic-search" :span="24" align="left">
         <!-- 參數(shù)配置 -->
         <template v-for="item in list.queryList">
           <!-- 查詢按鈕 -->
           <el-button v-if="item.type==='button'" :type="item.config.type" @click="handleClickQueryBtn(item.key)">{{ item.label }}</el-button>

           <el-input v-if="item.type==='input'" v-model="query[item.key]" type="text" :placeholder="item.config.placeholder" clearable></el-input>

           <template v-if="item.type==='select'">
             {{item.label}}
             <el-select v-model="query[item.key]" :placeholder="item.config.placeholder" clearable>
               <el-option
                 v-for="option in item.options"
                 :key="option.key"
                 :label="option.val"
                 :value="option.key">
               </el-option>
             </el-select>
           </template>

           <template v-if="item.type==='datePicker'">
             {{item.label}}
             <el-date-picker v-model="query[item.key]" :range-separator="item.config.separator" :value-format="item.config.format" :type="item.config.type" :placeholder="item.config.placeholder" :start-placeholder="item.config.startPlaceholder" :end-placeholder="item.config.endPlaceholder":picker-options="item.config.pickerOption"/>
           </template>
         </template>
       </el-col>
     </el-row>

     <el-row style="margin-top:10px;">
       <!-- 表格查詢模塊 -->
       <el-table class="dynamic-table" v-loading="tableLoading" border :data="tableData" style="width: 100%" size='mini'>
         <!-- <el-table-column type="index" label="序號" align="center"></el-table-column> -->
         <template v-for="item in list.tableColumns">
           <el-table-column align="center" :prop="item.key" :label="item.label" min-width="80" :key="Math.random()">
             <template slot-scope="scope">
               <el-button v-if="item.type === 'event'" type="primary" size="mini" @click="handleClickTableOptBtn(item.key, scope.row)" plain>{{item.name}}</el-button>
               <span v-else-if="item.type==='text'">{{scope.row[item.key]}}</span>
             </template>
           </el-table-column>
         </template>
       </el-table>

       <!-- 分頁條模塊 -->
       <el-row v-if="showPage" type="flex" justify="center" class="list-pagination" style="margin-top:10px;">
         <el-pagination
           background
           @size-change="handlePageSizeChange"
           @current-change="handlePageCurrentChange"
           :current-page.sync="curPage"
           :page-sizes="$store.state.app.page.size"
           :page-size="curLimit"
           :layout="$store.state.app.page.layout"
           :total="total">
         </el-pagination>
       </el-row>
     </el-row>
   </el-card>
 </div>
</template>
<script>
export default {
    props: [
        'list', //查詢條件和返回結果列信息
        'tableData', //查詢結果 需拼接對應的操作按鈕
        'tableLoading',//表格加載狀態(tài)
        'showPage',//是否需要分頁
        'total', //分頁條參數(shù)-總條數(shù)
        'currentPage',  //分頁條參數(shù)-頁數(shù)
        'limit', //分頁條參數(shù)-分頁條數(shù)
        'query',  //查詢條件對象封裝
        'listenHandleClickQueryBtn',    //查詢條件區(qū) 按鈕事件監(jiān)聽
        'listenHandleClickTableOptBtn', //表格操作區(qū) 按鈕事件監(jiān)聽
        'listenHandlePageSizeChange', //分頁條數(shù)監(jiān)聽
        'listenHandlePageCurrentChange'   //分頁碼修改
    ],
    data() {
        return {
            curPage: this.currentPage,
            curLimit: this.limit
        }
    },
    methods: {
        //查詢區(qū)域 事件監(jiān)聽
        handleClickQueryBtn(queryKey) {
            this.$emit('listenHandleClickQueryBtn', queryKey)
        },

        //表格區(qū)域 操作按鈕 事件監(jiān)聽
        handleClickTableOptBtn(columnKey, row) {
            this.$emit('listenHandleClickTableOptBtn', columnKey, row)
        },
        //每頁條數(shù) 修改事件監(jiān)聽
        handlePageSizeChange(val) {
            this.curPage = 1
            this.curLimit = val
            this.$emit('listenHandlePageSizeChange', val)
        },
        handlePageCurrentChange(val) {
            this.curPage = val
            this.$emit('listenHandlePageCurrentChange', val)
        }
    }
}
</script>
<style>
.dynamic-report-mod{
  margin:10px;
}
.dynamic-search .el-button,
.dynamic-search .el-input,
.dynamic-search .el-date-editor,
.dynamic-search .el-select{
  margin-left:10px;
}
</style>

備注:因報表的標題行存在二級诚欠,后續(xù)對el-table-column做過相應的邏輯判斷和代碼調整。分頁條里的page-sizes和layout參數(shù)放在全局變量漾岳,也可參考element api寫死處理轰绵。代碼的注釋說明寫的還是比較詳細的,如有不明白的問題可留言

組件使用Demo

demo是一個普通報表尼荆,篩選條件僅時間區(qū)間框【僅可選昨日以前的日期】左腔,列表無操作按鈕僅數(shù)據(jù)展示,且無分頁數(shù)據(jù)捅儒。后續(xù)擴展按照初始配置依樣畫葫蘆即可液样!

<!-- 綜合統(tǒng)計報表 -->
<template>
  <dynamicReport
    :list="list"
    :query="query"
    :tableLoading="loading"
    :tableData="tableData"
    :showPage="showPage"
    :currentPage="currentPage"
    :limit="limit"
    :total="total"
    @listenHandleClickQueryBtn="handleClickQueryBtn"
    @listenHandleClickTableOptBtn="handleClickTableOptBtn"
    @listenHandlePageSizeChange="handlePageSizeChange"
    @listenHandlePageCurrentChange="handlePageCurrentChange"
  ></dynamicReport>
</template>
<script>
import dynamicReport from '@/components/query/dynamic-report'
export default {
    name: "StatisticReport",
    components: {
        dynamicReport
    },
    data() {
        return {
            showPage:false,
            currentPage: 1,
            limit: 10,
            total: 0,
            loading:false,
            tableData: [],
            list:{},
            query:{}
        }
    },
    methods: {
        handleClickQueryBtn(_type) {
            if (_type === 'query') {
                this.handleClickQuery()
            }
        },
        handleClickTableOptBtn(_type, rowInfo) {
            console.log('click column '+_type)
        },
        handlePageSizeChange(size) {
            this.currentPage = 1
            this.limit = size
            this.handleClickQuery()
        },
        handlePageCurrentChange(num) {
            this.currentPage = num
            this.handleClickQuery()
        },

        async handleClickQuery() {
          const _this = this;
          let _params = {..._this.query};
          if(_params.datePeriod.length==0){
            _this.$message.error("請先選擇時間振亮!");
            return false;
          }
          _this.loading = true;

          _params.startTime = _params.datePeriod[0]
          _params.endTime = _params.datePeriod[1];
          //====S 此處為數(shù)據(jù)請求   具體代碼刪除 此處僅做賦值操作
           _this.tableData = [{'aaa':'111','bbb':'222','ccc':'333','ddd':'444'}]
           _this.loading = false;
           //====E 此處為數(shù)據(jù)請求   具體代碼刪除 此處僅做賦值操作
        }
    },
    created(){
      //初始化報表配置數(shù)據(jù)
      this.list ={
        queryList: [
              {
                  label: '時間周期',
                  key: 'datePeriod',
                  type: 'datePicker',
                  config: {
                      type: 'daterange',
                      rangeSeparator: '-',
                      startPlaceholder: '開始日期',
                      endPlaceholder: '結束日期',
                      format:"yyyyMMdd",
                      pickerOption:{
                        disabledDate(time) {
                          return time.getTime() > Date.now()-24*60*60*1000;
                        }
                      }
                  },
              },
              {
                  label: '查詢',
                  key: 'query',
                  type: 'button',
                  config: {
                      type: 'primary'
                  }
              }
          ],
          tableColumns: [
              {
                  label: '字段1',
                  key: 'aaa',
                  type:"text"
              },
              {
                  label: '字段2',
                  key: 'bbb',
                  type:"text"
              },
              {
                  label: '字段3',
                  key: 'ccc',
                  type:"text"
              },
              {
                  label: '字段4',
                  key: 'ddd',
                  type:"text"
              }
          ]
        }

      //初始化查詢條件
      this.query = this.list.queryList.reduce((obj, item) => {
          if (item.type !== 'button') {
              obj[item.key] = ''
          }
          return obj;   //返回的是 {datePeriod:""}
      }, {})
    }
}
</script>
效果預覽

做完后可以用類似的思維進行表單的動態(tài)配置,單獨table渲染的配置等

完...

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蓄愁,一起剝皮案震驚了整個濱河市双炕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撮抓,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摇锋,死亡現(xiàn)場離奇詭異丹拯,居然都是意外死亡,警方通過查閱死者的電腦和手機荸恕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門乖酬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人融求,你說我怎么就攤上這事咬像。” “怎么了县昂?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長陷舅。 經(jīng)常有香客問我倒彰,道長,這世上最難降的妖魔是什么莱睁? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任待讳,我火速辦了婚禮,結果婚禮上仰剿,老公的妹妹穿的比我還像新娘创淡。我一直安慰自己,他們只是感情好南吮,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布琳彩。 她就那樣靜靜地躺著,像睡著了一般旨袒。 火紅的嫁衣襯著肌膚如雪汁针。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天砚尽,我揣著相機與錄音施无,去河邊找鬼。 笑死必孤,一個胖子當著我的面吹牛猾骡,可吹牛的內容都是我干的瑞躺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼兴想,長吁一口氣:“原來是場噩夢啊……” “哼幢哨!你這毒婦竟也來了?” 一聲冷哼從身側響起嫂便,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤捞镰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毙替,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體岸售,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年厂画,在試婚紗的時候發(fā)現(xiàn)自己被綠了凸丸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡袱院,死狀恐怖屎慢,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情忽洛,我是刑警寧澤腻惠,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站脐瑰,受9級特大地震影響妖枚,放射性物質發(fā)生泄漏。R本人自食惡果不足惜苍在,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一绝页、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧寂恬,春花似錦续誉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牙咏,卻和暖如春臼隔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背妄壶。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工摔握, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丁寄。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓氨淌,卻偏偏與公主長得像泊愧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子盛正,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348