image-view.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template>
  2. <div class="hc-layout-box">
  3. <div :style="`width:${leftWidth}px;`" class="hc-layout-left-box bg-white">
  4. <template v-if="dataType === 1">
  5. <div class="hc-project-box">
  6. <div class="hc-project-icon-box">
  7. <HcIcon name="stack" />
  8. </div>
  9. <div class="project-name-box ml-2">
  10. <span class="project-alias">{{ projectInfo.projectName }}</span>
  11. </div>
  12. </div>
  13. <div v-if="dataType === 1" class="hc-tree-box">
  14. <el-scrollbar>
  15. <WbsTree
  16. :auto-expand-keys="TreeAutoExpandKeys" :contract-id="contractId" :project-id="projectId"
  17. :class-id="dataId" @node-tap="nodeWbsElTreeClick"
  18. />
  19. </el-scrollbar>
  20. </div>
  21. </template>
  22. <div v-else class="hc-tree-box date-tree">
  23. <el-scrollbar v-if="dataType === 2">
  24. <HcTreeData
  25. :auto-expand-keys="TreeExpandedKeys" :datas="dateElTreeData"
  26. @node-tap="dateWbsElTreeClick"
  27. />
  28. </el-scrollbar>
  29. </div>
  30. <!-- 左右拖动 -->
  31. <div class="horizontal-drag-line" @mousedown="onmousedown" />
  32. </div>
  33. <div class="hc-layout-content-box">
  34. <HcNewCard :scrollbar="false" action-size="lg">
  35. <template #header>
  36. <HcTooltip keys="image-data-add">
  37. <el-button :disabled="!queryKey && dataType === 1" hc-btn type="primary" @click="addFormFile">
  38. <HcIcon name="add_box" />
  39. <span>新增文件</span>
  40. </el-button>
  41. </HcTooltip>
  42. <HcTooltip keys="image-data-download">
  43. <el-button
  44. :disabled="tableCheckedKeys.length <= 0" :loading="downloadLoading" hc-btn
  45. @click="downloadClick"
  46. >
  47. <HcIcon name="download" />
  48. <span>下载图片</span>
  49. </el-button>
  50. </HcTooltip>
  51. <HcTooltip keys="image-data-download">
  52. <el-button
  53. :disabled="tableCheckedKeys.length <= 0" :loading="downPdfLoading" hc-btn
  54. @click="downloadPdfClick"
  55. >
  56. <HcIcon name="download" />
  57. <span>下载PDF</span>
  58. </el-button>
  59. </HcTooltip>
  60. <HcTooltip keys="image-data-album">
  61. <el-button
  62. :disabled="tableCheckedKeys.length <= 0" :loading="downPdfLoading" hc-btn
  63. @click="combineAlbumClick"
  64. >
  65. <HcIcon name="play-list-add" />
  66. <span>组成相册</span>
  67. </el-button>
  68. </HcTooltip>
  69. <HcTooltip keys="image-data-del">
  70. <el-button
  71. :disabled="tableCheckedKeys.length <= 0" :loading="delLoading" hc-btn
  72. @click="delClick"
  73. >
  74. <HcIcon name="delete" />
  75. <span>删除</span>
  76. </el-button>
  77. </HcTooltip>
  78. </template>
  79. <template #extra>
  80. <div class="w-60">
  81. <el-input v-model="searchForm.queryStr" clearable placeholder="根据题名名称或拍摄者搜索" @keyup="keyUpEvent" />
  82. </div>
  83. <div class="ml-2">
  84. <el-button type="primary" @click="searchClick">搜索</el-button>
  85. </div>
  86. </template>
  87. <HcTable
  88. ref="tableListRef" :column="tableListColumn" :datas="tableListData" :loading="tableLoading"
  89. is-new :index-style="{ width: 60 }" is-check :check-style="{ width: 29 }"
  90. @selection-change="tableSelectionChange"
  91. >
  92. <template #info="{ row }">
  93. <div class="hc-table-col-item">
  94. <div v-if="row.type !== 1" class="img-box">
  95. <HcImg :src="setImageUrl(row.imageUrl)" class="hc-image" :is-https="isHttps" />
  96. </div>
  97. <div v-else class="img-box">
  98. <video :src="row.imageUrl">
  99. 您的浏览器不支持 video
  100. </video>
  101. </div>
  102. <div class="content-box">
  103. <div class="text-cut title">{{ row.title }}</div>
  104. <div class="shootingUser">拍摄者:{{ row.shootingUser }}</div>
  105. <div class="shootingTimeStr">拍摄时间:{{ row.shootingTimeStr }}</div>
  106. <div class="fileSize">文件大小:{{ row.fileSize }}</div>
  107. </div>
  108. </div>
  109. </template>
  110. <template #operate="{ row }">
  111. <HcTooltip keys="image-data-preview">
  112. <el-button
  113. :loading="previewLoading" size="small" text type="primary"
  114. @click="previewClick(row)"
  115. >
  116. 查看
  117. </el-button>
  118. </HcTooltip>
  119. <HcTooltip keys="image-data-edit">
  120. <el-button size="small" text type="primary" @click="editClick(row)">编辑</el-button>
  121. </HcTooltip>
  122. </template>
  123. </HcTable>
  124. <template #action>
  125. <div class="lr-dialog-footer">
  126. <div class="left">
  127. <el-button size="large" @click="goToBack">
  128. <HcIcon name="arrow-go-back" />
  129. <span>返回</span>
  130. </el-button>
  131. </div>
  132. <div class="right">
  133. <HcPages :pages="searchForm" @change="pageChange" />
  134. </div>
  135. </div>
  136. </template>
  137. </HcNewCard>
  138. </div>
  139. <!-- 视频预览 弹框 -->
  140. <hc-new-dialog v-model="previewVideoModal" title="预览" widths="47rem">
  141. <video
  142. v-if="previewVideoUrl" :src="previewVideoUrl" autoplay="autoplay" class="preview-video"
  143. controls="controls"
  144. >
  145. 您的浏览器不支持 video
  146. </video>
  147. </hc-new-dialog>
  148. <!-- 组成相册 弹框 -->
  149. <hc-new-dialog v-model="albumDialog" title="组成相册" widths="47rem" :loading="albumDialogLoading" @save="saveAlbum">
  150. <el-form ref="albumFormRef" :model="albumForm" label-width="auto" :rules="albumRules">
  151. <el-form-item label="相册文件题名" prop="imagesName">
  152. <el-input v-model="albumForm.imagesName" placeholder="请输入" />
  153. </el-form-item>
  154. <el-form-item label="主要拍摄人" prop="photographer">
  155. <el-input v-model="albumForm.photographer" placeholder="请输入" />
  156. </el-form-item>
  157. <el-form-item label="分组号">
  158. <el-input v-model="albumForm.groupNumber" placeholder="请输入" />
  159. </el-form-item>
  160. <el-form-item label="拍摄起止日期" prop="dateValue">
  161. <!-- <el-input v-model="albumForm.dateValue" /> -->
  162. <hc-date-picker :dates="betweenTime" clearable @change="betweenTimeUpdate" />
  163. </el-form-item>
  164. </el-form>
  165. </hc-new-dialog>
  166. </div>
  167. </template>
  168. <script setup>
  169. import { onActivated, onMounted, ref, watch } from 'vue'
  170. import { useAppStore } from '~src/store'
  171. import { useRoute, useRouter } from 'vue-router'
  172. import WbsTree from './components/WbsTree.vue'
  173. import HcTreeData from './components/HcTreeData.vue'
  174. import imageApi from '~api/other-file/imageData'
  175. import { getStoreValue, setStoreValue } from '~src/utils/storage'
  176. import { arrToId, arrToKey, downloadBlob, formValidate, getArrValue } from 'js-fast-way'
  177. import { HcDelMsg } from 'hc-vue3-ui'
  178. import { toPdfPage } from '~uti/btn-auth'
  179. import website from '~src/config'
  180. import albumApi from '~api/other-file/album'
  181. //变量
  182. const router = useRouter()
  183. const useRoutes = useRoute()
  184. const useAppState = useAppStore()
  185. const projectId = ref(useAppState.getProjectId)
  186. const contractId = ref(useAppState.getContractId)
  187. const projectInfo = ref(useAppState.getProjectInfo)
  188. const isCollapse = ref(useAppState.getCollapse)
  189. //路由参数
  190. const routerQuery = useRoutes?.query
  191. //存储目录格式 1按部位存储,2按日期存储
  192. const dataId = ref(routerQuery?.id || '')
  193. const dataType = ref(parseInt(routerQuery?.type + '') )
  194. const fileType = ref(parseInt(routerQuery?.fileType + '') || 2)
  195. //监听
  196. watch(() => [
  197. useAppState.getCollapse,
  198. useAppState.getContractId,
  199. ], ([Collapse, ContractId]) => {
  200. isCollapse.value = Collapse
  201. contractId.value = ContractId
  202. })
  203. //监听路由参数改变
  204. watch(() => [
  205. useRoutes?.query,
  206. ], ([query]) => {
  207. console.log(query, 'query')
  208. dataId.value = query?.id || ''
  209. dataType.value = parseInt(query?.type + '')
  210. fileType.value = parseInt(query?.fileType + '') || 2
  211. searchForm.value.classifyId = query?.id || ''
  212. initMounted()
  213. }, { deep: true })
  214. watch(contractId, (val) => {
  215. if (val) {
  216. console.log(val)
  217. router.push({
  218. path: '/other-file/image-data',
  219. })
  220. }
  221. })
  222. //自动展开缓存
  223. const TreeAutoExpandKeys = ref([])
  224. const TreeExpandedKeys = ref([])
  225. const TreeCurrentNodeKey = ref(getStoreValue('TreeCurrentNodeKey') || '')
  226. //渲染完成
  227. // onMounted(() => {
  228. // initMounted()
  229. // })
  230. const isHttps = ref(false)
  231. onMounted(() => {
  232. isHttps.value = !website.localModel
  233. })
  234. onActivated(()=>{
  235. initMounted()
  236. })
  237. const initMounted = () => {
  238. console.log('onMounted')
  239. const nodeKey = TreeCurrentNodeKey.value
  240. if (dataType.value === 1) {
  241. TreeAutoExpandKeys.value = getStoreValue('TreeExpandKeys') || []
  242. } else {
  243. TreeExpandedKeys.value = getStoreValue('TreeExpandedKeys') || []
  244. }
  245. if (dataType.value === 2 && dataId.value) {
  246. getYearDateTree()
  247. queryKey.value = nodeKey
  248. //console.log(queryKey.value, ' queryKey.value');
  249. if (isNaN(queryKey.value) && !isNaN(Date.parse(queryKey.value))) {
  250. queryKey.value = ''
  251. }
  252. searchForm.value.queryDate = nodeKey
  253. searchForm.value.current = 1
  254. getTableData()
  255. } else {
  256. queryKey.value = ''
  257. getTableData()
  258. }
  259. }
  260. //获取时间结构
  261. const dateElTreeData = ref([])
  262. const getYearDateTree = async () => {
  263. const { error, code, data } = await imageApi.getYearDateTree({
  264. projectId: projectId.value,
  265. contractId: contractId.value,
  266. classifyId: dataId.value,
  267. })
  268. //处理数据
  269. if (!error && code === 200) {
  270. dateElTreeData.value = getArrValue(data)
  271. } else {
  272. dateElTreeData.value = []
  273. }
  274. }
  275. //日期树被点击
  276. const nodeDataInfo = ref({})
  277. const dateWbsElTreeClick = ({ data, keys, key }) => {
  278. // queryKey.value = key
  279. queryKey.value = ''
  280. nodeDataInfo.value = data
  281. //缓存自动展开
  282. TreeExpandedKeys.value = keys
  283. TreeCurrentNodeKey.value = key
  284. setStoreValue('TreeExpandedKeys', keys)
  285. setStoreValue('TreeCurrentNodeKey', key)
  286. //改变搜索表单数据
  287. searchForm.value.queryDate = data['hierarchy'] || ''
  288. searchForm.value.wbsIdsStr = null
  289. searchForm.value.current = 1
  290. getTableData()
  291. }
  292. //项目树被点击
  293. const nodeWbsElTreeClick = ({ data, keys }) => {
  294. searchForm.value.wbsIdsStr = data?.primaryKeyId || ''
  295. if (data?.notExsitChild === true) {
  296. nodeDataInfo.value = data
  297. queryKey.value = data['primaryKeyId'] || ''
  298. //缓存自动展开
  299. TreeAutoExpandKeys.value = keys
  300. setStoreValue('TreeExpandKeys', keys)
  301. //改变搜索表单数据
  302. searchForm.value.queryDate = null
  303. // searchForm.value.wbsIdsStr = data?.primaryKeyId || ''
  304. searchForm.value.current = 1
  305. getTableData()
  306. } else {
  307. getTableData()
  308. queryKey.value = ''
  309. nodeDataInfo.value = {}
  310. searchForm.value.queryDate = null
  311. searchForm.value.wbsIdsStr = null
  312. tableListData.value = []
  313. searchForm.value.total = 0
  314. }
  315. }
  316. //搜索和分页数据
  317. const queryKey = ref(null)
  318. const searchForm = ref({
  319. queryStr: null, classifyId: dataId.value, wbsIdsStr: null,
  320. current: 1, size: 20, total: 0,
  321. })
  322. //回车搜索
  323. const keyUpEvent = (e) => {
  324. if (e.key === 'Enter') {
  325. searchClick()
  326. }
  327. }
  328. //搜索
  329. const searchClick = () => {
  330. // if (queryKey.value) {
  331. // searchForm.value.current = 1
  332. // getTableData()
  333. // } else {
  334. // window?.$message?.warning('请先在左边选择一个树节点')
  335. // }
  336. if (dataType.value === 1 && !queryKey.value) {
  337. window?.$message?.warning('请先在左边选择一个树子节点')
  338. return
  339. } else {
  340. searchForm.value.current = 1
  341. getTableData()
  342. }
  343. }
  344. //分页被点击
  345. const pageChange = ({ current, size }) => {
  346. searchForm.value.current = current
  347. searchForm.value.size = size
  348. getTableData()
  349. }
  350. //获取数据
  351. const tableListRef = ref(null)
  352. const tableLoading = ref(false)
  353. const tableListData = ref([])
  354. const tableListColumn = ref([
  355. { key: 'info', name: '文件详情' },
  356. { key: 'textContent', name: '文字说明' },
  357. { key: 'operate', name: '操作', align: 'center', width: '140' },
  358. ])
  359. const getTableData = async () => {
  360. tableLoading.value = true
  361. const { error, code, data } = await imageApi.getPageList({
  362. ...searchForm.value,
  363. projectId: projectId.value,
  364. contractId: contractId.value,
  365. })
  366. //判断状态
  367. tableLoading.value = false
  368. if (!error && code === 200) {
  369. tableListData.value = getArrValue(data['records'])
  370. searchForm.value.total = data['total'] || 0
  371. } else {
  372. tableListData.value = []
  373. searchForm.value.total = 0
  374. }
  375. }
  376. //多选
  377. const tableCheckedKeys = ref([])
  378. const tableSelectionChange = (rows) => {
  379. tableCheckedKeys.value = rows.filter((item) => {
  380. return (item ?? '') !== ''
  381. })
  382. }
  383. //处理图片预览问题
  384. const setImageUrl = (url) => {
  385. if (url) {
  386. const urlArr = url.split(',')
  387. if (urlArr.length > 0 && urlArr[0]) {
  388. return urlArr[0]
  389. } else {
  390. return ''
  391. }
  392. } else {
  393. return ''
  394. }
  395. }
  396. //预览
  397. const previewVideoUrl = ref('')
  398. const previewVideoModal = ref(false)
  399. const previewLoading = ref(false)
  400. const previewClick = async (item) => {
  401. const { id, type, imageUrl, margePdfUrl } = item
  402. console.log(parseInt(type), 'parseInt(type)')
  403. if (parseInt(type) === 1 ) {
  404. if (imageUrl) {
  405. previewVideoUrl.value = imageUrl
  406. previewVideoModal.value = true
  407. } else {
  408. window.$message?.warning('暂无可预览的资料文件')
  409. }
  410. } else if (parseInt(type) === 2 || type === null || type === -1) {
  411. if (margePdfUrl) {
  412. toPdfPage(margePdfUrl)
  413. //window.open(margePdfUrl, '_blank')
  414. } else {
  415. window.$message?.warning('暂无可预览的资料文件')
  416. }
  417. // else {
  418. // previewLoading.value = true
  419. // const { error, code, data } = await imageApi.imageClassificationFile({
  420. // ids: id,
  421. // }, false)
  422. // //判断状态
  423. // previewLoading.value = false
  424. // if (!error && code === 200 && isString(data)) {
  425. // item.margePdfUrl = data
  426. // toPdfPage(data)
  427. // //window.open(data, '_blank')
  428. // } else {
  429. // window.$message?.warning('预览资料文件异常')
  430. // }
  431. // }
  432. }
  433. }
  434. //新增文件
  435. const addFormFile = () => {
  436. router.push({
  437. path: '/other-file/image-form',
  438. query: {
  439. wbsId: queryKey.value, //树节点ID
  440. dataType: dataType.value, //存储目录格式 1按部位存储,2按日期存储
  441. fileType: fileType.value, //文件类型,1视频文件,2图片文件
  442. classifyId: dataId.value, //classifyId,分类ID,
  443. },
  444. })
  445. }
  446. //编辑修改
  447. const editClick = ({ id }) => {
  448. router.push({
  449. path: '/other-file/image-form',
  450. query: {
  451. wbsId: queryKey.value, //树节点ID
  452. dataType: dataType.value, //存储目录格式 1按部位存储,2按日期存储
  453. fileType: fileType.value, //文件类型,1视频文件,2图片文件
  454. classifyId: dataId.value, //classifyId,分类ID,
  455. id: id, //数据ID
  456. },
  457. })
  458. }
  459. //下载文件
  460. const downloadLoading = ref(false)
  461. const downloadClick = async () => {
  462. const rows = tableCheckedKeys.value
  463. if (rows.length > 0) {
  464. downloadLoading.value = true
  465. const ids = arrToId(rows)
  466. const { error, disposition, res } = await imageApi.batchDownloadFileToZip({ ids: ids }, false)
  467. //判断状态
  468. if (!error) {
  469. if (disposition) {
  470. downloadBlob(res, disposition)
  471. } else {
  472. window.$message?.error('下载异常')
  473. }
  474. }
  475. } else {
  476. window.$message?.warning('请先勾选需要下载的资料文件')
  477. }
  478. }
  479. //下载PDF
  480. const downPdfLoading = ref(false)
  481. const downloadPdfClick = async () => {
  482. const rows = tableCheckedKeys.value
  483. if (rows.length > 0) {
  484. downPdfLoading.value = true
  485. const ids = arrToId(rows)
  486. const { error, disposition, res } = await imageApi.batchDownloadFPDFFileToZip({ ids: ids }, false)
  487. //判断状态
  488. if (!error) {
  489. if (disposition) {
  490. downloadBlob(res, disposition)
  491. } else {
  492. window.$message?.error('下载异常')
  493. }
  494. }
  495. downPdfLoading.value = false
  496. } else {
  497. window.$message?.warning('请先勾选需要下载的资料文件')
  498. }
  499. }
  500. //删除文件
  501. const delLoading = ref(false)
  502. const delClick = () => {
  503. const rows = tableCheckedKeys.value
  504. if (rows.length > 0) {
  505. const ids = arrToId(rows)
  506. HcDelMsg( async ( resolve) => {
  507. await removeImageclassifyFile(ids)
  508. resolve() //关闭弹窗的回调
  509. })
  510. } else {
  511. window.$message?.warning('请先勾选需要删除的资料文件')
  512. }
  513. }
  514. const removeImageclassifyFile = async (ids) => {
  515. delLoading.value = true
  516. const { error, code } = await imageApi.removeImageclassifyFile({ ids: ids }, false)
  517. //判断状态
  518. delLoading.value = false
  519. if (!error && code === 200) {
  520. window.$message?.success('删除成功')
  521. getTableData()
  522. } else {
  523. window.$message?.error('删除异常')
  524. }
  525. }
  526. //回到影像资料页
  527. const goToBack = () => {
  528. router.push({ path: '/other-file/image-data' })
  529. }
  530. //左右拖动,改变树形结构宽度
  531. const leftWidth = ref(dataType.value === 1 ? 382 : 220)
  532. const onmousedown = () => {
  533. const leftNum = isCollapse.value ? 142 : 272
  534. document.onmousemove = (ve) => {
  535. const diffVal = ve.clientX - leftNum
  536. const minWidth = dataType.value === 1 ? 310 : 200
  537. const maxWidth = dataType.value === 1 ? 900 : 300
  538. if (diffVal >= minWidth && diffVal <= maxWidth) {
  539. leftWidth.value = diffVal
  540. }
  541. }
  542. document.onmouseup = () => {
  543. document.onmousemove = null
  544. document.onmouseup = null
  545. }
  546. }
  547. //组成相册
  548. const albumDialog = ref(false)
  549. const albumFormRef = ref(null)
  550. const albumForm = ref({})
  551. const albumRules = ref({
  552. imagesName: [
  553. { required: true, message: '请输入相册文件题名', trigger: 'blur' },
  554. ],
  555. photographer: [
  556. { required: true, message: '请输入主要拍摄人', trigger: 'blur' },
  557. ],
  558. dateValue: [
  559. { required: true, message: '请选择拍摄起止日期', trigger: 'blur' },
  560. ],
  561. })
  562. //日期时间被选择
  563. const betweenTime = ref([])
  564. const betweenTimeUpdate = ({ arr, val, query }, row) => {
  565. betweenTime.value = arr
  566. albumForm.value.dateValue = query
  567. console.log(arr, 'val')
  568. console.log(query, 'query')
  569. }
  570. const combineAlbumClick = ()=>{
  571. albumForm.value = {
  572. imagesName: '',
  573. photographer: '',
  574. groupNumber: '',
  575. dateValue: '',
  576. }
  577. betweenTime.value = []
  578. albumDialog.value = true
  579. const arr = getDateRangeFromShootTime(tableCheckedKeys.value)
  580. betweenTime.value = arr
  581. albumForm.value.dateValue = arr.join('~')
  582. }
  583. const getDateRangeFromShootTime = (items) =>{
  584. if (!items || items.length === 0) return [null, null]
  585. // 提取并格式化所有有效日期
  586. const dates = items
  587. .map(item => item.shootingTimeStr)
  588. .filter(time => typeof time === 'string' && time.trim() !== '')
  589. .map(time => {
  590. const date = new Date(time)
  591. return isNaN(date.getTime()) ? null : date
  592. })
  593. .filter(Boolean)
  594. if (dates.length === 0) return [null, null]
  595. // 获取最早和最晚日期
  596. const minDate = new Date(Math.min(...dates))
  597. const maxDate = new Date(Math.max(...dates))
  598. // 格式化为 YYYY-MM-DD
  599. const formatDate = (date) => date.toISOString().split('T')[0]
  600. return [formatDate(minDate), formatDate(maxDate)]
  601. }
  602. // 使用示例
  603. const [startDate, endDate] = getDateRangeFromShootTime(tableCheckedKeys.value)
  604. console.log('日期范围:', [startDate, endDate]) // 输出: ["2025-07-01", "2025-07-31"]
  605. const albumDialogLoading = ref(false)
  606. const saveAlbum = async () => {
  607. const rows = tableCheckedKeys.value
  608. // 初始化 margePdfUrls 数组
  609. let margePdfUrls = []
  610. rows.forEach(item => {
  611. const { id, imageUrl } = item
  612. margePdfUrls.push({ id, imageUrl })
  613. })
  614. const validate = await formValidate(albumFormRef.value)
  615. if (!validate) return
  616. albumDialogLoading.value = true
  617. const { error, code, msg } = await albumApi.save(
  618. { ...albumForm.value,
  619. projectId:projectId.value,
  620. contractId: contractId.value,
  621. classifyId:dataId.value,
  622. margePdfUrls: margePdfUrls,
  623. },
  624. )
  625. //判断状态
  626. if (!error && code === 200) {
  627. window.$message?.success(msg)
  628. getTableData()
  629. albumDialog.value = false
  630. }
  631. albumDialogLoading.value = false
  632. }
  633. </script>
  634. <style lang="scss" scoped>
  635. @import '../../styles/other-file/image-view.scss';
  636. </style>
  637. <style lang="scss">
  638. .preview-video {
  639. width: 100%;
  640. }
  641. </style>