cameraScene.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. <template>
  2. <PageWrapper contentBackground>
  3. <template #footer>
  4. <a-tabs v-model:activeKey="tableType" @change="changeTable">
  5. <a-tab-pane :key="0" tab="四维看看" :disabled="loading" />
  6. <a-tab-pane :key="1" tab="四维看见" :disabled="loading" />
  7. <a-tab-pane :key="2" tab="深时点云场景" :disabled="loading" />
  8. <a-tab-pane :key="5" tab="深时Mesh场景" :disabled="loading" />
  9. <a-tab-pane :key="6" tab="深光点云场景" :disabled="loading" />
  10. <a-tab-pane :key="7" tab="深光Mesh场景" :disabled="loading" />
  11. <a-tab-pane :key="3" tab="四维双目Lite" :disabled="loading" />
  12. </a-tabs>
  13. </template>
  14. <div class="desc-wrap-BasicTable">
  15. <BasicTable @register="registerTable" ref="tableRef">
  16. <template #toolbar>
  17. <!-- <a-button type="primary" @click="exportExcel"> 导出1</a-button> -->
  18. </template>
  19. <template #status="{ record }">
  20. <span v-if="record.status != '-1'">{{ record.statusString }}</span>
  21. <Tooltip v-else placement="right">
  22. <template #title>
  23. <span>失败原因:{{ record.buildErrorReason }}</span>
  24. <p>
  25. <span>serverPath:{{ record.dataSource }}</span>
  26. </p>
  27. </template>
  28. <span
  29. >{{ record.statusString }}
  30. <Icon icon="mdi:warning-octagon-outline" />
  31. </span>
  32. </Tooltip>
  33. </template>
  34. <template #href="{ record }">
  35. <a
  36. v-if="record.sceneName && record.thumb"
  37. target="_blank"
  38. :href="record.webSite || record.thumb"
  39. >{{ record.sceneName }}</a
  40. >
  41. <span v-else-if="record.sceneName">{{ record.sceneName }}</span>
  42. <span v-else>-</span>
  43. </template>
  44. <template #action="{ record }">
  45. <TableAction
  46. stopButtonPropagation
  47. :actions="[
  48. {
  49. label: '迁移',
  50. disabled: !(record.status == 1 || record.status == -2),
  51. ifShow: getTypeCheckPerm('scenes-move') && tableType != 3,
  52. onClick: handleMove.bind(null, record),
  53. },
  54. {
  55. label: '下载',
  56. ifShow: getTypeCheckPerm('scenes-download') && tableType != 3,
  57. disabled: !(record.status == 1 || (record.status == -2 && record.payStatus == 1)),
  58. //icon: 'carbon:download',
  59. onClick: handleDownload.bind(null, record),
  60. },
  61. {
  62. label: '重算',
  63. disabled: record.status == 0 || (record.status == -2 && record.payStatus != 1),
  64. ifShow: getTypeCheckPerm('scenes-recalculate') && tableType != 3,
  65. popConfirm: {
  66. title: '是否重算?',
  67. confirm: handleReset.bind(null, record),
  68. },
  69. },
  70. {
  71. label: '复制',
  72. disabled: !(record.status == 1 || (record.status == -2 && record.payStatus == 1)),
  73. ifShow: getTypeCheckPerm('scenes-copy') && tableType != 3,
  74. onClick: handleCopy.bind(null, record),
  75. },
  76. {
  77. label: '删除',
  78. //icon: 'ic:outline-delete-outline',
  79. color: 'error',
  80. ifShow: getTypeCheckPerm('scenes-delete'),
  81. disabled: record.status == 0,
  82. //onClick: handleDelete.bind(null, record),
  83. popConfirm: {
  84. title: '是否删除?',
  85. confirm: handleDelete.bind(null, record),
  86. placement: 'topRight',
  87. },
  88. },
  89. ]"
  90. />
  91. </template>
  92. </BasicTable>
  93. </div>
  94. <DownLoadModal
  95. :downloadOption="downloadOption"
  96. @cancel="afterClose"
  97. @register="registerDownModal"
  98. @update="reload"
  99. cancelText="取消下载"
  100. okText="下载"
  101. @cancelDownload="cancelDownload"
  102. :okButtonProps="{ disabled: canDownload }"
  103. />
  104. <MoveModal @register="registerMoveModal" />
  105. </PageWrapper>
  106. </template>
  107. <script lang="ts">
  108. import { defineComponent, h, reactive, toRefs, ref, unref } from 'vue';
  109. import {
  110. BasicTable,
  111. useTable,
  112. TableAction,
  113. BasicColumn,
  114. TableActionType,
  115. TableImg,
  116. FormProps,
  117. } from '/@/components/Table';
  118. import { PageWrapper } from '/@/components/Page';
  119. import DownLoadModal from './modal/DownLoadModal.vue';
  120. import MoveModal from './modal/MoveModal.vue';
  121. import { Time } from '/@/components/Time';
  122. import { Icon } from '/@/components/Icon';
  123. import { Descriptions, Tabs, Progress, Tooltip } from 'ant-design-vue';
  124. import { useI18n } from '/@/hooks/web/useI18n';
  125. import { useMessage } from '/@/hooks/web/useMessage';
  126. import { useModal } from '/@/components/Modal';
  127. import {
  128. operateSceneList,
  129. sceneMove,
  130. sceneDelete,
  131. sceneReset,
  132. sceneDownload,
  133. checkDownLoad,
  134. downloadProcess,
  135. sceneCopy,
  136. rebuildScene,
  137. } from '/@/api/operate';
  138. import { message } from 'ant-design-vue';
  139. import { usePermissionStore } from '/@/store/modules/permission';
  140. import { func } from 'vue-types';
  141. import { truncate } from 'fs/promises';
  142. export default defineComponent({
  143. components: {
  144. DownLoadModal,
  145. MoveModal,
  146. BasicTable,
  147. TableAction,
  148. PageWrapper,
  149. Icon,
  150. Tooltip,
  151. [Descriptions.name]: Descriptions,
  152. [Descriptions.Item.name]: Descriptions.Item,
  153. [Tabs.name]: Tabs,
  154. [Tabs.TabPane.name]: Tabs.TabPane,
  155. },
  156. setup() {
  157. const { t } = useI18n();
  158. const { createMessage, createConfirm } = useMessage();
  159. const permissionStore = usePermissionStore();
  160. const { getCheckPerm } = permissionStore;
  161. const loading = ref(false);
  162. const tableRef = ref<Nullable<TableActionType>>(null);
  163. const tableType = ref<Number>(0); //0看看 、1看见、2深时
  164. function columns(isobj): BasicColumn[] {
  165. return [
  166. {
  167. title: '场景标题',
  168. dataIndex: 'sceneName',
  169. slots: { customRender: 'href' },
  170. width: 150,
  171. },
  172. {
  173. title: '场景码',
  174. dataIndex: 'num',
  175. ellipsis: true,
  176. width: 180,
  177. },
  178. {
  179. title: '拍摄时间',
  180. dataIndex: 'createTime',
  181. sorter: true,
  182. width: 180,
  183. customRender: ({ record }) => {
  184. return (
  185. record.createTime &&
  186. h(Time, {
  187. value: record.createTime,
  188. mode: 'datetime',
  189. })
  190. );
  191. },
  192. },
  193. {
  194. title: 'obj生成状态',
  195. dataIndex: 'isObj',
  196. ellipsis: true,
  197. ifShow: isobj,
  198. width: 180,
  199. customRender: ({ record }) => {
  200. return record.isObj == 0 ? '未生成' : record.isObj == 1 ? '已生成' : '计算中';
  201. },
  202. },
  203. {
  204. title: '计算完成时间',
  205. dataIndex: 'amount',
  206. width: 180,
  207. customRender: ({ record }) => {
  208. return (
  209. (record.algorithmTime &&
  210. h(Time, {
  211. value: record.algorithmTime,
  212. mode: 'datetime',
  213. })) ||
  214. '-'
  215. );
  216. },
  217. },
  218. {
  219. title: 'SN码',
  220. dataIndex: 'snCode',
  221. width: 180,
  222. },
  223. {
  224. title: '点位数量',
  225. dataIndex: 'shootCount',
  226. width: 80,
  227. },
  228. {
  229. title: '场景大小',
  230. dataIndex: 'sceneSize',
  231. width: 80,
  232. customRender: ({ record }) => {
  233. return record.sceneSize && record.sceneSize != 0
  234. ? h('span', { class: 'sceneSize' }, Math.ceil(record.sceneSize / 1024 / 1024) + 'M')
  235. : '-';
  236. },
  237. },
  238. {
  239. title: '拍摄位置',
  240. dataIndex: 'addressComponent',
  241. width: 100,
  242. customRender: ({ record }) => {
  243. if (!record.addressComponent) {
  244. return '';
  245. }
  246. let { city } = record.addressComponent;
  247. return city; // + district + township;
  248. },
  249. },
  250. {
  251. title: '是否复制',
  252. dataIndex: 'isCopy',
  253. width: 80,
  254. customRender: ({ record }) => {
  255. return record.isCopy ? '是' : '否';
  256. },
  257. },
  258. {
  259. title: '复制时间',
  260. dataIndex: 'copyTime',
  261. width: 180,
  262. customRender: ({ record }) => {
  263. return record.copyTime
  264. ? h(Time, {
  265. value: record.copyTime,
  266. mode: 'datetime',
  267. })
  268. : '-';
  269. },
  270. },
  271. {
  272. title: '绑定账号',
  273. dataIndex: 'userName',
  274. width: 100,
  275. },
  276. {
  277. title: '浏览量',
  278. dataIndex: 'viewCount',
  279. sorter: true,
  280. width: 80,
  281. },
  282. {
  283. title: '状态',
  284. dataIndex: 'statusString',
  285. width: 120,
  286. slots: { customRender: 'status' },
  287. },
  288. {
  289. title: '操作',
  290. dataIndex: 'action',
  291. slots: { customRender: 'action' },
  292. ifShow: true,
  293. fixed: 'right',
  294. flag: 'ACTION',
  295. width: 250,
  296. },
  297. ];
  298. }
  299. // const searchForm: Partial<FormProps> = {
  300. // labelWidth: 100,
  301. // schemas: [
  302. // {
  303. // field: 'sceneName',
  304. // label: '场景标题',
  305. // component: 'Input',
  306. // componentProps: {
  307. // maxLength: 100,
  308. // },
  309. // colProps: {
  310. // xl: 7,
  311. // xxl: 7,
  312. // },
  313. // },
  314. // {
  315. // field: 'snCode',
  316. // label: 'SN码',
  317. // component: 'Input',
  318. // componentProps: {
  319. // maxLength: 100,
  320. // },
  321. // colProps: {
  322. // xl: 7,
  323. // xxl: 7,
  324. // },
  325. // },
  326. // {
  327. // field: 'userName',
  328. // label: '绑定账号',
  329. // component: 'Input',
  330. // componentProps: {
  331. // maxLength: 100,
  332. // },
  333. // colProps: {
  334. // xl: 6,
  335. // xxl: 6,
  336. // },
  337. // },
  338. // ],
  339. // };
  340. const searchFormSs: Partial<FormProps> = {
  341. labelWidth: 100,
  342. autoSubmitOnEnter: true,
  343. autoAdvancedLine: 1,
  344. actionColOptions: {
  345. span: 24,
  346. },
  347. schemas: [
  348. {
  349. field: 'sceneName',
  350. label: '场景标题',
  351. component: 'Input',
  352. componentProps: {
  353. maxLength: 100,
  354. },
  355. colProps: {
  356. xl: 7,
  357. xxl: 7,
  358. },
  359. },
  360. {
  361. field: 'num',
  362. label: '场景码',
  363. component: 'Input',
  364. componentProps: {
  365. maxLength: 100,
  366. },
  367. colProps: {
  368. xl: 7,
  369. xxl: 7,
  370. },
  371. },
  372. {
  373. field: 'snCode',
  374. label: 'SN码',
  375. component: 'Input',
  376. componentProps: {
  377. maxLength: 100,
  378. },
  379. colProps: {
  380. xl: 7,
  381. xxl: 7,
  382. },
  383. },
  384. {
  385. field: 'userName',
  386. label: '绑定账号',
  387. component: 'Input',
  388. componentProps: {
  389. maxLength: 100,
  390. },
  391. colProps: {
  392. xl: 7,
  393. xxl: 7,
  394. },
  395. },
  396. {
  397. field: 'timeList',
  398. label: '拍摄时间段',
  399. component: 'RangePicker',
  400. componentProps: {
  401. maxLength: 100,
  402. minWidth: '385px',
  403. format: 'YYYY-MM-DD',
  404. valueFormat: 'YYYY-MM-DD',
  405. showTime: true,
  406. },
  407. colProps: {
  408. xl: 8,
  409. xxl: 8,
  410. },
  411. },
  412. ],
  413. };
  414. function cancelDownload() {
  415. downloadOption.value = {};
  416. }
  417. const [registerDownModal, { openModal: openDownModal }] = useModal();
  418. const [registerMoveModal, { openModal: openMoveModal }] = useModal();
  419. const [registerTable, { reload, setColumns }] = useTable({
  420. api: operateSceneList,
  421. title: `场景列表`,
  422. columns: columns(false),
  423. searchInfo: { type: tableType },
  424. useSearchForm: true,
  425. formConfig: searchFormSs,
  426. showTableSetting: true,
  427. beforeFetch: (T) => {
  428. loading.value = true;
  429. return T;
  430. },
  431. afterFetch: (T) => {
  432. loading.value = false;
  433. return T;
  434. },
  435. rowKey: 'num',
  436. fetchSetting: {
  437. pageField: 'pageNum',
  438. sizeField: 'pageSize',
  439. listField: 'list',
  440. totalField: 'total',
  441. },
  442. canResize: true,
  443. });
  444. function getTableAction() {
  445. const tableAction = unref(tableRef);
  446. if (!tableAction) {
  447. console.log('tableAction', tableAction, tableRef);
  448. throw new Error('tableAction is null');
  449. }
  450. return tableAction;
  451. }
  452. function changeTable(val: string) {
  453. tableType.value = val;
  454. setColumns(columns(val == 2));
  455. // setColumns(columns)
  456. reload();
  457. }
  458. async function handleCopy(record: Recordable) {
  459. createConfirm({
  460. title: '复制场景',
  461. content: '复制场景,场景归属在原相机下。<br/>确定要复制场景吗?',
  462. onOk: async () => {
  463. sceneCopy({ num: record.num }).then(() => {
  464. message.success({
  465. content: '复制成功',
  466. });
  467. reload();
  468. });
  469. },
  470. });
  471. }
  472. async function handleDelete(record: Recordable) {
  473. console.log('handleDelete', record);
  474. // createConfirm({
  475. // title: '删除',
  476. // content: '确定要删除场景吗?',
  477. // onOk: async () => {
  478. sceneDelete({ num: record.num }).then(() => {
  479. message.success({
  480. content: '删除成功',
  481. });
  482. reload();
  483. });
  484. // },
  485. // });
  486. }
  487. async function handleMove(record: Recordable) {
  488. openMoveModal(true, {
  489. ...record,
  490. });
  491. // sceneMove({ snCode: record.snCode, num: record.num })
  492. // .then(() => {
  493. // message.success({
  494. // content: '迁移成功',
  495. // });
  496. // })
  497. // .catch(() => {
  498. // message.success({
  499. // content: '迁移失败',
  500. // });
  501. // });
  502. }
  503. let timer: null = ref(null);
  504. const downloadOption = ref<Object>({});
  505. const canDownload = ref<boolean>(true);
  506. function handleDownload(record: Recordable) {
  507. console.log('handleDownload', record, tableType.value);
  508. let isObj = tableType.value == 5 ? 1 : 0;
  509. let params = { num: record.num, isObj: 0 };
  510. if (tableType.value == 4 || tableType.value == 5) {
  511. params.isObj = isObj;
  512. }
  513. canDownload.value = true;
  514. checkDownLoad(params).then((res) => {
  515. if (res.downloadStatus != 3) {
  516. // 未下载过,需要打包
  517. sceneDownload(params).then((res) => {
  518. console.log(res);
  519. openDownModal(true, {
  520. ...record,
  521. isObj: params.isObj,
  522. });
  523. if (res.downloadStatus == 1) {
  524. if (timer.value) {
  525. afterClose();
  526. }
  527. timer.value = setInterval(() => {
  528. downloadProcess(params).then((res) => {
  529. if (res.status == '1003') {
  530. createMessage.error('下载失败');
  531. afterClose();
  532. return;
  533. }
  534. if (res.percent >= 100) {
  535. canDownload.value = false;
  536. afterClose();
  537. }
  538. downloadOption.value = res;
  539. console.log(res);
  540. });
  541. }, 1000);
  542. }
  543. });
  544. } else {
  545. canDownload.value = false;
  546. window.open(res.downloadUrl);
  547. }
  548. });
  549. }
  550. function afterClose() {
  551. clearInterval(timer.value);
  552. timer.value = null;
  553. }
  554. function handleReset(record: Recordable) {
  555. console.log('handleReset', record);
  556. rebuildScene({ num: record.num }).then(() => {
  557. message.success({
  558. content: '操作成功',
  559. });
  560. reload();
  561. });
  562. }
  563. function getTypeCheckPerm(val) {
  564. let myType = tableType.value;
  565. return getCheckPerm(val) || getCheckPerm(`${val}-${myType}`);
  566. }
  567. return {
  568. registerTable,
  569. handleDelete,
  570. handleCopy,
  571. handleMove,
  572. handleDownload,
  573. handleReset,
  574. tableType,
  575. loading,
  576. reload,
  577. changeTable,
  578. t,
  579. openDownModal,
  580. registerDownModal,
  581. registerMoveModal,
  582. afterClose,
  583. timer,
  584. canDownload,
  585. downloadOption,
  586. cancelDownload,
  587. getTypeCheckPerm,
  588. };
  589. },
  590. });
  591. </script>
  592. <style lang="less" scoped>
  593. // .tableHeader {
  594. // height: 50px;
  595. // display: flex;
  596. // align-items: center;
  597. // .item {
  598. // font-size: 14px;
  599. // color: #666;
  600. // margin-right: 10px;
  601. // cursor: pointer;
  602. // &.active {
  603. // font-weight: bold;
  604. // color: #222;
  605. // }
  606. // }
  607. // }
  608. .desc-wrap-BasicTable {
  609. background-color: #f0f2f5;
  610. .vben-basic-table-form-container {
  611. padding: 0;
  612. }
  613. }
  614. </style>