<script setup lang="ts">
import * as echarts from 'echarts';
import { ElMessage, ElMessageBox } from 'element-plus';
import readXlsxFile from 'read-excel-file/browser';
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { useRoute } from 'vue-router';
import { http } from '../api/http';
import { displayModality, displayModelName } from '../utils/display';

const route = useRoute();
const id = route.params.id as string;
const detail = ref<any>({});
const balance = ref<any>({});
const members = ref<any[]>([]);
const projects = ref<any[]>([]);
const usage = ref<any>({ breakdown: [] });
const usageChart = ref<HTMLDivElement>();
const activeUsageGroup = ref('model');
const recharge = reactive({ amount: 0, note: '', externalRefId: '' });
const quota = reactive({ maxMembers: undefined, maxProjects: undefined, maxMonthlyCredits: undefined, maxConcurrentTasks: undefined, notes: '' } as any);
const memberDialog = ref(false);
const importDialog = ref(false);
const importing = ref(false);
const editingMember = ref<any | null>(null);
const importRows = ref<any[]>([]);
const importResults = ref<any[]>([]);
const memberForm = reactive({
  username: '',
  email: '',
  phone: '',
  password: '',
  role: 'member',
  position: '',
  status: 1,
});
let usageChartInstance: echarts.ECharts | null = null;

const tenant = computed(() => detail.value.tenant || {});
const quotaInfo = computed(() => detail.value.quota || {});
const currentBalance = computed(() => balance.value.balance || detail.value.balance || {});
const usageRows = computed(() => (usage.value.breakdown || []).map((row: any) => ({ ...row, label: usageLabel(row.label) })));
const isActive = computed(() => Number(tenant.value.status) === 1);
const spentRate = computed(() => {
  const recharged = Number(currentBalance.value.totalRecharged || 0);
  const spent = Number(currentBalance.value.totalSpent || 0);
  return recharged ? Math.round((spent / recharged) * 1000) / 10 : 0;
});
const quotaCards = computed(() => [
  { label: '成员上限', value: quotaInfo.value.maxMembers ?? '-' },
  { label: '项目上限', value: quotaInfo.value.maxProjects ?? '-' },
  { label: '月积分上限', value: quotaInfo.value.maxMonthlyCredits ?? '-' },
  { label: '并发任务', value: quotaInfo.value.maxConcurrentTasks ?? '-' },
]);

const usageGroups = [
  { label: '按模型', value: 'model' },
  { label: '按模态', value: 'modality' },
  { label: '按用户', value: 'user' },
  { label: '按天', value: 'day' },
];
const importValidRows = computed(() => importRows.value.filter((row) => !row.error));
const importSuccessCount = computed(() => importResults.value.filter((row) => row.success).length);
const importFailCount = computed(() => importResults.value.filter((row) => !row.success).length);

function formatNumber(value?: number | string) {
  return Number(value || 0).toLocaleString('zh-CN', { maximumFractionDigits: 1 });
}

function usageLabel(value?: string) {
  if (activeUsageGroup.value === 'model') return displayModelName(value);
  if (activeUsageGroup.value === 'modality') return displayModality(value);
  return value || '-';
}

async function load() {
  detail.value = await http.get(`/tenants/${id}`);
  balance.value = await http.get(`/tenants/${id}/balance`);
  members.value = await http.get(`/tenants/${id}/members`);
  projects.value = await http.get(`/tenants/${id}/projects`);
  quota.maxMembers = detail.value.quota?.maxMembers;
  quota.maxProjects = detail.value.quota?.maxProjects;
  quota.maxMonthlyCredits = detail.value.quota?.maxMonthlyCredits;
  quota.maxConcurrentTasks = detail.value.quota?.maxConcurrentTasks;
  quota.notes = detail.value.quota?.notes;
  await loadUsage(activeUsageGroup.value);
}

async function loadUsage(groupBy: string) {
  activeUsageGroup.value = groupBy;
  usage.value = await http.get(`/tenants/${id}/usage-detail`, { params: { groupBy } });
  await nextTick();
  renderUsageChart();
}

function renderUsageChart() {
  if (!usageChart.value) return;
  usageChartInstance?.dispose();
  usageChartInstance = echarts.init(usageChart.value);
  usageChartInstance.setOption({
    color: ['#2f6bff', '#0f766e', '#8b5cf6', '#f4b840', '#ef6f6c'],
    tooltip: { trigger: 'item' },
    series: [
      {
        name: '积分消耗',
        type: 'pie',
        radius: ['54%', '74%'],
        center: ['50%', '50%'],
        label: { show: false },
        labelLine: { show: false },
        data: usageRows.value.map((x: any) => ({ name: x.label, value: x.totalCredits })),
      },
    ],
  });
}

async function rechargeTenant() {
  await http.post(`/tenants/${id}/recharge`, recharge);
  ElMessage.success('充值已入账');
  await load();
}

async function updateQuota() {
  await http.put(`/tenants/${id}/quota`, quota);
  ElMessage.success('配额已更新');
  await load();
}

function roleLabel(role?: string) {
  const map: Record<string, string> = { owner: '所有者', admin: '管理员', member: '成员' };
  return role ? map[role] || role : '-';
}

function normalizeImportRole(value?: string) {
  const role = String(value || '').trim().toLowerCase();
  const map: Record<string, string> = {
    owner: 'owner',
    admin: 'admin',
    member: 'member',
    所有者: 'owner',
    管理员: 'admin',
    成员: 'member',
  };
  return map[role] || 'member';
}

function normalizeImportStatus(value?: string) {
  const status = String(value || '').trim();
  if (['0', '禁用', '停用'].includes(status)) return 0;
  return 1;
}

function splitDelimitedLine(line: string, delimiter: string) {
  if (delimiter === '\t') return line.split('\t').map((cell) => cell.trim());
  const cells: string[] = [];
  let current = '';
  let quoted = false;
  for (let index = 0; index < line.length; index += 1) {
    const char = line[index];
    if (char === '"') {
      if (quoted && line[index + 1] === '"') {
        current += '"';
        index += 1;
      } else {
        quoted = !quoted;
      }
    } else if (char === ',' && !quoted) {
      cells.push(current.trim());
      current = '';
    } else {
      current += char;
    }
  }
  cells.push(current.trim());
  return cells;
}

function buildImportRows(rows: string[][]) {
  const cleanedRows = rows
    .map((line) => line.map((cell) => String(cell || '').trim()))
    .filter((line) => line.some(Boolean));
  if (cleanedRows.length < 2) {
    ElMessage.warning('表格至少需要表头和一行成员数据');
    return [];
  }
  const headers = cleanedRows[0].map((header) => header.replace(/\s/g, '').toLowerCase());
  const headerAlias: Record<string, string> = {
    用户名: 'username',
    username: 'username',
    账号: 'username',
    邮箱: 'email',
    email: 'email',
    手机号: 'phone',
    phone: 'phone',
    组织角色: 'role',
    角色: 'role',
    role: 'role',
    岗位: 'position',
    position: 'position',
    初始密码: 'password',
    密码: 'password',
    password: 'password',
    状态: 'status',
    status: 'status',
  };
  const headerProps = headers.map((header) => headerAlias[header] || header);
  return cleanedRows.slice(1).map((cells, index) => {
    const raw: Record<string, string> = {};
    headerProps.forEach((prop, cellIndex) => {
      raw[prop] = cells[cellIndex] || '';
    });
    const row = {
      rowNumber: index + 2,
      username: raw.username?.trim(),
      email: raw.email?.trim(),
      phone: raw.phone?.trim(),
      role: normalizeImportRole(raw.role),
      roleLabel: roleLabel(normalizeImportRole(raw.role)),
      position: raw.position?.trim(),
      password: raw.password?.trim(),
      status: normalizeImportStatus(raw.status),
      statusLabel: normalizeImportStatus(raw.status) === 1 ? '正常' : '禁用',
      error: '',
    };
    if (!row.username) row.error = '用户名必填';
    else if (!row.email) row.error = '邮箱必填';
    else if (row.password && row.password.length < 8) row.error = '密码至少 8 位';
    return row;
  });
}

function parseMemberTable(text: string) {
  const lines = text
    .replace(/^\uFEFF/, '')
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);
  const delimiter = lines[0]?.includes('\t') ? '\t' : ',';
  return buildImportRows(lines.map((line) => splitDelimitedLine(line, delimiter)));
}

function downloadImportTemplate() {
  const rows = [
    ['用户名', '邮箱', '手机号', '组织角色', '岗位', '初始密码', '状态'],
    ['zhangsan_editor', 'zhangsan@example.com', '13800000001', '成员', '短剧制作', 'Dramix@123', '正常'],
    ['lisi_admin', 'lisi@example.com', '13800000002', '管理员', '项目负责人', 'Dramix@123', '正常'],
  ];
  const csv = rows.map((line) => line.map((cell) => `"${cell}"`).join(',')).join('\n');
  const blob = new Blob([`\uFEFF${csv}`], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = '组织成员批量导入模板.csv';
  link.style.display = 'none';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

async function handleImportFile(file: any) {
  const raw = file.raw;
  if (!raw) return;
  const fileName = String(raw.name || '').toLowerCase();
  if (fileName.endsWith('.xlsx')) {
    const rows = await readXlsxFile(raw) as unknown as unknown[][];
    importRows.value = buildImportRows(rows.map((line) => line.map((cell) => String(cell || ''))));
  } else {
    const text = await raw.text();
    importRows.value = parseMemberTable(text);
  }
  importResults.value = [];
}

function openImportMembers() {
  importRows.value = [];
  importResults.value = [];
  importDialog.value = true;
}

function resetMemberForm() {
  editingMember.value = null;
  memberForm.username = '';
  memberForm.email = '';
  memberForm.phone = '';
  memberForm.password = '';
  memberForm.role = 'member';
  memberForm.position = '';
  memberForm.status = 1;
}

function openCreateMember() {
  resetMemberForm();
  memberDialog.value = true;
}

function openEditMember(row: any) {
  editingMember.value = row;
  memberForm.username = row.username || '';
  memberForm.email = row.email || '';
  memberForm.phone = row.phone || '';
  memberForm.password = '';
  memberForm.role = row.memberRole || row.accountRole || 'member';
  memberForm.position = row.position || '';
  memberForm.status = Number(row.status ?? 1);
  memberDialog.value = true;
}

async function saveMember() {
  const payload = { ...memberForm };
  if (!payload.password) delete (payload as any).password;
  if (editingMember.value) {
    await http.patch(`/tenants/${id}/members/${editingMember.value.userId}`, payload);
    ElMessage.success('成员信息已更新');
  } else {
    await http.post(`/tenants/${id}/members`, payload);
    ElMessage.success('成员已写入数据库');
  }
  memberDialog.value = false;
  await load();
}

async function submitImportMembers() {
  if (!importValidRows.value.length) {
    ElMessage.warning('没有可导入的有效成员');
    return;
  }
  importing.value = true;
  try {
    importResults.value = await http.post(`/tenants/${id}/members/import`, importValidRows.value.map((row) => ({
      username: row.username,
      email: row.email,
      phone: row.phone,
      role: row.role,
      position: row.position,
      password: row.password,
      status: row.status,
    })));
    const success = importResults.value.filter((row) => row.success).length;
    const failed = importResults.value.length - success;
    ElMessage.success(`导入完成：成功 ${success} 条，失败 ${failed} 条`);
    if (success) await load();
  } finally {
    importing.value = false;
  }
}

async function toggleMemberStatus(row: any) {
  await http.patch(`/tenants/${id}/members/${row.userId}`, {
    status: Number(row.status) === 1 ? 0 : 1,
  });
  ElMessage.success(Number(row.status) === 1 ? '成员已禁用' : '成员已启用');
  await load();
}

async function deleteMember(row: any) {
  await ElMessageBox.confirm(`确认移除成员「${row.username}」？该账号会被软删除并强制下线。`, '移除成员', {
    type: 'warning',
    confirmButtonText: '继续',
    cancelButtonText: '取消',
  });
  await ElMessageBox.prompt('请输入“确认移除”完成二次确认。', '二次确认', {
    type: 'warning',
    inputPattern: /^确认移除$/,
    inputErrorMessage: '请输入：确认移除',
    confirmButtonText: '确认移除',
    cancelButtonText: '取消',
  });
  await http.delete(`/tenants/${id}/members/${row.userId}`);
  ElMessage.success('成员已移除');
  await load();
}

async function suspendTenant() {
  await http.post(`/tenants/${id}/suspend`, { reason: '运营后台暂停' });
  await load();
}

async function resumeTenant() {
  await http.post(`/tenants/${id}/resume`);
  await load();
}

async function impersonate() {
  const res = await http.post<any>(`/tenants/${id}/impersonate`, {});
  ElMessage.success(`已生成客户端 token：${res.token}`);
}

function resizeChart() {
  usageChartInstance?.resize();
}

onMounted(() => {
  load();
  window.addEventListener('resize', resizeChart);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeChart);
  usageChartInstance?.dispose();
});
</script>

<template>
  <div>
    <div class="page-head tenant-hero">
      <div>
        <div class="tenant-title-line">
          <h1>{{ tenant.name || '租户详情' }}</h1>
          <el-tag :type="isActive ? 'success' : 'warning'" effect="plain">{{ isActive ? '正常' : '暂停' }}</el-tag>
        </div>
        <p>{{ tenant.slug }} · {{ tenant.plan || '-' }} · ID {{ tenant.id || '-' }}</p>
      </div>
      <div class="page-actions">
        <el-button type="warning" plain @click="suspendTenant">暂停</el-button>
        <el-button type="success" plain @click="resumeTenant">恢复</el-button>
        <el-button type="primary" @click="impersonate">模拟登录</el-button>
      </div>
    </div>

    <div class="tenant-overview-grid">
      <div class="metric"><span>当前余额</span><strong>{{ formatNumber(currentBalance.balance) }}</strong><small>可用积分</small></div>
      <div class="metric"><span>累计充值</span><strong>{{ formatNumber(currentBalance.totalRecharged) }}</strong><small>历史入账</small></div>
      <div class="metric"><span>累计消费</span><strong>{{ formatNumber(currentBalance.totalSpent) }}</strong><small>消耗率 {{ spentRate }}%</small></div>
      <div class="metric"><span>成员 / 项目</span><strong>{{ detail.memberCount || 0 }} / {{ detail.projectCount || 0 }}</strong><small>组织使用规模</small></div>
    </div>

    <el-tabs class="tenant-tabs">
      <el-tab-pane label="基本信息">
        <div class="tenant-section-grid">
          <div class="panel">
            <div class="panel-title"><div><b>企业档案</b><span>企业基础资料与运营备注</span></div></div>
            <el-descriptions :column="2" border>
              <el-descriptions-item label="租户编号">{{ tenant.id }}</el-descriptions-item>
              <el-descriptions-item label="租户标识">{{ tenant.slug }}</el-descriptions-item>
              <el-descriptions-item label="套餐">{{ tenant.plan }}</el-descriptions-item>
              <el-descriptions-item label="状态">{{ isActive ? '正常' : '暂停' }}</el-descriptions-item>
              <el-descriptions-item label="创建时间">{{ tenant.createdAt || '-' }}</el-descriptions-item>
              <el-descriptions-item label="备注">{{ tenant.notes || '-' }}</el-descriptions-item>
            </el-descriptions>
          </div>
          <div class="panel">
            <div class="panel-title"><div><b>配额摘要</b><span>当前套餐资源边界</span></div></div>
            <div class="quota-card-grid">
              <div v-for="item in quotaCards" :key="item.label" class="quota-mini-card">
                <span>{{ item.label }}</span>
                <strong>{{ formatNumber(item.value) }}</strong>
              </div>
            </div>
          </div>
        </div>
      </el-tab-pane>

      <el-tab-pane label="余额概览">
        <div class="panel">
          <div class="panel-title"><div><b>手动充值</b><span>充值会写入资源流水并更新余额</span></div></div>
          <div class="toolbar tenant-form-toolbar">
            <el-input-number v-model="recharge.amount" :min="0" placeholder="充值积分" />
            <el-input v-model="recharge.note" placeholder="充值备注，例如合同补录 / 活动赠送" />
            <el-input v-model="recharge.externalRefId" placeholder="外部订单号，可选" />
            <el-button type="primary" @click="rechargeTenant">确认充值</el-button>
          </div>
        </div>
      </el-tab-pane>

      <el-tab-pane label="成员列表">
        <div class="panel">
          <div class="panel-title">
            <div><b>组织成员</b><span>写入员工账号与成员关系，支持新增、编辑、角色与状态维护</span></div>
            <div class="panel-tools">
              <el-button @click="downloadImportTemplate">下载模板</el-button>
              <el-button @click="openImportMembers">批量导入</el-button>
              <el-button type="primary" @click="openCreateMember">新增成员</el-button>
            </div>
          </div>
          <el-table :data="members" class="module-table">
            <el-table-column label="员工账号" min-width="230">
              <template #default="{ row }">
                <div class="relation-cell">
                  <strong>{{ row.username }}</strong>
                  <small>{{ row.email }}</small>
                  <small>{{ row.phone || '未填写手机号' }}</small>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="组织角色" min-width="180">
              <template #default="{ row }">
                <div class="relation-cell">
                  <strong>{{ roleLabel(row.memberRole || row.accountRole) }}</strong>
                  <small>{{ row.position || '未设置岗位' }}</small>
                  <small>关系 ID：{{ row.memberId || '-' }}</small>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="状态" width="110">
              <template #default="{ row }">
                <el-tag :type="Number(row.status) === 1 ? 'success' : 'info'" effect="plain">
                  {{ Number(row.status) === 1 ? '正常' : '禁用' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="joinedAt" label="加入时间" min-width="180" />
            <el-table-column prop="lastLoginAt" label="最近登录" min-width="180" />
            <el-table-column label="操作" width="260">
              <template #default="{ row }">
                <div class="row-actions">
                  <el-button text type="primary" @click="openEditMember(row)">编辑</el-button>
                  <el-button text @click="toggleMemberStatus(row)">{{ Number(row.status) === 1 ? '禁用' : '启用' }}</el-button>
                  <el-button text type="danger" @click="deleteMember(row)">移除</el-button>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-tab-pane>

      <el-tab-pane label="项目列表">
        <div class="panel">
          <div class="panel-title"><div><b>项目列表</b><span>企业下短剧项目与制作状态</span></div></div>
          <el-table :data="projects">
            <el-table-column prop="name" label="项目" min-width="180" />
            <el-table-column prop="style" label="风格" width="120" />
            <el-table-column prop="resolution" label="分辨率" width="120" />
            <el-table-column prop="status" label="状态" width="120" />
            <el-table-column prop="createdAt" label="创建时间" min-width="170" />
          </el-table>
        </div>
      </el-tab-pane>

      <el-tab-pane label="积分明细">
        <div class="panel usage-panel">
          <div class="panel-title">
            <div><b>积分消耗分析</b><span>按模型、模态、用户和日期拆解消耗来源</span></div>
            <div class="segmented-actions">
              <el-button
                v-for="group in usageGroups"
                :key="group.value"
                :type="activeUsageGroup === group.value ? 'primary' : 'default'"
                @click="loadUsage(group.value)"
              >
                {{ group.label }}
              </el-button>
            </div>
          </div>

          <div v-if="usageRows.length" class="tenant-usage-grid">
            <div ref="usageChart" class="chart-box tenant-usage-chart" />
            <el-table :data="usageRows">
              <el-table-column prop="label" label="维度" min-width="160" />
              <el-table-column prop="totalCredits" label="积分" width="120" />
              <el-table-column prop="count" label="次数" width="100" />
              <el-table-column prop="percent" label="占比" width="100" />
            </el-table>
          </div>
          <div v-else class="empty-business-state">
            <b>暂无该维度消耗数据</b>
            <p>当前企业还没有产生可统计的模型调用记录。发生剧本生成、图片生成、视频生成或运营充值后，这里会自动汇总到对应维度。</p>
          </div>
        </div>
      </el-tab-pane>

      <el-tab-pane label="配额">
        <div class="panel">
          <div class="panel-title"><div><b>配额调整</b><span>控制成员、项目、月积分和并发上限</span></div></div>
          <div class="toolbar tenant-form-toolbar">
            <el-input-number v-model="quota.maxMembers" placeholder="成员" />
            <el-input-number v-model="quota.maxProjects" placeholder="项目" />
            <el-input-number v-model="quota.maxMonthlyCredits" placeholder="月积分" />
            <el-input-number v-model="quota.maxConcurrentTasks" placeholder="并发任务" />
            <el-button type="primary" @click="updateQuota">保存配额</el-button>
          </div>
        </div>
      </el-tab-pane>
    </el-tabs>

    <el-dialog v-model="memberDialog" :title="editingMember ? '编辑组织成员' : '新增组织成员'" width="620px">
      <el-form label-position="top" class="business-form-grid">
        <el-form-item label="用户名">
          <el-input v-model="memberForm.username" placeholder="如 zhangsan_editor" />
        </el-form-item>
        <el-form-item label="邮箱">
          <el-input v-model="memberForm.email" placeholder="员工登录邮箱" />
        </el-form-item>
        <el-form-item label="手机号">
          <el-input v-model="memberForm.phone" placeholder="可选" />
        </el-form-item>
        <el-form-item label="初始/重置密码">
          <el-input v-model="memberForm.password" show-password placeholder="留空则不修改；新增默认 Dramix@123" />
        </el-form-item>
        <el-form-item label="组织角色">
          <el-select v-model="memberForm.role">
            <el-option label="所有者" value="owner" />
            <el-option label="管理员" value="admin" />
            <el-option label="成员" value="member" />
          </el-select>
        </el-form-item>
        <el-form-item label="账号状态">
          <el-radio-group v-model="memberForm.status" class="business-radio-group">
            <el-radio-button :value="1">正常</el-radio-button>
            <el-radio-button :value="0">禁用</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="岗位" class="span-2">
          <el-input v-model="memberForm.position" placeholder="如 企业管理员、短剧制作、财务对接、项目负责人" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="memberDialog = false">取消</el-button>
        <el-button type="primary" @click="saveMember">写入数据库</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="importDialog" title="批量导入组织成员" width="960px" class="member-import-dialog">
      <div class="member-import-layout">
        <section class="import-uploader">
          <div>
            <b>上传成员表格</b>
            <span>请使用模板填写，支持 Excel xlsx、CSV 文件上传。</span>
          </div>
          <el-upload
            drag
            accept=".xlsx,.csv,.txt"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="handleImportFile"
          >
            <div class="upload-compact">
              <b>点击或拖拽表格到这里</b>
              <span>表头：用户名、邮箱、手机号、组织角色、岗位、初始密码、状态</span>
            </div>
          </el-upload>
          <el-button @click="downloadImportTemplate">下载导入模板</el-button>
        </section>

        <section class="import-summary">
          <span>待导入</span>
          <strong>{{ importValidRows.length }}</strong>
          <small>有效行 / 共 {{ importRows.length }} 行</small>
          <div v-if="importResults.length">
            <el-tag type="success" effect="plain">成功 {{ importSuccessCount }}</el-tag>
            <el-tag type="danger" effect="plain">失败 {{ importFailCount }}</el-tag>
          </div>
        </section>
      </div>

      <div class="import-preview-table">
        <el-table :data="importResults.length ? importResults : importRows" max-height="360">
          <el-table-column prop="rowNumber" label="行号" width="80" />
          <el-table-column prop="username" label="用户名" min-width="150" />
          <el-table-column prop="email" label="邮箱" min-width="190" />
          <el-table-column prop="phone" label="手机号" min-width="130" />
          <el-table-column label="组织角色" width="110">
            <template #default="{ row }">{{ row.roleLabel || roleLabel(row.member?.memberRole || row.member?.accountRole || row.role) }}</template>
          </el-table-column>
          <el-table-column prop="position" label="岗位" min-width="140">
            <template #default="{ row }">{{ row.position || row.member?.position || '-' }}</template>
          </el-table-column>
          <el-table-column label="状态" width="110">
            <template #default="{ row }">
              <el-tag v-if="importResults.length" :type="row.success ? 'success' : 'danger'" effect="plain">
                {{ row.success ? '成功' : '失败' }}
              </el-tag>
              <el-tag v-else :type="row.error ? 'danger' : 'success'" effect="plain">
                {{ row.error || row.statusLabel }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="结果说明" min-width="180">
            <template #default="{ row }">{{ row.message || row.error || '待导入' }}</template>
          </el-table-column>
        </el-table>
        <el-empty v-if="!importRows.length && !importResults.length" description="请先上传成员表格" />
      </div>

      <template #footer>
        <el-button @click="importDialog = false">取消</el-button>
        <el-button type="primary" :loading="importing" :disabled="!importValidRows.length" @click="submitImportMembers">
          写入数据库
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>
