使用vuematerial编写通用列表组件

2022-04-25 19:05:39 浏览数 (1)

技术: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>

0 人点赞