8
0
duy 5 сар өмнө
parent
commit
5efc634a26

+ 246 - 0
src/views/project/list/file-title-dialog.vue

@@ -0,0 +1,246 @@
+<template>
+    <!-- 文件题名全局配置 -->
+    <hc-dialog
+        v-model="dialogVisible"
+        title="文件题名全局配置"
+        widths="60%"
+        is-table
+        @close="closeDialog"
+    >
+        <div class="flexEnd">
+            <HcIcon
+                name="add"
+                style="font-size: 24px; color: rgb(37, 193, 99); cursor: pointer"
+                @click="addRow"
+            />
+            <HcIcon
+                name="refresh"
+                style="font-size: 24px; color: rgb(37, 193, 99); cursor: pointer"
+                @click="refreshRow"
+            />
+        </div>
+    
+      
+        <div style="height: calc(100% - 60px);">
+            <hc-table
+                v-loading="fileTableLoading"
+                :datas="fileTableData"
+                :column="tableColumn"
+          
+                align="center"
+            >
+                <template #ruleName="{ row }">
+                    <el-select
+                        v-if="row.isEdit"
+                      
+                        v-model="row.ruleName"
+                        multiple
+                        placeholder="请选择"
+                        style="width: 240px"
+                        @change="changeRoleName($event, row)"
+                    >
+                        <el-option
+                            v-for="item in nodeTypelist"
+                            :key="item.id"
+                            :label="item.dictValue"
+                            :value="item.dictKey"
+                        />
+                    </el-select>
+                    <span v-else>
+                        <el-tag v-for="item in row.roleNameVal" :key="item" class="mr-1">{{ item }}</el-tag>
+                    </span>
+                </template>
+
+                <template #ruleSize="{ row }">
+                    <div v-if="isShowSize">
+                        <span v-if="row.type === 1" :class="{ orange: row.isEdit }" @click="chooseFile(row)">所有节点</span>
+                        <div v-else>
+                            <el-link v-if="!row.ruleSizeVal" type="warning" @click="chooseFile(row)">选择题名范围</el-link>
+                            <span v-else :class="{ orange: row.isEdit }" @click="chooseFile(row)">{{ row.ruleSizeVal }}</span>
+                        </div>
+                    </div>
+                </template>
+
+                <template #action="{ row }">
+                    <el-link
+                        v-if="!row.isEdit"
+                        type="primary"
+                        class="mg-r-10"
+                        @click="editRow(row)"
+                    >
+                        编辑
+                    </el-link>
+                    <el-link
+                        v-else
+                        type="primary"
+                        class="mg-r-10"
+                        @click="saveRow(row)"
+                    >
+                        保存
+                    </el-link>
+                    <el-link
+                        type="danger"
+                        @click="delRow(row)"
+                    >
+                        删除
+                    </el-link>
+                </template>
+            </hc-table>
+        </div>
+
+        <template #footer>
+            <el-button @click="closeDialog">取消</el-button>
+            <el-button type="primary" @click="batchsaveFileSize">
+                保存
+            </el-button>
+        </template>
+    </hc-dialog>
+</template>
+
+<script setup>
+import { nextTick, ref } from 'vue'
+
+import privateApi from '~api/wbs/private'
+import { getArrValue } from 'js-fast-way'
+import { getDictionary } from '~api/other'
+const props = defineProps({
+    projectInfo: {
+        type: Object,
+        default: () => ({}),
+    },
+})
+// 定义组件名称
+defineOptions({
+    name: 'FileTitleDialog',
+})
+const dialogVisible = ref(false)
+const fileTableLoading = ref(false)
+const fileTableData = ref([])
+const nodeTypelist = ref([])
+const isShowSize = ref(true)
+
+const projectId = ref(props.projectInfo.id || '')
+// 表格列配置
+const tableColumn = ref([
+    { key: 'ruleName', name: '文件题名规则' },
+    { key: 'ruleSize', name: '文件题名范围' },
+    { key: 'action', name: '操作', width: 150 },
+])
+
+
+// 获取节点类型列表
+const getNodeTypelist = async () => {
+    const { data } = await getDictionary({ code:'name_rule' })
+    nodeTypelist.value = getArrValue(data)
+
+}
+//获取文件题名规则
+const getFileTableData = async () => {
+    const { data } = await privateApi.GetNameRule(
+        { projectId:projectId.value },
+    )
+    fileTableData.value = getArrValue(data)
+    fileTableData.value.forEach((element) => {
+            element.roleNameVal = element.nameRule.split(',')
+            element.ruleName = element.nameVaule.split('-')
+            if (element.type === 2) {
+              const list = element.list
+              let arr = []
+              let arrId = []
+              list.forEach((ele) => {
+                arr.push(ele.nodeName)
+                arrId.push(ele.nodeId)
+              })
+              element.ruleSizeVal = arr.join('、')
+              element.ruleSizeValId = arrId
+            } else {
+              element.ruleSizeVal = ''
+              element.ruleSizeValId = ''
+            }
+          })
+}
+// 显示弹窗
+const show = async () => {
+    await nextTick()
+    dialogVisible.value = true
+    getNodeTypelist()
+    getFileTableData()
+}
+
+// 关闭弹窗
+const closeDialog = () => {
+    dialogVisible.value = false
+}
+
+// 添加行
+const addRow = () => {
+    fileTableData.value.push({
+        isEdit: true,
+        ruleName: [],
+        roleNameVal: [],
+        type: 2,
+    })
+}
+
+// 刷新
+const refreshRow = () => {
+    // TODO: 实现刷新逻辑
+}
+
+// 编辑行
+const editRow = (row) => {
+    row.isEdit = true
+}
+
+// 保存行
+const saveRow = (row) => {
+    row.isEdit = false
+    row.roleNameVal = row.ruleName.map(key => {
+        const item = nodeTypelist.value.find(i => i.dictKey === key)
+        return item?.dictValue || key
+    })
+}
+
+// 删除行
+const delRow = (row) => {
+    const index = fileTableData.value.indexOf(row)
+    if (index > -1) {
+        fileTableData.value.splice(index, 1)
+    }
+}
+
+// 选择文件
+const chooseFile = (row) => {
+    if (!row.isEdit) return
+    // TODO: 实现选择文件逻辑
+}
+
+// 改变规则名称
+const changeRoleName = (value, row) => {
+    row.ruleName = value
+}
+
+// 批量保存
+const batchsaveFileSize = () => {
+    // TODO: 实现批量保存逻辑
+}
+
+defineExpose({
+    show,
+})
+</script>
+
+<style lang="scss" scoped>
+.flexEnd {
+    display: flex;
+    justify-content: flex-end;
+    margin-bottom: 10px;
+    gap: 8px;
+    float: right;
+  
+}
+.orange{
+    color: orange;
+    cursor: pointer;
+}
+</style>

+ 83 - 83
src/views/project/list/independent/allocateWbs.vue

@@ -3,10 +3,10 @@
         v-model="isShow"
         title="分配WBS"
         widths="56rem"
-        isTable
+        is-table
+        :loading="submitLoading"
         @close="dialogClose"
         @save="submitClick"
-        :loading="submitLoading"
     >
         <div v-loading="treeLoading">
             <el-scrollbar>
@@ -16,8 +16,8 @@
                     lazy
                     accordion
                     highlight-current
-                    @node-click="treeClick"
                     :default-checked-keys="checkedLinkNodesKeys"
+                    @node-click="treeClick"
                 >
                     <template #default="{ node, data }">
                         <span
@@ -26,11 +26,10 @@
                         >
                             <span>
                                 <el-checkbox
-                                    v-model="data.checked"
                                     v-if="!data.hasChildren"
+                                    v-model="data.checked"
                                     @change="handleCheckChange($event, data)"
-                                ></el-checkbox
-                            ></span>
+                                /></span>
                             {{ node.label }}
                         </span>
                     </template>
@@ -39,32 +38,26 @@
         </div>
     </hc-dialog>
 </template>
+
 <script setup>
-import { ref, watch, nextTick } from "vue";
-import mainApi from "~api/desk/wbs";
-import privateApi from "~api/wbs/private";
-import { arrToId, getArrValue, getObjValue } from "js-fast-way";
-import { useAppStore } from "~src/store";
+import { nextTick, ref, watch } from 'vue'
+import mainApi from '~api/desk/wbs'
+import privateApi from '~api/wbs/private'
+import { arrToId, getArrValue, getObjValue } from 'js-fast-way'
+import { useAppStore } from '~src/store'
 
-//事件
-const emit = defineEmits(["close"]);
-//双向绑定
-// eslint-disable-next-line no-undef
-const isShow = defineModel("modelValue", {
-    default: false,
-});
 const props = defineProps({
     projectId: {
         type: String,
-        default: "",
+        default: '',
     },
     wbsType: {
         type: [String, Number],
-        default: "",
+        default: '',
     },
     wbsId: {
         type: [String, Number],
-        default: "",
+        default: '',
     },
     data: {
         type: Object,
@@ -72,74 +65,81 @@ const props = defineProps({
     },
     type: {
         type: [String, Number],
-        default: "0", //私有wbs为1,独立表单库为0
+        default: '0', //私有wbs为1,独立表单库为0
     },
-});
-const store = useAppStore();
-const userInfo = ref(store.getUserInfo);
+})
+//事件
+const emit = defineEmits(['close'])
+//双向绑定
+// eslint-disable-next-line no-undef
+const isShow = defineModel('modelValue', {
+    default: false,
+})
+const store = useAppStore()
+const userInfo = ref(store.getUserInfo)
 watch(
     () => store.getUserInfo,
     (info) => {
-        userInfo.value = info;
+        userInfo.value = info
     },
-    { immediate: true, deep: true }
-);
-const projectId = ref(props.projectId);
-const wbsId = ref(props.wbsId);
-const wbsType = ref(props.wbsType);
-const dataInfo = ref(props.data);
-const type = ref(props.type);
+    { immediate: true, deep: true },
+)
+const projectId = ref(props.projectId)
+const wbsId = ref(props.wbsId)
+const wbsType = ref(props.wbsType)
+const dataInfo = ref(props.data)
+const type = ref(props.type)
 //监听数据
 watch(
     () => [props.projectId, props.wbsId, props.wbsType, props.data, props.type],
     ([pid, wid, wtype, info, tpe]) => {
-        projectId.value = pid;
-        wbsId.value = wid;
-        wbsType.value = wtype;
-        dataInfo.value = info;
-        type.value = tpe;
+        projectId.value = pid
+        wbsId.value = wid
+        wbsType.value = wtype
+        dataInfo.value = info
+        type.value = tpe
     },
-    { deep: true }
-);
+    { deep: true },
+)
 //监听显示
 watch(isShow, (val) => {
-    selectData.value = [];
+    selectData.value = []
     if (val) {
         if (type.value === 1) {
-            getLinekNodeTreelistData();
+            getLinekNodeTreelistData()
         }
     } else {
-        emit("close");
+        emit('close')
     }
-});
+})
 //获取关联的节点
-const checkedLinkNodesKeys = ref([]);
+const checkedLinkNodesKeys = ref([])
 const getLinekNodeTreelistData = async () => {
     const { data } = await privateApi.LinekNodeTreelist({
         pkeyid: dataInfo.value.pkeyId,
-    });
-    checkedLinkNodesKeys.value = getArrValue(data);
-};
+    })
+    checkedLinkNodesKeys.value = getArrValue(data)
+}
 //关闭弹窗
 const dialogClose = () => {
-    selectData.value = [];
-    isShow.value = false;
-    emit("close");
-};
+    selectData.value = []
+    isShow.value = false
+    emit('close')
+}
 //树
 const treeProps = {
-    label: "title",
+    label: 'title',
     isLeaf: (item) => {
-        return !item.hasChildren;
+        return !item.hasChildren
     },
-};
+}
 
 //懒加载树
-const treeLoading = ref(false);
+const treeLoading = ref(false)
 const treeLoad = async (node, resolve) => {
-    const { tenant_id } = getObjValue(userInfo.value);
-    treeLoading.value = true;
-    const parentId = node.level === 0 ? 0 : node.data.id;
+    const { tenant_id } = getObjValue(userInfo.value)
+    treeLoading.value = true
+    const parentId = node.level === 0 ? 0 : node.data.id
 
     const { data } = await privateApi.getLazytree({
         parentId: parentId,
@@ -147,53 +147,53 @@ const treeLoad = async (node, resolve) => {
         tenantId: tenant_id,
         projectId: projectId.value,
         wbsType: wbsType.value,
-    });
-    treeLoading.value = false;
-    resolve(getArrValue(data));
-};
+    })
+    treeLoading.value = false
+    resolve(getArrValue(data))
+}
 
 //树节点被点击
 
-const treeClick = ({ id, type, nodeName }) => {};
-const selectData = ref([]);
+const treeClick = ({ id, type, nodeName }) => {}
+const selectData = ref([])
 const handleCheckChange = (isCheck, data) => {
     if (isCheck) {
-        selectData.value.push(data);
+        selectData.value.push(data)
     } else {
-        const index = selectData.value.indexOf(data);
+        const index = selectData.value.indexOf(data)
         if (index !== -1) {
-            selectData.value.splice(index, 1);
+            selectData.value.splice(index, 1)
         }
     }
-};
-const submitLoading = ref(false);
+}
+const submitLoading = ref(false)
 const submitClick = async () => {
-    const nodesIdArray = selectData.value.map((obj) => obj.primaryKeyId);
-    const commaSeparatedIds = nodesIdArray.join(","); // 使用逗号连接数组中的所有元素
+    const nodesIdArray = selectData.value.map((obj) => obj.primaryKeyId)
+    const commaSeparatedIds = nodesIdArray.join(',') // 使用逗号连接数组中的所有元素
 
     if (type.value === 1) {
-        submitLoading.value = true;
+        submitLoading.value = true
         const { code, error, msg } = await privateApi.LinekNodeTree({
             nodeids: commaSeparatedIds,
             pkeyid: dataInfo.value.id,
-        });
-        submitLoading.value = false;
+        })
+        submitLoading.value = false
         if (!error && code === 200) {
-            window.$message.success(msg);
-            dialogClose();
+            window.$message.success(msg)
+            dialogClose()
         }
     } else {
-        submitLoading.value = true;
+        submitLoading.value = true
         const { code, error, msg } = await privateApi.syncFormToContractNode({
             nodeIds: commaSeparatedIds,
             projectId: projectId.value,
             primaryKeyId: dataInfo.value.id,
-        });
-        submitLoading.value = false;
+        })
+        submitLoading.value = false
         if (!error && code === 200) {
-            window.$message.success(msg);
-            dialogClose();
+            window.$message.success(msg)
+            dialogClose()
         }
     }
-};
+}
 </script>

+ 20 - 0
src/views/project/list/wbs-tree.vue

@@ -17,6 +17,14 @@
                             </el-dropdown-menu>
                         </template>
                     </el-dropdown>
+                    <el-button 
+                        hc-btn 
+                        type="primary" 
+                        class="ml-3" 
+                        @click="showFileTitleDialog"
+                    >
+                        文件题名(全局)
+                    </el-button>
                     <el-button v-if="isFormSet" class="ml-3" hc-btn type="primary" @click="setIsFormSetValue">表单设置</el-button>
                     <el-button v-else class="ml-3" hc-btn type="primary" @click="setIsFormSetValue">元素设置</el-button>
                     <el-button hc-btn type="danger" @click="nodeParamClick">节点参数</el-button>
@@ -177,6 +185,9 @@
 
         <!-- 分配WBS -->
         <allocateWbs v-model="isAllocateShow" :data="allocateWbsInfo" :project-id="projectInfo.id" :type="1" :wbs-type="isType" />
+
+        <!-- 添加文件题名弹窗组件 -->
+        <FileTitleDialog ref="fileTitleDialogRef" :project-info="projectInfo" />
     </hc-drawer>
 </template>
 
@@ -201,6 +212,7 @@ import tableSort from '../../desk/wbs/table-sort.vue'
 import previewPage from './previewPage.vue'
 import createNewExcel from '../../desk/wbs/create-new-excel.vue'
 import allocateWbs from '../list/independent/allocateWbs.vue'
+import FileTitleDialog from './file-title-dialog.vue'
 
 //接口
 import excelApi from '~api/exctab/exceltab'
@@ -1056,6 +1068,14 @@ const linkNodeClick = async (row) => {
     await nextTick()
     isAllocateShow.value = true
 }
+
+// 文件题名弹窗引用
+const fileTitleDialogRef = ref(null)
+
+// 显示文件题名弹窗
+const showFileTitleDialog = () => {
+    fileTitleDialogRef.value?.show()
+}
 </script>
 
 <style lang="scss" scoped>