<template>
  <!-- 地区管理模块 -->
  <div class="mod-sys-area">
    <!-- 地区名称输入框，用于过滤树状结构中的节点 -->
    <el-input
      v-model="areaName"
      class="area-search-input"
      placeholder="地区关键词"
    />
    <!-- 新增按钮，点击时触发新增或更新操作 -->
    <el-button
      type="primary"
      class="area-add-btn"
      @click="onAddOrUpdate()"
    >
      新增
    </el-button>

    <!-- 树形控件，展示地区层级结构 -->
    <el-tree
      ref="tree2Ref"
    :data="areaTreeData"
    node-key="areaId"
    :filter-node-method="filterNode"
    :props="props"
    :expand-on-click-node="false"
    >
    <!-- 自定义节点内容模板 -->
    <template #default="{ node, data }">
      <span class="addr-name">{{ node.label }}</span> <!-- 显示地区名称 -->
      <span>
          <!-- 修改按钮，点击时触发修改操作 -->
          <el-button
            type="text"
            icon="el-icon-edit"
            @click="() => update(node, data)"
          >
            修改
          </el-button>
        <!-- 删除按钮，点击时触发删除操作 -->
          <el-button
            type="text"
            icon="el-icon-delete"
            @click="() => remove(node, data)"
          >
            删除
          </el-button>
        </span>
    </template>
    </el-tree>

    <!-- 添加或更新对话框组件 -->
    <add-or-update
      v-if="addOrUpdateVisible"
    ref="addOrUpdateRef"
    @refresh-data-list="getDataList"
    @close="addOrUpdateVisible=false"
    />
  </div>
</template>

<script setup>
import { ElMessage, ElMessageBox } from 'element-plus'
import AddOrUpdate from './add-or-update.vue' // 引入添加或更新对话框组件
import { treeDataTranslate } from '@/utils'   // 引入树数据转换工具函数
import { ref, watch, onMounted, reactive, nextTick } from 'vue'

// 地区名称过滤器绑定的响应式变量
const areaName = ref('')

// 树形控件节点属性映射配置
const props = {
  id: 'areaId',
  label: 'areaName',
  children: 'children'
}

// 监听地区名称变化，自动过滤树节点
watch(
  () => areaName.value,
  (val) => {
    tree2Ref.value?.filter(val)
  }
)

// 页面加载完成后获取地区列表
onMounted(() => {
  getDataList(page)
})

// 分页信息配置
const page = reactive({
  total: 0, // 总条目数
  currentPage: 1, // 当前页码
  pageSize: 10 // 每页条目数
})

// 地区树形数据绑定的响应式变量
const areaTreeData = ref(null)

// 获取地区列表的方法
const getDataList = (pageParam, params) => {
  http({
    url: http.adornUrl('/admin/area/list'),
    method: 'get',
    params: http.adornParams(Object.assign({
      current: pageParam == null ? page.currentPage : pageParam.currentPage,
      size: pageParam == null ? page.pageSize : pageParam.pageSize
    }, params))
  }).then(({ data }) => {
    // 将获取到的数据转换成树形结构并赋值给areaTreeData
    areaTreeData.value = treeDataTranslate(data, 'areaId', 'parentId')
  })
}

// 添加或更新对话框引用
const addOrUpdateRef = ref(null)

// 控制添加或更新对话框显示状态的响应式变量
const addOrUpdateVisible = ref(false)

/**
 * 触发新增或更新操作
 * @param id 可选参数，若提供则表示更新指定ID的地区信息
 */
const onAddOrUpdate = (id) => {
  addOrUpdateVisible.value = true
  nextTick(() => {
    addOrUpdateRef.value?.init(id) // 初始化对话框组件
  })
}

/**
 * 执行删除操作
 * @param areaId 要删除的地区ID
 */
const onDelete = (areaId) => {
  // 弹出确认对话框，询问用户是否确定删除
  ElMessageBox.confirm('确定进行删除操作?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 发送HTTP请求执行删除操作
    http({
      url: http.adornUrl('/admin/area/' + areaId),
      method: 'delete',
      data: http.adornData({})
    }).then(() => {
      // 成功提示，并刷新地区列表
      ElMessage({
        message: '操作成功',
        type: 'success',
        duration: 1500,
        onClose: () => {
          getDataList(page)
        }
      })
    })
  }).catch(() => { /* 用户取消删除 */ })
}

// 更新地区信息的代理方法，实际调用onAddOrUpdate
const update = (node, data) => {
  onAddOrUpdate(data.areaId)
}

// 删除地区信息的代理方法，实际调用onDelete
const remove = (node, data) => {
  onDelete(data.areaId)
}

// 节点过滤方法，根据输入的地区名称筛选符合条件的节点
const filterNode = (value, data) => {
  if (!value) return true // 如果没有输入，则不做过滤
  return data.areaName.indexOf(value) !== -1 // 包含输入值的节点通过过滤
}
</script>

<style lang="scss" scoped>
.mod-sys-area {
  .area-search-input {
    width: 30%; // 设置搜索输入框宽度为容器的30%
  }
  .area-add-btn {
    float: right; // 新增按钮右对齐
  }
}
/* 使用:deep选择器穿透样式作用于子组件 */
:deep(.el-tree-node) .addr-name {
  width: 100%; // 地址名称占满整个行宽
}
</style>
