EntryOrgList.vue 7.83 KB
<template>
  <div class="entry-org-container">
    <el-table ref="tableRef" class="entry-org-table" :data="tableData" :height="tableHeight"
      :highlight-current-row="true" stripe tooltip-effect="light" border>
      <el-table-column label="序号" width="56" align="center" fixed="left" :formatter="formatIndex" />
      <el-table-column prop="organisationName" label="所属部门" :width="columnWidths.organisationName" align="left"
        :show-overflow-tooltip="true">
        <template #header>
          <span>所属部门</span>
          <span style="color:red;margin-left: 2px;">*</span>
        </template>
        <template #default="scope">
            <el-tree-select v-if="!isDetail" v-model="scope.row.organisationGuid" placeholder="请选择" :data="organisationList" 
             @node-click="(node, nodeObj) => handleTreeSelectNodeChange(node, nodeObj, scope)"
            :props="{
              value: 'guid',
              label: 'name',
              children: 'children'
            }" clearable filterable :checkStrictly="true" :showAllLevels="false" class="input-width">
            </el-tree-select>
          <!-- <el-input v-if="!isDetail" v-model="scope.row.organisationName" placeholder="请选择" readonly
            @click="openOrgSelector(scope.$index)"></el-input> -->
          <span v-else>{{ scope.row.organisationName || '--' }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="isLeader" label="是否部门负责人" :width="columnWidths.isLeader" align="left"
        :show-overflow-tooltip="true">
        <template #header>
          <span>是否部门负责人</span>
          <span style="color:red;margin-left: 2px;">*</span>
        </template>
        <template #default="scope">
          <el-select v-if="!isDetail" v-model="scope.row.isLeader" placeholder="请选择" clearable filterable>
            <el-option v-for="opt in yesNoOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
          </el-select>
          <span v-else>{{ scope.row.isLeader == 'Y' ? '是' : '否' }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="isMainOrg" label="是否主责部门" :width="columnWidths.isMainOrg" align="left"
        :show-overflow-tooltip="true">
        <template #header>
          <span>是否主责部门</span>
          <span style="color:red;margin-left: 2px;">*</span>
        </template>
        <template #default="scope">
          <el-select v-if="!isDetail" v-model="scope.row.isMainOrg" placeholder="请选择" clearable filterable
            @change="handleMainOrgChange(scope.row)">
            <el-option v-for="opt in yesNoOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
          </el-select>
          <span v-else>{{ scope.row.isMainOrg == 'Y' ? '是' : '否' }}</span>
        </template>
      </el-table-column>
      <el-table-column v-if="!isDetail" label="操作" width="140" align="left" fixed="right">
        <template #default="scope">
          <span class="text_btn" @click="deleteItem(scope)" v-preReClick>删除</span>
        </template>
      </el-table-column>
    </el-table>
  </div>
  <div v-if="!isDetail" class="add-btn-container">
    <el-button link @click="addNewRow" :icon="CirclePlus" v-preReClick>
      新增入职部门
    </el-button>
  </div>
</template>

<script lang="ts" setup name="EntryOrgList">
import { CirclePlus } from "@element-plus/icons-vue";
import {
  getOrganisationRelTreeList
} from '@/api/modules/dataBasic';
import { isAllPropertiesEmpty } from '@/utils/common';
import useUserStore from "@/store/modules/user";

const userStore = useUserStore();
const userData = JSON.parse(userStore.userData)

const { proxy } = getCurrentInstance() as any;

// Props 定义
const props = defineProps({
  disabled: {
    type: Boolean,
    default: false
  },
  organisationJson: {
    type: Array as PropType<any[]>,
    default: () => []
  },
  projectDate: {
    type: Array as PropType<any[]>,
    default: () => []
  },
});

// 响应式数据
const tableRef = ref();
const currentIndex = ref<number>(0);
const organisationList = ref<any[]>([]);
const yesNoOptions = ref<any[]>([]);

// 表格数据计算属性
const tableData = computed(() => {
  return props.organisationJson;
});

// 详情状态计算属性
const isDetail = computed((): boolean => {
  return proxy.$route.query.isDetail || props.disabled;
});

// 表格高度计算
const tableHeight = computed(() => {
  return 'auto';
});

// 列宽配置
const columnWidths = computed(() => {
  return {
    organisationName: '180px',
    isLeader: '140px',
    isMainOrg: '140px'
  };
});

// 初始化数据
const initializeData = async () => {
  try {
    // 获取是否字典选项
    yesNoOptions.value = [{
      value: 'Y',
      label: '是'
    }, {
      value: 'N',
      label: '否'
    }];

    // 获取组织列表
    await getOrganisationList();
  } catch (error) {
    console.error('初始化数据失败:', error);
  }
};

// 获取组织列表
const getOrganisationList = async () => {
  try {
    const res: any = await getOrganisationRelTreeList({
      tenantGuid: userData.tenantGuid
    });
    organisationList.value = res?.data || [];
  } catch (error) {
    console.error('获取组织列表失败:', error);
  }
};

// 格式化序号
const formatIndex = (row: any, column: any, cellValue: any, index: number) => {
  return String(index + 1);
};

// 处理主责部门变更
const handleMainOrgChange = (row: any) => {
  // 检查是否已经有主责部门
  const mainOrgCount = tableData.value.filter(item => item.isMainOrg === 'Y').length;
  if (mainOrgCount > 1) {
    row.isMainOrg = null;
    proxy.$message.warning('只能选择一个主责部门');
  }
};

// 添加新行
const addNewRow = () => {
  // 检查最后一行是否填写完整
  if (tableData.value.length > 0) {
    const lastItem = tableData.value[tableData.value.length - 1];
    const isEmpty = isAllPropertiesEmpty(lastItem, ['organisationGuid', 'isLeader', 'isMainOrg']);
    if (isEmpty) {
      proxy.$message.warning('请填写完整');
      return;
    }
  }
  unref(tableData).push({});
};

// 删除行
const deleteItem = (scope: any) => {
  if (isDetail.value) return;

  proxy.$openMessageBox('确定删除吗?', () => {
    unref(tableData).splice(scope.$index, 1);
    proxy.$ElMessage.success('删除成功');
  }, () => {
    proxy.$ElMessage.info('已取消删除');
  });
};

const currentTreeNode = ref({});
const handleTreeSelectNodeChange = (node, nodeObj, scope) => {
  currentTreeNode.value = node;
  scope.row.organisationName = node.name;
}

// 验证数据
const validateData = (): boolean => {
  const guidSet = new Set();
  for (const item of tableData.value) {
    if (!item.organisationGuid) {
      proxy.$ElMessage.error('所属部门必填,请填写完整');
      return false;
    }
    if (!item.isLeader) {
      proxy.$ElMessage.error('是否部门负责人必填,请填写完整');
      return false;
    }
    if (!item.isMainOrg) {
      proxy.$ElMessage.error('是否主责部门必填,请填写完整');
      return false;
    }
    if (guidSet.has(item.organisationGuid)) {
      proxy.$ElMessage.error('部门不能重复');
      return false;
    }
    guidSet.add(item.organisationGuid);
  }

  return true;
};

// 暴露方法
defineExpose({
  tableData,
  validateData,
  tableRef
});

// 生命周期钩子
onBeforeMount(() => {
  initializeData();
});

onMounted(() => {
  // 组件挂载后的逻辑
});
</script>

<style lang="scss" scoped>
.entry-org-container {
  .entry-org-table {
    :deep(.el-table__row) {
      .el-input.is-disabled .el-input__inner {
        background-color: #f5f7fa;
        cursor: not-allowed;
      }
    }
  }
}


.add-btn-container {
  .el-button--default {
    padding: 4px 0px;
    margin-top: 4px;
  }

  :deep(.el-icon) {
    width: 16px;
    height: 16px;

    svg {
      width: 16px;
      height: 16px;
    }
  }
}
</style>