VUE组件系列7:Table封装3

前面写的Table封装,只是省了一部分事情,还是需要通过slot配置表结构,没有达到一开始的想法:

只配置一个加载url和一个增删改url 就完事了。

所以就再次优化。

问题1 修改与非修改间切换,通过这么一个JSON数组 {"name":"标签名称","val":"标签值","flag":"是否显示"}

     <div class="unit" v-for="(item, index) in userData" :key="index">
        <label>{{ item.name }}:</label>
        <input
          type="text"
          v-model="item.val"
          class="sys_input"
          v-bind:disabled="item.flag == '0' ? false : true"
        />
      </div>

实现效果如下,这样就可以直接控制是否可以修改了。

d97b895091eaba86e4623a517e951120338.jpg

测试源码如下:

<template>
  <div>
    <!-- table部分 -->
    <div class="carddata">
      <table class="pre_dataintable">
        <thead>
          <tr>
            <th v-for="(item, index) in tab_th" :key="index">
              {{ item.val }}
            </th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(item, index) in tab_tr" :key="index">
            <td v-for="(temp, index) in item" :key="index">
              <input
                type="text"
                v-model="temp.val"
                v-bind:disabled="temp.flag == '0' ? false : true"
              />
            </td>
            <td>
              <button @click="fun_upd(item)">修改</button>
              <button @click="fun_sav(item)">保存</button>
              <button @click="fun_del(item)">删除</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <!-- 分页部分 -->
    <div class="pre_page" v-show="show_page">
      <ul style="text-align: right; margin-right: 20px;">
        <li>
          当前页:<label>{{ nowpage }}</label
          >&nbsp; 合计页:<label>{{ maxpage }}</label
          >&nbsp;&nbsp; <a href="#" @click="firstpage">首页</a>|
          <a href="#" @click="beforepage">上一页</a>|
          <a href="#" @click="nextpage">下一页</a>|
          <a href="#" @click="lastpage">尾页</a>
          <input type="text" v-model="jumppage" value="" /><a
            href="#"
            @click="gopage"
            class="go"
            >Go</a
          >
        </li>
      </ul>
    </div>
    <!-- 弹出向导层 start-->
    <div id="pop" class="pop" v-show="pop_show">
      <div class="pop_head">
        <a class="close" href="javascript:void(0);" @click="hide()"></a>
      </div>
      <div id="pop_bodyup" class="pop_bodyup">
        <div class="input_data">
          <slot name="tab_addorupdate"></slot>
          <!-- <button
            @click="neworupdate"
            @keyup.enter="neworupdate"
            style="margin:30px 0 0 80px;background:#4f5f6f;width:56px;height:28px;border:none;outline:none;cursor: pointer;color:#fff;"
          >
            新增或修改
          </button> -->
        </div>
      </div>
    </div>
    <!-- 弹出向导层 end-->
    <!-- 添加到下面 start -->
    <div class="data_down">
      <slot name="tab_addorupdate_down"></slot>
    </div>
    <!-- 添加到下面 end -->
    <!-- 组件引入部分 弹窗组件和等待组件 -->
    <div>
      <per-message ref="msg_back" :message_data="msg_obj" />
      <pre-loading :pre_show_loading="fullloading" />
    </div>
  </div>
</template>
<script >
/*
名称:Table组件
日期:2019-03-21
作者:hj
目标:1、传入一组数据,自动构建标题和内容=>两个数组  1个数组是标题  1个数组是内容  方便构造 
     2、所有的增、删、改、查、均在组件内容完成。
     3、还可以分页

分析:1、增、删、改、查 调用api主动配置。=>容易
     2、标题主动配置。=>容易
     3、每一列的校验方式 =>配置  
     4、不使用 solo 占位符实现

*/
import '@/assets/css/pop.css';
import '@/assets/css/pre_table.css';
export default {  
  name: "pre_table_base",
  components: {    
    'per-message':()=>import("./pre_message.vue"),
    'pre-loading':()=>import("./pre_loading.vue")
  },  
  data() {
    return {
      tab_th: [],     //标题
      tab_tr: [],     //内容  
      show_page:true,
      maxpage:'',
      nowpage:'',
      jumppage:'',
      msg_obj:{},
      fullloading:false,      
      pop_show:false,
      show_btn_upd:true,
      show_btn_del:true,
      show_btn_sav:true,
    };
  },
  props: {
    api_url:String,
    pre_post:String, 
    page:String,   
    /* 需要 增 删 改 就绑定这个 */
    pre_post_upd:{ type:String,default:'' },
    /* 按钮显示控制 */ 
    show_btn_upd:{type:Boolean,default:true},
    show_btn_del:{type:Boolean,default:true},
    show_btn_sav:{type:Boolean,default:true}

  },
  created:function(){
      if(Number(this.nowpage)==0) this.nowpage=1;
  },
  watch:{
    pre_post(val){
      //监测查询条件 改变即重查
      this.loaddata();
    },
    pre_post_upd(val){
      // 监测修改条件 改变即修改
      if(String(val)!='')
        this.neworupdate();
    },
    page(val){
      // 监测翻页
      if(Number(val)==0){
        this.nowpage=1;
      }else{
        this.nowpage=Number(val);
      }
    },
    nowpage(val){
      // 返回新页数
      this.$emit("tab-event", this.nowpage);
    }
  },
  mounted() {
    this.initTable();
    this.loaddata();
  },
  methods: {
    initTable:function(){
      if(Number(this.maxpage)==0){
        this.show_page=false;
      }else{
        this.show_page=true;
      }
    },
    firstpage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage=1;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是第一页'};
        }
    },
    beforepage:function(){
        if(Number(this.nowpage)>1){
            this.nowpage--;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是第一页'};
        }
    },
    nextpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage++;
            this.refresh_data();
        }else{            
            this.msg_obj={'showtype':'warning','note':'已经是最后一页'};
        }
    },
    lastpage:function(){
        if(Number(this.nowpage)<Number(this.maxpage)){
            this.nowpage=this.maxpage;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'已经是最后一页'};
        }
    },
    gopage:function(){
        console.log('跳转到='+this.jumppage);
        if(Number(this.jumppage)>0 && Number(this.jumppage)<=Number(this.maxpage)){
            this.nowpage=this.jumppage;
            this.refresh_data();
        }else{
            this.msg_obj={'showtype':'warning','note':'跳转页数不在规定范围内,请检查'+this.jumppage};
        }
    },
    loaddata:function() {
      // console.log(this.api_url);
      // console.log(this.pre_post);      
      // this.fullloading=true;
      // this.$post(
      //   this.api_url,
      //   this.pre_post,
      // ).then(res => {
      //   this.fullloading=false;
      //   try {         
      //     res=JSON.parse(res); 
      //     console.log(res.data);         
      //     if (res.data.status == 1) {
      //       this.maxpage=res.data.allpage;
      //       this.data_tab=res.data.data;
      //     } else {
      //       this.msg_obj={'showtype':'warning','note':res.data.msg};
      //     }
      //     this.initTable();
      //   } catch (ex) {
      //     this.msg_obj={'showtype':'warning','note':"查询失败"+ex};
      //   }
      // });

      // 构建测试数据 二维数组 模拟通过api取到如下数据
      var data=[];
      var tobj=[];
      tobj.push({"val":"序号"});
      tobj.push({"val":"列名1"});
      tobj.push({"val":"列名2"});
      tobj.push({"val":"列名3"});      
      data[0]=tobj;
      console.log(data);
      for(var i=1;i<5;i++){
        tobj=[];
        tobj.push({"val":""+i+"","flag":"1"});
        tobj.push({"val":""+i+"行数据1","flag":"1"});
        tobj.push({"val":""+i+"行数据2","flag":"1"});
        tobj.push({"val":""+i+"行数据3","flag":"1"});
        data[i]=tobj;
      }
      
      //  将表头和内容分开
      this.tab_th=data[0];
      var tdata=[],num=0;
      for(var i=1;i<data.length;i++){        
        tdata[num]=data[i];
        num++;
      }
      this.tab_tr=tdata;
      console.log(this.tab_th);
      console.log(this.tab_tr);

    },
    refresh_data() {
      console.log('刷新');
      this.$emit("tab-event", this.nowpage,this.key_word,'');
    },
    showpop:function(){
      this.pop_show=true;
    },
    hide:function(){
      this.pop_show=false;
    },
    fun_add:function(){

    },
    fun_del:function(item){
      console.log('删除');
      var ts=JSON.stringify(item).toString();
      console.log(ts);
      
    },
    fun_upd:function(item){
      console.log('修改');
      // var ts=JSON.stringify(item).toString();
      // console.log(ts);
      // 释放修改权限
      console.log(item);
      var id=item[0].val;
      for(var i=0;i<this.tab_tr.length;i++){
        if(this.tab_tr[i][0].val==item[0].val){
          for(var j=1;j<this.tab_tr[i].length;j++){
            this.tab_tr[i][j].flag='0';
          }
        }else{
          for(var j=1;j<this.tab_tr[i].length;j++){
            this.tab_tr[i][j].flag='1';
          }
        }
      }

    },
    fun_sav:function(item){
      console.log('保存');
      var ts=JSON.stringify(item).toString();
      console.log(ts);
    },
    fun_sel:function(){

    },
    neworupdate:function() {
      // console.log(this.api_url);
      // console.log(this.pre_post_upd);      
      this.fullloading=true;
      this.$post(
        this.api_url,
        this.pre_post_upd,
      ).then(res => {
        this.fullloading=false;
        this.pop_show=false;
        try {         
          res=JSON.parse(res); 
          console.log(res.data);         
          if (res.data.status == 1) {
            this.msg_obj={'showtype':'ok','note':res.data.msg};
            this.loaddata();
          } else {
            this.msg_obj={'showtype':'err','note':res.data.msg};
          }
          this.initTable();
        } catch (ex) {
          this.msg_obj={'showtype':'warning','note':"查询失败"+ex};
        }
      });
    },
  }
};
</script>
 
<style scoped >
</style>

CSS样式文件

/* pre_search */
.pre_btn {
	text-align: left;
}
.pre_btn > label {
	position: relative;
	/* left: 2%; */
}
.pre_btn > input {
	position: relative;
	/* left: 2%; */
}
.pre_btn > input :focus {
	border: 1px solid #024aee;
	background-color: #aaa;
}

.pre_btn > button {
	position: relative;
	left: 2%;
	width: 120px;
	height: 32px;
	line-height: 32px;
	border-radius: 5px;
}

.pre_btn_ok {
	background-color: rgba(68, 70, 238, 0.986);
	color: white;
	font-optical-sizing: 16px;
}

.pre_btn_ok :focus {
	background-color: rgba(247, 61, 36, 0.986);
}

/* table 整体样式 */
.pre_dataintable {
	margin-top: 15px;
	border-collapse: collapse;
	border: 1px solid #aaa;
	width: 95%;
	/* padding 没有作用 */
	/* padding: 0px 5px 10px 5px; */
	position: relative;
	/* left: 2%; */
}
.pre_dataintable th {
	vertical-align: baseline;
	padding: 5px 15px 5px 6px;
	background-color: rgb(87, 201, 230);
	border: 1px solid #3f3f3f;
	text-align: center;
	color: #000000;
	font-size: 16px;
	font-weight: bolder;
}
.pre_dataintable td {
	/* vertical-align: text-top; */
	padding: 5px 8px 5px 8px;
	border: 1px solid #aaa;
	text-align: left;
}
/* 表格内按钮 */
.pre_dataintable td button {
	width: 80px;
	padding: 6px 6px 6px 6px;
	border: 1px solid #aaa;
	text-align: center;
	display: inline-block;
}
/* 表格内输入框 */
.pre_dataintable td input {
	width: 100%;
	height: 100%;
	border: 0px;
	text-align: left;
	padding: 2px 2px 2px 2px;
  /* font-size: 16px; */
  background-color: #babcbe00;
}

.pre_dataintable tr {
	cursor: pointer;
}
.pre_dataintable tr:nth-child(odd) {
	background-color: #f5f5f5;
}
.pre_dataintable tr:nth-child(even) {
	background-color: #fff;
}
.pre_dataintable tr:hover {
	background-color: #e2fde2;
}

.tab_add {
	width: 95%;
	display: flex;
	margin-top: 5px;
	margin-left: 2%;
	background-color: rgba(103, 233, 77, 0.644);
}
.tab_upd {
	width: 95%;
	display: flex;
	margin-left: 2%;
	background-color: rgba(209, 212, 36, 0.644);
}

/* 翻页样式 */
.pre_page {
	width: 100%;
	margin-top: 5px;
	margin-bottom: 5px;
}
.pre_page > ul {
	text-align: right;
	list-style: none;
}
.pre_page > ul > li > a {
	text-decoration: none;
}
.pre_page > ul > li > .go {
	display: inline-block;
	width: 40px;
	height: 20px;
	border: 1px solid #cccccc;
	background: #024aee;
	color: #fff;
	border-radius: 4px;
	text-align: center;
	margin-left: 5px;
}
.pre_page > ul > li > a:hover {
	color: #394656;
}
/* 下面样式 */
.td_btn {
	text-align: center;
}
.td_btn > button {
	border-radius: 3px;
	height: 28px;
	padding: 1px 2px 2px 2px;
}
.td_btn > button:hover {
	background-color: rgba(155, 222, 231, 0.986);
	cursor: pointer;
}
.btn_upd {
	background-color: rgba(244, 247, 111, 0.986);
}
.btn_sub {
	background-color: rgba(44, 247, 61, 0.986);
}
.btn_can {
	background-color: rgba(234, 248, 246, 0.986);
}
.btn_del {
	background-color: rgba(236, 26, 26, 0.986);
}
/* 单选样式 */
.radio_name {
}
.radio_val {
	width: 20px;
}

效果如下

调用方式

73b94c71d3525f77c5e179a0b4881ad6110.jpg

展示效果:

默认数据

4ac1e2cca5c4784a8ebc1bcc11e4cc3b1c1.jpg

点击修改后数据

cb04400f5f39ce0692f5a2451df005f6187.jpg

818519d58ffa7d2f9376bdf7a43de409042.jpg

剩下的慢慢补全,总算不用每次都写好几个slot

PS:但是这样搞,又有新的限制,在列的样式控制上很麻烦啊。不如继续slot,至少样式问题没有解决前,真心不好整啊。

另一个问题就是sql返回,之前的返回直接拼接成json格式就好,

现在得拼接成这样子。

set @jsonData+='['
set @jsonData+='{"name":"id","val":"'+CONVERT(varchar(10),@temp_id)+'","flag":"1"},'
set @jsonData+='{"name":"h_short","val":"'+@parm1+'","flag":"0"},'
set @jsonData+='{"name":"h_title","val":"'+@parm2+'","flag":"0"},'
set @jsonData+='],'

目前处理方法:

sql拼接还是这样,

set @jsonData+='{"id":"'+CONVERT(varchar(10),@temp_id)+
              '","h_short":"'+@parm1+
              '","h_title":"'+@parm2+'"},'

然后在webservice里统一做转换,但是这样就不能很方便的通过修改flag来控制那些字段可以修改了。

纠结啊,所以看来还得继续slot站位!当然也有一些好处,自我感觉某些场景下还是有用的

伤心。。。。。。

想到好办法再更新

 

2019-06-13 add

第一步 样式

用CSS把input标签透明了,

tab tr td:nth-child(列数) 可以正向指定列样式

tab tr td:last-child(列数) 可以反向指定列样式

第二步修改 默认肯定都是 readonly

当点击修改时 应该是指定部分项目 可以改,同时修改input 背景色当点击保存时 再改回去。

缺点:如果 修改项目有下拉菜单 这样的选择项目 就呵呵了,不过如果都是字符串貌似就可以。

这样看还是占位符简单、容易实现啊。

还是没有完美解决,想到了再更新

转载于:https://my.oschina.net/qingqingdego/blog/3039645

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值