asideData.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. <template>
  2. <el-container style="height: 100%">
  3. <el-header class="panel-header">
  4. <p>{{ titlename }}</p>
  5. <el-button style="border: none" @click="closePanel">
  6. <el-icon><Close /></el-icon>
  7. </el-button>
  8. </el-header>
  9. <el-main>
  10. <el-tabs v-model="activename" style="height: 100%">
  11. <el-tab-pane label="数据" name="data" style="height: 100%">
  12. <Splitpanes horizontal>
  13. <Pane min-size="20" size="50" max-size="80">
  14. <el-table :data="filteredData" border class="datatable">
  15. <el-table-column type="index" width="40" label="" />
  16. <el-table-column prop="name" label="属性"> </el-table-column>
  17. <el-table-column prop="value" label="值">
  18. <template #default="{ row }">
  19. <!-- 如果是1 :下拉选择 -->
  20. <el-select
  21. v-if="row.valueType === 1"
  22. v-model="row.value"
  23. placeholder="请选择"
  24. class="full-width-select"
  25. @change="(val) => handleShapeChange(row, val)"
  26. >
  27. <el-option
  28. v-for="option in row.options"
  29. :key="option.val"
  30. :label="option.tag"
  31. :value="option.val"
  32. >
  33. </el-option>
  34. </el-select>
  35. <!-- 如果是2: 输入框 -->
  36. <el-input
  37. v-else-if="row.valueType === 2"
  38. v-model="row.value"
  39. class="full-width-input"
  40. />
  41. <!-- 如果是3: 弹窗 -->
  42. <el-button
  43. v-else-if="row.valueType === 3"
  44. :loading="loadingStates[row.pcaId] || false"
  45. @click="handleClick(row)"
  46. ></el-button>
  47. <div v-else>{{ row.valueDef }}</div>
  48. </template>
  49. </el-table-column>
  50. <el-table-column prop="unit" label="单位" width="100">
  51. <template #default="{ row }">
  52. <el-select
  53. v-if="row.unitType !== '无'"
  54. v-model="row.unitDef"
  55. placeholder="请选择"
  56. @focus="fetchUnitsForRow(row)"
  57. :loading="moreOptionsLoading"
  58. class="full-width-select"
  59. >
  60. <el-option
  61. v-for="option in row.unitoptions"
  62. :key="option.utId"
  63. :label="option.value"
  64. :value="option.value"
  65. >
  66. </el-option>
  67. </el-select>
  68. <div v-else>{{ row.unitType }}</div>
  69. </template>
  70. </el-table-column>
  71. </el-table>
  72. <div class="footbtn">
  73. <el-button @click="savecomvalue">保存</el-button>
  74. </div>
  75. </Pane>
  76. <Pane min-size="20" size="50" max-size="80">
  77. <!-- <div>xia</div> -->
  78. <el-table :data="resultData" border class="datatable">
  79. <el-table-column type="index" width="40" label="" />
  80. <el-table-column prop="name" label="属性"> </el-table-column>
  81. <el-table-column prop="value" label="值">
  82. <template #default="{ row }">
  83. <el-button
  84. v-if="row.coms.length > 1"
  85. @click="openresultline(row.name, row.unit, row.coms)"
  86. ></el-button>
  87. <div v-else>{{ row.value }}</div>
  88. </template>
  89. </el-table-column>
  90. <el-table-column
  91. v-if="resultData.some((item) => item.coms.length <= 1)"
  92. prop="unit"
  93. label="单位"
  94. >
  95. </el-table-column>
  96. </el-table>
  97. </Pane>
  98. </Splitpanes>
  99. </el-tab-pane>
  100. </el-tabs>
  101. </el-main>
  102. <!-- 用于数据按钮table -->
  103. <el-dialog
  104. v-model="paneTabledialog"
  105. align-center
  106. :append-to-body="true"
  107. width="700"
  108. class="dialog_class"
  109. draggable
  110. >
  111. <template #header="{ titleId, titleClass }">
  112. <div class="my-header">
  113. <!-- <el-image :src="icon" fit="contain"></el-image> -->
  114. <h4 :id="titleId" :class="titleClass">{{ dialogname }}</h4>
  115. </div>
  116. </template>
  117. <el-row :gutter="10" style="margin-bottom: 10px">
  118. <el-col :span="4"> </el-col>
  119. <el-col :span="5"> </el-col>
  120. <el-col :span="5">
  121. <el-button class="btnwidth100" @click="handleAddRow">添加</el-button>
  122. </el-col>
  123. <el-col :span="5">
  124. <el-button class="btnwidth100" @click="handleDeleteSelected"
  125. >删除</el-button
  126. >
  127. </el-col>
  128. <el-col :span="5">
  129. <el-button class="btnwidth100" @click="handleInsertSelected"
  130. >插入</el-button
  131. >
  132. </el-col>
  133. </el-row>
  134. <el-table
  135. :data="tableData"
  136. border
  137. height="300"
  138. style="width: 100%"
  139. @row-click="handleRowClick"
  140. highlight-current-row
  141. ref="tableRef"
  142. >
  143. <el-table-column type="index" width="40"></el-table-column>
  144. <el-table-column
  145. v-for="col in tableColumns"
  146. :key="col.code"
  147. :label="col.name"
  148. :min-width="200"
  149. >
  150. <template #header>
  151. <div class="unitheader">
  152. <div>{{ col.name }}</div>
  153. <div style="width: 50%; min-width: 100px">
  154. <el-select
  155. v-if="col.unit !== '无'"
  156. v-model="col.unitDef"
  157. size="small"
  158. @focus="fetchUnitsForRow(col)"
  159. @change="saveSelectedUnit(col)"
  160. >
  161. <el-option
  162. v-for="opt in col.unitoptions"
  163. :key="opt.utId"
  164. :label="opt.value"
  165. :value="opt.value"
  166. />
  167. </el-select>
  168. </div>
  169. </div>
  170. </template>
  171. <template #default="{ row }">
  172. <el-select
  173. v-if="col.valueType === 1"
  174. v-model="row[col.code].value"
  175. class="full-width-select"
  176. >
  177. <el-option
  178. v-for="option in row[col.code].options"
  179. :key="option.val"
  180. :label="option.tag"
  181. :value="option.val"
  182. >
  183. </el-option>
  184. </el-select>
  185. <el-input
  186. v-else-if="col.valueType === 2"
  187. v-model="row[col.code].value"
  188. class="full-width-input"
  189. />
  190. <el-button v-else-if="col.valueType === 3"></el-button>
  191. <div v-else>{{ col.valueDef }}</div>
  192. </template>
  193. </el-table-column>
  194. </el-table>
  195. <template #footer>
  196. <span class="lastbtn">
  197. <el-button @click="paneTabledialog = false">{{
  198. $t("dialog.cancel")
  199. }}</el-button>
  200. <el-button type="primary" @click="saveTabelDialog()">
  201. {{ $t("dialog.ok") }}
  202. </el-button>
  203. </span>
  204. </template>
  205. </el-dialog>
  206. <!-- 用于数据按钮键值对 -->
  207. <el-dialog
  208. v-model="paneKVdialog"
  209. align-center
  210. :append-to-body="true"
  211. width="500"
  212. class="dialog_class"
  213. draggable
  214. >
  215. <template #header="{ titleId, titleClass }">
  216. <div class="my-header">
  217. <!-- <el-image :src="icon" fit="contain"></el-image> -->
  218. <h4 :id="titleId" :class="titleClass">{{ dialogname }}</h4>
  219. </div>
  220. </template>
  221. <el-table :data="tableKVData" border height="300" style="width: 100%">
  222. <el-table-column type="index" label="编号" width="60"></el-table-column>
  223. <el-table-column prop="property" label="属性"></el-table-column>
  224. <el-table-column prop="value" label="值">
  225. <template #default="{ row }">
  226. <el-input v-model="row.value" class="full-width-input"></el-input>
  227. </template>
  228. </el-table-column>
  229. </el-table>
  230. <template #footer>
  231. <span class="lastbtn">
  232. <el-button @click="paneKVdialog = false">{{
  233. $t("dialog.cancel")
  234. }}</el-button>
  235. <el-button type="primary" @click="saveKVTabelDialog">
  236. {{ $t("dialog.ok") }}
  237. </el-button>
  238. </span>
  239. </template>
  240. </el-dialog>
  241. <!-- 结果曲线弹窗 -->
  242. <el-dialog
  243. v-model="resultlinedialog"
  244. align-center
  245. :append-to-body="true"
  246. width="770"
  247. class="dialog_class"
  248. draggable
  249. >
  250. <template #header="{ titleId, titleClass }">
  251. <div class="my-header">
  252. <!-- <el-image :src="icon" fit="contain"></el-image> -->
  253. <h4 :id="titleId" :class="titleClass">结果曲线</h4>
  254. </div>
  255. </template>
  256. <el-space>
  257. <el-table
  258. :data="tableResultData"
  259. border
  260. height="300"
  261. style="width: 100%"
  262. >
  263. <el-table-column type="index" label="" width="60"></el-table-column>
  264. <el-table-column
  265. prop="step"
  266. :label="resultxLabel"
  267. width="100"
  268. ></el-table-column>
  269. <el-table-column prop="value" :label="resultyLabel" width="150">
  270. </el-table-column>
  271. </el-table>
  272. <div class="resultecharts">
  273. <EchartLine
  274. :key="resultChartKey"
  275. :chart-data="tableResultData"
  276. :x-label="resultxLabel"
  277. :y-label="resultyLabel"
  278. />
  279. </div>
  280. </el-space>
  281. </el-dialog>
  282. </el-container>
  283. </template>
  284. <script setup>
  285. import { Splitpanes, Pane } from "splitpanes"
  286. import "splitpanes/dist/splitpanes.css"
  287. import { Close } from "@element-plus/icons-vue"
  288. import { request } from "@/utils/request"
  289. import {
  290. ElMessage,
  291. ElButton,
  292. ElDialog,
  293. ElSelect,
  294. ElMessageBox
  295. } from "element-plus"
  296. import { Loading } from "@element-plus/icons-vue"
  297. import EchartLine from "../../echarts/EchartLine.vue"
  298. const activename = ref("data")
  299. const emit = defineEmits(["close"])
  300. const titlename = ref()
  301. const comdata = ref()
  302. const paneTabledialog = ref(false)
  303. const paneKVdialog = ref(false)
  304. const resultlinedialog = ref(false)
  305. const dialogname = ref("")
  306. // 用于侧栏按钮打开弹窗加载
  307. const loadingStates = ref({})
  308. // data表格按钮点击弹窗表格
  309. const tableColumns = ref([])
  310. const tableData = ref([])
  311. let pcId = ref("") // 项目组件id
  312. let pcaId = ref("") //项目组件的属性id
  313. const tableKVData = ref([])
  314. const tableResultData = ref([])
  315. const resultChartKey = ref(0) // 用于强制刷新图表
  316. const resultxLabel = ref("时间(s)")
  317. const resultyLabel = ref("")
  318. // 单位选项缓存
  319. const unitOptionsCache = ref({});
  320. // 更多选项加载状态
  321. const moreOptionsLoading = ref(false);
  322. const closePanel = () => {
  323. emit("close")
  324. }
  325. const filteredData = computed(() => {
  326. return comdata.value ? comdata.value.filter((item) => item.isVisible) : []
  327. })
  328. const resultData = ref([])
  329. // 定义形状与隐藏字段的映射
  330. const SHAPE_HIDDEN_FIELDS = {
  331. 0: [
  332. "SideLength",
  333. "Width",
  334. "Height",
  335. "InnerWallThickness",
  336. "OuterWallThickness",
  337. "Inside",
  338. "Outside"
  339. ],
  340. 1: [
  341. "Diameter",
  342. "Width",
  343. "Height",
  344. "InnerWallThickness",
  345. "OuterWallThickness",
  346. "Inside",
  347. "Outside"
  348. ],
  349. 2: [
  350. "Diameter",
  351. "SideLength",
  352. "InnerWallThickness",
  353. "OuterWallThickness",
  354. "Inside",
  355. "Outside"
  356. ],
  357. 3: [
  358. "Diameter",
  359. "Width",
  360. "Height",
  361. "InnerWallThickness",
  362. "OuterWallThickness",
  363. "Inside",
  364. "Outside"
  365. ],
  366. 4: ["Diameter", "SideLength", "Width", "Height", "PipeThickness"]
  367. }
  368. const handleShapeChange = (row, val) => {
  369. if (row.code === "CrossSectionalShape") {
  370. // 先重置所有行可见
  371. comdata.value.forEach((item) => {
  372. item.isVisible = true
  373. })
  374. // 隐藏对应形状不需要的字段
  375. const fieldsToHide = SHAPE_HIDDEN_FIELDS[val] || []
  376. comdata.value.forEach((item) => {
  377. if (fieldsToHide.includes(item.code)) {
  378. item.isVisible = false
  379. }
  380. })
  381. }
  382. }
  383. const getcomdata = async (onpcId) => {
  384. pcId.value = onpcId // 将传入的pcId赋值给响应式变量
  385. const params = {
  386. transCode: "ES0009",
  387. pcId: onpcId
  388. }
  389. try {
  390. const res = await request(params) // 使用 await 等待请求完成
  391. titlename.value = `${res.name}${res.idCode}${res.ser}`
  392. comdata.value = res.rows.map((item) => ({
  393. ...item,
  394. isVisible: true // 默认所有行都可见
  395. }))
  396. console.log("comdata.value", comdata.value)
  397. // 处理 unit 和 unitDef 的关系
  398. comdata.value.forEach(row => {
  399. // 如果有 unit 字段,则将其值赋给 unitDef(用于下拉框显示)
  400. if (row.unit && row.unitType !== '无') {
  401. row.unitDef = row.unit;
  402. }
  403. });
  404. // 使用 for...of 循环以便使用 await
  405. for (const item of comdata.value) {
  406. if (!item.pcaId) continue
  407. // 并行处理 value 和 unit 的初始化
  408. const promises = []
  409. if (item.valueType === 1) {
  410. promises.push(getlistopt(item, "value"))
  411. } else if (item.valueType === 0) {
  412. item.value = item.valueDef
  413. }
  414. if (item.unitType !== "无") {
  415. // promises.push(getlistopt(item, "unit"))
  416. } else {
  417. item.unit = "无"
  418. }
  419. // 等待当前 item 的所有初始化完成
  420. await Promise.all(promises)
  421. }
  422. console.log("所有数据初始化完成")
  423. // 查找截面形状行并触发初始处理
  424. const shapeRow = comdata.value.find(
  425. (item) => item.code === "CrossSectionalShape"
  426. )
  427. if (shapeRow && shapeRow.value !== undefined) {
  428. console.log("形状")
  429. handleShapeChange(shapeRow, shapeRow.value)
  430. }
  431. } catch (err) {
  432. console.error("初始化失败:", err)
  433. ElMessage.error("初始化失败")
  434. }
  435. }
  436. const getbtnvalue = async (pcaId, dataType) => {
  437. const params = {
  438. transCode: "ES0010",
  439. pcaId: pcaId
  440. }
  441. try {
  442. const res = await request(params)
  443. if (dataType === 1) {
  444. // 处理 headers - 使用 Promise.all 确保所有异步操作完成
  445. await Promise.all(
  446. res.headers?.map(async (header) => {
  447. if (header?.unitType !== "无") {
  448. // await getlistopt(header, "unit")
  449. } else {
  450. header.unit = "无"
  451. header.unitoptions = []
  452. }
  453. if (header?.valueType === 1) {
  454. await getlistopt(header, "value")
  455. } else {
  456. header.options = []
  457. }
  458. })
  459. )
  460. // 设置表格列
  461. tableColumns.value = res.headers || []
  462. // 将 datas 按行号分组
  463. const rowMap = new Map()
  464. // 使用 Promise.all 确保所有数据项处理完成
  465. await Promise.all(
  466. res.datas?.map(async (item) => {
  467. if (!item?.pcadgId) return
  468. const rowId = item.pcadgId
  469. // 为行加pcadgId
  470. if (!rowMap.has(rowId)) {
  471. rowMap.set(rowId, { pcadgId: rowId })
  472. }
  473. const header = res.headers?.find((h) => h?.cdvId === item?.cdvId)
  474. if (!header) return
  475. const row = rowMap.get(rowId)
  476. if (item.unit) {
  477. header.unitDef = item.unit
  478. }
  479. // 为表头的下拉框赋值
  480. // if (header.unitType !== "无") {
  481. // header.unit = item.unit
  482. // }
  483. // 处理下拉类型
  484. if (header?.valueType === 1) {
  485. await getlistopt(header, "value")
  486. row[header.code] = {
  487. value: item?.value || header?.value || "",
  488. unit: item?.unit || header?.unitDef || "无",
  489. options: header?.options || [],
  490. pcadgId: item.pcadgId,
  491. pcadId: item.pcadId,
  492. cdvId: item.cdvId
  493. }
  494. } else {
  495. // 非下拉类型
  496. row[header.code] = {
  497. value: item?.value || "",
  498. unit: item?.unit || header?.unitDef || "无",
  499. pcadgId: item.pcadgId,
  500. pcadId: item.pcadId,
  501. cdvId: item.cdvId
  502. }
  503. }
  504. })
  505. )
  506. // 确保所有数据处理完成后再设置 tableData
  507. // tableData.value = Array.from(rowMap.values())
  508. // 排序
  509. tableData.value = Array.from(rowMap.values()).sort(
  510. (a, b) => a.pcadgId - b.pcadgId
  511. )
  512. console.log("tableData赋值:", tableData.value)
  513. } else if (dataType === 2) {
  514. // 处理属性-值对形式
  515. const kvData = []
  516. let rowCount = 0
  517. res.headers?.forEach((header) => {
  518. if (!header?.cdvId) return
  519. const dataItem = res.datas?.find((item) => item?.cdvId === header.cdvId)
  520. rowCount++
  521. kvData.push({
  522. cdvId: header.cdvId,
  523. property: header?.name || "",
  524. value: dataItem?.value || "",
  525. pcadId: dataItem?.pcadId || "",
  526. pcadgId: rowCount,
  527. unit: dataItem?.unit || "无"
  528. })
  529. })
  530. tableKVData.value = kvData
  531. }
  532. } catch (err) {
  533. console.error("值初始化失败:", err)
  534. ElMessage.error("值初始化失败")
  535. }
  536. }
  537. const getlistopt = async (item, gettype) => {
  538. let params = {}
  539. if (gettype === "value") {
  540. params = {
  541. transCode: "BES001",
  542. type: item.valueDef
  543. }
  544. } else {
  545. params = {
  546. transCode: "BES001",
  547. type: item.unitType
  548. }
  549. }
  550. try {
  551. const res = await request(params)
  552. // console.log("选项获取成功", res)
  553. if (gettype === "value") {
  554. if (
  555. item.value === undefined ||
  556. item.value === null ||
  557. item.value === ""
  558. ) {
  559. item.value = res.rows?.[0]?.val ?? ""
  560. }
  561. item.options = res.rows || []
  562. } else if (gettype === "unit") {
  563. if (item.unit === undefined || item.unit === null || item.unit === "") {
  564. item.unit = res.rows?.[0]?.val ?? ""
  565. }
  566. item.unitoptions = res.rows || []
  567. }
  568. } catch (err) {
  569. console.error("err", err)
  570. ElMessage.error("选项初始化失败")
  571. }
  572. }
  573. const handleClick = async (row) => {
  574. try {
  575. loadingStates.value = { ...loadingStates.value, [row.pcaId]: true } // 开始加载
  576. dialogname.value = row.name
  577. pcaId = row.pcaId
  578. const dataType = row.dataType
  579. // 因为公用table,清除上次数据
  580. tableColumns.value = []
  581. tableData.value = []
  582. tableKVData.value = []
  583. // 等待异步操作完成
  584. await getbtnvalue(pcaId, dataType)
  585. // 确保数据准备好后再打开弹窗
  586. if (dataType === 1) {
  587. paneTabledialog.value = true
  588. } else if (dataType === 2) {
  589. paneKVdialog.value = true
  590. }
  591. } catch (error) {
  592. console.error("处理点击时出错:", error)
  593. } finally {
  594. loadingStates.value = { ...loadingStates.value, [row.pcaId]: false } // 无论成功失败都结束加载
  595. }
  596. }
  597. const savecomvalue = () => {
  598. // dataType 为 -1 的数据
  599. const validItems = comdata.value.filter((item) => item.dataType === -1)
  600. console.log("validItemsssssssssaaaaaaaaaa", validItems);
  601. const pcavals = validItems
  602. .map((item) => {
  603. const pcaId = item.pcaId ?? ""
  604. const value = item.value ?? ""
  605. const unit = item.unitDef != '' ? item.unitDef : "无"
  606. return `${pcaId},${value},${unit}`
  607. })
  608. .join(";");
  609. const params = {
  610. transCode: "ES0008",
  611. pcavals: pcavals
  612. }
  613. request(params)
  614. .then((res) => {
  615. ElMessage.success("保存成功")
  616. })
  617. .catch((err) => {
  618. console.error("err", err)
  619. ElMessage.error("保存失败")
  620. })
  621. }
  622. //
  623. // 关于表格弹窗的操作
  624. //
  625. const tableRef = ref(null) // 表格引用
  626. const currentRow = ref(null) // 当前选中行
  627. // 创建新行的辅助函数
  628. const createNewRow = () => {
  629. const newRow = {}
  630. console.log("tableColumns.value", tableColumns.value);
  631. tableColumns.value.forEach((col) => {
  632. newRow[col.code] = {
  633. value: col.valueType === 1 ? col.options?.[0]?.val || "" : "",
  634. unit: col.unitDef || "无",
  635. options: col.valueType === 1 ? col.options : [],
  636. pcadgId: "", // 初始化为空字符串
  637. pcadId: "",
  638. cdvId: col.cdvId
  639. }
  640. })
  641. return newRow
  642. }
  643. const handleAddRow = () => {
  644. const newRow = createNewRow()
  645. tableData.value.push(newRow)
  646. // 选中新添加的行
  647. nextTick(() => {
  648. currentRow.value = newRow
  649. tableRef.value?.setCurrentRow(newRow)
  650. })
  651. }
  652. // 处理行点击
  653. const handleRowClick = (row) => {
  654. currentRow.value = row
  655. // 高亮显示选中行
  656. tableRef.value?.setCurrentRow(row)
  657. }
  658. // 删除选中行 - 如果pcadgId不为空则调用API删除
  659. const handleDeleteSelected = async () => {
  660. if (!currentRow.value) {
  661. ElMessage.warning("请先点击选择要删除的行")
  662. return
  663. }
  664. const index = tableData.value.findIndex((row) => row === currentRow.value)
  665. if (index === -1) return
  666. // 检查是否有pcadgId(非空字符串)
  667. const pcadgId = currentRow.value.pcadgId
  668. console.log("获取到的pcadgId:", pcadgId) // 调试用
  669. try {
  670. if (pcadgId && pcadgId !== "") {
  671. // 使用await等待删除完成
  672. await deleterow(pcadgId)
  673. }
  674. // 无论是否有pcadgId,最终都要从本地删除
  675. tableData.value.splice(index, 1)
  676. updateSelectionAfterDelete(index)
  677. } catch (error) {
  678. ElMessage.error("删除失败,请重试")
  679. console.error("删除过程中出错:", error)
  680. }
  681. }
  682. // 删除后更新选中行的辅助函数
  683. const updateSelectionAfterDelete = (deletedIndex) => {
  684. if (tableData.value.length > 0) {
  685. const newIndex = Math.min(deletedIndex, tableData.value.length - 1)
  686. currentRow.value = tableData.value[newIndex]
  687. nextTick(() => {
  688. tableRef.value?.setCurrentRow(currentRow.value)
  689. })
  690. } else {
  691. currentRow.value = null
  692. }
  693. ElMessage.success("删除成功")
  694. }
  695. // 后端删除API调用
  696. const deleterow = async (pcadgId) => {
  697. const params = {
  698. transCode: "ES0016",
  699. pcaId: pcaId,
  700. pcadgId: pcadgId
  701. }
  702. try {
  703. const res = await request(params)
  704. return res // 返回成功结果
  705. } catch (err) {
  706. console.error("删除请求失败:", err)
  707. throw err // 重新抛出错误以便外部捕获
  708. }
  709. }
  710. // 在选中行下方插入新行 - 简化版,不再更新pcadgId
  711. const handleInsertSelected = () => {
  712. if (!currentRow.value && tableData.value.length > 0) {
  713. ElMessage.warning("请先点击选择要插入的位置")
  714. return
  715. }
  716. const index = currentRow.value
  717. ? tableData.value.findIndex((row) => row === currentRow.value)
  718. : -1
  719. const newRow = createNewRow()
  720. tableData.value.splice(index + 1, 0, newRow)
  721. // 选中新插入的行
  722. nextTick(() => {
  723. currentRow.value = newRow
  724. tableRef.value?.setCurrentRow(newRow)
  725. })
  726. }
  727. const handleUnitChange = (column, newUnit) => {
  728. // 更新该列所有行的单位值
  729. tableData.value.forEach((row) => {
  730. if (row[column.code]) {
  731. row[column.code].unit = newUnit
  732. }
  733. })
  734. }
  735. // 保存
  736. // 保存 - 在保存时统一更新pcadgId
  737. const saveTabelDialog = () => {
  738. // 检查表格数据是否为空
  739. if (!tableData.value || tableData.value.length === 0) {
  740. ElMessage.warning("请设置正确的数据")
  741. return
  742. }
  743. // 深拷贝原始数据
  744. const originalData = JSON.parse(JSON.stringify(tableData.value))
  745. // 在拷贝的数据上更新pcadgId
  746. const dataToSave = originalData.map((row, rowIndex) => {
  747. const newRow = { ...row }
  748. tableColumns.value.forEach((col) => {
  749. if (newRow[col.code] && typeof newRow[col.code] === "object") {
  750. newRow[col.code] = {
  751. ...newRow[col.code],
  752. pcadgId: rowIndex + 1, // 行号从1开始
  753. unit: col.unitDef
  754. }
  755. }
  756. })
  757. return newRow
  758. })
  759. console.log("准备保存的表格数据:", dataToSave)
  760. // 收集所有行数据
  761. const formattedData = dataToSave.map((row) => {
  762. // 收集当前行的所有字段数据
  763. const rowFields = tableColumns.value.map((col) => {
  764. const cellData = row[col.code]
  765. if (!cellData) return ""
  766. console.log("cellDataqqqqqqqq", cellData);
  767. // 组装 cdvId-pcadgId-pcadId-value-unit 格式
  768. return [
  769. cellData.cdvId || "", // cdvId
  770. cellData.pcadgId || "", // pcadgId (行号)
  771. cellData.pcadId || "", // pcadId
  772. cellData.value || "", // value
  773. cellData.unit || "" // unit
  774. ].join(",") // 字段间用逗号分隔
  775. })
  776. return rowFields.join(";") // 行内字段用分号分隔
  777. })
  778. // 最终数据用分号分隔各行
  779. const result = formattedData.join(";")
  780. const params = {
  781. transCode: "ES0011",
  782. pcaId: pcaId,
  783. pcadvals: result
  784. }
  785. request(params)
  786. .then((res) => {
  787. paneTabledialog.value = false
  788. ElMessage.success("保存成功")
  789. })
  790. .catch((err) => {
  791. console.error("err", err)
  792. // 保存失败,保持原始数据不变
  793. ElMessage.error("保存失败")
  794. })
  795. }
  796. //
  797. // 关于KV表格弹窗的操作
  798. //
  799. const saveKVTabelDialog = () => {
  800. // 检查表格数据是否为空
  801. if (!tableKVData.value || tableKVData.value.length === 0) {
  802. ElMessage.warning("请设置正确的数据")
  803. return
  804. }
  805. console.log("表格数据:", tableKVData.value)
  806. const result = tableKVData.value
  807. .map((item) => {
  808. return [
  809. item.cdvId,
  810. item.pcadgId,
  811. item.pcadId,
  812. item.value,
  813. item.unit
  814. ].join(",")
  815. })
  816. .join(";")
  817. // console.log('格式化后的字符串:', result);
  818. const params = {
  819. transCode: "ES0011",
  820. pcaId: pcaId,
  821. pcadvals: result
  822. }
  823. request(params)
  824. .then((res) => {
  825. paneKVdialog.value = false
  826. ElMessage.success("保存成功")
  827. })
  828. .catch((err) => {
  829. console.error("err", err)
  830. ElMessage.error("保存失败")
  831. })
  832. }
  833. function parseKey(key, type) {
  834. if (typeof key !== "string") {
  835. return type === "name" || type === "unit" ? "" : { name: "", unit: "" }
  836. }
  837. const match = key.match(/^(.+?)\((.+?)\)$/)
  838. const name = match ? match[1] : key
  839. const unit = match ? match[2] : ""
  840. if (type === "name") return name
  841. if (type === "unit") return unit
  842. return { name, unit }
  843. }
  844. const getresultData = (jobId) => {
  845. const params = {
  846. transCode: "ES0015",
  847. pcId: pcId.value,
  848. jobId: jobId
  849. }
  850. request(params)
  851. .then((res) => {
  852. console.log("jieguo:", res)
  853. resultData.value = res.rows
  854. .filter((item) => item.keyEn !== "Time(Time-s)")
  855. .map((item) => ({
  856. name: parseKey(item.keyZh, "name"),
  857. unit: parseKey(item.keyEn, "unit"),
  858. value: item.coms[0]?.value,
  859. coms: item.coms
  860. }))
  861. })
  862. .catch((err) => {
  863. console.error("err", err)
  864. })
  865. }
  866. const openresultline = (name, unit, coms) => {
  867. if (!coms || coms.length === 0) {
  868. ElMessage.warning("没有可用的结果数据")
  869. return
  870. }
  871. resultyLabel.value = name + "(" + unit + ")" || ""
  872. tableResultData.value = coms.map((item, index) => ({
  873. step: item.step,
  874. value: item.value
  875. }))
  876. resultChartKey.value = Date.now() //刷新图表
  877. resultlinedialog.value = true
  878. }
  879. // 组件参数点击下拉框调用接口获取单位
  880. const fetchUnitsForRow = async (row) => {
  881. if (unitOptionsCache.value[row.unitType]) {
  882. row.unitoptions = unitOptionsCache.value[row.unitType]
  883. if (!row.unitDef && row.unitOptions.length > 0) {
  884. row.unitDef = row.unitOptions[0].value
  885. }
  886. return
  887. }
  888. moreOptionsLoading.value = true;
  889. const params = {
  890. transCode: "ES0019",
  891. gutId: row.unitType
  892. }
  893. try {
  894. const res = await request(params)
  895. row.unitoptions = res.rows || []
  896. console.log("单位选项获取成功", row.unitoptions );
  897. unitOptionsCache.value[row.unitType] = row.unitoptions
  898. if (!row.unitType && row.unitoptions .length > 0) {
  899. row.unitDef = row.unitoptions [0].value
  900. }
  901. moreOptionsLoading.value = false;
  902. } catch (err) {
  903. moreOptionsLoading.value = false;
  904. ElMessage.error(err.returnMsg || t("error.fetchFailed"))
  905. row.unitoptions = []
  906. unitOptionsCache.value[row.unitType] = []
  907. } finally {
  908. moreOptionsLoading.value = false;
  909. }
  910. }
  911. // 保存选中的单位
  912. const saveSelectedUnit = async (col) => {
  913. console.log("保存选中的单位111111111111:", col);
  914. try {
  915. const selectedUnit = col.unitOptions.find(
  916. (unit) => unit.value === col.selectedUnitId
  917. )
  918. const params = {
  919. transCode: "ES0022",
  920. gutId: col.gutId,
  921. utId: selectedUnit.utId || "",
  922. sutId: selectedGroupId.value || "",
  923. gsutId: col.gsutId || "",
  924. value: selectedUnit.value
  925. }
  926. const res = await request(params)
  927. ElMessage.success(t("message.settingSuccess"))
  928. } catch (err) {
  929. ElMessage.error(err.returnMsg || t("message.settingFailed"))
  930. }
  931. }
  932. defineExpose({
  933. getcomdata,
  934. getresultData
  935. })
  936. </script>
  937. <style scoped>
  938. .panel-header {
  939. display: flex;
  940. justify-content: space-between;
  941. align-items: center;
  942. }
  943. .datatable {
  944. width: 100%;
  945. max-height: 290px;
  946. overflow: auto;
  947. }
  948. .footbtn {
  949. display: flex;
  950. justify-content: end;
  951. align-items: center;
  952. padding: 10px 20px;
  953. }
  954. .unitheader {
  955. width: 100%;
  956. display: flex;
  957. gap: 10px;
  958. }
  959. .unitheader :deep(.el-select__wrapper) {
  960. width: 100%;
  961. }
  962. .btnwidth100 {
  963. width: 100%;
  964. }
  965. .resultecharts {
  966. width: 420px;
  967. height: 400px;
  968. }
  969. </style>