editTable.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. <template>
  2. <hc-sys id="app-sys" class="h-full hc-ledger-table-form" navBarUi="white">
  3. <template #navBar>
  4. <hc-nav-back-bar :title="pageNode.title + '填报'">
  5. <zb-tooltip placement="bottom-end" ref="tooltipRef" v-if="currentPage > 0">
  6. <view class="hc-page-bar">
  7. <text class="i-ri-arrow-down-s-line icon"/>
  8. <text class="text">第{{currentPage}}页</text>
  9. </view>
  10. <template #content>
  11. <template v-for="item in pageTotal" :key="item">
  12. <view class="more-bar-item" @click="pageClick(item)">第{{item}}页</view>
  13. </template>
  14. </template>
  15. </zb-tooltip>
  16. </hc-nav-back-bar>
  17. </template>
  18. <view id="title-bar" class="title-bar z-24">
  19. <button type="primary" class="title-bar-btn" @click="editTypeClick">切换表单</button>
  20. <button type="primary" class="title-bar-btn" @click="linkTabClick">+ 关联工序</button>
  21. <button type="primary" class="title-bar-btn" @click="delCurrentPage" v-if="currentPage > 1">删除当前页</button>
  22. </view>
  23. <template v-if="webviewShow">
  24. <web-view :webview-styles="webViewStyle" :style="webViewStyle" :src="webSrc" name="exceliframe" @message="handleMessage"/>
  25. </template>
  26. <view id="action-bar" class="action-bar">
  27. <view class="text-bar">
  28. <view class="left" @click="copyTableFormClick">复制当前表格及内容</view>
  29. <view class="right" @click="copyTimeLogModal">复制任意时间表格及内容</view>
  30. </view>
  31. <uni-row :gutter="20">
  32. <uni-col :span="6">
  33. <button class="cu-btn round c1" @click="addFormClick">新 增</button>
  34. </uni-col>
  35. <uni-col :span="6">
  36. <button class="cu-btn round c2" @click="previewTap">预 览</button>
  37. </uni-col>
  38. <uni-col :span="6">
  39. <button class="cu-btn round c3" @click="reportModalClick">上 报</button>
  40. </uni-col>
  41. <uni-col :span="6">
  42. <button class="cu-btn round c4" @click="formSaveClick">保 存</button>
  43. </uni-col>
  44. </uni-row>
  45. </view>
  46. </hc-sys>
  47. </template>
  48. <script setup>
  49. import {ref, getCurrentInstance} from "vue";
  50. import {onLoad, onReady, onShow, onUnload} from '@dcloudio/uni-app'
  51. import {errorToast, toPdfPreview, querySelect} from "@/utils/tools";
  52. import {getObjValue, isNullES} from "js-fast-way";
  53. import {getStorage} from "@/utils/storage";
  54. import mainApi from '~api/ledger/index';
  55. import {getFormApiUrl} from '@/config/envApi';
  56. const instance = getCurrentInstance().proxy
  57. let wv; //计划创建的webview
  58. //初始变量
  59. const pageNode = ref({});
  60. const webViewStyle = ref({})
  61. const webviewShow = ref(true)
  62. const tooltipRef = ref(null)
  63. onLoad((option) => {
  64. // #ifdef H5
  65. window.addEventListener('message', handleMessage);
  66. // #endif
  67. const user = encodeURIComponent(JSON.stringify(getStorage('login_user_info')))
  68. if (option.node) {
  69. uni.showLoading({title: '加载中...', mask: true});
  70. const res = JSON.parse(decodeURIComponent(option.node));
  71. uni.setNavigationBarTitle({title: res.title + '填报'})
  72. pageNode.value = res
  73. webSrc.value = `${htmlsrc}&user=${user}&node=${option.node}`
  74. checkTheLogTaskStatus()
  75. } else {
  76. errorToast('参数错误');
  77. setTimeout(() => {
  78. toBack()
  79. },1500)
  80. }
  81. })
  82. onShow(() => {
  83. webviewShow.value = true
  84. })
  85. //表格地址
  86. const webSrc = ref('');
  87. const envUrl = getFormApiUrl()
  88. const htmlsrc = `${envUrl}/#/app/table-form?date=${new Date().getTime()}&source=app&type=log-fill`
  89. //渲染完成
  90. onReady(() => {
  91. setWebViewStyle()
  92. })
  93. //获取状态
  94. const taskStatus = ref(1)
  95. const checkTheLogTaskStatus = async () => {
  96. const {projectId, contractId, pkeyId, date} = pageNode.value
  97. const { error, code, data } = await mainApi.checkTheLogTaskStatus({
  98. projectId: projectId,
  99. contractId: contractId,
  100. nodePrimaryKeyId: pkeyId,
  101. recordTime: date,
  102. })
  103. //处理数据
  104. const res = isNullES(data) ? '' : data || ''
  105. if (!error && code === 200 && res) {
  106. //1和2的时候所有按钮皆可操作,废除 除外
  107. //3和4时, 除了预览和废除 都不行
  108. taskStatus.value = data
  109. } else {
  110. taskStatus.value = 1
  111. }
  112. }
  113. const setWebViewStyle = async () => {
  114. // #ifdef APP-PLUS
  115. await initWebview()
  116. // #endif
  117. const {height: appHeight} = await querySelect(instance, 'app-sys')
  118. const {height: navHeight} = await querySelect(instance,'hc-nav-bar')
  119. const {height: titleHeight} = await querySelect(instance,'title-bar')
  120. webViewStyle.value.top = (navHeight + titleHeight) + 'px'
  121. //底部
  122. const {height: actionHeight} = await querySelect(instance,'action-bar')
  123. webViewStyle.value.height = (appHeight - navHeight - titleHeight - actionHeight - 1) + 'px'
  124. }
  125. //初始化webview
  126. const initWebview = async () => {
  127. return new Promise((resolve) => {
  128. let currentWebview = instance.$scope.$getAppWebview()
  129. //如果是页面初始化调用时,需要延时一下
  130. setTimeout(() => {
  131. wv = currentWebview.children()[0]
  132. wv.setStyle({scalable:true})
  133. resolve(true)
  134. }, 1000);
  135. })
  136. }
  137. //接收webview消息
  138. const handleMessage = (event) => {
  139. let msg = {};
  140. // #ifdef H5
  141. if (event.data && event.data.data && event.data.data.arg) {
  142. msg = event.data.data.arg
  143. }
  144. // #endif
  145. // #ifdef APP-PLUS
  146. msg = event.detail.data[0]
  147. // #endif
  148. if (msg.source === 'web') {
  149. console.log('收到web消息', msg)
  150. setMsgData(msg)
  151. }
  152. }
  153. // 处理接收到的消息
  154. const isFormRender = ref(false)
  155. const setMsgData = ({type, data}) => {
  156. //表格数量
  157. if (type === 'formRender') {
  158. uni.hideLoading();
  159. isFormRender.value = true
  160. }
  161. //表格数量
  162. if (type === 'formLength') {
  163. pageTotal.value = Number(data)
  164. }
  165. //当前表格
  166. if (type === 'formIndex') {
  167. const {id, page} = getObjValue(data)
  168. itemFormId.value = id //当前表格id
  169. currentPage.value = page //当前页码
  170. }
  171. //pdf预览
  172. if (type === 'formPdfUrl') {
  173. uni.hideLoading();
  174. previewPdf(data)
  175. }
  176. //保存结果
  177. if (type === 'saveRes') {
  178. uni.hideLoading();
  179. saveResData(data)
  180. }
  181. //消息提示
  182. if (type === 'msg') {
  183. uni.hideLoading();
  184. const { title, icon } = getObjValue(data)
  185. uni.showToast({
  186. title: title,
  187. duration: 2000,
  188. icon: icon,
  189. mask: true
  190. });
  191. }
  192. }
  193. //页码
  194. const pageTotal = ref(0)
  195. const currentPage = ref(0)
  196. const itemFormId = ref('')
  197. //切换页码
  198. const pageClick = (item) => {
  199. tooltipRef.value?.close()
  200. if (item !== currentPage) {
  201. postMsg({
  202. type: 'pageTap',
  203. data: item -1,
  204. fun: `pageTap('${item -1}')`
  205. })
  206. }
  207. }
  208. const toBack = () => {
  209. webviewShow.value = false
  210. uni.navigateBack()
  211. }
  212. //切换显示模式
  213. const editType = ref('form')
  214. const editTypeClick = () => {
  215. if (isFormRender.value === false) {
  216. errorToast('表单未渲染完成,请稍后再试');
  217. return
  218. }
  219. const type = editType.value === 'form' ? 'table' : 'form'
  220. postMsg({
  221. type: 'editTypeClick',
  222. data: type,
  223. fun: `editTypeClick('${type}')`
  224. })
  225. editType.value = type
  226. }
  227. //关联工序
  228. const linkTabClick = () => {
  229. if (isFormRender.value === false) {
  230. errorToast('表单未渲染完成,请稍后再试');
  231. return
  232. }
  233. uni.navigateTo({
  234. url: '/pages/ledger/linkTab?id=' + itemFormId.value,
  235. events: {
  236. finish: (data) => {
  237. linkTabFinish(data)
  238. }
  239. }
  240. });
  241. }
  242. //通知更新关联工序数据
  243. const linkTabFinish = (data) => {
  244. const ids = data.length > 0 ? JSON.stringify(data) : ''
  245. postMsg({
  246. type: 'linkIds',
  247. data: ids,
  248. fun: `linkIdsTap('${ids}')`
  249. })
  250. }
  251. //新增表格
  252. const addFormClick = () => {
  253. if (isFormRender.value === false) {
  254. errorToast('表单未渲染完成,请稍后再试');
  255. return
  256. }
  257. postMsg({
  258. type: 'addForm',
  259. fun: `addFormTap()`
  260. })
  261. }
  262. //复制当前表格及内容
  263. const copyTableFormClick = () => {
  264. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  265. errorToast('当前状态不可操作');
  266. return
  267. }
  268. postMsg({
  269. type: 'copyFormData',
  270. fun: `copyFormData()`
  271. })
  272. }
  273. //复制任意时间
  274. const copyTimeLogModal = () => {
  275. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  276. errorToast('当前状态不可操作');
  277. return
  278. }
  279. uni.navigateTo({
  280. url: '/pages/ledger/copyTime?node=' + encodeURIComponent(JSON.stringify(pageNode.value)),
  281. events: {
  282. finish: () => {
  283. flushedPage()
  284. }
  285. }
  286. })
  287. }
  288. //删除当前页
  289. const delCurrentPage = () => {
  290. if (isFormRender.value === false) {
  291. errorToast('表单未渲染完成,请稍后再试');
  292. return
  293. }
  294. postMsg({
  295. type: 'delForm',
  296. fun: `delFormTap()`
  297. })
  298. }
  299. //预览表单PDF
  300. const previewTap = () => {
  301. if (!isFormRender.value || taskStatus.value === 1) {
  302. errorToast('当前状态不可操作');
  303. return
  304. }
  305. uni.showLoading({title: '获取数据中...', mask: true});
  306. postMsg({
  307. type: 'getPdfUrl',
  308. fun: `getPdfUrl()`
  309. })
  310. }
  311. //预览表单
  312. const previewPdf = (data) => {
  313. uni.hideLoading();
  314. if (!data) {
  315. errorToast('暂无PDF,无法预览');
  316. return
  317. }
  318. //预览文件
  319. toPdfPreview(data)
  320. }
  321. //保存
  322. const formSaveClick = () => {
  323. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  324. errorToast('当前状态不可操作');
  325. return
  326. }
  327. uni.showLoading({title: '保存中...', mask: true})
  328. postMsg({
  329. type: 'formSave',
  330. fun: `formSave()`
  331. })
  332. }
  333. //保存结果
  334. const saveResData = (data) => {
  335. if (data === 'success') {
  336. uni.showLoading({title: '获取预览中...', mask: true})
  337. //flushedPage()
  338. }
  339. }
  340. //上报
  341. const reportModalClick = () => {
  342. const status = taskStatus.value
  343. if (!isFormRender.value || status === 1 || status === 3 || status === 4) {
  344. errorToast('当前状态不可操作');
  345. return
  346. }
  347. const {projectId, contractId, pkeyId, date, taskName} = pageNode.value
  348. //路由跳转
  349. uni.navigateTo({
  350. url: '/pages/report/report',
  351. events:{
  352. finish: () => {
  353. flushedPage()
  354. }
  355. },
  356. success:(res) => {
  357. res.eventChannel.emit('reportProps', {
  358. type: "log",
  359. typeData: pkeyId,
  360. projectId: projectId,
  361. contractId: contractId,
  362. taskName: taskName,
  363. url: 'contractLog/startTaskTheLog',
  364. addition: {
  365. nodePrimaryKeyId: pkeyId,
  366. recordTime: date,
  367. },
  368. })
  369. }
  370. });
  371. }
  372. //发送消息
  373. const postMsg = ({type, data, fun}) => {
  374. // #ifdef H5
  375. window.frames["exceliframe"].postMessage({
  376. type: type,
  377. source: 'app',
  378. data: data ?? {}
  379. }, envUrl);
  380. // #endif
  381. // #ifdef APP-PLUS
  382. if (fun) wv.evalJS(fun)
  383. // #endif
  384. }
  385. //刷新页面
  386. const flushedPage = () => {
  387. webviewShow.value = false
  388. checkTheLogTaskStatus()
  389. setTimeout(() => {
  390. webviewShow.value = true
  391. }, 500);
  392. }
  393. onUnload(()=>{
  394. // #ifdef H5
  395. window.removeEventListener('message', handleMessage);
  396. // #endif
  397. })
  398. </script>
  399. <style lang="scss" scoped>
  400. page {
  401. height: 100%;
  402. background: #FAFBFE;
  403. }
  404. </style>
  405. <style lang="scss">
  406. @import "@/style/ledger/edit-table.scss";
  407. </style>