qinyan 1 year ago
parent
commit
0b437d873e

+ 6 - 5
package.json

@@ -16,9 +16,10 @@
   "dependencies": {
     "@linaria/core": "^4.1.1",
     "@queenjs-modules/auth": "^0.0.18",
-    "@queenjs-modules/queditor": "^0.0.9",
-    "@queenjs-modules/queentree": "^0.0.8",
-    "@queenjs-modules/queentree-explorer": "^0.0.2",
+    "@queenjs-modules/queditor": "^0.0.10",
+    "@queenjs-modules/queentree": "^0.0.9",
+    "@queenjs-modules/queentree-explorer": "^0.0.3",
+    "@queenjs-modules/queentree-explorer-viewer": "^0.0.1",
     "@queenjs/components": "^0.0.5",
     "@queenjs/controllers": "^0.0.6",
     "@queenjs/icons": "^0.0.20",
@@ -43,12 +44,12 @@
     "lodash": "^4.17.21",
     "moment": "^2.29.4",
     "nanoid": "^4.0.2",
-    "nats.ws": "^1.12.0",
+    "nats.ws": "^1.14.0",
     "proto.gl": "^1.0.0",
     "qrcode": "^1.5.1",
     "queen3d": "^0.0.85",
     "queenjs": "^1.0.0-beta.69",
-    "queentree": "^0.1.86-nocheck",
+    "queentree": "^0.1.95-nocheck",
     "rimraf": "^3.0.2",
     "scp2": "^0.5.0",
     "swiper": "^8.4.4",

+ 1 - 1
src/modules-ctx/collocationCtx/index.ts

@@ -14,7 +14,7 @@ export class CollocationCtxModule extends ModuleRoot {
     initCollocation({
       config: {
         httpConfig: {
-          baseURL: "https://www.3dqueen.cloud/cloud/v1",
+          baseURL: "http://192.168.110.226:62293",
         },
       },
     });

+ 2 - 2
src/modules-ctx/storage.ts

@@ -1,10 +1,10 @@
-import { Exp_Storage } from "@queenjs-modules/queentree-explorer/dicts/storage";
+import { QueentreeExplorer_Storage } from "@queenjs-modules/queentree-explorer/storage";
 import {
   HostRootItem,
   NodeRootItem,
 } from "@queenjs-modules/queentree-explorer/typings";
 
-Exp_Storage.setVersion("1.0.0").setDefaultValue(() => {
+QueentreeExplorer_Storage.setVersion("1.0.0").setDefaultValue(() => {
   const expHosts: { [name: string]: HostRootItem } = {};
 
   const cloudRootNode: NodeRootItem = {

+ 9 - 3
src/modules/collocation/index.ts

@@ -1,21 +1,27 @@
-import { PageListController } from "@queenjs/controllers";
+import { PageListController, UploadController } from "@queenjs/controllers";
 import { ModuleRoot } from "queenjs";
 import { designAction } from "./module/actions/design";
 import { initAction } from "./module/actions/init";
 import { sourceAction } from "./module/actions/source";
 import { helper } from "./module/helper";
 import { https } from "./module/http";
-import { sourceStore } from "./module/stores/source";
+import { designStore } from "./module/stores/design";
 
 export class CollocationModule extends ModuleRoot {
   config = this.setConfig({});
   https = this.createHttps([https]);
-  store = this.createStore(sourceStore);
+  store = this.createStore(designStore);
   helper = this.createHelper(helper);
   actions = this.createActions([initAction, sourceAction, designAction]);
 
   controls = {
     listCtrl: new PageListController(this.config?.httpConfig),
+    uploader: new UploadController({
+      httpConfig: {
+        baseURL: "https://www.infish.cn/tree/v1/assetcenter",
+      },
+      dir: "queentree",
+    }),
   };
 
   onReady() {

+ 99 - 0
src/modules/collocation/module/actions/design.ts

@@ -1,7 +1,16 @@
+import { ScenePackageSource } from "@queenjs-modules/queditor/module/objects/scenePack";
 import { queenApi } from "queenjs";
 import { CollocationModule } from "../..";
+import { details } from "../stores/data";
 
 export const designAction = CollocationModule.action({
+  async queryStyleDetail(id: string) {
+    // const res = await this.https.getStyleDetail(id);
+    // this.store.setDesignDetail(res.result);
+    const res = details;
+    this.store.setDesignDetail(res);
+  },
+
   async delDesign(item: IStyle) {
     const result = await queenApi.showConfirm({
       title: "删除提示",
@@ -14,4 +23,94 @@ export const designAction = CollocationModule.action({
     if (res.errorNo != 200) return;
     this.controls.listCtrl.fresh();
   },
+
+  async saveDesign() {
+    const { _id, matMatchs, prodMatchs } = this.store.designDetail;
+    await this.https.updateStyle({ _id, matMatchs, prodMatchs });
+  },
+
+  async addDesign(values) {
+    const styleItem = { ...values };
+
+    if (!styleItem.scenePack.source) {
+      queenApi.messageError("所选数据错误!");
+      return;
+    }
+
+    const packSource: ScenePackageSource = styleItem.scenePack.source;
+    const scenes = packSource.scenes || [];
+
+    const prodCompMap = new Map();
+
+    scenes.forEach((c) => {
+      const sprods = c.products || []; //场景里面的单品
+      sprods.forEach((sp) => {
+        if (!sp.visible) return; //当前单品是隐藏的,忽略
+
+        const prod = packSource.products.find((item) => item.id == sp.prodId);
+        if (!prod) return;
+        const comps = prod?.components || []; //单品的材质配置
+        comps.forEach((comp) => {
+          if (!comp.visible) return; //当前部件是隐藏的,忽略
+
+          //获取单品部件配置
+          if (!prodCompMap.get(prod.id)) {
+            prodCompMap.set(prod.id, new Map());
+          }
+
+          const compMap = prodCompMap.get(prod.id);
+
+          if (!compMap.get(comp.name)) {
+            compMap[comp.name] = {
+              index: 0,
+              name: comp.name,
+              matIds: [],
+              sceneProId: sp.id,
+              visible: comp.visible,
+            };
+          }
+
+          const currComp = compMap[comp.name];
+
+          if (comp.matId && currComp.matIds.indexOf(comp.matId) < 0) {
+            currComp.matIds.push(comp.matId);
+          }
+        });
+      });
+    });
+
+    const matMatchs: MatsMatchComp[] = [];
+    const CompMaps: any = {};
+
+    for (const [key, value] of prodCompMap.entries()) {
+      const prodConf = value;
+
+      for (const compKey in prodConf) {
+        if (!CompMaps[compKey]) {
+          CompMaps[compKey] = prodConf[compKey];
+          CompMaps[compKey].productId = key;
+          continue;
+        }
+        const compConf = CompMaps[compKey];
+        const conf = prodConf[compKey];
+        conf.matIds.forEach((e: any) => {
+          if (compConf.matIds.indexOf(e) < 0) {
+            compConf.matIds.push(e);
+          }
+        });
+      }
+    }
+
+    for (const k in CompMaps) {
+      matMatchs.push(CompMaps[k]);
+    }
+
+    styleItem.matMatchs = matMatchs;
+    styleItem.prodMatchs = [];
+
+    await this.https.createStyle(styleItem);
+    queenApi.messageSuccess("添加成功");
+    this.controls.listCtrl.fresh();
+    return true;
+  },
 });

+ 11 - 1
src/modules/collocation/module/actions/source.ts

@@ -2,5 +2,15 @@ import { queenApi } from "queenjs";
 import { CollocationModule } from "../..";
 
 export const sourceAction = CollocationModule.action({
-  // 
+  async addMatchCategory() {
+    const res = await queenApi.showInput({ title: "请输入分类名称" });
+    if (!res) return;
+    const data = {
+      index: -1,
+      category: res,
+      group: "",
+      productIds: [],
+    };
+    this.store.addMatchCategory(data);
+  },
 });

+ 6 - 3
src/modules/collocation/module/http.ts

@@ -2,7 +2,10 @@ import { CollocationModule } from "..";
 
 export const https = CollocationModule.http({
   getStyleDetail(id: string) {
-    return this.request(`match/style/detail/${id}`, { method: "GET" });
+    return this.request(`match/style/detail/${id}`, {
+      method: "GET",
+      silence: false,
+    });
   },
 
   createStyle(data) {
@@ -13,11 +16,11 @@ export const https = CollocationModule.http({
     return this.request("/match/style/list", { method: "GET", params });
   },
 
-  updateStyle(data: IStyle) {
+  updateStyle(data) {
     return this.request("/match/style/update", { method: "POST", data });
   },
 
   deleteStyle(id: string) {
-    return this.request(`/delete/${id}`, { method: "POST" });
+    return this.request(`/match/style/delete/${id}`, { method: "POST" });
   },
 });

File diff suppressed because it is too large
+ 373 - 0
src/modules/collocation/module/stores/data.ts


+ 48 - 0
src/modules/collocation/module/stores/design.ts

@@ -0,0 +1,48 @@
+import { RadioGroupProps } from "ant-design-vue";
+import { CollocationModule } from "../..";
+
+export const designStore = CollocationModule.store({
+  state: () => ({
+    designDetail: {
+      matMatchs: [],
+      prodMatchs: [],
+    } as any,
+  }),
+  getters: {
+    menuOptions(state) {
+      const options: RadioGroupProps["options"] = [
+        { label: "换料", value: "mat" },
+        { label: "换单品", value: "product" },
+      ];
+
+      const sourceData: any = {
+        mat: state.designDetail.matMatchs,
+        product: [],
+      };
+
+      state.designDetail.prodMatchs?.forEach((element: ProductMatching) => {
+        console.log("element: ", element);
+        const key = element.category || "product";
+        if (!sourceData[key]) {
+          sourceData[key] = [];
+          options.push({ label: key, value: key });
+        }
+        sourceData[key].push(element);
+      });
+      return {
+        options: options.concat({ label: "+", value: "add" }),
+        sourceData,
+      };
+    },
+  },
+  actions: {
+    setDesignDetail(data: IStyle) {
+      this.store.designDetail = data;
+    },
+    addMatchCategory(data) {
+      if (!this.store.designDetail.prodMatchs)
+        this.store.designDetail.prodMatchs = [];
+      this.store.designDetail.prodMatchs?.push(data);
+    },
+  },
+});

+ 0 - 7
src/modules/collocation/module/stores/source.ts

@@ -1,7 +0,0 @@
-import { CollocationModule } from "../..";
-
-export const sourceStore = CollocationModule.store({
-  state: () => ({}),
-  getters: {},
-  actions: {},
-});

+ 0 - 0
src/pages/collocation/Home/components/DesignListModel.tsx → src/pages/collocation/Design/components/DesignListModel.tsx


+ 2 - 5
src/pages/collocation/Home/components/OperationModal.tsx → src/pages/collocation/Design/components/OperationModal.tsx

@@ -1,4 +1,3 @@
-import { useCollocation } from "@/modules/collocation";
 import { css } from "@linaria/core";
 import { Button, Form, Input } from "ant-design-vue";
 import { Rule } from "ant-design-vue/lib/form";
@@ -18,7 +17,6 @@ export default defineComponent({
   },
   setup(props) {
     const modal = queenApi.useDialog();
-    const collocation = useCollocation();
 
     const formRef = ref();
 
@@ -28,7 +26,7 @@ export default defineComponent({
     });
 
     const checkPack = async (_rule: Rule, value: any) => {
-      if (!value.id) {
+      if (!value._id) {
         return Promise.reject("款式不能为空");
       } else {
         return Promise.resolve();
@@ -38,8 +36,7 @@ export default defineComponent({
     const submit = async () => {
       const values = await formRef.value?.validateFields();
       values.thumbnail = values.scenePack.thumbnail;
-      const res = await collocation.https.createStyle(values);
-      return res;
+      modal.submit(values);
     };
 
     return () => {

+ 24 - 18
src/pages/collocation/Home/components/Thumbnail.tsx → src/pages/collocation/Design/components/Thumbnail.tsx

@@ -3,7 +3,7 @@ import { css } from "@linaria/core";
 import { IconAddImg } from "@queenjs/icons";
 import { Image } from "@queenjs/ui";
 import { Button } from "ant-design-vue";
-import { useModal } from "queenjs";
+import { queenApi, useModal } from "queenjs";
 import { defineComponent, reactive } from "vue";
 import { object } from "vue-types";
 import DesignListModel from "./DesignListModel";
@@ -28,9 +28,8 @@ export default defineComponent({
         onOk: async (v: any) => {
           if (v) {
             const folder = v[0][0];
-            // const asset = await folder.getAssetDetail(true);
-            // emit("update:value", asset);
-            emit("update:value", folder.state);
+            const asset = await folder.getAssetDetail(true);
+            emit("update:value", asset);
 
             const DefaultThumbnail = require("@/assets/images/default.png");
             state.thumbnail = folder.state?.thumbnail;
@@ -42,22 +41,29 @@ export default defineComponent({
         onCancel: () => modal.cancel(),
       });
     };
+
     const changeThumbnail = async () => {
-      // let [file] = await ctx.webui.upload.selectAnyFile(false, "image/*");
-      // if (file) {
-      //   if (!["png", "jpg"].includes(file.ext)) {
-      //     ctx.webui.messageError("上传文件格式不正确,仅支持jpg/png格式");
-      //     return false;
-      //   }
-      // }
-      // let res = await ctx.webui.upload.uploadFile(file.file, "thumbnail");
-      // if (res) {
-      //   let { value } = props;
-      //   value.thumbnail = res;
-      //   state.thumbnail = res;
-      //   emit("change", value);
-      // }
+      const [blob] = await queenApi.selectFile({ accept: "image/*" });
+      console.log("blob: ", blob);
+
+      if (blob) {
+        if (!["image/png", "image/jpeg"].includes(blob.type)) {
+          queenApi.messageError("上传文件格式不正确,仅支持jpg/png格式");
+          return false;
+        }
+      }
+      const res = await collocation.controls.uploader.uploadFile(
+        blob,
+        "thumbnail"
+      );
+      if (res) {
+        const { value } = props;
+        value.thumbnail = res;
+        state.thumbnail = res;
+        emit("update:value", value);
+      }
     };
+
     return () => {
       const { thumbnail } = state;
       return (

+ 7 - 19
src/pages/collocation/Home/index.tsx → src/pages/collocation/Design/index.tsx

@@ -26,22 +26,11 @@ export default defineComponent({
         key: "name",
         width: 200,
       },
-      {
-        title: "款式编号",
-        dataIndex: "code",
-        key: "code",
-      },
       {
         title: "款式类别",
         dataIndex: "category",
         key: "category",
       },
-      {
-        title: "价格(元)",
-        dataIndex: "price",
-        key: "price",
-        customRender: ({ text }) => (text / 100 || 0).toFixed(2),
-      },
       {
         title: "操作",
         key: "action",
@@ -62,8 +51,8 @@ export default defineComponent({
                 定制内容
               </Button>
               <Button
-                type="text"
                 danger
+                type="text"
                 onClick={() => collocation.actions.delDesign(record)}
               >
                 删除
@@ -84,17 +73,15 @@ export default defineComponent({
         width: "500px",
       });
       if (!values) return;
-
-      values.thumbnail = values.scenePack?.thumbnail;
-      await collocation.https.createStyle(values);
+      await collocation.actions.addDesign(values);
     };
 
     const showEdit = async (record: IStyle) => {
-      const item: IStyle = await collocation.https.getStyleDetail(record._id);
-      if (!item) return false;
+      const res = await collocation.https.getStyleDetail(record._id);
+      if (!res) return false;
 
       const values: IStyle = await collocation.showModal(
-        <OperationModal data={record} />,
+        <OperationModal data={res.result} />,
         {
           title: "编辑可定制款式",
           width: "500px",
@@ -102,8 +89,9 @@ export default defineComponent({
       );
       if (!values) return;
 
-      values.thumbnail = values.scenePack.thumbnail;
+      values._id = res.result._id;
       await collocation.https.updateStyle(values);
+      collocation.controls.listCtrl.fresh();
     };
 
     return () => {

+ 26 - 28
src/pages/collocation/Editor/components/Header/index.tsx

@@ -1,13 +1,20 @@
+import { useCollocation } from "@/modules/collocation";
 import { css } from "@linaria/core";
 import { IconClose } from "@queenjs/icons";
-import { Space } from "ant-design-vue";
+import {
+  Radio,
+  RadioChangeEvent,
+  RadioGroupProps,
+  Space,
+} from "ant-design-vue";
 import { queenApi } from "queenjs";
 import { defineComponent } from "vue";
 import { useRouter } from "vue-router";
 
 export default defineComponent({
-  setup(props) {
+  setup() {
     const router = useRouter();
+    const collocation = useCollocation();
 
     async function close() {
       if (history.state.canSave) {
@@ -23,36 +30,29 @@ export default defineComponent({
       }
     }
 
+    const changeGroup = (e: RadioChangeEvent) => {
+      switch (e.target.value) {
+        case "add":
+          console.log(collocation.store.designDetail);
+          collocation.actions.addMatchCategory();
+          break;
+      }
+    };
+
     return () => {
       return (
         <div class={headerStyles}>
           <span class="title">搭配定制中心</span>
-          {/* <TipIcon
-            icon="undo"
-            tip="撤销"
-            onClick={() => history.undo()}
-            disabled={!history.state.canUndo}
-          />
-          <TipIcon
-            icon="redo"
-            tip="重做"
-            onClick={() => history.redo()}
-            disabled={!history.state.canRedo}
-          /> */}
-          <div class="flex-1">
-            {/* <RadioGroup
-              class="radio_btns"
-              data={ctx.webui.state.editTypeGroup}
-              value={ctx.webui.state.editType}
-              onChange={(v: any) => (ctx.webui.state.editType = v)}
-            ></RadioGroup> */}
+          <div class="flex-1 text-center">
+            <Radio.Group
+              value="Apple"
+              optionType="button"
+              options={collocation.store.menuOptions.options}
+              onChange={(e) => changeGroup(e)}
+            />
           </div>
           <Space>
-            <IconClose
-              class="icon_close"
-              type="close"
-              onClick={() => close()}
-            />
+            <IconClose class="icon_close" type="close" onClick={close} />
           </Space>
         </div>
       );
@@ -70,8 +70,6 @@ const headerStyles = css`
   padding: 0 20px;
   background-color: #fff;
   .title {
-    width: 140px;
-    margin-right: 64px;
     font-size: 16px;
     font-weight: bold;
     color: #111111;

+ 3 - 2
src/pages/collocation/Editor/components/RightPanel/components/PanelCard.tsx

@@ -5,21 +5,22 @@ import { bool, func, string } from "vue-types";
 
 export default defineComponent({
   props: {
-    onSave: func(),
+    title: string(),
     okText: string().def("保存"),
     showFooter: bool().def(true),
+    onSave: func(),
   },
   setup(props, { slots }) {
     return () => {
       return (
         <div class={PanelStyles}>
+          <h3 class="pt-15px px-10px m-0 font-bold">{props.title}</h3>
           <div class="content">{slots.default?.()}</div>
           {props.showFooter && (
             <div class="footer">
               <Button
                 size="large"
                 type="primary"
-                // loading={match.state.updating}
                 class="submit"
                 onClick={() => props.onSave?.()}
               >

+ 108 - 3
src/pages/collocation/Editor/components/RightPanel/index.tsx

@@ -1,14 +1,119 @@
+import { useCollocation } from "@/modules/collocation";
 import { css } from "@linaria/core";
+import { useQueditor } from "@queenjs-modules/queditor";
+import {
+  IconClear,
+  IconEdit,
+  IconGroup,
+  IconLock,
+  IconUngroup,
+  IconUnlock,
+} from "@queenjs/icons";
+import { List } from "@queenjs/ui";
 import { defineComponent } from "vue";
+import { any } from "vue-types";
+import PanelCard from "./components/PanelCard";
 
 export default defineComponent({
   setup() {
+    const collocation = useCollocation();
+
+    return () => {
+      return (
+        <PanelCard title="部件库" onSave={collocation.actions.saveDesign}>
+          {collocation.store.menuOptions.sourceData?.mat.map(
+            (record: MatsMatchComp, index: number) => {
+              return <Group record={record} key={index} />;
+            }
+          )}
+        </PanelCard>
+      );
+    };
+  },
+});
+
+const Group = defineComponent({
+  props: {
+    record: any(),
+  },
+  setup(props) {
+    const { controls, components, actions } = useQueditor();
+    const { DropView } = components;
+
+    controls.drager.on(
+      "drop:selfDrop",
+      async (event: DragEvent, { type, data }: any) => {
+        console.log(event, type, await data());
+      }
+    );
+
     return () => {
-      return <div class={panelStyles}></div>;
+      const { record } = props;
+      return (
+        <DropView name="selfDrop" type={["asset3d.*"]} class="my-10px">
+          <div class={groupStyles}>
+            <div class="flex items-center justify-between">
+              <span>{record.name}</span>
+              <div class="icons">
+                <IconEdit title="重命名" />
+                {/* <IconUngroup  title="修改分组" /> */}
+                {/* <IconGroup title="解除分组" /> */}
+                {/* <IconLock title="解锁部件" /> */}
+                <IconUnlock title="锁定部件" />
+                <IconClear title="清空面料" />
+              </div>
+            </div>
+            <div>
+              <List data={[]} columns={5} gap="5px">
+                {{
+                  item: () => <div></div>,
+                  empty: () => (
+                    <div class="py-20px text-gray-500 text-center text-12px">
+                      暂无数据
+                    </div>
+                  ),
+                }}
+              </List>
+            </div>
+          </div>
+        </DropView>
+      );
     };
   },
 });
 
-const panelStyles = css`
-  border-left: 1px solid #eaeaea;
+const groupStyles = css`
+  border: 1px solid transparent;
+  border-radius: 4px;
+  padding: 10px;
+  cursor: pointer;
+  transition: all 0.1s ease-in-out;
+  &.active,
+  &:hover {
+    /* background-color: @inf-primary-fade-color; */
+    background-color: #eef1fe;
+  }
+  &.active {
+    border: 1px solid @inf-border-color;
+  }
+
+  &:hover {
+    .icons {
+      opacity: 1;
+    }
+  }
+  .icons {
+    color: @inf-text-less-color;
+    font-size: 18px;
+    opacity: 0;
+    transition: all 0.1s ease-in-out;
+    .inficon {
+      margin-left: 5px;
+      padding: 2px 3px;
+      &:hover {
+        background-color: #e1e1e1;
+        transition: all 0.1s ease-in-out;
+      }
+    }
+  }
 `;

+ 32 - 28
src/pages/collocation/Editor/index.tsx

@@ -1,21 +1,43 @@
-import { initExpViewer } from "@/modules/expViewer";
-import { css } from "@linaria/core";
-import { DefaultUI } from "queenjs";
-import { defineComponent } from "vue";
+import { useCollocation } from "@/modules/collocation";
+import { initQueditor } from "@queenjs-modules/queditor";
+import { initExpViewer } from "@queenjs-modules/queentree-explorer-viewer";
+import { defineComponent, onMounted } from "vue";
+import { useRoute } from "vue-router";
 import Header from "./components/Header";
 import RightPanel from "./components/RightPanel";
-import SourcePanel from "./components/SourcePanel";
 
 export default defineComponent({
   setup() {
-    const expViewer = initExpViewer();
+    const { params } = useRoute();
+    const collocatin = useCollocation();
+
+    onMounted(() => collocatin.actions.queryStyleDetail(params.id as string));
+
+    const expViewer = initExpViewer({
+      modules: {
+        queditor: initQueditor({
+          config: {
+            dragEnable: true,
+          },
+        }),
+      },
+    });
+
     const { queditor } = expViewer.modules;
 
+    expViewer.initComponents({
+      Viewport: {
+        Header: {
+          default: Header,
+        },
+        EditPanel: {
+          default: RightPanel,
+        },
+      },
+    });
+
     queditor.initComponents({
       Viewport: {
-        Header: () => <Header />,
-        SiderLeft: () => <SourcePanel class="w-340px h-1/1" />,
-        SiderRight: () => <RightPanel />,
         Toolbar: {
           default: () => null,
         },
@@ -24,26 +46,8 @@ export default defineComponent({
 
     return () => (
       <div class="h-100vh">
-        <queditor.components.Viewport />
+        <expViewer.components.Viewport />
       </div>
-
-      // <div class={modalStyles}>
-      //   <Header />
-      //   <SourcePanel />
-      //   <Canvas3d />
-      //   <RightPanel />
-      // </div>
     );
   },
 });
-
-const modalStyles = css`
-  height: 100vh;
-  display: grid;
-  grid-template-areas:
-    "header header header"
-    "leftPanel content rightPanel";
-  grid-template-columns: 400px auto 300px;
-  grid-template-rows: 64px auto;
-  background-color: #fff;
-`;

+ 126 - 0
src/pages/collocation/Marchant/Category.tsx

@@ -0,0 +1,126 @@
+import { useCollocation } from "@/modules/collocation";
+import { css } from "@linaria/core";
+import { IconDelete } from "@queenjs/icons";
+import { Button, Switch } from "ant-design-vue";
+import { queenApi } from "queenjs";
+import { defineComponent } from "vue";
+import { any } from "vue-types";
+
+export default defineComponent({
+  props: {
+    value: any(),
+  },
+  emits: ["change"],
+  setup(props, { emit }) {
+    const collocation = useCollocation();
+
+    const addCate = async () => {
+      if (props.value && props.value.length >= 5) {
+        queenApi.messageInfo("暂时不支持添加更多的分类");
+        return false;
+      }
+
+      const res = await queenApi.showInput({
+        title: "分类名称",
+        placeholder: "请输入分类名称",
+        maxLength: 4,
+      });
+      if (!res) return;
+
+      const newCate = { name: res, use: true };
+      const value = props.value ? [...props.value] : [];
+      value.push(newCate);
+      emit("change", value);
+    };
+
+    const switchChange = (checked: boolean, i: number) => {
+      const value = [...props.value];
+      value[i].use = checked;
+      emit("change", value);
+    };
+
+    const delCate = (i: number) => {
+      const value = [...props.value];
+      value.splice(i, 1);
+      emit("change", value);
+    };
+
+    return () => {
+      return (
+        <div class={CategoryView}>
+          <div class={"top"}>
+            <div>款式分类</div>
+            <Button
+              ghost
+              shape="round"
+              size="small"
+              type="primary"
+              onClick={addCate}
+            >
+              添加+
+            </Button>
+          </div>
+          {props.value && props.value.length > 0 && (
+            <div class={"cate_list"}>
+              <div class={"list_top"}>
+                <div>分类名称</div>
+                <div>是否展示在首页</div>
+                <div>操作</div>
+              </div>
+              {props.value.map((e: any, i: number) => {
+                return (
+                  <div key={i} class={"list_item"}>
+                    <div>{e.name}</div>
+                    <div>
+                      <Switch
+                        size="small"
+                        checked={e.use}
+                        // onChange={(checked) => switchChange(checked, i)}
+                      />
+                    </div>
+                    <div>
+                      <Button
+                        type="text"
+                        icon={<IconDelete type="delete" />}
+                        onClick={() => {
+                          delCate(i);
+                        }}
+                      ></Button>
+                    </div>
+                  </div>
+                );
+              })}
+            </div>
+          )}
+        </div>
+      );
+    };
+  },
+});
+
+const CategoryView = css`
+  .top {
+    margin-bottom: 12px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+  .cate_list {
+    border: 1px solid #ccc;
+    border-radius: 2px;
+    .list_top,
+    .list_item {
+      display: flex;
+      align-items: center;
+      border-bottom: 1px solid #ccc;
+      & > div {
+        flex: 1;
+        text-align: center;
+        padding: 5px 10px;
+      }
+      &:last-child {
+        border-bottom: none;
+      }
+    }
+  }
+`;

+ 55 - 0
src/pages/collocation/Marchant/Shoplogo.tsx

@@ -0,0 +1,55 @@
+import { css } from "@linaria/core";
+import { defineComponent } from "vue";
+import { any } from "vue-types";
+import { Image } from "@queenjs/ui";
+import { Button } from "ant-design-vue";
+import { useCollocation } from "@/modules/collocation";
+import { queenApi } from "queenjs";
+
+export default defineComponent({
+  props: {
+    value: any(),
+  },
+  emits: ["update.value"],
+  setup(props, { emit }) {
+    const collocation = useCollocation();
+
+    const uploadThumbnail = async () => {
+      const [Blob] = await queenApi.selectFile({ accept: "image/*" });
+
+      const res = await collocation.controls.uploader.uploadFile(
+        Blob,
+        "avatar"
+      );
+      emit("update.value", res);
+    };
+
+    return () => {
+      return (
+        <div class={LogoThumb}>
+          <div>
+            <Image size={100} src={props.value?.url} />
+          </div>
+          <Button
+            ghost
+            type="primary"
+            class="mt-20px"
+            shape="round"
+            onClick={uploadThumbnail}
+          >
+            修改商城logo
+          </Button>
+        </div>
+      );
+    };
+  },
+});
+const LogoThumb = css`
+  text-align: center;
+
+  img {
+    border: 1px solid #f1f1f1;
+    max-height: 100px;
+    object-fit: contain;
+  }
+`;

+ 92 - 0
src/pages/collocation/Marchant/index.tsx

@@ -0,0 +1,92 @@
+import { useCollocation } from "@/modules/collocation";
+import { css } from "@linaria/core";
+import { Button, Form, Input } from "ant-design-vue";
+import { queenApi } from "queenjs";
+import { defineComponent, reactive, ref } from "vue";
+import Category from "./Category";
+import Shoplogo from "./Shoplogo";
+
+export default defineComponent({
+  setup() {
+    const collocation = useCollocation();
+
+    const formRef = ref();
+
+    const formState = reactive({});
+
+    const submit = async () => {
+      const data = await formRef.value.validate();
+      console.log("data: ", data);
+    };
+
+    const update = async (values: any) => {
+      await collocation.actions.updateMerchant(values);
+      queenApi.messageSuccess("商城信息更新成功");
+    };
+
+    return () => (
+      <div class={DesignStyle}>
+        <h3 class="font-bold">商家信息</h3>
+        <div class={"marchant_form"}>
+          <Form
+            layout="vertical"
+            colon={false}
+            ref={formRef}
+            model={formState}
+            // key={ctx.shop.state.ShopInfo?.merchantId}
+            // data={ctx.shop.state.ShopInfo}
+          >
+            <Form.Item name="thumbnail">
+              <Shoplogo />
+            </Form.Item>
+
+            <Form.Item name="name" label="商城名称">
+              <Input placeholder="请输入定制商城名称" maxlength={12} />
+            </Form.Item>
+
+            <Form.Item name="sellerKey" label="收款账号">
+              <Input placeholder="请输入收款账号" />
+            </Form.Item>
+
+            <Form.Item name="categories">
+              <Category />
+            </Form.Item>
+
+            <Form.Item class="text-center">
+              <Button
+                class="w-200px"
+                size="large"
+                type="primary"
+                onClick={submit}
+              >
+                保存
+              </Button>
+            </Form.Item>
+          </Form>
+        </div>
+      </div>
+    );
+  },
+});
+
+const DesignStyle = css`
+  padding: 20px;
+  .marchant_form {
+    width: 500px;
+    margin: 0 auto;
+    .form_item {
+      .form_item_view {
+        flex-flow: column;
+        align-items: flex-start;
+        .form_item_label {
+          width: 100%;
+          max-width: 100%;
+          margin-bottom: 12px;
+        }
+        .form_item_child {
+          width: 100%;
+        }
+      }
+    }
+  }
+`;

+ 6 - 1
src/pages/collocation/router.ts

@@ -12,6 +12,11 @@ const routes = [
     component: BasicLayout,
     redirect: "/design",
     children: [
+      {
+        path: "/marchant",
+        name: "基础信息",
+        component: () => import("./Marchant"),
+      },
       {
         path: "/design",
         name: "款式管理",
@@ -21,7 +26,7 @@ const routes = [
           {
             path: "/design/list",
             name: "款式列表",
-            component: () => import("./Home"),
+            component: () => import("./Design"),
           },
         ],
       },

+ 2 - 2
src/typings/collocation.d.ts

@@ -20,6 +20,6 @@ declare interface IStyle {
   thumbnail?: Image;
   category?: string[];
   matMatchs?: MatsMatchComp[];
-  proMatchs?: ProductMatching[];
-  scenePack: IAssetMesh;
+  prodMatchs?: ProductMatching[];
+  scenePack: any;
 }

+ 26 - 21
yarn.lock

@@ -1224,20 +1224,25 @@
   resolved "http://124.70.149.18:4873/@queenjs-modules%2fauth/-/auth-0.0.18.tgz"
   integrity sha512-zQGPz1GUR2QE3qCkfpdQ3vDkNNuFRhvrD+ErCynnlDP/QQNgvOoHizPEO5OE4VzdBu+/psGWymQs+9zONGuO3A==
 
-"@queenjs-modules/queditor@^0.0.9":
-  version "0.0.9"
-  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueditor/-/queditor-0.0.9.tgz#2c4c0b8d68da48e3e30dc92b0acb5f1f8d8761ce"
-  integrity sha512-iK9PykYQO0gZOcz851e4NNBUAg/DlmhuQrQgRkmlK287oD7u6r8pD/ONOD7Anyy04FP6BTe9DOhGMW55imdlVw==
+"@queenjs-modules/queditor@^0.0.10":
+  version "0.0.10"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueditor/-/queditor-0.0.10.tgz#d79b432409a1da86042c4f4e8a00e5704a8b073b"
+  integrity sha512-eQFq07e8CK0VJekDJ43+Cbias7cE8iC2uSPqaKaJiAFnDQ9A5pJYDh6MN6cMzUSUEkoY+5I9hP4PagDSw0KW+Q==
 
-"@queenjs-modules/queentree-explorer@^0.0.2":
-  version "0.0.2"
-  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer/-/queentree-explorer-0.0.2.tgz#fbbee041ed4d6de19edc7401f1c2734a2b971952"
-  integrity sha512-gV3Uba0LJxcpgDltktvtQ6F2ndj3w7T57PV1iD0xpezLCDYgNGnOVWBGrpKekr2QAnbxlX2z2jRv6XotHicRww==
+"@queenjs-modules/queentree-explorer-viewer@^0.0.1":
+  version "0.0.1"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer-viewer/-/queentree-explorer-viewer-0.0.1.tgz#0776486096c4f8ceaea25944d07baa2a242e6658"
+  integrity sha512-oTFT2CiQhbY3RM0JFQCc6zaTYcMqFpTrZNlo6QiVgbV7XOf63aTnaKo4HMhFQo2Mv8l1lloTQVHmcV7X5hy2Vg==
 
-"@queenjs-modules/queentree@^0.0.8":
-  version "0.0.8"
-  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree/-/queentree-0.0.8.tgz#2a471100a1d09e72dcbc54daa453fc4c275a71b7"
-  integrity sha512-+B9WbIUgm656hR9bougNDLAq2p7foaEhybfyjLHu2DIqmyNooKkzNth8e/R/R4QjbCI6Who6Pg6q0H9txnjLcA==
+"@queenjs-modules/queentree-explorer@^0.0.3":
+  version "0.0.3"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree-explorer/-/queentree-explorer-0.0.3.tgz#6838878c6b3ca7b3f69eddb8f6ae75824235f515"
+  integrity sha512-QEQouW58aMc5sQqR4mWf96vovnazkOqpECAZFFS/8Q7w75nV1CDLHRPWgYYTYCy7MngyXZTlskiq2mDHIyl9kg==
+
+"@queenjs-modules/queentree@^0.0.9":
+  version "0.0.9"
+  resolved "http://124.70.149.18:4873/@queenjs-modules%2fqueentree/-/queentree-0.0.9.tgz#6f9c2513a2c60febf3f807bc028e515e01f3f710"
+  integrity sha512-Tm1sUkyD5ppr1ksGjbgwViBrza5VkKr0iKmyZTT3wKblovHtgzOEZKTJ9KEY6IjtG7XVeAyFxu0l5KHbEUu+xw==
 
 "@queenjs/components@^0.0.5":
   version "0.0.5"
@@ -5465,12 +5470,12 @@ nanopop@^2.1.0:
   resolved "http://124.70.149.18:4873/nanopop/-/nanopop-2.2.0.tgz"
   integrity sha512-E9JaHcxh3ere8/BEZHAcnuD10RluTSPyTToBvoFWS9/7DcCx6gyKjbn7M7Bx7E1veCxCuY1iO6h4+gdAf1j73Q==
 
-nats.ws@^1.12.0:
-  version "1.12.0"
-  resolved "http://124.70.149.18:4873/nats.ws/-/nats.ws-1.12.0.tgz"
-  integrity sha512-SMixcOp1FVVNEqa4nvU1m921++fXOUxcxrsVGJImqbw1prcda/OVB/t2dNT2onUTBDru+z2RZhS0H4x2vBRuSQ==
+nats.ws@^1.14.0:
+  version "1.14.0"
+  resolved "http://124.70.149.18:4873/nats.ws/-/nats.ws-1.14.0.tgz#b7c07fcf0334f58ff4d0ef4354149393de6691ec"
+  integrity sha512-2s/4v1KWG+JG4I11e301t+0oGBbpjsU/arPhVjrCzPRam83w+m1gqF85xSZgLDIge/S1Do2E0bmka1cUH5Qc/Q==
   optionalDependencies:
-    nkeys.js "1.0.4"
+    nkeys.js "1.0.5"
 
 natural-compare@^1.4.0:
   version "1.4.0"
@@ -5506,10 +5511,10 @@ nice-try@^1.0.4:
   resolved "http://124.70.149.18:4873/nice-try/-/nice-try-1.0.5.tgz"
   integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
 
-nkeys.js@1.0.4:
-  version "1.0.4"
-  resolved "http://124.70.149.18:4873/nkeys.js/-/nkeys.js-1.0.4.tgz"
-  integrity sha512-xeNDE6Ha5I3b3PnlHyT9AbmBxq3Vb9KHzmaI/h4IXYg0PUVZSUXNHNhTfU20oBsubw2ZdV/1AdC6hnRuMiZfMQ==
+nkeys.js@1.0.5:
+  version "1.0.5"
+  resolved "http://124.70.149.18:4873/nkeys.js/-/nkeys.js-1.0.5.tgz#3024bde671eb33be0316ff2d5abe8b8cec960158"
+  integrity sha512-u25YnRPHiGVsNzwyHnn+PT90sgAhnS8jUJ1nxmkHMFYCJ6+Ic0lv291w7uhRBpJVJ3PH2GWbYqA151lGCRrB5g==
   dependencies:
     tweetnacl "1.0.3"
 

Some files were not shown because too many files changed in this diff