{% extends "./layout.html" %}

{% block title %}送检样本管理{% endblock %}

{% block css %}
<style>
  .drag-handle { cursor: move; color: #999; font-size: 18px; }
  .drag-handle:hover { color: #ff7800; }
  .sortable-ghost { opacity: 0.4; background: #fff7ed; }
</style>
{% endblock %}

{% block content %}
<div id="sampleTypeApp" v-cloak>
  <el-card shadow="never">
    <template #header>
      <div class="flex items-center justify-between">
        <div class="flex items-center gap-4">
          <el-button type="primary" @click="showAdd">+ 新增样本类型</el-button>
          <el-switch v-model="sampleRequired" active-text="送检样本必选" inactive-text="送检样本非必选"
            @change="handleRequiredChange" />
        </div>
        <span class="text-xs text-gray-400">拖拽行可调整排序</span>
      </div>
    </template>

    <el-table :data="list" v-loading="loading" stripe border row-key="id">
      <el-table-column width="60" align="center">
        <template #header>排序</template>
        <template #default>
          <span class="drag-handle">⠿</span>
        </template>
      </el-table-column>
      <el-table-column prop="id" label="ID" width="70"></el-table-column>
      <el-table-column prop="name" label="样本类型名称"></el-table-column>
      <el-table-column label="可选需寄回" width="120" align="center">
        <template #default="{ row }">
          <el-tag :type="row.need_return ? 'success' : 'info'" size="small">${ row.need_return ? '是' : '否' }</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" width="100" align="center">
        <template #default="{ row }">
          <el-tag :type="row.status ? 'success' : 'danger'" size="small">${ row.status ? '启用' : '禁用' }</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="180" align="center">
        <template #default="{ row }">
          <el-button type="primary" link @click="showEdit(row)">编辑</el-button>
          <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-card>

  <!-- 新增/编辑弹窗 -->
  <el-dialog v-model="dialogVisible" :title="dialogTitle" width="480px" destroy-on-close draggable :close-on-click-modal="false">
    <el-form :model="form" label-width="110px">
      <el-form-item label="样本类型名称" required>
        <el-input v-model="form.name" placeholder="请输入样本类型名称" maxlength="50" />
      </el-form-item>
      <el-form-item label="可选需寄回">
        <el-switch v-model="form.need_return" />
        <span style="margin-left:8px;font-size:12px;color:#909399;">开启后，用户选择该样本类型时可选择是否需要寄回</span>
      </el-form-item>
      <el-form-item label="排序">
        <el-input-number v-model="form.sort" :min="0" :max="999" />
      </el-form-item>
      <el-form-item label="状态">
        <el-switch v-model="form.status" :active-value="1" :inactive-value="0" />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" @click="handleSave" :loading="saving">确定</el-button>
    </template>
  </el-dialog>
</div>
{% endblock %}

{% block js %}
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.6/Sortable.min.js"></script>
<script>
const initRequired = '{{ sampleRequired }}';
const { createApp, ref, reactive, onMounted, nextTick } = Vue;

const app = createApp({
  delimiters: ['${', '}'],
  setup() {
    const loading = ref(false);
    const list = ref([]);
    const sampleRequired = ref(initRequired === '1');
    const dialogVisible = ref(false);
    const dialogTitle = ref('新增样本类型');
    const saving = ref(false);
    const form = reactive({ id: null, name: '', need_return: false, sort: 0, status: 1 });
    let sortableInstance = null;

    async function loadList() {
      loading.value = true;
      try {
        const res = await fetch('/admin/sample_type/list').then(r => r.json());
        if (res.code === 0) {
          list.value = res.data || [];
          nextTick(() => initSortable());
        }
      } finally { loading.value = false; }
    }

    function initSortable() {
      if (sortableInstance) { sortableInstance.destroy(); sortableInstance = null; }
      const tbody = document.querySelector('#sampleTypeApp .el-table__body-wrapper tbody');
      if (!tbody) return;
      sortableInstance = Sortable.create(tbody, {
        handle: '.drag-handle',
        animation: 150,
        ghostClass: 'sortable-ghost',
        onEnd(evt) {
          if (evt.oldIndex === evt.newIndex) return;
          const arr = list.value.slice();
          const item = arr.splice(evt.oldIndex, 1)[0];
          arr.splice(evt.newIndex, 0, item);
          list.value = arr;
          fetch('/admin/sample_type/sort', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ ids: arr.map(i => i.id) })
          }).then(r => r.json()).then(res => {
            if (res.code === 0) ElementPlus.ElMessage.success('排序已保存');
            else loadList();
          });
        }
      });
    }

    function showAdd() {
      dialogTitle.value = '新增样本类型';
      form.id = null; form.name = ''; form.need_return = false; form.sort = 0; form.status = 1;
      dialogVisible.value = true;
    }

    function showEdit(row) {
      dialogTitle.value = '编辑样本类型';
      form.id = row.id; form.name = row.name; form.need_return = !!row.need_return; form.sort = row.sort; form.status = row.status;
      dialogVisible.value = true;
    }

    async function handleSave() {
      if (!form.name.trim()) { ElementPlus.ElMessage.warning('请输入样本类型名称'); return; }
      saving.value = true;
      try {
        const url = form.id ? '/admin/sample_type/edit' : '/admin/sample_type/add';
        const res = await fetch(url, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(form)
        }).then(r => r.json());
        if (res.code === 0) {
          ElementPlus.ElMessage.success('保存成功');
          dialogVisible.value = false;
          loadList();
        } else {
          ElementPlus.ElMessage.error(res.msg || '保存失败');
        }
      } finally { saving.value = false; }
    }

    async function handleDelete(row) {
      try {
        await ElementPlus.ElMessageBox.confirm(`确定要删除「${row.name}」吗？`, '提示', { type: 'warning' });
        const res = await fetch('/admin/sample_type/delete', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ id: row.id })
        }).then(r => r.json());
        if (res.code === 0) { ElementPlus.ElMessage.success('删除成功'); loadList(); }
        else { ElementPlus.ElMessage.error(res.msg || '删除失败'); }
      } catch (e) {}
    }

    async function handleRequiredChange(val) {
      const res = await fetch('/admin/sample_type/setRequired', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ value: val ? 1 : 0 })
      }).then(r => r.json());
      if (res.code === 0) ElementPlus.ElMessage.success('设置已保存');
      else ElementPlus.ElMessage.error(res.msg || '设置失败');
    }

    onMounted(() => loadList());

    return { loading, list, sampleRequired, dialogVisible, dialogTitle, saving, form, showAdd, showEdit, handleSave, handleDelete, handleRequiredChange };
  }
});

app.use(ElementPlus, { locale: ElementPlusLocaleZhCn });
app.mount('#sampleTypeApp');
</script>
{% endblock %}
