qinyan 1 年之前
父节点
当前提交
0b73086b3b

+ 2 - 2
package.json

@@ -26,9 +26,9 @@
     "@ckeditor/ckeditor5-vue": "^5.1.0",
     "@linaria/core": "^4.1.1",
     "@queenjs-modules/auth": "^0.0.18",
-    "@queenjs-modules/queditor": "^0.0.11",
+    "@queenjs-modules/queditor": "^0.0.12",
     "@queenjs-modules/queentree": "^0.0.10",
-    "@queenjs-modules/queentree-explorer": "^0.0.5",
+    "@queenjs-modules/queentree-explorer": "^0.0.6",
     "@queenjs-modules/queentree-explorer-viewer": "^0.0.3",
     "@queenjs/components": "^0.0.5",
     "@queenjs/controllers": "^0.0.6",

+ 85 - 0
src/modules/_default/viewerStorage.ts

@@ -0,0 +1,85 @@
+import { Dict_Apis } from "@/dict/apis";
+import {
+  HostRootItem,
+  NodeRootItem,
+  QueentreeExplorer_Storage
+} from "@queenjs-modules/queentree-explorer";
+import { nanoid } from "nanoid";
+
+// 设置资源面板Tab页
+QueentreeExplorer_Storage.setVersion("1.0.6");
+QueentreeExplorer_Storage.setDefaultValue(() => {
+  const expHosts: { [name: string]: HostRootItem } = {};
+
+  const cloudRootNode: NodeRootItem = {
+    names: ["云盘"],
+    ids: [nanoid()],
+    nodeType: "host",
+    tabPerms: ["rename", "login"],
+    nodePerms: ["editable", "saveAs"],
+  };
+
+  const platformRootNode: NodeRootItem = {
+    names: ["平台", "楦库", "面料"],
+    ids: [
+      cloudRootNode.ids[0],
+      "628b4ae8633d10f8e3658557",
+      "62a300a0a4fd6456392ebe76",
+    ],
+    nodeType: "branch",
+    assetType: 31,
+    tabPerms: [],
+    nodePerms: ["saveAs"],
+  };
+
+  const myRootNodes = [cloudRootNode];
+
+  // if (Dict_Apis.queentree) {
+  //   const localNodeRoot: NodeRootItem = {
+  //     names: ["本地"],
+  //     ids: [nanoid()],
+  //     nodeType: "host",
+  //     tabPerms: ["rename"],
+  //     nodePerms: ["editable", "saveAs"],
+  //   };
+
+  //   myRootNodes.unshift(localNodeRoot);
+
+  //   expHosts[localNodeRoot.ids[0]] = {
+  //     baseURL: Dict_Apis.queentree,
+  //     authURL: Dict_Apis.auth,
+  //     authKey: "queentreesku3d",
+  //   };
+  // }
+
+  expHosts[cloudRootNode.ids[0]] = {
+    baseURL: Dict_Apis.queentree,
+    authURL: Dict_Apis.auth,
+    authKey: "queentreesku3d",
+  };
+
+  const expNodeRoots = [...myRootNodes, platformRootNode];
+
+  return {
+    expHosts,
+    expWindows: [
+      {
+        groupName: "我的资源",
+        rootNodeIds: myRootNodes.map((rootNode) => rootNode.ids.at(-1) || ""),
+      },
+      {
+        groupName: "平台资源",
+        rootNodeIds: [platformRootNode.ids.at(-1) as string],
+      },
+      {
+        groupName: "共享资源",
+        rootNodeIds: [],
+        showShareBtn: true,
+      },
+    ],
+    expNodeRoots,
+    expActiveState: {
+      currWindowName: "我的资源",
+    },
+  };
+});

+ 1 - 0
src/modules/resource/actions/material.ts

@@ -48,6 +48,7 @@ export const materialActions = ResourceModule.action({
   async queryTplsDetail(id) {
     const res = await this.https.queryTplsDetail(id);
     this.store.setSourceDetail(res.result);
+    this.store.setSelectedId(res.result.webEditor?.meshSlots[0]?.Id);
   },
   async submitRender() {
     //

+ 3 - 1
src/modules/resource/index.ts

@@ -38,8 +38,10 @@ export class ResourceModule extends ModuleRoot {
     this.controls.promotionListCtrl.state.size = 12;
     this.controls.materialListCtrl.setCrudPrefix("/source");
     this.controls.materialListCtrl.state.size = 24;
-    this.controls.matTempListCtrl.setCrudPrefix("/tpls");
     this.controls.renderTaskListCtrl.setCrudPrefix("/tpls");
+    this.controls.renderTaskListCtrl.state.size = 24;
+    this.controls.matTempListCtrl.setCrudPrefix("/tpls");
+    this.controls.matTempListCtrl.state.size = 20;
   }
 }
 

+ 16 - 0
src/modules/resource/store.ts

@@ -3,10 +3,23 @@ import { ResourceModule } from ".";
 export const store = ResourceModule.store({
   state: () => ({
     type: "video",
+    selectedId: "",
     sourceDetail: {
       webEditor: { pack: {} },
     } as any,
   }),
+  getters: {
+    currentMesh(state) {
+      return state.sourceDetail.webEditor?.meshSlots?.filter(
+        (e: any) => e.Id == state.selectedId
+      );
+    },
+    currentMats(state) {
+      return state.sourceDetail.webEditor?.matSlots?.filter(
+        (e: any) => e.meshSlotId == state.selectedId
+      );
+    },
+  },
   actions: {
     setSourceType(v: string) {
       this.store.type = v;
@@ -14,5 +27,8 @@ export const store = ResourceModule.store({
     setSourceDetail(data) {
       this.store.sourceDetail = data;
     },
+    setSelectedId(id: string) {
+      this.store.selectedId = id;
+    },
   },
 });

+ 2 - 2
src/pages/website/EditMaterial/components/Header.tsx

@@ -4,14 +4,14 @@ import { IconMore } from "@queenjs/icons";
 import { Button, Divider } from "ant-design-vue";
 import { defineComponent } from "vue";
 import Logo from "../../components/layout/Logo";
-import SelectTemplateModal from "./SelectTemplateModal";
+import OutputTemplateModal from "./OutputTemplateModal";
 
 export default defineComponent({
   setup() {
     const resource = useResource();
 
     const showModal = () => {
-      resource.showModal(<SelectTemplateModal />, {
+      resource.showModal(<OutputTemplateModal />, {
         title: "选择模板",
         width: "900px",
       });

+ 109 - 0
src/pages/website/EditMaterial/components/LeftPanel.tsx

@@ -0,0 +1,109 @@
+import { useResource } from "@/modules/resource";
+import { cx } from "@linaria/core";
+import { useQueditor } from "@queenjs-modules/queditor";
+import { switchSceneProdComp } from "@queenjs-modules/queditor/module/controls/Queen3dCtrl/actions/geom";
+import { Pack } from "@queenjs-modules/queditor/objects";
+import { AssetItemFile } from "@queenjs-modules/queentree-explorer/objects/fileSystem/assetFiles";
+import { Image, List } from "@queenjs/ui";
+import { Button } from "ant-design-vue";
+import { defineComponent } from "vue";
+import { any, bool } from "vue-types";
+import LibraryModal from "./LibraryModal";
+
+export default defineComponent({
+  setup() {
+    const resource = useResource();
+    const queditor = useQueditor();
+
+    const replaceMesh = async () => {
+      const res = await resource.showModal<AssetItemFile>(<LibraryModal />, {
+        width: "900px",
+      });
+      console.log("res: ", res);
+
+      const pack = await res.getAssetDetail();
+      const data = queditor.helper.getRelatedSourceByProduct(
+        pack.source as Pack["source"],
+        res.state.id
+      );
+      console.log("data: ", data);
+      queditor.actions.insertMesh(data);
+    };
+
+    return () => {
+      const list = resource.store.sourceDetail.webEditor?.meshSlots || [];
+      return (
+        <div class="w-300px flex flex-col">
+          <div class="p-15px text-16px text-white border-dark-800 border-0 border-b-1 border-solid">
+            模型列表
+          </div>
+          <List data={list} gap="10px" class="scrollbar flex-1 py-15px px-15px">
+            {{
+              item: (record: any) => (
+                <ProductItem
+                  record={record}
+                  onChange={replaceMesh}
+                  active={record.Id == resource.store.selectedId}
+                  onClick={() => {
+                    // queditor.
+                    debugger;
+                    switchSceneProdComp.call(
+                      queditor.controls.queen3dCtrl,
+                      queditor.store.pack.scenes[0].products[0].prodId,
+                      record.meshName
+                    );
+                    resource.store.setSelectedId(record.Id);
+                  }}
+                />
+              ),
+              loadmore: () => (
+                <div class="text-center py-20px text-12px opacity-80">
+                  没有更多了
+                </div>
+              ),
+            }}
+          </List>
+        </div>
+      );
+    };
+  },
+});
+
+const ProductItem = defineComponent({
+  props: {
+    record: any().isRequired,
+    active: bool().def(false),
+  },
+  emits: ["change", "click"],
+  setup(props, { emit }) {
+    return () => {
+      const { active, record } = props;
+      return (
+        <div
+          style={{ backgroundColor: "#303030" }}
+          class={cx(
+            "flex items-center py-6px px-12px rounded-4px border-1 border-solid cursor-pointer hover:opacity-80 transition-all",
+            active ? "border-orange-200" : "border-transparent"
+          )}
+          onClick={() => emit("click", record)}
+        >
+          <Image src={record.thumbnail} class="w-48px rounded-4px" />
+          <div class="ml-10px flex-1 mr-5px truncate w-0">
+            {record.meshName || "未命名"}
+          </div>
+          <Button
+            type="primary"
+            ghost
+            size="small"
+            onClick={(e) => {
+              e.stopPropagation();
+              emit("change", record);
+            }}
+          >
+            替换
+          </Button>
+        </div>
+      );
+    };
+  },
+});

+ 63 - 0
src/pages/website/EditMaterial/components/LibraryModal.tsx

@@ -0,0 +1,63 @@
+import "@/modules/_default/viewerStorage";
+import {
+  initQueentreeExplorer,
+  NodeTypes
+} from "@queenjs-modules/queentree-explorer";
+import PickNodeSteps from "@queenjs-modules/queentree-explorer/components/PickNodeSteps";
+import PickNodeStep from "@queenjs-modules/queentree-explorer/components/PickNodeSteps/PickNodeStep";
+import { StepController } from "@queenjs-modules/queentree-explorer/components/PickNodeSteps/StepController";
+import { Exception, useModal } from "queenjs";
+import { defineComponent } from "vue";
+import { array } from "vue-types";
+
+export default defineComponent({
+  props: {
+    nodeTypes: array<NodeTypes>().def(["packProd"]),
+  },
+
+  setup(props) {
+    const stepCtrol = new StepController(1);
+    const modal = useModal();
+
+    initQueentreeExplorer({
+      config: {
+        showNodeToolbar: false,
+        nodeListColumns: 6,
+      },
+    });
+
+    async function submit() {
+      try {
+        const branchFolder = stepCtrol.state.data.pickNodes[0];
+        modal.submit(branchFolder);
+      } catch (error: any) {
+        Exception.error(error?.toString());
+      }
+    }
+
+    return () => {
+      const { nodeTypes } = props;
+      return (
+        <PickNodeSteps
+          onSubmit={submit}
+          control={stepCtrol}
+          lastStepText="发送"
+          steps={[
+            {
+              title: "选择",
+              content: () => (
+                <PickNodeStep
+                  control={stepCtrol}
+                  options={{
+                    nodeTypes: nodeTypes,
+                    //   childNodeType: "packProd",
+                  }}
+                />
+              ),
+            },
+          ]}
+        />
+      );
+    };
+  },
+});

+ 0 - 57
src/pages/website/EditMaterial/components/ModelPanel.tsx

@@ -1,57 +0,0 @@
-import { useResource } from "@/modules/resource";
-import { Image, List } from "@queenjs/ui";
-import { Button } from "ant-design-vue";
-import { defineComponent } from "vue";
-import { any } from "vue-types";
-
-export default defineComponent({
-  setup() {
-    const resource = useResource();
-
-    return () => {
-      const list = resource.store.sourceDetail.webEditor?.meshSlots || [];
-      return (
-        <div class="w-300px flex flex-col">
-          <div class="p-15px text-16px text-white border-dark-800 border-0 border-b-1 border-solid">
-            模型列表
-          </div>
-          <List data={list} gap="10px" class="scrollbar flex-1 py-15px px-15px">
-            {{
-              item: (record: any) => <ProductItem record={record} />,
-              loadmore: () => (
-                <div class="text-center py-20px text-12px opacity-80">
-                  没有更多了
-                </div>
-              ),
-            }}
-          </List>
-        </div>
-      );
-    };
-  },
-});
-
-const ProductItem = defineComponent({
-  props: {
-    record: any().isRequired,
-  },
-  setup(props) {
-    return () => {
-      const { record } = props;
-      return (
-        <div
-          class="flex items-center py-6px px-12px rounded-4px"
-          style={{ backgroundColor: "#303030" }}
-        >
-          <Image src={record.thumbnail} class="w-48px rounded-4px" />
-          <div class="ml-10px flex-1 mr-5px truncate w-0">
-            {record.meshName || "未命名"}
-          </div>
-          <Button type="primary" ghost size="small">
-            替换
-          </Button>
-        </div>
-      );
-    };
-  },
-});

+ 0 - 0
src/pages/website/EditMaterial/components/SelectTemplateModal.tsx → src/pages/website/EditMaterial/components/OutputTemplateModal.tsx


+ 27 - 4
src/pages/website/EditMaterial/components/ComponentPanel.tsx → src/pages/website/EditMaterial/components/RightPanel.tsx

@@ -1,15 +1,30 @@
 import { useResource } from "@/modules/resource";
+import { AssetItemFile } from "@queenjs-modules/queentree-explorer/objects/fileSystem/assetFiles";
 import { Image, List } from "@queenjs/ui";
 import { Button } from "ant-design-vue";
 import { defineComponent } from "vue";
 import { any } from "vue-types";
+import LibraryModal from "./LibraryModal";
 
 export default defineComponent({
   setup() {
     const resource = useResource();
 
+    const replaceMat = async () => {
+      const res = await resource.showModal<AssetItemFile>(
+        <LibraryModal nodeTypes={["matGroupItem", "mat", "packMat"]} />,
+        {
+          width: "900px",
+        }
+      );
+      console.log("res: ", res);
+
+      const data = await res.getAssetDetail();
+      console.log("data: ", data);
+    };
+
     return () => {
-      const list = resource.store.sourceDetail.webEditor?.matSlots || [];
+      const list = resource.store.currentMats || [];
       return (
         <div class="w-300px flex flex-col">
           <div class="p-15px text-16px text-white border-dark-800 border-0 border-b-1 border-solid">
@@ -17,7 +32,9 @@ export default defineComponent({
           </div>
           <List data={list} gap="10px" class="scrollbar flex-1 py-15px px-15px">
             {{
-              item: (record: any) => <CompItem record={record} />,
+              item: (record: any) => (
+                <CompItem record={record} onClick={replaceMat} />
+              ),
               loadmore: () => (
                 <div class="text-center py-20px text-12px opacity-80">
                   没有更多了
@@ -35,7 +52,8 @@ const CompItem = defineComponent({
   props: {
     record: any().isRequired,
   },
-  setup(props) {
+  emits: ["change", "click"],
+  setup(props, { emit }) {
     return () => {
       const { record } = props;
       return (
@@ -45,7 +63,12 @@ const CompItem = defineComponent({
         >
           <Image src={record.thumbnail} class="w-48px rounded-4px" />
           <div class="ml-10px flex-1 mr-5px w-0">{record.name || "未命名"}</div>
-          <Button type="primary" ghost size="small">
+          <Button
+            ghost
+            type="primary"
+            size="small"
+            onClick={() => emit("click", record)}
+          >
             替换
           </Button>
         </div>

+ 10 - 4
src/pages/website/EditMaterial/index.tsx

@@ -3,9 +3,10 @@ import { initQueditor } from "@queenjs-modules/queditor";
 import { initExpViewer } from "@queenjs-modules/queentree-explorer-viewer";
 import { defineComponent, onBeforeUnmount, onMounted } from "vue";
 import { useRoute } from "vue-router";
-import ComponentPanel from "./components/ComponentPanel";
+import RightPanel from "./components/RightPanel";
 import Header from "./components/Header";
-import ModelPanel from "./components/ModelPanel";
+import LeftPanel from "./components/LeftPanel";
+import { switchSceneProdComp } from "@queenjs-modules/queditor/module/controls/Queen3dCtrl/actions/geom";
 
 export default defineComponent({
   setup() {
@@ -29,7 +30,7 @@ export default defineComponent({
           default: Header,
         },
         EditPanel: {
-          default: ComponentPanel,
+          default: RightPanel,
         },
       },
     });
@@ -37,7 +38,7 @@ export default defineComponent({
     queditor.initComponents({
       Viewport: {
         SiderLeft: {
-          default: ModelPanel,
+          default: LeftPanel,
         },
         Toolbar: {
           default: () => null,
@@ -52,6 +53,11 @@ export default defineComponent({
       queditor.actions.initPack(resource.store.sourceDetail?.webEditor?.pack);
       queditor.store.setCurrScene(0);
       expViewer.store.setEditNodeUid(resource.store.sourceDetail._id);
+      switchSceneProdComp.call(
+        queditor.controls.queen3dCtrl,
+        queditor.store.pack.scenes[0].products[0].prodId,
+        resource.store.currentMesh.meshName
+      );
     };
 
     onMounted(() => init());

+ 10 - 8
yarn.lock

@@ -1604,20 +1604,22 @@
   resolved "http://124.70.149.18:4873/@queenjs-modules%2fauth/-/auth-0.0.18.tgz#48a7abd1023cee213cbfdd1b822e52041a070818"
   integrity sha512-zQGPz1GUR2QE3qCkfpdQ3vDkNNuFRhvrD+ErCynnlDP/QQNgvOoHizPEO5OE4VzdBu+/psGWymQs+9zONGuO3A==
 
-"@queenjs-modules/queditor@^0.0.11":
-  version "0.0.11"
-  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueditor/-/queditor-0.0.11.tgz#05fdea6cb5dc0f9618e9c4138eaaa314cb658fd9"
-  integrity sha512-KlQ6po02/ZVBXnfzR+hZxQ3C9tcZG2EQDj0TXPjhY3J54BuxDvktIGnlXvFv8GcUpM+/bA4Ka3JPOapgR4Or2Q==
+"@queenjs-modules/queditor@^0.0.12":
+  version "0.0.12"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueditor/-/queditor-0.0.12.tgz#12036f9226065cd013507742edd2624a057fd2a9"
+  integrity sha512-lkBFRbamdQVkwT0CZMlW1mTxH1N6Kp7LfTMLYGO/iVPu1QWTUiS6MOE/7yBjLmqZfSiiqzZa0QUo3Oi6u6sVJg==
 
 "@queenjs-modules/queentree-explorer-viewer@^0.0.3":
   version "0.0.3"
   resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer-viewer/-/queentree-explorer-viewer-0.0.3.tgz#1952b50a9a0cc92b04ea24cfd3064c8d3b19bd70"
   integrity sha512-sQYuJdq46GoYIv+yyQPd5eVNKeOPgaOoBEine8PQxVFh7gLxcdRi4mfPZq7Wq92g+5juCSFwkSRavaANHrf1kA==
 
-"@queenjs-modules/queentree-explorer@^0.0.5":
-  version "0.0.5"
-  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer/-/queentree-explorer-0.0.5.tgz#3820f033d23e594838205c3204d7ecbe78831fa0"
-  integrity sha512-/F447pKOt0Kgq4nQqAW7w9RZlj49nhX0FQiQCtwHZVVGBPd/g8d1G4jKdpbQDGZoM2Z8yUfoei2MGnYQ5xZwnQ==
+"@queenjs-modules/queentree-explorer@^0.0.6":
+  version "0.0.6"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer/-/queentree-explorer-0.0.6.tgz#e2ba1ba4a247a5f6ed5a9de50271315bf81e39ee"
+  integrity sha512-2efcbsCT0+4BiuRQk0SPC4cSiVenArCCFxapkgE+4mymwkiIlXBQ/s2bJNUuylLFxjQGsvW2bHdgQzA2zvRqRg==
+  dependencies:
+    "@queenjs-modules/queentree" "^0.0.10"
 
 "@queenjs-modules/queentree@^0.0.10":
   version "0.0.10"