duy 1 неделя назад
Родитель
Сommit
9c785e9351

+ 1 - 1
package.json

@@ -25,7 +25,7 @@
         "dayjs": "^1.11.13",
         "echarts": "^5.5.1",
         "element-plus": "^2.8.5",
-        "hc-vue3-ui": "^4.9.6",
+        "hc-vue3-ui": "^4.9.7",
         "js-base64": "^3.7.7",
         "js-cookie": "^3.0.5",
         "js-fast-way": "^0.5.7",

+ 1 - 0
src/api/modules/archiveConfig/archiveConfig.js

@@ -19,4 +19,5 @@ export default {
     }, msg)
   },
 
+
 }

+ 10 - 0
src/api/modules/archiveConfig/tuning.js

@@ -163,4 +163,14 @@ async splitArchive(form, msg = true) {
             responseType: 'blob',
         }, msg)
     },
+
+      ///插卷
+
+    async insertArchives(form, msg = true) {
+      return HcApi({
+        url: '/api/blade-archive/archivesauto/insertArchives',
+        method: 'post',
+        data: form,
+      }, msg)
+  },
 }

+ 408 - 0
src/views/archives/manage/FileInsertModal.vue

@@ -0,0 +1,408 @@
+<template>
+    <hc-new-dialog 
+        v-model="insertDialog" 
+        :loading="insertDialogLoading" 
+        widths="65vw" 
+        @close="insertDialogClose" 
+        @save="insertDialogSave"
+    >
+        <template #header>
+            <div class="text-1xl mt-2 text-center font-bold">
+                文件插卷 
+            </div>
+        </template>
+    
+        <div class="p-4 space-y-6">
+            <!-- 被插卷档号和插入位置选择区 -->
+            <div class="flex">
+                <div class="flex items-center space-x-2">
+                    <span class="w-24 text-gray-700">
+                        被插卷档号:<span class="text-red-500">*</span>
+                    </span>
+                    <el-select 
+                        v-model="insertModal.fileNumber" 
+                        clearable 
+                        placeholder="请选择" 
+                        class="w-200px flex-1"
+                        :class="{ 'border-red-500': validateForm.fileNumberError }"
+                        @change="fileNumberChange"
+                    >
+                        <el-option 
+                            v-for="item in fileNumberOptions" 
+                            :key="item.id" 
+                            :label="item.fileNumber" 
+                            :value="item.id" 
+                        />
+                    </el-select>
+                    <span v-if="validateForm.fileNumberError" class="text-sm text-red-500">
+                        请选择被插卷档号
+                    </span>
+                </div>
+        
+                <div class="ml-8 flex items-center space-x-2">
+                    <span class="w-30 text-gray-700">
+                        文件插入位置:<span class="text-red-500">*</span>
+                    </span>
+                    <el-select 
+                        v-model="insertModal.type" 
+                        placeholder="请选择"
+                        class="w-150px flex-1"
+                        :class="{ 'border-red-500': validateForm.typeError }"
+                    >
+                        <el-option value="1" label="前" />
+                        <el-option value="0" label="后" />
+                    </el-select>
+                    <span v-if="validateForm.typeError" class="text-sm text-red-500">
+                        请选择插入位置
+                    </span>
+                </div>
+            </div>
+      
+            <!-- 说明文字 -->
+            <div class="rounded bg-[#FEF1F1] p-2 text-sm text-red">
+                点击下方文件行,将在该文件的{{ insertModal.type === '1' ? '前' : '后' }}插入选中的文件,可进行拖动、点图标进行排序调整
+            </div>
+      
+            <!-- 文件列表表格 -->
+            <div class="overflow-hidden border">
+                <HcTable
+                    ref="tableRef" 
+                 
+                    :check-style="{ width: 29 }"
+                    :column="tableColumn"
+                    :datas="tableData"
+                    :index-style="{ width: 70 }"
+                    :is-arr-index="false"
+                    :loading="tableLoading"
+                    is-row-drop ui="hc-table-row-drop" is-new
+                    :is-current-row="false"
+                    :row-style="tableRowStyle"
+                    @row-drop="sortTableRowDrop"
+                    @selection-change="handleSelectionChange"
+                    @row-click="handleRowClick"
+                >
+                    <!-- 排序操作按钮 -->
+                    <template #action="{ index }">
+                        <span class="text-link text-xl" @click="upSortClick(index)">
+                            <HcIcon fill name="arrow-up" />
+                        </span>
+                        <span class="text-link ml-2 text-xl" @click="downSortClick(index)">
+                            <HcIcon fill name="arrow-down" />
+                        </span>
+                    </template>
+                </HcTable>
+            </div>
+        </div>
+    </hc-new-dialog>
+</template>
+
+<script setup>
+import { arrToId, deepClone, getArrValue } from 'js-fast-way'
+import { onMounted, reactive, ref, watch } from 'vue'
+import tuningApi from '~api/archiveConfig/tuning.js'
+import { useAppStore } from '~src/store'
+
+const useAppState = useAppStore()
+const projectId = ref(useAppState.getProjectId)
+const contractId = ref(useAppState.getContractId)
+// 弹窗控制变量
+const insertDialog = ref(false)
+const insertDialogLoading = ref(false)
+const insertModal = reactive({
+  fileNumber: '', // 被插卷档号
+  type: '', // 插入位置,初始化为空,确保必须选择
+})
+
+// 验证状态
+const validateForm = reactive({
+  fileNumberError: false,
+  typeError: false,
+})
+
+// 档号选项
+const fileNumberOptions = ref([])
+//获取档号
+const fileNumberLoad = ref(false)
+
+const getFileNumberOptions = async () => {
+    fileNumberLoad.value = true
+    const { error, code, data } = await tuningApi.pageByArchive({
+        size:5000,
+        current:1,
+        projectId: projectId.value,
+        contractId: contractId.value,
+        isArchive: 1,
+        nodeIds:nodeIds.value,
+    })
+    fileNumberLoad.value = false
+    if (!error && code === 200) {
+        fileNumberOptions.value = getArrValue(data?.records)
+    } else {
+        fileNumberOptions.value = []
+    }
+}
+
+//获取表格数据
+const numberId = ref('')
+const fileNumberChange = (val)=>{
+  // 选择档号后清除错误状态
+  validateForm.fileNumberError = false
+  numberId.value = val
+if (val) {
+    loadTableData()
+}
+}
+
+// 监听插入位置变化,清除错误状态
+watch(() => insertModal.type, () => {
+  validateForm.typeError = false
+})
+
+// 表格配置
+const tableRef = ref(null)
+const tableLoading = ref(false)
+const tableData = ref([])
+
+// 表格列配置
+const tableColumn = ref([
+  { key: 'fileNumber', name: '文件编号', width: 180 },
+  { key: 'fileName', name: '文件名称' },
+  { key: 'action', name: '排序', width: 100 },
+])
+
+// 选中的文件
+const selectedFiles = ref([])
+// 当前点击的行ID
+const currentRowId = ref(null)
+
+// 根据ID获取行索引的方法
+const getRowIndexById = (id) => {
+  return tableData.value.findIndex(row => row.id === id)
+}
+
+// 表格选择变化
+const handleSelectionChange = (selection) => {
+  selectedFiles.value = selection
+}
+
+// 行点击事件 - 精确插入逻辑
+const handleRowClick = ({ row }) => {
+  if (!insertModal.type) {
+    window?.$message?.error('请选择插入位置')
+    return
+  }
+  // 记录当前点击行的ID
+  currentRowId.value = row.id
+  tableRef.value?.toggleRowSelection(row)
+  
+  // 如果有要插入的行数据,则执行插入操作
+  if (insertRows.value && insertRows.value.length > 0) {
+    // 获取当前行ID对应的索引
+    const index = getRowIndexById(row.id)
+    
+    if (index === -1) {
+      window?.$message?.error('未找到指定行')
+      return
+    }
+    
+    // 深拷贝要插入的数据,避免引用问题
+    const rowsToInsert = JSON.parse(JSON.stringify(insertRows.value))
+    
+    // 生成新的ID(实际项目中可能由后端生成)
+    const newRows = rowsToInsert.map(item => ({
+      ...item,
+      id: Date.now() + Math.floor(Math.random() * 1000), // 简单的ID生成策略
+    }))
+    
+    // 根据选择的位置插入数据
+    if (insertModal.type === '1') {
+      // 插入到当前行之前
+      tableData.value.splice(index, 0, ...newRows)
+      window?.$message?.success(`已在第${index + 1}行的文件前插入 ${newRows.length} 个文件`)
+    } else {
+      // 插入到当前行之后
+      tableData.value.splice(index + 1, 0, ...newRows)
+      window?.$message?.success(`已在ID为${index + 1}的文件后插入 ${newRows.length} 个文件`)
+    }
+    
+    // 清空插入数据,避免重复插入
+    insertRows.value = []
+  }
+}
+
+// 移动行 - 上移
+const downSortClick = (index) => {
+  const indexs = index + 1
+  const data = [...tableData.value] // 创建副本避免直接修改源数据
+  if (indexs !== data.length) {
+    // 提取要移动的行(保留所有属性,包括inType)
+    const tmp = data.splice(indexs, 1)[0]
+    // 插入到新位置
+    tableData.value = [...data.slice(0, index), tmp, ...data.slice(index)]
+  } else {
+    window?.$message?.warning('已经处于置底,无法下移')
+  }
+}
+
+// 移动行 - 下移
+const upSortClick = (index) => {
+  const data = [...tableData.value] // 创建副本避免直接修改源数据
+  if (index !== 0) {
+    // 提取要移动的行(保留所有属性,包括inType)
+    const tmp = data.splice(index - 1, 1)[0]
+    // 插入到新位置
+    tableData.value = [...data.slice(0, index), tmp, ...data.slice(index)]
+  } else {
+    window?.$message?.warning('已经处于置顶,无法上移')
+  }
+}
+
+// 打开弹窗
+const insertRows = ref([])
+const nodeIds = ref('')
+const archiveId = ref('')
+const openInsertDialog = (rows, fromId, aId) => {
+  insertDialog.value = true
+  insertRows.value = rows || [] // 接收要插入的行数据
+  insertRows.value.forEach(row => {
+    row.inType = 1 // 标记为插入的数据
+  })
+  nodeIds.value = fromId
+  archiveId.value = aId
+
+  getFileNumberOptions() // 加载文件编号选项
+
+}
+
+//设置某一行的样式
+const tableRowStyle = ({ row }) => {
+  // 只根据inType属性判断样式,确保排序后依然有效
+  if (row?.inType === 1) {
+    return 'color: red;'
+  }
+}
+
+// 加载表格数据
+const loadTableData = async () => {
+  tableLoading.value = true
+  const { error, code, data } = await tuningApi.getarchiveFilePage({
+    current: 1,
+    size: 5000,
+    total:0,
+    archiveId: numberId.value,
+  })
+  tableLoading.value = false
+  if (!error && code === 200) {
+    tableData.value = getArrValue(data['records'])
+  } else {
+    tableData.value = []
+  }
+}
+
+// 关闭弹窗
+const insertDialogClose = () => {
+  tableData.value = []
+  insertDialog.value = false
+  resetForm()
+}
+
+// 表单验证方法
+const validateRequiredFields = () => {
+  let isValid = true
+  
+  // 验证被插卷档号
+  if (!insertModal.fileNumber) {
+    validateForm.fileNumberError = true
+    isValid = false
+  } else {
+    validateForm.fileNumberError = false
+  }
+  
+  // 验证插入位置
+  if (!insertModal.type) {
+    validateForm.typeError = true
+    isValid = false
+  } else {
+    validateForm.typeError = false
+  }
+  
+  return isValid
+}
+
+// 保存插卷设置
+const insertDialogSave = async () => {
+  // 先验证必填项
+  if (!validateRequiredFields()) {
+    window?.$message?.warning('请完善必填信息')
+    return
+  }
+  
+  if (selectedFiles.value.length === 0) {
+    window?.$message?.warning('请选择文件')
+    return
+  }
+  
+  // 准备提交的数据,保留inType信息
+  const submitData = {
+    targetId: insertModal.fileNumber,
+    sourceId: archiveId.value,
+    targetIndexFileId:currentRowId.value,
+    type: insertModal.type,
+    sourceArchiveFileIds: arrToId(selectedFiles.value),
+    sortFileList	: arrToId(tableData.value),
+  }
+  insertDialogLoading.value = true
+    const { error, code, msg } = await tuningApi.insertArchives(submitData)
+      insertDialogLoading.value = false
+  tableLoading.value = false
+  if (!error && code === 200) {
+    window?.$message?.success(msg)
+         insertDialog.value = false
+      resetForm()
+  } 
+}
+
+// 重置表单
+const resetForm = () => {
+  insertModal.fileNumber = ''
+  insertModal.type = '' // 重置为为空
+  selectedFiles.value = []
+  insertRows.value = []
+  currentRowId.value = null
+  // 重置验证状态
+  validateForm.fileNumberError = false
+  validateForm.typeError = false
+  if (tableRef.value) {
+    tableRef.value.clearSelection()
+  }
+}
+
+// 拖动完成 - 关键修复:确保拖动后保留inType属性
+const sortTableRowDrop = (rows) => {
+  // 拖动后,使用原数据中的inType属性更新新的排序结果
+  const updatedRows = rows.map(row => {
+    // 查找原数据中对应的行,获取inType属性
+    const originalRow = tableData.value.find(item => item.id === row.id)
+    return {
+      ...row,
+      // 保留原有的inType属性
+      inType: originalRow ? originalRow.inType : row.inType,
+    }
+  })
+  
+  tableData.value = updatedRows
+}
+
+// 暴露方法供外部调用
+defineExpose({
+  openInsertDialog,
+})
+
+onMounted(() => {
+  // 组件挂载时的初始化操作
+})
+</script>
+
+<style scoped>
+
+</style>

+ 37 - 6
src/views/archives/manage/tuning.vue

@@ -132,7 +132,8 @@
                         ref="tableRef" :check-style="{ width: 29 }" :column="tableColumn" :datas="tableData"
                         :index-style="{ width: 70 }" :is-arr-index="false" :loading="tableLoading" :ui="hoverHand ? 'hover-hand' : ''"
                         is-check is-new is-current-row
-                        @selection-change="tableSelection" @row-click="tableRowClick"
+                        :row-style="tableRowStyle" @selection-change="tableSelection"
+                        @row-click="tableRowClick"
                     >
                         <template #name="{ row }">
                             <span class="text-link" :class="row.colourStatus === 2 ? 'text-orange' : ''"> 
@@ -167,18 +168,24 @@
                             <HcIcon class="hc-icon-close text-hover" name="arrow-up-double" style="color:rgb(64, 149, 229);" @mousedown="startDrag($event)" />
                         </el-tooltip>
                         <div>
-                            <HcIcon class="hc-icon-close text-hover" name="edit" style=" color:rgb(64, 149, 229);" @click="batchEditClick(2)" />
-                        
+                            <el-button hc-btn type="success" size="small" :disabled="intableCheckedKeys.length <= 0" @click="insertClick">
+                                插卷
+                            </el-button>
+                            <el-button hc-btn type="primary" size="small" @click="batchEditClick(2)">
+                                编辑
+                            </el-button>
                   
-                         
-                            <HcIcon class="hc-icon-close text-hover" name="close" style=" color:rgb(64, 149, 229);" @click="closetableFile" />
+                            <el-button hc-btn type="warning" size="small" @click="closetableFile(2)">
+                                删除
+                            </el-button>
                         </div>
                     </div>
                     <div v-loading="intableLoading" class="hc-file-table-box">
                         <HcTable
                             ref="tableFileRef" :check-style="{ width: 29 }" :column="innertableColumn" :datas="intableData"
                             :index-style="{ width: 60 }" :loading="intableLoading" is-check is-new
-                            @selection-change="intableSelection"
+                            :row-style="inTableRowStyle"
+                            @selection-change="intableSelection" 
                         >
                             <template #table-column-header-num>
                                 <HcTooltip keys="archives_tuning_btn_sort">
@@ -499,6 +506,10 @@
                 </el-form>
             </div>
         </hc-new-dialog>
+
+        <!-- 插卷弹窗 -->     
+       
+        <FileInsertModal ref="fileInsertModalRef" />
     </hc-body>
 </template>
 
@@ -520,6 +531,7 @@ import { getDictionaryBiz } from '~api/other'
 import CarrySpotChecksDrawer from './carryDrawer/carrySpotChecksDrawer.vue'
 import tasksApi from '~api/tasks/data'
 import { useRouter } from 'vue-router'
+import FileInsertModal from './FileInsertModal.vue'
 
 //变量
 const router = useRouter()
@@ -702,6 +714,19 @@ const intableCheckedKeys = ref([])
 const tableSelection = (rows) => {
     tableCheckedKeys.value = rows
 }
+const tableRowStyle = ({ row }) => {
+  // 只根据inType属性判断样式,确保排序后依然有效
+  if (row?.actionType === 1 || row?.actionType === 2) {
+    return 'color: orange;'
+  }
+}
+
+const inTableRowStyle = ({ row }) => {
+  // 只根据inType属性判断样式,确保排序后依然有效
+  if (row?.pageNum === '') {
+    return 'color: orange;'
+  }
+}
 const intableSelection = (rows) => {
     intableCheckedKeys.value = rows
 }
@@ -1671,6 +1696,12 @@ const saveReplaceCollect = async ()=>{
 }
 const replaceTitleCollect = ref('查找替换')
 const tabPositionCollect = ref('1')
+
+const insertClick = ()=>{
+fileInsertModalRef.value?.openInsertDialog(intableCheckedKeys.value, searchForm.value.nodeIds, checkInid.value)
+}
+
+const fileInsertModalRef = ref(null)
 </script>
 
 <style lang="scss" scoped>

+ 4 - 4
yarn.lock

@@ -2164,10 +2164,10 @@ has-flag@^4.0.0:
   resolved "http://219.151.181.73:9000/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
   integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
 
-hc-vue3-ui@^4.9.6:
-  version "4.9.6"
-  resolved "http://219.151.181.73:9000/hc-vue3-ui/-/hc-vue3-ui-4.9.6.tgz#78ef8a1c69f3baf22db2d5ee6f326169bfddff66"
-  integrity sha512-HxZjSh1NCNKUtl0Q8IqAtkY9AD+EVfeSJiw01i13flFIg42Xf2zKtT/visDTCGpAMsZR2LJZK0VWmE5HVvie1A==
+hc-vue3-ui@^4.9.7:
+  version "4.9.7"
+  resolved "http://219.151.181.73:9000/hc-vue3-ui/-/hc-vue3-ui-4.9.7.tgz#5a394b913a90cccc411bd925f88c175a47010f94"
+  integrity sha512-akFIbgDvKkMT5J8XhS0GdxHQEdVMXdSSyeiRs3OvMnRXw/26+/VCenVeN/IkcW1bKhRPXFCgi+SN2Kva6IElIQ==
   dependencies:
     axios "^1.7.7"
     dayjs "^1.11.13"