|
@@ -0,0 +1,532 @@
|
|
|
+<template>
|
|
|
+ <hc-dialog
|
|
|
+ v-model="isShow"
|
|
|
+ ui="hc-exctab-element-web-temp"
|
|
|
+ title="关联公共WBS模板"
|
|
|
+ widths="1200px"
|
|
|
+ :padding="false"
|
|
|
+ is-table
|
|
|
+ @close="dialogClose"
|
|
|
+ >
|
|
|
+ <div class="hc-exctab-element-web-temp-box hc-flex h-full">
|
|
|
+ <div class="left h-full flex-1">
|
|
|
+ <hc-card scrollbar>
|
|
|
+ <template #header>
|
|
|
+ <div class="w-full">
|
|
|
+ <el-select
|
|
|
+ v-model="formModelName"
|
|
|
+ filterable
|
|
|
+ block
|
|
|
+ placeholder="请选择清表模板"
|
|
|
+ @change="formNameChange"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in excelData"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.wbsName"
|
|
|
+ :value="item.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #search>
|
|
|
+ <div v-if="formModelName" class="w-full">
|
|
|
+ <hc-search-input
|
|
|
+ v-model="filterText"
|
|
|
+ placeholder="输入关键字搜索"
|
|
|
+ @search="treeFilterClick"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-if="formModelName">
|
|
|
+ <template v-if="isTreeMode === 1">
|
|
|
+ <hc-lazy-tree
|
|
|
+ v-if="isShow"
|
|
|
+ ref="treeRef1"
|
|
|
+ :h-props="treeProps"
|
|
|
+ tree-key="id"
|
|
|
+ :show-checkbox="tabsKey === '2'"
|
|
|
+ check-strictly
|
|
|
+ :default-checked-keys="treeNodeIds"
|
|
|
+ @load="treeLoadNode"
|
|
|
+ @node-tap="treeNodeTap"
|
|
|
+ >
|
|
|
+ <template #name="{ data }">
|
|
|
+ <span class="text-16px font-400">{{
|
|
|
+ data.title
|
|
|
+ }}</span>
|
|
|
+ </template>
|
|
|
+ </hc-lazy-tree>
|
|
|
+ </template>
|
|
|
+ <template v-if="isTreeMode === 2">
|
|
|
+ <hc-data-tree
|
|
|
+ ref="treeRef2"
|
|
|
+ :h-props="treeProps"
|
|
|
+ tree-key="id"
|
|
|
+ :show-checkbox="tabsKey === '2'"
|
|
|
+ :datas="treeData"
|
|
|
+ check-strictly
|
|
|
+ :default-checked-keys="treeNodeIds"
|
|
|
+ @node-tap="treeNodeTap"
|
|
|
+ >
|
|
|
+ <template #name="{ data }">
|
|
|
+ <span class="text-16px font-400">{{
|
|
|
+ data.title
|
|
|
+ }}</span>
|
|
|
+ </template>
|
|
|
+ </hc-data-tree>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </hc-card>
|
|
|
+ </div>
|
|
|
+ <div class="right h-full flex-1">
|
|
|
+ <hc-tab-card
|
|
|
+ :tabs="tabsData"
|
|
|
+ :tab-key="tabsKey"
|
|
|
+ @change="tabsChange"
|
|
|
+ >
|
|
|
+ <template v-if="tabsKey === '1'">
|
|
|
+ <hc-table
|
|
|
+ :column="nodeTableColumn"
|
|
|
+ :datas="nodeTableData"
|
|
|
+ :is-index="false"
|
|
|
+ >
|
|
|
+ <template #action="{ row }">
|
|
|
+ <el-link
|
|
|
+ v-if="row.checknd"
|
|
|
+ type="warning"
|
|
|
+ @click="rowUnlinkClick(row)"
|
|
|
+ >取消关联</el-link
|
|
|
+ >
|
|
|
+ <el-link
|
|
|
+ v-else
|
|
|
+ type="primary"
|
|
|
+ @click="rowLinkClick(row)"
|
|
|
+ >选择关联</el-link
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </hc-table>
|
|
|
+ </template>
|
|
|
+ <div v-if="tabsKey === '2'">
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formModel"
|
|
|
+ :rules="formRules"
|
|
|
+ label-position="top"
|
|
|
+ label-width="auto"
|
|
|
+ size="large"
|
|
|
+ >
|
|
|
+ <el-form-item label="元素表名:" prop="nodeName">
|
|
|
+ <el-input
|
|
|
+ v-model="formModel.nodeName"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="请输入元素表名"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="清表类型:" prop="tableType">
|
|
|
+ <el-select
|
|
|
+ v-model="formModel.tableType"
|
|
|
+ filterable
|
|
|
+ block
|
|
|
+ placeholder="请选择清表类型"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in excelTypeData"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="所属方:" prop="tableOwner">
|
|
|
+ <el-select
|
|
|
+ v-model="formModel.tableOwner"
|
|
|
+ filterable
|
|
|
+ block
|
|
|
+ placeholder="请选择所属方"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in ownerTypeList"
|
|
|
+ :key="item.value"
|
|
|
+ :label="item.label"
|
|
|
+ :value="item.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </hc-tab-card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <el-button hc-btn @click="dialogClose">取消</el-button>
|
|
|
+ <el-button
|
|
|
+ hc-btn
|
|
|
+ type="primary"
|
|
|
+ :loading="submitLoading"
|
|
|
+ @click="dialogSubmit"
|
|
|
+ >提交</el-button
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </hc-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, watch } from "vue";
|
|
|
+import { getDictionaryData, getDictionaryVal } from "~uti/tools";
|
|
|
+import { formValidate, getArrValue, getObjValue, isNullES } from "js-fast-way";
|
|
|
+import mainApi from "~api/exctab/exceltab";
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ info: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({}),
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ type: Array,
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+//事件
|
|
|
+const emit = defineEmits(["finish", "close"]);
|
|
|
+
|
|
|
+//双向绑定
|
|
|
+const isShow = defineModel("modelValue", {
|
|
|
+ default: false,
|
|
|
+});
|
|
|
+
|
|
|
+//监听数据
|
|
|
+const dataInfo = ref(props.info);
|
|
|
+watch(
|
|
|
+ () => props.info,
|
|
|
+ (data) => {
|
|
|
+ dataInfo.value = getObjValue(data);
|
|
|
+ },
|
|
|
+ { immediate: true, deep: true }
|
|
|
+);
|
|
|
+
|
|
|
+//监听数据
|
|
|
+const datas = ref(props.data);
|
|
|
+watch(
|
|
|
+ () => props.data,
|
|
|
+ (data) => {
|
|
|
+ datas.value = getArrValue(data);
|
|
|
+ },
|
|
|
+ { immediate: true, deep: true }
|
|
|
+);
|
|
|
+
|
|
|
+//监听显示
|
|
|
+watch(isShow, (val) => {
|
|
|
+ if (val) getInfoData();
|
|
|
+});
|
|
|
+
|
|
|
+//获取数据详情
|
|
|
+const tableData = ref([]);
|
|
|
+const formModelName = ref("");
|
|
|
+const getInfoData = () => {
|
|
|
+ getWbsTypeList();
|
|
|
+ //处理元素字段信息
|
|
|
+ const data = getArrValue(datas.value);
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ data[i].eName = data[i].textInfo;
|
|
|
+ data[i].eType = data[i].textElementType;
|
|
|
+ data[i].eAllowDeviation = data[i].textDeviation;
|
|
|
+ }
|
|
|
+ tableData.value = data;
|
|
|
+};
|
|
|
+
|
|
|
+//获取清表模板信息
|
|
|
+const excelData = ref([]);
|
|
|
+const getWbsTypeList = async () => {
|
|
|
+ const { data } = await mainApi.getWbsTypeList({ wbstype: 1 });
|
|
|
+ excelData.value = getArrValue(data);
|
|
|
+};
|
|
|
+
|
|
|
+//清表模板被改变
|
|
|
+const formNameChange = () => {
|
|
|
+ isTreeMode.value = 5;
|
|
|
+ filterText.value = "";
|
|
|
+ nodeTableData.value = [];
|
|
|
+ formModel.value = {};
|
|
|
+ tabsKey.value = "1";
|
|
|
+ nodeInfo.value = {};
|
|
|
+ treeNodeIds.value = [];
|
|
|
+ treeData.value = [];
|
|
|
+ setTimeout(() => {
|
|
|
+ isTreeMode.value = 1;
|
|
|
+ }, 200);
|
|
|
+};
|
|
|
+
|
|
|
+//树配置
|
|
|
+const treeRef1 = ref(null);
|
|
|
+const treeRef2 = ref(null);
|
|
|
+const treeProps = {
|
|
|
+ label: "title",
|
|
|
+ children: "children",
|
|
|
+ isLeaf: (item) => {
|
|
|
+ const isExistForm = Number(item.isExistForm);
|
|
|
+ if (item.hasChildren && isExistForm !== 1) {
|
|
|
+ return false;
|
|
|
+ } else if (item.hasChildren && isExistForm === 1) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+//筛选搜索
|
|
|
+const filterText = ref("");
|
|
|
+const isTreeMode = ref(1); //1懒加载,2全加载
|
|
|
+const treeFilterClick = async () => {
|
|
|
+ if (isNullES(filterText.value)) {
|
|
|
+ isTreeMode.value = 1;
|
|
|
+ } else {
|
|
|
+ isTreeMode.value = 2;
|
|
|
+ await getTreeAllData();
|
|
|
+ treeRef2.value?.treeRef?.filter(filterText.value);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//懒加载树
|
|
|
+const treeLoadNode = async ({ item, level }, resolve) => {
|
|
|
+ const parentId = level === 0 ? 0 : item.id;
|
|
|
+ const { data } = await mainApi.getLazyTree({
|
|
|
+ parentId: parentId,
|
|
|
+ wbsId: formModelName.value,
|
|
|
+ wbsType: "1",
|
|
|
+ });
|
|
|
+ const res = getArrValue(data);
|
|
|
+ res.forEach((item) => {
|
|
|
+ item.isExistForm = !!item.isExistForm;
|
|
|
+ });
|
|
|
+ resolve(res);
|
|
|
+};
|
|
|
+
|
|
|
+//全加载树
|
|
|
+const treeData = ref([]);
|
|
|
+const getTreeAllData = async () => {
|
|
|
+ const { data } = await mainApi.getAllTree({
|
|
|
+ tenantId: "000000",
|
|
|
+ type: 1,
|
|
|
+ wbsId: formModelName.value,
|
|
|
+ });
|
|
|
+ treeData.value = getArrValue(data);
|
|
|
+};
|
|
|
+
|
|
|
+//树节点被点击
|
|
|
+const nodeInfo = ref({});
|
|
|
+const treeNodeIds = ref([]);
|
|
|
+const treeNodeTap = ({ data, keys }) => {
|
|
|
+ nodeInfo.value = data;
|
|
|
+ treeNodeIds.value = keys;
|
|
|
+ getNodeTable(data.id);
|
|
|
+};
|
|
|
+
|
|
|
+//获取清表信息
|
|
|
+const nodeTableColumn = [
|
|
|
+ { key: "tableName", name: "已有元素表名称" },
|
|
|
+ { key: "action", name: "操作", width: 90, align: "center" },
|
|
|
+];
|
|
|
+const nodeTableData = ref([]);
|
|
|
+const getNodeTable = async (id) => {
|
|
|
+ const { data } = await mainApi.getNodeTables({
|
|
|
+ nodeId: nodeInfo.value.id,
|
|
|
+ excelTabId: dataInfo.value.id,
|
|
|
+ });
|
|
|
+ const res = getArrValue(data);
|
|
|
+ for (let i = 0; i < res.length; i++) {
|
|
|
+ res[i].checknd = Number(res[i].isLinkTable) === 2;
|
|
|
+ }
|
|
|
+ nodeTableData.value = res;
|
|
|
+};
|
|
|
+
|
|
|
+//选择关联
|
|
|
+const rowLinkClick = async (row) => {
|
|
|
+ const { isRes } = await mainApi.saveLinkTableInfo({
|
|
|
+ type: 1,
|
|
|
+ linkids: row.id,
|
|
|
+ tabId: dataInfo.value.id,
|
|
|
+ wbsId: formModelName.value,
|
|
|
+ });
|
|
|
+ if (!isRes) return;
|
|
|
+ row.checknd = true;
|
|
|
+ row.isLinkTable = 2;
|
|
|
+};
|
|
|
+
|
|
|
+//取消关联
|
|
|
+const rowUnlinkClick = async (row) => {
|
|
|
+ const { isRes } = await mainApi.cancelRelation({
|
|
|
+ type: 4,
|
|
|
+ linkids: row.id,
|
|
|
+ tabId: dataInfo.value.id,
|
|
|
+ wbsId: formModelName.value,
|
|
|
+ });
|
|
|
+ if (!isRes) return;
|
|
|
+ row.checknd = false;
|
|
|
+ row.isLinkTable = 1;
|
|
|
+};
|
|
|
+
|
|
|
+//选项卡
|
|
|
+const tabsKey = ref("1");
|
|
|
+const tabsData = ref([
|
|
|
+ { key: "1", name: "关联元素表" },
|
|
|
+ { key: "2", name: "新增元素表" },
|
|
|
+]);
|
|
|
+const tabsChange = async ({ key }) => {
|
|
|
+ tabsKey.value = key;
|
|
|
+ const form = getObjValue(dataInfo.value);
|
|
|
+ const tree = getObjValue(nodeInfo.value);
|
|
|
+ console.log(form, "form");
|
|
|
+ console.log(tree, "tree");
|
|
|
+
|
|
|
+ //默认表单数据
|
|
|
+ formModel.value = {
|
|
|
+ wbsId: formModelName.value,
|
|
|
+ parentId: tree.id,
|
|
|
+ nodeName: form.title,
|
|
|
+ excelTabId: form.id,
|
|
|
+ elementList: tableData.value,
|
|
|
+ };
|
|
|
+ //判断当前选项卡
|
|
|
+ if (key === "1") {
|
|
|
+ formModel.value.submitStatus = 1;
|
|
|
+ getNodeTable(nodeInfo.value.id).then();
|
|
|
+ } else if (key === "2") {
|
|
|
+ //默认表单数据
|
|
|
+ formModel.value.submitStatus = 2;
|
|
|
+ //获取下拉数据
|
|
|
+ excelTypeData.value = await getDictionaryData("table_type");
|
|
|
+ ownerTypeList.value = await getDictionaryData("owner_type");
|
|
|
+ //设置默认类型
|
|
|
+ formModel.value.tableType = getDictionaryVal(
|
|
|
+ excelTypeData.value,
|
|
|
+ form.tabType
|
|
|
+ );
|
|
|
+ formModel.value.tableOwner = getDictionaryVal(
|
|
|
+ ownerTypeList.value,
|
|
|
+ form.tabOwner
|
|
|
+ );
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const excelTypeData = ref([]);
|
|
|
+const ownerTypeList = ref([]);
|
|
|
+
|
|
|
+//基础表单
|
|
|
+const formRef = ref(null);
|
|
|
+const formModel = ref({});
|
|
|
+const formRules = {
|
|
|
+ nodeName: {
|
|
|
+ required: true,
|
|
|
+ trigger: "blur",
|
|
|
+ message: "请输入元素表名",
|
|
|
+ },
|
|
|
+ tableType: {
|
|
|
+ required: true,
|
|
|
+ trigger: "blur",
|
|
|
+ message: "请选择清表类型",
|
|
|
+ },
|
|
|
+ tableOwner: {
|
|
|
+ required: true,
|
|
|
+ trigger: "blur",
|
|
|
+ message: "请选择所属方",
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+//提交
|
|
|
+const submitLoading = ref(false);
|
|
|
+const dialogSubmit = async () => {
|
|
|
+ const isForm = await formValidate(formRef.value);
|
|
|
+ if (!isForm) return false;
|
|
|
+ if (tabsKey.value === "1") {
|
|
|
+ submitLoading.value = true;
|
|
|
+ const { isRes } = await mainApi.submitExcelElement(formModel.value);
|
|
|
+ submitLoading.value = false;
|
|
|
+ if (!isRes) return;
|
|
|
+ window.$message.success("操作成功");
|
|
|
+ emit("finish");
|
|
|
+ } else {
|
|
|
+ submitLoading.value = true;
|
|
|
+ let nodeIds1, nodeIds2;
|
|
|
+ if (treeRef1.value) {
|
|
|
+ nodeIds1 = treeRef1.value?.treeRef?.getCheckedKeys();
|
|
|
+ }
|
|
|
+ if (treeRef1.value) {
|
|
|
+ nodeIds2 = treeRef2.value?.treeRef?.getCheckedKeys();
|
|
|
+ }
|
|
|
+ const selectNodeIds = uniqueArr(nodeIds1, nodeIds2);
|
|
|
+ if (selectNodeIds.length <= 0) {
|
|
|
+ window?.$message.warning("至少勾选一个节点");
|
|
|
+ submitLoading.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ formModel.value.nodeIds = selectNodeIds;
|
|
|
+ const { isRes } = await mainApi.submitExcelElement(formModel.value);
|
|
|
+ submitLoading.value = false;
|
|
|
+ if (!isRes) return;
|
|
|
+ window.$message.success("操作成功");
|
|
|
+ dialogClose();
|
|
|
+ emit("finish");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//数组去重
|
|
|
+const uniqueArr = (arr1, arr2) => {
|
|
|
+ //合并两个数组
|
|
|
+ arr1.push(...arr2); //或者arr1 = [...arr1,...arr2]
|
|
|
+ //去重
|
|
|
+ return Array.from(new Set(arr1)); //let arr3 = [...new Set(arr1)]
|
|
|
+};
|
|
|
+
|
|
|
+//关闭弹窗
|
|
|
+const dialogClose = () => {
|
|
|
+ isShow.value = false;
|
|
|
+ submitLoading.value = false;
|
|
|
+ emit("close");
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.hc-exctab-element-web-temp-box {
|
|
|
+ .left {
|
|
|
+ position: relative;
|
|
|
+ border-right: 1px solid #eee;
|
|
|
+ padding: 12px 12px 12px 0;
|
|
|
+ }
|
|
|
+ .right {
|
|
|
+ position: relative;
|
|
|
+ padding: 12px 0 12px 12px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.el-overlay-dialog
|
|
|
+ .el-dialog.hc-new-dialog.hc-exctab-element-web-temp
|
|
|
+ .el-dialog__body
|
|
|
+ .hc-new-dialog-body {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+.el-overlay-dialog
|
|
|
+ .hc-exctab-element-web-temp-box
|
|
|
+ .el-card.hc-card-box.hc-new-card-box {
|
|
|
+ --el-card-bg-color: transparent;
|
|
|
+ --el-card-padding: 0;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+.hc-exctab-element-web-temp-box
|
|
|
+ .hc-div-new-card-box.hc-tab-card-box
|
|
|
+ .el-card
|
|
|
+ .hc-card-header-box {
|
|
|
+ margin-top: 0;
|
|
|
+}
|
|
|
+.hc-exctab-element-web-temp-box
|
|
|
+ .hc-div-new-card-box.hc-tab-card-box
|
|
|
+ .el-card
|
|
|
+ .tab-card-header-tabs
|
|
|
+ .item {
|
|
|
+ height: 30px;
|
|
|
+}
|
|
|
+</style>
|