equipCheckRecordEditor.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <route lang="json5" type="page">
  2. {
  3. layout: 'default',
  4. style: {
  5. navigationBarTitleText: '',
  6. navigationStyle: 'custom',
  7. disableScroll: true,
  8. },
  9. }
  10. </route>
  11. <!-- 检测记录编辑 -->
  12. <template>
  13. <view>
  14. <!-- 相比于 SpreadDesignerGeneric 悬浮输入框,有拍摄图片,但是导航栏没有扩展性 -->
  15. <SpreadDesigner
  16. ref="spreadDesignerRef"
  17. :checkItemData="checkItemData"
  18. :reportList="reportList"
  19. :taskOrderItem="taskOrderItem"
  20. :templateBlob="templateBlob"
  21. @save="handleSave"
  22. @cancel="handleCancel"
  23. @close="handleCancel"
  24. @openCamera="handleOpenCamera"
  25. @selectedReport="handleSelectedReport"
  26. />
  27. </view>
  28. </template>
  29. <script setup lang="ts">
  30. import { ref } from 'vue'
  31. import SpreadDesigner from '@/components/SpreadDesigner/spreadDesigner.vue'
  32. import { onLoad } from '@dcloudio/uni-app'
  33. import { getCheckerEquipmentDetailById, getDynamicTbVal, saveDynamicTbVal } from '@/api/task'
  34. import { getStandardTemplate } from '@/api/index'
  35. import { buildFileUrl } from '@/utils/index'
  36. import { PressureCheckerMyTaskStatus } from '@/utils/dictMap'
  37. const spreadDesignerRef = ref<any>(null)
  38. const checkItemData = ref<any>(null)
  39. const reportList = ref<any[]>([])
  40. const taskOrderItem = ref<any>(null)
  41. const templateBlob = ref<string>('')
  42. let orderItemId = ''
  43. let checkItemId = ''
  44. let useOnline = ''
  45. let templateId = ''
  46. let equipCode = ''
  47. let reportUrlParam = ''
  48. const init = async () => {
  49. await handleGetCheckItemDetail(checkItemId, templateId)
  50. await getDetail()
  51. }
  52. const handleGetCheckItemDetail = async (
  53. reportId: string | undefined,
  54. newTemplateId: string | undefined,
  55. ) => {
  56. const isTemplateSwitch =
  57. checkItemData.value?.checkItemId && checkItemData.value.checkItemId !== reportId
  58. if (!reportId) {
  59. console.error('reportId 为空,无法获取模板详情')
  60. return
  61. }
  62. if (useOnline === '1') {
  63. const templateResult = await getStandardTemplate({ id: newTemplateId || '' })
  64. const templateDetail = (templateResult as any).data
  65. if (!templateDetail) {
  66. uni.showToast({ title: '模板缺失了,请检查!', icon: 'error' })
  67. uni.navigateBack()
  68. return
  69. }
  70. const dynamicTbResp = await getDynamicTbVal({
  71. refId: reportId,
  72. })
  73. const dynamicTb = dynamicTbResp.data
  74. const initJSONResult = {}
  75. for (let i = 0; i < dynamicTb.dynamicTbValRespVOList.length; i++) {
  76. const item = dynamicTb.dynamicTbValRespVOList[i]
  77. initJSONResult[item.colCode] = item.valValue
  78. }
  79. const recordTemplateUrl: string | undefined = templateDetail.fileUrl
  80. const blob = await getBlob(recordTemplateUrl || '')
  81. const dic = {
  82. blob: blob || '',
  83. reportUrl: recordTemplateUrl || '',
  84. instId: dynamicTb?.dynamicTbInsRespVO?.id || '',
  85. bindingPathSchema: templateDetail?.bindingPathSchema || '',
  86. bindingPathNameJson: templateDetail?.bindingPathNameJson,
  87. prepareJson: (initJSONResult as any) || '',
  88. reportName: templateDetail?.name || '',
  89. reportType: templateDetail?.reportType || '',
  90. taskStatus: templateDetail?.taskStatus || '',
  91. checkItemId: reportId,
  92. templateId: newTemplateId,
  93. templateUrl: recordTemplateUrl || '',
  94. }
  95. checkItemData.value = dic
  96. return dic
  97. } else {
  98. checkItemData.value = {
  99. blob: '',
  100. reportUrl: reportUrlParam || '',
  101. bindingPathSchema: '',
  102. bindingPathNameJson: {},
  103. prepareJson: '{}',
  104. reportName: '本地模板',
  105. reportType: 100,
  106. taskStatus: 200,
  107. checkItemId: reportId,
  108. }
  109. return checkItemData.value
  110. }
  111. }
  112. const getDetail = async () => {
  113. if (useOnline === '1') {
  114. const result = await getCheckerEquipmentDetailById({ id: orderItemId })
  115. if (result) {
  116. const resData = (result as any).data
  117. const resDataReportList = resData?.reportList
  118. let filteredReportList = []
  119. if (resDataReportList) {
  120. filteredReportList = resDataReportList
  121. .map((item: any) => ({
  122. ...item,
  123. equipId: resData.taskOrderItem.equipId,
  124. equipCode: resData.taskOrderItem.equipCode,
  125. }))
  126. .filter((item: any) =>
  127. [
  128. PressureCheckerMyTaskStatus.CONFIRMED,
  129. PressureCheckerMyTaskStatus.RECORD_INPUT,
  130. ].includes(item.taskStatus),
  131. )
  132. }
  133. reportList.value = filteredReportList
  134. taskOrderItem.value = resData?.taskOrderItem
  135. }
  136. }
  137. }
  138. const getBlob = async (url: string): Promise<string> => {
  139. if (!url) return ''
  140. const fileUrl = buildFileUrl(url)
  141. return downloadFileAsBase64(fileUrl)
  142. }
  143. const downloadFileAsBase64 = (fileUrl: string): Promise<string> => {
  144. return new Promise((resolve, reject) => {
  145. uni.request({
  146. url: fileUrl,
  147. method: 'GET',
  148. responseType: 'arraybuffer',
  149. success: (res) => {
  150. if (res.statusCode === 200) {
  151. const arrayBuffer = res.data as ArrayBuffer
  152. const uint8Array = new Uint8Array(arrayBuffer)
  153. const binaryString = uint8Array.reduce((data, byte) => {
  154. return data + String.fromCharCode(byte)
  155. }, '')
  156. const base64 = btoa(binaryString)
  157. resolve(base64)
  158. } else {
  159. reject(new Error(`Request failed with status ${res.statusCode}`))
  160. }
  161. },
  162. fail: (err) => {
  163. reject(err)
  164. },
  165. })
  166. })
  167. }
  168. const handleSave = async (data: any) => {
  169. try {
  170. if (useOnline === '1') {
  171. const instId = data.instId
  172. const result = await saveDynamicTbVal({ params: data.prepareJson, instId })
  173. if (result?.code === 0 && result?.data) {
  174. uni.showToast({ title: '保存成功', icon: 'success' })
  175. } else {
  176. const msg = result?.msg || '保存失败'
  177. uni.showToast({ title: msg, icon: 'error' })
  178. }
  179. } else {
  180. uni.showToast({ title: '文件存储成功', icon: 'success' })
  181. uni.$emit('webViewSaved', {
  182. checkItemId: data.checkItemId,
  183. localReportUrl: data.reportUrl,
  184. bindingPathSchema: data.bindingPathSchema,
  185. prepareJson: data.prepareJson,
  186. images: data.images,
  187. })
  188. uni.navigateBack()
  189. }
  190. } catch (error) {
  191. console.error('保存失败:', error)
  192. uni.showToast({ title: '保存失败', icon: 'error' })
  193. }
  194. // try {
  195. // if (useOnline === '1') {
  196. // const uploadItems: any[] = []
  197. // if (data.blob) {
  198. // const uploadRes = await reportUploadApi({
  199. // items: [{ reportId: data.checkItemId, image: data.blob }],
  200. // })
  201. // if ((uploadRes as any)?.data) {
  202. // const uploadedUrl = Array.isArray((uploadRes as any).data)
  203. // ? (uploadRes as any).data[0]
  204. // : (uploadRes as any).data
  205. // data.reportUrl = uploadedUrl || data.reportUrl
  206. // }
  207. // }
  208. // const submitResult = await saveTaskReportTemplate({
  209. // id: data.checkItemId,
  210. // reportUrl: data.reportUrl,
  211. // prepareJson: data.prepareJson,
  212. // })
  213. // if ((submitResult as any)?.data) {
  214. // if (data.images && data.images.length > 0) {
  215. // const images = [...data.images]
  216. // for (const image of images) {
  217. // const imgUploadRes = await reportUploadApi({
  218. // items: [{ reportId: data.checkItemId, image: image.imgUrl }],
  219. // })
  220. // if ((imgUploadRes as any)?.data) {
  221. // const uploadedImgUrl = Array.isArray((imgUploadRes as any).data)
  222. // ? (imgUploadRes as any).data[0]
  223. // : (imgUploadRes as any).data
  224. // image.imgUrl = uploadedImgUrl
  225. // }
  226. // }
  227. // await saveTaskReportTemplateImages({ itemReportId: data.checkItemId, images })
  228. // }
  229. // uni.showToast({ title: '保存成功', icon: 'success' })
  230. // uni.$emit('webViewSaved', {
  231. // checkItemId: data.checkItemId,
  232. // reportUrl: data.reportUrl,
  233. // bindingPathSchema: data.bindingPathSchema,
  234. // prepareJson: data.prepareJson,
  235. // isOnline: true,
  236. // })
  237. // uni.navigateBack()
  238. // }
  239. // } else {
  240. // uni.showToast({ title: '文件存储成功', icon: 'success' })
  241. // uni.$emit('webViewSaved', {
  242. // checkItemId: data.checkItemId,
  243. // localReportUrl: data.reportUrl,
  244. // bindingPathSchema: data.bindingPathSchema,
  245. // prepareJson: data.prepareJson,
  246. // images: data.images,
  247. // })
  248. // uni.navigateBack()
  249. // }
  250. // } catch (error) {
  251. // console.error('保存失败:', error)
  252. // uni.showToast({ title: '保存失败', icon: 'error' })
  253. // }
  254. }
  255. const handleCancel = () => {
  256. uni.navigateBack()
  257. }
  258. const handleOpenCamera = () => {
  259. console.log('打开相机')
  260. }
  261. const handleSelectedReport = async (data: any) => {
  262. if (data.reportId === checkItemData.value?.checkItemId) {
  263. return
  264. }
  265. try {
  266. const dic = await handleGetCheckItemDetail(data.reportId, data.templateId)
  267. if (dic && spreadDesignerRef.value) {
  268. spreadDesignerRef.value.updateCheckItemData(dic)
  269. }
  270. } catch (error) {
  271. console.error('模板切换失败:', error)
  272. uni.showToast({ title: '模板切换失败', icon: 'error' })
  273. }
  274. }
  275. onLoad((options: any) => {
  276. orderItemId = options.orderItemId || ''
  277. checkItemId = options.checkItemId || ''
  278. useOnline = options.useOnline || '0'
  279. templateId = options.templateId || ''
  280. equipCode = options.equipCode || ''
  281. reportUrlParam = options.reportUrl || ''
  282. if (!checkItemId) {
  283. console.error('checkItemId 为空')
  284. uni.navigateBack()
  285. return
  286. }
  287. init()
  288. })
  289. </script>