editTable.vue 13 KB

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