从WTM vue2版到 WtmPlus vue3

 从2019年开始注意到WTM,觉得代码生成器真是能省不少事,大部分的项目都缺不了系统管理(包含用户,用户组,角色,角色权限,数据权限),这个通用功能WTM项目已经集成,开发者可以把主要精力投入到业务开发。对于几个人做的小型项目,想要MVC模式开发,在这个基础上进行开发,风格就能达到统一;

到2020年,vue版本发布了,想着现在前后端分离是前端开发热门,就尝试了一下,我谈谈我的粗浅认识。

对这个Vue版本,WTM群友的第一感觉就是前端写出了后端的感觉,能把这个WTM-Vue版本吃透,Vue从基础到高级用法差不多了解得差不多了。

 

 对于初次接触的人,Vue 的 Mixins(混入)比较费解,但要了解WTM vue2 代码生成器生成的每个放在ClientApp/src/pages目录下的每个窗体页面,了解数据从webapi获取,在前端页面上面显示,然后响应按钮事件,Vue页面的生命周期,要细细,反反复复的看form-mixin.ts,action-minxin.ts,search.ts 这几个文件,要不都弄不清 store目录下的api.ts 里面写的。

import { contentType } from "@/config/enum";
const reqPath = config.headerApi + "/_actionlog/";

// 列表
const search = {
  url: reqPath + "Search",
  method: "post",
  dataType: "array"
};
// 批量删除
const batchDelete = {
  url: reqPath + "BatchDelete",
  method: "post"
};
// 详情
const detail = {
  url: reqPath + "{ID}",
  method: "get"
};
const exportExcel = {
  url: reqPath + "ExportExcel",
  method: "post",
  contentType: contentType.stream
};
const exportExcelByIds = {
  url: reqPath + "ExportExcelByIds",
  method: "post",
  contentType: contentType.stream
};
const getExcelTemplate = {
  url: reqPath + "GetExcelTemplate",
  method: "get",
  contentType: contentType.stream
};

// 导入
const imported = {
  url: reqPath + "Import",
  method: "post"
};
export default {
  search,
  batchDelete,
  detail,
  exportExcel,
  exportExcelByIds,
  getExcelTemplate,
  imported
};

 这些是怎么被调用。

另外就是 ClientApp/src/components/ 下面的文件,这个可以

<template>
    <wtm-dialog-box :is-show.sync="isShow" :status="status" :events="formEvent">
        <wtm-create-form :ref="refName" :status="status" :options="formOptions">
        </wtm-create-form>
    </wtm-dialog-box>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { Action, State } from "vuex-class";
import formMixin from "@/vue-custom/mixin/form-mixin";

@Component({ mixins: [formMixin()] })
export default class Index extends Vue {
    // 表单结构
    get formOptions() {
        return {
            formProps: {
                "label-width": this.$t("actionlog.LabelWidthForm")
            },
            formItem: {
                "Entity.ID": {
                    isHidden: true
                },
                "Entity.ModuleName": {
                    type: "input",
                    label: this.$t("actionlog.ModuleName")
                },
                "Entity.ActionName": {
                    type: "input",
                    label: this.$t("actionlog.ActionName")
                },
                "Entity.ITCode": {
                    type: "input",
                    label: "ITCode"
                },
                "Entity.ActionUrl": {
                    type: "input",
                    label: "Url"
                },
                "Entity.ActionTime": {
                    type: "input",
                    label: this.$t("actionlog.ActionTime")
                },
                "Entity.Duration": {
                    type: "input",
                    label: this.$t("actionlog.Duration")
                },
                "Entity.IP": {
                    type: "input",
                    label: "IP"
                },
                "Entity.Remark": {
                    type: "input",
                    label: this.$t("actionlog.Remark")
                }
            }
        };
    }
}
</script>

把表单结构转换成element组件,注意分析下 ClientApp/src/components/page/CreateForm/utils.tsx 文件,里面的generateWtmFormItemComponent 值得好好分析;

生成普通的页面,例如下图页面就很容易,

但是generateWtmFormItemComponent 生成复杂页面就力不从心,

 

 要怎么把element组件集成到wtm-create-form里面,

   <wtm-create-form :ref="refName" :status="status" :options="formOptions">
   </wtm-create-form>

我自己是修改 ClientApp/Src/Components/page/CreateForm/index.ts

render(h) {
    const components = _.keys(this.options.formItem).map((key) => {
      const createItem=this.options.formProps["createItem"];
     
      const item = this.options.formItem[key];
      if (_.isFunction(item.isHidden)) {
        if (item.isHidden(this.getFormData(), this.status)) {
          return;
        }
      }
      if ((_.isBoolean(item.isHidden) && item.isHidden) || !item.type) {
        return;
      }
      const itemComp = componentObj[item.type];
        const option = { ...item, key };
        if (createItem == false) {            
            return;
        }
      const contentComp = itemComp ? itemComp.call(this, h, option) : null;

      return componentObj.wtmFormItem.call(this, h, option, contentComp);
    });
    const props = {
      ...this.options.formProps,
      disabled: this.status === "detail",
      model: this.sourceFormData || this.formData,
    };
    const slots = this.$scopedSlots["default"];
    if(props["createItem"]==false){
       return  (      
      <el-form ref={this.elFormRefKey} {...{ props }}>      
         <el-row class={this.elRowClass}>
           {slots && slots({})}
         </el-row> 
      </el-form>
     );
    }    
    if(props["tabs"]){       
       const tbpanes=props["tabs"].panes.map((key)=>{
         const tbpanes_Components=components.slice(Number(key.start),Number(key.end)+1);    
         return (  <el-tab-pane label={key.label} name={key.name}>
                      {tbpanes_Components}
                    </el-tab-pane>
         );
         });       
       return (      
      <el-form ref={this.elFormRefKey} {...{ props }}>
         <el-row class={this.elRowClass}>
           <el-tabs v-model={props["tabs"].activeName} type="border-card">
               {tbpanes}                       
           </el-tabs>
              {slots && slots({})}
           </el-row>
      </el-form>
      );
    }
    else{
    return (      
      <el-form ref={this.elFormRefKey} {...{ props }}>
                           <el-row class={this.elRowClass}>
                             {components}
                              {slots && slots({})}
                              </el-row>

      </el-form>
     );
    }

其中一个用法是根据组件顺序,把指定范围的组件放到 一个 el-tab-pane,但是用到这种的情况比较少,另一个就是

<template>
    <wtm-dialog-box :is-show.sync="isShow" :status="status" :events="formEvent">
        <wtm-create-form :ref="refName" :status="status" :options="formOptions" :sourceFormData="mergeFormData">       
                <el-form-item prop="Entity.Name" :rules="formOptions.formItem['Entity.Name'].rules">
                    <el-input  v-model="mergeFormData.Entity.Name" placeholder="请输入库名" @blur="blur"></el-input>
                </el-form-item>
            <el-form-item>
                <el-input v-model="mergeFormData.Entity.Address" placeholder="请输入地址" @blur="blur"></el-input>
            </el-form-item>
        </wtm-create-form>
    </wtm-dialog-box>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { Action, State } from "vuex-class";
import formMixin from "@/vue-custom/mixin/form-mixin";
import UploadImg from "@/components/page/UploadImg.vue";
    //:sourceFormData="mergeFormData"
@Component({
    mixins: [formMixin()]
})
export default class Index extends Vue {

    mergeFormData ={
       Entity:{
        "ID":0,
        Name:"Name",
        Address:"Address",
      }
    }
    

    // 表单结构
    get formOptions() {
        const filterMethod = (query, item) => {
            return item.label.indexOf(query) > -1;
        };
        return {
            formProps: {
                "label-width": "100px",
                "createItem":false,
            },
            formItem: {
                "Entity.ID": {
                    isHidden: true
                },
             "Entity.Name":{
                 label: "Name",
                 rules: [{ required: true, message:"库名不能为空",trigger: "blur" }],
                 type: "input",
                 modifier:"trim",//v-model.trim v-model.number,v-model.lazy
                 slotKey:"SlotName"
            },
             "Entity.Address":{
                 label: "Address",
                 rules: [{ required: true, message: "地址"+this.$t("form.notnull"),trigger: "blur" }],
                 type: "input"
            }
                
            }
        };
    }
     beforeRequest(formData?: object): object | void {
      console.log("beforeRequest:", formData);
      return formData;
    }

    blur(){
      console.log("this.form",this.$refs[this.refName]);
      console.log("blur",this.mergeFormData);      
      this.$refs[this.refName].setFormDataItem("Entity.Name",this.mergeFormData.Entity.Name);
      this.$refs[this.refName].validate((valid) => {
          if (valid) {          
          } else {            
            return false;
          }
        });
    }
}
</script>

当 "createItem":false 时,在 wtm-create-form 里面自己绑定组件;总之Vu2版本要写项目,还是要进行各种改造,不像 Layui版本那种绑定风格,自由度感觉受到限制;

有看过 WTM react 版本,react版本跟layUI版本的绑定比较类似,自己把实体绑定到每个组件上,后来听说WTM vue版本要进行WTM VU3重制,我不知道了解信息有没有错误,是WTM react操刀人要进行WTM vue3版本重制,我就想风格应该会跟React类似;

千呼万唤,2021.11.18 WTMPlus Vu3版本正式发布,听说刘总为了发布都熬通宵了;

第一时间生成几个Model试了一下,看看有啥变化。

 

 

 整个目录结构都变了,UI也由Vue element 换成了 Vue antd,看绑定,是不是跟 layUI版本有点类似了。

<template>
  <WtmDetails :queryKey="queryKey" :loading="Entities.loading" :onFinish="onFinish">
    <a-row :gutter="6">
      <a-col :span="12">
         <WtmField entityKey="NameAdd"/>
      </a-col>
      <a-col :span="12">
         <WtmField entityKey="Id_NoAdd"/>
      </a-col>
      <a-col :span="12">
         <WtmField entityKey="Day_of_birthAdd"/>
      </a-col>
    </a-row>

      <div style="text-align:right;">


      </div>

  <template #button>
  
   <a-divider type="vertical" />
   <a-button type="primary" html-type="submit">
       <template v-slot:icon>
           <SaveOutlined style='margin-right:5px'/>
       </template>
       <i18n-t :keypath="$locales.SysSubmit" />
   </a-button>
   <a-divider type="vertical" />
   <a-button type="primary" @click.stop.prevent="__wtmBackDetails()">
       <template v-slot:icon>
           <RedoOutlined style='margin-right:5px'/>
       </template>
       <i18n-t :keypath="$locales.SysClose" />
   </a-button>
  </template>
  </WtmDetails>
</template>

 

 还刚接触Vue3版本的,等认识更深刻后再发表看法;

最后夸一夸 WTMPlus,拥有多个微软MVP的团队倾力打造的低码平台,而且项目源码全部可以下载,开发者可以进行自由发挥,对于一个程序员,源码在手,天下我有的感觉是不一样的。

网址:http://wtmplus.walkingtec.cn

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值