123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <template>
- <Modal
- width="800px"
- title="添加场景"
- :visible="visible"
- @ok="okHandler"
- @cancel="visible = false"
- okText="确定"
- cancelText="取消"
- class="model-table"
- >
- <div>
- <div className="model-header">
- <p class="header-desc">
- 已选择数据<span>( {{ rowSelection.selectedRowKeys.length }} )</span>
- </p>
- <Search
- className="content-header-search"
- placeholder="输入名称搜索"
- 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.modelId"
- :columns="cloumns"
- :rowSelection="rowSelection"
- :data-source="typeFilterScenes[current]"
- :pagination="false"
- />
- <div style="padding: 1px" v-else>
- <Empty
- description="暂无搜索结果"
- :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 ? '暂无搜索结果' : '暂无结果'"
- :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">场景管理</MenuItem>
- <MenuItem @click="selectModel">媒体库</MenuItem>
- </Menu>
- </template>
- </Dropdown>
- </div>
- </template>
- <script lang="ts" setup>
- import {
- Modal,
- Input,
- Table,
- Empty,
- Tabs,
- TabPane,
- Dropdown,
- Menu,
- MenuItem,
- } 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 { SceneType, uploadMaterialToModel, type Scene } from "@/api";
- import { activeModel, getSceneModel } from "@/sdk";
- import { selectMaterials } from "@/components/materials/quisk";
- import { custom } from "@/env";
- import { actionItems, currentItem } from "@/views/merge";
- type Key = Scene["modelId"];
- const Search = Input.Search;
- const selectIds = computed(() => fuseModels.value.filter(item => item.type !== SceneType.SWMX).map((item) => item.modelId));
- const visible = ref(false);
- const keyword = ref("");
- const SceneGroupTypeDesc: any = {
- [SceneType.SWKK]: 'Mesh场景',
- [SceneType.SWKJ]: 'Mesh场景',
- [SceneType.SWSS]: '点云场景',
- [SceneType.SWSSMX]: 'Mesh场景',
- [SceneType.SWYDSS]: '点云场景',
- [SceneType.SWYDMX]: 'Mesh场景',
- [SceneType.DSFXJ]: 'Mesh场景'
- }
- const origin = computed(() =>
- scenes.value.filter(scene => scene.type !== SceneType.SWMX).map((scene) => ({
- ...scene,
- createTime: scene.createTime.substr(0, 16),
- type: SceneGroupTypeDesc[scene.type],
- }))
- );
- const typeFilterScenes = computed(() => {
- const typeScenes: any = {};
- for (const type of types.value) {
- typeScenes[type] = origin.value
- .filter((item) => item.name && item.modelId && item.name.includes(keyword.value))
- .filter((item) => item.type === type);
- }
- return typeScenes;
- });
- const types = computed(() => [
- ...new Set(origin.value.map((item) => item.type)).values(),
- ]);
- const type = ref(types.value[0]);
- const cache = {} as any
- const selects = ref<Key[]>(selectIds.value);
- const rowSelection: any = ref({
- selectedRowKeys: selects,
- onChange: (ids: number[]) => {
- 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.modelId),
- }),
- });
- const cloumns = [
- {
- width: "400px",
- title: "名称",
- dataIndex: "name",
- key: "name",
- },
- {
- title: "类型",
- dataIndex: "type",
- key: "type",
- },
- {
- title: "拍摄/创建时间",
- dataIndex: "createTime",
- key: "createTime",
- },
- ];
- const addModelHandler = createLoadPack(async (modelIds: number[]) => {
- const models = modelIds.map((modelId) => createFuseModels({ modelId }));
- const addPromises = models.map(addFuseModel);
- const addModels = await Promise.all(addPromises);
- await new Promise<void>((resolve) => {
- nextTick(() => {
- const stop = watchEffect(() => {
- if (fuseModelsLoaded.value) {
- nextTick(() => {
- stop();
- resolve();
- });
- }
- });
- });
- });
- models.forEach((model) => {
- if (getSceneModel(model)) {
- model.rotation = getSceneModel(model)!.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 () => {
- console.log(selects.value);
- const models = selects.value.filter(
- (modelId) => !fuseModels.value.some((model) => model.modelId === modelId)
- );
- await addModelHandler(models);
- visible.value = false;
- });
- watch(visible, (visible, oldvisible) => {
- if (visible !== oldvisible) {
- keyword.value = "";
- selects.value = selectIds.value;
- visible && initialScenes();
- }
- });
- const selectModel = async () => {
- const list = await selectMaterials({
- uploadFormat: ["zip"],
- format: ["obj", "ply", "las", "laz", "b3dm", "shp", "osgb", "glb"],
- maxSize: 2 * 1024 * 1024 * 1024,
- });
- if (!list?.length) return;
- const modelList = await Promise.all(list.filter(item => item.uploadId).map(item => uploadMaterialToModel(item.uploadId!)))
- const modelIds = modelList
- .map((item) => item.modelId!)
- .filter(
- (modelId) => modelId && !fuseModels.value.some((model) => model.modelId === modelId)
- );
- await addModelHandler(modelIds);
- };
- </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>
|