<template>
  <a-spin :spinning="loading">
    <div class="bg-partymatter-bpm-form">
      <a-form class="main-form" :class="{ 'main-form-readonly': mainDisabled }" labelAlign="left" :labelCol="labelCol" :wrapperCol="wrapperCol" :model="mainForm">
        <div class="base-info-header section-toolbar">
          <div class="section-title">基础信息</div>
          <a-space class="section-actions">
            <a-button v-if="!mainDisabled" class="base-save-button" type="link" size="small" :loading="savingMain" @click="submitForm">
              <Icon icon="ant-design:save-outlined" />
              保存
            </a-button>
            <a-button class="section-action-button" :type="showBaseInfoDetail ? 'default' : 'link'" size="small" @click="showBaseInfoDetail = !showBaseInfoDetail">
              <Icon :icon="showBaseInfoDetail ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
              {{ showBaseInfoDetail ? '收起基础信息' : '展开全部信息' }}
            </a-button>
          </a-space>
        </div>
        <a-row class="base-info-row" :gutter="[12, 4]">
          <a-col :xs="24" :md="12">
            <a-form-item label="事项名称" name="title" :labelCol="compactLabelCol" :wrapperCol="compactWrapperCol">
              <a-input v-model:value="mainForm.title" :disabled="mainDisabled" allow-clear />
            </a-form-item>
          </a-col>
          <a-col :xs="24" :md="12">
            <a-form-item label="会议决议" name="content" :labelCol="compactLabelCol" :wrapperCol="compactWrapperCol">
              <a-textarea v-model:value="mainForm.content" :auto-size="{ minRows: 1, maxRows: 7 }" :disabled="mainDisabled" allow-clear />
            </a-form-item>
          </a-col>
          <template v-if="showBaseInfoDetail">
            <a-divider />
            <a-col :span="12">
              <a-form-item label="年份" name="year">
                <j-dict-select-tag v-model:value="mainForm.year" :disabled="mainDisabled" dictCode="super_year" placeholder="请选择年份" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="密级" name="secretLevel">
                <j-dict-select-tag v-model:value="mainForm.secretLevel" disabled dictCode="secret_level" placeholder="请选择密级" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="序号" name="number">
                <a-input v-model:value="mainForm.number" :disabled="mainDisabled" :readonly="true" />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="议题序号" name="itemNumber">
                <a-input-number v-model:value="mainForm.itemNumber" :disabled="mainDisabled" style="width: 100%" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="会议时间" name="matterTime">
                <a-date-picker v-model:value="mainForm.matterTime" value-format="YYYY-MM-DD" :disabled="mainDisabled" style="width: 100%" allow-clear />
              </a-form-item>
            </a-col>

            <a-col :span="12">
              <a-form-item label="事项目录编码" name="matterCode">
                <a-input v-model:value="mainForm.matterCode" :disabled="mainDisabled" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="抄告单编号" name="noticeNumber">
                <a-input v-model:value="mainForm.noticeNumber" :disabled="mainDisabled" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="是否为三重一大决策" name="isImportant">
                <j-dict-select-tag v-model:value="mainForm.isImportant" :disabled="mainDisabled" dictCode="yn" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="分管所领导" name="manageSuoleader">
                <DeptRoleUserSelectDropDown
                  v-model:value="mainForm.manageSuoleader"
                  :deptId="CHARGE_LEADER_DEPT_ID"
                  :roleId="CHARGE_LEADER_ROLE_ID"
                  :disabled="mainDisabled"
                  placeholder="请选择分管所领导"
                />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="责任部门" name="responDeptid">
                <j-select-dept
                  v-model:value="mainForm.responDeptid"
                  :disabled="mainDisabled"
                  :multiple="true"
                  checkStrictly
                  allow-clear
                  @change="handleDeptChange('responDeptid', $event)"
                  @select="handleDeptSelect('responDeptid', $event)"
                />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="协办部门" name="assistDeptid">
                <j-select-dept
                  v-model:value="mainForm.assistDeptid"
                  :disabled="mainDisabled"
                  :multiple="true"
                  checkStrictly
                  allow-clear
                  @change="handleDeptChange('assistDeptid', $event)"
                  @select="handleDeptSelect('assistDeptid', $event)"
                />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="要求完成日期" name="deadline">
                <a-date-picker v-model:value="mainForm.deadline" value-format="YYYY-MM-DD" :disabled="mainDisabled" style="width: 100%" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="是否急件" name="urgencyLevel">
                <j-dict-select-tag v-model:value="mainForm.urgencyLevel" :disabled="mainDisabled" dictCode="yn" placeholder="请选择是否急件" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="督办次数" name="superviseCount">
                <a-input v-model:value="mainForm.superviseCount" :disabled="mainDisabled" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item label="完成状态" name="bpmStatus">
                <j-dict-select-tag v-model:value="mainForm.bpmStatus" disabled dictCode="super_status" allow-clear />
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item label="实际执行情况" name="actualExect" :labelCol="wideLabelCol" :wrapperCol="wideWrapperCol">
                <a-textarea v-model:value="mainForm.actualExect" :auto-size="{ minRows: 1, maxRows: 7 }" :disabled="mainDisabled" allow-clear />
              </a-form-item>
            </a-col>
          </template>
        </a-row>
      </a-form>

      <a-divider />

      <div class="feedback-header section-toolbar">
        <div class="section-title">办理情况</div>
        <a-space class="section-actions">
          <a-button v-if="showAddFeedback" class="section-action-button feedback-add-button" type="primary" @click="openFeedbackModal">
            <Icon icon="ant-design:plus-outlined" />
            新增反馈
          </a-button>
          <a-button
            class="section-action-button"
            :type="showFeedbackDetail ? 'default' : 'link'"
            size="small"
            @click="showFeedbackDetail = !showFeedbackDetail"
          >
            <Icon :icon="showFeedbackDetail ? 'ant-design:up-outlined' : 'ant-design:down-outlined'" />
            {{ showFeedbackDetail ? '收起办理情况' : '展开办理情况' }}
          </a-button>
        </a-space>
      </div>
      <a-table
        v-if="showFeedbackDetail"
        rowKey="id"
        size="small"
        bordered
        :columns="feedbackColumns"
        :data-source="feedbackList"
        :pagination="false"
        :scroll="{ x: feedbackTableScrollX }"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'attachments'">
            <SUploadFile
              v-if="record.id"
              :key="getFeedbackAttachmentKey(record)"
              class="feedback-attachment-list"
              :bussiness-id="record.id"
              :disabled="true"
              :multiple="true"
            />
            <span v-else>-</span>
          </template>
          <template v-else-if="canManageFeedback && column.key === 'action'">
            <a-space>
              <a-button type="link" size="small" @click="openFeedbackEditModal(record)">编辑</a-button>
              <a-popconfirm title="是否确认删除" @confirm="handleFeedbackDelete(record)">
                <a-button type="link" size="small" danger>删除</a-button>
              </a-popconfirm>
            </a-space>
          </template>
        </template>
      </a-table>

      <BgPartymatterBPMFeedbackModal ref="feedbackModalRef" @success="loadFeedbackList" />

      <template v-if="showProcessHandle">
        <a-divider />
        <div class="process-header section-toolbar">
          <div class="section-title">流程办理</div>
        </div>
        <a-form v-if="showSubApproveUser" class="process-variable-form" labelAlign="left" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-row :gutter="16">
            <a-col :span="12">
              <a-form-item label="是否办结" :labelCol="wideLabelCol" :wrapperCol="wideWrapperCol">
                <a-radio-group v-model:value="isEnd" :disabled="savingSubApproveUser">
                  <a-radio :value="0">否（分配部门经办人）</a-radio>
                  <a-radio :value="1">是（办结）</a-radio>
                </a-radio-group>
              </a-form-item>
            </a-col>
            <a-col v-if="showSubApproveUserSelector" :span="12">
              <a-form-item label="部门经办人" :labelCol="wideLabelCol" :wrapperCol="wideWrapperCol">
                <sz-dept-user-modal
                  v-model:value="subApproveUser"
                  :disabled="savingSubApproveUser"
                />
              </a-form-item>
            </a-col>
<!--            <a-col :span="24">-->
<!--              <a-form-item :wrapperCol="wideActionWrapperCol">-->
<!--                <a-button type="primary" :loading="savingSubApproveUser" @click="saveSubApproveUserVariable()">保存</a-button>-->
<!--              </a-form-item>-->
<!--            </a-col>-->
          </a-row>
        </a-form>
        <a-form v-if="showFinishSelector" class="process-variable-form" labelAlign="left" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-row :gutter="16">
            <a-col :span="12">
              <a-form-item label="是否已完成" :labelCol="wideLabelCol" :wrapperCol="wideWrapperCol">
                <a-radio-group v-model:value="isFinish" :disabled="savingFinish">
                  <a-radio value="0">否（未完成）</a-radio>
                  <a-radio value="1">是（已完成）</a-radio>
                </a-radio-group>
              </a-form-item>
            </a-col>
          </a-row>
        </a-form>
        <TaskHandleInnerContent
          :form-data="formData"
          :claim="claim"
          :beforeHandle="saveMainFormBeforeProcessHandle"
          :defaultReason="defaultHandleReason"
          @success="handleProcessSuccess"
          @claimSuccess="handleClaimSuccess"
        />
      </template>
    </div>
  </a-spin>
</template>

<script lang="ts" setup>
  import { computed, onMounted, reactive, ref, watch } from 'vue';
  import { defHttp } from '/@/utils/http/axios';
  import { getUserList, queryDepartTreeSync } from '/@/api/common/api';
  import { useMessage } from '/@/hooks/web/useMessage';
  import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
  import Icon from '/@/components/Icon/index';
  import { bgPartymatterFeedbackDelete, bgPartymatterFeedbackList, saveBpmForm, setBpmVariableLocal } from '../BgPartymatter.api';
  import { usePermission } from '/@/hooks/web/usePermission';
  import TaskHandleInnerContent from '/@/views/super/bpm/process/personalOffice/myHandleTask/content/TaskHandleInnerContent.vue';
  import JDictSelectTag from "../../../../components/Form/src/jeecg/components/JDictSelectTag.vue";
  import BgPartymatterBPMFeedbackModal from './BgPartymatterBPMFeedbackModal.vue';
  import SUploadFile from '/@/components/semri/fileComponent/SUploadFile.vue';
  import SzDeptUserModal from '/@/components/semri/deptUserComponent/SzDeptUserModal.vue';
  import DeptRoleUserSelectDropDown from '/@/components/semri/userComponent/DeptRoleUserSelectDropDown.vue';
  import {
    PARTY_COMMITTEE_DEPT_ID as CHARGE_LEADER_DEPT_ID,
    CHARGE_LEADER_ROLE_ID,
  } from '/@/constant/supervision';
  const { isDisabledAuth, hasPermission, initBpmFormData} = usePermission();

  const props = defineProps({
    formDisabled: { type: Boolean, default: false },
    formData: { type: Object, default: () => ({}) },
    formBpm: { type: Boolean, default: true },
    claim: { type: Boolean, default: false },
  });

  initBpmFormData(props.formData);
  console.log("@props.formData", props.formData);
  console.log("@props", props);

  const emit = defineEmits(['ok', 'success', 'claimSuccess']);
  const { createMessage } = useMessage();
  const queryByIdUrl = '/bgpartymatter/bgPartymatter/queryById';

  const labelCol = { xs: { span: 24 }, sm: { span: 7 } };
  const wrapperCol = { xs: { span: 24 }, sm: { span: 17 } };
  const wideLabelCol = { xs: { span: 24 }, sm: { span: 3 } };
  const wideWrapperCol = { xs: { span: 24 }, sm: { span: 21 } };
  const compactLabelCol = { xs: { span: 24 }, sm: { span: 5 } };
  const compactWrapperCol = { xs: { span: 24 }, sm: { span: 19 } };
  const wideActionWrapperCol = { xs: { span: 24 }, sm: { span: 21, offset: 3 } };

  const feedbackModalRef = ref();
  const loading = ref(false);
  const savingMain = ref(false);
  const savingSubApproveUser = ref(false);
  const savingFinish = ref(false);
  const showBaseInfoDetail = ref(false);
  const showFeedbackDetail = ref(true);
  const feedbackList = ref<any[]>([]);
  const feedbackAttachmentRefreshKey = ref(0);
  const deptNameText = reactive<Record<string, string>>({
    responDeptid: '',
    assistDeptid: '',
  });
  const deptOptionCache = reactive<Record<string, Record<string, string>>>({
    responDeptid: {},
    assistDeptid: {},
  });
  const deptResolveVersion = ref(0);
  const subApproveUser = ref('');
  const subApproveUserNameText = ref('');
  const userResolveVersion = ref(0);
  const isEnd = ref(0);
  const isFinish = ref('0');
  const lastGeneratedNumber = ref('');

  const mainForm = reactive<Record<string, any>>({
    id: '',
    year: '',
    secretLevel: '',
    number: '',
    itemNumber: undefined,
    matterTime: '',
    title: '',
    content: '',
    matterCode: '',
    noticeNumber: '',
    isImportant: '',
    manageSuoleader: '',
    responDeptid: '',
    assistDeptid: '',
    actualExect: '',
    bpmStatus: '',
    superviseCount: '',
    deadline: '',
    urgencyLevel: '',
    isNeedAppro: '',
    supDeptleaderid: '',
    isNeedSuoleader: '',
    suoleaderid: '',
    isNeedInterval: '',
    startCount: '',
    intervalType: '',
    intervalStartTime: '',
    meetingType: 'party',
  });

  const feedbackBaseColumns = [
    { title: '责任部门名称', dataIndex: 'responDeptname', align: 'center', width: 160 },
    { title: '反馈人姓名', dataIndex: 'responPersonname', align: 'center', width: 140 },
    { title: '计划完成目标', dataIndex: 'planExect', align: 'center', width: 260 },
    {
      title: '计划完成日期',
      dataIndex: 'planTime',
      align: 'center',
      width: 140,
      customRender: ({ text }) => (!text ? '' : String(text).slice(0, 10)),
    },
    { title: '实际执行情况', dataIndex: 'actualExect', align: 'center', width: 280 },
    { title: '实际完成日期', dataIndex: 'actualTime', align: 'center', width: 180, customRender: ({ text }) => (!text ? '' : String(text).slice(0, 10)) },
    { title: '完成状态', dataIndex: 'bpmStatus', align: 'center', width: 120, customRender: ({ record }) => record?.bpmStatus_dictText || record?.bpmStatus },
    { title: '附件', dataIndex: 'id', key: 'attachments', align: 'left', width: 340 },
  ];
  const feedbackActionColumn = { title: '操作', dataIndex: 'action', key: 'action', align: 'center', width: 120, fixed: 'right' };
  const feedbackColumns = computed(() => {
    return canManageFeedback.value ? [...feedbackBaseColumns, feedbackActionColumn] : feedbackBaseColumns;
  });
  const feedbackTableScrollX = computed(() => {
    return canManageFeedback.value ? 1740 : 1620;
  });

  const mainDisabled = computed(() => {
    if (props.formBpm) {
      return props.formData?.disabled !== false;
    }
    return props.formDisabled;
  });
  // 只有待办办理入口展示流程办理区，历史/抄送查看即使有 taskId 也只展示业务表单。
  const showProcessHandle = computed(() => props.formBpm && props.formData?.PROCESS_TAB_TYPE === 'run' && !!props.formData?.taskId);
  const canManageFeedback = computed(() => props.formBpm && props.formData?.PROCESS_TAB_TYPE === 'run' && !!props.formData?.taskId);
  const showAddFeedback = computed(() => String(props.formData?.extendUrlParams?.addfeedback ?? '') === '1');
  const showSubApproveUser = computed(() => String(props.formData?.extendUrlParams?.selectuser ?? '') === '1');
  const showFinishSelector = computed(() => String(props.formData?.extendUrlParams?.selectfinish ?? '') === '1');
  const showSubApproveUserSelector = computed(() => showSubApproveUser.value && String(isEnd.value) !== '1');

  const processInfo = computed(() => ({
    taskId: props.formData?.taskId,
    taskDefKey: props.formData?.taskDefKey,
    processInstanceId:
      props.formData?.procInsId ||
      props.formData?.procInstId ||
      props.formData?.processInstanceId ||
      props.formData?.vars?.BPM_INST_ID ||
      props.formData?.vars?.JG_LOCAL_PROCESS_ID ||
      props.formData?.vars?.process_inst_id ||
      props.formData?.vars?.processInstanceId,
    processDataId: props.formData?.processDataId,
    processTableName: props.formData?.processTableName,
  }));
  const handleReasonTemplateMap: Record<string, () => string> = {
    Task_137y5vq: buildLeaderDeptReason,
    Task_0d4iflp: buildDeptLeaderAssignReason,
    Task_01ynnpq: buildDeptHandlerFeedbackReason,
    Task_1s7zk9h: buildDeptLeaderApproveReason,
    Task_0mpxssh: buildSuperviseHandlerConfirmReason,
    Task_1g8igx5: buildSuperviseHandlerArchiveReason,
  };
  const defaultHandleReason = computed(() => {
    const builder = handleReasonTemplateMap[String(processInfo.value.taskDefKey || '')];
    return builder ? builder() : '';
  });

  onMounted(() => {
    initFormData();
  });

  watch(
    [() => props.formData?.dataId, () => processInfo.value.processInstanceId],
    () => initFormData()
  );

  watch(
    () => props.formData?.vars?.isEnd,
    (value) => {
      isEnd.value = String(value ?? '0') === '1' ? 1 : 0;
    },
    { immediate: true }
  );

  watch(
    () => props.formData?.vars?.isFinish,
    (value) => {
      isFinish.value = String(value ?? '0') === '1' ? '1' : '0';
    },
    { immediate: true }
  );

  watch(
    subApproveUser,
    (value) => {
      resolveSubApproveUserName(value);
    },
    { immediate: true }
  );

  // 根据会议时间和议题序号自动生成业务序号，例如：2026-05-20 + 2 => 20260520-2。
  watch(
    () => [mainForm.matterTime, mainForm.itemNumber],
    () => {
      syncGeneratedNumber();
    }
  );

  async function initFormData() {
    const dataId = props.formData?.dataId;
    if (!dataId) {
      return;
    }
    showBaseInfoDetail.value = false;
    loading.value = true;
    try {
      const data = await defHttp.get({ url: queryByIdUrl, params: { id: dataId } });
      if (dataId !== props.formData?.dataId) {
        return;
      }
      setMainForm(data || {});
      await syncDeptNamesFromRecord(data || {});
      if (dataId !== props.formData?.dataId) {
        return;
      }
      await loadFeedbackList();
    } finally {
      loading.value = false;
    }
  }

  function setMainForm(record: Record<string, any>) {
    Object.keys(mainForm).forEach((key) => {
      mainForm[key] = record[key] ?? '';
    });
    // 部门选择组件未展开时不会立刻回传 label，先使用详情接口的字典文本生成默认办理意见。
    deptNameText.responDeptid = normalizeDeptNames(record.responDeptid_dictText || record.responDeptname);
    deptNameText.assistDeptid = normalizeDeptNames(record.assistDeptid_dictText || record.assistDeptname);
  }

  async function syncDeptNamesFromRecord(record: Record<string, any>) {
    const resolveVersion = ++deptResolveVersion.value;
    const [responDept, assistDept] = await Promise.all([
      resolveDeptNameText('responDeptid', record.responDeptid, record.responDeptid_dictText || record.responDeptname),
      resolveDeptNameText('assistDeptid', record.assistDeptid, record.assistDeptid_dictText || record.assistDeptname),
    ]);
    if (resolveVersion !== deptResolveVersion.value) {
      return;
    }
    applyResolvedDeptName(responDept);
    applyResolvedDeptName(assistDept);
  }

  async function resolveDeptNameText(field: 'responDeptid' | 'assistDeptid', ids: any, fallbackText: any) {
    const deptIds = normalizeDeptIds(ids);
    const fallbackNames = splitDeptNames(fallbackText);
    if (!deptIds.length) {
      return { field, cache: {}, nameText: '' };
    }

    if (fallbackNames.length) {
      return { field, cache: buildDeptOptionCache(deptIds, fallbackNames), nameText: normalizeDeptNames(fallbackNames.join(',')) };
    }

    try {
      const records = (await queryDepartTreeSync({ ids: deptIds.join(','), primaryKey: 'id' })) || [];
      const cache = records.reduce((cache: Record<string, string>, item: any) => {
        const id = String(item?.id || item?.value || item?.key || '').trim();
        const name = String(item?.departName || item?.title || item?.label || '').trim();
        if (id && name) {
          cache[id] = name;
        }
        return cache;
      }, {});
      const names = deptIds.map((id) => cache[id]).filter(Boolean);
      return { field, cache, nameText: normalizeDeptNames(names.join(',')) };
    } catch {
      return { field, cache: {}, nameText: '' };
    }
  }

  function applyResolvedDeptName(result: { field: 'responDeptid' | 'assistDeptid'; cache: Record<string, string>; nameText: string }) {
    deptOptionCache[result.field] = result.cache;
    deptNameText[result.field] = result.nameText;
  }

  function handleDeptSelect(field: 'responDeptid' | 'assistDeptid', options?: any[] | null) {
    const nextCache: Record<string, string> = {};
    if (Array.isArray(options)) {
      options.forEach((item) => {
        const value = String(item?.value || item?.id || item?.key || '').trim();
        const label = String(item?.label || item?.title || item?.departName || item?.text || '').trim();
        if (value && label) {
          nextCache[value] = label;
        }
      });
    }
    deptOptionCache[field] = nextCache;
    syncDeptNameText(field, mainForm[field]);
  }

  function handleDeptChange(field: 'responDeptid' | 'assistDeptid', value: any) {
    syncDeptNameText(field, value);
  }

  function buildLeaderDeptReason() {
    const responDeptName = normalizeDeptNames(deptNameText.responDeptid);
    if (!responDeptName) {
      return '';
    }
    const assistDeptName = normalizeDeptNames(deptNameText.assistDeptid);
    return assistDeptName ? `同意。请${responDeptName}、${assistDeptName}反馈办理情况；` : `同意。请${responDeptName}反馈办理情况。`;
  }

  function buildDeptLeaderAssignReason() {
    if (String(isEnd.value) === '1') {
      return '已反馈完成情况，请确认。';
    }
    const userNameText = normalizeDeptNames(subApproveUserNameText.value || subApproveUser.value);
    return userNameText ? `请${userNameText}办理。` : '';
  }

  function buildDeptHandlerFeedbackReason() {
    return '已完成反馈，请领导审批。';
  }

  function buildDeptLeaderApproveReason() {
    return String(isFinish.value) === '1' ? '已审批，请督办部门确认。' : '请反馈完成情况。';
  }

  function buildSuperviseHandlerConfirmReason() {
    return '已确认。';
  }

  function buildSuperviseHandlerArchiveReason() {
    return '已归档确认。';
  }

  function normalizeDeptNames(value: any) {
    return splitDeptNames(value).join('、');
  }

  function splitDeptNames(value: any) {
    return String(value || '')
      .split(/[,，;；、]/)
      .map((item) => item.trim())
      .filter(Boolean);
  }

  function buildDeptOptionCache(ids: string[], names: string[]) {
    return ids.reduce((cache: Record<string, string>, id, index) => {
      const name = names[index];
      if (id && name) {
        cache[id] = name;
      }
      return cache;
    }, {});
  }

  function syncDeptNameText(field: 'responDeptid' | 'assistDeptid', value: any) {
    const ids = normalizeDeptIds(value);
    if (!ids.length) {
      deptNameText[field] = '';
      return;
    }
    const names = ids.map((id) => deptOptionCache[field][id]).filter(Boolean);
    if (names.length) {
      deptNameText[field] = normalizeDeptNames(names.join(','));
    }
  }

  function normalizeDeptIds(value: any) {
    if (Array.isArray(value)) {
      return value.map((item) => String(item || '').trim()).filter(Boolean);
    }
    return String(value || '')
      .split(',')
      .map((item) => item.trim())
      .filter(Boolean);
  }

  async function resolveSubApproveUserName(value: any) {
    const resolveVersion = ++userResolveVersion.value;
    const usernames = normalizeUsernameList(value);
    if (!usernames) {
      subApproveUserNameText.value = '';
      return;
    }

    // JSelectUser 的 v-model 存 username，办理意见展示需要尽量翻译为真实姓名。
    subApproveUserNameText.value = normalizeDeptNames(usernames);
    try {
      const res = await getUserList({ username: usernames, isMultiTranslate: 'true', pageNo: 1, pageSize: 999 });
      if (resolveVersion !== userResolveVersion.value) {
        return;
      }
      const records = res?.records || res?.result?.records || res || [];
      const userNameMap = Array.isArray(records)
        ? records.reduce((cache: Record<string, string>, item: any) => {
            const username = String(item?.username || '').trim();
            const realname = String(item?.realname || item?.name || '').trim();
            if (username && realname) {
              cache[username] = realname;
            }
            return cache;
          }, {})
        : {};
      const names = usernames
        .split(',')
        .map((username) => userNameMap[username] || username)
        .filter(Boolean);
      subApproveUserNameText.value = normalizeDeptNames(names.join(','));
    } catch {
      if (resolveVersion === userResolveVersion.value) {
        subApproveUserNameText.value = normalizeDeptNames(usernames);
      }
    }
  }

  function syncGeneratedNumber() {
    const generatedNumber = buildGeneratedNumber(mainForm.matterTime, mainForm.itemNumber);
    if (generatedNumber) {
      mainForm.number = generatedNumber;
      lastGeneratedNumber.value = generatedNumber;
      return;
    }
    if (lastGeneratedNumber.value && mainForm.number === lastGeneratedNumber.value) {
      mainForm.number = '';
      lastGeneratedNumber.value = '';
    }
  }

  // 只在两个必要字段都填写后生成，避免用户未填完整时写入半截序号。
  function buildGeneratedNumber(matterTime, itemNumber) {
    const dateText = formatMatterTime(matterTime);
    if (!dateText || itemNumber === undefined || itemNumber === null || itemNumber === '') {
      return '';
    }
    return `${dateText}-${itemNumber}`;
  }

  // 兼容日期选择器返回的字符串、Date、dayjs/moment 对象。
  function formatMatterTime(value) {
    if (!value) {
      return '';
    }
    if (typeof value === 'string') {
      return value.slice(0, 10).replace(/-/g, '');
    }
    if (value instanceof Date) {
      const year = value.getFullYear();
      const month = String(value.getMonth() + 1).padStart(2, '0');
      const day = String(value.getDate()).padStart(2, '0');
      return `${year}${month}${day}`;
    }
    if (typeof value.format === 'function') {
      return value.format('YYYYMMDD');
    }
    return '';
  }

  async function loadFeedbackList() {
    const bpmProcessId = processInfo.value.processInstanceId;
    if (!mainForm.id || !bpmProcessId) {
      feedbackList.value = [];
      feedbackAttachmentRefreshKey.value += 1;
      return;
    }
    const res = await bgPartymatterFeedbackList({ mainId: mainForm.id, bpmProcessId, pageNo: 1, pageSize: 999 });
    feedbackList.value = res?.records || res?.result?.records || [];
    feedbackAttachmentRefreshKey.value += 1;
  }

  function getFeedbackAttachmentKey(record: Recordable) {
    return `${record?.id || ''}-${feedbackAttachmentRefreshKey.value}`;
  }

  async function submitForm() {
    return saveMainForm();
  }

  async function saveMainForm(options: { showMessage?: boolean; emitOk?: boolean } = {}) {
    const { showMessage = true, emitOk = true } = options;
    savingMain.value = true;
    try {
      const processInstanceId = processInfo.value.processInstanceId;
      console.log('BgPartymatter BPM process info', { ...processInfo.value, processInstanceId });
      const res = await saveBpmForm({
        processInstanceId,
        varField: 'json_data',
        formData: { ...mainForm },
      });
      if (res.success) {
        if (showMessage) {
          createMessage.success(res.message || '保存成功');
        }
        if (emitOk) {
          emit('ok');
        }
        return true;
      }
      createMessage.warning(res.message || '保存失败');
      return false;
    } catch (error) {
      createMessage.warning('保存失败');
      return false;
    } finally {
      savingMain.value = false;
    }
  }

  async function saveMainFormBeforeProcessHandle() {
    if (!mainDisabled.value) {
      const mainSaved = await saveMainForm({ showMessage: false, emitOk: false });
      if (!mainSaved) {
        return false;
      }
    }
    if (showSubApproveUser.value) {
      const subApproveUserSaved = await saveSubApproveUserVariable({ showSuccessMessage: false });
      if (!subApproveUserSaved) {
        return false;
      }
    }
    if (showFinishSelector.value) {
      return saveFinishVariable({ showSuccessMessage: false });
    }
    return true;
  }

  function openFeedbackModal() {
    if (!mainForm.id) {
      createMessage.warning('主表数据不存在，无法新增反馈');
      return;
    }
    const processInstanceId = processInfo.value.processInstanceId;
    if (!processInstanceId) {
      createMessage.warning('流程实例ID不能为空，无法新增反馈');
      return;
    }
    feedbackModalRef.value?.open(mainForm.id, mainForm.secretLevel, processInstanceId);
  }

  function openFeedbackEditModal(record: Recordable) {
    if (!canManageFeedback.value) {
      createMessage.warning('当前流程状态不允许编辑反馈');
      return;
    }
    if (!record?.id) {
      createMessage.warning('反馈记录不存在，无法编辑');
      return;
    }
    feedbackModalRef.value?.open(mainForm.id, mainForm.secretLevel, processInfo.value.processInstanceId, record);
  }

  async function handleFeedbackDelete(record: Recordable) {
    if (!canManageFeedback.value) {
      createMessage.warning('当前流程状态不允许删除反馈');
      return;
    }
    if (!record?.id) {
      createMessage.warning('反馈记录不存在，无法删除');
      return;
    }
    try {
      await bgPartymatterFeedbackDelete({ id: record.id }, () => undefined);
      createMessage.success('删除成功');
      await loadFeedbackList();
    } catch (error) {
      createMessage.warning('删除失败');
    }
  }

  async function saveSubApproveUserVariable(options: { showSuccessMessage?: boolean } = {}) {
    const { showSuccessMessage = true } = options;
    const processInstanceId = processInfo.value.processInstanceId;
    const isEndValue = String(isEnd.value);
    const usernameValue = normalizeUsernameList(subApproveUser.value);
    if (!processInstanceId) {
      createMessage.warning('流程实例ID不能为空');
      return false;
    }
    if (isEndValue !== '1' && !usernameValue) {
      createMessage.warning('请选择部门经办人');
      return false;
    }

    savingSubApproveUser.value = true;
    try {
      const isEndResult = await saveProcessVariable('isEnd', isEndValue);
      if (!isEndResult?.success) {
        createMessage.warning(isEndResult.message || '保存失败');
        return false;
      }

      if (isEndValue !== '1') {
        const subApproveUserResult = await saveProcessVariable('subApproveUser', usernameValue);
        if (!subApproveUserResult?.success) {
          createMessage.warning(subApproveUserResult.message || '保存失败');
          return false;
        }
      }
      if (showSuccessMessage) {
        createMessage.success('保存成功');
      }
      return true;
    } catch (error) {
      createMessage.warning('保存失败');
      return false;
    } finally {
      savingSubApproveUser.value = false;
    }
  }

  async function saveFinishVariable(options: { showSuccessMessage?: boolean } = {}) {
    const { showSuccessMessage = true } = options;
    const processInstanceId = processInfo.value.processInstanceId;
    if (!processInstanceId) {
      createMessage.warning('流程实例ID不能为空');
      return false;
    }

    savingFinish.value = true;
    try {
      // Gateway_isfinish 读取当前执行分支的局部变量，需在办理动作前写入。
      const result = await saveProcessVariable('isFinish', String(isFinish.value));
      if (!result?.success) {
        createMessage.warning(result.message || '保存失败');
        return false;
      }
      if (showSuccessMessage) {
        createMessage.success('保存成功');
      }
      return true;
    } catch (error) {
      createMessage.warning('保存失败');
      return false;
    } finally {
      savingFinish.value = false;
    }
  }

  function saveProcessVariable(varField: string, varVal: any) {
    return setBpmVariableLocal({
      processInstanceId: processInfo.value.processInstanceId,
      taskId: processInfo.value.taskId,
      parentLevel: 2,
      varField,
      varVal,
    });
  }

  function normalizeUsernameList(value: string) {
    return String(value || '')
      .split(',')
      .map((item) => item.trim())
      .filter(Boolean)
      .join(',');
  }

  function handleProcessSuccess() {
    emit('success');
  }

  function handleClaimSuccess() {
    emit('claimSuccess');
  }

  defineExpose({
    submitForm,
    initFormData,
    loadFeedbackList,
  });
</script>

<style lang="less" scoped>
  .bg-partymatter-bpm-form {
    padding: 8px 12px 14px;
  }

  .main-form {
    background: #fff;
  }

  .main-form,
  .process-variable-form {
    :deep(.ant-form-item-label) {
      text-align: left;
    }

    :deep(.ant-form-item-label > label) {
      justify-content: flex-start;
      color: #1f2937;
      font-weight: 500;
    }

    :deep(.ant-form-item-control),
    :deep(.ant-form-item-control-input),
    :deep(.ant-form-item-control-input-content) {
      text-align: left;
    }
  }

  .section-title {
    margin-bottom: 8px;
    padding-left: 8px;
    border-left: 3px solid #1677ff;
    color: #1f2937;
    font-size: 14px;
    font-weight: 600;
    line-height: 16px;
  }

  .section-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    padding: 6px 10px;
    background: #f6fbff;
    border: 1px solid #d6e8ff;
    border-radius: 6px;

    .section-title {
      margin-bottom: 0;
    }

    .section-actions {
      display: inline-flex;
      align-items: center;
      gap: 4px;
    }

    .section-action-button {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      min-width: 58px;
      justify-content: center;
      font-weight: 500;
      box-shadow: none;
    }

    .base-save-button {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      height: 24px;
      padding: 0 6px;
      color: #64748b;
      font-weight: 400;
    }
  }

  .base-info-header {
    margin-top: 0;
  }

  .base-info-row {
    padding: 0 10px;

    :deep(.ant-form-item) {
      margin-bottom: 6px;
    }

    :deep(.ant-form-item-label) {
      padding-bottom: 0;
    }

    :deep(.ant-form-item-label > label) {
      width: 100%;
    }

    :deep(.ant-input),
    :deep(.ant-input-number),
    :deep(.ant-picker),
    :deep(.ant-select-selector) {
      min-height: 30px;
    }
  }

  .main-form-readonly {
    :deep(.ant-input[disabled]),
    :deep(.ant-input-disabled),
    :deep(.ant-input-affix-wrapper-disabled),
    :deep(.ant-input-affix-wrapper-disabled.ant-input-outlined),
    :deep(.ant-input-affix-wrapper-disabled:hover),
    :deep(.ant-input-affix-wrapper-disabled:focus),
    :deep(.ant-input-affix-wrapper-disabled-focused),
    :deep(.ant-input-outlined[disabled]),
    :deep(.ant-input-outlined.ant-input-disabled),
    :deep(.ant-input-number-disabled),
    :deep(.ant-input-number-disabled:hover),
    :deep(.ant-input-number-disabled:focus),
    :deep(textarea.ant-input[disabled]),
    :deep(.ant-picker-disabled),
    :deep(.ant-select-disabled .ant-select-selector) {
      background: transparent !important;
      border-color: transparent !important;
      color: #1f2937 !important;
      box-shadow: none !important;
      cursor: default !important;
      opacity: 1 !important;
    }

    :deep(.ant-input[disabled]),
    :deep(.ant-input-disabled),
    :deep(.ant-input-number-disabled),
    :deep(.ant-input-affix-wrapper-disabled),
    :deep(textarea.ant-input[disabled]) {
      padding-left: 0 !important;
      padding-right: 0 !important;
    }

    :deep(.ant-input-affix-wrapper-disabled .ant-input) {
      background: transparent !important;
      color: #1f2937 !important;
      cursor: default !important;
    }

    :deep(.ant-input-number-disabled .ant-input-number-input) {
      background: transparent !important;
      color: #1f2937 !important;
      -webkit-text-fill-color: #1f2937 !important;
      cursor: default !important;
    }

    :deep(.ant-input[disabled]::placeholder),
    :deep(.ant-input-disabled::placeholder),
    :deep(.ant-input-affix-wrapper-disabled .ant-input::placeholder) {
      color: #9ca3af !important;
    }

    :deep(.ant-picker-disabled input),
    :deep(.ant-select-disabled .ant-select-selection-item),
    :deep(.ant-select-disabled .ant-select-selection-item span),
    :deep(.ant-select-disabled .ant-select-selection-placeholder),
    :deep(.ant-select-disabled .ant-select-selection-placeholder span) {
      color: #1f2937 !important;
      -webkit-text-fill-color: #1f2937 !important;
      cursor: default !important;
    }

    :deep(.ant-picker-disabled),
    :deep(.ant-select-disabled .ant-select-selector) {
      padding-left: 0 !important;
    }

    :deep(.ant-select-disabled),
    :deep(.ant-select-disabled *),
    :deep(.ant-select-disabled.ant-select-outlined),
    :deep(.ant-select-disabled.ant-select-outlined .ant-select-selector) {
      color: #1f2937 !important;
      -webkit-text-fill-color: #1f2937 !important;
      opacity: 1 !important;
    }

    :deep(.ant-select-disabled .ant-select-arrow),
    :deep(.ant-picker-disabled .ant-picker-suffix),
    :deep(.ant-input-disabled .ant-input-clear-icon),
    :deep(.ant-input-affix-wrapper-disabled .ant-input-clear-icon),
    :deep(.ant-input-number-disabled .ant-input-number-handler-wrap),
    :deep(.ant-select-disabled .ant-select-clear) {
      display: none;
    }
  }

  .feedback-header {
    margin-bottom: 8px;

    .feedback-add-button {
      min-width: 104px;
    }
  }

  .process-variable-form {
    margin-bottom: 8px;
  }

  .sub-approve-user-row {
    display: flex;
    width: 100%;

    :deep(.ant-input-affix-wrapper),
    :deep(.ant-input) {
      min-width: 280px;
    }
  }

  :deep(.ant-divider-horizontal) {
    margin: 10px 0;
  }

  .feedback-attachment-list {
    min-width: 300px;

    :deep(.file-list-wrapper) {
      min-height: 0 !important;
      padding: 4px 8px;
    }

    :deep(.ant-spin-nested-loading),
    :deep(.ant-spin-container) {
      min-height: 0 !important;
      line-height: 20px;
    }

    :deep(.file-list-header) {
      margin-bottom: 6px;
      padding-bottom: 6px;
    }

    :deep(.file-list .file-item) {
      padding: 8px;
      margin-bottom: 6px;
    }

    :deep(.ant-empty) {
      margin: 0 !important;
      display: flex;
      align-items: center;
      min-height: 20px;
      text-align: left;
    }

    :deep(.ant-empty-image) {
      display: none !important;
    }

    :deep(.ant-empty-description) {
      color: #94a3b8;
      font-size: 12px;
      line-height: 20px;
    }
  }
</style>
