前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用vuematerial编写通用列表组件

使用vuematerial编写通用列表组件

作者头像
4O4
发布2022-04-25 19:05:39
4830
发布2022-04-25 19:05:39
举报
文章被收录于专栏:404404

技术:vue + vuematerial + ts

声明父组件

代码语言:javascript
复制
<template>
  <div>
    <myTable
      :error="error"
      :showTable="showTable"
      :data="data"
      :operation="operation"
      :columns="columns"
    ></myTable>
		
		// 新增组件
    <addDialog :addValue="addValue" @add="add" @edit="edit"></addDialog>

		// 删除组件
		<deleteDialog @delete="deleteItem" @deletes="deleteItems"></deleteDialog>

		// 提示信息
    <md-snackbar md-position="center" :md-duration="2000" :md-active.sync="snackShow" md-persistent>
      <span>{{snackMsg}}</span>
      <md-button class="md-primary" @click="snackShow = false">关闭</md-button>
    </md-snackbar> 
  </div>
</template>

<script lang='ts'>
import { Vue, Watch, Component, Provide } from "vue-property-decorator";
import { personnelManageApi } from "@/utils/api.ts";
import { getInfo } from "@/utils/token";
import {
  default as myTable,
  Opera,
  Columns
} from "@/components/commen/table.vue";
import {
  deleteItem,
  addItem,
  getData,
  getDep,
  deletesItem
} from "@/utils/request";
import {
  default as addDialog,
  Filed
} from "@/components/addDialog/addDialog.vue";
import { required } from "vuelidate/lib/validators";
import deleteDialog from "@/components/delete/delete.vue";
import bus from "@/utils/eventBus";
import Axios from "axios";
import clone from "@/utils/clone";

// 注册钩子
Component.registerHooks([
  "beforeRouteEnter",
  "beforeRouteLeave",
  "beforeRouteUpdate" // for vue-router 2.2+
]);

@Component({
  components: { myTable, addDialog, deleteDialog }
})
export default class Department extends Vue {
  /* data */
  private operation: Opera = {
    modify: {
      active: true,
      title: "修改",
      type: "string"
    },
    delete: {
      active: true,
      title: "删除",
      type: "string"
    },
    add: {
      active: true,
      title: "添加",
      type: "string"
    },
    previous: {
      active: true,
      title: "查看",
      text: "上一级",
      type: "string"
    },
    next: {
      active: true,
      title: "查看",
      text: "下一级",
      type: "string"
    },
    child: {
      active: true,
      title: "添加子部门",
      type: "string"
    }
  };

  private columns: Columns = {
    id: {
      title: "序号",
      value: (r: any, i: any): any => {
        return i + 1;
      }
    },
    name: {
      title: "部门名称"
    },
    address: {
      title: "部门地址"
    },
    landline: {
      title: "座机"
    },
    phone: {
      title: "手机"
    },
    postcode: {
      title: "邮编"
    },
    email: {
      title: "邮箱"
    },
    fax: {
      title: "传真"
    }
  };

  private addValue: Filed[] = [
    {
      id: "name",
      title: "部门名称",
      type: "string",
      verification: [
        {
          name: "required",
          rule: required,
          errorMsg: "此项为必填项"
        }
      ]
    },
    {
      id: "address",
      title: "部门地址",
      type: "string",
      verification: [
        {
          name: "required",
          rule: required,
          errorMsg: "此项为必填项"
        }
      ]
    },
    {
      id: "duty",
      title: "部门负责人",
      type: "string"
    },
    {
      id: "landline",
      title: "座机",
      type: "string"
    },
    {
      id: "phone",
      title: "手机",
      type: "string",
      verification: [
        {
          name: "required",
          rule: required,
          errorMsg: "此项为必填项"
        }
      ]
    },
    {
      id: "postcode",
      title: "邮编",
      type: "string"
    },
    {
      id: "email",
      title: "电子邮箱",
      type: "string",
      verification: [
        {
          name: "required",
          rule: required,
          errorMsg: "此项为必填项"
        }
      ]
    },
    {
      id: "fax",
      title: "传真",
      type: "string"
    }
  ];

  // table 组件依赖的数据
  private data: any = [];
  
  // table 组件选中的数据
  private select: any = [];

  // snackbar 数据
  private snackMsg: string = "";
  private snackShow: boolean = false;
  
  // 是否显示错误提示组件
  private error: boolean = false;
  
  // 显示 table
  private showTable: boolean = false;
	
  // 路由导航守卫
  // beforeRouteUpdate(to: any, from: any, next: any) {
  //   this.ready();
  //   next();
  // }

  private onClickChip(i: any): void {
    this.$router.push({
      path: `/department/${this.paths.slice(0, i).join("/")}`
    });
  }

  @Watch("paths", { immediate: true, deep: true })
  onRouteChanged(val: string, oldVal: string) {
    console.log(val);
    this.ready();
  }

  get paths(): any {
    return (
      this.$route.params &&
      this.$route.params.id &&
      this.$route.params.id.split("/")
    );
  }

  /* methods */
  public deleteItem(i: any): void {
    deleteItem(`${personnelManageApi.delDep(i)}`, i, this);
  }

  public deleteItems(selected: any): void {
    deletesItem(`/deletes`, selected, this);
  }

  private add(addData: any) {
    addItem(`${personnelManageApi.addDep}`, addData, this);
  }

  private edit(data: any) {
    // editItem(personnelManageApi.editDevice(data.id), data, this);
  }

  // private child(id: any) {
  //   Axios.get(`${personnelManageApi.getChildDep(id)}`)
  //     .then((res: any) => {
  //       if (res.status === 200) {
  //         this.data = res.data.data;
  //       } else {
  //         this.snackMsg = "没有数据";
  //         this.snackShow = true;
  //       }
  //     })
  //     .catch((err: any) => {
  //       this.snackMsg = "没有错误";
  //       this.snackShow = true;
  //     });
  // }

  private beforeMount() {
    bus.$on("handleChild", (id: any) => {
      this.$router.push({ path: `${this.$route.fullPath}/${id}` });
    });
  }

  private getChildData(depId: any) {
    Axios.get(personnelManageApi.getChildDep(depId))
      .then((res: any) => {
        console.log(res);
        this.data = res.data.data;
      })
      .catch((err: any) => {
        console.log(err);
      });
  }

  private ready() {
    if (this.paths == undefined) {
      console.log(this.paths);
      let comId: number = getInfo().comId;
      getData(personnelManageApi.getAllDep(comId), this);
    } else {
      getDep(
        personnelManageApi.getChildDep(this.paths[this.paths.length - 1]),
        this
      );
      console.log(this.paths[this.paths.length - 1]);
    }
  }

  private created() {
    this.ready();
  }

  private beforeUpdate() {
    this.ready();
  }
}
</script>

<style lang="scss" scoped>
.md-table + .md-table {
  margin-top: 16px;
}
.md-dialog {
  width: 400px;
}
.inp {
  margin: 0 24px 24px;
  width: 352px;
}

.error-page {
  width: 100%;
  height: 70%;
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
  align-items: center;
  align-content: center;
}
</style>

声明 table 组件

代码语言:javascript
复制
<template>
  <div>
    <div v-if="error ? error : false" class="error-page">
      <aside class="error-wrapper">
        <md-empty-state
          class="md-accent"
          md-icon="alarm_off"
          md-label="加载失败"
          md-description="请刷新页面"
        >
          <div>
            <md-button class="md-dense md-primary" @click="reload">刷新页面</md-button>
            <md-button class="md-dense md-primary" @click="back">返回上级</md-button>
          </div>
        </md-empty-state>
      </aside>
    </div>

    <article v-else-if="!showTable">
      <h3>加载中...</h3>
    </article>

    <md-table v-model="data" @md-selected="onSelect" v-else>
      <md-table-toolbar slot="md-table-alternate-header" slot-scope="{ count }">
        <div class="md-toolbar-section-start">{{ getAlternateLabel(count) }}</div>

        <div class="md-toolbar-section-end">
          <md-button class="md-icon-button delsButton" @click.stop="dels()">
            <md-icon>delete</md-icon>
            <md-tooltip md-direction="bottom">删除选中</md-tooltip>
          </md-button>
        </div>
      </md-table-toolbar>
      <md-table-empty-state md-label="数据为空" :md-description="`当前没有数据`" id="empty">
        <md-button class="md-primary md-raised" @click="$store.commit('SHOW_DIALOG', true)">添加数据</md-button>
      </md-table-empty-state>

      <md-table-row
        slot="md-table-row"
        slot-scope="{ item, index }"
        md-selectable="multiple"
        md-auto-select
      >
        <!-- 循环列 -->
        <template v-for="(v, k) in columns">
          <md-table-cell
            v-if="!v.hide"
            :key="v.id"
            :md-numeric="v.type == 'numeric'"
            :md-label="v.title"
          >
            <p>{{v.value ? v.value(item,index) : item[k]}}</p>
          </md-table-cell>
        </template>

        <!-- 修改/删除 commen -->
        <md-table-cell
          style="text-align: right;"
          v-if="operation ? (operation.modify || operation.delete) : false"
        >
          <md-button
            class="md-icon-button editButton"
            v-if="operation.modify"
            @click.stop="edit(item)"
          >
            <md-icon>edit</md-icon>
            <md-tooltip md-direction="top" md-delay="300">编辑</md-tooltip>
          </md-button>

          <md-button
            class="md-icon-button delButton"
            v-if="operation.delete"
            @click.stop="del(item.id || item)"
          >
            <md-icon>delete</md-icon>
            <md-tooltip md-direction="top" md-delay="300">删除</md-tooltip>
          </md-button>
        </md-table-cell>

        <!-- 查看下级 department.vue -->
        <md-table-cell style="text-align: left;" v-if="operation.next ? true : false">
          <span
            class="child-view"
            v-if="operation.next"
            @click.stop="handleGetChild(item.id)"
          >{{ operation.next.text }}</span>
        </md-table-cell>

        <!-- 添加子部门 department.vue -->
        <md-table-cell
          :md-label="operation.child.title"
          style="text-align: left;"
          v-if="operation.child? true : false"
        >
          <md-button
            class="md-icon-button addButton"
            v-if="operation.child"
            @click.stop="handleAddItem"
          >
            <md-icon>add</md-icon>
          </md-button>
        </md-table-cell>

        <!-- 禁用用户 staff.vue -->
        <md-table-cell v-if="operation.disUser ? true : false" md-numeric>
          <md-button
            class="md-dense md-primary"
            @click.stop="userDisabled(item.id, item.disabled)"
          >{{ item.disabled ? '启用' : '禁用' }}</md-button>
        </md-table-cell>
      </md-table-row>
    </md-table>

    <!-- 新增按钮 commen -->
    <md-button
      v-if="operation.add ? true : false"
      class="md-fab md-fab-bottom-right"
      id="addButton"
      @click.stop="handleAddItem"
    >
      <md-icon>add</md-icon>
    </md-button>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Inject, Watch } from "vue-property-decorator";
import clone from "@/utils/clone";
import bus from "@/utils/eventBus";

interface Column {
  title: string;
  value?: fun;
  type?: string;
  hide?: boolean;
}

interface Multiple {
  required?: boolean;
  numeric?: boolean;
  email?: boolean;
}

interface fun {
  (item: any, index?: number): string | number | any;
}

//table 操作传值数据类型定义
interface Modify {
  active?: boolean;
  title?: string;
  type?: string;
}

interface Delete {
  active?: boolean;
  title?: string;
  type?: string;
}

interface Add {
  active?: boolean;
  title?: string;
  type?: string;
}

interface Child {
  active?: boolean;
  title?: string;
  type?: string;
}

interface Previous {
  active?: boolean;
  title?: string;
  text?: string;
  type?: string;
}

interface Next {
  active?: boolean;
  title?: string;
  text?: string;
  type?: string;
}

interface DisUser {
  active?: boolean;
  title?: string;
  text?: string;
  type?: string;
}

// table 传值类型定义
export interface Columns {
  [propName: string]: Column;
}

export interface Opera {
  modify?: Modify;
  delete?: Delete;
  add?: Add;
  next?: Next;
  child?: Child;
  disUser?: DisUser;
  previous?: Previous;
}

@Component
export default class Table extends Vue {
  @Prop() public operation!: Opera;
  @Prop() public data!: any;
  @Prop() public columns!: Columns;
  @Prop() public showTable!: boolean;
  @Prop() public error?: boolean;

  private show: boolean = false;
  private selected: Array<object> = [];

  private handleAddItem(): void {
    bus.$emit("showAdd");
  }

  // 部门 - 查询下级部门
  private handleGetChild(id: any): void {
    bus.$emit("handleChild", id);
  }

  private handleGetParent(id: any): void {
    bus.$emit("handleParent", id);
  }

  private onSelect(items: any): void {
    this.selected = items;
  }

  private getAlternateLabel(count: number) {
    return `当前选中 ${count} 项`;
  }

  /* 修改 */
  private edit(item: any): void {
    let items = clone(item);
    for (let i in this.columns) {
      if (this.columns[i].value && i !== "id") {
        items[i] = clone(this.columns[i].value!(items));
      }
    }
    bus.$emit("showEdit", items);
  }

  private userDisabled(id: string, status: boolean) {
    bus.$emit("disabled", id, status);
  }

  private del(item: string) {
    bus.$emit("showDelete", item);
  }

  private dels() {
    bus.$emit("showDeleteSelect", this.selected);
  }

  reload() {
    history.go(0);
  }

  back() {
    history.back();
  }
}
</script>

<style lang="scss" scoped>
.child-view:hover {
  color: #448aff;
  transition: 0.2s;
}
</style>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 声明父组件
  • 声明 table 组件
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档