<template>
  <el-dialog class="dialog-with-menu" :visible="dialogVisible" :destroy-on-close="false" @close="handleClose"
    :close-on-click-modal="configs.clickModalToClose ?? true">
    <!-- title  -->
    <div slot="title" class="dialog-title">
      <h1 class="">
        {{ detailMode ? "查看详情" : dataForm.id ? "编辑" : "新增" }}
      </h1>
    </div>

    <div class="dialog-body__inner relative">
      <!-- v-if="dataForm.id && !detailMode && /属性|详情/.test(activeMenu) && $hasPermission()" -->
      <el-button v-if="configs.allowAdd ?? (dataForm.id && !detailMode && /属性|详情|参数/.test(activeMenu))" plain
        type="primary" size="small" class="at-right-top" style="margin-bottom: 16px" @click="handleAddParam()">+
        添加</el-button>
      <template v-if="dataForm.id && !detailMode && /附件/.test(activeMenu)">
        <el-upload style="position: absolute; width: 100%; height: 0" name="files" :action="uploadUrl"
          :show-file-list="false" :headers="uploadHeaders" :on-success="handleUploadSuccess"
          :before-upload="handleUploadCheck">
          <el-button plain type="primary" size="small" class="at-right-top" style=""> <i class="el-icon-upload"></i> 上传
          </el-button>
        </el-upload>
      </template>

      <!-- menu  -->
      <el-tabs v-model="activeMenu" type="card" @tab-click="handleTabClick">
        <!-- <el-tab-pane v-for="(tab, index) in configs.menu" :key="index" :label="tab.name" :name="tab.name"> -->
        <el-tab-pane v-for="(tab, index) in actualMenus" :key="index" :name="tab.name">
          <span class="slot" slot="label">
            <i :class="{
              'el-icon-edit': tab.key === 'info',
              'el-icon-s-data': tab.key === 'attr',
              'el-icon-folder-opened': tab.key === 'attachment',
            }"></i>
            {{ tab.name }}
          </span>

          <!-- 表单标签页 -->
          <div v-if="tab.key === 'info'">
            <!-- form  -->
            <el-form ref="dataForm" :model="dataForm" v-loading="loadingStatus">
              <el-row v-for="(row, rowIndex) in configs.form.rows" :key="'row_' + rowIndex" :gutter="20">
                <el-col v-for="(col, colIndex) in row" :key="colIndex" :span="24 / row.length">
                  <el-form-item :label="col.label" :prop="col.prop" :rules="col.rules || null"
                    v-show="!col.forceDisabled || (col.forceDisabled && dataForm.id)">
                    <div v-if="col.forceDisabled && dataForm.id" class="force-disabled">
                      <el-tag :key="col.key" :type="col.type">{{ dataForm[col.prop] || "-" }}</el-tag>
                    </div>
                    <el-input v-if="col.input" v-model="dataForm[col.prop]" clearable
                      :disabled="disableCondition(col.prop)" v-bind="col.elparams" />
                    <el-cascader v-if="col.cascader" v-model="dataForm[col.prop]" :options="col.options"
                      :disabled="detailMode" v-bind="col.elparams"></el-cascader>
                    <el-select v-if="col.select" v-model="dataForm[col.prop]" clearable
                      :disabled="disableCondition(col.prop)" v-bind="col.elparams"
                      @change="handleSelectChange(col, $event)">
                      <el-option v-for="(opt, optIdx) in col.options" :key="'option_' + optIdx" :label="opt.label"
                        :value="opt.value" />
                    </el-select>
                    <el-switch v-if="col.switch" v-model="dataForm[col.prop]" :active-value="1" :inactive-value="0"
                      @change="handleSwitchChange" :disabled="disableCondition(col.prop)" />
                    <el-input v-if="col.textarea" type="textarea" v-model="dataForm[col.prop]"
                      :disabled="disableCondition(col.prop)" v-bind="col.elparams" />
                    <quillEditor v-if="col.richInput" ref="quill-editor" v-model="dataForm[col.prop]"
                      :options="col.quillConfig ?? defaultQuillConfig" style="margin-top: 42px"
                      :disabled="disableCondition(col.prop)" />

                    <div class="" v-if="col.component" style="margin: 42px 0 0">
                      <!-- 下面这个 component 几乎是为 富文本 quill 定制的了... TODO：后续可能会根据业务需求创建新的版本  -->
                      <component :is="col.component" :key="'component_' + col.prop"
                        @update:modelValue="handleComponentModelUpdate(col.prop, $event)" :modelValue="dataForm[col.prop]"
                        :mode="detailMode ? 'detail' : dataForm.id ? 'edit' : 'create'" />
                    </div>
                    <!-- add more...  -->
                  </el-form-item>
                </el-col>
              </el-row>
            </el-form>
          </div>

          <!-- 表格标签页 -->
          <div v-if="dataForm.id && tab.key === 'attr'" key="attr-list">
            <BaseListTable :table-config="null" :column-config="filteredTableProps" :table-data="subList"
              @operate-event="handleTableRowOperate" :current-page="attrPage" :current-size="attrSize"
              :refresh-layout-key="Math.random()" v-loading="loadingStatus" />
            <!-- paginator  -->
            <el-pagination class="" style="text-align: left" background @size-change="handleSizeChange"
              @current-change="handlePageChange" :current-page.sync="attrPage" :page-sizes="[5, 10, 20]"
              :page-size="attrSize" :total="attrTotal" layout="total, sizes, prev, next"></el-pagination>
          </div>

          <!-- 附件标签页 -->
          <div v-if="dataForm.id && tab.key === 'attachment'" key="attachment">
            <div class="upload-tips" style="font-size: 0.8em; margin-bottom: 12px">文件大小不要超过 2MB</div>
            <!-- 附件列表 -->
            <div class="" v-loading="loadingStatus">
              <ul class="file-list">
                <li v-for="(file, index) in fileList" :key="index">
                  <span class="file-name">{{ file.name }}</span>
                  <span class="file-operations">
                    <span class="file-icon preview" @click="handleFileClick('view', file)">
                      <i class="el-icon-view" style="cursor: pointer"></i>
                    </span>
                    <span class="file-icon download" @click="handleFileClick('download', file)">
                      <i class="el-icon-download" style="color: #0b58ff; cursor: pointer"></i>
                    </span>
                    <span class="file-icon delete" @click="handleFileClick('delete', file)">
                      <i class="el-icon-delete" style="color: red; cursor: pointer"></i>
                    </span>
                  </span>
                </li>
              </ul>
            </div>
            <!-- img preview dialog  -->
            <el-dialog key="image-preview-dialog" class="image-preview-dialog" :visible.sync="imgPreviewDialogVisible"
              :append-to-body="true">
              <div class="img-container">
                <img width="100%" :src="currentImgUrl" alt="" />
              </div>
            </el-dialog>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>

    <!-- sub dialog  -->
    <small-dialog :append-to-body="true" v-if="showSubDialog" ref="subDialog" :url="urls.subase"
      :configs="configs.subDialog" :related-id="dataForm.id" @refreshDataList="getSubList"></small-dialog>

    <!-- footer  -->
    <div slot="footer">
      <template v-for="(operate, index) in configs.form.operations">
        <el-button v-if="showButton(operate)" :key="'operation_' + index" :type="operate.type"
          @click="handleBtnClick(operate)"
          :loading="(operate.name === 'add' || operate.name === 'update') && btnLoading">{{ operate.label }}</el-button>
      </template>
      <el-button @click="handleBtnClick({ name: 'cancel' })">取消</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { pick as __pick } from "@/utils/filters";
import SmallDialog from "@/components/SmallDialog.vue";
import BaseListTable from "@/components/BaseListTable.vue";
import Cookies from "js-cookie";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";

import { quillEditor } from "vue-quill-editor";

function reConstructTreeData(listObj) {
  const entry = [];
  Object.keys(listObj).map((key) => {
    const currentNode = listObj[key];
    currentNode.label = currentNode.name;
    currentNode.value = currentNode.id;
    if (currentNode.parentId === "0") {
      entry.push(listObj[key]);
      return; // return { label: currentNode.name, value: currentNode.id, children: currentNode.children ?? [] };
    }
    const parentNode = listObj[currentNode.parentId];
    if (!parentNode.children) {
      parentNode.children = [];
    }
    parentNode.children.push(currentNode);
  });
  return entry;
}

export default {
  name: "DialogWithMenu",
  components: { SmallDialog, BaseListTable, quillEditor },
  props: {
    configs: {
      type: Object,
      default: () => ({}),
    },
    dialogVisible: {
      type: Boolean,
      default: false,
    },
  },
  inject: ["urls"],
  data() {
    const dataForm = {};
    const autoDisabledQueue = [];
    const watingToRefreshQueue = [];
    const cached = {}

    this.configs.form.rows.forEach((row) => {
      row.forEach((col) => {
        if (col.upload) dataForm[col.prop] = col.default ?? [];
        else dataForm[col.prop] = col.default ?? null;

        if (col.autoDisabled) autoDisabledQueue.push(col.prop);
        if (!!col.refreshOptionsAfterConfirm) watingToRefreshQueue.push(col);

        if (col.fetchData)
          col.fetchData().then(({ data: res }) => {
            console.log("[Fetch Data]", "list" in res.data, res.data, res.data.list);
            if (res.code === 0) {
              if (col.cacheFetchedData) {
                // cache fetched data
                cached[col.prop] = 'list' in res.data ? res.data.list : (Array.isArray(res.data) ? res.data : [])
              }

              if (!col.options || !col.options.length) {
                this.$set(
                  col,
                  "options",
                  "list" in res.data
                    ? res.data.list.map((i) => ({
                      label: col.optionLabel ? i[col.optionLabel] : i.name,
                      value: col.optionValue ? i[col.optionValue] : i.id,
                    }))
                    : res.data.map((i) => ({
                      label: col.optionLabel ? i[col.optionLabel] : i.name,
                      value: col.optionValue ? i[col.optionValue] : i.id,
                    }))
                );
              }
              // col.options = res.data.list;
              else if (col.options.length) {
                "list" in res.data ? res.data.list.unshift(...col.options) : res.data.unshift(...col.options);
                this.$set(
                  col,
                  "options",
                  "list" in res.data
                    ? res.data.list.map((i) => ({
                      label: col.optionLabel ? i[col.optionLabel] : i.name,
                      value: col.optionValue ? i[col.optionValue] : i.id,
                    }))
                    : res.data.map((i) => ({
                      label: col.optionLabel ? i[col.optionLabel] : i.name,
                      value: col.optionValue ? i[col.optionValue] : i.id,
                    }))
                );
              }
            } else {
              col.options.splice(0);
            }
            // dataForm[col.prop] = col.default ?? null; // not perfect!
          });
        else if (col.fetchTreeData) {
          // 获取设备类型时触发的，用于前端构建属性结构，约定，parentId 为0时是顶级节点
          col.fetchTreeData().then(({ data: res }) => {
            console.log("[Fetch Tree Data]", res.data);
            if (res.code === 0) {
              // 先把数据先重构成一个对象
              const obj = {};

              if ("list" in res.data) {
                res.data.list.map((item) => {
                  obj[item.id] = item;
                });
              } else if (Array.isArray(res.data)) {
                res.data.map((item) => {
                  obj[item.id] = item;
                });
              }
              // 再过滤这个对象
              let filteredList = reConstructTreeData(obj);
              console.log("** filteredList **", filteredList);
              // 最后设置 options
              this.$set(col, "options", filteredList);
            } else {
              col.options.splice(0);
              this.$message.error(res.msg);
            }
          });
        }
      });
    });

    return {
      // configs,
      btnLoading: false,
      loadingStatus: false,
      activeMenu: this.configs.menu[0].name,
      dataForm,
      detailMode: false,
      autoDisabledQueue,
      watingToRefreshQueue,
      cached,
      showBaseDialog: false,
      baseDialogConfig: null,
      subList: [],
      showSubDialog: false,
      disableXXX: false,
      defaultQuillConfig: {
        modules: {
          toolbar: [
            [{ font: [] }],
            [{ size: ["small", false, "large", "huge"] }], // custom dropdown
            ["bold", "italic", "underline", "strike"], // toggled buttons
            [{ color: [] }, { background: [] }], // dropdown with defaults from theme
            ["blockquote", "code-block"],
            [{ header: 1 }, { header: 2 }], // custom button values
            [{ list: "ordered" }, { list: "bullet" }],
            // [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
            [{ indent: "-1" }, { indent: "+1" }], // outdent/indent
            // [{ 'direction': 'rtl' }],                         // text direction
            // [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
            // [{ 'align': [] }],
            // ['clean']                                         // remove formatting button
          ],
        },
        theme: "snow",
        readOnly: false,
        placeholder: "在这里输入描述信息...",
        scrollingContainer: null,
      },
      attrPage: 1,
      attrSize: 10,
      attrTotal: 0,
      fileList: [],
      imgPreviewDialogVisible: false,
      currentImgUrl: "",
    };
  },
  mounted() {
    this.configs.form.rows.forEach((row) => {
      row.forEach((col) => {
        if (col.changeReflects && typeof col.changeReflects === 'object' && 'fromKey' in col.changeReflects && 'toProp' in col.changeReflects) {
          this.$watch(
            () => this.dataForm[col.prop],
            val => {
              if (val && (col.prop in this.cached)) {
                console.log("here changeReflects", col.prop, col.changeReflects.toProp, this.cached[col.prop])
                if (typeof col.changeReflects.fromKey === 'string') {
                  this.dataForm[col.changeReflects.toProp] = this.cached[col.prop].find(item => item.id === val)?.[col.changeReflects.fromKey]
                } else if (Array.isArray(col.changeReflects.fromKey) && col.changeReflects.delimiter) {
                  const foundItem = this.dataForm[col.changeReflects.toProp] = this.cached[col.prop].find(item => item.id === val)
                  if (foundItem) {
                    const values = col.changeReflects.fromKey.map(key => foundItem[key])
                    this.dataForm[col.changeReflects.toProp] = values.join(col.changeReflects.delimiter)
                  } else {
                    this.dataForm[col.changeReflects.toProp] = col.changeReflects.delimiter
                    console.log("[DialogWithMenu] mounted() 没找到对应数据")
                  }
                }
              }
            },
            {
              immediate: false
            }
          )
        }
      });
    });
  },

  watch: {
    dialogVisible: function (val) {
      if (!!val) {
        this.attrPage = 1
        this.attrSize = 10
      }
    },
  },
  computed: {
    actualMenus() {
      return this.configs.menu.filter((m) => {
        if (m.onlyEditMode && !this.dataForm.id) {
          return false;
        }
        return true;
      });
    },
    filteredTableProps() {
      return this.detailMode ? this.configs.table.props.filter((v) => v.prop !== "operations") : this.configs.table.props;
    },
    uploadHeaders() {
      return {
        token: Cookies.get("token") || "",
      };
    },
    uploadUrl() {
      return this.configs.menu.find((item) => item.key === "attachment")?.actionUrl || "#";
    },
  },

  methods: {
    disableCondition(prop) {
      return this.detailMode || (this.disableXXX && this.autoDisabledQueue.indexOf(prop) !== -1);
    },
    /** utitilities */
    showButton(operate) {
      const notDetailMode = !this.detailMode;
      const showAlways = operate.showAlways ?? false;
      const editMode = operate.showOnEdit && this.dataForm.id;
      const addMode = !operate.showOnEdit && !this.dataForm.id;
      const permission = operate.permission ? this.$hasPermission(operate.permission) : true;
      const currentMenuKey = this.configs.menu.find((item) => item.name === this.activeMenu)?.key;
      return notDetailMode && (showAlways || ((editMode || addMode) && permission)) && currentMenuKey === "info";
    },

    resetForm(excludeId = false, immediate = false) {
      setTimeout(
        () => {
          Object.keys(this.dataForm).forEach((key) => {
            if (excludeId && key === "id") return;
            if ("files" in this.dataForm) this.dataForm.files = [];
            if ("fileIds" in this.dataForm) this.dataForm.fileIds = [];
            else this.dataForm[key] = null;
            if (Array.isArray(this.fileList)) {
              this.fileList = [];
            }
          });
          this.activeMenu = this.configs.menu[0].name;
          this.$refs.dataForm[0].clearValidate();
        },
        immediate ? 0 : 200
      );
    },

    updateOptions() {
      return new Promise((resolve, reject) => {
        if (this.watingToRefreshQueue.length) {
          this.watingToRefreshQueue.forEach((opt) => {
            console.log("[刷新数据, ", opt, "]");
            if ("fetchData" in opt) {
              opt.fetchData(this.dataForm.id ? this.dataForm.id : -1).then(({ data: res }) => {
                if (res.code === 0) {
                  this.$set(
                    opt,
                    "options",
                    "list" in res.data
                      ? res.data.list.map((i) => ({ label: i.code, value: i.id }))
                      : res.data.map((i) => ({ label: i.code, value: i.id }))
                  );

                  resolve({ done: true });
                } else {
                  this.$message({
                    message: `${res.code}: ${res.msg}`,
                    type: "error",
                    duration: 1500,
                  });

                  resolve({ done: false });
                }
              });
            }
          });
        } else resolve(null);
      });
    },

    /** init **/
    init(id, detailMode, menu) {
      // this.dialogVisible = true;
      if (this.$refs.dataForm && this.$refs.dataForm.length) {
        // 当不是首次渲染dialog的时候，一开始就清空验证信息，本组件的循环里只有一个 dataForm 所以只用取 [0] 即可
        this.$refs.dataForm[0].clearValidate();
      }
      console.log("[dialog] DialogWithHead init():", id, detailMode);

      this.detailMode = detailMode ?? false;
      this.$nextTick(() => {
        this.dataForm.id = id || null;
        if (this.dataForm.id) {
          // 如果是编辑
          this.loadingStatus = true;
          // 提前获取属性列表
          this.getSubList();
          // 获取详情
          this.updateOptions().then((result) => {
            if (result === null || (typeof result === "object" && result.done)) {
              this.$http.get(this.urls.base + `/${this.dataForm.id}`).then(({ data: res }) => {
                if (res && res.code === 0) {
                  const dataFormKeys = Object.keys(this.dataForm);
                  this.dataForm = __pick(res.data, dataFormKeys);
                  if ("files" in res.data) {
                    console.log("[DialogWithMenu] fileList===>", res.data.files, this.fileList);
                    /** 返回的文件列表 */
                    this.fileList = res.data.files
                      ? res.data.files.map((file) => ({
                        id: file.id,
                        name: file.fileUrl.split("/").pop(),
                        url: file.fileUrl,
                        typeCode: file.typeCode,
                      }))
                      : [];
                  }
                }
                this.loadingStatus = false;
                // 是否要跳转到附件页
                if (menu && menu.key) {
                  this.activeMenu = this.configs.menu.find((item) => item.key === menu.key)?.name;
                }
              });
            }
          });
        } else {
          // 如果不是编辑
          this.updateOptions();
        }
      });
    },

    /** handlers */
    handleFileClick(type, file) {
      switch (type) {
        case "view": {
          // 加载图片
          this.$http
            .get("/pms/attachment/downloadFile", {
              params: {
                attachmentId: file.id,
                type: 0, // 0 预览，1 下载
              },
              responseType: "blob",
            })
            .then(({ data: res }) => {
              console.log("preivew", res);
              if (/image/i.test(res.type)) {
                // 显示图片
                this.currentImgUrl = URL.createObjectURL(res);
                this.imgPreviewDialogVisible = true;
              } else if (/pdf/i.test(res.type)) {
                // 预览pdf 
                let a = document.createElement('a')
                a.setAttribute('target', '_blank')
                a.href = URL.createObjectURL(res)
                a.click()
                console.log('before remove a ', a)
                a.remove()
                console.log('removed a ', a)
              } else {
                this.$message({
                  message: "非图片和PDF文件请下载后预览",
                  type: "error",
                  duration: 1500,
                });
              }
            });
          break;
        }

        case "download": {
          // 下载图片
          this.$http
            .get("/pms/attachment/downloadFile", {
              params: {
                attachmentId: file.id,
                type: 1, // 0 预览，1 下载
              },
              responseType: "blob",
            })
            .then(({ data: res }) => {
              const blob = new Blob([res]);

              /** 通知 */
              this.$notify({
                title: "成功",
                message: "开始下载",
                type: "success",
                duration: 1200,
              });

              if ("download" in document.createElement("a")) {
                const alink = document.createElement("a");
                alink.download = file.name;
                alink.style.display = "none";
                alink.target = "_blank";
                alink.href = URL.createObjectURL(blob);
                document.body.appendChild(alink);
                alink.click();
                URL.revokeObjectURL(alink.href);
                document.body.removeChild(alink);
              } else {
                navigator.msSaveBlob(blob, fileName);
              }
            });

          break;
        }

        case "delete": {
          return this.$confirm(`确定删除图片: ${file.name}`, "提示", {
            confirmButtonText: "确认",
            cancelButtonText: "我再想想",
            type: "warning",
          })
            .then(() => {
              this.loadingStatus = true;
              const newFilelist = this.fileList.filter((f) => f.id !== file.id);
              this.updateRemoteFiles(newFilelist).then((msg) => {
                if (msg && msg === "success") {
                  this.fileList = newFilelist;
                  this.loadingStatus = false;
                  /** 通知 */
                  this.$notify({
                    title: "成功",
                    message: "已删除",
                    type: "success",
                    duration: 1200,
                  });
                }
              });
            })
            .catch((err) => { });
        }
      }
    },

    handleUploadSuccess(response, file, fileList) {
      console.log("[DialogWithMenu] uploadedFileList", response, file, fileList);

      if (response.code === 0) {
        const uploadedFile = response.data[0];
        const fileItem = {
          id: uploadedFile.id,
          name: uploadedFile.fileUrl.split("/").pop(),
          url: uploadedFile.fileUrl,
          typeCode: file.typeCode,
        };

        this.loadingStatus = true;
        this.updateRemoteFiles([...this.fileList, fileItem]).then((msg) => {
          if (msg && msg === "success") {
            this.fileList.push(fileItem);
            this.loadingStatus = false;
            /** 通知 */
            this.$notify({
              title: "成功",
              message: "上传成功",
              type: "success",
              duration: 1200,
            });
          }
        });
      }
    },

    updateRemoteFiles(filelist) {
      return this.$http
        .put("/pms/product", {
          id: "id" in this.dataForm ? this.dataForm.id : "DEFAULT_ID",
          fileIds: filelist.map((f) => f.id),
        })
        .then(({ data: res }) => {
          if (res.code === 0) return "success";
        });
    },

    handleUploadCheck(file) {
      console.log("[before upload]", file);
      const LIMIT = 2 * 1024 * 1024; // bytes
      if (file.size > LIMIT) {
        this.$message({
          message: "文件大小不能超过 2MB",
          type: "error",
          duration: 1500,
        });
        return false;
      } else return true;
    },

    handleComponentModelUpdate(propName, { subject, payload: { data } }) {
      this.dataForm[propName] = JSON.stringify(data);
      console.log("[DialogJustForm] handleComponentModelUpdate", this.dataForm[propName]);
    },
    handleSelectChange(col, eventValue) {
      console.log("[dialog] select change: ", col, eventValue);
    },
    handleSwitchChange(val) {
      console.log("[dialog] switch change: ", val, this.dataForm);
    },
    handleBtnClick(payload) {
      console.log("btn click payload: ", payload);

      if ("name" in payload) {
        switch (payload.name) {
          case "cancel":
            this.handleClose();
            break;
          case "reset":
            this.resetForm(true, true); // true means exclude id
            break;
          case "add":
          case "update": {
            this.$refs.dataForm[0].validate((passed, result) => {
              if (passed) {
                // 如果通过验证
                this.btnLoading = true
                this.loadingStatus = true;
                const method = payload.name === "add" ? "POST" : "PUT";

                // 判断是否有附件选项
                const hasAttachment = !!this.configs.menu.find((item) => item.key === "attachment");
                if (hasAttachment) {
                  const fileIds = this.fileList.map((item) => item.id);
                  this.$set(this.dataForm, "fileIds", fileIds);
                }

                // 加载额外需要的 id
                let extraIds = {};
                if (this.configs.extraIds && typeof this.configs.extraIds === "object") {
                  // 如果配置里，有 extraIds 选项
                  Object.entries(this.configs.extraIds).forEach(([key, value]) => {
                    extraIds[key] = value;
                  });
                }

                // 实际发送请求
                this.btnLoading = true
                this.$http({
                  url: this.urls.base,
                  method,
                  data: {
                    ...extraIds,
                    ...this.dataForm,
                  },
                })
                  .then(({ data: res }) => {
                    this.btnLoading = false
                    this.loadingStatus = false;
                    console.log("[add&update] res is: ", res);
                    if (res.code === 0) {
                      this.$message.success(payload.name === "add" ? "添加成功" : "更新成功");
                      this.$emit("refreshDataList");

                      // 如果 watingToRefreshQueue 队列里有数据
                      // if (this.watingToRefreshQueue.length) {
                      //   // 刷新队列
                      //   this.watingToRefreshQueue.forEach((opt) => {
                      //     console.log("[刷新数据, ", opt, "]");
                      //     if ("fetchData" in opt) {
                      //       opt.fetchData().then(({ data: res }) => {
                      //         if (res.code === 0) {
                      //           this.$set(
                      //             opt,
                      //             "options",
                      //             "list" in res.data
                      //               ? res.data.list.map((i) => ({ label: i.name, value: i.id }))
                      //               : res.data.map((i) => ({ label: i.name, value: i.id }))
                      //           );
                      //         }
                      //       });
                      //     }
                      //   });
                      // }

                      this.handleClose();
                    } else {
                      this.$message({
                        message: `${res.code}: ${res.msg}`,
                        type: "error",
                        duration: 2000,
                      });
                      if (this.btnLoading) this.btnLoading = false
                    }
                  })
                  .catch((errMsg) => {
                    this.$message.error("参数错误：" + errMsg);
                    if (this.loadingStatus) this.loadingStatus = false;
                    if (this.btnLoading) this.btnLoading = false
                  });
              } else {
                this.$message.error("请核查字段信息");
              }
            });
          }
        }
      }
    },
    handleTabClick(payload) {
      //   console.log("tab click payload: ", this.activeMenu);
      //   if (this.activeMenu === this.configs.menu[1].name) {
      //     // 获取数据
      //     this.getSubList();
      //   }
    },

    handlePageChange(val) {
      this.getSubList(val, this.attrSize);
    },
    handleSizeChange(val) {
      this.attrPage = 1;
      this.attrSize = val
      this.getSubList(1, val);
    },

    getSubList(page, size) {
      const params = {};
      params.page = page ?? this.attrPage;
      params.limit = size ?? this.attrSize;

      const requiredParams = this.configs.table.extraParams;
      if (requiredParams) {
        if (Array.isArray(requiredParams)) {
          requiredParams.forEach((str) => {
            if (/id/i.test(str)) {
              params[str] = this.dataForm.id;
            } else {
              params[str] = "";
            }
          });
        } else if (typeof requiredParams === "string") {
          // 如果需要额外参数，一般肯定需要
          params[this.configs.table.extraParams] = this.dataForm.id;
          // 此时 dataForm.id 一定是存在的
        }
      }
      this.$http.get(this.urls.subpage, { params }).then(({ data: res }) => {
        console.log("[DialogWithMenu] getSubList:", res);
        if (res.code === 0 && res.data?.list) {
          // 有数据
          this.subList = res.data.list;
          this.attrTotal = res.data.total;
        } else {
          this.subList.splice(0);
          this.attrTotal = 0;
        }
      });
    },

    handleAddParam(id) {
      this.showSubDialog = true;
      this.$nextTick(() => {
        this.$refs.subDialog.init(id ?? null);
      });
    },

    handleClose() {
      this.resetForm();
      this.$emit("update:dialogVisible", false);
    },

    /** 列表handlers */
    handleAddItem() {
      // console.log('[dialog] handleAddItem ot list...');
      this.showBaseDialog = true;
      this.$nextTick(() => {
        console.log("[sub-dialog] ", this.$refs["sub-dialog"].init());
      });
    },
    handleTableRowOperate({ type, data }) {
      console.log("handleTableRowOperate", type, data);

      switch (type) {
        case "delete": {
          // 确认是否删除
          console.log('delete....', data)
          const itemName = typeof data === 'object' ? (data.attrName || data.name || data.material || data.id) : data
          return this.$confirm(`是否删除条目: ${itemName}`, "提示", {
            confirmButtonText: "确认",
            cancelButtonText: "我再想想",
            type: "warning",
          })
            .then(() => {
              // this.$http.delete(this.urls.base + `/${data}`).then((res) => {
              this.$http({
                url: this.urls.subase,
                method: "DELETE",
                data: [`${data.id}`],
              }).then(({ data: res }) => {
                if (res.code === 0) {
                  this.$message.success({
                    message: "删除成功!",
                    duration: 1000,
                    onClose: () => {
                      this.getSubList(1, 20);
                    },
                  });
                }
              });
            })
            .catch((err) => { });
        }
        case "edit": {
          this.handleAddParam(data); /** data is ==> id */
          break;
        }
        // case 'view-detail-action':
        // 	this.openDialog(data, true);
        // 	break;
      }
    },
  },
};
</script>

<style scoped>
.el-menu {
  margin: 16px 0 !important;
}

.el-menu.el-menu--horizontal {
  border: none !important;
  /* background: #0f02 !important; */
}

/* .el-menu--horizontal > .el-menu-item.is-active { */
/* border-bottom-color: #0b58ff; */
/* } */

.dialog-with-menu>>>.el-dialog__body {
  /* padding-top: 16px !important;
  padding-bottom: 16px !important; */
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

.el-select,
.el-cascader {
  width: 100% !important;
}

.dialog-with-menu>>>.el-dialog__header {
  padding: 10px 20px 10px;
  /* background: linear-gradient(to bottom, rgba(0, 0, 0, 0.25), white); */
}

.relative {
  position: relative;
}

.at-right-top {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 10000;
}

ul.file-list,
ul.file-list>li {
  padding: 0;
  margin: 0;
  list-style: none;
}

.file-list {
  max-height: 20vh;
  overflow-y: auto;
  margin-top: 12px;
  /* width: 240px; */
  display: flex;
  flex-direction: column;
}

ul.file-list>li {
  border-radius: 4px;
  background-color: #edededd2;
  padding: 8px;
  margin-bottom: 2px;
  display: flex;
  justify-content: space-between;
}

ul.file-list>li:hover {
  background-color: #ededed;
}

.file-operations {
  display: flex;
}

.file-icon {
  margin-right: 8px;
  font-size: 16px;
  line-height: 1;
  display: flex;
  place-content: center;
  width: 16px;
  height: 16px;
}

/* .image-preview-dialog {
} */

.force-disabled {
  margin-top: 42px;
}
</style>
