<template>
  <basic-container class="process-config-page">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      v-model:page="page"
      v-model="form"
      ref="crud"
      :permission="permissionList"
      :before-open="beforeOpen"
      @row-save="rowSave"
      @row-update="rowUpdate"
      @row-del="rowDel"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
    >
      <template #menu-left>
        <el-button
          type="primary"
          icon="el-icon-plus"
          v-if="hasPermission('process_config_add')"
          @click="$refs.crud.rowAdd()"
          >新建过程配置
        </el-button>
        <el-button
          type="primary"
          icon="el-icon-download"
          plain
          v-if="config.exportUrl && hasPermission('process_config_export')"
          @click="handleExport"
          >批量导出
        </el-button>
        <el-button
          type="danger"
          icon="el-icon-delete"
          plain
          v-if="hasPermission('process_config_delete')"
          @click="handleDelete"
          >批量删除
        </el-button>
      </template>

      <template #status="{ row }">
        <el-tag :type="statusTagType(row.status)">
          {{ row.statusName || displayStatus(row.status) }}
        </el-tag>
      </template>

      <template #includedNodes="{ row }">
        <span class="process-config-page__node-value">
          {{ formatProcessNodes(row.includedNodes) }}
        </span>
      </template>

      <template #basicInfo-form>
        <div class="process-config-page__section">
          <div class="dialog-section-title">基本信息</div>
          <el-row :gutter="16">
            <el-col :span="8">
              <div class="process-config-page__field">
                <span
                  class="process-config-page__field-label process-config-page__field-label--required"
                >
                  配置名称
                </span>
                <el-input
                  v-model="form.configName"
                  :disabled="dialogReadonly"
                  maxlength="100"
                  placeholder="请输入"
                />
              </div>
            </el-col>
            <el-col :span="8">
              <div class="process-config-page__field">
                <span
                  class="process-config-page__field-label process-config-page__field-label--required"
                >
                  项目
                </span>
                <el-select
                  v-model="selectedProjectId"
                  clearable
                  filterable
                  remote
                  :remote-method="loadProjectOptions"
                  :loading="projectLoading"
                  :disabled="dialogReadonly"
                  placeholder="请选择"
                  style="width: 100%"
                  @change="handleProjectChange"
                >
                  <el-option
                    v-for="item in projectOptions"
                    :key="item.id"
                    :label="formatProjectLabel(item)"
                    :value="String(item.id)"
                  />
                </el-select>
              </div>
            </el-col>
            <el-col :span="8">
              <div class="process-config-page__field">
                <span class="process-config-page__field-label">运输完成时限</span>
                <div class="process-config-page__finish-days">
                  <span>默认</span>
                  <el-input
                    v-model="form.defaultFinishDays"
                    :disabled="dialogReadonly"
                    maxlength="3"
                    placeholder="请输入"
                    @input="handleFinishDaysInput"
                  />
                  <span>天后完成运输</span>
                </div>
              </div>
            </el-col>
            <el-col :span="24">
              <div class="process-config-page__field">
                <span class="process-config-page__field-label">备注</span>
                <el-input
                  v-model="form.remark"
                  type="textarea"
                  :rows="4"
                  :disabled="dialogReadonly"
                  maxlength="500"
                  show-word-limit
                  placeholder="请输入"
                />
              </div>
            </el-col>
          </el-row>
        </div>
      </template>

      <template #nodeConfigJson-form>
        <div class="process-config-page__custom-form">
          <div class="dialog-section-title">现行过程节点</div>
          <div class="process-config-page__timeline" v-if="enabledNodes.length">
            <div class="process-config-page__timeline-line"></div>
            <div
              v-for="node in enabledNodes"
              :key="node.key"
              class="process-config-page__timeline-item"
            >
              <span class="process-config-page__timeline-dot"></span>
              <div class="process-config-page__timeline-name">{{ node.name }}</div>
              <div class="process-config-page__timeline-desc">
                <div v-for="text in timelineDescriptions(node)" :key="text">{{ text }}</div>
              </div>
            </div>
          </div>
          <el-empty v-else description="请在节点设置中勾选过程节点" :image-size="72" />

          <div class="dialog-section-title">节点设置</div>
          <el-table
            class="process-config-page__node-table"
            border
            :data="nodeRows"
            :span-method="nodeSpanMethod"
          >
            <el-table-column label="节点设置" width="136">
              <template #default="{ row, $index }">
                <div class="process-config-page__node-cell">
                  <el-checkbox
                    v-model="row.enabled"
                    :disabled="dialogReadonly"
                    @change="syncNodeFields"
                  />
                  <span class="process-config-page__node-name">{{ row.name }}</span>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="操作要求" min-width="660">
              <template #default="{ row }">
                <div class="process-config-page__requirements">
                  <template v-if="row.key === 'accept'">
                    <div class="process-config-page__require-line">
                      <span class="process-config-page__require-label">是否确认</span>
                      <el-radio-group
                        v-model="row.confirmMode"
                        :disabled="dialogReadonly || !row.enabled"
                        @change="syncNodeFields"
                      >
                        <el-radio label="yes">是</el-radio>
                        <el-radio label="no_confirm_accept">无需确认接单</el-radio>
                      </el-radio-group>
                    </div>
                    <div class="process-config-page__require-line">
                      <span class="process-config-page__require-label">确认接单人</span>
                      <el-checkbox
                        v-model="row.confirmDriver"
                        :disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
                        @change="syncNodeFields"
                        >司机</el-checkbox
                      >
                    </div>
                  </template>

                  <template v-else-if="row.key === 'return'">
                    <div class="process-config-page__require-line">
                      <span class="process-config-page__require-label">是否确认</span>
                      <el-radio-group
                        v-model="row.confirmMode"
                        :disabled="dialogReadonly || !row.enabled"
                        @change="handleReturnConfirmChange(row)"
                      >
                        <el-radio label="yes">是</el-radio>
                        <el-radio label="no_confirm_complete">无需确认完成</el-radio>
                      </el-radio-group>
                    </div>
                    <div class="process-config-page__require-line">
                      <span class="process-config-page__require-label">确认完成</span>
                      <el-checkbox
                        v-model="row.confirmInternal"
                        :disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
                        @change="syncNodeFields"
                        >内部人员</el-checkbox
                      >
                    </div>
                  </template>

                  <template v-else>
                    <div class="process-config-page__require-grid">
                      <div class="process-config-page__require-line">
                        <span class="process-config-page__require-label">是否打卡</span>
                        <el-radio-group
                          v-model="row.punch"
                          :disabled="dialogReadonly || !row.enabled"
                          @change="syncNodeFields"
                        >
                          <el-radio :label="true">是</el-radio>
                          <el-radio :label="false">否</el-radio>
                        </el-radio-group>
                      </div>
                      <div class="process-config-page__require-line" v-if="row.supportCargo">
                        <span class="process-config-page__require-label">上传货量</span>
                        <el-radio-group
                          v-model="row.uploadCargo"
                          :disabled="dialogReadonly || !row.enabled"
                          @change="syncNodeFields"
                        >
                          <el-radio :label="true">是</el-radio>
                          <el-radio :label="false">否</el-radio>
                        </el-radio-group>
                      </div>
                      <div
                        class="process-config-page__require-line process-config-page__require-line--wide"
                        v-if="row.key === 'transit'"
                      >
                        <span class="process-config-page__require-label">打卡频次，每</span>
                        <el-input
                          v-model="row.frequencyDays"
                          :disabled="dialogReadonly || !row.enabled || !row.punch"
                          maxlength="3"
                          @input="value => handleFrequencyInput(row, value)"
                        />
                        <span>天打卡1次</span>
                      </div>
                      <div class="process-config-page__require-line">
                        <span class="process-config-page__require-label">打卡定位</span>
                        <el-radio-group
                          v-model="row.location"
                          :disabled="dialogReadonly || !row.enabled || !row.punch"
                          @change="syncNodeFields"
                        >
                          <el-radio :label="true">是</el-radio>
                          <el-radio :label="false">否</el-radio>
                        </el-radio-group>
                      </div>
                      <div class="process-config-page__require-line" v-if="row.supportCargo">
                        <span class="process-config-page__require-label">上传货量类型</span>
                        <el-checkbox-group
                          v-model="row.cargoTypes"
                          :disabled="dialogReadonly || !row.enabled || !row.uploadCargo"
                          @change="syncNodeFields"
                        >
                          <el-checkbox label="重量">重量</el-checkbox>
                          <el-checkbox label="体积">体积</el-checkbox>
                          <el-checkbox label="数量">数量</el-checkbox>
                        </el-checkbox-group>
                      </div>
                      <div
                        class="process-config-page__require-line process-config-page__require-line--wide"
                        v-if="row.key === 'transit'"
                      >
                        <span class="process-config-page__require-label">打卡时段</span>
                        <el-time-picker
                          v-model="row.timeStart"
                          :disabled="dialogReadonly || !row.enabled || !row.punch"
                          format="HH:mm"
                          value-format="HH:mm"
                          placeholder="开始"
                        />
                        <span>-</span>
                        <el-time-picker
                          v-model="row.timeEnd"
                          :disabled="dialogReadonly || !row.enabled || !row.punch"
                          format="HH:mm"
                          value-format="HH:mm"
                          placeholder="结束"
                        />
                      </div>
                    </div>
                  </template>
                </div>
              </template>
            </el-table-column>
            <el-table-column label="附件要求" min-width="320">
              <template #default="{ row }">
                <div class="process-config-page__attachments" v-if="row.supportVoucher">
                  <div class="process-config-page__require-line">
                    <span class="process-config-page__require-label">上传凭证</span>
                    <el-radio-group
                      v-model="row.uploadVoucher"
                      :disabled="dialogReadonly || !row.enabled"
                      @change="syncNodeFields"
                    >
                      <el-radio :label="true">是</el-radio>
                      <el-radio :label="false">否</el-radio>
                    </el-radio-group>
                  </div>
                  <div class="process-config-page__require-line">
                    <span class="process-config-page__require-label">凭证类型</span>
                    <el-checkbox-group
                      v-model="row.voucherTypes"
                      :disabled="dialogReadonly || !row.enabled || !row.uploadVoucher"
                      @change="syncNodeFields"
                    >
                      <el-checkbox v-for="item in row.voucherOptions" :key="item" :label="item">
                        {{ item }}
                      </el-checkbox>
                    </el-checkbox-group>
                  </div>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </template>

      <template #menu="{ row, index }">
        <el-link
          type="primary"
          v-if="hasPermission('process_config_view')"
          @click="$refs.crud.rowView(row, index)"
        >
          查看
        </el-link>
        <el-link
          type="primary"
          v-if="canEdit(row)"
          @click="$refs.crud.rowEdit(row, index)"
        >
          编辑
        </el-link>
        <el-link
          type="primary"
          v-if="hasPermission('process_config_copy')"
          @click="handleCopy(row)"
        >
          复制
        </el-link>
        <el-link
          type="primary"
          v-if="canEnable(row)"
          @click="handleAction('enable', row)"
        >
          启用
        </el-link>
        <el-link
          type="primary"
          v-if="canDisable(row)"
          @click="handleAction('disable', row)"
        >
          停用
        </el-link>
        <el-link
          type="primary"
          v-if="canDelete(row)"
          @click="rowDel(row)"
        >
          删除
        </el-link>
      </template>
    </avue-crud>

    <empty-pagination
      :page="page"
      @size-change="sizeChange"
      @current-change="currentChange"
      @load="onLoad(page, query)"
    />
  </basic-container>
</template>

<script>
import * as api from '@/api/business/process-config';
import { getList as getProjectList } from '@/api/business/project-apply';
import { getDeptTree } from '@/api/system/dept';
import { exportBlob } from '@/api/common';
import { config, option } from '@/option/business/process-config';
import { getToken } from '@/utils/auth';
import { downloadXls } from '@/utils/util';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

const NODE_TEMPLATES = [
  {
    key: 'accept',
    name: '接单',
    type: 'confirm',
    supportVoucher: false,
  },
  { key: 'arrive_scene', name: '到场', type: 'punch', enabled: false },
  {
    key: 'load',
    name: '装货',
    type: 'cargo',
    enabled: false,
    supportCargo: true,
    supportVoucher: true,
    voucherOptions: ['委托单', '发货单', '磅单', '装车照片'],
  },
  {
    key: 'dispatch',
    name: '发货',
    type: 'cargo',
    supportCargo: true,
    supportVoucher: true,
    voucherOptions: ['委托单', '发货单', '磅单', '装车照片'],
  },
  {
    key: 'transit',
    name: '在途',
    type: 'transit',
    enabled: false,
    supportVoucher: true,
    voucherOptions: ['货物照片'],
  },
  {
    key: 'arrival',
    name: '到货',
    type: 'cargo',
    supportCargo: true,
    supportVoucher: true,
    voucherOptions: ['磅单', '卸货照片', '签收单'],
  },
  {
    key: 'unload',
    name: '卸货',
    type: 'cargo',
    enabled: false,
    supportCargo: true,
    supportVoucher: true,
    voucherOptions: ['磅单', '卸货照片', '签收单'],
  },
  {
    key: 'sign',
    name: '签收',
    type: 'cargo',
    enabled: false,
    supportCargo: true,
    supportVoucher: true,
    voucherOptions: ['磅单', '签收单'],
  },
  {
    key: 'return',
    name: '回单',
    type: 'confirm',
    supportVoucher: true,
    voucherOptions: ['磅单', '签收单'],
  },
];

export default {
  data() {
    return {
      api,
      config,
      option,
      form: {},
      query: {},
      loading: true,
      data: [],
      dialogReadonly: false,
      projectOptions: [],
      projectLoading: false,
      selectedProjectId: '',
      nodeRows: [],
      page: {
        pageSize: 10,
        pageSizes: [10, 20, 50, 100],
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
    };
  },
  computed: {
    ...mapGetters(['permission', 'userInfo']),
    permissionList() {
      return {
        addBtn: this.hasPermission('process_config_add'),
      };
    },
    isAdmin() {
      const authority = this.userInfo && this.userInfo.authority;
      return Array.isArray(authority)
        ? authority.includes('admin')
        : String(authority || '').includes('admin');
    },
    ids() {
      return this.selectionList.map(item => item.id).join(',');
    },
    enabledNodes() {
      return this.nodeRows.filter(item => item.enabled);
    },
  },
  created() {
    this.resetNodeRows();
    this.loadProjectOptions('');
    this.initDeptOptions();
  },
  methods: {
    hasPermission(code) {
      return this.isAdmin || this.validData(this.permission && this.permission[code], false);
    },
    handleReturnConfirmChange(row) {
      row.confirmInternal = row.confirmMode === 'yes';
      this.syncNodeFields();
    },
    initDeptOptions() {
      getDeptTree(this.userInfo.tenantId).then(res => {
        const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
        if (deptColumn) {
          deptColumn.dicData = this.flattenDept(res.data.data || []);
        }
      });
    },
    flattenDept(tree, level = 0) {
      return tree.flatMap(item => [
        {
          label: `${'　'.repeat(level)}${item.title || item.deptName || item.name}`,
          value: item.id,
        },
        ...(item.children && item.children.length
          ? this.flattenDept(item.children, level + 1)
          : []),
      ]);
    },
    displayStatus(status) {
      const statusMap = {
        0: '草稿',
        1: '启用',
        2: '停用',
      };
      return statusMap[status] || status || '未知';
    },
    formatProcessNodes(nodes) {
      return String(nodes || '')
        .split(/[,，]/)
        .map(item => item.trim())
        .filter(Boolean)
        .join('-');
    },
    statusTagType(status) {
      if (status === 1) return 'success';
      if (status === 2) return 'info';
      return 'warning';
    },
    canEdit(row) {
      return this.hasPermission('process_config_edit') && !row.readonly;
    },
    canDelete(row) {
      return (
        this.hasPermission('process_config_delete') && !row.readonly && [0, 2].includes(row.status)
      );
    },
    canEnable(row) {
      return (
        this.hasPermission('process_config_enable') && !row.readonly && [0, 2].includes(row.status)
      );
    },
    canDisable(row) {
      return this.hasPermission('process_config_disable') && !row.readonly && row.status === 1;
    },
    cloneNode(template) {
      return {
        enabled: false,
        punch: true,
        location: true,
        uploadCargo: true,
        cargoTypes: [],
        uploadVoucher: undefined,
        voucherTypes: [],
        frequencyDays: '1',
        timeStart: '00:00',
        timeEnd: '23:59',
        supportCargo: false,
        supportVoucher: false,
        voucherOptions: [],
        confirmMode: 'yes',
        confirmDriver: false,
        confirmInternal: false,
        ...template,
      };
    },
    resetNodeRows() {
      this.nodeRows = NODE_TEMPLATES.map(item => this.cloneNode(item));
      this.syncNodeFields();
    },
    parseNodeConfig(row = {}) {
      let nodes = [];
      if (row.nodeConfigJson) {
        try {
          const parsed = JSON.parse(row.nodeConfigJson);
          nodes = Array.isArray(parsed) ? parsed : parsed.nodes || [];
        } catch (error) {
          nodes = [];
        }
      }
      const includedNodes = String(row.includedNodes || '')
        .split(',')
        .map(item => item.trim())
        .filter(Boolean);
      this.nodeRows = NODE_TEMPLATES.map(template => {
        const stored =
          nodes.find(item => item.key === template.key || item.name === template.name) || {};
        const node = this.cloneNode({ ...template, ...stored });
        if (includedNodes.length) {
          node.enabled = includedNodes.includes(node.name);
        }
        return node;
      });
      this.syncNodeFields();
    },
    nodeSpanMethod({ row, columnIndex }) {
      if (!row.supportVoucher && columnIndex === 2) {
        return [1, 1];
      }
      return [1, 1];
    },
    loadProjectOptions(keyword = '') {
      this.projectLoading = true;
      return getProjectList(1, 50, {
        projectName: keyword,
        approvalStatus: 'approved',
        allDept: 0,
      })
        .then(res => {
          const data = res.data.data || {};
          this.projectOptions = data.records || [];
          this.syncProjectSearchOptions();
          this.ensureSelectedProjectOption();
        })
        .finally(() => {
          this.projectLoading = false;
        });
    },
    ensureSelectedProjectOption() {
      if (!this.form.projectIds || !this.form.projectNames) return;
      const exists = this.projectOptions.some(
        item => String(item.id) === String(this.form.projectIds)
      );
      if (exists) return;
      this.projectOptions = [
        {
          id: this.form.projectIds,
          projectName: this.form.projectNames,
          projectCode: this.form.projectCode,
        },
        ...this.projectOptions,
      ];
      this.syncProjectSearchOptions();
    },
    syncProjectSearchOptions() {
      const column = this.option.column.find(item => item.prop === 'projectNames');
      if (!column) return;
      column.dicData = this.projectOptions.map(item => ({
        label: this.formatProjectLabel(item),
        value: item.projectName,
      }));
    },
    formatProjectLabel(item) {
      return item.projectCode ? `${item.projectName}（${item.projectCode}）` : item.projectName;
    },
    handleProjectChange(value) {
      const project = this.projectOptions.find(item => String(item.id) === String(value));
      this.form.projectIds = project ? String(project.id) : '';
      this.form.projectNames = project ? project.projectName : '';
    },
    handleFinishDaysInput(value) {
      this.form.defaultFinishDays = String(value || '')
        .replace(/\D/g, '')
        .slice(0, 3);
    },
    handleFrequencyInput(row, value) {
      row.frequencyDays = String(value || '')
        .replace(/\D/g, '')
        .slice(0, 3);
      this.syncNodeFields();
    },
    syncNodeFields() {
      const enabledNodes = this.nodeRows.filter(item => item.enabled);
      this.form.includedNodes = enabledNodes.map(item => item.name).join(',');
      this.form.nodeConfigJson = JSON.stringify(
        this.nodeRows.map(item => ({
          key: item.key,
          name: item.name,
          enabled: item.enabled,
          confirmMode: item.confirmMode,
          confirmDriver: item.confirmDriver,
          confirmInternal: item.confirmInternal,
          punch: item.punch,
          location: item.location,
          uploadCargo: item.uploadCargo,
          cargoTypes: item.uploadCargo ? item.cargoTypes : [],
          frequencyDays: item.frequencyDays,
          timeStart: item.timeStart,
          timeEnd: item.timeEnd,
          uploadVoucher: item.uploadVoucher,
          voucherTypes: item.uploadVoucher ? item.voucherTypes : [],
        }))
      );
    },
    timelineDescriptions(node) {
      const result = [];
      if (node.key === 'accept') {
        result.push(
          `是否接单：${node.confirmMode === 'no_confirm_accept' ? '无需确认接单' : '是'}`
        );
        return result;
      }
      if (node.key === 'return') {
        if (node.uploadVoucher && node.voucherTypes.length) {
          result.push(`上传凭证：${node.voucherTypes.join('、')}`);
        }
        return result;
      }
      if (node.type === 'transit') {
        result.push(`打卡操作：${node.punch ? '是' : '否'}`);
        result.push(`打卡定位：${node.location ? '是' : '否'}`);
        if (node.punch) {
          result.push(`打卡频次：每${node.frequencyDays || 1}天打卡1次`);
          result.push(`打卡时段：${node.timeStart || '00:00'}-${node.timeEnd || '23:59'}`);
        }
      } else {
        result.push(`打卡操作：${node.punch ? '是' : '否'}`);
        result.push(`打卡定位：${node.location ? '是' : '否'}`);
      }
      if (node.supportCargo && node.uploadCargo && node.cargoTypes.length) {
        result.push(`上传货量：${node.cargoTypes.join('、')}`);
      }
      if (node.supportVoucher && node.uploadVoucher && node.voucherTypes.length) {
        result.push(`上传凭证：${node.voucherTypes.join('、')}`);
      }
      return result;
    },
    normalizeRow(row) {
      const submitRow = { ...row };
      Object.keys(submitRow).forEach(key => {
        if (typeof submitRow[key] === 'string') {
          submitRow[key] = submitRow[key].trim();
        }
      });
      submitRow.defaultFinishDays = submitRow.defaultFinishDays
        ? Number(submitRow.defaultFinishDays)
        : undefined;
      return submitRow;
    },
    validateRow(row) {
      if (!row.configName) {
        this.$message.warning('配置名称不能为空');
        return false;
      }
      if (row.configName.length > 100) {
        this.$message.warning('配置名称不能超过100个字符');
        return false;
      }
      if (!row.projectNames) {
        this.$message.warning('项目不能为空');
        return false;
      }
      if (row.defaultFinishDays !== undefined && row.defaultFinishDays !== '') {
        if (!Number.isInteger(Number(row.defaultFinishDays)) || Number(row.defaultFinishDays) < 0) {
          this.$message.warning('完成天数不能小于0');
          return false;
        }
        if (Number(row.defaultFinishDays) > 999) {
          this.$message.warning('完成天数不能超过999');
          return false;
        }
      }
      if (row.remark && row.remark.length > 500) {
        this.$message.warning('备注不能超过500个字符');
        return false;
      }
      if (!this.enabledNodes.length) {
        this.$message.warning('请至少选择一个过程节点');
        return false;
      }
      const transit = this.nodeRows.find(item => item.key === 'transit');
      if (transit && transit.enabled && transit.punch) {
        if (!transit.frequencyDays || Number(transit.frequencyDays) < 1) {
          this.$message.warning('请输入打卡频次');
          return false;
        }
        if (!transit.timeStart || !transit.timeEnd) {
          this.$message.warning('请选择打卡时段');
          return false;
        }
      }
      return true;
    },
    stopSubmitLoading(loading) {
      if (typeof loading === 'function') {
        loading();
      }
    },
    needsDuplicateVoucherConfirm() {
      const signNode = this.nodeRows.find(item => item.key === 'sign');
      const returnNode = this.nodeRows.find(item => item.key === 'return');
      const hasSignVoucher =
        signNode &&
        signNode.enabled &&
        signNode.uploadVoucher &&
        signNode.voucherTypes.includes('签收单');
      const hasReturnVoucher =
        returnNode &&
        returnNode.enabled &&
        returnNode.uploadVoucher &&
        returnNode.voucherTypes.includes('签收单');
      return hasSignVoucher && hasReturnVoucher;
    },
    confirmDuplicateVoucher() {
      if (!this.needsDuplicateVoucherConfirm()) {
        return Promise.resolve();
      }
      return this.$confirm(
        '签收与回单同时勾选了上传凭证，司机将需重复上传凭证，是否确认？',
        '提示',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        }
      );
    },
    submitRow(row, done, loading) {
      this.syncNodeFields();
      const submitRow = this.normalizeRow(row);
      if (!this.validateRow(submitRow)) {
        this.stopSubmitLoading(loading);
        return;
      }
      this.confirmDuplicateVoucher()
        .then(() => api.submit(submitRow))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
          done();
        })
        .catch(error => {
          if (error !== 'cancel' && error !== 'close') {
            window.console.log(error);
          }
          this.stopSubmitLoading(loading);
        });
    },
    rowSave(row, done, loading) {
      this.submitRow(row, done, loading);
    },
    rowUpdate(row, index, done, loading) {
      this.submitRow(row, done, loading);
    },
    rowDel(row) {
      this.$confirm('确定将选择数据删除?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => api.remove(row.id))
        .then(res => {
          this.afterRemove(res.data.data);
        });
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning('请选择至少一条数据');
        return;
      }
      const selection = this.selectionList.filter(item => this.canDelete(item));
      if (!selection.length) {
        this.$message.warning('所选数据当前状态不可删除');
        return;
      }
      this.$confirm('确定将选择数据删除?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => api.remove(selection.map(item => item.id).join(',')))
        .then(res => {
          this.afterRemove(res.data.data);
        });
    },
    afterRemove(result = {}) {
      this.onLoad(this.page);
      const successCount = result.successCount || 0;
      const skippedCount = result.skippedCount || 0;
      if (skippedCount) {
        this.$message.warning(`成功删除${successCount}条，因引用跳过${skippedCount}条`);
      } else {
        this.$message({ type: 'success', message: '删除成功!' });
      }
      this.selectionClear();
    },
    beforeOpen(done, type) {
      this.dialogReadonly = type === 'view';
      if (type === 'add') {
        this.form = {
          configName: '',
          projectIds: '',
          projectNames: '',
          defaultFinishDays: '',
          remark: '',
          status: 0,
        };
        this.selectedProjectId = '';
        this.resetNodeRows();
        done();
        return;
      }
      if (['edit', 'view'].includes(type)) {
        api.getDetail(this.form.id).then(res => {
          this.form = res.data.data || {};
          this.selectedProjectId = this.form.projectIds ? String(this.form.projectIds) : '';
          this.ensureSelectedProjectOption();
          this.parseNodeConfig(this.form);
          done();
        });
        return;
      }
      done();
    },
    searchReset() {
      this.query = {};
      this.page.currentPage = 1;
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      if (this.$refs.crud) {
        this.$refs.crud.toggleSelection();
      }
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      api
        .getList(page.currentPage, page.pageSize, {
          ...params,
          ...this.query,
          allDept: this.isAdmin ? 1 : 0,
        })
        .then(res => {
          const result = res.data.data || {};
          this.page.total = result.total || 0;
          this.data = result.records || [];
          this.selectionClear();
        })
        .finally(() => {
          this.loading = false;
        });
    },
    buildExportParams() {
      return {
        ...this.query,
        allDept: this.isAdmin ? 1 : 0,
        ids: this.ids,
        [this.website.tokenHeader]: getToken(),
      };
    },
    handleExport() {
      this.$confirm(`是否导出${config.exportName}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        NProgress.start();
        exportBlob(config.exportUrl, this.buildExportParams(), { feedback: true })
          .then(res => {
            downloadXls(
              res.data,
              `${config.exportName}${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`
            );
          })
          .finally(() => {
            NProgress.done();
          });
      });
    },
    handleCopy(row) {
      this.$confirm(`确定复制该${config.title}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => api.copy(row.id))
        .then(() => {
          this.$message.success('复制成功');
          this.onLoad(this.page, this.query);
        });
    },
    handleAction(action, row) {
      const actionName = {
        enable: '启用',
        disable: '停用',
      }[action];
      this.$confirm(`确定${actionName}该${config.title}?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => api[action](row.id))
        .then(() => {
          this.$message.success(`${actionName}成功`);
          this.onLoad(this.page, this.query);
        });
    },
  },
};
</script>

<style lang="scss" scoped>
.process-config-page {
  &__section {
    width: 100%;
  }

  &__field {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 16px;
  }

  &__field-label {
    flex: 0 0 150px;
    line-height: 32px;
    color: #303133;
    font-weight: 500;
    text-align: right;
    white-space: nowrap;

    &--required::before {
      margin-right: 4px;
      color: #f56c6c;
      content: '*';
    }
  }

  &__node-value {
    white-space: normal;
    word-break: break-all;
  }

  &__finish-days {
    display: flex;
    align-items: center;
    gap: 8px;

    .el-input {
      width: 88px;
    }
  }

  &__custom-form {
    width: 100%;
  }

  &__timeline {
    position: relative;
    display: flex;
    justify-content: space-between;
    min-height: 136px;
    padding: 12px 28px 18px;
  }

  &__timeline-line {
    position: absolute;
    top: 22px;
    right: 58px;
    left: 58px;
    height: 3px;
    background: #1e90ff;
  }

  &__timeline-item {
    position: relative;
    z-index: 1;
    flex: 1;
    text-align: center;
  }

  &__timeline-dot {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #1e90ff;
  }

  &__timeline-name {
    margin-top: 14px;
    color: #1688ff;
    font-size: 18px;
    font-weight: 600;
  }

  &__timeline-desc {
    margin-top: 6px;
    color: #303133;
    line-height: 1.7;
    white-space: nowrap;
  }

  &__node-table {
    margin-top: 8px;
  }

  &__node-cell {
    display: flex;
    align-items: center;
    gap: 12px;
  }

  &__node-name {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 64px;
    height: 44px;
    padding: 0 14px;
    border-radius: 4px;
    background: #f2f3f5;
    color: #303133;
    font-size: 16px;
    font-weight: 600;
  }

  &__requirements,
  &__attachments {
    padding: 8px 0;
  }

  &__require-grid {
    display: grid;
    grid-template-columns: minmax(240px, 1fr) minmax(260px, 1fr);
    gap: 12px 24px;
  }

  &__require-line {
    display: flex;
    align-items: center;
    min-height: 30px;
    gap: 10px;

    .el-input {
      width: 62px;
    }

    .el-time-editor.el-input {
      width: 116px;
    }
  }

  &__require-line--wide {
    white-space: nowrap;
  }

  &__require-label {
    flex: 0 0 96px;
    color: #303133;
    font-weight: 500;
    text-align: right;
  }

  :deep(.avue-crud__header) {
    margin-top: 12px;
    background: transparent;
  }

  :deep(.el-table) {
    --el-table-border-color: #eff1f7;
  }

  :deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
    background: #fafafa;
  }
}
</style>
