Browse Source

第二版,保存功能

xzc 1 day ago
parent
commit
bab40a9097

+ 56 - 1
yudao-ui-admin-vue3/src/components/SsjsonReportViewer/index.vue

@@ -15,6 +15,7 @@ import '@synboy/spreadjs-custom-render/dist/style.css'
 import { getStandardTemplateInfo } from '@/api/pressure2/standard/template'
 import { ExcelApi } from '@/api/pressure2/excel'
 import { DynamicTbValApi } from '@/api/pressure2/dynamictbval'
+import { serializeDataSourceForStorage } from '@/utils/reportUtil'
 import { buildFileUrl } from '@/utils'
 import axios from 'axios'
 import { ElMessage } from 'element-plus'
@@ -24,10 +25,16 @@ defineOptions({ name: 'SsjsonReportViewer' })
 const emit = defineEmits<{
   ready: []
   save: [data: Record<string, any>]
+  saveSuccess: [result: { insId: string; dataSource: Record<string, any>; refId: string }]
+  saveFail: []
 }>()
 
 const previewRef = ref<InstanceType<typeof OptimizedTemplatePreview>>()
 const loading = ref(false)
+// 当前实例ID(从 loadByRefId 的后端响应中获取)
+const currentInsId = ref<string>('')
+// 当前 refId(保存成功事件透传用)
+const currentRefId = ref<string>('')
 
 // SpreadJS 授权(仅设置一次,避免反复赋值)
 const licenseKey = import.meta.env.VITE_SPREADJS_LICENSE_KEY
@@ -279,6 +286,9 @@ const loadByRefId = async (
     //    OptimizedTemplatePreview 根据 bindingPath + formData 渲染,不需要在 workbook 上 setDataSource
     let sheetData: Record<string, any> = {}
     const res = await DynamicTbValApi.getDynamicTbInsAndValByRefId(initData)
+    // 保存实例ID和refId,供保存功能使用
+    currentInsId.value = res.dynamicTbInsRespVO?.id || ''
+    currentRefId.value = initData.refId || ''
     if (res.dynamicTbValRespVOList?.length) {
       res.dynamicTbValRespVOList.forEach((i: any) => {
         const val = i.valValue
@@ -365,7 +375,51 @@ const clearFormData = () => previewRef.value?.clearFormData?.()
 const getUploadFields = () => previewRef.value?.getUploadFields?.()
 
 const handleReady = () => emit('ready')
-const handleSave = (data: Record<string, any>) => emit('save', data)
+
+/**
+ * 保存数据(供父组件通过 ref 调用,或由内部 @save 事件触发)
+ * 参考 SpreadViewer.handleSave:
+ * 1. 收集 OptimizedTemplatePreview 的表单数据(bindingPath → value)
+ * 2. 序列化(对象/数组 → JSON 字符串)
+ * 3. 调用 DynamicTbValApi.saveAllColValue 持久化
+ */
+const handleSave = async () => {
+  if (!currentInsId.value) {
+    ElMessage.warning('缺少实例ID,无法保存')
+    return
+  }
+  loading.value = true
+  try {
+    // 收集表单数据(bindingPath → value,来自各表单组件的双向绑定)
+    const boundData = previewRef.value?.getBoundFormData?.() || {}
+    if (!Object.keys(boundData).length) {
+      ElMessage.warning('没有可保存的数据')
+      loading.value = false
+      return
+    }
+    // 序列化(对象/数组 → JSON 字符串,与 SpreadViewer 保持一致)
+    const serializedData = serializeDataSourceForStorage(boundData)
+    // 调用后端 API 持久化
+    const res = await DynamicTbValApi.saveAllColValue(currentInsId.value, serializedData)
+    if (res) {
+      ElMessage.success('保存成功')
+      emit('saveSuccess', {
+        insId: currentInsId.value,
+        dataSource: serializedData,
+        refId: currentRefId.value
+      })
+    } else {
+      ElMessage.error('保存失败')
+      emit('saveFail')
+    }
+  } catch (e) {
+    console.error('保存失败:', e)
+    ElMessage.error('保存失败')
+    emit('saveFail')
+  } finally {
+    loading.value = false
+  }
+}
 
 onBeforeUnmount(() => {
   if (tempHost) {
@@ -378,6 +432,7 @@ defineExpose({
   loadByTemplateId,
   loadByRefId,
   loadFromConfig,
+  handleSave,
   getBoundFormData,
   setFormData,
   clearFormData,

+ 4 - 5
yudao-ui-admin-vue3/src/views/pressure2/boilerchecker/components/StatusOperationPanel.vue

@@ -123,7 +123,7 @@
         <div ref="pdfPanelRef" class="pdf-panel" >
           <!-- ssjson 模式:自定义渲染葡萄城组件 -->
           <div v-if="showReportPdfType === 'ssjson'" class="!h-full" :style="{ width: pdfContentWidth + 'px'}">
-            <SsjsonReportViewer ref="ssjsonPreviewRef" @save="handleSsjsonSave" />
+            <SsjsonReportViewer ref="ssjsonPreviewRef" @save="handleSsjsonSave" @saveSuccess="saveSuccess" />
           </div>
           <!-- PDF预览区域 -->
           <div v-else class="!h-full" :style="{ width: pdfContentWidth + 'px'}">
@@ -2625,10 +2625,9 @@ const loadSsjsonConfig = async (sourceType: 'record' | 'report' = 'record') => {
   )
 }
 
-// ssjson 自定义渲染组件保存回调
-const handleSsjsonSave = (data: Record<string, any>) => {
-  console.log('ssjson 保存数据:', data)
-  ElMessage.success('保存成功(数据已打印到控制台)')
+// ssjson 自定义渲染组件保存回调(由内部工具栏"保存"按钮触发)
+const handleSsjsonSave = () => {
+  ssjsonPreviewRef.value?.handleSave()
 }
 
 const isCanSyncReportData = computed(() => {

+ 4 - 4
yudao-ui-admin-vue3/src/views/pressure2/pipechecker/components/StatusOperationPanel.vue

@@ -123,7 +123,7 @@
         <div ref="pdfPanelRef" class="pdf-panel" >
           <!-- ssjson 模式:自定义渲染葡萄城组件 -->
           <div v-if="showReportPdfType === 'ssjson'" class="!h-full" :style="{ width: pdfContentWidth + 'px'}">
-            <SsjsonReportViewer ref="ssjsonPreviewRef" @save="handleSsjsonSave" />
+            <SsjsonReportViewer ref="ssjsonPreviewRef" @save="handleSsjsonSave" @saveSuccess="saveSuccess" />
           </div>
           <!-- PDF预览区域 -->
           <div v-else class="!h-full" :style="{ width: pdfContentWidth + 'px'}">
@@ -2490,9 +2490,9 @@ const loadSsjsonConfig = async (sourceType: 'record' | 'report' = 'record') => {
 }
 
 // ssjson 自定义渲染组件保存回调
-const handleSsjsonSave = (data: Record<string, any>) => {
-  console.log('ssjson 保存数据:', data)
-  ElMessage.success('保存成功(数据已打印到控制台)')
+// ssjson 自定义渲染组件保存回调(由内部工具栏"保存"按钮触发)
+const handleSsjsonSave = () => {
+  ssjsonPreviewRef.value?.handleSave()
 }
 
 const isCanSyncReportData = computed(() => {