Jelajahi Sumber

公众号比例

xia 4 tahun lalu
induk
melakukan
fb0fc53282

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "clipboard": "^2.0.6",
     "core-js": "^3.6.5",
     "qrcode": "^1.4.4",
+    "smooth-dnd": "^0.12.1",
     "vue": "^3.0.0",
     "vue-router": "^4.0.0-0",
     "vuex": "^4.0.0-0"

+ 14 - 1
src/api/index.ts

@@ -380,4 +380,17 @@ export const setGroupDay = (data: {
   budget?:number | string;
 }) => {
   return axios.post("/ad/updateAdvertiserBudget", data);
-};
+};
+
+//获取自定义所有列
+export const getCoustomClomuns = (): AxiosPromise<any> =>{
+  return axios("/ad/getFields");
+}
+
+//设置站点回传比例
+export const setChannelRate = (data: {
+  rate: string | number;
+  channel_id: string;
+}) => {
+  return axios.post("/setChannelConfig", data);
+}; 

+ 57 - 0
src/components/drag-wrapper/index.vue

@@ -0,0 +1,57 @@
+<!--
+ * @Author: your name
+ * @Date: 2021-01-21 15:28:08
+ * @LastEditTime: 2021-01-21 15:28:09
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \precise_delivery_distribution_front\src\components\drag-wrapper\index.vue
+-->
+<template>
+  <Container @drop="onDrop">
+    <Draggable v-for="(item, i) in source"
+               :key="i">
+      <slot :data="item" />
+    </Draggable>
+  </Container>
+</template>
+
+<script lang="ts">
+import { defineComponent, PropType, ref } from "vue";
+
+import { Container, Draggable, DropResult } from "@/plugins/smooth-dnd";
+
+const DragWrapper = defineComponent({
+  components: {
+    Container,
+    Draggable,
+  },
+  props: {
+    source: {
+      type: Object as PropType<any[]>,
+      default: {},
+    },
+  },
+  setup(props) {},
+  methods: {
+    onDrop(dropResult: DropResult) {
+      const result = this.doDropDataAction(this.source, dropResult);
+      this.$emit("after-drag", result);
+    },
+    doDropDataAction(list: any[], dropResult: DropResult) {
+      const { removedIndex, addedIndex, payload } = dropResult;
+      if (removedIndex === null && addedIndex === null) return list;
+
+      const result = [...list];
+      let itemToAdd = payload;
+
+      if (removedIndex !== null) itemToAdd = result.splice(removedIndex, 1)[0];
+
+      if (addedIndex !== null) result.splice(addedIndex, 0, itemToAdd);
+
+      return result;
+    },
+  },
+});
+
+export default DragWrapper;
+</script>

+ 10 - 0
src/components/edit-cell/index.vue

@@ -49,6 +49,10 @@ const EditableCell = defineComponent({
       type: Number,
       default: 0,
     },
+    maxValue:{
+      type: Number,
+      default: 0,
+    },
     customValue:String,
     muliteType: {
       type: Boolean,
@@ -88,6 +92,12 @@ const EditableCell = defineComponent({
           return;
         } 
       }
+      if (this.maxValue && this.value != this.customValue) {
+        if (this.maxValue < Number(this.value)){
+          this.$message.error(`最大值必须是${this.maxValue}`);
+          return;
+        } 
+      }
       Modal.confirm({
         title: `修改${this.titles}`,
         icon: createVNode(ExclamationCircleOutlined),

+ 147 - 0
src/plugins/smooth-dnd/container.ts

@@ -0,0 +1,147 @@
+/*
+ * @Author: your name
+ * @Date: 2021-01-21 15:19:45
+ * @LastEditTime: 2021-01-21 15:23:49
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \precise_delivery_distribution_front\src\plugins\container.ts
+ */
+import {
+    defineComponent,
+    onMounted,
+    onUpdated,
+    SetupContext,
+    ref,
+    onUnmounted,
+    watch,
+    h,
+  } from "vue";
+  import { smoothDnD, dropHandlers, SmoothDnD } from "smooth-dnd";
+  import { getTagProps, validateTagProp } from "./utils";
+  
+  smoothDnD.dropHandler = dropHandlers.reactDropHandler().handler;
+  smoothDnD.wrapChild = false;
+  
+  const emitEventMap = {
+    "drag-start": "onDragStart",
+    "drag-end": "onDragEnd",
+    drop: "onDrop",
+    "drag-enter": "onDragEnter",
+    "drag-leave": "onDragLeave",
+    "drop-ready": "onDropReady",
+  };
+  
+  const getContainerOptions = (
+    props: Record<string, any>,
+    context: SetupContext
+  ) => {
+    const options = Object.keys(props).reduce(
+      (result: Record<string, any>, key: string) => {
+        const optName = key;
+        const prop = props[optName];
+        if (prop !== undefined) {
+          if (typeof prop === "function") {
+            if ((<Record<string, string>>emitEventMap)[optName]) {
+              result[(<Record<string, string>>emitEventMap)[optName]] = (
+                params: any
+              ) => {
+                context.emit(optName, params);
+              };
+            } else {
+              result[optName] = (...params: any[]) => {
+                return prop(...params);
+              };
+            }
+          } else result[optName] = prop;
+        }
+        return result;
+      },
+      {}
+    );
+  
+    return options;
+  };
+  
+  const mapOptions = (appProps: Record<string, any>, context: SetupContext) => {
+    const props = Object.assign({}, appProps, context.attrs);
+    return getContainerOptions(props, context);
+  };
+  
+  const Container = defineComponent({
+    props: {
+      behaviour: String,
+      groupName: String,
+      orientation: String,
+      dragHandleSelector: String,
+      nonDragAreaSelector: String,
+      dragBeginDelay: Number,
+      animationDuration: Number,
+      autoScrollEnabled: { type: Boolean, default: true },
+      lockAxis: String,
+      dragClass: String,
+      dropClass: String,
+      removeOnDropOut: { type: Boolean, default: false },
+      "drag-start": Function,
+      "drag-end": Function,
+      drop: Function,
+      getChildPayload: Function,
+      shouldAnimateDrop: Function,
+      shouldAcceptDrop: Function,
+      "drag-enter": Function,
+      "drag-leave": Function,
+      tag: {
+        validator: validateTagProp,
+        default: "div",
+      },
+      getGhostParent: Function,
+      "drop-ready": Function,
+      dropPlaceholder: [Object, Boolean],
+    },
+    setup(props, context) {
+      const container = ref<HTMLElement | null>(null);
+  
+      const dndContainer = ref<SmoothDnD | null>(null);
+  
+      onMounted(() => {
+        dndContainer.value = smoothDnD(
+          container.value!,
+          mapOptions(props, context)
+        );
+      });
+  
+      watch(
+        () => container.value,
+        () => {
+          console.log("change dnd container");
+          if (dndContainer.value) dndContainer.value.dispose();
+          dndContainer.value = smoothDnD(
+            container.value!,
+            mapOptions(props, context)
+          );
+        }
+      );
+  
+      onUpdated(() => dndContainer.value?.setOptions(mapOptions(props, context)));
+  
+      onUnmounted(() => {
+        if (dndContainer.value) dndContainer.value.dispose();
+      });
+  
+      const tagProps = getTagProps(props);
+  
+      const renderContainer = () => {
+        return h(
+          tagProps.value,
+          Object.assign({}, { ref: container }, tagProps.props),
+          {
+            default: () =>
+              context.slots.default ? context.slots.default() : "default text",
+          }
+        );
+      };
+  
+      return () => h(renderContainer);
+    },
+  });
+  
+  export default Container;

+ 23 - 0
src/plugins/smooth-dnd/draggable.ts

@@ -0,0 +1,23 @@
+import { defineComponent, h } from "vue";
+import { constants } from "smooth-dnd";
+import { getTagProps, validateTagProp } from "./utils";
+
+const Draggable = defineComponent({
+  props: {
+    tag: {
+      validator: validateTagProp,
+      default: "div",
+    },
+  },
+  setup(props, ctx) {
+    const tagProps = getTagProps(props, constants.wrapperClass);
+
+    return () =>
+      h(tagProps.value, Object.assign({}, tagProps.props), {
+        default: () =>
+          ctx.slots.default ? ctx.slots.default() : "default wrap",
+      });
+  },
+});
+
+export default Draggable;

+ 14 - 0
src/plugins/smooth-dnd/index.ts

@@ -0,0 +1,14 @@
+/*
+ * @Author: your name
+ * @Date: 2021-01-21 15:18:53
+ * @LastEditTime: 2021-01-21 15:21:42
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \precise_delivery_distribution_front\src\plugins\smooth-dnd\index.ts
+ */
+import Container from "./container";
+import Draggable from "./draggable";
+
+export * from "smooth-dnd";
+
+export { Container, Draggable };

+ 61 - 0
src/plugins/smooth-dnd/utils.ts

@@ -0,0 +1,61 @@
+/*
+ * @Author: your name
+ * @Date: 2021-01-21 15:19:16
+ * @LastEditTime: 2021-01-21 15:22:35
+ * @LastEditors: Please set LastEditors
+ * @Description: In User Settings Edit
+ * @FilePath: \precise_delivery_distribution_front\src\plugins\smooth-dnd\util.ts
+ */
+const isArray = function(obj: any) {
+  return Object.prototype.toString.call(obj) === "[object Array]";
+};
+
+export const getTagProps = (
+  props: Record<string, any>,
+  tagClasses?: string
+) => {
+  const tag = props.tag;
+  if (tag) {
+    if (typeof tag === "string") {
+      const result: Record<string, any> = { value: tag };
+      if (tagClasses) {
+        result.props = { class: tagClasses };
+      }
+      return result;
+    } else if (typeof tag === "object") {
+      const result = { value: tag.value || "div", props: tag.props || {} };
+
+      if (tagClasses) {
+        if (result.props.class) {
+          if (isArray(result.props.class)) {
+            result.props.class.push(tagClasses);
+          } else {
+            result.props.class = [tagClasses, result.props.class];
+          }
+        } else {
+          result.props.class = tagClasses;
+        }
+      }
+
+      return result;
+    }
+  }
+  return { value: "div" };
+};
+
+export const validateTagProp = (tag: any) => {
+  if (tag) {
+    if (typeof tag === "string") return true;
+    if (typeof tag === "object") {
+      if (
+        typeof tag.value === "string" ||
+        typeof tag.value === "function" ||
+        typeof tag.value === "object"
+      ) {
+        return true;
+      }
+    }
+    return false;
+  }
+  return true;
+};

+ 12 - 6
src/views/_pageOptions/table-account.ts

@@ -5,7 +5,7 @@ export const TableColumnOfAccount = [
     ellipsis: true,
   },
   {
-    title: "公众号唯一标识",
+    title: "公众号appid",
     dataIndex: "app_id",
     ellipsis: true,
   },
@@ -25,16 +25,22 @@ export const TableColumnOfAccount = [
     ellipsis: true,
   },
   {
-    title: "开始时间",
+    title: "开始/结束时间",
     dataIndex: "start_time",
     ellipsis: true,
+    width:200,
+    slots: {
+      customRender: "time",
+    },
   },
   {
-    title: "结束时间",
-    dataIndex: "end_time",
-    ellipsis: true,
+    title: "站点回传比例",
+    dataIndex: "rate",
+    width:120,
+    slots: {
+      customRender: "rate",
+    },
   },
-
   {
     title: "操作",
     dataIndex: "operte",

+ 23 - 3
src/views/account/account.vue

@@ -28,6 +28,19 @@
       :data-source="list"
       @change="onLoadOfficials"
     >
+      <template #rate="{ text, record }">
+        <editable-cell
+          :text="`${text}`"
+          title="回传比例"
+          :maxValue="100"
+          :minValue="1"
+          @change="(val) => onCellChange(record, 'rate', val)"
+        />
+      </template>
+      <template #time="{ text, record }">
+        <p>起:{{ record.start_time }}</p>
+        <p>止:{{ record.end_time }}</p>
+      </template>
       <template #operte="{ text, record }">
         <p
           v-clipboard:copy="record.fans_add_monitor_link"
@@ -50,18 +63,19 @@ import {
   ref,
   toRefs,
 } from "vue";
-
+import EditableCell from "@/components/edit-cell/index.vue";
 import ToolBar from "@/components/tool-bar/index.vue";
 import useApp from "@/hooks/useApp";
 import usePagination from "@/hooks/usePagination";
 
 import { TableColumnOfAccount } from "@/views/_pageOptions/table-account";
-import { getOfficialAccounts } from "@/api";
-import { IOfficials } from "@/types/api";
+import { getOfficialAccounts,setChannelRate } from "@/api";
+import { IOfficials,  } from "@/types/api";
 
 const Account = defineComponent({
   components: {
     ToolBar,
+    EditableCell,
   },
   setup() {
     let { loading, meta, tablePageOptions } = usePagination();
@@ -110,6 +124,12 @@ const Account = defineComponent({
     copySuccess() {
       this.$message.success("复制成功");
     },
+    onCellChange(record: any, dataIndex: string, value: string) {
+      console.log(record)
+      setChannelRate({rate:value,channel_id:record.channel_id}).then(res=>{
+        this.$message.success("修改回传比例成功!");
+      })
+    },
   },
 });
 

+ 81 - 0
src/views/put/component/customClomu.vue

@@ -0,0 +1,81 @@
+<template>
+  <div class="customized-column-content">
+    <div class="column-area">
+      <div class="column-select-panel">
+        <div class="panel-title-line">
+          可添加的列
+        </div>
+      </div>
+      <div class="column-selected">
+        <div class="panel-title-line">
+          已选26列<span class="delete-all">清空全部</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+import {
+  defineComponent,
+  reactive,
+  toRefs,
+  ref,
+  watchEffect,
+  onMounted,
+} from "vue";
+import { getCoustomClomuns } from "@/api";
+interface itemLine {}
+const CustomCloumn = defineComponent({
+  props: {},
+  setup(props) {
+    const state = reactive({
+      ad: ref<any[]>([]),
+    });
+
+    const getData = () => {
+      getCoustomClomuns().then((res) => {
+        console.log(res);
+      });
+    };
+
+    onMounted(() => {
+      getData();
+    });
+
+    return {};
+  },
+  methods: {},
+});
+
+export default CustomCloumn;
+</script>
+<style lang="scss" scoped>
+.column-area {
+  height: 445px;
+  .panel-title-line {
+    background-color: #f9fafd;
+    border: #e4e9ed 1px solid;
+    box-sizing: border-box;
+    line-height: 22px;
+    padding: 8px 12px;
+  }
+  .column-selected {
+    width: 226px;
+    float: left;
+    height: 445px;
+    padding-bottom: 9px;
+    .delete-all {
+      cursor: pointer;
+      font-size: 14px;
+      color: #338aff;
+      float: right;
+    }
+  }
+  .column-select-panel {
+    width: 430px;
+    float: left;
+    margin-right: 16px;
+    height: 445px;
+  }
+}
+</style>

+ 13 - 2
src/views/put/put-ad-plan.vue

@@ -1,6 +1,5 @@
 <template>
-  <div class="page-wrap page-wrap-account">
-    <a-button @click="getTest"> 测试啊</a-button>
+  <div class="page-wrap page-wrap-account page-adplan">
     <tool-bar
       :text="['ad_id', 'advertiser_id', 'campaign_id']"
       :label="['计划名/ID', '账号名/ID', '广告组名称/ID']"
@@ -45,6 +44,9 @@
       <a-button type="primary" @click="openBackDrawer">
         回本数据
       </a-button>
+      <a-button type="primary" @click="openCustomLine">
+        自定义列
+      </a-button>
     </div>
 
     <a-table
@@ -249,6 +251,9 @@
         :back_platform="register.back_platform"
       ></register-datad>
     </a-drawer>
+    <!-- <a-modal v-model:visible="columnShow" title="自定义列" @ok="makeDine" :width="722">
+      <custom-cloumn></custom-cloumn>
+    </a-modal> -->
   </div>
 </template>
 
@@ -257,6 +262,7 @@ import { defineComponent, reactive, toRefs, ref, unref, onMounted } from "vue";
 import moment from "moment";
 import ToolBar from "@/components/tool-bar/index.vue";
 import PutData from "@/views/put/put-log.vue";
+import CustomCloumn from "@/views/put/component/customClomu.vue";
 import useApp from "@/hooks/useApp";
 import PutCount from "@/views/put/put-ad-count.vue";
 import RegisterDatad from "@/views/put/register-data.vue";
@@ -291,6 +297,7 @@ const PutAdPlan = defineComponent({
     PutCount,
     InfoCircleOutlined,
     RegisterDatad,
+    CustomCloumn
   },
 
   setup() {
@@ -317,6 +324,7 @@ const PutAdPlan = defineComponent({
       showPop: false,
       visible1: false,
       registerVisable: false,
+      columnShow:false,
       register: {
         ad_lid: 0,
         back_platform: "",
@@ -699,4 +707,7 @@ export default PutAdPlan;
     margin-right: 10px;
   }
 }
+
+
+
 </style>

+ 5 - 0
yarn.lock

@@ -8043,6 +8043,11 @@ smart-buffer@^4.1.0:
   resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba"
   integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==
 
+smooth-dnd@^0.12.1:
+  version "0.12.1"
+  resolved "https://registry.npm.taobao.org/smooth-dnd/download/smooth-dnd-0.12.1.tgz#cdb44c972355659e32770368b29b6a80e0ed96f1"
+  integrity sha1-zbRMlyNVZZ4ydwNosptqgODtlvE=
+
 snapdragon-node@^2.0.1:
   version "2.1.1"
   resolved "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"