ListItem.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194
  1. <template>
  2. <div class="data-fill-list-box">
  3. <el-collapse v-model="ActiveKey" accordion @change="CollapseChange">
  4. <template v-for="(item,index) in listDatas" :key="item?.pKeyId">
  5. <el-collapse-item :name="`item-${index}-${item?.pKeyId}`" :disabled="item['isBussShow'] === 2" :id="`item-${index}-${item?.pKeyId}`">
  6. <template #title>
  7. <div class="hc-collapse-item-header">
  8. <div class="text-lg truncate item-title">{{item.nodeName}}</div>
  9. <div class="hc-extra-text-box">
  10. <HcTooltip keys="wbs_del_table" v-if="item['isCopeTab'] === 2">
  11. <el-button type="danger" plain :disabled="item['isBussShow'] === 2" @click.stop="delClick(item,index)">删除本表</el-button>
  12. </HcTooltip>
  13. <HcTooltip keys="wbs_copy_table">
  14. <el-button type="primary" plain :disabled="item['isBussShow'] === 2" @click.stop="copyClick(item,index)">复制本表</el-button>
  15. </HcTooltip>
  16. <HcTooltip keys="wbs_hide_table">
  17. <el-button type="primary" plain @click.stop="hideClick(item,index)">
  18. <template v-if="item['isBussShow'] === 1">隐藏本表</template>
  19. <template v-else>显示本表</template>
  20. </el-button>
  21. </HcTooltip>
  22. <HcTooltip keys="wbs_preview_table">
  23. <el-button type="info" plain disabled v-if="item['isBussShow'] === 2 || item['isTabPdf'] === 1">预览</el-button>
  24. <el-button type="primary" plain @click.stop="previewClick(item,index)" v-else>预览</el-button>
  25. </HcTooltip>
  26. <HcTooltip keys="wbs_upload_table">
  27. <el-button :type="item['tabFileType'] === 2?'success':'primary'" plain :disabled="item['isBussShow'] === 2" @click.stop="uploadClick(item,index)">
  28. <template v-if="item['tabFileType'] === 2">已上传</template>
  29. <template v-else>上传</template>
  30. </el-button>
  31. </HcTooltip>
  32. </div>
  33. </div>
  34. </template>
  35. <div class="data-fill-list-item-content">
  36. <div class="data-fill-table-form-box">
  37. <div class="hc-excel-table-form-view" :id="`table-form-${item?.pKeyId}`"/>
  38. <div class="hc-no-table-form" v-if="item?.isTableForm === false">
  39. <div class="table-form-no">
  40. <img :src="notableform" alt=""/>
  41. <div class="desc">暂无表单数据</div>
  42. </div>
  43. </div>
  44. </div>
  45. <div class="data-fill-table-tip-box">
  46. <div class="text-orange tip-title">
  47. <HcIcon name="error" fill ui="text-2xl"/>
  48. <span class="ml-1">提示</span>
  49. </div>
  50. <div class="text-gray-400 tip-item">1、灰色框代表可通过系统识别计算,公式自动引用,可通过公式计算少量数据,(表头数据及简单),也可只填写白色框数据</div>
  51. <div class="text-gray-400 tip-item">2、系统支持键盘中,shift + tab键向上一个填报框切换,tab向下一个填报框切换。暂不支持上下按键切换输入框</div>
  52. <div class="table-tip-foot">
  53. <div class="tip-left-btn">
  54. <HcTooltip keys="wbs_import_table">
  55. <div class="text-gray-400 dow-text">
  56. <HcIcon name="publish" ui="text-lg"/>
  57. <span class="ml-1">导入列表数据</span>
  58. </div>
  59. </HcTooltip>
  60. <HcTooltip keys="wbs_download_table">
  61. <div class="text-main dow-text">
  62. <HcIcon name="file_download" ui="text-lg"/>
  63. <span class="ml-1">下载导入模板</span>
  64. </div>
  65. </HcTooltip>
  66. </div>
  67. <div class="tip-right-btn">
  68. <HcTooltip keys="wbs_save_table">
  69. <el-button type="primary" hc-btn :disabled="item?.isTableForm === false" :loading="tableFormSaveLoading" @click="tableFormSaveClick(item,index)">
  70. <HcIcon name="save"/>
  71. <span>保存</span>
  72. </el-button>
  73. </HcTooltip>
  74. </div>
  75. </div>
  76. </div>
  77. </div>
  78. </el-collapse-item>
  79. </template>
  80. </el-collapse>
  81. </div>
  82. <!--右键菜单-->
  83. <HcContextMenu ref="contextMenuRef" :datas="tableFormMenu" @item-click="handleMenuSelect"/>
  84. <!--上传文件-->
  85. <HcDialog :show="uploadModal" title="上传文件" widths="38rem" :footer="false" @close="uploadModal = false">
  86. <HcUpload :fileList="fileListData" :datas="uploadData" @change='uploadChange' :tableTypeValue="tableTypeValue" :contractId="contractId" :baseData="baseData"/>
  87. </HcDialog>
  88. <!--插入特殊字符-->
  89. <HcDialog :show="specialModal" title="插入特殊字符" widths="600px" saveText="确认插入" @close="specialModal = false" @save="specialNodeClick">
  90. <el-form ref="specialFormRef" :model="specialFormModel" :rules="specialFormRules" label-width="0px" size="large" class="mb-6">
  91. <el-form-item prop="val" class="special-form-item">
  92. <el-input v-model="specialFormModel.val" ref="specialRef" id="specialId" placeholder="请选择特殊字符代码" clearable @blur="specialInputBlur"/>
  93. </el-form-item>
  94. </el-form>
  95. <el-row :gutter="20" style="margin: -10px;">
  96. <el-col :span="3" style="padding: 10px;" v-for="item in specialCharacters">
  97. <div class="special-box" @click="specialClick">
  98. <span class="font-EUDC" :title="`字符代码(C):${item !== 'K̅'?item.slice(2,7):'K̅'}`" v-html="item"/>
  99. </div>
  100. </el-col>
  101. </el-row>
  102. </HcDialog>
  103. <!--引用容器参数-->
  104. <HcDialog :show="vesselModal" title="引用容器参数" widths="84%" saveText="确认引用" isTable @close="vesselModalClose" @save="vesselModalSave">
  105. <div class="adding-form-dialog-box">
  106. <div class="dialog-tree-box">
  107. <el-scrollbar>
  108. <HcMenuSimple :datas="menus" :props="menuProps" :keys="menuKey" @change="menuChange"/>
  109. </el-scrollbar>
  110. </div>
  111. <div class="dialog-table-box">
  112. <div class="dialog-table">
  113. <HcTable ref="vesselTableRef" :column="vesselTableColumn" :datas="vesselTableData" :loading="vesselTableLoading" isCheck @selection-change="vesselTableSelection"/>
  114. </div>
  115. <div class="dialog-pages">
  116. <HcPages :pages="vesselTablePage" @change="vesselTablePageChange"/>
  117. </div>
  118. </div>
  119. </div>
  120. </HcDialog>
  121. <!--引用设备仪器-->
  122. <HcDialog :show="deviceModal" title="引用设备仪器" widths="84%" saveText="确认引用" isTable @close="deviceModalClose" @save="deviceModalSave">
  123. <!-- <HcTable ref="deviceTableRef" :column="deviceTableColumn" :datas="deviceTableData" :loading="deviceTableLoading" isCheck @selection-change="deviceTableSelection"/> -->
  124. <div class="adding-form-dialog-box">
  125. <div class="dialog-tree-box">
  126. <el-scrollbar>
  127. <HcMenuSimple :datas="equipmentmenus" :props="equipmentmenuProps" :keys="equipmentmenuKey" @change="equipmentmenuChange"/>
  128. </el-scrollbar>
  129. </div>
  130. <div class="dialog-table-box">
  131. <div class="dialog-table">
  132. <HcTable ref="deviceTableRef" :column="deviceTableColumn" :datas="deviceTableData" :loading="deviceTableLoading" isCheck @selection-change="deviceTableSelection"/>
  133. </div>
  134. <div class="dialog-pages">
  135. <HcPages :pages="equipmentPage" @change="equipmentTablePageChange"/>
  136. </div>
  137. </div>
  138. </div>
  139. </HcDialog>
  140. </template>
  141. <script setup>
  142. import {ref,watch,nextTick} from "vue";
  143. import {useAppStore} from "~src/store";
  144. import {useRouter, useRoute} from 'vue-router'
  145. import wbsApi from "~api/data-fill/wbs"
  146. import HcUpload from "./HcUpload.vue"
  147. import HTableForm from "~src/plugins/HTableForm"
  148. import dataApi from "~api/tentative/detect/test";
  149. import dataApi1 from "~api/tentative/parameter/container"
  150. import dataApi2 from "~api/tentative/device/approach"
  151. import {getClassList} from "~api/tentative";
  152. import notableform from '~src/assets/view/notableform.svg';
  153. import {utilsText, isType, formValidate, deepClone} from "vue-utils-plus"
  154. const router = useRouter()
  155. const useRoutes = useRoute()
  156. //路由参数
  157. const routerQuery = useRoutes?.query;
  158. const isaddType = routerQuery?.isaddType || false;
  159. //初始
  160. const props = defineProps({
  161. datas: {
  162. type: Array,
  163. default: () => ([])
  164. },
  165. status: {
  166. type: [String,Number],
  167. default: ''
  168. },
  169. baseData: {
  170. type: Object,
  171. default: () => ({})
  172. },
  173. deviceUseIds:{
  174. type: String,
  175. default: () => ('')
  176. },
  177. authBtnTabKey:{
  178. type: String,
  179. default: () => ('')
  180. },
  181. checkTableId:{
  182. type: String,
  183. default: () => ('')
  184. },
  185. tabTypeKey:{
  186. type: String,
  187. default: () => ('')
  188. }
  189. })
  190. const {isString, getObjNullValue, getArrValue} = isType()
  191. const {setPosInsert, setPosRange} = utilsText()
  192. const listDatas = ref(props.datas)
  193. const isStatus = ref(props.status)
  194. const baseData = ref(props.baseData)
  195. const authBtnTabKeyType = ref(props.authBtnTabKey)//所属方
  196. const useAppState = useAppStore()
  197. const projectId = ref(useAppState.getProjectId);
  198. const contractId = ref(useAppState.getContractId);
  199. const tabTypeKeyInfo=ref(props.tabTypeKey)
  200. //监听
  201. watch(() => [
  202. props.datas,
  203. props.tabTypeKey
  204. ], ([datas,TabTypeKey]) => {
  205. listDatas.value = datas
  206. tabTypeKeyInfo.value=TabTypeKey
  207. setFormDataNum(datas)
  208. })
  209. //监听
  210. watch(() => [
  211. props.status,
  212. props.baseData,
  213. ], ([val, base]) => {
  214. //1 未填报,2待上报,3已上报
  215. isStatus.value = val
  216. baseData.value = base
  217. })
  218. //渲染完成
  219. nextTick(() => {
  220. setFormDataNum(props.datas)
  221. })
  222. //获取pKeyId
  223. const getValString = (val) => {
  224. return val ? val + '' : ''
  225. }
  226. //获取表单初始数据
  227. const getFormDataInit = ({projectId, cid, pKeyId}) => {
  228. const { nodeId, contractId } = baseData.value
  229. return {
  230. projectId: projectId,
  231. contractId: cid || contractId,
  232. pkeyId: getValString(pKeyId),
  233. nodeId: nodeId
  234. }
  235. }
  236. //设置表单对象的数量
  237. const formData = ref([])
  238. const setFormDataNum = (datas) => {
  239. ActiveKey.value = ''
  240. let newArr = [];
  241. for (let i = 0; i < datas.length; i++) {
  242. newArr.push({
  243. ...getFormDataInit(datas[i]),
  244. isCollapseLoad: false,
  245. })
  246. }
  247. formData.value = newArr
  248. }
  249. //展开事件
  250. const ActiveKey = ref('')
  251. const formKeyIds = ref('')
  252. const CollapseChange = async (name) => {
  253. ActiveKey.value = name
  254. const names = name ? name.split('-') : []
  255. console.log(names[2]);
  256. formData.value.forEach((changeitem)=>{
  257. if(changeitem.pkeyId===names[2]){
  258. changeitem.isCollapseLoad=true
  259. }
  260. })
  261. if (names.length > 0) {
  262. getOffsetTop(name)
  263. const index = names[1]
  264. const item = listDatas.value[index]
  265. emit('upcheckTableId', item.id)
  266. formKeyIds.value = getValString(item.pKeyId)
  267. if (!item.isTableFormRender) {
  268. //获取已填写的数据
  269. if(!isaddType){
  270. await getBussDataInfo(item, index)
  271. }
  272. //渲染表单
  273. await getExcelHtml(item,index)
  274. }
  275. } else {
  276. getOffsetTop()
  277. formKeyIds.value = ''
  278. }
  279. }
  280. //获取模板标签数据
  281. const formRegExpJson = ref({})
  282. const getExcelHtml = async (item,index) => {
  283. const pkeyIds = getValString(item.pKeyId)
  284. if (pkeyIds) {
  285. const { id } = baseData.value
  286. const {error, code, data} = await dataApi.getExcelHtml({
  287. id: id,
  288. primaryKeyId: pkeyIds
  289. }, false)
  290. const resData = isString(data) ? data || '' : ''
  291. if (!error && code === 200 && resData) {
  292. item.isTableForm = true
  293. //渲染表单
  294. HTableForm.createForm({
  295. template: resData,
  296. tableForm: formData.value[index],
  297. appId: `#table-form-${pkeyIds}`,
  298. onRight: (event, KeyName) => {
  299. onRightClick(event, KeyName, index)
  300. },
  301. //表单正则效验
  302. onBlur: (event, key, reg, val, msg) => {
  303. setTableFormBlurReg(pkeyIds, event, key, reg, val, msg, item, index)
  304. }
  305. })
  306. item.isTableFormRender = true
  307. item.isRenderTableForm = true
  308. } else {
  309. item.isTableForm = false
  310. item.isRenderTableForm = true
  311. window?.$message?.warning('暂无表单')
  312. }
  313. } else {
  314. item.isTableForm = false
  315. item.isRenderTableForm = false
  316. window?.$message?.warning('pkeyId为空')
  317. }
  318. }
  319. //正则效验
  320. const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg, item, index) => {
  321. const dom = document.getElementById(key)?.parentElement ?? ''
  322. if (dom) {
  323. if (val && reg) {
  324. let regx = new RegExp(reg);
  325. let state = regx.test(val);
  326. if (state) {
  327. delete formRegExpJson.value[pkeyId]
  328. dom.style = ''
  329. } else {
  330. formRegExpJson.value[pkeyId] = {key, reg, val, msg, state, nodeName: item.nodeName, itemId: `item-${index}-${item?.pKeyId}`}
  331. dom.style = '--el-input-border-color: #fe0000; box-shadow: 0 0 0 2px #fe0000 inset;'
  332. window?.$message?.warning(msg)
  333. }
  334. } else {
  335. delete formRegExpJson.value[pkeyId]
  336. dom.style = ''
  337. }
  338. }
  339. }
  340. //获取已填写的数据
  341. const getBussDataInfo = async (item, index) => {
  342. const pkeyIds = getValString(item.pKeyId)
  343. if (pkeyIds) {
  344. const { id } = baseData.value
  345. const {error, code, data} = await dataApi.getBussDataInfo({
  346. id: id,
  347. pkeyId: pkeyIds
  348. }, false)
  349. data.forEach((item1)=>{
  350. const resData = getObjNullValue(item1)
  351. if (!error && code === 200 && resData) {
  352. HTableForm.setPickerKey(resData)
  353. const InitObj = getFormDataInit(item) //有数据,关联数据
  354. formData.value[index] = {
  355. ...resData, ...InitObj,
  356. isCollapseLoad: true
  357. }
  358. }else {
  359. formData.value[index] = {
  360. ...getFormDataInit(item),
  361. isCollapseLoad: true
  362. }
  363. }
  364. })
  365. // if (!error && code === 200 && resData) {
  366. // HTableForm.setPickerKey(resData)
  367. // const InitObj = getFormDataInit(item) //有数据,关联数据
  368. // formData.value[index] = {
  369. // ...resData, ...InitObj,
  370. // isCollapseLoad: true
  371. // }
  372. // } else {
  373. // formData.value[index] = {
  374. // ...getFormDataInit(item),
  375. // isCollapseLoad: true
  376. // }
  377. // }
  378. } else {
  379. window?.$message?.warning('pkeyId为空')
  380. }
  381. }
  382. const toBackClick = () => {
  383. router.push({
  384. path: '/tentative/detect/test',
  385. query: {}
  386. })
  387. }
  388. //单个保存
  389. const tableFormSaveLoading = ref(false)
  390. const tableFormSaveClick = async (item,index) => {
  391. if (isStatus.value !== '3') {
  392. if(tabTypeKeyInfo.value==='2'&&baseData.value['detectionResult']===''){
  393. window.$message?.warning('请选择是否合格')
  394. }else{
  395. const res = await saveExcelBussData(item,index)
  396. if (res) {
  397. if(!isaddType){
  398. await getBussPdfInfo(item)
  399. }else{
  400. //返回
  401. toBackClick()
  402. }
  403. renewData()
  404. }
  405. }
  406. } else {
  407. window?.$message?.warning('已上报的资料,不允许保存。')
  408. }
  409. }
  410. //保存表单数据
  411. const saveExcelBussData = async (item, index, showTip = true) => {
  412. if (!getObjNullValue(formRegExpJson.value)) {
  413. tableFormSaveLoading.value = true
  414. const InitObj = getFormDataInit(item)
  415. const {error, code} = await dataApi.saveExcelBussData({
  416. ...baseData.value,
  417. isBatchSave:0,
  418. dataInfo: {
  419. orderList: [{...formData.value[index], ...InitObj}]
  420. }
  421. })
  422. //处理数据
  423. tableFormSaveLoading.value = false
  424. if (!error && code === 200) {
  425. if(showTip) window?.$message?.success('保存成功')
  426. return true
  427. } else {
  428. return false
  429. }
  430. } else {
  431. window?.$message?.warning('请先修改完红色输入框的数据')
  432. return false
  433. }
  434. }
  435. //预览PDF
  436. const getBussPdfInfo = async ({pKeyId}, showTip = true) => {
  437. const pkeyIds = getValString(pKeyId)
  438. if (pkeyIds) {
  439. const { id } = baseData.value
  440. const {error, code, data} = await dataApi.getBussPdf({
  441. id: id,
  442. pKeyId: pkeyIds
  443. },false)
  444. if (!error && code === 200) {
  445. if (data) {
  446. window.open(data, '_blank')
  447. } else if(showTip) {
  448. window?.$message?.warning('PDF错误')
  449. }
  450. } else {
  451. if(showTip) {
  452. window?.$message?.warning(data.msg || '获取PDF失败')
  453. }
  454. }
  455. } else {
  456. window?.$message?.warning('pkeyId为空')
  457. }
  458. }
  459. //删除本表
  460. const delClick = async ({pKeyId}) => {
  461. const pkeyIds = getValString(pKeyId)
  462. if (pkeyIds) {
  463. const { id } = baseData.value
  464. const {error, code} = await dataApi.removeBussTabInfo({
  465. id: id,
  466. pKeyId: pkeyIds
  467. })
  468. if (!error && code === 200) {
  469. window?.$message?.success('操作成功')
  470. renewData()
  471. }
  472. } else {
  473. window?.$message?.warning('pkeyId为空')
  474. }
  475. }
  476. //复制本表
  477. const copyClick = async (item,index) => {
  478. const pkeyIds = getValString(item.pKeyId)
  479. if (pkeyIds) {
  480. if (isStatus.value !== '3') {
  481. if (!item.isRenderTableForm) {
  482. await copeBussTab(pkeyIds)
  483. } else if (!item.isTableForm) {
  484. window?.$message?.warning('暂无表单数据')
  485. } else if (item.isRenderTableForm) {
  486. const res = await saveExcelBussData(item,index,false)
  487. if (res) {
  488. await copeBussTab(pkeyIds)
  489. } else {
  490. window?.$message?.warning('复制本表操作失败')
  491. }
  492. } else {
  493. window?.$message?.warning(`数据异常了, isRenderTableForm: ${item.isRenderTableForm}, isTableForm: ${item.isTableForm}, pKeyId:${pkeyIds}`)
  494. }
  495. } else {
  496. window?.$message?.warning('已上报的资料,不允许复制')
  497. }
  498. } else {
  499. window?.$message?.warning('pkeyId为空')
  500. }
  501. }
  502. const copeBussTab = async (pkeyIds) => {
  503. const { id } = baseData.value
  504. const {error, code} = await dataApi.copyBussTab({
  505. id: id,
  506. pKeyId: pkeyIds
  507. })
  508. if (!error && code === 200) {
  509. window?.$message?.success('操作成功')
  510. renewData()
  511. }
  512. }
  513. //隐藏本表
  514. const hideClick = async ({pKeyId, isBussShow}) => {
  515. const pkeyIds = getValString(pKeyId)
  516. if (pkeyIds) {
  517. if (isStatus.value !== '3') {
  518. const { id } = baseData.value
  519. const isBussShows = isBussShow === 2 ? 1 : 2 //状态(1显示 2隐藏)
  520. const {error, code} = await dataApi.showBussTab({
  521. id: id,
  522. pKeyId: pkeyIds,
  523. status: isBussShows
  524. })
  525. if (!error && code === 200) {
  526. window?.$message?.success('操作成功')
  527. renewData()
  528. }
  529. } else {
  530. window?.$message?.warning('已上报的资料,不允许隐藏')
  531. }
  532. } else {
  533. window?.$message?.warning('pkeyId为空')
  534. }
  535. }
  536. //预览
  537. const previewClick = async (item,index) => {
  538. await getBussPdfInfo(item)
  539. }
  540. //上传变量
  541. const uploadModal = ref(false)
  542. const fileListData = ref([]);
  543. const uploadData = ref({})
  544. const tableTypeValue=ref('')
  545. //上传被点击
  546. const uploadClick = (item,index) => {
  547. const pkeyIds = item.pKeyId ? item.pKeyId + '' : ''
  548. const { id } = baseData.value
  549. const tableType = item.tableType ? item.tableType : ''
  550. tableTypeValue.value= item.tableType ? item.tableType : ''
  551. const classify = authBtnTabKeyType.value
  552. const keyName = `item-${index}-${pkeyIds}`
  553. if (pkeyIds) {
  554. if (isStatus.value !== '3' && item.isTableForm) {
  555. uploadModal.value = true
  556. uploadData.value = getFormDataInit(item,pkeyIds)
  557. uploadData.value.tableType =tableType
  558. uploadData.value.classify =classify
  559. uploadData.value.id =id
  560. console.log( uploadData.value,' uploadData.value');
  561. //获取文件列表
  562. getBussFileList(pkeyIds)
  563. } else if (!item.isRenderTableForm) {
  564. CollapseChange(keyName)
  565. window?.$message?.warning('请再次点击上传')
  566. } else if (!item.isTableForm) {
  567. window?.$message?.warning('暂无表单数据')
  568. } else {
  569. window?.$message?.warning('已上报的资料,不允许上传')
  570. }
  571. } else {
  572. window?.$message?.warning('pkeyId为空')
  573. }
  574. }
  575. //获取文件列表
  576. const getBussFileList = async (pkeyId) => {
  577. const { id } = baseData.value
  578. const {error, code, data} = await wbsApi.getBussFileList1({
  579. pkeyid: pkeyId,
  580. id:id
  581. })
  582. if (!error && code === 200) {
  583. fileListData.value = getArrValue(data)
  584. } else {
  585. fileListData.value = []
  586. }
  587. }
  588. //上传文件
  589. const uploadChange = async ({type}) => {
  590. if(type === 'success') {
  591. uploadModal.value = false
  592. renewData()
  593. } else if (type === 'del') {
  594. renewData()
  595. }
  596. }
  597. //相关变量
  598. const tableFormItemNode = ref({})
  599. //菜单数据
  600. const tableFormMenu = ref([
  601. {label: '容器参数', key: "vessel"},
  602. {label: '引用设备仪器', key: "device"},
  603. {label: '插入特殊字符', key: "special"},
  604. ])
  605. //鼠标右键事件
  606. const contextMenuRef = ref(null)
  607. const onRightClick = (event, KeyName, index) => {
  608. //取光标位置
  609. const specialDom = document.getElementById(KeyName + "")
  610. const startPos = specialDom?.selectionStart || 0
  611. const endPos = specialDom?.selectionEnd || 0
  612. //存储临时信息
  613. tableFormItemNode.value = {KeyName, index, startPos, endPos, pkeyId: formKeyIds.value}
  614. contextMenuRef.value?.showMenu(event) //展开菜单
  615. }
  616. //鼠标右键菜单被点击
  617. const handleMenuSelect = ({key}) => {
  618. if (key === 'vessel') {
  619. vesselModal.value = true
  620. getMenusData()
  621. } else if (key === 'special') {
  622. specialModalShow()
  623. } else if (key === 'device') {
  624. deviceModal.value = true
  625. getequipmentMenusData()
  626. }
  627. }
  628. //引用容器参数
  629. const vesselModal = ref(false)
  630. const vesselTableRef = ref(null)
  631. //引用容器参数菜单数据
  632. const menuProps = {
  633. key: 'id',
  634. label: 'containerName',
  635. }
  636. //引用容器参数菜单数据
  637. const equipmentmenuProps = {
  638. key: 'id',
  639. label: 'className',
  640. }
  641. const menus = ref([]);
  642. const getMenusData = async () => {
  643. const { data } = await dataApi1.queryClassification({
  644. projectId: projectId.value,
  645. contractId: contractId.value
  646. })
  647. const arr = getArrValue(data)
  648. menus.value = arr
  649. if (arr.length > 0) {
  650. const item = arr[0]
  651. console.log(item,'item');
  652. menuItem.value = item
  653. menuKey.value = item?.id
  654. getVesselTableData()
  655. }
  656. }
  657. //菜单被点击
  658. const menuKey = ref()
  659. const menuItem = ref({})
  660. const menuChange = (item) => {
  661. menuItem.value = item
  662. menuKey.value = item?.id
  663. getVesselTableData()
  664. }
  665. //表格数据
  666. const vesselTableColumn = ref([
  667. {key:'key_1', name: '容器编号'},
  668. ])
  669. const vesselTableData = ref([])
  670. const vesselTablePage = ref({current: 1, size: 20, total: 0})
  671. const vesselTablePageChange = ({current, size}) => {
  672. vesselTablePage.value.current = current
  673. vesselTablePage.value.size = size
  674. getVesselTableData()
  675. }
  676. //获取表格数据
  677. const vesselTableLoading = ref(false)
  678. const getVesselTableData = async () => {
  679. const {id, fieldList} = menuItem.value
  680. const fieldLists = getArrValue(fieldList)
  681. if (fieldLists.length > 0) {
  682. vesselTableLoading.value = true
  683. const { error, code, data } = await dataApi1.queryPage({
  684. projectId: projectId.value,
  685. contractId: contractId.value,
  686. containerId: menuKey.value,
  687. fieldKey:fieldList[0].fieldKey,
  688. size:vesselTablePage.value.size,
  689. current:vesselTablePage.value.current,
  690. })
  691. //处理数据
  692. vesselTableLoading.value = false
  693. if (!error && code === 200) {
  694. vesselTableData.value = getArrValue(data['records'])
  695. vesselTablePage.value.total = data.total || 0
  696. } else {
  697. vesselTableData.value = []
  698. vesselTablePage.value.total = 0
  699. }
  700. }
  701. }
  702. //多选
  703. const vesselTableKeys = ref([]);
  704. const vesselTableSelection = (rows) => {
  705. vesselTableKeys.value = rows
  706. }
  707. //确认引用
  708. const vesselModalSave = () => {
  709. if (vesselTableKeys.value.length>0) {
  710. const item = tableFormItemNode.value
  711. const form = formData.value[item.index]
  712. const val =[]
  713. vesselTableKeys.value.forEach((item)=>{
  714. val.push(item.key_1)
  715. })
  716. const newval=val.join('、')
  717. formData.value[item.index][item.KeyName] = setPosInsert(item.startPos, item.endPos, form[item.KeyName], newval)
  718. vesselModal.value = false
  719. let posVal = item.startPos + newval.length;
  720. nextTick(() => {
  721. setPosRange(item.KeyName, posVal)
  722. })
  723. }else{
  724. window?.$message?.warning('请先选择引用容器参数')
  725. }
  726. }
  727. //关闭
  728. const vesselModalClose = () => {
  729. vesselModal.value = false
  730. }
  731. const equipmentmenus = ref([]);
  732. const getequipmentMenusData = async () => {
  733. const { data } = await getClassList({
  734. projectId: projectId.value,
  735. contractId: contractId.value
  736. })
  737. const arr = getArrValue(data)
  738. equipmentmenus.value = arr
  739. if (arr.length > 0) {
  740. const item = arr[0]
  741. equipmentmenuItem.value = item
  742. equipmentmenuKey.value = item?.id
  743. getDeviceTableData()
  744. }
  745. }
  746. //菜单被点击
  747. const equipmentmenuKey = ref()
  748. const equipmentmenuItem = ref({})
  749. const equipmentmenuChange = (item) => {
  750. equipmentmenuItem.value = item
  751. equipmentmenuKey.value = item?.id
  752. getDeviceTableData()
  753. }
  754. //引用设备仪器
  755. const deviceModal = ref(false)
  756. const deviceTableRef = ref(null)
  757. //表格数据
  758. const deviceTableColumn = ref([
  759. {key:'deviceNumber', name: '设备编号'},
  760. {key:'deviceName', name: '设备仪器名称'},
  761. ])
  762. const deviceTableData = ref([])
  763. const equipmentPage = ref({current: 1, size: 20, total: 0})
  764. const equipmentTablePageChange = ({current, size}) => {
  765. equipmentPage.value.current = current
  766. equipmentPage.value.size = size
  767. getDeviceTableData()
  768. }
  769. //获取表格数据
  770. const deviceTableLoading = ref(false)
  771. const getDeviceTableData =async () => {
  772. deviceTableLoading.value = true
  773. const { error, code, data } = await dataApi2.queryPage({
  774. projectId: projectId.value,
  775. contractId: contractId.value,
  776. deviceClassId: equipmentmenuKey.value,
  777. size:equipmentPage.value.size,
  778. current:equipmentPage.value.current,
  779. })
  780. //处理数据
  781. deviceTableLoading.value = false
  782. if (!error && code === 200) {
  783. deviceTableData.value = getArrValue(data['records'])
  784. vesselTablePage.value.total = data.total || 0
  785. } else {
  786. deviceTableData.value = []
  787. equipmentPage.value.total = 0
  788. }
  789. }
  790. //多选
  791. const deviceTableKeys = ref([]);
  792. const deviceTableSelection = (rows) => {
  793. deviceTableKeys.value = rows
  794. }
  795. //确认引用
  796. const deviceModalSave = () => {
  797. if (deviceTableKeys.value.length>0) {
  798. const item = tableFormItemNode.value
  799. const form = formData.value[item.index]
  800. const val =[]
  801. const idarr=[]
  802. const listr=[]
  803. deviceTableKeys.value.forEach((item)=>{
  804. val.push(item.deviceNumber)
  805. idarr.push(item.id)
  806. listr.push(item.deviceNumber+"_"+item.deviceName)
  807. })
  808. const newval=listr.join('、');
  809. const idval=idarr.join(',')
  810. formData.value[item.index][item.KeyName] = setPosInsert(item.startPos, item.endPos, form[item.KeyName], newval)
  811. vesselModal.value = false
  812. let posVal = item.startPos + newval.length;
  813. nextTick(() => {
  814. setPosRange(item.KeyName, posVal)
  815. })
  816. deviceModal.value = false;
  817. emit('updeviceUseIds', idval)
  818. }else{
  819. window?.$message?.warning('请先选择引用容器设备')
  820. }
  821. }
  822. //关闭
  823. const deviceModalClose = () => {
  824. deviceModal.value = false
  825. }
  826. //插入特殊字符
  827. const specialModal = ref(false)
  828. const specialCharacters = ref([
  829. '&#57344;', "&#57345;", "&#57346;", "&#57347;", '&#8804;', '&#8805;', '&#8451;',
  830. '&#9312;', '&#9313;', '&#9314;', '&#9315;', '&#9316;', '&#9317;', '&#9318;', '&#9319;', '&#9320;', '&#9321;', '&#9322;', '&#9323;',
  831. '&#9324;', '&#9325;', '&#9326;', '&#9327;', '&#9328;', '&#9329;', '&#9330;', '&#9331;',
  832. "&#8544;", "&#8545;", "&#8546;", "&#8547;", "&#8548;", "&#8549;", "&#8550;", "&#8551;", "&#8552;", "&#8553;", "&#8554;", "&#8555;","K̅"
  833. ])
  834. //输入框验证
  835. const specialFormRef = ref(null)
  836. const specialFormModel = ref({val: ''})
  837. const specialFormRules = {
  838. val: {
  839. required: true,
  840. trigger: "blur",
  841. message: "请选择特殊字符代码"
  842. }
  843. }
  844. //显示插入特殊字符
  845. const specialRef = ref(null)
  846. const specialModalShow = () => {
  847. specialFormModel.value.val = ''
  848. specialModal.value = true
  849. nextTick(() => {
  850. specialRef.value?.focus();
  851. })
  852. }
  853. //失去焦点
  854. const specialPos = ref({start: 0, end: 0})
  855. const specialInputBlur = (e) => {
  856. specialPos.value = {
  857. start: e?.target?.selectionStart || 0,
  858. end: e?.target?.selectionEnd || 0
  859. }
  860. }
  861. //点击符号
  862. const specialClick = (event) => {
  863. const text = event?.target?.innerText ?? ''
  864. const start = specialPos.value.start
  865. const end = specialPos.value.end
  866. const form = specialFormModel.value.val
  867. specialFormModel.value.val = setPosInsert(start, end, form, text)
  868. specialRef.value?.focus();
  869. let posVal = start + text.length;
  870. nextTick(() => {
  871. setPosRange('specialId', posVal)
  872. })
  873. }
  874. //确认插入
  875. const specialNodeClick = async () => {
  876. const res = await formValidate(specialFormRef.value)
  877. if (res) {
  878. const item = tableFormItemNode.value
  879. const form = formData.value[item.index]
  880. const val = specialFormModel.value.val ?? ''
  881. formData.value[item.index][item.KeyName] = setPosInsert(item.startPos, item.endPos, form[item.KeyName], val)
  882. specialModal.value = false
  883. specialRef.value?.focus();
  884. let posVal = item.startPos + val.length;
  885. nextTick(() => {
  886. setPosRange(item.KeyName, posVal)
  887. })
  888. }
  889. }
  890. //事件
  891. const emit = defineEmits(['renew','offsetTop','updeviceUseIds','upcheckTableId'])
  892. //被点击
  893. const getOffsetTop = (key = '') => {
  894. if (key) {
  895. const dom = document.getElementById(key)
  896. emit('offsetTop', dom.offsetTop)
  897. } else {
  898. emit('offsetTop', 0)
  899. }
  900. }
  901. //通知数据更新
  902. const renewData = () => {
  903. emit('renew')
  904. ActiveKey.value = ''
  905. }
  906. //获取表单数据
  907. const getFormData = () => {
  908. const formArr = formData.value;
  909. console.log( formData.value,' formData.value');
  910. return formArr.filter(({pkeyId, isCollapseLoad}) => {
  911. return (pkeyId ?? '') !== '' && isCollapseLoad;
  912. })
  913. }
  914. //获取表单效验数据
  915. const getFormRegExpJson = () => {
  916. return deepClone(formRegExpJson.value);
  917. }
  918. //获取当前展开项
  919. const getActiveKey = () => {
  920. return ActiveKey.value;
  921. }
  922. //设置当前展开项
  923. const setActiveKey = (key) => {
  924. return ActiveKey.value = key;
  925. }
  926. // 暴露出去
  927. defineExpose({
  928. getFormData,
  929. getFormRegExpJson,
  930. getActiveKey,
  931. setActiveKey
  932. })
  933. </script>
  934. <style lang="scss" scoped>
  935. .data-fill-list-box {
  936. position: relative;
  937. //margin-bottom: 25%;
  938. .hc-collapse-item-header {
  939. flex: 1;
  940. position: relative;
  941. margin-left: 46px;
  942. display: flex;
  943. align-items: center;
  944. .item-title {
  945. flex: 1;
  946. position: relative;
  947. user-select: none;
  948. color: #50545E;
  949. font-size: 16px;
  950. font-weight: 400;
  951. cursor: pointer;
  952. }
  953. .hc-extra-text-box {
  954. position: relative;
  955. padding-right: 24px;
  956. }
  957. }
  958. .data-fill-list-item-content {
  959. position: relative;
  960. display: flex;
  961. height: calc(100vh - 428px);
  962. .data-fill-table-form-box {
  963. position: relative;
  964. padding: 24px 20px;
  965. height: 100%;
  966. overflow: auto;
  967. flex: 1;
  968. .hc-no-table-form {
  969. position: relative;
  970. height: 100%;
  971. display: flex;
  972. justify-content: center;
  973. align-items: center;
  974. .table-form-no {
  975. position: relative;
  976. img {
  977. width: 350px;
  978. }
  979. .desc {
  980. text-align: center;
  981. font-size: 20px;
  982. color: #aaa;
  983. }
  984. }
  985. }
  986. }
  987. .data-fill-table-tip-box {
  988. width: 240px;
  989. position: relative;
  990. border-left: 1px solid #E9E9E9;
  991. padding: 20px 15px 80px;
  992. .tip-title {
  993. font-size: 16px;
  994. margin-bottom: 10px;
  995. display: flex;
  996. align-items: center;
  997. }
  998. .tip-item {
  999. margin-bottom: 20px;
  1000. }
  1001. .table-tip-foot {
  1002. position: absolute;
  1003. bottom: 15px;
  1004. right: 0;
  1005. left: 0;
  1006. display: flex;
  1007. align-items: center;
  1008. padding: 0 15px;
  1009. .tip-left-btn {
  1010. flex: 1;
  1011. .dow-text {
  1012. cursor: pointer;
  1013. display: flex;
  1014. align-items: center;
  1015. }
  1016. }
  1017. }
  1018. }
  1019. }
  1020. }
  1021. .special-box {
  1022. position: relative;
  1023. display: flex;
  1024. justify-content: center;
  1025. align-items: center;
  1026. border: 1px solid #eee;
  1027. border-radius: 3px;
  1028. height: 52px;
  1029. width: 52px;
  1030. cursor: pointer;
  1031. user-select: none;
  1032. transition: color .3s, background-color .3s;
  1033. &:hover {
  1034. color: var(--el-color-primary);
  1035. background-color: var(--el-color-primary-light-8);
  1036. }
  1037. .font-EUDC {
  1038. font-size: 22px;
  1039. }
  1040. }
  1041. </style>
  1042. <style lang="scss">
  1043. .data-fill-list-box {
  1044. .el-collapse {
  1045. --el-collapse-header-height: 60px;
  1046. border: 0;
  1047. .el-collapse-item {
  1048. margin: 0 0 16px;
  1049. background-color: #f1f5f8;
  1050. border: 1px solid #E9E9E9;
  1051. border-radius: 4px;
  1052. }
  1053. .el-collapse-item__header {
  1054. background-color: transparent;
  1055. font-weight: 400;
  1056. border-bottom: 0;
  1057. cursor: default;
  1058. font-size: 14px;
  1059. .el-collapse-item__arrow {
  1060. position: absolute;
  1061. color: #50545E;
  1062. cursor: pointer;
  1063. left: 20px;
  1064. margin: 0;
  1065. }
  1066. }
  1067. .el-collapse-item.is-active .el-collapse-item__header.is-active {
  1068. background-color: #E7EEF4;
  1069. }
  1070. .el-collapse-item__wrap {
  1071. background-color: transparent;
  1072. border-bottom: 0;
  1073. .el-collapse-item__content {
  1074. position: relative;
  1075. padding-bottom: 0;
  1076. font-size: 14px;
  1077. color: #50545E;
  1078. line-height: initial;
  1079. }
  1080. }
  1081. }
  1082. }
  1083. //插入特殊字符弹窗的输入框
  1084. .data-fill-list-box .data-fill-table-form-box td,
  1085. .data-fill-list-box .data-fill-table-form-box td .el-input .el-input__wrapper .el-input__inner,
  1086. .el-form-item.special-form-item .el-form-item__content .el-input .el-input__wrapper .el-input__inner {
  1087. font-family: "EUDC", 宋体, v-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  1088. }
  1089. //引用容器参数弹窗
  1090. //关联试验数据
  1091. .adding-form-dialog-box {
  1092. position: relative;
  1093. height: 100%;
  1094. display: flex;
  1095. .dialog-tree-box {
  1096. position: relative;
  1097. border-right: 1px solid #EEEEEE;
  1098. width: 500px;
  1099. height: 100%
  1100. }
  1101. .dialog-table-box {
  1102. position: relative;
  1103. flex: 1;
  1104. height: 100%;
  1105. padding: 18px;
  1106. .dialog-search {
  1107. position: relative;
  1108. display: flex;
  1109. }
  1110. .dialog-table {
  1111. position: relative;
  1112. height: calc(100% - 68px);
  1113. padding: 18px 0;
  1114. }
  1115. .dialog-pages {
  1116. position: relative;
  1117. }
  1118. }
  1119. }
  1120. </style>