<template>
  <popup
    v-model="showDialog"
    :title="popupTitle"
    width="620px"
    :close-on-click-modal="false"
    :confirmLoading="isLoading"
    @confirm="handleSubmit"
  >
    <el-scrollbar height="500px" class="px-3 mx-[-12px]">
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="isLoading">
        <el-form-item label="菜单类型" prop="type" required>
          <el-radio-group v-model="formData.type">
            <el-radio :value="1">目录</el-radio>
            <el-radio :value="2">菜单</el-radio>
            <el-radio :value="3">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="上级菜单" prop="pid">
          <el-tree-select
            class="flex-1"
            v-model="formData.pid"
            :data="menuTreeData"
            clearable
            placeholder="请选择上级菜单"
            node-key="id"
            :props="{ label: 'name', children: 'children' }"
            check-strictly
            default-expand-all
          />
        </el-form-item>
        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入菜单名称" clearable />
        </el-form-item>
        <el-form-item label="菜单图标" prop="icon" v-if="formData.type != 3">
          <select-icon :type="formData.icon_type" :name="formData.icon" @select="handleSelectIcon" />
        </el-form-item>
        <el-form-item label="路由路径" icon="InfoFilled" prop="paths" v-if="formData.type != 3">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip
                content="访问的路由地址，如：`user`，如外网地址需内链访问则以`http(s)://`开头"
                placement="top"
              >
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              路由路径
            </span>
          </template>
          <el-input v-model="formData.paths" placeholder="请输入路由路径" clearable />
        </el-form-item>
        <el-form-item label="组件路径" prop="component" v-if="formData.type == 2">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="访问的组件路径，如：`system/user/index`，默认在`views`目录下" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              组件路径
            </span>
          </template>
          <el-autocomplete
            class="w-full"
            v-model="formData.component"
            :fetch-suggestions="querySearch"
            clearable
            placeholder="请输入组件路径"
          />
        </el-form-item>
        <el-form-item label="权限标识" prop="perms" v-if="formData.type != 1">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="将作为server端API验权使用，如`system.user/list`，请谨慎修改" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              权限标识
            </span>
          </template>
          <el-input v-model="formData.perms" placeholder="请输入权限标识" clearable />
        </el-form-item>
        <el-form-item label="路由参数" prop="params" v-if="formData.type == 2">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip
                content='访问路由的默认传递参数，如：`{"id": 1, "name": "admin"}`或`id=1&name=admin`'
                placement="top"
              >
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              路由参数
            </span>
          </template>
          <el-input v-model="formData.params" placeholder="请输入路由参数" clearable />
        </el-form-item>
        <el-form-item label="选中菜单" prop="selected" v-if="formData.type == 2">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="访问详情页面，编辑页面时，菜单高亮显示，如`/system/user`" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              选中菜单
            </span>
          </template>
          <el-input v-model="formData.selected" placeholder="请输入路由路径" clearable />
        </el-form-item>
        <el-form-item label="显示排序" prop="sort">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="数值越大越排前" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              显示排序
            </span>
          </template>
          <el-input-number v-model="formData.sort" :min="0" :max="9999" />
        </el-form-item>
        <el-form-item label="是否缓存" prop="is_cache" required v-if="formData.type == 2">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="选择是则会被`keep-alive`缓存" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              是否缓存
            </span>
          </template>
          <el-radio-group v-model="formData.is_cache">
            <el-radio :value="1">缓存</el-radio>
            <el-radio :value="0">不缓存</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="显示状态" prop="is_show" required v-if="formData.type != 3">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="选择隐藏则路由将不会出现在侧边栏，但仍然可以访问" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              显示状态
            </span>
          </template>
          <el-radio-group v-model="formData.is_show">
            <el-radio :value="1">显示</el-radio>
            <el-radio :value="0">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item class="mb-0" label="菜单状态" prop="is_disable" required v-if="formData.type != 3">
          <template #label>
            <span class="flex items-center gap-1">
              <el-tooltip content="选择停用则路由将不会出现在侧边栏，也不能被访问" placement="top">
                <el-icon class="cursor-pointer"><InfoFilled /></el-icon>
              </el-tooltip>
              菜单状态
            </span>
          </template>
          <el-radio-group v-model="formData.is_disable">
            <el-radio :value="0">正常</el-radio>
            <el-radio :value="1">停用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
    </el-scrollbar>
  </popup>
</template>

<script setup lang="ts">
import type { FormInstance } from 'element-plus'
import { menuAdd, menuDetail, menuEdit, menuOptions } from '@/api/permission/menu'
import { getModulesKey } from '@/router'
import { filterTree } from '@/utils/util'

// 定义组件事件
const emit = defineEmits<{
  (event: 'success'): void
}>()

// 表单引用
const formRef = shallowRef<FormInstance>()
// 模式：add=新增，edit=编辑
const mode = ref<'add' | 'edit'>('add')
// 加载状态
const isLoading = ref(false)
// 是否显示弹窗
const showDialog = ref(false)
// 组件选项列表
const componentsOptions = ref<string[]>(getModulesKey())
// 菜单树选项
const menuTreeData = ref<any[]>([])
// 初始表单数据
const initialFormData = {
  id: '',
  pid: 0, // 父级ID
  type: 1, // 菜单类型：1=目录，2=菜单，3=按钮
  name: '', // 菜单名称
  icon_type: 1, // 图标类型：1=element图标，2=本地图标
  icon: '', // 图标名称
  paths: '', // 路由路径
  component: '', // 前端组件路径
  perms: '', // 权限标识
  params: '', // 路由参数
  selected: '', // 选中路径，用于菜单高亮
  sort: 0, // 排序号，数值越大越排前
  is_cache: 1, // 是否缓存：0=否，1=是
  is_show: 1, // 是否显示：0=否，1=是
  is_disable: 0 // 是否禁用：0=否，1=是
}
// 表单数据
const formData = reactive<Record<string, any>>({ ...initialFormData })
// 表单验证规则
const formRules = reactive({
  pid: [
    {
      required: true,
      message: '请选择上级菜单',
      trigger: ['blur', 'change']
    }
  ],
  name: [
    {
      required: true,
      message: '请输入菜单名称',
      trigger: ['blur', 'change']
    }
  ],
  paths: [
    {
      required: true,
      message: '请输入路由地址',
      trigger: ['blur', 'change']
    }
  ],
  component: [
    {
      required: true,
      message: '请输入组件地址',
      trigger: ['blur', 'change']
    }
  ]
})
// 弹窗标题
const popupTitle = computed(() => {
  return mode.value === 'edit' ? '编辑菜单' : '新增菜单'
})

// 打开弹窗
const open = (type: 'add' | 'edit' = 'add') => {
  getOptions()
  mode.value = type
  showDialog.value = true
}
// 设置表单数据
const setFormData = async (row?: Record<string, any>) => {
  isLoading.value = true
  resetForm()
  if (row) {
    if (row.id) {
      const data = await menuDetail({ id: row.id })
      Object.keys(formData).forEach((key: string) => {
        if (data[key] != undefined) formData[key] = data[key]
      })
    } else {
      Object.keys(formData).forEach((key: string) => {
        if (row[key] != undefined) formData[key] = row[key]
      })
    }
  }
  isLoading.value = false
}
// 表单重置
const resetForm = () => {
  Object.assign(formData, initialFormData)
  formRef.value?.resetFields()
}
// 查询组件路径建议
const querySearch = (queryString: string, cb: (results: { value: string }[]) => void) => {
  const results = queryString
    ? componentsOptions.value.filter((item) => item.toLowerCase().includes(queryString.toLowerCase()))
    : componentsOptions.value
  cb(results.map((item) => ({ value: item })))
}
// 获取菜单列表
const getOptions = async () => {
  menuTreeData.value = []
  const data = await menuOptions()
  const menuTree = { id: 0, name: '主类目', children: filterTree(data, { type: 3 }) }
  menuTreeData.value.push(menuTree)
}
// 选择图标
const handleSelectIcon = (icon: string, type: number) => {
  formData.icon = icon
  formData.icon_type = type
}
// 提交表单
const handleSubmit = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      isLoading.value = true
      const submitEvent = mode.value === 'edit' ? menuEdit : menuAdd
      submitEvent(formData)
        .then(() => {
          isLoading.value = false
          showDialog.value = false
          ElMessage.success('操作成功')
          emit('success')
        })
        .catch(() => {
          isLoading.value = false
        })
    }
  })
}

defineExpose({
  open,
  setFormData
})
</script>
