umy-ui使用手册

3 篇文章 0 订阅

可支持大批量table长列表虚拟表格(几万行数据渲染是没问题的)
项目直接安装
npm install umy-ui
在main.js中引用

import UmyUi from 'umy-ui'
import 'umy-ui/lib/theme-chalk/index.css'// 引入样式
Vue.use(UmyUi)

实列:

<template>
	<div class="content">
		<i class="el-icon-edit"></i>
		<i class="el-icon-minus"></i>
		
		<el-button type="primary" @click="exportData">下载</el-button>
		<el-button type="primary" @click="openDialog">筛选字段</el-button>
		<div class="content_table">
			<ux-grid 
			  :key="Math.random()" 
			  :edit-config="{trigger: 'click', mode: 'cell'}" 
			  :highlight-current-row="false"
				show-summary
				:summary-method="summaryMethod"
				ref="plTable" 
				:data="data" 
				:max-height="height" 
				use-virtual 
				show-header-overflow="tooltip"
				show-footer-overflow="tooltip" 
				show-overflow="tooltip" 
				:stripe="true"
				:row-style="rowStyle"
				moveDownIcon="el-icon-caret-bottom"
        moveUpIcon="el-icon-caret-top"
				:showDialogIcon="true"
				field-title="选择展示列表"
        :field-sort="true"
				:dialog-data="dialogData"
				:checkbox-config="{highlight: true}"
				@show-field="showField"

				@toggle-tree-expand="toggleTreeExpand"
				:tree-config="{ iconOpen: 'el-icon-minus', iconClose: 'el-icon-plus',children:'children' , indent:40, line:'true'}"
				:header-row-style="{color:'#FFFFFF',backgroundColor:'rgba(1, 73, 95)'}" 
				border>
				
				<ux-table-column type="expand1" width="55" title="展开" align="center" fixed="left" tree-node/>
				<!-- <ux-table-column type="checkbox" width="55" align="center" fixed="left"/> -->
				<ux-table-column type="index" width="50" title="序号" align="center" fixed="left"/>
				
				<template v-for="(item,index) in columns">
					<ux-table-column
					v-if="item.dataIndex!='score'&&item.dataIndex!='sex'&&item.dataIndex!='avatar'&&item.dataIndex!='mtime'&&item.dataIndex!='action'&&findIndex(item.title)"
					:key="index"
					prop="date"
					:filters="[{ data: '' }]"
					:filter-method="filterNameMethod"
					:resizable="true" 
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title"
					:fixed="item.fixed"
					:width="item.width"
					:min-width="item.minWidth"
					:align="item.align"
					:edit-render="['select','input'].indexOf(item.type)>-1"
					>
					  <!-- 可编辑项 -->
					  <template v-slot:edit="scope">
					    <a-input v-if="item.type=='input'" v-model="scope.row[item.dataIndex]"></a-input>
						<el-select v-if="item.type=='select'" v-model="scope.row[item.dataIndex]">
	                      <el-option
                            v-for="item in userList"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                          </el-option>
						</el-select>
					  </template>
						
						<template v-slot="{ row }">
							{{ row[item.dataIndex]}}
						</template>
						<!-- 筛选功能 -->
							<template v-slot:filter="{ $panel, column }">
								<a-input type="type"
									v-for="(option, index) in column.filters"
									:key="index"
									v-model="option.data"
									@input="$panel.changeOption($event, option.data, option)"/>
							</template>
					</ux-table-column>
					
					<!-- 将布尔值转化为数字 -->
					<ux-table-column
					:key="index"
					v-if="item.dataIndex=='sex'&&findIndex(item.title)"
					:resizable="true" 
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title" 
					:width="item.width" 
					:align="item.align">
						<template v-slot="{ row }">
							<select v-if="item.type=='select'&&item.dataIndex=='USER_TYPE'" v-model="scope.row.USER_TYPE">
							  <option v-for="(item1,index1) in userList" :key="item1.value" :value="item1.value">{{item1.label}}</option>
							</select>
							{{ row[item.dataIndex]?'男':'女'}}
						</template>
					</ux-table-column>
					<!-- 将base64转体图片 -->
					<ux-table-column
					:key="index"
					v-if="item.dataIndex=='avatar'&&findIndex(item.title)"
					:resizable="true" 
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title" 
					:width="item.width" 
					:align="item.align">
						<template v-slot="{ row }">
							<img :src="row[item.dataIndex]" >
						</template>
					</ux-table-column>
					
					<!-- 将数字转换为进度条 -->
					<ux-table-column
					:key="index"
					v-if="item.dataIndex=='score'&&findIndex(item.title)"
					:resizable="true" 
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title" 
					:width="item.width" 
					:align="item.align">
						<template v-slot="{ row }">
							<el-progress :percentage="row[item.dataIndex]" color="#5a1216"></el-progress>
						</template>
					</ux-table-column>

					<!-- 筛选时间范围 -->
					<ux-table-column
					:key="index"
					v-if="item.dataIndex=='mtime'&&findIndex(item.title)"
					:filters="[{ data: [] }]"
					:filter-method="filterNameMethod"
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title" 
					:width="item.width" 
					:align="item.align">
					 <template v-slot="{ row }">
              {{ row[item.dataIndex]}}
            </template>
					<!-- 时间筛选功能 -->
            <template v-slot:filter="{ $panel, column }">
                <cTimeRange 
                v-for="(option, index) in column.filters"
                :key="index"
                v-model="option.data"
                :defaultValue = "option.data"
                @input="$panel.changeOption($event, option.data, option)"
                ></cTimeRange>
            </template>
					</ux-table-column>
					
					<ux-table-column
					:key="index"
					v-if="item.dataIndex=='action'&&findIndex(item.title)"
					:resizable="true" 
					:show-overflow-tooltip="true"
					:field="item.dataIndex" 
					:title="item.title" 
					:width="item.width" 
					:align="item.align">
						<template v-slot="{ row }">
						  <router-link to="{name:'detail',params:'{id:row.id}'" >
						    <span>详情</span>
						  </router-link>
						</template>
					</ux-table-column>
				</template>
			</ux-grid>
		</div>
	</div>
</template>
<script>
	import {umyData} from '../../utils/fakedata'
	import axios from 'axios'
	import cTimeRange from '../../component/cTimeRange.vue'
	import moment from 'moment'

	const columns = [
		{
			title: "id",
			dataIndex: "id",
			minWidth: 200, //可用作自适应
			align: "center",
			fixed: "left",
			type:'text',
		},
		{
			title: "姓名",
			dataIndex: "nickname",
			width: 100,
			align: "center",
			fixed: "left",
			type:'input',
		},
		{
			title: "头像",
			dataIndex: "avatar",
			width: 200,
			align: "center",
			fixed: "left",
			type:'img',
		},
		{
			title: "部门",
			dataIndex: "dep",
			width: 100,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "地址",
			dataIndex: "address",
			width: 100,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "城市",
			dataIndex: "city",
			width: 220,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "性别",
			dataIndex: "sex",
			width: 70,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "时间",
			dataIndex: "mtime",
			width: 270,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "级别",
			dataIndex: "rank",
			width: 100,
			align: "center",
			fixed: "",
			type:'select',
		},
		{
			title: "成绩",
			dataIndex: "score",
			width: 170,
			align: "center",
			fixed: "",
			type:'text',
		},
		{
			title: "星数",
			dataIndex: "stars",
			width: 100,
			align: "center",
			fixed: "right",
			type:'text',
		},
		{
			title: "操作",
			dataIndex: "action",
			width: 100,
			align: "center",
			fixed: "right",
			type:'text',
		}
	];
	export default {
		components:{
			cTimeRange
		},
		data() {
			return {
				moment,
				height: '470px',
				data: umyData.list,//就用了101条数据。
				columns: columns,
				userList:[
				  {label:1,value:1},
				  {label:2,value:2},
				  {label:3,value:3},
				],
				dialogData:[
					{ name: 'id', state: true, disabled: true },
					{ name: '姓名', state: true,},
                    { name: '头像', state: true },
                    { name: '部门', state: true,},
					{ name: '地址', state: true, },
					{ name: '城市', state: true, },
					{ name: '性别', state: true, },
                    { name: '时间', state: true, },
                    { name: '级别', state: true, },
                    { name: '成绩', state: true, },
                    { name: '星数', state: true, },
                    { name: '操作', state: true, },
				]
			}
		},
		created() {},
		mounted() {
			console.log(umyData)
			// let objData = this.$refs.plTable.getTableData().visibleData;
		},
		methods: {
			//斑马纹
			rowStyle({row, rowIndex}){
			  if(rowIndex % 2 !== 0){
			    return {background: 'rgba(33, 119, 184)', color: '#FFF',height:'30px'}
			  }else {
			    return {background: 'rgba(65, 174, 60)', color: '#FFF',height:'30px'}        
			  }
			},
			//表头搜索重置
			filterNameMethod({ option, row ,column}){
			  const property = column['property'];
			  let format = 'YYYY-MM-DD';
        //判断字段是否为null、模糊查询
        if(typeof row[property] === 'string'){
          //时间筛选
          if(property == 'mtime'){
            let starT = moment(option.data[0],format);
            let endT = moment(option.data[1],format);
            let currentT = moment(row[property],format);
            if(moment(currentT).diff(endT,'days')<=0&&moment(currentT).diff(starT,'days')>=0){
              return true
            }else{
              return false
            }
          }else{
            return row[property].indexOf(option.data) > -1?true:false
          }
        }else{
          return false
        }
			},
			//合计
			summaryMethod ({ columns, data }) {
		      // 平均值算法(不需要自己去掉)
		      function cacl(arr, callback) {
		        let ret;
		        for (let i=0; i<arr.length;i++) {
		          ret = callback(arr[i], ret);
		        }
		        return ret;
		      }
		      // 平均值算法(不需要自己去掉)
		      Array.prototype.sum = function () {
		        return cacl(this, function (item, sum) {
		          if (typeof (sum) == 'undefined') {
		            return item;
		          }
		          else {
		            return sum += item;
		          }
		        });
		      };
		      const means = [] // 合计
		      columns.forEach((column, columnIndex) => {
		      if (columnIndex === 0) {
		        means.push('合计')
		      }
		      else if(column.title === '姓名'){
		        return;
		      }else if(column.title === '头像'){
		        return;
		      }else if(column.title === '时间'){
		        return;
		      }else {
		        const values = data.map(item => Number(item[column.property]));
		        // 合计
		        if (!values.every(value => isNaN(value))) {
		          means[columnIndex] = values.reduce((prev, curr) => {
		            const value = Number(curr);
		            if (!isNaN(value)) {
		              return prev + curr;
		            } else {
		              return prev;
		            }
		          }, 0);
		          // means[columnIndex] += ' 元'
		          // 改变了ele的合计方式,扩展了合计场景
		          // 你以为就只有上面这样玩吗?错啦,你还可以自定义样式哦
		          // means[columnIndex] = '<span style="color: red">' + means[columnIndex] + '元</span>'
		          // means[columnIndex] = '<span>' + means[columnIndex]+ '</span>'
		          // means[columnIndex] = '<span>' + Math.round(means[columnIndex]*100)/100+ '</span>'
		          means[columnIndex] = Math.round(means[columnIndex]*100)/100
		        } else {
		          means[columnIndex] = '';
		        }
		      }
		    })
		      return [means]
		    },
			//展开关闭树形结构
			toggleTreeExpand({ expanded, row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }){
				console.log({ expanded, row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event })
			},
			//导出
			exportData(){
			  //获取当前表格数据(筛选后的数据)
			  let objData = this.$refs.plTable.getTableData().visibleData;
			  console.log(objData);
			  axios({
			    method: 'post',
			    url: '',
			    data: objData,
			    responseType: "blob",
			    }).then((res)=>{
			      const content = res.data;
			      const bLob = new Blob([content]);
			      const fileName = "表格数据.xLs";
			      if ("download" in document.createElement("a")) { //非IE下载
			      const elink = document.createElement("a");
			      elink.download = fileName;
			      elink.style.display = "none";
			      elink.href = URL.createObjectURL(bLob);
			      document.body.appendChild(elink) ;
			      elink.click();
			      URL.revokeObjectURL(elink.href); //释放URL对象
			      document.body.removeChild(elink) ;
			      } else {
			        navigator.msSaveBlob(bLob,fileName);
			      }
			  })
			},
			//筛选字段
			openDialog(){
				this.$refs.plTable.plDialogOpens()
			},
			showField(e){
		    //   console.log(e);
			  this.dialogData = e
	    },
			//查找索引,判断是否显示
			findIndex(sele){
		    const index = this.dialogData.indexOf(this.dialogData.filter(d => d.name === sele)[0])
			  if(index> -1){
				  return this.dialogData[index]['state']
			  }else{
				  return false
			  }
			},
		}
	};
</script>
<style scoped>
.content{
	height: 100%;
	width: 100%;
	background: #c7d2d4;
}
.content_table{
	padding: 10px;
	width: calc(100% - 20px);
}

::v-deep ::-webkit-scrollbar {
  height: 15px;
  width: 15px;
}
::v-deep ::-webkit-scrollbar-thumb {
  /* border-radius: 5px; */
  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
  background: rgba(0, 203, 255, 0.6);
}
::v-deep ::-webkit-scrollbar-track {
  box-shadow: 0;
  border-radius: 0;
  background: rgba(0, 0, 0, 0.37);;
}
</style>

mock 假数据代码。
fakedata.js

// 使用 Mock
var Mock = require('mockjs')
var data = Mock.mock({
	// 属性 list 的值是一个数组,其中含有 1 到 10 个元素
	'list|10': [{
		// 属性 id 是一个自增数,起始值为 1,每次增 1
		'id': "@id()",        // 随机生成id
		"mtime": "@date", //随机生成日期时间
		"dep": "一级部门",
		"sex|1-2": true,      //随机生成布尔值
		"address": '@region',  //随机生成区域
		"city": '@county(true)', //随机生成城市
		"avatar": "@dataImage('40x25','你的名字')", //生成base64图片
		"score|0-100": 800, //随机生成1-100的数字
		"rank|1-3": 1, //随机生成1-3的数字
		"stars|1-5": '★', //随机生成1-5个★
		"nickname": "@cname", //随机生成中文名字
		"children|1-10": [{
			'id': "@guid",		  // 随机生成guid
			"mtime": "@date", //随机生成日期时间
			"dep": "二级部门",
			"sex|1-2": true,     //随机生成布尔值
			"address": '@region',  //随机生成区域
			"city": '@county(true)', //随机生成城市
			"avatar": "@dataImage('40x25','你的名字')", //生成base64图片
			"score|1-100": 800, //随机生成1-100的数字
			"rank|1-3": 1, //随机生成1-3的数字
			"stars|1-5": '★', //随机生成1-5个★
			"nickname": "@cname", //随机生成中文名字
		}]
	}]
})
export const umyData = data


效果图
在这里插入图片描述
封装的时间范围组件(因为antd DatePicker组件不支持@input事件)

<template>
  <div class="gtTimeRange">
    <input type="date" v-model="defaultValue[0]" @input="startInput"/>
    <span class="gtTimeRange_splitLine">-</span>
    <input type="date" v-model="defaultValue[1]" @input="endInput" @focus="endMousemove"/>
  </div>
</template>
<script>
import moment from "moment";
import "moment/locale/zh-cn";
export default {
  name: "gtTimeRange",
  props: {
    defaultValue: {
      type: Array,
      // required: true,
      default: () => [null,null]
    },
  },
  watch:{
    defaultValue(val){
      // console.log(val)
    }
  },
  mounted() {
  },
  data() {
    return {
      moment,
      startTime:null,
      endTime:null,
      timeRange:null,
    };
  },
  created(){
    // console.log(moment().format("YYYY-MM-DD"));
  },
  methods:{
    startInput(e){
      this.$emit('input',this.defaultValue);
    },
    endInput(e){
      this.$emit('input',this.defaultValue);
    },
    endMousemove(e){
      // console.log(e);
    },
  
};
</script>
<style scoped>
.gtTimeRange{
  display: flex;
  height: 50px;
  width: 100%;
}
.gtTimeRange_splitLine{
  color: rgb(10, 0, 0);
  margin: 10px;
}
</style>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值