dataMap.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <template>
  2. <div class="layout-container">
  3. <div class="panel" ref="panel1">
  4. <div
  5. class="parent hc-excel-table-form"
  6. id="parent"
  7. @click="parentClick($event)"
  8. ></div>
  9. </div>
  10. <div class="splitter"></div>
  11. <div class="panel" ref="panel2">
  12. <div style="margin-bottom: 20px; text-align: right">
  13. <el-button @click="goBack">返回上一级</el-button>
  14. <el-button type="primary" @click="saveInfo" :loading="saveLoaing"
  15. >保存</el-button
  16. >
  17. </div>
  18. <template v-if="listArr.length>0">
  19. <div class="right_box" v-for="(eleItem,index) in listArr" :key="index">
  20. <div>
  21. <span>选择表单</span>
  22. <el-select
  23. v-model="eleItem.initTabId"
  24. placeholder="请选择"
  25. style="width: 65%; margin-left: 10px"
  26. @change="changeform($event,index)"
  27. >
  28. <el-option
  29. v-for="item in formoptions"
  30. :key="item.initTabId"
  31. :label="item.tabName"
  32. :value="item.initTabId"
  33. >
  34. </el-option>
  35. </el-select>
  36. </div>
  37. <div>
  38. <span>选择元素</span>
  39. <el-select
  40. v-model="eleItem.elementId"
  41. placeholder="请选择"
  42. style="width: 65%; margin-left: 10px; margin-top: 15px"
  43. @change="changeEle($event,index)"
  44. filterable
  45. >
  46. <el-option
  47. v-for="item in eleOptions"
  48. :key="item.id"
  49. :label="item.eName"
  50. :value="item.id"
  51. >
  52. </el-option>
  53. </el-select>
  54. </div>
  55. <div class="martop10 replace_box">
  56. <div style="width: 100%; height: 100%; overflow-y: auto">
  57. <el-row class="mb-4">
  58. <div class="form_text">
  59. <div>表单名称:{{ eleItem.tabName }}</div>
  60. <div>元素字段:{{ eleItem.elementName }}</div>
  61. </div>
  62. </el-row>
  63. <div class="martop20">
  64. <el-button type="primary" size="small" @click="addList(index)">新增元素</el-button>
  65. <el-button type="danger" size="small" v-if="index>0" @click="delList(index,eleItem)">删除元素</el-button>
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </template>
  71. <el-empty description="暂无数据" v-else ></el-empty>
  72. </div>
  73. </div>
  74. </template>
  75. <script>
  76. import {
  77. getLinkHtml,
  78. getLinkTablist,
  79. getLinkElelist,
  80. getLinkDetail,
  81. removeLinkData,
  82. getLinkData,
  83. saveLinkDetail
  84. } from "@/api/tentative/testcollect";
  85. import Vue from "vue";
  86. import Split from "split.js";
  87. export default {
  88. data() {
  89. return {
  90. formoptions: [],
  91. eleOptions: [],
  92. heights: "",
  93. initTabId: "",
  94. formpid: "",
  95. formname: "",
  96. classId: "",
  97. elementId: "",
  98. eleId: "",
  99. clickKeyname: "",
  100. infoDetail: {
  101. elementName: "",
  102. tabName: "",
  103. id: "",
  104. },
  105. saveLoaing: false,
  106. clickArr: [], //需要绑定的数组
  107. curItem: {
  108. elementId: "",
  109. elementKey: "",
  110. htmlKeyName: "",
  111. trialTabId: "",
  112. trialTabName: "",
  113. },
  114. linkedData: [], //已经绑定的数组
  115. listArr: [
  116. {}
  117. ],
  118. };
  119. },
  120. watch: {
  121. },
  122. methods: {
  123. async getExcelHtmlCol(classId, form) {
  124. //获取excel模板
  125. const { data: res } = await getLinkHtml({ classId });
  126. console.log(res);
  127. if (res.code == 200) {
  128. // let _that = this
  129. var MyComponent = await Vue.extend({
  130. data() {
  131. return {
  132. formData: form,
  133. };
  134. },
  135. //监听数据,伪双向绑定(v-model)
  136. watch: {
  137. formData: {
  138. handler(obj) {
  139. this.formData = obj;
  140. },
  141. deep: true,
  142. immediate: true,
  143. },
  144. },
  145. template: res.data,
  146. methods: {
  147. contextmenuClick() {},
  148. getInformation() {},
  149. formUploadSuccess() {},
  150. formUploadExceed() {},
  151. formUploadLoading() {},
  152. delTableFormFile() {},
  153. formUploadError() {},
  154. uploadprogress() {},
  155. formRemoteMethod() {},
  156. getRegularExpression() {},
  157. checkboxGroupChange() {},
  158. formRemoteChange() {},
  159. dateKeydown() {},
  160. keyupShiftUp() {},
  161. keyupShiftDown() {},
  162. keyupShiftLeft() {},
  163. keyupShiftRight() {},
  164. inputLeftClick() {},
  165. },
  166. });
  167. var component = new MyComponent().$mount();
  168. let na = document.getElementById("parent");
  169. na.innerHTML = `<div
  170. class='parent'
  171. id='parent'"
  172. ></div>`;
  173. document.getElementById("parent").appendChild(component.$el);
  174. }
  175. },
  176. //excel父节点点击检测
  177. async parentClick(e) {
  178. let target = e.target;
  179. let bgs = document.querySelectorAll("#parent .oldlace-bg");
  180. target.classList.add("oldlace-bg");
  181. //console.log(bgs)
  182. let tdEle = this.getParentTD(target);
  183. let target1;
  184. if (tdEle) {
  185. let mydiv = tdEle.getElementsByTagName("div");
  186. target1 = mydiv[0];
  187. } else {
  188. tdEle = target;
  189. let mydiv = tdEle.getElementsByTagName("div");
  190. target = mydiv[0];
  191. }
  192. for (let i = 0; i < bgs.length; i++) {
  193. bgs[i].classList.remove("oldlace-bg");
  194. }
  195. if (
  196. target.getAttribute("trindex") !== null &&
  197. target.getAttribute("tdindex")
  198. ) {
  199. target = target;
  200. } else {
  201. target = target1;
  202. }
  203. //console.log(target.getAttribute('trindex'))
  204. if (
  205. target.getAttribute("trindex") !== null &&
  206. target.getAttribute("tdindex")
  207. ) {
  208. let tdEle = this.getParentTD(target);
  209. if (tdEle) {
  210. target.classList.add("oldlace-bg");
  211. let trtd =
  212. target.getAttribute("trindex") +
  213. "_" +
  214. target.getAttribute("tdindex");
  215. this.$nextTick(() => {
  216. let row = document.querySelectorAll(".warning-row");
  217. if (row.length) {
  218. this.$refs.tablescroll.$el.scrollTop = row[0].offsetTop;
  219. }
  220. });
  221. }
  222. this.clickKeyname = target.getAttribute("keyname") || target1.getAttribute("keyname");
  223. this.$set(this.curItem, "htmlKeyName", this.clickKeyname);
  224. this.listArr.forEach((ele)=>{
  225. ele.htmlKeyName= this.clickKeyname
  226. })
  227. await this.getInfoDEtail();
  228. }
  229. },
  230. getParentTD(ele) {
  231. let targetParent = ele.parentNode;
  232. while (targetParent.nodeName !== "TD") {
  233. if (targetParent.id == "parent") {
  234. return null;
  235. }
  236. targetParent = targetParent.parentNode;
  237. }
  238. return targetParent;
  239. },
  240. setFormData2(obj) {
  241. console.log(obj, "obj");
  242. },
  243. goBack() {
  244. this.$router.go(-1);
  245. },
  246. //获取表单类别
  247. async getFormoptions() {
  248. const { data: res } = await getLinkTablist({
  249. classId: this.classId,
  250. });
  251. if (res.code === 200) {
  252. this.formoptions = res.data;
  253. } else {
  254. this.formoptions = [];
  255. }
  256. },
  257. //获取当前清表表所有已匹配的映射字段列表
  258. async getLinkedData() {
  259. const { data: res } = await getLinkData({
  260. id: this.classId,
  261. });
  262. if (res.code === 200) {
  263. this.linkedData = res.data;
  264. const mappedObject = Object.fromEntries(
  265. res.data.map((item) => [item.htmlKeyName, item.elementValue])
  266. );
  267. this.linkedData = mappedObject;
  268. } else {
  269. this.linkedData = [];
  270. }
  271. },
  272. //选择表单获
  273. changeform(val,index) {
  274. this.getEleList(val);
  275. this.formoptions.forEach((ele) => {
  276. if (ele.initTabId === val) {
  277. this.listArr[index].trialTabId= ele.pkeyId
  278. this.listArr[index].trialTabName= ele.initTableName
  279. this.listArr[index].tabName= ele.tabName
  280. }
  281. });
  282. },
  283. changeEle(val,index) {
  284. this.eleOptions.forEach((ele) => {
  285. if (ele.id === val) {
  286. this.listArr[index].elementName= ele.eName
  287. this.listArr[index].elementId= ele.id
  288. }
  289. });
  290. },
  291. //获取元素列表
  292. async getEleList(val) {
  293. const { data: res } = await getLinkElelist({
  294. id: val,
  295. });
  296. if (res.code === 200) {
  297. this.eleOptions = res.data;
  298. } else {
  299. this.eleOptions = [];
  300. }
  301. },
  302. //获取数据映射源
  303. async getInfoDEtail() {
  304. const { data: res } = await getLinkDetail({
  305. classId: this.classId,
  306. keyName: this.clickKeyname,
  307. });
  308. if (res.code === 200) {
  309. this.listArr = res.data.length>0?res.data:[{}]
  310. this.listArr.forEach((ele)=>{
  311. ele.htmlKeyName= this.clickKeyname
  312. })
  313. this.formoptions.forEach((ele)=>{
  314. this.listArr.forEach(async(eleItem,eleIndex)=>{
  315. if(ele.pkeyId===eleItem.trialTabId){
  316. eleItem.initTabId=ele.initTabId
  317. await this.getEleList(ele.initTabId)
  318. this.changeEle(eleItem.elementId,eleIndex)
  319. }
  320. })
  321. })
  322. } else {
  323. this.listArr = [{}]
  324. }
  325. },
  326. //映射数据保存
  327. async saveInfo() {
  328. if (this.listArr.length === 0) {
  329. this.$message.warning("请进行数据映射配置");
  330. return;
  331. }
  332. const isValid = this.listArr.every(item =>
  333. item.elementId && item.initTabId
  334. );
  335. if (!isValid) {
  336. this.$message.warning("请确保选择了所有表单和元素字段!");
  337. return;
  338. }
  339. this.saveLoaing = true;
  340. const { data: res } = await saveLinkDetail({
  341. classId: this.classId,
  342. reflectionBeanList: this.listArr,
  343. });
  344. this.saveLoaing = false;
  345. if (res.code === 200) {
  346. this.$message({
  347. type: "success",
  348. message: res.msg,
  349. });
  350. await this.getLinkedData();
  351. await this.getExcelHtmlCol(this.classId, this.linkedData); //获取excel模板
  352. this.clickArr = [];
  353. this.curItem={}
  354. }
  355. },
  356. addList(index){
  357. const currentItem = this.listArr[index];
  358. if (!currentItem.elementId || !currentItem.initTabId) {
  359. this.$message({
  360. type: "warning",
  361. message: "请选择元素和表单",
  362. });
  363. return; // 不满足条件则不添加
  364. }
  365. this.listArr.splice(index + 1, 0, {
  366. htmlKeyName: this.clickKeyname
  367. ,
  368. tabName: '',
  369. elementName: ''
  370. });
  371. },
  372. delList(index, item) {
  373. if (!item.id) {
  374. this.listArr.splice(index, 1);
  375. return;
  376. } else {
  377. this.$confirm('删除后,数据将无法恢复,是否确认删除!', '提示', {
  378. confirmButtonText: '确定',
  379. cancelButtonText: '取消',
  380. type: 'warning'
  381. }).then(() => {
  382. // 接口调用时添加 catch 处理接口错误
  383. removeLinkData({ id: item.id })
  384. .then((res) => {
  385. if (res.data.code === 200) {
  386. this.$message.success(res.data.msg);
  387. this.listArr.splice(index, 1);
  388. this.getLinkedData();
  389. this.getExcelHtmlCol(this.classId, this.linkedData);
  390. } else {
  391. this.$message.error(res.data.msg);
  392. }
  393. })
  394. .catch((err) => {
  395. // 处理接口调用失败(如网络错误、500错误等)
  396. this.$message.error('删除接口调用失败,请重试');
  397. console.error('删除失败:', err); // 方便调试
  398. });
  399. }).catch(() => {
  400. // 这里仅处理用户点击“取消”的情况
  401. this.$message.info('已取消删除');
  402. });
  403. }
  404. }
  405. },
  406. async created() {
  407. this.classId = this.$route.query.classId;
  408. await this.getLinkedData();
  409. await this.getExcelHtmlCol(this.classId, this.linkedData); //获取excel模板
  410. this.getFormoptions();
  411. },
  412. mounted() {
  413. Split([this.$refs.panel1, this.$refs.panel2], {
  414. direction: "horizontal", // 设置分割方向,'horizontal' 或 'vertical'
  415. gutterSize: 10, // 设置分割条的大小
  416. sizes: [75, 25], // 初始化各个面板的宽度比例
  417. minSize: 100, // 设置面板的最小尺寸
  418. onDragEnd: () => {
  419. // 拖动结束后的回调,可以执行一些额外的操作
  420. console.log("Panel sizes adjusted");
  421. },
  422. });
  423. },
  424. };
  425. </script>
  426. <style scoped>
  427. .layout-container {
  428. display: flex;
  429. height: 100vh;
  430. width: 100%;
  431. }
  432. .panel {
  433. background: white;
  434. border: 1px solid #ccc;
  435. padding: 10px;
  436. box-sizing: border-box;
  437. overflow: auto;
  438. }
  439. .panel:nth-child(odd) {
  440. background: white;
  441. }
  442. .gutter {
  443. background-color: #eee;
  444. background-repeat: no-repeat;
  445. background-position: 50%;
  446. }
  447. #parent ::v-deep .oldlace-bg {
  448. background-color: oldlace;
  449. }
  450. </style>
  451. <style>
  452. .gutter-horizontal {
  453. background-image: url('/img/split.png') !important;
  454. cursor: col-resize;
  455. background-repeat: no-repeat;
  456. background-position: center;
  457. }
  458. .right_box{
  459. margin-bottom: 15px;
  460. }
  461. </style>