bianjiang 1 year ago
parent
commit
12061ee069

BIN
src/assets/imgs/icon_preview.png


+ 33 - 9
src/modules/resource/actions/collection.tsx

@@ -21,6 +21,12 @@ export const collectionAction = ResourceModule.action({
       await this.https.createCollection(data);
     }
   },
+  async showCollectionList(record: any) {
+    this.showModal(<this.components.CollectionListModal record={record} />, {
+      title: `${record.title}作品集`,
+      fullscreen: true,
+    });
+  },
   async collectionDTL(id: string) {
     const res = await this.https.detailCollection(id);
     if (res.errorNo != 200) {
@@ -28,18 +34,36 @@ export const collectionAction = ResourceModule.action({
     }
     return res.result;
   },
-  async searchCollection(key: string) {
-    const res = await this.https.searchCollection({ key });
-    if (res.errorNo != 200) {
-      return;
+  async searchCollection(key: string, commitId: string) {
+    try {
+      const res = await this.https.searchCollection({ key, commitId });
+      return res.result;
+    } catch (e) {
+      queenApi.messageError("未查询到接收地址数据!");
     }
-    return res.result;
   },
   async commitCollection(data: any) {
-    const res = await this.https.commitCollection(data);
-    if (res.errorNo != 200) {
-      return;
+    try {
+      const res = await this.https.commitCollection(data);
+      return res.result;
+    } catch (e) {
+      console.log(e);
+    }
+  },
+  async getCommitHistoryDetail(id: string) {
+    try {
+      const res = await this.https.commitHistoryDetail(id);
+      return res.result;
+    } catch (e) {
+      queenApi.messageError("未查询到数据!");
+    }
+  },
+  async updateCommitData(data: any) {
+    try {
+      const res = await this.https.updateCommitData(data);
+      return res.result;
+    } catch (e) {
+      console.log(e);
     }
-    return res.result;
   },
 });

+ 20 - 12
src/modules/resource/components/CollectionEditModal.tsx

@@ -51,8 +51,8 @@ export default defineComponent({
           flags: [],
           status: "",
           title: "",
-          startTime: "",
-          endTime: "",
+          startTime: undefined,
+          endTime: undefined,
         };
 
     const resource = useResource();
@@ -99,35 +99,39 @@ export default defineComponent({
     };
 
     const statusOptions = () => {
-      const options = formState.statues.map((e: any) => {
+      const options = formState?.statues?.map((e: any) => {
         return { label: e, value: e };
       });
-      return options;
+      return options || [];
     };
     const addStatus = async () => {
+      const statues = formState?.statues || [];
       const text = await queenApi.showInput({
         title: "添加状态",
         placeholder: "输入状态名称",
       });
       if (!text) return;
-      if (formState.statues.length == 0) {
+      if (statues.length == 0) {
         formState.status = text;
       }
-      formState.statues.push(text);
+      statues.push(text);
+      formState.statues = statues;
     };
     const flagsOptions = () => {
-      const options = formState.flags.map((e: any) => {
+      const options = formState?.flags?.map((e: any) => {
         return { label: e, value: e };
       });
-      return options;
+      return options || [];
     };
     const addFlag = async () => {
+      const flags = formState?.flags || [];
       const text = await queenApi.showInput({
         title: "添加标签",
         placeholder: "输入标签名称",
       });
       if (!text) return;
-      formState.flags.push(text);
+      flags.push(text);
+      formState.flags = flags;
     };
     const h5Options = () => {
       const options = resource.controls.promotionListCtrl.state.list.map(
@@ -278,8 +282,13 @@ export default defineComponent({
                 ranges={pickerRanges()}
                 value={time}
                 onChange={(datas: any) => {
-                  formState.startTime = dayjs(datas[0]);
-                  formState.endTime = dayjs(datas[1]);
+                  if (datas) {
+                    formState.startTime = dayjs(datas[0]);
+                    formState.endTime = dayjs(datas[1]);
+                  } else {
+                    formState.startTime = undefined;
+                    formState.endTime = undefined;
+                  }
                 }}
               />
             </Form.Item>
@@ -303,7 +312,6 @@ const ImageUploader = defineComponent({
   },
   emits: ["change"],
   setup(props, { emit }) {
-    const { controls } = useEditor();
     const uploadImage = async () => {
       const url = await SelectOneImage();
       if (!url) return;

+ 159 - 0
src/modules/resource/components/CollectionListModal.tsx

@@ -0,0 +1,159 @@
+import { css, cx } from "@linaria/core";
+import { defineComponent, onMounted } from "vue";
+import { any } from "vue-types";
+import List from "@/components/AssetsList";
+import { PageListController } from "@queenjs/controllers";
+import { defineUI } from "queenjs";
+import { Image, View } from "@queenjs/ui";
+import { useResource } from "..";
+import dayjs from "dayjs";
+import { useEditor } from "@/modules/editor";
+import { Select } from "ant-design-vue";
+export default defineComponent({
+  props: {
+    record: any(),
+  },
+  setup(props, { emit }) {
+    const resource = useResource();
+    const editor = useEditor();
+    const ListCtrl = new PageListController(resource.config?.httpConfig);
+    ListCtrl.setCrudPrefix("/wk/h5");
+    ListCtrl.state.query = { id: props.record._id };
+    onMounted(() => {
+      ListCtrl.loadPage(1);
+    });
+    const previewInModal = async (id: string, title: string) => {
+      if (!id) {
+        return;
+      }
+      const ret = await resource.actions.getCommitHistoryDetail(id);
+      if (!ret) {
+        return;
+      }
+      editor.store.setDesignData(ret);
+      editor.actions.switchMode("preview");
+      resource.showModal(
+        <div class={"!p-0"}>
+          <div class={"h-600px scrollbar"}>
+            <editor.components.Preview class="pointer-events-none" />
+          </div>
+        </div>,
+        {
+          title: title,
+          destroyOnClose: true,
+        }
+      );
+    };
+
+    return () => {
+      return (
+        <div>
+          <List
+            gap="24px"
+            class={"p-24px h-full scrollbar"}
+            columns={6}
+            control={ListCtrl}
+            item={(item: any) => (
+              <ListItem
+                item={item}
+                record={props.record}
+                onPreview={(id, title) => {
+                  previewInModal(id, title);
+                }}
+                onEdit={async (record) => {
+                  await resource.actions.updateCommitData(record);
+                  ListCtrl.fresh();
+                }}
+              />
+            )}
+          />
+        </div>
+      );
+    };
+  },
+});
+const ListItem = defineUI({
+  props: {
+    item: any(),
+    record: any(),
+  },
+  emits: ["edit", "preview"],
+  setup(props, { emit }) {
+    return () => {
+      const { item, record } = props;
+      const h5 = item.h5[0] || {};
+      const wks = item.wks || {};
+      const options = record?.flags?.map((e: string) => {
+        return { label: e, value: e };
+      });
+      return (
+        <div class={cx(itemStyles, "relative")}>
+          <View ratio={1} class="overflow-hidden relative">
+            <Image
+              class="h-1/1 w-1/1 !object-contain bg-[#ebebeb]"
+              src={h5?.thumbnail}
+            />
+            <div class="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity">
+              <div
+                class="text-white icon_action w-60px leading-60px orange cursor-pointer rounded-1/2 text-center transition-opacity hover:opacity-90 active:opacity-80"
+                onClick={() => emit("preview", wks.id, h5?.title)}
+              >
+                查看
+              </div>
+              {record.flags && record.flags.length > 0 && (
+                <div class={"select_box"}>
+                  <Select
+                    value={wks.flag}
+                    options={options}
+                    onChange={(v) => {
+                      wks.flag = v;
+                      emit("edit", {
+                        id: record._id,
+                        wkId: wks.id,
+                        flag: wks.flag,
+                      });
+                    }}
+                  ></Select>
+                </div>
+              )}
+            </div>
+          </View>
+          <div class="item_footer rounded-b-4px flex items-center justify-between p-15px">
+            <div class="flex-1 w-0">
+              <div class="text-white text-bold truncate">{h5?.title}</div>
+              <div class="flex items-center text-opacity-60 text-white text-12px mt-5px">
+                {dayjs(wks.commitTime).format("YYYY.MM.DD")} 提交
+              </div>
+            </div>
+          </div>
+        </div>
+      );
+    };
+  },
+});
+const itemStyles = css`
+  .item_footer {
+    background: #414141;
+  }
+  .icon_action {
+    background-color: rgba(0, 0, 0, 0.8);
+    &.orange {
+      background-color: rgba(232, 139, 0, 0.8);
+    }
+  }
+  .select_box {
+    position: absolute;
+    left: 10px;
+    top: 10px;
+    .ant-select {
+      font-size: 12px;
+      .ant-select-selector {
+        height: 24px;
+        background-color: @inf-component-bg;
+        .ant-select-selection-item {
+          line-height: 22px;
+        }
+      }
+    }
+  }
+`;

+ 2 - 0
src/modules/resource/components/index.ts

@@ -2,10 +2,12 @@ import MaterialItem from "./MaterialItem";
 import PromotionItem from "./PromotionItem";
 import ResourceManager from "./ResourceManager";
 import CollectionEditModal from "./CollectionEditModal";
+import CollectionListModal from "./CollectionListModal";
 
 export const compoents = {
   MaterialItem,
   PromotionItem,
   ResourceManager,
   CollectionEditModal,
+  CollectionListModal,
 };

+ 6 - 0
src/modules/resource/http.ts

@@ -66,6 +66,12 @@ export const http = ResourceModule.http({
   commitCollection(data: any) {
     return this.request("/works/commit", { method: "POST", data });
   },
+  commitHistoryDetail(id: any) {
+    return this.request(`/wk/h5/detail/${id}`, { method: "GET" });
+  },
+  updateCommitData(data: any) {
+    return this.request("/wk/update/flag", { method: "POST", data });
+  },
 });
 
 /**

+ 33 - 2
src/pages/website/MyCollection/components/CollectionItem.tsx

@@ -1,4 +1,5 @@
 import { css, cx } from "@linaria/core";
+import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
 import { IconMore } from "@queenjs/icons";
 import { Image, View } from "@queenjs/ui";
 import { Dropdown, Menu } from "ant-design-vue";
@@ -14,17 +15,32 @@ export default defineUI({
   setup(props, { emit }) {
     return () => {
       const { record } = props;
+      const options = record?.statues?.map((e: string) => {
+        return { label: e, value: e };
+      });
       return (
         <div class={cx(itemStyles, "relative")}>
           <View ratio={1.4} class=" relative">
             <Image class="h-1/1 w-1/1  bg-[#ebebeb]" src={record?.cover} />
-            <div class="absolute inset-0 flex items-center justify-center opacity-0 hover:opacity-100 transition-opacity">
+            <div class="absolute inset-0 flex items-center justify-center  transition-opacity">
               <div
                 class="text-white icon_action w-60px leading-60px  cursor-pointer rounded-1/2 text-center transition-opacity hover:opacity-90 active:opacity-80"
-                onClick={() => emit("preview", props.record)}
+                onClick={() => emit("preview", record)}
               >
                 查看
               </div>
+              {record.statues && record.statues.length > 0 && (
+                <div class={"select_box"}>
+                  <Select
+                    value={record.status}
+                    options={options}
+                    onChange={(v) => {
+                      record.status = v;
+                      emit("edit", record);
+                    }}
+                  ></Select>
+                </div>
+              )}
             </div>
           </View>
           <div class="item_footer rounded-b-4px flex items-center justify-between p-15px">
@@ -63,4 +79,19 @@ const itemStyles = css`
   .icon_action {
     background-color: rgba(0, 0, 0, 0.8);
   }
+  .select_box {
+    position: absolute;
+    left: 10px;
+    top: 10px;
+    .ant-select {
+      font-size: 12px;
+      .ant-select-selector {
+        height: 24px;
+        background-color: @inf-component-bg;
+        .ant-select-selection-item {
+          line-height: 22px;
+        }
+      }
+    }
+  }
 `;

+ 3 - 0
src/pages/website/MyCollection/components/index.tsx

@@ -38,6 +38,9 @@ export default defineUI({
                 onMenu={(name) => {
                   props.Controller.onMenuClick(name, record);
                 }}
+                onEdit={(record) => {
+                  props.Controller.onEdit(record);
+                }}
                 onPreview={(record) => props.Controller.onPreview(record)}
               />
             )}

+ 10 - 1
src/pages/website/MyCollection/controller.tsx

@@ -10,9 +10,10 @@ export function createCollectionController(resource: ResourceModule) {
 
   ctrl.createCollection = async () => {
     await resource.actions.createOrUpdateCollection(null);
+    ctrl.ListCtrl.fresh();
   };
   ctrl.onPreview = (record: any) => {
-    console.log(record);
+    resource.actions.showCollectionList(record);
   };
   ctrl.onMenuClick = async (name: string, record: any) => {
     if (name == "delete") {
@@ -24,7 +25,15 @@ export function createCollectionController(resource: ResourceModule) {
       }
       const detail = await resource.actions.collectionDTL(record._id);
       await resource.actions.createOrUpdateCollection(detail);
+      ctrl.ListCtrl.fresh();
+    }
+  };
+  ctrl.onEdit = async (record: any) => {
+    if (!record._id) {
+      return;
     }
+    await resource.https.updateCollection(record);
+    ctrl.ListCtrl.fresh();
   };
   return ctrl;
 }

+ 129 - 8
src/pages/website/Promotion2/components/CollectionModal.tsx

@@ -9,6 +9,7 @@ import { useResource } from "@/modules/resource";
 
 import dayjs from "dayjs";
 import { queenApi, useModal } from "queenjs";
+import { useEditor } from "@/modules/editor";
 export default defineComponent({
   props: {
     record: any().isRequired,
@@ -19,6 +20,7 @@ export default defineComponent({
       currCollection: {} as any,
       searchVal: "",
     });
+    const editor = useEditor();
     const modal = useModal();
     const EmptyHistory = () => {
       return (
@@ -61,13 +63,95 @@ export default defineComponent({
         </div>
       );
     };
+    const workPreview = async (currId: string) => {
+      await editor.actions.initDesign(currId, false);
+      previewInModal("当前提交");
+    };
+    const historyPreview = async (hisId: string) => {
+      const ret = await resource.actions.getCommitHistoryDetail(hisId);
+      if (!ret) {
+        return;
+      }
+      editor.store.setDesignData(ret);
+      previewInModal("历史提交");
+    };
+    const collectionPreview = async (collection: any) => {
+      if (collection.introLink) {
+        window.open(collection.introLink);
+        return;
+      }
+      if (collection.introH5Id) {
+        await editor.actions.initDesign(collection.introH5Id, false);
+        previewInModal("详情介绍");
+      }
+    };
+    const previewInModal = (title: string) => {
+      editor.actions.switchMode("preview");
+      resource.showModal(
+        <div class={"!p-0"}>
+          <div class={"h-600px scrollbar"}>
+            <editor.components.Preview class="pointer-events-none" />
+          </div>
+        </div>,
+        {
+          title: title,
+          destroyOnClose: true,
+        }
+      );
+    };
     const itemRender = (data: any) => {
       return (
-        <div class={"flex"}>
-          <Image class="w-160px h-160px rounded-6px" src={data?.thumbnail} />
-          <div class={"flex-1 pl-20px"}>
+        <div class={"flex h-full overflow-hidden"}>
+          <div class={[itemPreview, "relative"]}>
+            <Image class="w-160px h-160px rounded-6px" src={data?.thumbnail} />
+            <div
+              class={"icon_preview absolute top-8px right-8px"}
+              onClick={() => workPreview(data._id)}
+            >
+              <img
+                class={"w-20px h-20px"}
+                src={require("@/assets/imgs/icon_preview.png")}
+              />
+            </div>
+          </div>
+
+          <div class={"flex-1 pl-20px  flex flex-col"}>
             <div class={"text-18px"}>{data.title}</div>
-            <div class={"mt-14px text-gray"}>{data.desc}</div>
+            <div class={"my-12px text-gray break-all flex-1 overflow-hidden"}>
+              {data.desc}
+            </div>
+          </div>
+        </div>
+      );
+    };
+    const itemHistory = () => {
+      if (!state.currCollection.h5) {
+        return null;
+      }
+      const h5 = state.currCollection.h5[0];
+      const wks = state.currCollection.wks;
+      return (
+        <div class={"flex h-full overflow-hidden"}>
+          <div class={[itemPreview, "relative"]}>
+            <Image class="w-160px h-160px rounded-6px" src={h5.thumbnail} />
+            <div
+              class={"icon_preview absolute top-8px right-8px"}
+              onClick={() => historyPreview(wks.id)}
+            >
+              <img
+                class={"w-20px h-20px"}
+                src={require("@/assets/imgs/icon_preview.png")}
+              />
+            </div>
+          </div>
+          <div class={"flex-1 pl-20px flex flex-col"}>
+            <div class={"text-18px"}>{h5.title}</div>
+            <div class={"my-12px text-gray break-all flex-1 overflow-hidden"}>
+              {h5.desc}
+            </div>
+            <div class={"text-12px text-gray"}>
+              提交日期:{dayjs(wks.endTime).format("YYYY-MM-DD")}
+            </div>
           </div>
         </div>
       );
@@ -76,8 +160,22 @@ export default defineComponent({
       const data = state.currCollection;
       return (
         <div>
-          <div class={"w-full h-290px rounded-6px"}>
+          <div class={"text-18px mb-20px"}>{data.title}</div>
+          <div class={[itemPreview, "w-full h-290px rounded-6px relative"]}>
             <Image class={"w-full h-full rounded-6px"} src={data.cover} />
+            {(data.introLink || data.introH5Id) && (
+              <div
+                class={"icon_preview absolute top-10px right-10px"}
+                onClick={() => {
+                  collectionPreview(data);
+                }}
+              >
+                <img
+                  class={"w-30px h-30px"}
+                  src={require("@/assets/imgs/icon_preview.png")}
+                />
+              </div>
+            )}
           </div>
           <div class={"flex justify-between items-center mt-15px"}>
             <div>
@@ -107,16 +205,26 @@ export default defineComponent({
       );
     };
     const search = async () => {
+      if (!state.searchVal) {
+        return false;
+      }
       const collection = await resource.actions.searchCollection(
-        state.searchVal
+        state.searchVal,
+        props.record._id
       );
+      if (!collection) {
+        return;
+      }
       state.currCollection = collection[0];
     };
     const commit = async () => {
       const res = await resource.actions.commitCollection({
         id: state.currCollection._id,
-        ...props.record,
+        h5Id: props.record._id,
       });
+      if (!res) {
+        return;
+      }
       modal.submit();
       queenApi.messageSuccess("发送成功");
     };
@@ -161,7 +269,9 @@ export default defineComponent({
               </div>
               <div class={"flex-1 bg-white px-30px py-18px rounded-6px"}>
                 <div class={"text-16px"}>历史发送</div>
-                <div class={"mt-20px h-160px"}>{EmptyHistory()}</div>
+                <div class={"mt-20px h-160px"}>
+                  {state.currCollection.h5 ? itemHistory() : EmptyHistory()}
+                </div>
               </div>
             </div>
           </div>
@@ -182,6 +292,17 @@ export default defineComponent({
     };
   },
 });
+const itemPreview = css`
+  &:hover {
+    .icon_preview {
+      opacity: 1;
+    }
+  }
+  .icon_preview {
+    opacity: 0;
+    cursor: pointer;
+  }
+`;
 const ModalStyle = css`
   color: #111;
   .ant-input {