editTable.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  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. uni.navigateTo({
  244. url: '/pages/ledger/linkTab?id=' + itemFormId.value,
  245. events: {
  246. finish: (data) => {
  247. linkTabFinish(data)
  248. }
  249. }
  250. });
  251. }
  252. //通知更新关联工序数据
  253. const linkTabFinish = (data) => {
  254. const ids = data.length > 0 ? JSON.stringify(data) : ''
  255. postMsg({
  256. type: 'linkIds',
  257. data: ids,
  258. fun: `linkIdsTap('${ids}')`
  259. })
  260. }
  261. //新增表格
  262. const addFormClick = () => {
  263. if (isFormRender.value === false) {
  264. errorToast('表单未渲染完成,请稍后再试');
  265. return
  266. }
  267. postMsg({
  268. type: 'addForm',
  269. fun: `addFormTap()`
  270. })
  271. }
  272. //复制当前表格及内容
  273. const copyTableFormClick = () => {
  274. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  275. errorToast('当前状态不可操作');
  276. return
  277. }
  278. postMsg({
  279. type: 'copyFormData',
  280. fun: `copyFormData()`
  281. })
  282. }
  283. //复制任意时间
  284. const copyTimeLogModal = () => {
  285. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  286. errorToast('当前状态不可操作');
  287. return
  288. }
  289. uni.navigateTo({
  290. url: '/pages/ledger/copyTime?node=' + encodeURIComponent(JSON.stringify(pageNode.value)),
  291. events: {
  292. finish: () => {
  293. flushedPage()
  294. }
  295. }
  296. })
  297. }
  298. //删除当前页
  299. const delCurrentPage = () => {
  300. if (isFormRender.value === false) {
  301. errorToast('表单未渲染完成,请稍后再试');
  302. return
  303. }
  304. postMsg({
  305. type: 'delForm',
  306. fun: `delFormTap()`
  307. })
  308. }
  309. //预览表单PDF
  310. const previewTap = () => {
  311. if (!isFormRender.value || taskStatus.value === 1) {
  312. errorToast('当前状态不可操作');
  313. return
  314. }
  315. uni.showLoading({title: '获取数据中...', mask: true});
  316. postMsg({
  317. type: 'getPdfUrl',
  318. fun: `getPdfUrl()`
  319. })
  320. }
  321. //预览表单
  322. const previewPdf = (data) => {
  323. uni.hideLoading();
  324. if (!data) {
  325. errorToast('暂无PDF,无法预览');
  326. return
  327. }
  328. //预览文件
  329. toPdfPreview(data)
  330. }
  331. //保存
  332. const formSaveClick = () => {
  333. if (!isFormRender.value || taskStatus.value === 3 || taskStatus.value === 4) {
  334. errorToast('当前状态不可操作');
  335. return
  336. }
  337. uni.showLoading({title: '保存中...', mask: true})
  338. postMsg({
  339. type: 'formSave',
  340. fun: `formSave()`
  341. })
  342. }
  343. //保存结果
  344. const saveResData = async (data) => {
  345. await checkTheLogTaskStatus()
  346. if (data === 'success') {
  347. previewTap()
  348. }
  349. }
  350. //上报
  351. const reportModalClick = () => {
  352. const status = taskStatus.value
  353. if (!isFormRender.value || status === 1 || status === 3 || status === 4) {
  354. errorToast('当前状态不可操作');
  355. return
  356. }
  357. const {projectId, contractId, pkeyId, date, taskName} = pageNode.value
  358. //路由跳转
  359. uni.navigateTo({
  360. url: '/pages/report/report',
  361. events:{
  362. finish: () => {
  363. flushedPage()
  364. }
  365. },
  366. success:(res) => {
  367. res.eventChannel.emit('reportProps', {
  368. type: "log",
  369. typeData: pkeyId,
  370. projectId: projectId,
  371. contractId: contractId,
  372. taskName: taskName,
  373. url: 'contractLog/startTaskTheLog',
  374. addition: {
  375. nodePrimaryKeyId: pkeyId,
  376. recordTime: date,
  377. },
  378. })
  379. }
  380. });
  381. }
  382. //发送消息
  383. const postMsg = ({type, data, fun}) => {
  384. // #ifdef H5
  385. window.frames["exceliframe"].postMessage({
  386. type: type,
  387. source: 'app',
  388. data: data ?? {}
  389. }, envUrl);
  390. // #endif
  391. // #ifdef APP-PLUS
  392. if (fun) wv.evalJS(fun)
  393. // #endif
  394. }
  395. //刷新页面
  396. const flushedPage = () => {
  397. webviewShow.value = false
  398. checkTheLogTaskStatus()
  399. setTimeout(() => {
  400. webviewShow.value = true
  401. }, 500);
  402. }
  403. onUnload(()=>{
  404. // #ifdef H5
  405. window.removeEventListener('message', handleMessage);
  406. // #endif
  407. })
  408. </script>
  409. <style lang="scss" scoped>
  410. page {
  411. height: 100%;
  412. background: #FAFBFE;
  413. }
  414. </style>
  415. <style lang="scss">
  416. @import "@/style/ledger/edit-table.scss";
  417. </style>