| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <Modal
- width="800px"
- :title="$t('scene.add')"
- :visible="visible"
- @ok="okHandler"
- @cancel="visible = false"
- :okText="$t('sys.enter')"
- :cancelText="$t('sys.cancel')"
- class="model-table"
- >
- <div>
- <div className="model-header">
- <p class="header-desc">
- {{ $t("material.selectCount")
- }}<span>( {{ rowSelection.selectedRowKeys.length }} )</span>
- </p>
- <Search
- className="content-header-search"
- :placeholder="$t('material.search')"
- v-model:value="keyword"
- allow-clear
- style="width: 244px"
- />
- </div>
- <div class="table-layout" v-if="origin.length">
- <Tabs v-model:activeKey="type">
- <TabPane v-for="current in types" :key="current" :tab="current">
- <Table
- v-if="typeFilterScenes[current].length"
- :row-key="(record: Scene) => record.num"
- :columns="cloumns"
- :rowSelection="rowSelection"
- :data-source="typeFilterScenes[current]"
- :pagination="{ ...params, current: params.pageNum }"
- @change="handleTableChange"
- />
- <div style="padding: 1px" v-else>
- <Empty
- :description="$t('sys.unSearchData')"
- :image="Empty.PRESENTED_IMAGE_SIMPLE"
- className="ant-empty ant-empty-normal"
- />
- </div>
- </TabPane>
- </Tabs>
- </div>
- <div style="padding: 1px" v-else>
- <Empty
- :description="keyword.length ? $t('sys.unSearchData') : $t('sys.undata')"
- :image="Empty.PRESENTED_IMAGE_SIMPLE"
- className="ant-empty ant-empty-normal"
- />
- </div>
- </div>
- </Modal>
- <div class="slot-layout">
- <Dropdown placement="bottom">
- <slot></slot>
- <template #overlay>
- <Menu>
- <MenuItem @click="visible = true">{{ $t("scene.manage") }}</MenuItem>
- <MenuItem @click="selectModel">{{ $t("material.name") }}</MenuItem>
- </Menu>
- </template>
- </Dropdown>
- </div>
- </template>
- <script lang="ts" setup>
- import {
- Modal,
- Input,
- Table,
- Empty,
- Tabs,
- TabPane,
- Dropdown,
- Menu,
- MenuItem,
- TableProps,
- } from "ant-design-vue";
- import { computed, nextTick, ref, watch, watchEffect } from "vue";
- import { scenes, save, SceneTypeDesc } from "@/store";
- import { asyncTimeout, createLoadPack, diffArrayChange } from "@/utils";
- import {
- fuseModels,
- createFuseModels,
- addFuseModel,
- fuseModelsLoaded,
- initialScenes,
- } from "@/store";
- import { fetchScenesAll, SceneType, uploadMaterialToModel, type Scene } from "@/api";
- import { activeModel, getSceneModel } from "@/sdk";
- import { selectMaterials } from "@/components/materials/quisk";
- import { lang, ui18n } from "@/lang";
- import { custom } from "@/env";
- import { actionItems, currentItem } from "@/views/merge";
- type Key = string;
- const Search = Input.Search;
- const spStr = '----ll----'
- const selectIds = computed(() => fuseModels.value.filter(item => item.type !== SceneType.SWMX).map((item) => item.raw.isObj + spStr + item.raw.num));
- const visible = ref(false);
- const keyword = ref("");
- const SceneGroupTypeDesc: any = lang.scene.typeRaws
- const types = computed(() => [
- ...new Set(Object.values(SceneGroupTypeDesc) as any[]).values(),
- ]);
- const type = ref(types.value[0]);
- const handleTableChange: TableProps["onChange"] = (pag) => {
- params.value.pageSize = pag.pageSize!;
- params.value.pageNum = pag.current!;
- };
- const meshParams = ref({ isObj: 1, pageNum: 1, pageSize: 12, total: 0 })
- const cloudParams = ref({ isObj: 0, pageNum: 1, pageSize: 12, total: 0 })
- const meshList = ref<Scene[]>([])
- const cloudList = ref<Scene[]>([])
- const params = computed(() => type.value === ui18n.t('scene.typeRaws.0') ? meshParams.value : cloudParams.value)
- let loadCount = 0
- watchEffect(() => {
- const list = type.value === ui18n.t('scene.typeRaws.2') ? meshList : cloudList
- const currentCount = ++loadCount
- fetchScenesAll(params.value).then((data) => {
- console.log('====>', currentCount, loadCount, params.value)
- if (currentCount === loadCount) {
- params.value.total = data.total
- list.value = data.list.map(item => ({ ...item, type: type.value, num: item.isObj + spStr + item.num })) as any
- console.log(data.total, list.value)
- }
- })
- })
- const origin = computed(() => [...meshList.value, ...cloudList.value]);
- const typeFilterScenes = computed(() => {
- const typeScenes: any = {};
- for (const type of types.value) {
- typeScenes[type] = origin.value
- .filter((item) => item.name && item.num && item.name.includes(keyword.value))
- .filter((item) => item.type === type);
- }
- return typeScenes;
- });
- let cache = {} as any
- watchEffect(() => {
- if (!visible.value) {
- cache = {}
- }
- })
- const selects = ref<Key[]>(selectIds.value);
- watchEffect(() => console.error(selects.value), {flush: 'sync'})
- const rowSelection: any = ref({
- selectedRowKeys: selects,
- hideSelectAll: true,
- onChange: (ids: string[]) => {
- console.error(ids)
- ids = ids.filter(id => !selectIds.value.includes(id))
- cache[type.value] = ids
- const curIds = [...selectIds.value]
- for (const key in cache) {
- curIds.push(...cache[key])
- }
- selects.value = curIds
- },
- getCheckboxProps: (record: Scene) => ({
- disabled: selectIds.value.includes(record.num),
- }),
- });
- const cloumns = [
- {
- width: "400px",
- title: ui18n.t('scene.tabs.name'),
- dataIndex: "name",
- key: "name",
- },
- {
- title: ui18n.t('scene.tabs.type'),
- dataIndex: "type",
- key: "type",
- },
- {
- title: ui18n.t('scene.tabs.createTime'),
- dataIndex: "createTime",
- key: "createTime",
- },
- ];
- const addModelHandler = createLoadPack(async (attachs: any[]) => {
- await save();
- const items = attachs.map((attach) => {
- return {
- data: createFuseModels(),
- attach
- }
- });
- const addPromises = items.map(item => addFuseModel(item.data, item.attach));
- const addModels = await Promise.all(addPromises);
- await new Promise<void>((resolve) => {
- nextTick(() => {
- const stop = watchEffect(() => {
- if (fuseModelsLoaded.value) {
- nextTick(() => {
- stop();
- resolve();
- });
- }
- });
- });
- });
- items.forEach(item => {
- if (getSceneModel(item.data)) {
- item.data.rotation = getSceneModel(item.data)!.getDefaultRotation();
- }
- });
- await asyncTimeout(100);
- await save();
- activeModel({ showMode: 'fuse', active: addModels[addModels.length - 1] })
- // custom.currentModel = addModels[addModels.length - 1]
- currentItem.value = actionItems[0]
- });
- const okHandler = createLoadPack(async () => {
- const attachs = selects.value.map(item => {
- const isObj = Number(item.split(spStr)[0])
- const num = item.split(spStr)[1]
- return {isObj, num}
- }).filter(({isObj, num}) =>
- num && !fuseModels.value.some((model) => model.raw.isObj === isObj && model.raw.num === num)
- )
- await addModelHandler(attachs);
- visible.value = false;
- });
- watch(visible, (visible, oldvisible) => {
- if (visible !== oldvisible) {
- keyword.value = "";
- selects.value = selectIds.value;
- visible && initialScenes();
- }
- });
- const selectModel = async () => {
- let list = await selectMaterials({
- uploadFormat: ["zip"],
- format: ["obj", "ply", "las", "laz", "b3dm", "shp", "osgb", "glb"],
- maxSize: 2 * 1024 * 1024 * 1024,
- });
- if (!list?.length) return;
- list = list.filter(item => item.uploadId)
- // const modelList = await Promise.all(list.map(item => uploadMaterialToModel(item.uploadId!)))
- const attachs: any[] = []
- for (let i = 0; i < list.length; i++) {
- const uploadId = list[i].uploadId
- if (uploadId ) {
- attachs.push({ uploadId })
- }
- }
- await addModelHandler(attachs);
- };
- </script>
- <style lang="less" scoped>
- .model-header {
- display: flex;
- justify-content: space-between;
- padding-bottom: 24px;
- align-items: center;
- }
- .table-layout {
- max-height: 500px;
- overflow-y: auto;
- }
- .slot-layout {
- display: flex;
- align-items: center;
- height: 100%;
- }
- </style>
- <style lang="less">
- .model-header .header-desc {
- margin-bottom: 0;
- }
- .ant-modal-root .ant-table-tbody > tr > td {
- word-break: break-all;
- }
- </style>
|