<script setup lang="ts">
import AForm from '@/components/AForm/index.vue'
import MenuTreeSelect from '@/views/components/MenuTreeSelect/index.vue'
import { FormConfigType } from '@/components/AForm/type'
import { ToolbarConfigType } from '@/components/AToolbar/type'
import { ColumnConfigType } from '@/components/ATable/type'
import { StrAnyObj, StrAnyObjArr } from '@/typings'
import { useHandleData } from '@/utils/useHandleData'
import { addApi, deleteApi, editApi, getDetailApi, getTreeApi } from '@/api/system/menu'
import { getCodeListApi } from '@/api/system/permission'

const queryRef = ref<InstanceType<typeof AForm>>()
const formRef = ref<InstanceType<typeof AForm>>()
const parentIdRef = ref<InstanceType<typeof MenuTreeSelect>>()

const showQuery = ref<boolean>(true)
const expandAll = ref<boolean>(true)

const queryData = ref<StrAnyObj>({})
const tableData = ref<StrAnyObjArr>([])
const formData = ref<StrAnyObj>({
  type: 1,
  sort: 1,
  isHide: 0,
  isKeepAlive: 0,
  isLink: 0,
  isFull: 0,
  status: 1
})

const dialogTitle = ref<string>('')
const dialogVisible = ref<boolean>(false)

const queryConfig: FormConfigType[] = [
  {
    type: 'input',
    prop: 'title',
    label: '菜单名称'
  },
  {
    type: 'input',
    prop: 'name',
    label: '路由名称'
  },
  {
    type: 'select',
    prop: 'status',
    label: '状态',
    dict: 'enable_disable'
  }
]

const toolbarConfig: ToolbarConfigType[] = [
  {
    common: 'search',
    click() {
      queryData.value.pageNum = 1
      getTree()
    }
  },
  {
    common: 'reset',
    click() {
      queryRef.value?.resetFields()
      getTree()
    }
  },
  {
    common: 'add',
    permissions: 'sysMenu:add',
    click() {
      dialogVisible.value = true
      dialogTitle.value = '新增'
      nextTick(() => {
        formData.value.parentId = '0'
        parentIdRef.value?.load({ selectType: [1] })
      })
    }
  },
  {
    text: '展开/折叠',
    icon: 'sort',
    type: 'info',
    click: () => {
      expandAll.value = !expandAll.value
    }
  }
]

const columnConfig: ColumnConfigType[] = [
  {
    prop: 'title',
    label: '菜单名称'
  },
  {
    prop: 'name',
    label: '路由名称'
  },
  {
    prop: 'path',
    label: '组件路径'
  },
  {
    prop: 'status',
    label: '状态',
    dict: 'enable_disable'
  },
  {
    prop: 'sort',
    label: '排序'
  },
  {
    width: 250,
    handleConfig: [
      {
        common: 'add',
        permissions: 'sysMenu:add',
        if(row: StrAnyObj) {
          return row.type != 3
        },
        click(row) {
          dialogVisible.value = true
          dialogTitle.value = '新增'
          nextTick(() => {
            formData.value.parentId = row.id
            switch (row.type) {
              case 1:
                formData.value.type = 2
                parentIdRef.value?.load({ selectType: [1] })
                break
              case 2:
                formData.value.type = 3
                parentIdRef.value?.load({ selectType: [1, 2], disabledType: [1] })
                break
            }
          })
        }
      },
      {
        common: 'update',
        permissions: 'sysMenu:edit',
        click(row) {
          dialogVisible.value = true
          dialogTitle.value = '编辑'
          getDetailApi({ id: row.id }).then((resp: StrAnyObj) => {
            formData.value = resp
            nextTick(() => {
              switch (resp.type) {
                case 1:
                case 2:
                  parentIdRef.value?.load({ selectType: [1], filterNodeKey: row.id })
                  break
                case 3:
                  parentIdRef.value?.load({ selectType: [1, 2], disabledType: [1] })
              }
            })
          })
        }
      },
      {
        common: 'delete',
        permissions: 'sysMenu:delete',
        click(row) {
          handleRemove(row.id)
        }
      }
    ]
  }
]

const formConfig: FormConfigType[] = [
  {
    type: 'radio',
    prop: 'type',
    label: '菜单类型',
    option: [
      {
        key: 1,
        label: '目录'
      },
      {
        key: 2,
        label: '菜单'
      },
      {
        key: 3,
        label: '按钮'
      }
    ],
    span: 24,
    disabled() {
      return formData.value.id != undefined
    },
    change(type) {
      formData.value.parentId = undefined
      formData.value.title = undefined
      formData.value.name = undefined
      formData.value.path = undefined
      formData.value.isHide = 0
      formData.value.isKeepAlive = 0
      formData.value.isLink = 0
      formData.value.isFull = 0
      formData.value.status = 1
      formData.value.sort = 1
      formData.value.perms = undefined
      formData.value.icon = undefined
      formData.value.remark = undefined
      formRef.value?.clearValidate()
      switch (type) {
        case 1:
        case 2:
          parentIdRef.value?.load({ selectType: [1] })
          break
        case 3:
          parentIdRef.value?.load({ selectType: [1, 2], disabledType: [1] })
      }
    },
    rule: [{ required: true, message: '菜单类型不能为空', trigger: 'blur' }]
  },
  {
    type: 'slot',
    prop: 'parentId',
    label: '上级菜单',
    rule: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }]
  },
  {
    type: 'input',
    prop: 'title',
    label: '菜单名称',
    rule: [{ required: true, message: '菜单名称不能为空', trigger: 'blur' }]
  },
  {
    type: 'slot',
    prop: 'icon',
    label: '菜单图标',
    if() {
      return formData.value.type == 1 || formData.value.type == 2
    },
    rule: [{ required: true, message: '菜单图标不能为空', trigger: 'blur' }]
  },
  {
    type: 'inputNumber',
    prop: 'sort',
    label: '排序',
    min: 0,
    precision: 0,
    rule: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
  },
  {
    type: 'radio',
    prop: 'isHide',
    label: '是否隐藏',
    dict: 'yes_no',
    if() {
      return formData.value.type == 2
    },
    rule: [{ required: true, message: '是否隐藏不能为空', trigger: 'blur' }]
  },
  {
    type: 'radio',
    prop: 'isKeepAlive',
    label: '是否缓存',
    dict: 'yes_no',
    if() {
      return formData.value.type == 2
    },
    rule: [{ required: true, message: '是否缓存不能为空', trigger: 'blur' }]
  },
  {
    type: 'radio',
    prop: 'isLink',
    label: '是否外链',
    dict: 'yes_no',
    if() {
      return formData.value.type == 2
    },
    rule: [{ required: true, message: '是否外链不能为空', trigger: 'blur' }]
  },
  {
    type: 'radio',
    prop: 'isFull',
    label: '是否全屏',
    dict: 'yes_no',
    if() {
      return formData.value.type == 2
    },
    rule: [{ required: true, message: '是否全屏不能为空', trigger: 'blur' }]
  },
  {
    type: 'input',
    prop: 'name',
    label: '路由名称',
    span: 24,
    if() {
      return formData.value.type == 2
    },
    rule: [{ required: true, message: '路由名称不能为空', trigger: 'blur' }]
  },
  {
    type: 'slot',
    prop: 'path',
    label: '组件路径',
    span: 24,
    if() {
      return formData.value.type == 1 || formData.value.type == 2
    },
    rule: [{ required: true, message: '组件路径不能为空', trigger: 'blur' }]
  },
  {
    type: 'select',
    prop: 'permArray',
    label: '权限标识',
    multiple: true,
    span: 24,
    async option() {
      const codeList = await getCodeListApi()
      return codeList.map((item) => {
        return {
          key: item,
          label: item
        }
      })
    },
    if() {
      return (formData.value.type == 2 || formData.value.type == 3) && formData.value.isLink == 0
    }
  },
  {
    type: 'radio',
    prop: 'status',
    label: '菜单状态',
    dict: 'enable_disable',
    rule: [{ required: true, message: '菜单状态不能为空', trigger: 'blur' }]
  }
]

onMounted(() => {
  getTree()
})

function getTree() {
  getTreeApi(queryData.value).then((resp) => {
    tableData.value = resp
  })
}

function formSubmit() {
  formRef.value?.validate(() => {
    if (formData.value.id) {
      editApi(formData.value).then(() => {
        dialogVisible.value = false
        ElMessage.success('修改成功')
        getTree()
      })
    } else {
      addApi(formData.value).then(() => {
        dialogVisible.value = false
        ElMessage.success('新增成功')
        getTree()
      })
    }
  })
}

function formClosed() {
  formRef.value?.resetFields()
}

function handleRemove(id: string) {
  useHandleData('是否确认删除？', () => {
    deleteApi({ id }).then(() => {
      ElMessage.success('删除成功')
      getTree()
    })
  })
}

function toggleRowExpansion(obj: any, expand: boolean) {
  if (expand) {
    if (obj.type === 2) {
      return false
    }
  }
  return expand
}
</script>

<template>
  <div>
    <el-card v-if="showQuery">
      <a-form ref="queryRef" v-model="queryData" :config="queryConfig" :span="6"></a-form>
    </el-card>

    <a-table
      :data="tableData"
      :toolbar-config="toolbarConfig"
      :column-config="columnConfig"
      :expand-all="expandAll"
      :toggle-row-expansion="toggleRowExpansion"
      v-model:showQuery="showQuery"
    >
    </a-table>

    <a-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      @submit="formSubmit"
      @closed="formClosed"
      width="700px"
    >
      <a-form ref="formRef" v-model="formData" :config="formConfig" :span="12">
        <template #parentId>
          <menu-tree-select
            ref="parentIdRef"
            v-model="formData.parentId"
            :select-type="formData.type"
          />
        </template>
        <template #icon>
          <svg-select v-model="formData.icon" />
        </template>
        <template #path>
          <el-input v-model="formData.path" clearable placeholder="请输入路由地址">
            <template #prepend v-if="formData.isLink == 0"> src/views </template>
            <template #append v-if="formData.isLink == 0 && formData.type === 2">
              /index.vue
            </template>
          </el-input>
        </template>
      </a-form>
    </a-dialog>
  </div>
</template>
