Jelajahi Sumber

410mathfunc,tacs,fsi

tangjunhao 5 bulan lalu
induk
melakukan
6f2cdf4968

+ 50 - 10
src/views/home.vue

@@ -1092,11 +1092,11 @@
                 <h4 :id="titleId" :class="titleClass">TACS</h4>
               </div>
             </template>
-            <TACS />
+            <TACS ref="Tacsref" />
             <template #footer>
               <div class="dialog-footer">
                 <el-button @click="dialog.Taxs = false">取消</el-button>
-                <el-button type="primary" @click="dialog.Taxs = false">
+                <el-button type="primary" @click="gettacstosave();dialog.Taxs = false">
                   确定
                 </el-button>
               </div>
@@ -1288,7 +1288,7 @@
                 </div>
                 <div class="dialog-footer">
                   <el-button @click="dialog.MathFuncdialog = false">取消</el-button>
-                  <el-button type="primary" @click="; dialog.MathFuncdialog = false">
+                  <el-button type="primary" @click="getmathfunctosave(); dialog.MathFuncdialog = false">
                     确定
                   </el-button>
                 </div>
@@ -1299,7 +1299,7 @@
           <!-- FSI -->
            <el-dialog v-model="dialog.fsidialog" align-center :modal="false" :close-on-click-modal="false"
             :append-to-body="true" draggable :fullscreen="false" :modal-append-to-body="false" modal-class="summary-dlg"
-            :before-close="handleClose" width="670" class="dialog_class bgcolor tianjia sel colortext">
+            :before-close="handleClose" width="570" class="dialog_class bgcolor tianjia sel colortext">
             <template #header="{ titleId, titleClass }">
               <div class="my-header ">
                 <!-- <el-image :src="getImgPath('xuek0.png')" fit="contain"></el-image> -->
@@ -1310,7 +1310,7 @@
             <template #footer>
               <div class="dialog-footer">
                 <el-button @click="dialog.fsidialog = false">取消</el-button>
-                <el-button type="primary" @click=" dialog.fsidialog = false">
+                <el-button type="primary" @click="getfsitosave();dialog.fsidialog = false">
                   确定
                 </el-button>
               </div>
@@ -1728,6 +1728,7 @@ let Toptimizeref=ref();
 let Fsiref=ref();
 let Flightref=ref();
 let MathFuncref=ref();
+let Tacsref=ref();
 let f4ce = ref("优化问题组件");
 let modelban = ref("学科分析组件");
 let undmodel=ref('优化器组件');
@@ -2272,8 +2273,10 @@ const handleClick = (tab, event) => {
 
   tabactive.value = tab.props.name;
   if (tabactive.value == 'User') {
-    vuefval.value.logToObject1();
-    router.replace({ path: '/' })
+    vuefval.value.logToObject1().then(() => {
+      router.replace({ path: '/' });
+      // console.log('跳转到首页');
+    });
   } else {
 
   }
@@ -2438,20 +2441,37 @@ const optimizerfalse = (val) => {
     });
   }else if(name == 'TACS'){
     dialog.value.Taxs = true;
+    nextTick(() => {
+      // 确保 ref 已经初始化
+      if (Tacsref.value) {
+        Tacsref.value.gettacs(pid.value,wid);
+      }
+    });
   }else if(name == '模版'){
     dialog.value.optgroup = true;
     activeadf.value='代理优化器';
   }else if(name == 'Python'){
     dialog.value.Pythonshow = true;
     initPython(wid);
-  }else if(name == 'FUM to FEM'){
+  }else if(name == 'FSI'){
     dialog.value.fsidialog = true;
-    
+    nextTick(() => {
+      // 确保 ref 已经初始化
+      if (Fsiref.value) {
+        Fsiref.value.getfsi(pid.value,wid);
+      }
+    });
   }else if(name == 'Flight'){
     dialog.value.flightdialog = true;
     
   }else if(name == 'MathFunc'){
     dialog.value.MathFuncdialog = true;
+    nextTick(() => {
+      // 确保 ref 已经初始化
+      if (MathFuncref.value) {
+        MathFuncref.value.getmathfunc(pid.value,wid);
+      }
+    });
   }
    else {
     dialog.value.optimizer = false;
@@ -4288,7 +4308,7 @@ const adflowok=(nowid)=>{
   }
 }
 
-// xfoiladflow保存
+// 气动优化xfoiladflow保存
 const getXfoilAdflowsave = (activeadf) => {
   if (activeadf == 'Xfoil') {
     xfoilok(qidongyouhuawid.value);
@@ -4297,6 +4317,26 @@ const getXfoilAdflowsave = (activeadf) => {
   }
 }
 
+// Fsi保存
+const getfsitosave = () => {
+  if (Fsiref.value) {
+    Fsiref.value.getfsisave(pid.value);
+  }
+}
+
+// MathFunc保存
+const getmathfunctosave = () => {
+  if (MathFuncref.value) {
+    MathFuncref.value.getmathfuncsave(pid.value);
+  }
+}
+
+// TACS保存
+const gettacstosave = () => {
+  if (Tacsref.value) {
+    Tacsref.value.gettacssave(pid.value);
+  }
+}
 
 // 云图打开二级弹窗
 let seconddialogshow = ref(false)

+ 81 - 16
src/views/titlecomponent/FSI.vue

@@ -15,26 +15,24 @@
     <div v-if="currentTab1 == '0'" class="eldesign classtable" style="margin-top: 10px">
       <el-form>
         <el-form-item label="最大耦合迭代步:" :label-width="formLabelWidth1">
-          <el-input v-model="fsi.maxIter"></el-input>
+          <el-input v-model="fsi.stepmax"></el-input>
         </el-form-item>
         <el-form-item label="输出每轮迭代结果:" :label-width="formLabelWidth1">
-          <el-input v-model="fsi.result"></el-input>
+          <el-input v-model="fsi.outputsteps"></el-input>
         </el-form-item>
-        <el-form-item label="插值方法:" :label-width="formLabelWidth1">
-          <el-select v-model="fsi.interpolation">
+        <el-form-item label="数据插值方法:" :label-width="formLabelWidth1">
+          <el-select v-model="fsi.method">
             <el-option label="MELD" value="MELD"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="耦合区域" :label-width="formLabelWidth1">
-        </el-form-item>
-        <el-form-item label="气动区域:" :label-width="formLabelWidth1">
-          <el-select v-model="fsi.aeroRegion">
+        <el-form-item label="气动耦合区域:" :label-width="formLabelWidth1">
+          <el-select v-model="fsi.aerogroup">
             <el-option label="wall" value="wall"></el-option>
           </el-select>
         </el-form-item>
-        <el-form-item label="结构区域" :label-width="formLabelWidth1">
-          <el-checkbox label="Skin"></el-checkbox>
-          <el-checkbox label="Spar"></el-checkbox>
+        <el-form-item label="结构耦合区域" :label-width="formLabelWidth1">
+          <el-checkbox v-model="fsi.skin" :true-label=1 :false-label=0>Skin</el-checkbox>
+          <el-checkbox v-model="fsi.spar" :true-label=1 :false-label=0>Spar</el-checkbox>
         </el-form-item>
       </el-form>
     </div>
@@ -49,13 +47,17 @@ import { request, uploadFile } from "@/utils/request"
 import configParams from "@/assets/img/configParams.png";
 let currentTab1 = ref(0)
 let formLabelWidth1 = ref(190)
+let pid = ref()
+let wid = ref()
+let fsiid = ref()
 
 let fsi = ref({
-  maxIter: 2,
-  result: 1,
-  interpolation: "MELD",
-  aeroRegion: "wall",
-  
+  stepmax: 2,
+  outputsteps: 0,
+  method: "MELD",
+  aerogroup: "wall",
+  skin: 1,
+  spar: 1,
 })
 
 let tabslist1 = ref([
@@ -66,4 +68,67 @@ const selectTab1 = (index) => {
   currentTab1.value = index
 }
 
+const getfsi = (id,nowid) => {
+  pid.value = id;
+  if(nowid){
+    wid.value = nowid;
+  }
+  // console.log('pid-1:',pid.value)
+  const params = {
+    transCode: "MDO0069",
+    pid: pid.value,
+    wid: wid.value
+  };
+  request(params).then((res) => {
+    if (res.hasOwnProperty("fsiid")) {
+      getfsiAssign(res);
+    }
+  })
+  .catch((err) => {
+      ElMessage.error('fsi初始化失败')
+    })
+}
+
+const getfsiAssign = (data) => {
+  // console.log('getfsiAssign-data:', data);
+  pid.value = data.pid;
+  fsiid.value = data.fsiid;
+  fsi.value.stepmax = data.stepmax;
+  fsi.value.outputsteps = data.outputsteps;
+  fsi.value.method = data.method;
+  fsi.value.aerogroup = data.aerogroup;
+  fsi.value.skin = data.skin;
+  fsi.value.spar = data.spar;
+}
+
+const getfsisave = (id,nowid) => {
+  if(nowid){
+    wid.value = nowid
+  }
+  pid.value = id;
+  // console.log("pid:",pid.value);
+  const params = {
+    transCode: "MDO0070",
+    pid: pid.value,
+    wid: wid.value,
+    stepmax: fsi.value.stepmax,
+    outputsteps: fsi.value.outputsteps,
+    method: fsi.value.method,
+    aerogroup: fsi.value.aerogroup,
+    skin: fsi.value.skin,
+    spar: fsi.value.spar,
+  };
+  request(params).then((res) => {
+    ElMessage({
+        message: '保存成功',
+        type: 'success',
+      })
+  })
+  .catch((err) => {
+      ElMessage.error('保存失败')
+    })
+}
+
+defineExpose({ getfsi, getfsiAssign, getfsisave })
+
 </script>

+ 100 - 16
src/views/titlecomponent/MathFunc.vue

@@ -13,7 +13,7 @@
       </li>
     </ul>
     <div v-show="currentTab1 == '0'" class="eldesign classtable" style="margin-top: 10px">
-      <el-table :data="xvaluelist" border style="width: 100%; " :header-cell-class-name="headerCellClassName">
+      <el-table :data="inParams" border style="width: 100%; " :header-cell-class-name="headerCellClassName">
           <el-table-column type="index" width="70" label="编号"/>
           <el-table-column prop="name" label="参数名称">
             <!-- <template #default="{ row }">
@@ -28,7 +28,7 @@
           <el-table-column prop="flag" label="启用" width="100">
             <template v-slot="scope">
               <el-checkbox
-                :false-label="-1"
+                :false-label="0"
                 :true-label="1"
                 :label="false"
                 v-model="scope.row.flag"
@@ -39,11 +39,11 @@
     </div>
 
       <div v-show="currentTab1 == '1'" style="margin-top: 10px">
-        <PythonEdit :value="textarea" language="python" />
+        <PythonEdit :value="equation" language="python" />
       </div> 
 
       <div v-show="currentTab1 == '2'" class="eldesign classtable" style="margin-top: 10px">
-        <el-table :data="yvaluelist" border style="width: 100%; height: 280px" :header-cell-class-name="headerCellClassName">
+        <el-table :data="outParams" border style="width: 100%; height: 280px" :header-cell-class-name="headerCellClassName">
           <el-table-column type="index" width="70" label="编号" />
           <el-table-column prop="name" label="参数名称">
             <!-- <template #default="{ row }">
@@ -83,19 +83,23 @@ import MathFuncY from "@/assets/img/MathFuncY.png";
 
 let currentTab1 = ref(0)
 
+let pid = ref();
+let wid = ref();
+let mfcid = ref();
+
 let tabslist1 = ref([
   { id: "0", name: "自变量x", imgSrc: MathFuncX },
   { id: "1", name: "表达式y=F(x)", imgSrc: MathFuncFx },
   { id: "2", name: "因变量y", imgSrc: MathFuncY },
 ])
 
-let xvaluelist = ref([
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
+let inParams = ref([
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
 ])
 
-let textarea = ref(`import os
+let equation = ref(`import os
 import numpy as np
 from surromdao.solver import BaseSolver
 
@@ -107,13 +111,13 @@ class Branin(BaseSolver):
         x = np.zeros(2)
         # x[1] = x[2]`);
 
-let yvaluelist = ref([
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
-  { name: "00", value: 0, flag: 1 },
+let outParams = ref([
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
+  { code:'', name: "00", value: 0, flag: 1 },
 ])
 
 let emit = defineEmits(['selectTab']);
@@ -138,4 +142,84 @@ const headerCellClassName = ({ column }) => {
 };
 
 
+const convertToStringArray = (result, Data) => {
+  console.log('Data:', Data);
+
+  // 安全检查 Data,确保它是一个数组
+  if (!Array.isArray(Data)) {
+    console.error('Data should be an array');
+    return result; // 返回原 result 或者根据需要返回其他默认值
+  }
+
+  result = Data.map(row => {
+    // 获取每一行的 `code`, `name`, `value` 和 `flag`
+    const code = row.code || ' ';
+    const name = row.name || ' ';
+    const value = (row.value === null || row.value === undefined || row.value === '') ? ' ' : row.value;
+    const flag = (row.flag === null || row.flag === undefined || row.flag === '') ? ' ' : row.flag;
+
+    // 将字段连接为一个以逗号分隔的字符串
+    return `${code},${name},${value},${flag}`;
+  }).join(';');  // 每行之间用分号分隔
+
+  return result;
+}
+
+const getmathfunc = (id,nowid) => {
+  pid.value = id;
+  if(nowid){
+    wid.value = nowid;
+  }
+  // console.log('pid-1:',pid.value)
+  const params = {
+    transCode: "MDO0063",
+    pid: pid.value,
+    wid: wid.value
+  };
+  request(params).then((res) => {
+    if (res.hasOwnProperty("mfcid")) {
+      getmathfuncAssign(res);
+    }
+  })
+  .catch((err) => {
+      ElMessage.error('MathFunc初始化失败')
+    })
+}
+
+const getmathfuncAssign = (data) => {
+  // console.log('getxfoilAssign-data:', data);
+  pid.value = data.pid;
+  mfcid.value = data.mfcid;
+  equation.value = data.equation;
+  inParams.value = data.inParams;
+  outParams.value = data.outParams;
+}
+
+const getmathfuncsave = (id,nowid) => {
+  if(nowid){
+    wid.value = nowid
+  }
+  pid.value = id;
+  // console.log("pid:",pid.value);
+  const params = {
+    transCode: "MDO0064",
+    pid: pid.value,
+    wid: wid.value,
+    equation: equation.value,
+    inParams: convertToStringArray([],inParams.value),
+    outParams: convertToStringArray([],outParams.value)
+  };
+  request(params).then((res) => {
+    ElMessage({
+        message: '保存成功',
+        type: 'success',
+      })
+  })
+  .catch((err) => {
+      ElMessage.error('保存失败')
+    })
+}
+
+defineExpose({ getmathfunc, getmathfuncAssign, getmathfuncsave })
+
 </script>

+ 235 - 45
src/views/titlecomponent/TACS.vue

@@ -20,7 +20,7 @@
     >
       <el-form label-position="left">
         <el-form-item label="网格文件:" :label-width="formLabelWidth120">
-          <el-input v-model="tacsFilename">
+          <el-input v-model="fname">
             <template #append>
               <fileUploads
                 :projectId="125"
@@ -47,7 +47,7 @@
     >
       <el-form-item label="分析对象名称:" :label-width="formLabelWidth1">
         <el-input
-          v-model="tacsvalue.objname"
+          v-model="tacsvalue.proname"
           :step="100"
           :min="0"
           :max="1000"
@@ -61,7 +61,7 @@
           </template>
           <el-form-item label="材料密度:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.density"
+              v-model="tacsvalue.rho"
               :step="100"
               :min="0"
               :max="1000"
@@ -70,7 +70,7 @@
           </el-form-item>
           <el-form-item label="杨氏模量:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.ysml"
+              v-model="tacsvalue.e"
               :step="100"
               :min="0"
               :max="1000"
@@ -79,7 +79,7 @@
           </el-form-item>
           <el-form-item label="泊松比:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.ratio"
+              v-model="tacsvalue.nu"
               :step="100"
               :min="0"
               :max="1000"
@@ -88,7 +88,7 @@
           </el-form-item>
           <el-form-item label="屈服应力:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.stress"
+              v-model="tacsvalue.ys"
               :step="100"
               :min="0"
               :max="1000"
@@ -96,9 +96,9 @@
             />
           </el-form-item>
           <el-form-item label="启用FFD参数化:" :label-width="formLabelWidth1">
-            <el-radio-group v-model="tacsvalue.radio">
-              <el-radio label="1">是</el-radio>
-              <el-radio label="0">否</el-radio>
+            <el-radio-group v-model="tacsvalue.useffd">
+              <el-radio :label='1'>是</el-radio>
+              <el-radio :label='0'>否</el-radio>
             </el-radio-group>
           </el-form-item>
         </el-collapse-item>
@@ -108,7 +108,7 @@
           </template>
           <el-form-item label="绝对收敛参数:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.absolute "
+              v-model="tacsvalue.l2convergence "
               :step="100"
               :min="0"
               :max="1000"
@@ -117,7 +117,7 @@
           </el-form-item>
           <el-form-item label="相对收敛参数:" :label-width="formLabelWidth1">
             <el-input
-              v-model="tacsvalue.relative "
+              v-model="tacsvalue.l2convergencerel "
               :step="100"
               :min="0"
               :max="1000"
@@ -131,7 +131,7 @@
     <div v-show="currentTab2 == '1'">
       <div class="eldesign classtable" style="margin-top: 10px">
         <el-table
-          :data="TACSlailiutable"
+          :data="inParams"
           border
           style="width: 100%; "
         >
@@ -143,15 +143,15 @@
             <template v-slot:header>
               <!-- 表头显示复选框 -->
               <el-checkbox
-                :false-label="'-1'"
-                :true-label="'1'"
+                :false-label="0"
+                :true-label="1"
                 :label="false"
-                v-model="thcheckbox"
+                v-model="writesolution"
               />
             </template>
-            <el-table-column prop="data" label="厚度分布" width="100">
+            <el-table-column prop="value" label="厚度分布" width="100">
               <template #default="{ row }">
-                <el-input v-model.number="row.data" />
+                <el-input v-model.number="row.value" />
               </template>
             </el-table-column>
           </el-table-column>
@@ -165,7 +165,7 @@
     <div v-show="currentTab2 == '3'">
       <div class="eldesign classtable" style="margin-top: 10px">
         <el-table
-          :data="TACSfenxitable"
+          :data="outParams"
           border
           style="width: 100%; "
           :header-cell-class-name="headerCellClassName"
@@ -184,8 +184,8 @@
           <el-table-column prop="flag" label="启用" width="100">
             <template v-slot="scope">
               <el-checkbox
-                :false-label="'-1'"
-                :true-label="'1'"
+                :false-label="0"
+                :true-label="1"
                 :label="false"
                 v-model="scope.row.flag"
               />
@@ -203,12 +203,18 @@ import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
 import { Edit, CaretBottom } from "@element-plus/icons-vue"
 import fileUploads from '../components/fileuploads.vue'
 import cloudChart from "../threejsView/index.vue" // 云图
+import { request, uploadFile } from "@/utils/request"
 
 let fid = ref()
 let formLabelWidth1 = ref(170)
 let formLabelWidth120 = ref(120)
 let bdfData = ref()
 let currentTab2=ref(0);
+
+let pid = ref();
+let wid = ref();
+let tacsid = ref();
+
 let tabslist2= ref([
   { id: '0', name: '网格文件' },
   { id: '1', name: '结构参数' },
@@ -223,83 +229,119 @@ const tacsfileSrc = new URL('@/assets/flowimg/ffdFileSave.png', import.meta.url)
 let TACSactiveNames = ref(['1','2']);
 
 let tacsvalue = ref({
-  objname:'CRM',
-  density:'2780.0',
-  ysml:'73.1e9',
-  ratio:'0.33',
-  stress:'262.0e6',
-  radio:'1',
-  absolute:'1e3',
-  relative:'1e3'
+  proname:'CRM',
+  rho:'2780.0',
+  e:'73.1e9',
+  nu:'0.33',
+  ys:'262.0e6',
+  useffd: 1,
+  l2convergence:'1e3',
+  l2convergencerel:'1e3'
 })
 
-let thcheckbox = ref('1')
+let writesolution = ref(1);
 
-let tacsFilename = ref('')
+let fname = ref('')
 
-let TACSlailiutable=ref([
+let inParams=ref([
   {
-    data: '0.995208',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.995208',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.992144',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.992144',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.988525',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.988525',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.984251',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.984251',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.979202',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.979202',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.973236',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.973236',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.966186',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.966186',
+    flag: 1,
     con: ''
   },
   {
-    data: '0.957851',
+    code:'thickness',
+    name: '厚度分布',
+    value: '0.957851',
+    flag: 1,
     con: ''
   },
   {
-    data: '',
+    code:'thickness',
+    name: '厚度分布',
+    value: '',
+    flag: 1,
     con: ''
   },
   {
-    data: '',
+    code:'thickness',
+    name: '厚度分布',
+    value: '',
+    flag: 1,
     con: ''
   },
   {
-    data: '',
+    code:'thickness',
+    name: '厚度分布',
+    value: '',
+    flag: 1,
     con: ''
   },
 ])
 
-let TACSfenxitable=ref([
+let outParams=ref([
   {
+    code:'mass',
     name: '结构质量',
     value: 13972.2123,
     flag:'1'
   },
   {
+    code:'ks_vmfailure',
     name: 'KS聚合应力',
     value: 0.3337,
     flag:'1'
   },
   {
+    code:'maxdeform',
     name: '最大变形',
     value: 0.0,
     flag: '1'
-  }
+  },
 ])
 
 const selectTab2=(index)=>{
@@ -319,8 +361,156 @@ const headerCellClassName = ({ column }) => {
   return '';
 };
 
+const gettacs = (id,nowid) => {
+  pid.value = id;
+  if(nowid){
+    wid.value = nowid;
+  }
+  // console.log('pid-1:',pid.value)
+  const params = {
+    transCode: "MDO0066",
+    pid: pid.value,
+    wid: wid.value
+  };
+  request(params).then((res) => {
+    if (res.hasOwnProperty("tacsid")) {
+      gettacsAssign(res);
+    }
+  })
+  .catch((err) => {
+      console.log('TACS初始化失败err:',err)
+      ElMessage.error('TACS初始化失败')
+    })
+}
+
+const gettacsAssign = (data) => {
+  // console.log('getfsiAssign-data:', data);
+  pid.value = data.pid;
+  tacsid.value = data.tacsid;
+  fid.value = data.fid;
+  fname.value = data.fname;
+  tacsvalue.value.proname = data.proname;
+  tacsvalue.value.rho = data.rho;
+  tacsvalue.value.e = data.e;
+  tacsvalue.value.nu = data.nu;
+  tacsvalue.value.ys = data.ys;
+  tacsvalue.value.useffd = data.useffd;
+  tacsvalue.value.l2convergence = data.l2convergence;
+  tacsvalue.value.l2convergencerel = data.l2convergencerel;
+  writesolution.value = data.writesolution;
+  inParams.value = parseStringToArray(data.inParams);
+  outParams.value = data.outParams;
+}
+
+
+const convertToStringArray = (result, Data) => {
+  console.log('Data:', Data);
+
+  // 安全检查 Data,确保它是一个数组
+  if (!Array.isArray(Data)) {
+    console.error('Data should be an array');
+    return result; // 返回原 result 或者根据需要返回其他默认值
+  }
+
+  result = Data.map(row => {
+    // 获取每一行的 `code`, `name`, `value` 和 `flag`
+    const code = row.code || ' ';
+    const name = row.name || ' ';
+    const value = (row.value === null || row.value === undefined || row.value === '') ? ' ' : row.value;
+    const flag = (row.value === null || row.flag === undefined || row.flag === '') ? ' ' : row.flag;
+
+    // 将字段连接为一个以逗号分隔的字符串
+    return `${code},${name},${value},${flag}`;
+  }).join(';');  // 每行之间用分号分隔
+
+  return result;
+}
+
+// "code,name,value#value#value,flag" 格式的字符串
+const convertToStringArray1 = (result, Data) => {
+  console.log('Data:', Data);
+
+  // 安全检查 Data,确保它是一个数组
+  if (!Array.isArray(Data)) {
+    console.error('Data should be an array');
+    return result; // 返回原 result 或者根据需要返回其他默认值
+  }
+
+  if (Data.length === 0) {
+    return result; // 如果数组为空,直接返回原 result
+  }
+
+  // 获取第一行的 code, name 和 writesolution
+  const code = Data[0].code || ' ';
+  const name = Data[0].name || ' ';
+  const flag = writesolution.value !== undefined && writesolution.value !== null
+  ? writesolution.value
+  : ' ';
+
+  // 收集所有行的 value,用 # 拼接
+  const values = Data.map(row => {
+    return (row.value === null || row.value === undefined || row.value === '') ? ' ' : row.value;
+  }).join('#');
+
+  // 构建最终字符串
+  result = `${code},${name},${values},${flag}`;
+
+  return result;
+}
+
+// 将 "code,name,value#value#value,flag" 格式的字符串转回数组格式
+const parseStringToArray = (inParamsArray) => {
+  if (!Array.isArray(inParamsArray)) return [];
+  
+  return inParamsArray.map(item => {
+    const values = item.value.split('#').map(v => v === ' ' ? '' : v);
+    
+    return values.map(value => ({
+      ...item,        // 保留原对象所有属性
+      value: value,   // 覆盖为单个值
+    }));
+  }).flat(); // 将二维数组展平
+}
+
+const gettacssave = (id,nowid) => {
+  if(nowid){
+    wid.value = nowid
+  }
+  pid.value = id;
+  // console.log("pid:",pid.value);
+  const params = {
+    transCode: "MDO0067",
+    pid: pid.value,
+    wid: wid.value,
+    proname: tacsvalue.value.proname,
+    rho: tacsvalue.value.rho,
+    e: tacsvalue.value.e,
+    nu: tacsvalue.value.nu,
+    ys: tacsvalue.value.ys,
+    useffd: tacsvalue.value.useffd,
+    l2convergence: tacsvalue.value.l2convergence,
+    l2convergencerel: tacsvalue.value.l2convergencerel,
+    writesolution: writesolution.value,
+    fid: fid.value,
+    fname: fname.value,
+    inParams: convertToStringArray1([],inParams.value),
+    outParams: convertToStringArray([],outParams.value)
+  };
+  request(params).then((res) => {
+    ElMessage({
+        message: '保存成功',
+        type: 'success',
+      })
+  })
+  .catch((err) => {
+      ElMessage.error('保存失败')
+    })
+}
+
+defineExpose({ gettacs, gettacsAssign, gettacssave })
+
 const handleFileUploadSuccess = (data) => {
-  tacsFilename.value = data.fname
+  fname.value = data.fname
   fid.value = data.bfid
   console.log("文件上传成功,bfid:", data.bfid, "fname:", data.fname)
   bdfData.value = {

+ 6 - 0
src/views/vuetree/eltree.vue

@@ -47,7 +47,13 @@ onMounted(() => {
 .vue-flow__node-default, .vue-flow__node-input, .vue-flow__node-output{
   width: 60px;
   height: 58px;
+  pointer-events: auto;
 }
+
+.vue-flow__node-default:not(.selected) {
+  z-index: 1 !important; /* 强制设置未选中时的 z-index */
+}
+
 .vue-flow__node.draggable {
     background-color: rgba(0,0,0,0);
 }

+ 75 - 0
src/views/vuetree/eltreeGroup.vue

@@ -0,0 +1,75 @@
+<script  setup>
+import { ref, onMounted, reactive, } from "vue";
+import { VueFlow,Handle, useVueFlow,Position } from '@vue-flow/core'
+const props = defineProps({
+  node: {
+    type: Object,
+    required: true,
+  },
+  sourcePosition: {
+    type: String,
+  },
+  targetPosition: {
+    type: String,
+  },
+})
+onMounted(() => {
+});
+</script>
+<template>
+  <!-- <div v-if="props.node.data.label!='模块化'"> -->
+  <div v-if="props.node.data!=null" style="height: 100%;">
+    <div class="custom-node icons  " :id="`node-${node.id}`" >
+    <img v-if="props.node.data.label!='模块化'" :src="props.node.data.image"/>
+    <span>{{props.node.data.label }}</span>
+  </div>
+  <Handle  v-if="props.node.data.label!='模块化'"  type="source" id="target-a" :position="Position.Right"  />
+  <Handle id="target-c" type="source" :position="Position.Top"  /> 
+  <Handle  v-if="props.node.data.label!='模块化'"  id="target-b" type="source"  :position="Position.Left" /> 
+  <Handle id="target-d" type="source" :position="Position.Bottom"  /> 
+  </div>
+<!-- </div> -->
+</template>
+<style scoped> 
+
+.icons img{
+    width: 26px;
+
+}
+.icons span{
+  display: block;
+  font-size: 8px;
+}
+
+.custom-node.icons {
+  display: flex;
+  flex-direction: column; /* 垂直排列 img 和 span */
+  align-items: center;     /* 水平居中 */
+  justify-content: center; /* 垂直居中 */
+  width: 100%;
+  height: 100%;
+}
+
+</style>
+<style>
+.vue-flow__node-group{
+  width: 160px;
+  height: 160px;
+  border-radius: 3px;
+  border: 1px solid #409EFF;
+  pointer-events: none;
+}
+
+.vue-flow__node.draggable {
+    background-color: rgba(0,0,0,0);
+}
+
+.vue-flow__node-group.selected, .vue-flow__node-group.selected:hover{
+  box-shadow: 0 0 0 2px #007bff;
+}
+
+        
+ 
+
+
+</style>

+ 35 - 18
src/views/vuetree/index.vue

@@ -7,9 +7,14 @@
     @dragover="onDragOver" @dragleave="onDragLeave" @edge-click="onEdgeClick" @node-double-click="onNodeDoubleClick" 
     @node-click="onNodeClick" @edge-double-click="onEdgeDoubleClick">
 
+    <!-- 自定义节点类型为default的节点 -->
     <template  #node-default="props">
       <eltree :node="props" />
     </template>
+    <!-- 自定义节点类型为group的节点 -->
+    <template  #node-group="props">
+      <eltreeGroup :node="props" />
+    </template>
  
     <Background pattern-color="#aaa" :gap="16" 
     />
@@ -254,6 +259,7 @@ import { MiniMap } from '@vue-flow/minimap'
 import "./main.css";//重置样式
 import DropzoneBackground from './DropzoneBackground.vue'
 import eltree from './eltree.vue'
+import eltreeGroup from './eltreeGroup.vue'
 import CustomEdge from './CustomEdge.vue';
 import useDragAndDrop from './useDnD';
 import f11 from '@/assets/img/f11.png'
@@ -295,7 +301,7 @@ let newobj=ref({
 let nodesitem=ref([]);
 let linenum=ref(1);
 let bgcolor=ref();
-let linecolor=ref('#b1b1b7')
+let linecolor=ref('#2267B1')
 let pid=ref('');
 let newroter=ref();
 let vueflowimg=ref('');
@@ -370,25 +376,35 @@ onConnect((connection) => {
   const edgeId = `${lineType.value}-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`;
   connection.id = edgeId;  // 自定义 ID
   connection.type = 'smoothstep';//  smoothstep straight
-  connection.markerEnd = lineType.value === "data" ? "" : MarkerType.ArrowClosed;
+  if(lineType.value === 'process'){
+    connection.markerEnd = MarkerType.ArrowClosed;
+  }else if(lineType.value === 'data'){
+    connection.markerEnd = {
+      type: MarkerType.ArrowClosed,
+      width: 6, // 设置宽度(箭头大小)
+      height: 6, // 设置高度(箭头大小)实测长宽一样才生效
+      color: linecolor.value, // 设置颜色
+    };
+  }
+  // connection.markerEnd = lineType.value === "data" ? "" : MarkerType.ArrowClosed;
   connection.color=linecolor.value;
   // connection.label = '这是一条注释';
   connection.style = { strokeWidth:linenum.value ,stroke:linecolor.value};
 
   // 连接数据流线前应先连接逻辑流
-  if(lineType.value === 'data'){
-    const processEdgeId = `process-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`;
-    const hasProcessEdge = edges.value.some(edge => edge.id === processEdgeId);
-    if(!hasProcessEdge){
-      ElMessage({
-        message:'请先连接逻辑流连线!',
-        type:'error'
-      })
-      return;
-    }
-  }
+  // if(lineType.value === 'data'){
+  //   const processEdgeId = `process-${connection.source}-${connection.sourceHandle}-${connection.target}-${connection.targetHandle}`;
+  //   const hasProcessEdge = edges.value.some(edge => edge.id === processEdgeId);
+  //   if(!hasProcessEdge){
+  //     ElMessage({
+  //       message:'请先连接逻辑流连线!',
+  //       type:'error'
+  //     })
+  //     return;
+  //   }
+  // }
 
-  // 
+  // 相同线删除上一条线的流
   const sameEdge = edges.value.find(edge => edge.id === edgeId);
   if(sameEdge){
     deleteflow(sameEdge.data.wid);
@@ -876,8 +892,9 @@ function removeEdge(id) {
 
 // 触摸
 const onDrop1=(event)=>{
+  // console.log('onDrop1:',event);
   onDrop(event);
-emitter.emit('doSomethingEvent');
+  emitter.emit('doSomethingEvent');
 
 }
 
@@ -1230,14 +1247,14 @@ const getroter=()=>{
   // datatree.value[0].children.push(item);
 
 }
-//改变线的
+//改变线的类型
 const linestrokeWidth=(type)=>{
   if(type=='process'){
     linenum.value=1;
-    linecolor.value = '#b1b1b7';
+    linecolor.value = '#2267B1';
     lineType.value = 'process';
   }else if(type=='data'){
-    linenum.value=6;
+    linenum.value=9;
     linecolor.value = "rgba(150, 150, 150, 0.2)";
     lineType.value = 'data';
   }

+ 20 - 32
src/views/vuetree/useDnD.js

@@ -238,6 +238,10 @@ export default function useDragAndDrop() {
 
     }else{
       // 创建初始的节点数据,不包含 wid
+      // FSI为group类型
+      if(nid == '3-13'){
+        draggedType.value = 'group'
+      }
       const newNode = {
         id: nodeId,
         type: draggedType.value,
@@ -249,39 +253,24 @@ export default function useDragAndDrop() {
 
       // 异步保存数据并更新 wid
       saveflow(pid, newwid, newName, 'com', '', '').then((wid) => {
-      // 更新节点数据中的 wid
-      newNode.data.wid = wid;
+        // 更新节点数据中的 wid
+        newNode.data.wid = wid;
 
-      // 使用 onNodesInitialized 来更新节点数据
-      onNodesInitialized(() => {
-        // 更新节点的其他数据
-        updateNode(nodeId, (node) => ({
-          ...node, 
-          data: {
-            ...node.data,
-            wid: newNode.data.wid,  // 更新节点中的 wid
-          },
-        }));
+        // 使用 onNodesInitialized 来更新节点数据
+        onNodesInitialized(() => {
+          // 更新节点的其他数据
+          updateNode(nodeId, (node) => ({
+            ...node, 
+            data: {
+              ...node.data,
+              wid: newNode.data.wid,  // 更新节点中的 wid
+            },
+          }));
+        });
+      }).catch((err) => {
+        console.error('保存流程失败:', err.message);
+        ElMessage.error('保存流程失败');
       });
-    }).catch((err) => {
-      console.error('保存流程失败:', err.message);
-      ElMessage.error('保存流程失败');
-    });
-
-        // saveflow(pid , savewid, newName, 'com', '', '')
-        // console.log('返回的 wid:', widtemp.value)
-        // const wid = widtemp.value
-        // const uid = newName
-        // // 创建新节点,包含 wid 数据
-        // const newNode = {
-        //   id: nodeId,
-        //   type: draggedType.value,
-        //   position,
-        //   data: { ...image1, wid , uid}, // 将 wid 存入节点数据中
-        // }
-  
-        // snodes.value.push(newNode)
-    
     }
     const { off } = onNodesInitialized(() => {
       updateNode(nodeId, (node) => ({
@@ -294,7 +283,6 @@ export default function useDragAndDrop() {
     addNodes(snodes.value)
     treeobj.value=snodes.value
 
-   // addEdges(sedges.value)
   }
   return {
     treeobj,