<template>
  <!-- 对话框组件 -->
  <el-dialog
    v-model="visible"
  :title="!dataForm.id ? '新增' : '修改'"
  :close-on-click-modal="false"
  >
  <!-- 表单组件 -->
  <el-form
    ref="dataFormRef"
  :model="dataForm"
  :rules="dataRule"
  label-width="80px"
  @keyup.enter="onSubmit()"
  >
  <!-- 类型选择项 -->
  <el-form-item
    label="类型"
    prop="type"
  >
    <el-radio-group v-model="dataForm.type">
      <el-radio
        v-for="(type, index) in dataForm.typeList"
        :key="index"
        :label="index"
      >
        {{ type }}
      </el-radio>
    </el-radio-group>
  </el-form-item>

  <!-- 动态标签，根据类型改变 -->
  <el-form-item
    :label="dataForm.typeList[dataForm.type] + '名称'"
    prop="name"
  >
    <el-input
      v-model="dataForm.name"
      :placeholder="dataForm.typeList[dataForm.type] + '名称'"
    />
  </el-form-item>

  <!-- 上级菜单选择 -->
  <el-form-item label="上级菜单">
    <el-cascader
      v-model="selectedMenu"
      expand-trigger="hover"
      :options="menuList"
      :props="menuListTreeProps"
      change-on-select
      :clearable="true"
      @change="handleSelectMenuChange"
    />
  </el-form-item>

  <!-- 菜单路由输入（仅当类型为1时显示） -->
  <el-form-item
    v-if="dataForm.type === 1"
    label="菜单路由"
    prop="url"
  >
    <el-input
      v-model="dataForm.url"
      placeholder="菜单路由"
    />
  </el-form-item>

  <!-- 授权标识输入（除类型0外显示） -->
  <el-form-item
    v-if="dataForm.type !== 0"
    label="授权标识"
    prop="perms"
  >
    <el-input
      v-model="dataForm.perms"
      placeholder="多个用逗号分隔, 如: user:list,user:create"
    />
  </el-form-item>

  <!-- 排序号输入（除类型2外显示） -->
  <el-form-item
    v-if="dataForm.type !== 2"
    label="排序号"
    prop="orderNum"
  >
    <el-input-number
      v-model="dataForm.orderNum"
      controls-position="right"
      :min="0"
      label="排序号"
    />
  </el-form-item>

  <!-- 菜单图标选择（除类型2外显示） -->
  <el-form-item
    v-if="dataForm.type !== 2"
    label="菜单图标"
    prop="icon"
  >
    <el-row>
      <el-col :span="22">
        <el-input
          ref="iconInputRef"
          v-model="dataForm.icon"
          :virtual-ref="iconListPopoverRef"
          placeholder="菜单图标名称"
          clearable
        />
        <el-popover
          ref="iconListPopoverRef"
          style="width: 390px"
          :virtual-ref="iconInputRef"
          placement="bottom-start"
          trigger="click"
          :popper-style="iconPopoverClass"
          virtual-triggering
        >
          <el-button
            v-for="(item, index) in iconList"
            :key="index"
            style="padding: 8px; margin: 8px 0 0 8px"
            :class="{ 'is-active': item === dataForm.icon }"
            @click="iconActiveHandle(item)"
          >
            <svg-icon
              :icon-class="`${item}`"
            />
          </el-button>
        </el-popover>
      </el-col>
      <el-col
        :span="2"
        class="icon-list__tips"
      >
        <el-tooltip
          placement="top"
          effect="light"
        >
          <template #content>
            <div>全站推荐使用SVG Sprite, 详细请参考:icons/index.js 描述</div>
          </template>
          <i class="el-icon-warning" />
        </el-tooltip>
      </el-col>
    </el-row>
  </el-form-item>
  </el-form>

  <!-- 对话框底部操作按钮 -->
  <template #footer>
      <span class="dialog-footer">
        <el-button @click="visible = false">取消</el-button> <!-- 关闭对话框 -->
        <el-button type="primary" @click="onSubmit()">确定</el-button> <!-- 提交表单 -->
      </span>
  </template>
  </el-dialog>
</template>

<script setup>
import { treeDataTranslate, idList } from '@/utils'
import { ElMessage } from 'element-plus'
import { ref, reactive, computed, onMounted, nextTick, defineEmits, defineExpose } from 'vue'

// 定义父组件事件
const emit = defineEmits(['refreshDataList'])

// 引用图标输入框和弹出框
const iconInputRef = ref(null)
const iconListPopoverRef = ref(null)

// 计算图标弹出框样式
const iconPopoverClass = computed(() => ({
  width: '396px'
}))

// 控制对话框显示状态的响应式变量
const visible = ref(false)

// 表单数据模型，使用reactive定义以保证其响应性
const dataForm = reactive({
  id: 0,
  type: 1,
  typeList: ['目录', '菜单', '按钮'],
  name: '',
  parentId: 0,
  url: '',
  perms: '',
  orderNum: 0,
  icon: '',
  iconList: []
})

// 上级菜单列表和选中值
const menuList = ref([])
const selectedMenu = ref([])

// 上级菜单树形结构属性配置
const menuListTreeProps = {
  value: 'menuId',
  label: 'name',
  checkStrictly: true
}

// URL验证规则
const validateUrl = (rule, value, callback) => {
  if (dataForm.type === 1 && !/\S/.test(value)) {
    callback(new Error('菜单URL不能为空'))
  } else {
    callback()
  }
}

// 表单验证规则
const dataRule = ref({
  name: [
    { required: true, message: '菜单名称不能为空', trigger: 'blur' },
    { pattern: /\s\S+|S+\s|\S/, message: '请输入正确的菜单名称', trigger: 'blur' }
  ],
  url: [
    { validator: validateUrl, trigger: 'blur' }
  ]
})

// 加载图标方法
onMounted(() => {
  onLoadIcons()
})

/**
 * 加载图标
 */
const onLoadIcons = () => {
  const icons = import.meta.glob('@/icons/svg/*.svg')
  for (const icon in icons) {
    const iconName = icon.split('/src/icons/svg/')[1].split('.svg')[0]
    dataForm.iconList.push(iconName)
  }
}

// 获取表单实例引用
const dataFormRef = ref(null)

/**
 * 初始化方法，接收id作为参数
 * @param id 菜单项ID
 */
const init = (id) => {
  dataForm.id = id || 0 // 设置当前编辑的菜单项ID
  http({
    url: http.adornUrl('/sys/menu/list'),
    method: 'get',
    params: http.adornParams()
  })
    .then(({ data }) => {
      menuList.value = treeDataTranslate(data, 'menuId') // 将菜单列表转换成树形结构
    })
    .then(() => {
      visible.value = true // 打开对话框
      nextTick(() => {
        dataFormRef.value?.resetFields() // 重置表单
      })
    })
    .then(() => {
      if (dataForm.id) {
        // 如果有id，则获取该菜单项的详情
        http({
          url: http.adornUrl(`/sys/menu/info/${dataForm.id}`),
          method: 'get',
          params: http.adornParams()
        }).then(({ data }) => {
          // 填充表单数据
          dataForm.id = data.menuId
          dataForm.type = data.type
          dataForm.name = data.name
          dataForm.parentId = data.parentId
          dataForm.url = data.url
          dataForm.perms = data.perms
          dataForm.orderNum = data.orderNum
          dataForm.icon = data.icon
          selectedMenu.value = idList(menuList.value, data.parentId, 'menuId', 'children').reverse()
        })
      } else {
        selectedMenu.value = [] // 清空上级菜单选择
      }
    })
}
defineExpose({ init })

/**
 * 上级菜单选择变化处理
 * @param val 选中的菜单路径
 */
const handleSelectMenuChange = (val) => {
  dataForm.parentId = val[val.length - 1] // 设置parentId为最后一个选中的菜单ID
}

/**
 * 图标选中处理
 * @param iconName 选中的图标名称
 */
const iconActiveHandle = (iconName) => {
  dataForm.icon = iconName // 设置选中的图标名称
}

/**
 * 表单提交
 */
const onSubmit = Debounce(() => {
  // 验证表单
  dataFormRef.value?.validate((valid) => {
    if (valid) {
      // 发送HTTP请求保存菜单信息
      http({
        url: http.adornUrl('/sys/menu'),
        method: dataForm.id ? 'put' : 'post', // 判断是更新还是创建
        data: http.adornData({
          menuId: dataForm.id || undefined,
          type: dataForm.type,
          name: dataForm.name,
          parentId: dataForm.parentId,
          url: dataForm.url,
          perms: dataForm.perms,
          orderNum: dataForm.orderNum,
          icon: dataForm.icon
        })
      })
        .then(() => {
          // 成功提示
          ElMessage({
            message: '操作成功',
            type: 'success',
            duration: 1500,
            onClose: () => {
              visible.value = false // 关闭对话框
              emit('refreshDataList') // 触发刷新数据列表事件
            }
          })
        })
    }
  })
})
</script>
