<template>
  <div class="table-box">
    <div class="card table-search">
      <el-form ref="elSearchFormRef" :inline="true" size="small" :model="searchForm" class="demo-form-inline" @keyup.enter="onSubmit">
        <el-form-item label="任务名称">
          <el-input v-model="searchForm.title" placeholder="任务名称" style="width:150px"></el-input>
        </el-form-item>
        <el-form-item label="分类">
          <el-select v-model="searchForm.category_id" placeholder="分类" clearable style="width:120px">
            <el-option v-for="item in categoryOptions" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="状态" clearable style="width:100px">
            <el-option label="启用" :value="1" />
            <el-option label="禁用" :value="0" />
          </el-select>
        </el-form-item>
        <div class="operation">
          <el-button type="primary" icon="search" @click="onSubmit">查询</el-button>
          <el-button icon="refresh" @click="onResetSearch">重置</el-button>
        </div>
      </el-form>
    </div>

    <div class="card table-main">
      <div class="table-header">
        <div class="header-button-lf">
          <el-button type="primary" icon="Plus" @click="openDialog()">新增任务</el-button>
        </div>
        <div class="header-button-ri">
          <el-button :icon="Refresh" circle @click="refresh" />
        </div>
      </div>

      <el-table ref="myTable" :data="tableData" border size="small">
        <el-table-column prop="id" label="ID" align="center" width="80" />
        <el-table-column prop="title" label="任务名称" align="center" min-width="150" />
        <el-table-column prop="categoryId" label="分类" align="center" width="100">
          <template #default="{ row }">
            {{ getCategoryName(row.categoryId) }}
          </template>
        </el-table-column>
        <el-table-column prop="cover" label="图标" align="center" width="80">
          <template #default="{ row }">
            <el-image v-if="row.cover" :src="row.cover" style="width: 40px; height: 40px" fit="contain" />
          </template>
        </el-table-column>
        <el-table-column prop="rewardAmount" label="奖励金额(USDT)" align="center" min-width="130">
          <template #default="{ row }">
            <span class="text-success">{{ formatAmount(row.rewardAmount) }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="totalCount" label="任务总量" align="center" width="90" />
        <el-table-column prop="remainCount" label="剩余数量" align="center" width="90" />
        <el-table-column prop="dailyLimit" label="每日限制" align="center" width="90" />
        <el-table-column prop="totalLimit" label="总限制" align="center" width="90" />
        <el-table-column prop="completedCount" label="已完成" align="center" width="80" />
        <el-table-column prop="minLevel" label="最低等级" align="center" width="80" />
        <el-table-column label="完成条件" align="center" min-width="150">
          <template #default="{ row }">
            <el-tag v-if="row.requirePhone" type="primary" size="small" style="margin: 2px">手机</el-tag>
            <el-tag v-if="row.requireRealname" type="success" size="small" style="margin: 2px">实名</el-tag>
            <el-tag v-if="row.requireIdcard" type="warning" size="small" style="margin: 2px">身份</el-tag>
            <span v-if="!row.requirePhone && !row.requireRealname && !row.requireIdcard" class="text-muted">无</span>
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序" align="center" width="70" />
        <el-table-column prop="status" label="状态" align="center" width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === 1 ? 'success' : 'danger'">
              {{ row.status === 1 ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createdAt" label="创建时间" align="center" min-width="160">
          <template #default="{ row }">
            <span v-if="row.createdAt">{{ formatUnix(row.createdAt) }}</span>
          </template>
        </el-table-column>
        <el-table-column fixed="right" label="操作" align="center" width="240">
          <template #default="scope">
            <el-button type="primary" link @click="openDialog(scope.row)">编辑</el-button>
            <el-button type="info" link @click="openStepDialog(scope.row)">步骤</el-button>
            <el-button type="warning" link @click="openExampleDialog(scope.row)">样例</el-button>
            <el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <Pagination :pageable="pageable" @handleCurrent="handleCurrent" />
    </div>
  </div>

  <!-- 编辑任务弹窗 -->
  <el-dialog v-model="dialogVisible" :title="isEdit ? '编辑任务' : '新增任务'" width="600px" center destroy-on-close>
    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
      <el-form-item label="任务名称" prop="title">
        <el-input v-model="formData.title" placeholder="请输入任务名称" />
      </el-form-item>
      <el-form-item label="分类" prop="category_id">
        <el-select v-model="formData.category_id" placeholder="请选择分类" style="width: 100%">
          <el-option v-for="item in categoryOptions" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
      </el-form-item>
      <el-form-item label="图标" prop="icon">
        <div class="icon-upload-wrapper">
          <el-upload
            class="icon-uploader"
            action="#"
            :show-file-list="false"
            :http-request="handleIconUpload"
            :before-upload="beforeIconUpload"
            accept="image/*"
          >
            <el-image v-if="formData.icon" :src="formData.icon" class="icon-preview-img" fit="contain" />
            <el-icon v-else class="icon-uploader-icon"><Plus /></el-icon>
          </el-upload>
          <div class="icon-actions">
            <el-button type="primary" size="small" @click="openMaterialPicker">从素材库选择</el-button>
            <el-button v-if="formData.icon" type="danger" size="small" @click="formData.icon = ''">删除</el-button>
          </div>
        </div>
        <div class="icon-url-input">
          <el-input v-model="formData.icon" placeholder="或直接输入图标URL" size="small" clearable />
        </div>
        <div class="upload-tip">建议尺寸: 100 x 100 px，支持 jpg/png/gif 格式</div>
      </el-form-item>
      <el-form-item label="描述" prop="description">
        <el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入描述" />
      </el-form-item>
      <el-form-item label="任务链接" prop="url">
        <el-input v-model="formData.url" placeholder="请输入任务链接" />
      </el-form-item>
      <el-form-item label="奖励金额(USDT)" prop="reward_amount">
        <el-input-number v-model="formData.reward_amount" :min="0" :precision="2" :step="0.1" style="width: 100%" />
      </el-form-item>
      <el-form-item label="任务总量" prop="total_count">
        <el-input-number v-model="formData.total_count" :min="1" style="width: 100%" />
        <div class="form-tip">任务可被领取的总次数</div>
      </el-form-item>
      <el-form-item label="每日限制" prop="daily_limit">
        <el-input-number v-model="formData.daily_limit" :min="0" style="width: 100%" />
      </el-form-item>
      <el-form-item label="总限制" prop="total_limit">
        <el-input-number v-model="formData.total_limit" :min="0" style="width: 100%" />
      </el-form-item>
      <el-form-item label="最低等级" prop="min_level">
        <el-input-number v-model="formData.min_level" :min="0" style="width: 100%" />
      </el-form-item>
      <el-form-item label="排序" prop="sort">
        <el-input-number v-model="formData.sort" :min="0" style="width: 100%" />
      </el-form-item>
      <el-form-item label="完成条件">
        <el-checkbox-group v-model="formData.require_conditions">
          <el-checkbox label="requirePhone">手机认证</el-checkbox>
          <el-checkbox label="requireRealname">实名认证</el-checkbox>
          <el-checkbox label="requireIdcard">身份认证</el-checkbox>
        </el-checkbox-group>
        <div class="form-tip">用户需满足选中的条件才能领取该任务</div>
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-radio-group v-model="formData.status">
          <el-radio :value="1">启用</el-radio>
          <el-radio :value="0">禁用</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
    </template>
  </el-dialog>

  <!-- 任务步骤弹窗 -->
  <el-dialog v-model="stepDialogVisible" title="任务步骤" width="900px" center destroy-on-close>
    <div class="step-header">
      <el-button type="primary" size="small" icon="Plus" @click="openStepEditDialog()">新增步骤</el-button>
    </div>
    <el-table :data="stepList" border size="small">
      <el-table-column prop="stepNo" label="步骤序号" align="center" width="80" />
      <el-table-column prop="image" label="步骤图片" align="center" width="100">
        <template #default="{ row }">
          <el-image v-if="row.image" :src="row.image" style="width: 60px; height: 60px" fit="contain" :preview-src-list="[row.image]" />
          <span v-else class="text-muted">暂无</span>
        </template>
      </el-table-column>
      <el-table-column prop="title" label="步骤标题" align="center" min-width="120" />
      <el-table-column prop="description" label="描述" align="center" min-width="200" show-overflow-tooltip />
      <el-table-column prop="requireUpload" label="需上传凭证" align="center" width="100">
        <template #default="{ row }">
          <el-tag :type="row.requireUpload === 1 ? 'danger' : 'info'" size="small">
            {{ row.requireUpload === 1 ? '是' : '否' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column fixed="right" label="操作" align="center" width="150">
        <template #default="scope">
          <el-button type="primary" link @click="openStepEditDialog(scope.row)">编辑</el-button>
          <el-button type="danger" link @click="handleDeleteStep(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>

  <!-- 编辑步骤弹窗 -->
  <el-dialog v-model="stepEditDialogVisible" :title="isStepEdit ? '编辑步骤' : '新增步骤'" width="600px" center destroy-on-close>
    <el-form ref="stepFormRef" :model="stepFormData" :rules="stepFormRules" label-width="100px">
      <el-form-item label="步骤序号" prop="stepNo">
        <el-input-number v-model="stepFormData.stepNo" :min="1" style="width: 100%" />
      </el-form-item>
      <el-form-item label="步骤标题" prop="title">
        <el-input v-model="stepFormData.title" placeholder="请输入步骤标题" />
      </el-form-item>
      <el-form-item label="描述" prop="description">
        <el-input v-model="stepFormData.description" type="textarea" :rows="4" placeholder="请输入步骤描述，可详细说明该步骤的操作要求" />
      </el-form-item>
      <el-form-item label="步骤图片" prop="image">
        <div class="step-image-wrapper">
          <el-input v-model="stepFormData.image" placeholder="请输入图片URL或选择素材" style="flex: 1" />
          <el-button type="primary" @click="openStepMaterialPicker">选择素材</el-button>
        </div>
        <div v-if="stepFormData.image" class="step-image-preview">
          <el-image :src="stepFormData.image" style="width: 120px; height: 120px" fit="contain" />
          <el-button type="danger" size="small" @click="stepFormData.image = ''">删除</el-button>
        </div>
        <div class="form-tip">用于展示该步骤的操作截图</div>
      </el-form-item>
      <el-form-item label="需上传凭证" prop="requireUpload">
        <el-radio-group v-model="stepFormData.requireUpload">
          <el-radio :value="1">是</el-radio>
          <el-radio :value="0">否</el-radio>
        </el-radio-group>
        <div class="form-tip">开启后，用户需上传完成凭证才能进入下一步</div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="stepEditDialogVisible = false">取消</el-button>
      <el-button type="primary" :loading="stepSubmitLoading" @click="handleStepSubmit">确定</el-button>
    </template>
  </el-dialog>

  <!-- 审核样例弹窗 -->
  <el-dialog v-model="exampleDialogVisible" title="审核样例" width="900px" center destroy-on-close>
    <div class="example-header">
      <el-button type="primary" size="small" icon="Plus" @click="openExampleEditDialog()">新增样例</el-button>
      <span class="example-tip">审核样例用于展示任务完成示例，帮助用户了解如何正确完成任务</span>
    </div>
    <el-table :data="exampleList" border size="small">
      <el-table-column prop="id" label="ID" align="center" width="80" />
      <el-table-column prop="image" label="样例图片" align="center" width="120">
        <template #default="{ row }">
          <el-image v-if="row.image" :src="row.image" style="width: 80px; height: 80px" fit="contain" :preview-src-list="[row.image]" />
          <span v-else class="text-muted">暂无</span>
        </template>
      </el-table-column>
      <el-table-column prop="description" label="样例描述" align="center" min-width="200" show-overflow-tooltip />
      <el-table-column prop="sort" label="排序" align="center" width="80" />
      <el-table-column fixed="right" label="操作" align="center" width="150">
        <template #default="scope">
          <el-button type="primary" link @click="openExampleEditDialog(scope.row)">编辑</el-button>
          <el-button type="danger" link @click="handleDeleteExample(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-dialog>

  <!-- 编辑审核样例弹窗 -->
  <el-dialog v-model="exampleEditDialogVisible" :title="isExampleEdit ? '编辑样例' : '新增样例'" width="600px" center destroy-on-close>
    <el-form ref="exampleFormRef" :model="exampleFormData" :rules="exampleFormRules" label-width="100px">
      <el-form-item label="样例图片" prop="image">
        <div class="step-image-wrapper">
          <el-input v-model="exampleFormData.image" placeholder="请输入图片URL或选择素材" style="flex: 1" />
          <el-button type="primary" @click="openExampleMaterialPicker">选择素材</el-button>
        </div>
        <div v-if="exampleFormData.image" class="step-image-preview">
          <el-image :src="exampleFormData.image" style="width: 120px; height: 120px" fit="contain" />
          <el-button type="danger" size="small" @click="exampleFormData.image = ''">删除</el-button>
        </div>
        <div class="form-tip">用于展示任务完成后的截图示例</div>
      </el-form-item>
      <el-form-item label="样例描述" prop="description">
        <el-input v-model="exampleFormData.description" type="textarea" :rows="3" placeholder="请输入样例描述，说明该截图展示的内容" />
      </el-form-item>
      <el-form-item label="排序" prop="sort">
        <el-input-number v-model="exampleFormData.sort" :min="0" style="width: 100%" />
        <div class="form-tip">数值越小排序越靠前</div>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="exampleEditDialogVisible = false">取消</el-button>
      <el-button type="primary" :loading="exampleSubmitLoading" @click="handleExampleSubmit">确定</el-button>
    </template>
  </el-dialog>

  <!-- 步骤素材选择器 -->
  <MaterialPicker
    v-model="stepMaterialPickerVisible"
    :accept-types="['image', 'video']"
    @confirm="handleStepMaterialSelect"
  />

  <!-- 审核样例素材选择器 -->
  <MaterialPicker
    v-model="exampleMaterialPickerVisible"
    :accept-types="['image']"
    @confirm="handleExampleMaterialSelect"
  />

  <!-- 素材选择器 -->
  <MaterialPicker
    v-model="materialPickerVisible"
    :accept-types="['image', 'video']"
    @confirm="handleMaterialSelect"
  />
</template>

<script setup>
import { ref, reactive, onMounted } from "vue";
import dayjs from "dayjs";
import { Refresh, Plus } from "@element-plus/icons-vue";
import MaterialPicker from "@/components/MaterialPicker/index.vue";
import { ElNotification, ElMessageBox } from "element-plus";
import Pagination from "@/components/Pangination/Pagination.vue";
import {
  getTaskList, createTask, updateTask, deleteTask,
  getTaskCategoryList, getTaskStepList, createTaskStep, updateTaskStep, deleteTaskStep,
  getTaskExampleList, createTaskExample, updateTaskExample, deleteTaskExample,
  createMaterial, getMaterialGroupList
} from "@/api/modules/daytask.js";
import { uploadImg } from "@/api/modules/upload.js";

const searchForm = ref({ title: null, category_id: null, status: null });
const tableData = ref([]);
const pageable = reactive({ pageNum: 1, pageSize: 30, total: 0 });
const categoryOptions = ref([]);
const taskIconGroupId = ref(0); // task_icon 分组ID

const dialogVisible = ref(false);
const isEdit = ref(false);
const formRef = ref(null);
const materialPickerVisible = ref(false);
const submitLoading = ref(false);
const formData = ref({
  id: null,
  title: "",
  category_id: null,
  icon: "",
  description: "",
  url: "",
  reward_amount: 0,
  total_count: 100,
  daily_limit: 1,
  total_limit: 1,
  min_level: 0,
  sort: 0,
  require_conditions: [], // 完成条件：requirePhone, requireRealname, requireIdcard
  status: 1
});
const formRules = ref({
  title: [{ required: true, message: "请输入任务名称", trigger: "blur" }],
  category_id: [{ required: true, message: "请选择分类", trigger: "change" }],
  reward_amount: [{ required: true, message: "请输入奖励金额", trigger: "blur" }],
  status: [{ required: true, message: "请选择状态", trigger: "change" }]
});

// 步骤相关
const stepDialogVisible = ref(false);
const currentTaskId = ref(null);
const stepList = ref([]);

const stepEditDialogVisible = ref(false);
const isStepEdit = ref(false);
const stepFormRef = ref(null);
const stepSubmitLoading = ref(false);
const stepFormData = ref({
  id: null,
  taskId: null,
  stepNo: 1,
  title: "",
  description: "",
  image: "",
  requireUpload: 1
});
const stepMaterialPickerVisible = ref(false);
const stepFormRules = ref({
  stepNo: [{ required: true, message: "请输入步骤序号", trigger: "blur" }],
  title: [{ required: true, message: "请输入步骤标题", trigger: "blur" }]
});

// 审核样例相关
const exampleDialogVisible = ref(false);
const exampleList = ref([]);

const exampleEditDialogVisible = ref(false);
const isExampleEdit = ref(false);
const exampleFormRef = ref(null);
const exampleSubmitLoading = ref(false);
const exampleFormData = ref({
  id: null,
  taskId: null,
  image: "",
  description: "",
  sort: 0
});
const exampleMaterialPickerVisible = ref(false);
const exampleFormRules = ref({
  image: [{ required: true, message: "请选择样例图片", trigger: "change" }]
});

const formatUnix = (val) => {
  if (!val) return "";
  return dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss");
};

const formatAmount = (val) => {
  if (val === null || val === undefined) return "0.00";
  return (val / 100).toFixed(2);
};

const getCategoryName = (id) => {
  const item = categoryOptions.value.find(c => c.id === id);
  return item ? item.name : "-";
};

onMounted(() => {
  getList();
  getCategoryList();
  getTaskIconGroupId();
});

// 获取 task_icon 分组ID
const getTaskIconGroupId = async () => {
  try {
    const res = await getMaterialGroupList({ code: "task_icon", pageSize: 1 });
    if (res.code === 200 && res.data.list?.length > 0) {
      taskIconGroupId.value = res.data.list[0].id;
    }
  } catch (e) {
    console.error("获取task_icon分组失败", e);
  }
};

const getCategoryList = async () => {
  try {
    const res = await getTaskCategoryList({ pageSize: 100 });
    if (res.code === 200) {
      categoryOptions.value = res.data.list || [];
    }
  } catch (error) {
    console.error("获取分类列表失败", error);
  }
};

const getList = async () => {
  tableData.value = [];
  const params = {
    current: pageable.pageNum,
    pageSize: pageable.pageSize,
    order: "sort asc, id desc"
  };
  // 搜索参数映射为后端字段名
  if (searchForm.value.title) {
    params.title = searchForm.value.title;
  }
  if (searchForm.value.category_id) {
    params.categoryId = searchForm.value.category_id;
  }
  if (searchForm.value.status !== null && searchForm.value.status !== undefined) {
    params.status = searchForm.value.status;
  }
  try {
    const res = await getTaskList(params);
    if (res.code === 200) {
      tableData.value = res.data.list || [];
      pageable.total = res.data.paging?.total || 0;
    }
  } catch (error) {
    console.error("获取列表失败", error);
  }
};

const onSubmit = () => {
  pageable.pageNum = 1;
  getList();
};

const refresh = () => getList();

const onResetSearch = () => {
  searchForm.value = { title: null, category_id: null, status: null };
  getList();
};

const handleCurrent = (data) => {
  pageable.pageNum = data.current;
  pageable.pageSize = data.pageSize;
  getList();
};

const openDialog = (row) => {
  isEdit.value = !!row;
  if (row) {
    // 后端字段映射到前端表单字段
    // 解析完成条件
    const conditions = [];
    if (row.requirePhone) conditions.push('requirePhone');
    if (row.requireRealname) conditions.push('requireRealname');
    if (row.requireIdcard) conditions.push('requireIdcard');

    formData.value = {
      id: row.id,
      title: row.title || "",
      category_id: row.categoryId || null,
      icon: row.cover || "",
      description: row.description || "",
      url: row.targetUrl || "",
      reward_amount: row.rewardAmount || 0,
      total_count: row.totalCount || 100,
      daily_limit: row.dailyLimit || 1,
      total_limit: row.totalLimit || 1,
      min_level: row.minLevel || 0,
      sort: row.sort || 0,
      require_conditions: conditions,
      status: row.status ?? 1
    };
  } else {
    formData.value = {
      id: null,
      title: "",
      category_id: null,
      icon: "",
      description: "",
      url: "",
      reward_amount: 0,
      total_count: 100,
      daily_limit: 1,
      total_limit: 1,
      min_level: 0,
      sort: 0,
      require_conditions: [],
      status: 1
    };
  }
  dialogVisible.value = true;
  if (formRef.value) {
    formRef.value.clearValidate();
  }
};

const handleSubmit = async () => {
  if (!formRef.value) return;
  await formRef.value.validate(async (valid) => {
    if (!valid) return;
    submitLoading.value = true;
    try {
      const api = isEdit.value ? updateTask : createTask;
      // 后端期望 { id, data: {...} } 格式，字段名使用camelCase（与后端json tag一致）
      const { id } = formData.value;
      // 解析完成条件多选框
      const conditions = formData.value.require_conditions || [];
      const data = {
        title: formData.value.title,
        categoryId: formData.value.category_id,
        cover: formData.value.icon,
        description: formData.value.description,
        targetUrl: formData.value.url,
        rewardAmount: formData.value.reward_amount,
        totalCount: formData.value.total_count,
        remainCount: isEdit.value ? undefined : formData.value.total_count, // 新建任务时，剩余数量=任务总量
        dailyLimit: formData.value.daily_limit,
        totalLimit: formData.value.total_limit,
        minLevel: formData.value.min_level,
        sort: formData.value.sort,
        // 完成条件
        requirePhone: conditions.includes('requirePhone') ? 1 : 0,
        requireRealname: conditions.includes('requireRealname') ? 1 : 0,
        requireIdcard: conditions.includes('requireIdcard') ? 1 : 0,
        status: formData.value.status
      };
      const params = isEdit.value ? { id, data } : { data };
      const res = await api(params);
      if (res.code === 200) {
        ElNotification.success(isEdit.value ? "更新成功" : "创建成功");
        dialogVisible.value = false;
        getList();
      } else {
        ElNotification.error(res.msg || (isEdit.value ? "更新失败" : "创建失败"));
      }
    } catch (error) {
      ElNotification.error(isEdit.value ? "更新失败" : "创建失败");
    } finally {
      submitLoading.value = false;
    }
  });
};

// ==================== 素材选择器 ====================
const openMaterialPicker = () => {
  materialPickerVisible.value = true;
};

const handleMaterialSelect = (material) => {
  formData.value.icon = material.url;
};

// ==================== 图标上传 ====================
const beforeIconUpload = (file) => {
  const isImage = file.type.startsWith("image/");
  const isLt5M = file.size / 1024 / 1024 < 5;

  if (!isImage) {
    ElNotification.warning("只能上传图片文件");
    return false;
  }
  if (!isLt5M) {
    ElNotification.warning("图片大小不能超过 5MB");
    return false;
  }
  return true;
};

const handleIconUpload = async (options) => {
  const uploadFormData = new FormData();
  uploadFormData.append("file", options.file);
  uploadFormData.append("autoSave", "false"); // 禁止后端自动保存，由前端控制

  try {
    const res = await uploadImg(uploadFormData);
    if (res.code === 200) {
      formData.value.icon = res.data.path;
      // 保存到素材库，使用 task_icon 分组ID
      const fileName = options.file.name; // 保留完整文件名
      const file = options.file;
      try {
        await createMaterial({
          data: {
            name: fileName,
            type: "image",
            url: res.data.path,
            size: file.size || 0,
            mimeType: file.type || "",
            groupId: taskIconGroupId.value || 0,
            status: 1
          }
        });
        ElNotification.success("上传成功并已保存到素材库");
      } catch (e) {
        ElNotification.success("图片上传成功");
      }
    } else {
      ElNotification.error(res.msg || "图片上传失败");
    }
  } catch (error) {
    console.error("上传失败", error);
    ElNotification.error("图片上传失败");
  }
};

const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm("确认删除该任务吗？", "提示", {
      type: "warning",
      confirmButtonText: "确定",
      cancelButtonText: "取消"
    });
    const res = await deleteTask({ id: row.id });
    if (res.code === 200) {
      ElNotification.success("删除成功");
      getList();
    } else {
      ElNotification.error(res.msg || "删除失败");
    }
  } catch (error) {
    if (error !== "cancel" && error !== "close") {
      ElNotification.error("删除失败");
    }
  }
};

// 步骤相关方法
const openStepDialog = async (row) => {
  currentTaskId.value = row.id;
  stepDialogVisible.value = true;
  await getStepList();
};

const getStepList = async () => {
  try {
    const res = await getTaskStepList({ taskId: currentTaskId.value, pageSize: 100, order: "step_no asc" });
    if (res.code === 200) {
      stepList.value = res.data.list || [];
    }
  } catch (error) {
    console.error("获取步骤列表失败", error);
  }
};

const openStepEditDialog = (row) => {
  isStepEdit.value = !!row;
  if (row) {
    stepFormData.value = { ...row };
  } else {
    stepFormData.value = {
      id: null,
      taskId: currentTaskId.value,
      stepNo: stepList.value.length + 1,
      title: "",
      description: "",
      image: "",
      requireUpload: 1
    };
  }
  stepEditDialogVisible.value = true;
  if (stepFormRef.value) {
    stepFormRef.value.clearValidate();
  }
};

// 步骤素材选择器
const openStepMaterialPicker = () => {
  stepMaterialPickerVisible.value = true;
};

const handleStepMaterialSelect = (material) => {
  stepFormData.value.image = material.url;
};

const handleStepSubmit = async () => {
  if (!stepFormRef.value) return;
  await stepFormRef.value.validate(async (valid) => {
    if (!valid) return;
    stepSubmitLoading.value = true;
    try {
      const api = isStepEdit.value ? updateTaskStep : createTaskStep;
      // 后端期望 { id, data: {...} } 格式
      const { id } = stepFormData.value;
      const data = {
        taskId: stepFormData.value.taskId || currentTaskId.value,
        stepNo: stepFormData.value.stepNo,
        title: stepFormData.value.title,
        description: stepFormData.value.description,
        image: stepFormData.value.image,
        requireUpload: stepFormData.value.requireUpload
      };
      const params = isStepEdit.value ? { id, data } : { data };
      const res = await api(params);
      if (res.code === 200) {
        ElNotification.success(isStepEdit.value ? "更新成功" : "创建成功");
        stepEditDialogVisible.value = false;
        getStepList();
      } else {
        ElNotification.error(res.msg || (isStepEdit.value ? "更新失败" : "创建失败"));
      }
    } catch (error) {
      ElNotification.error(isStepEdit.value ? "更新失败" : "创建失败");
    } finally {
      stepSubmitLoading.value = false;
    }
  });
};

const handleDeleteStep = async (row) => {
  try {
    await ElMessageBox.confirm("确认删除该步骤吗？", "提示", {
      type: "warning",
      confirmButtonText: "确定",
      cancelButtonText: "取消"
    });
    const res = await deleteTaskStep({ id: row.id });
    if (res.code === 200) {
      ElNotification.success("删除成功");
      getStepList();
    } else {
      ElNotification.error(res.msg || "删除失败");
    }
  } catch (error) {
    if (error !== "cancel" && error !== "close") {
      ElNotification.error("删除失败");
    }
  }
};

// ==================== 审核样例相关方法 ====================
const openExampleDialog = async (row) => {
  currentTaskId.value = row.id;
  exampleDialogVisible.value = true;
  await getExampleList();
};

const getExampleList = async () => {
  try {
    const res = await getTaskExampleList({ taskId: currentTaskId.value, pageSize: 100, order: "sort asc, id asc" });
    if (res.code === 200) {
      exampleList.value = res.data.list || [];
    }
  } catch (error) {
    console.error("获取审核样例列表失败", error);
  }
};

const openExampleEditDialog = (row) => {
  isExampleEdit.value = !!row;
  if (row) {
    exampleFormData.value = { ...row };
  } else {
    exampleFormData.value = {
      id: null,
      taskId: currentTaskId.value,
      image: "",
      description: "",
      sort: 0
    };
  }
  exampleEditDialogVisible.value = true;
  if (exampleFormRef.value) {
    exampleFormRef.value.clearValidate();
  }
};

// 审核样例素材选择器
const openExampleMaterialPicker = () => {
  exampleMaterialPickerVisible.value = true;
};

const handleExampleMaterialSelect = (material) => {
  exampleFormData.value.image = material.url;
};

const handleExampleSubmit = async () => {
  if (!exampleFormRef.value) return;
  await exampleFormRef.value.validate(async (valid) => {
    if (!valid) return;
    exampleSubmitLoading.value = true;
    try {
      const api = isExampleEdit.value ? updateTaskExample : createTaskExample;
      const { id } = exampleFormData.value;
      const data = {
        taskId: exampleFormData.value.taskId || currentTaskId.value,
        image: exampleFormData.value.image,
        description: exampleFormData.value.description,
        sort: exampleFormData.value.sort
      };
      const params = isExampleEdit.value ? { id, data } : { data };
      const res = await api(params);
      if (res.code === 200) {
        ElNotification.success(isExampleEdit.value ? "更新成功" : "创建成功");
        exampleEditDialogVisible.value = false;
        getExampleList();
      } else {
        ElNotification.error(res.msg || (isExampleEdit.value ? "更新失败" : "创建失败"));
      }
    } catch (error) {
      ElNotification.error(isExampleEdit.value ? "更新失败" : "创建失败");
    } finally {
      exampleSubmitLoading.value = false;
    }
  });
};

const handleDeleteExample = async (row) => {
  try {
    await ElMessageBox.confirm("确认删除该审核样例吗？", "提示", {
      type: "warning",
      confirmButtonText: "确定",
      cancelButtonText: "取消"
    });
    const res = await deleteTaskExample({ id: row.id });
    if (res.code === 200) {
      ElNotification.success("删除成功");
      getExampleList();
    } else {
      ElNotification.error(res.msg || "删除失败");
    }
  } catch (error) {
    if (error !== "cancel" && error !== "close") {
      ElNotification.error("删除失败");
    }
  }
};
</script>

<style scoped>
.operation {
  display: inline-block;
  vertical-align: middle;
}
.text-success {
  color: #67c23a;
  font-weight: bold;
}
.step-header {
  margin-bottom: 16px;
}
.icon-upload-wrapper {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.icon-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.icon-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 0.3s;
}

.icon-uploader:hover {
  border-color: #409eff;
}

.icon-uploader :deep(.el-upload) {
  width: 80px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.icon-preview-img {
  width: 80px;
  height: 80px;
}

.icon-uploader-icon {
  font-size: 24px;
  color: #8c939d;
}

.icon-url-input {
  margin-top: 10px;
  width: 100%;
}

.upload-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 5px;
}
.step-image-wrapper {
  display: flex;
  gap: 10px;
  width: 100%;
}
.step-image-preview {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  margin-top: 10px;
}
.form-tip {
  color: #909399;
  font-size: 12px;
  line-height: 1.5;
  margin-top: 4px;
}
.text-muted {
  color: #c0c4cc;
  font-size: 12px;
}
.example-header {
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.example-tip {
  color: #909399;
  font-size: 12px;
}
</style>
