123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- <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: 264px"
- />
- </div>
- <div class="table-layout" v-if="filterScenes.length">
- <Table
- :row-key="(record) => record.modelId"
- :columns="cloumns"
- :rowSelection="rowSelection"
- :data-source="filterScenes"
- :pagination="false"
- >
- <template #bodyCell="{ column, record }">
- <template v-if="column.key === 'createStatus'">
- {{ record.createStatus === 2 ? "转换中……" : "可用" }}
- </template>
- </template>
- </Table>
- </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 @click="visible = true">
- <slot></slot>
- </div>
- </template>
- <script lang="ts" setup>
- import { Modal, Input, Table, Empty } from "ant-design-vue";
- import { computed, nextTick, ref, watch, watchEffect } from "vue";
- import { scenes, save, SceneTypeDesc, getFuseModel } from "@/store";
- import { asyncTimeout, createLoadPack } from "@/utils";
- import { getSceneModel } from "@/sdk";
- import {
- fuseModels,
- createFuseModels,
- addFuseModel,
- fuseModelsLoaded,
- initialScenes,
- } from "@/store";
- import type { Scene } from "@/api";
- type Key = Scene["modelId"];
- const Search = Input.Search;
- const selectIds = computed(() => fuseModels.value.map((item) => item.modelId));
- const visible = ref(false);
- const keyword = ref("");
- const filterScenes = computed(() =>
- scenes.value
- .filter((item) => item.name && item.modelId && item.name.includes(keyword.value))
- .map((scene) => ({
- ...scene,
- createTime: scene.createTime.substr(0, 16),
- type: SceneTypeDesc[scene.type],
- }))
- );
- const selects = ref<Key[]>(selectIds.value);
- const rowSelection: any = ref({
- selectedRowKeys: selects,
- onChange: (ids: number[]) => {
- selects.value = Array.from(new Set(ids.concat(selectIds.value)));
- },
- getCheckboxProps: (record: Scene) => {
- console.error(record);
- return {
- disabled: selectIds.value.includes(record.modelId) || record.createStatus === 2,
- };
- },
- });
- const cloumns = [
- {
- width: "300px",
- title: "名称",
- dataIndex: "name",
- key: "name",
- },
- {
- title: "类型",
- dataIndex: "type",
- key: "type",
- },
- {
- title: "状态",
- dataIndex: "createStatus",
- key: "createStatus",
- },
- {
- title: "拍摄/创建时间",
- dataIndex: "createTime",
- key: "createTime",
- },
- ];
- const okHandler = createLoadPack(async () => {
- const models = selects.value
- .filter((modelId) => !fuseModels.value.some((model) => model.modelId === modelId))
- .map((modelId) => createFuseModels({ modelId }));
- const addPromises = models.map(addFuseModel);
- 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();
- visible.value = false;
- });
- watch(visible, (visible, oldvisible) => {
- if (visible !== oldvisible) {
- keyword.value = "";
- selects.value = selectIds.value;
- visible && initialScenes();
- }
- });
- </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;
- }
- </style>
- <style lang="less">
- .model-header .header-desc {
- margin-bottom: 0;
- }
- .ant-modal-root .ant-table-tbody > tr > td {
- word-break: break-all;
- }
- </style>
|