<template>
  <div class="menu">
    <div class="menu-system">
      <span>{{ $t("TERMINAL") }}：</span>
      <a-select
        v-model="menuForm.clientType"
        class="d-inline-block"
        :placeholder="$t('PLACESELECT')"
        @change="moduleChange"
      >
        <a-select-option
          v-for="item in moduleList"
          :key="item.value"
          :value="item.value"
        >
          {{ $t(item.label) }}
        </a-select-option>
      </a-select>
    </div>
    <MomTable
      ref="MomTable"
      row-key="id"
      :row-selection="rowSelection"
      :init-call="false"
      :columns="columns"
      :data-source="menuList"
      :mega-extend="{
        rowIndex: false,
      }"
      :expand-icon-column-index="1"
      :action-buttons="tableAction"
      :pagination="false"
      :expanded-row-keys="expandedRowKeys"
      @expand="expandedOnClickIcon"
      @add="add"
      @edit="edit"
      @delete="del"
    >
      <template slot="toolbar">
        <a-button v-if="hasAuth('MENU_MANAGEMENT:ADD')" @click="addMenu">
          <a-icon type="plus" /> {{ $t("ADD") }}
        </a-button>
        <a-button
          :icon="isExpand ? 'up' : 'down'"
          class="btn__blue-4"
          @click="expandedAllRowsChange"
        >
          {{ isExpand ? $t("FOLD") : $t("UNFOLD") }}
        </a-button>
        <a-button
          v-if="hasAuth('MENU_MANAGEMENT:BATCH_DELETE')"
          type="danger"
          icon="delete"
          @click="handDelete"
        >
          {{ $t("BATCH_DELETE") }}
        </a-button>
        <!-- <a-button
          v-if="hasAuth('MENU_MANAGEMENT:EXPORT')"
          class="btn__green-1"
          icon="to-top"
          :disabled="!menuList.length"
          @click="handleExportExcel"
        >
          {{ $t("EXPORT") }}
        </a-button> -->
      </template>
      <span slot="menuName" slot-scope="text">{{ $t(text) }}</span>
      <span slot="icon" slot-scope="text">
        <i v-if="text" class="mr-7" />
        <Icon v-if="text" :type="text" :size="18" />
      </span>
    </MomTable>
    <drawer
      ref="drawer"
      :drawer="drawer"
      :title="title"
      :menu-form="menuForm"
      :menu-form-rules="menuFormRules"
      :menu-type-list="menuTypeList"
      :type-list="typeList"
      :menu-data="menuList"
      :module-list="moduleList"
      :menu-all-list="menuAllList"
      :code-rule="Number(code_rule)"
      :frame-type-list="menuFrameList"
      :open-type-list="menuFrameOpenList"
      :weight-list="weightList"
      :report-server-list="reportServerList"
      :cancel="cancel"
      :confirm="confirm"
      :is-frame-change="isFrameChange"
      :drawer-close="drawerClose"
      :selected="selected"
      @refresh-table="moduleChange"
      @saveMenuCodeI18n="saveMenuCodeI18n"
    />
  </div>
</template>
<script>
import { reduce as _reduce, uniqBy } from "lodash";
import { deleteLeafArray, getLevelMark } from "@mega-apps/utils";
import { Icon } from "@mega-design/ui-vue";
import ApiConstant from "@/api/ApiConstant";
import { loadGlobalLoading } from "@/plugins/axios";
import { exportExcel } from "@/utils";
import Drawer from "./drawer";

export default {
  components: { Drawer, Icon },
  data() {
    return {
      menuTypeList: [], // 菜单类型
      whetherCharList: [], // Y/N <==> 是否
      menuFrameList: [], // 菜单外链类型
      menuFrameOpenList: [], // 菜单外链打开类型
      weightList: [], // 权重
      reportServerList: [], // BI 报表服务器列表
      menuTab: [], // 菜单tab
      clientType: "", // 菜单tab key
      tableAction: [
        this.hasAuth("MENU_MANAGEMENT:ADD") && "add",
        this.hasAuth("MENU_MANAGEMENT:EDIT") && "edit",
        this.hasAuth("MENU_MANAGEMENT:DELETE") && "delete",
      ],
      expandedRowKeys: [],
      activeModule: "", // 选中的菜单
      menuList: [], // 表格数据
      // 表格列数据
      columns: [
        {
          dataIndex: "menuName",
          sorter: false,
          title: () => this.$t("MENU_NAME"),
          width: 260,
          dynamic: false,
          scopedSlots: { customRender: "menuName" },
        },
        {
          dataIndex: "icon",
          sorter: false,
          title: () => this.$t("ICON"),
          width: 110,
          scopedSlots: { customRender: "icon" },
        },
        {
          dataIndex: "menuTypeText",
          sorter: false,
          title: () => this.$t("TYPE"),
          width: 82,
        },
        {
          dataIndex: "seq",
          sorter: false,
          title: () => this.$t("SORT"),
          width: 82,
        },
        {
          dataIndex: "perms",
          sorter: false,
          title: () => this.$t("PERMISSION_ID"),
          width: 380,
        },
        {
          dataIndex: "isFrameText",
          sorter: false,
          title: () => this.$t("OUTSIDE"),
          width: 82,
        },
        {
          dataIndex: "openTypeText",
          sorter: false,
          title: () => this.$t("OPEN_TYPE"),
          width: 110,
        },
        {
          dataIndex: "frameTypeText",
          sorter: false,
          title: () => this.$t("FRAME_TYPE"),
          width: 110,
        },
        {
          dataIndex: "menuPath",
          sorter: false,
          title: () => this.$t("MENU_PATH"),
          minWidth: 260,
          ellipsis: true,
        },
        {
          dataIndex: "visibleText",
          sorter: false,
          title: () => this.$t("VISIBLE"),
          width: 82,
        },
        {
          dataIndex: "updateBy",
          sorter: false,
          title: () => this.$t("UPDATE_BY"),
          width: 120,
        },
        {
          dataIndex: "updateTime",
          sorter: false,
          title: () => this.$t("UPDATE_TIME"),
          width: 168,
        },
      ],
      menuListCode: [], // 表格数据的所有code
      // 下拉数据菜单
      moduleList: [],
      menuAllList: [],

      code_rule: "", // 编码规则
      // 是否展开
      isExpand: false,
      // 抽屉的显示隐藏
      drawer: false,
      title: "",
      id: "",
      menuForm: {
        name: "",
        clientType: "",
        menuCode: "",
        parentMenuCode: "",
        parentId: "",
        parentName: "",
        menuType: "MODULE",
        mobileAppFlag: "0",
        appHomeUrl: "",
        backgroundColor: "",
        isFrame: "N",
        openType: "",
        frameType: "",
        reportServerCode: "",
        icon: "",
        treeLevel: 0,
        seq: "",
        menuName: "",
        isRelated: "N", // 是否关联路由
        menuPath: "",
        component: "",
        perms: "",
        keepAlive: "0",
        menuTag: "",
        visible: "Y",
        weight: "",
      },
      typeList: [],
      selectedRowKeys: [],
      selectedRows: [],
    };
  },
  computed: {
    rowSelection() {
      return {
        selectedRowKeys: this.selectedRowKeys,
        onChange: (selectedRowKeys, selectedRows) => {
          this.selectedRowKeys = selectedRowKeys;
          if (this.selectedRowKeys.length) {
            this.selectedRows = uniqBy(this.selectedRows.concat(selectedRows));
          } else {
            this.selectedRows = selectedRows;
          }
        },
      };
    },
    // 默认权重
    defaultWeight() {
      return this.getAttrValue(this.weightList, "默认权重");
    },
    menuFormRules() {
      return {
        menuCode: [
          {
            required: true,
            message: this.$t("PLACEENTER"),
            trigger: "blur",
          },
        ],
        menuName: [
          {
            required: true,
            message: this.$t("PLACEENTER"),
            trigger: "blur",
          },
        ],
        menuPath: [
          {
            required: true,
            message: this.$t("PLACEENTER"),
            trigger: "blur",
          },
        ],
        component: [
          {
            required: true,
            message: this.$t("PLACEENTER"),
            trigger: "blur",
          },
        ],
        openType: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        frameType: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        reportServerCode: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        keepAlive: [
          {
            required: true,
            message: this.$t("PLACESELECT"),
            trigger: "change",
          },
        ],
        perms: [
          {
            max: 64,
            message: this.$t("PLACEENTER") + 64 + this.$t("LENGTH_TIP"),
            trigger: "blur",
          },
        ],
      };
    },
  },
  async created() {
    await this.queryDictData();
    await this.tableBeforeSearch();
    // 处理选中 第一个终端类型
    if (this.moduleList.length) {
      const { value } = this.moduleList[0];
      this.menuForm.clientType = value;
      this.moduleChange(value);
    }
  },
  methods: {
    // 查询数据字典
    queryDictData() {
      // 获取 权重
      this.$axios
        .get(`${ApiConstant.PREFIX_CORE}/api/sys/user/list-low-weight`)
        .then((res) => {
          this.weightList = res.data?.data;
        });

      // 类型
      this.getDictByCode("DIC:CORE:I18N_TYPE").then((res) => {
        this.typeList = res.data?.data;
      });
      this.$axios
        .get(
          `${ApiConstant.PREFIX_CORE}/api/report/report-server/list?enableFlag=Y`
        )
        .then((res) => {
          this.reportServerList = res.data.data;
        });
    },
    tableBeforeSearch() {
      return Promise.all([
        // 获取 菜单类型
        this.getDictByCode("DIC:CORE:SYS_MENU_TPYE"),
        // 获取 菜单外链类型
        this.getDictByCode("DIC:CORE:SYS_FRAME_TYPE"),
        // 获取 菜单外链打开类型
        this.getDictByCode("DIC:CORE:SYS_OUTER_LINK_OPEN_TYPE"),
        // 获取 Y/N <==> 是否
        this.getDictByCode("DIC:COMMON:WHETHER_CHAR"),
        // 终端
        this.getDictByCode("DIC:CORE:MENU_CLIENT"),
      ]).then(
        ([menuTypeRes, frameTypeRes, openTypeRes, whetherRes, clientRes]) => {
          this.menuTypeList = menuTypeRes.data?.data;
          this.menuFrameList = frameTypeRes.data?.data;
          this.menuFrameOpenList = openTypeRes.data?.data;
          this.whetherCharList = whetherRes.data?.data;
          this.moduleList = clientRes.data.data;
        }
      );
    },
    // 数据重构
    getDeptCodeList(list, parentIndex) {
      list.forEach((item, index) => {
        const data = item;
        const cIndex = index;
        data.value = item.id;
        data.title = this.$t(item.menuName);
        data.key = `${parentIndex}-${cIndex}`;
        if (item.children && item.children.length) {
          if (item.children[0].menuType === "BUTTON") {
            data.children = [];
          } else {
            this.getDeptCodeList(item.children, data.key);
          }
        }
      });
    },
    // 去掉自身
    deleteSelf(list, self) {
      const index = list.findIndex((item) => item.id === self.id);
      if (index >= 0) {
        list.splice(index, 1);
        return;
      }
      list.forEach((item) => {
        if (item.children && item.children.length) {
          this.deleteSelf(item.children, self);
        }
      });
    },
    // 模块切换，获取菜单
    moduleChange(moduleCode) {
      this.$axios
        .get(
          `${ApiConstant.PREFIX_CORE}/api/sys/menu/list-system-menu/${moduleCode}`
        )
        .then((res) => {
          deleteLeafArray(res.data.data, "children");
          this.menuListCode = getLevelMark(res.data.data, "children", "code");
          const fn = (data, arr = []) => {
            data.forEach((item) => {
              arr.push({
                ...item,
                menuTypeText: this.getAttrValue(
                  this.menuTypeList,
                  item.menuType
                ),
                isFrameText: this.getAttrValue(
                  this.whetherCharList,
                  item.isFrame
                ),
                openTypeText: this.getAttrValue(
                  this.menuFrameOpenList,
                  item.openType
                ),
                frameTypeText: this.getAttrValue(
                  this.menuFrameList,
                  item.frameType
                ),
                visibleText: this.getAttrValue(
                  this.whetherCharList,
                  item.visible
                ),
              });
              if (item.children && item.children.length) {
                // eslint-disable-next-line no-param-reassign
                arr[arr.length - 1].children = [];
                fn(item.children, arr[arr.length - 1].children);
              }
            });
            return arr;
          };
          this.menuList = fn(res.data.data);
          this.oldMenuAllList = fn(res.data.data);
          this.getDeptCodeList(this.oldMenuAllList, "0");
          if (this.expandedRowKeys.length === this.menuListCode.length) {
            this.isExpand = true;
          } else {
            this.isExpand = false;
          }
        });
    },
    // 展开/收起所有行
    expandedAllRowsChange() {
      loadGlobalLoading(1, this.$i18n);
      // setTimeout 不能修改为 $nextTick 原因请有兴趣的同学研究
      setTimeout(() => {
        if (this.expandedRowKeys.length === this.menuListCode.length) {
          this.expandedRowKeys = [];
          this.isExpand = false;
        } else {
          this.expandedRowKeys = [...this.menuListCode];
          this.isExpand = true;
        }
        loadGlobalLoading(0);
      }, 200);
    },
    expandedOnClickIcon(expanded, record) {
      if (expanded) {
        this.expandedRowKeys.push(record.code);
      } else {
        const index = this.expandedRowKeys.findIndex((e) => e === record.code);
        index !== -1 && this.expandedRowKeys.splice(index, 1);
      }
    },
    saveMenuCodeI18n(val) {
      this.$set(this.menuForm, "menuName", val);
    },
    // 选择图标
    selected(name) {
      this.menuForm.icon = name;
    },
    // 添加菜单
    addMenu() {
      this.drawer = true;
      this.menuForm = {
        name: "",
        clientType: this.menuForm.clientType,
        menuCode: "",
        parentMenuCode: "",
        parentId: "",
        parentName: "",
        menuType: "MODULE",
        mobileAppFlag: "0",
        appHomeUrl: "",
        backgroundColor: "",
        isFrame: "N",
        openType: "",
        frameType: "",
        reportServerCode: "",
        icon: "",
        treeLevel: 0,
        seq: "",
        menuName: "",
        isRelated: "N", // 是否关联路由
        menuPath: "",
        component: "",
        perms: "",
        keepAlive: "0",
        menuTag: "",
        visible: "Y",
        weight: "",
      };
      this.$set(this.menuForm, "parentName", "");
      this.$set(this.menuForm, "parentMenuCode", "");
      this.$set(this.menuForm, "parentId", "");
      this.$set(this.menuForm, "menuCode", "");
      this.$set(this.menuForm, "treeLevel", 0);
      this.$set(this.menuForm, "weight", this.defaultWeight);
      this.title = this.$t("ADD");
    },

    // 是否显示外链
    isFrameChange() {
      this.menuForm.openType = "";
      this.menuForm.frameType = "";
      this.menuForm.reportServerCode = "";
    },

    add(row) {
      this.drawer = true;
      this.title = this.$t("ADD");
      this.menuForm = {
        name: "",
        clientType: "",
        menuCode: "",
        parentMenuCode: "",
        parentId: "",
        parentName: "",
        menuType: "MODULE",
        mobileAppFlag: "0",
        appHomeUrl: "",
        backgroundColor: "",
        isFrame: "N",
        openType: "",
        frameType: "",
        reportServerCode: "",
        icon: "",
        treeLevel: 0,
        seq: "",
        menuName: "",
        isRelated: "N", // 是否关联路由
        menuPath: "",
        component: "",
        perms: "",
        keepAlive: "0",
        menuTag: "",
        visible: "Y",
        weight: "",
      };
      this.$nextTick(() => {
        this.menuForm.parentName = this.$t(row.menuName);
        this.menuForm.parentMenuCode = row.menuCode;
        this.menuForm.parentId = row.id;
        this.$set(this.menuForm, "treeLevel", row.treeLevel);
        this.$set(this.menuForm, "parentMenuCode", row.menuCode);
        this.$set(this.menuForm, "clientType", row.clientType);
        this.$set(this.menuForm, "menuCode", "");
        this.$set(this.menuForm, "menuName", "");
        this.$set(this.menuForm, "weight", this.defaultWeight);
        this.$set(this.menuForm, "parentId", row.id);
      });
    },
    // 编辑按钮点击事件
    edit(row) {
      this.drawer = true;
      this.title = this.$t("EDIT");
      // this.menuForm.parentName = this.$t(row.menuName)
      this.id = row.id;
      const list = JSON.parse(JSON.stringify(this.oldMenuAllList));
      this.deleteSelf(list, row);
      this.menuAllList = list;
      this.$axios
        .get(`${ApiConstant.PREFIX_CORE}/api/sys/menu/get-by-id/${row.id}`)
        .then((res) => {
          const { data } = res.data;
          this.menuForm = {
            ...data,
            mobileAppFlag: `${row.mobileAppFlag}`,
            clientType: row.clientType,
            name: `${data.menuName}(${data.dataValue})`,
            parentMenuCode: row.parentMenuCode,
            parentId: row.parentId,
            menuCode: row.menuCode,
            menuName: row.menuName,
            keepAlive: (data.keepAlive && `${data.keepAlive}`) || "0",
            menuTag: data.menuTag || "",
            weight: `${data.weight}` || this.defaultWeight,
          };
        });
    },
    del(row) {
      this.$confirm({
        title: this.$t("DELETE"),
        content: this.$t("DELETE_INFO"),
        okType: "warning",
        okText: this.$t("CONFIRM"),
        cancelText: this.$t("CANCEL"),
        centered: false,
        icon: "close-circle",
        onOk: () => {
          this.$axios
            .delete(`${ApiConstant.PREFIX_CORE}/api/sys/menu/${row.id}`)
            .then((res) => {
              this.$message.success(this.$t("DELETE_SUCCESS"));
              this.moduleChange(row.clientType);
            });
        },
      });
    },
    handDelete() {
      if (this.selectedRowKeys.length > 0) {
        this.$confirm({
          title: this.$t("DELETE"),
          content: this.$t("DELETE_INFO"),
          okType: "warning",
          okText: this.$t("CONFIRM"),
          cancelText: this.$t("CANCEL"),
          centered: false,
          icon: "close-circle",
          onOk: () => {
            this.$axios
              .delete(`${ApiConstant.PREFIX_CORE}/api/sys/menu/batch-delete`, {
                params: {
                  ids: this.selectedRowKeys.join(","),
                },
              })
              .then((res) => {
                this.$message.success(this.$t("DELETE_SUCCESS"));
                this.moduleChange(this.selectedRows[0]?.clientType);
              });
          },
        });
      } else {
        this.$message.error(this.$t("SELECT_ONE_DATA"));
      }
    },
    // 复制按钮点击事件
    handleCopy(row) {
      this.menuForm = { ...row };
      this.menuForm.id = "";
      this.menuForm.menuCode = "";
      delete this.menuForm.children;
      this.title = this.$t("COPY"); // 复制
      this.drawer = true;
    },
    // 导出菜单功能
    handleExportExcel() {
      this.$axios({
        url: `${ApiConstant.PREFIX_CORE}/api/sys/menu/export?clientType=${this.menuForm.clientType}`,
        method: "get",
        responseType: "blob",
      }).then((res) => {
        exportExcel(res.data, `${this.$t("MENU_MANAGEMENT")}.xls`);
      });
    },

    // eslint-disable-next-line
    async confirm() {
      // 表单验证
      const valid = await this.$refs.drawer.$refs.menuForm.validate();
      if (!valid) {
        return false;
      }
      let reqKeys = [];
      const defaultKeys = [
        "parentId",
        "id",
        "clientType",
        "menuType",
        "menuName",
        "seq",
        "weight",
      ];
      const frameKeys = [
        "isFrame",
        "frameType",
        "reportServerCode",
        "openType",
        "menuPath",
      ];
      const componentKeys = ["keepAlive", "component", "menuPath"];
      const { menuType } = this.menuForm;
      if (menuType === "MODULE") {
        reqKeys = [
          "perms",
          "visible",
          "mobileAppFlag",
          "appHomeUrl",
          "icon",
          "backgroundColor",
          "isRelated",
        ]
          .concat(defaultKeys)
          .concat(frameKeys);
      } else if (menuType === "CONTENTS") {
        reqKeys = ["perms", "icon", "visible", "isRelated"]
          .concat(defaultKeys)
          .concat(frameKeys);
      } else if (menuType === "MENU") {
        reqKeys = ["perms", "icon", "visible", "backgroundColor"]
          .concat(defaultKeys)
          .concat(frameKeys)
          .concat(componentKeys);
      } else if (menuType === "BUTTON") {
        reqKeys = ["perms", "isRelated", "menuTag"]
          .concat(defaultKeys)
          .concat(componentKeys);
      }
      const req = reqKeys.reduce((result, curr) => {
        // eslint-disable-next-line no-param-reassign
        result[curr] = this.menuForm[curr];
        return result;
      }, {});

      try {
        // ADD 或 EDIT 或 COPY
        if (this.title === this.$t("EDIT")) {
          await this.$axios.put(`${ApiConstant.PREFIX_CORE}/api/sys/menu`, {
            ...req,
            id: this.id,
          });
          this.$message.success(this.$t("EDIT_SUCCESS"));
        } else {
          await this.$axios.post(
            `${ApiConstant.PREFIX_CORE}/api/sys/menu`,
            req
          );
          this.$message.success(this.$t("ADD_SUCCESS"));
        }
        this.moduleChange(this.menuForm.clientType);
        this.drawer = false;
      } catch (_e) {}
    },
    cancel() {
      this.drawer = false;
    },
    // 关闭抽屉对话框时 重置表单信息
    drawerClose() {
      this.menuForm = {
        clientType: this.menuForm.clientType,
        menuCode: "",
        parentMenuCode: "",
        parentName: "",
        menuType: "MODULE",
        mobileAppFlag: "0",
        appHomeUrl: "",
        backgroundColor: "",
        isFrame: "N",
        openType: "",
        frameType: "",
        reportServerCode: "",
        keepAlive: "0",
        menuTag: "",
        icon: "",
        seq: "",
        menuName: "",
        parentId: "",
        isRelated: "N",
        menuPath: "",
        component: "",
        perms: "",
        visible: "Y",
        weight: this.defaultWeight,
      };
      this.drawer = false;
    },
  },
};
</script>
<style lang="less" scoped>
.menu {
  .menu-system {
    padding: 10px 20px 0;
    border-bottom: 10px solid #f0f2f5;
    .ant-select {
      margin-bottom: 10px;
      width: 260px;
    }
  }
}
</style>
