elementUI版系统更新日志

最终效果:

新增

查询页面:

<template>
<div class="app-container">
  <el-row>
    <el-col :span="12">
      <el-card>
        <el-statistic
          :value="updateNum"
          title="更新次数"
        ></el-statistic>
      </el-card>
    </el-col>
    <el-col :span="12">
      <el-card>
        <el-statistic
          :value="problemNum"
          title="解决问题数量"
        ></el-statistic>
      </el-card>
    </el-col>
  </el-row>
  <el-row :gutter="10" style="margin-top: 30px;height: 100%">
    <el-col :span="1.5">
      <el-button
        type="primary"
        plain
        :icon="IconEnum.ADD"
        size="mini"
        @click="handleAdd"
      >新增</el-button>
    </el-col>
  </el-row>
  <el-card style="margin-top: 30px;height: 100%">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
      <el-form-item label="版本号">
        <el-input v-model="queryParams.versionNo"
                  placeholder="请输入版本号"
                  clearable
                  @keyup.enter.native="searchQuery"></el-input>
      </el-form-item>
      <el-form-item label="发布时间">
        <el-date-picker
          v-model="queryParams.updateDateList"
          style="width: 240px"
          format="yyyy-MM-dd"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        ></el-date-picker>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" :icon="IconEnum.SEARCH" size="mini" @click="searchQuery">搜索</el-button>
        <el-button :icon="IconEnum.RESET" size="mini" @click="resetQuery('queryForm')">重置</el-button>
      </el-form-item>
    </el-form>
    <div style="overflow:auto">
      <el-timeline>
        <el-timeline-item  v-for="(item, index) in dataSource" :key="index" :timestamp="item.updateDate" placement="top">
            <div :class="isExpanded[index]?'extendCard':'hiddenCard'">
              <div>
                <el-button plain :icon="IconEnum.EDIT" type="warning" size="mini"
                           @click="handleEdit(item.id)">编辑</el-button>
                <el-button type="danger" plain :icon="IconEnum.DELETE" size="mini" @click="handleDelete(item)"
                >删除</el-button>
                <el-button style="float: right" size="mini" v-if="!isExpanded[index]" @click="expandCard(index)">展开</el-button>
                <el-button style="float: right" size="mini" v-else @click="collapseCard(index)">收起</el-button>
              </div>
              <span style="display: inline;font-weight: bold;font-size: large;line-height: 40px;">版本号:{{item.versionNo}}</span>
              <div v-for="content in item.sysVersionItemDtoList">
                <span style="font-weight:bold">【{{content.modelName}}】</span>
<!--                <div v-for="problem in content.problemList">-->
                  <div v-html="content.problem.replace(/\n/g, '<br>')"></div>
<!--                </div>-->
              </div>
            </div>
        </el-timeline-item>
      </el-timeline>
      <el-pagination
        :current-page.sync="queryParams.page"
        :page-sizes="[5, 10, 20, 30]"
        :page-size.sync="queryParams.pageSize"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      ></el-pagination>
    </div>
  </el-card>
  <!--  组件区域  -->
  <verson-modal ref="versionModal" @ok="handleOk"></verson-modal>
</div>
</template>

<script>
/**一些引入*/

export default {
  name: "index",
  components: {VersonModal},
  data(){
    return{
      updateNum:0,
      problemNum:0,
      url: {
        list: '/system/version/list',
        delete: '/system/version/batch/',
      },
      queryParams:{
        page: 1,
        pageSize: 10,
        versionNo:undefined,
        updateDateList:undefined,
      },
      dataSource:[],
      isExpanded:[],
    }
  },
  created() {
    this.loadData(1)//加载第一页
  },
  methods:{
    loadData(arg) {
     //加载数据逻辑,记得写分页
    },
    searchQuery() {
      this.isExpanded=[]
      this.loadData(1);
      // 点击查询清空列表选中行
      this.ids = []
    },
    handleSizeChange(pageSize) {
      this.isExpanded=[]
      this.queryParams.pageSize = pageSize
      // 请求列表
      this.loadData(1)
    },
    handleCurrentChange(page) {
      this.isExpanded=[]
      this.queryParams.page = page
      // 请求列表
      this.loadData()
    },
    resetQuery(queryForm) {
      this.resetForm(queryForm)
      this.queryParams = {}
      this.loadData(1);
    },
    expandCard(index) {
      this.isExpanded[index] = true;
      this.$forceUpdate()
    },
    collapseCard(index) {
      this.isExpanded[index] = false;
      this.$forceUpdate()
    },
    handleAdd(){
      this.$refs.versionModal.handleAdd()
    },
    handleEdit(id){
      this.$refs.versionModal.handleEdit(id)
    },
    handleOk(){
      this.loadData(1)
    }
  }
}
</script>

<style scoped>
.demo-infinite-container {
  overflow: auto;
  padding: 8px 24px;
  height: 100vh;
}
.hiddenCard{
  height:200px;
  overflow: hidden;
  border:1px solid rgba(196, 196, 196, 0.5);
  border-radius: 5px;
  padding: 30px 20px;
}
.extendCard{
  height: 100%;
  border:1px solid rgba(196, 196, 196, 0.5);
  border-radius: 5px;
  padding: 30px 20px;
}
.hiddenCard::before {
  content: "";
  position: absolute;
  right:auto;
  bottom: 1px;
  left: 10px;
  width: 90%;
  height: 40px;
  background: linear-gradient(rgba(255,255,255,0),rgba(255,255,255,1));
  pointer-events:none;
}
</style>

新增窗口:

<template>
  <div class="app-container">
    <el-dialog :title="title" :visible.sync="open" v-if="open" width="75%" :before-close="cancel" append-to-body>
      <el-form ref="form" :model="form" :rules="rules"  label-width="100px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="版本号" prop="versionNo">
              <el-input v-model="form.versionNo" placeholder="请输入版本号" style="width: 80%" :disabled="readOnly"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
          <el-form-item label="发布日期" prop="updateDate">
            <el-date-picker
              v-model="form.updateDate"
              value-format="yyyy-MM-dd"
              type="date"
              placeholder="选择日期">
            </el-date-picker>
          </el-form-item>
        </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" :loading="submitLoading" @click="submitForm" :disabled="readOnly">保存</el-button>
        <el-button @click="cancel">关闭</el-button>
      </div>
      <el-alert
        title="更新内容请按1./2./3.标明序号,使用回车符间隔每条内容"
        type="warning"
        :closable="false">
      </el-alert>
      <EditTable :config="config" ref="modelForm"  />
    </el-dialog>
  </div>
</template>

<script>
import EditTable from "@/components/EditTable";
import {addVersionApi, editVersionApi, getVersionApi} from "@/api/system/system/version";

export default {
  name: "versonModal",
  components: {
    EditTable,
  },
  data(){
    return {
      title: "",//标题
      open: false,//是否弹出
      readOnly: false,//表单可编辑
      submitLoading: false,
      form:{
        versionNo:undefined,
        updateDate:undefined,
      },
      modelList:[],
      config: {
        columns :[
          { prop: 'id', label: 'id', attr: {width: '180'}, hidden:true},
          { prop: 'modelName', label: '模块名',edit: true,rules: [{required: true, message: '请输入'}]},
          { prop: 'problem', label: '更新内容', edit: true,type:'textArea', rules: [{required: true, message: '请输入'}]},
          { prop: 'opt', label: '操作', edit: true, align: 'center'  }
        ],
        isAdd: !this.readOnly,
        isDetail:this.readOnly,
        isRowLimit: false,
        isSubmit:false,
        data:this.modelList
      },
      rules: {//表单校验
        versionNo: [
          {required: true, message: "请输入版本号", trigger: "change"}
        ],
        updateDate: [
          {required: true, message: "请选择发布日期", trigger: "change"}
        ],
      }
    }
  },
  methods:{
    /** 新增操作 */
    handleAdd() {
      this.open = true;
      this.readOnly = false
      this.title = "新增";
    },
    /** 编辑操作 */
    handleEdit(id) {
      if(id) {
        this.readOnly = false
        getVersionApi(id).then(res => {
          this.form = res.data
          this.modelList = res.data.sysVersionItemDtoList
          this.open = true;
          this.title = "编辑";
          this.$nextTick(() => {
            this.$refs.modelForm.setData(this.modelList)
          })
        })
      }
    },
    reset(){
      this.form={}
      this.$refs.modelForm.reset()
    },
    setData(data){
      this.$refs.form.setData(data)
    },
    cancel(){
      this.reset()
      this.readOnly=true
      this.open=false
    },

    getValue(){
      let list = this.$refs.modelForm.getTableData()
      this.form.sysVersionItemDtoList  = list
    },
    submitForm(){
      //子表表单验证
      let contentTableCheck = this.$refs.modelForm.validateTable()
      // 触发表单验证
      let formCheck = this.$refs.form.validate()
      Promise.all([formCheck,contentTableCheck]).then((valid)=>{
        if(valid){
          if(!this.$refs.modelForm.getTableData().length>0){
            this.$message.error("请填写模块和问题")
            // return
          }
          this.getValue()
          if(this.form.id){
            editVersionApi(this.form).then(res=>{
              this.$modal.msgSuccess("修改成功");
              this.cancel()
              this.$emit('ok')
            })
          }else{
            addVersionApi(this.form).then(res=>{
              this.$modal.msgSuccess("新增成功");
              this.cancel()
              this.$emit('ok')
            })
          }
        }
      })
    },
  }

}
</script>

<style scoped>

</style>

可编辑表格:

<template>
  <el-form :model="form" ref="form" size="small" :rules="rules">
    <el-form-item v-if="isAdd">
      <el-button type="primary" icon="el-icon-plus" size="mini" @click="add" plain>新增</el-button>
    </el-form-item>
    <el-table :data="form.list" border>
      <el-table-column type="index" label="#" align="center"></el-table-column>
      <el-table-column v-if="!x.hidden" v-for="x in columns" :key="x.prop" :label="x.label" :prop="x.prop" v-bind="x.attr" :align="x.align" >
        <template slot-scope="{row, $index}">
          <t-text v-if="(!x.edit) && (cellIndex === undefined)" :row="{x, row}" />
          <template v-else>
            <t-text v-if="isDetail" :row="{x, row}" />
            <template v-else>
              <t-text v-if="cellIndex !== $index && isRowLimit" :row="{x, row}" />
              <template v-else>
                <t-input v-if="x.prop !== 'opt'" v-model="row[`${x.prop}`]" v-bind="componentAttrs(x, row, $index)" class="width100" />
                <template v-else>
<!--                <el-link type="primary" :underline="false" @click="save(row, $index)">保存</el-link>-->
                  <el-link type="primary" :underline="false" @click="del($index)">删除</el-link>
                  <el-link type="primary" :underline="false" @click="resetField($index)">重置</el-link>
                </template>
               </template>
            </template>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <el-form-item >
      <template v-if="isSubmit">
        <el-button type="primary" @click="submit">提交</el-button>
        <el-button @click="reset">重置</el-button>
      </template>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  props: {
    config: Object
  },
  components: {
    TInput: {
      functional: true,
      props: ['prop', 'rules', 'type', 'options', 'row', 'cb'],
      render: (h, {props: { prop, rules, type = 'default', options = [], row, cb = () => {} }, data, listeners: {input = () => {}}}) => {
        const children = {
          checkbox: h => h('el-checkbox-group', {props: {...data.attrs}, on: {input(v) {input(v)}}}, options.map(o => h('el-checkbox', {props: {...o, label: o.value, key: o.value}}, [o.label]))),
          select: h => h('el-select', {class: 'width100', props: {...data.attrs}, on: {change(v){input(v)}}}, options.map(o => h('el-option', {props: {...o, key: o.value}}))),
          date: h => h('el-date-picker', {props: {type: 'date', valueFormat: 'yyyy-MM-dd'}, ...data}),
          switch: h => h('el-switch', {props: {activeColor: '#13ce66'}, ...data}),
          mixInput: h => h('el-input', data, [h('el-button', {slot: 'append', props: {icon: 'el-icon-search'}, on: {click(){cb(row)}}})]),
          opt: () => '-',
          textArea:h=>h('el-input',{props: {type: 'textarea'},...data}),
          default: h => h('el-input', data),
        }

        return h('el-form-item', {props: {prop, rules}}, [children[type](h)])
      }
    },
    TText: {
      functional: true,
      props: ['row'],
      render: (h, {props: { row: { x, row } }}) => {
        if(!row[`${x.prop}`]) return h('span', '-')
        else if(x.format && typeof x.format == 'function') return h('span', x.format(row))
        else if(x.type === 'select') return h('dict-tag', {props: {options: x.options, value: row[`${x.prop}`]}})
        else return h('span', row[`${x.prop}`])
      }
    },
  },
  data(){
    const { columns = [], isAdd = false, isDetail = false, isSubmit = false,data = [],isRowLimit = false } = this.config || {}
  //[columns.reduce((r, c) => ({...r, [c.prop]: c.type == 'checkbox' ? [] : (c.type == 'switch' ? false : '')}), {isAdd: true})]
    return {
      cellIndex: undefined,
      form: {
        list: data
      },
      columns,
      rules: columns.reduce((r, c) => ({...r, [c.prop]: c.rules ? c.rules : { required: c.required == false ? false : true, message: c.label + '必填'}}), {}),
      isAdd,
      isDetail,
      isRowLimit,
      isSubmit,
    }
  },
  methods: {
    componentAttrs(item, row, idx){
      const {type, label} = item, attrs = Object.fromEntries(Object.entries(item).filter(n => !/^(prop|edit|label|attr|format)/.test(n[0]))),
        placeholder = (/^(select|el-date-picker)/.test(type) ? '请选择' : '请输入') + label
      Object.assign(attrs, {prop: `list.${idx}.${item.prop}`, rules: this.rules[item.prop]})
      return {...attrs, row, placeholder}
    },
    add(){
      const { columns = [] } = this.config || {}, obj = columns.reduce((r, c) => ({...r, [c.prop]: c.type == 'checkbox' ? [] : (c.type == 'switch' ? false : '')}), {isAdd: true})
      if (this.isRowLimit){
        this.cellIndex = this.form.list.length
      }


      this.form.list.push(obj)
    },
    save(row, idx){
      let ret = Object.keys(row).map(r => `list.${idx}.${r}`).filter(r => !/isAdd|opt/g.test(r)), { $refs: { form } } = this, num = 0

      form.validateField(ret, valid => {
        if(valid) {
          num++
        }
      })

      if(num == 0) this.$emit('submit', Object.fromEntries(Object.entries(row).filter(n => !/^(isAdd|opt)/.test(n[0]))))
    },
    del(idx){
      this.form.list.splice(idx, 1)
      this.$refs.form.fields.forEach(n => {
        if(n.prop.split(".")[1] == idx){
          n.clearValidate();
        }
      })
    },
    submit(){
      this.$refs.form.validate(valid => {
        if(valid){
          this.$emit('submit', this.form.list.map(m => Object.fromEntries(Object.entries(m).filter(n => !/^(isAdd|opt)/.test(n[0])))))
        }
      })
    },
    resetField(idx){
      this.$refs.form.fields.forEach(n => {
        if(n.prop.split(".")[1] == idx){
          n.resetField();
        }
      })
    },
    reset(){
      this.$refs.form.resetFields();
    },
    // 回显数据
    setData(form){
      form = (form && form.length > 0) ? form.map(n => this.columns.reduce((r, c) => ({...r, [c.prop]: n[c.prop] == false ? n[c.prop] : (n[c.prop] || (c.type == 'checkbox' ? [] : ''))}), {}))
        //: [this.columns.reduce((r, c) => ({...r, [c.prop]: c.type == 'checkbox' ? [] : (c.type == 'switch' ? false : '')}), {isAdd: true})]
        :[]
      Object.assign(this.form, {list: form})
      setTimeout(()=> {this.$refs.form.clearValidate()})
    },
    setConfig(config){
      this.config = config
    },

    // 校验table,失败返回errMap,成功返回null
    validateTable() {

      return this.$refs.form.validate()

    },
    /** 获取表格数据 */
    getTableData() {
      return this.form.list
    },
  }
}
</script>
<style scoped>
.width100{width: 100%;}
.el-link {margin-right: 10px;}
.el-form-item {
  margin-bottom: 30px;
}

</style>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值