Browse Source

无数提交

xia 4 years ago
parent
commit
39c3b9aec5

+ 65 - 7
src/api/index.ts

@@ -18,6 +18,9 @@ import {
   adPlanCount,
   PlanBack,
   RegisterData,
+  FinanceData,
+  AdGroupData,
+  AdgroupList,
 } from "@/types/api";
 
 /**
@@ -96,13 +99,13 @@ export const getOfficialAccounts = (query: {
  */
 export const getADPlanlist = (
   query: Partial<{
-    email: string;
-    account_name: string;
-    ad_name: string;
+    ad_id: string;
+    advertiser_id: string;
+    campaign_id: string;
     status: string;
     begin_date: any;
     end_date: any;
-    campaign_name: string;
+    cost_order:number;
     page: number;
   }> = { page: 1, status: "AD_STATUS_DELIVERY_OK" }
 ): AxiosPromise<IList<ADPlanItem>> => {
@@ -119,7 +122,7 @@ export const getDeliveryStatList = (
     official_name: string;
     book_name: string;
     page: number;
-    day_num:number;
+    day_num: number;
   }> = { page: 1 }
 ): AxiosPromise<any> => {
   return axios("/delivery/stat", { params: query });
@@ -288,8 +291,8 @@ export const getRegisterData = (
   query: Partial<{
     ad_lid: number;
     back_platform: string;
-    is_paid:number;
-    show_all:number;
+    is_paid: number;
+    show_all: number;
     page: number;
   }> = { page: 1 }
 ): AxiosPromise<IList<RegisterData>> => {
@@ -322,3 +325,58 @@ export const getDesignList = (query: {
 }>> => {
   return axios("/delivery/getDeliveryStatFields", { params: query });
 };
+
+//财务数据
+export const getFinanceList = (
+  query: Partial<{
+    start_ymd: string;
+    end_ymd: string;
+    page: number;
+  }> = { page: 1 }
+): AxiosPromise<IList<FinanceData>> => {
+  return axios("/ad/adFinanceStat", { params: query });
+};
+
+//广告组数据
+export const getAdgroupList = (
+  query: Partial<{
+    advertiser_id: string;
+    account_id: string;
+    campaign_id: string;
+    begin_date: string;
+    end_date: string;
+    page: number;
+  }> = { page: 1 }
+): AxiosPromise<IList<AdGroupData>> => {
+  return axios("/ad/adCampaigns", { params: query });
+};
+
+//修改广告组状态
+export const setGroupStatus = (data: {
+  campaign_id: string | number;
+  status: string | number;
+}) => {
+  return axios.post("/ad/updateCampaignStatus", data);
+};
+
+//广告组账户列表
+export const getAdgroupData = (
+  query: Partial<{
+    advertiser_id: string| number;
+    account_id: string| number;
+    page: number;
+    begin_date: string;
+    end_date: string;
+  }> = { page: 1 }
+): AxiosPromise<IList<AdgroupList>> => {
+  return axios("/ad/adAdvertisers", { params: query });
+};
+
+//更新账户日预算
+export const setGroupDay = (data: {
+  advertiser_id: string | number;
+  budget_mode: string;
+  budget?:number | string;
+}) => {
+  return axios.post("/ad/updateAdvertiserBudget", data);
+};

+ 43 - 2
src/components/edit-cell/index.vue

@@ -1,7 +1,20 @@
 <template>
   <div class="editable-cell">
     <div v-if="editable" class="editable-cell-input-wrapper">
-      <a-input v-model:value="value" @pressEnter="check" />
+      <a-input v-model:value="value" @pressEnter="check" v-if="!muliteType" />
+      <a-input-search
+        v-model:value="value"
+        placeholder="请输入值"
+        size="small"
+        v-else
+        @search="changeBtn"
+      >
+        <template #enterButton>
+          <a-button>
+            {{customTitle}}
+          </a-button>
+        </template>
+      </a-input-search>
       <check-outlined class="editable-cell-icon-check" @click="check" />
     </div>
     <div v-else class="editable-cell-text-wrapper">
@@ -28,9 +41,19 @@ import {
 } from "vue";
 const EditableCell = defineComponent({
   props: {
-    text: Number,
+    text: String,
+    customTitle:String,
     onChange: Function,
     title: String,
+    minValue: {
+      type: Number,
+      default: 0,
+    },
+    customValue:String,
+    muliteType: {
+      type: Boolean,
+      default: false,
+    },
   },
   components: {
     CheckOutlined,
@@ -50,8 +73,21 @@ const EditableCell = defineComponent({
       const value = e.target.value;
       this.value = value;
     },
+    changeBtn() {
+      this.value = this.customValue??'';
+    },
     check() {
       let _self = this;
+      if (this.value == undefined || this.value == null || this.value =='') {
+        this.$message.error("请输入值");
+        return;
+      }
+      if (this.minValue && this.value != this.customValue) {
+        if (this.minValue > Number(this.value)){
+          this.$message.error(`最小值必须是${this.minValue}`);
+          return;
+        } 
+      }
       Modal.confirm({
         title: `修改${this.titles}`,
         icon: createVNode(ExclamationCircleOutlined),
@@ -77,6 +113,11 @@ const EditableCell = defineComponent({
 export default EditableCell;
 </script>
 <style lang="scss">
+.editable-cell-input-wrapper {
+  .ant-input-group {
+    width: 140px;
+  }
+}
 .editable-cell {
   position: relative;
   .editable-cell-input-wrapper,

+ 29 - 13
src/layout/components/AppSubMenu.vue

@@ -1,20 +1,27 @@
 <template>
-  <a-sub-menu class="nav-item"
-              :key="menus.path"
-              :title="menus.meta.title">
+  <a-sub-menu class="nav-item" :key="menus.path">
+    <template #title>
+      <span
+        ><component :is="menus.icon" /><span>{{ menus.meta.title }}</span></span
+      >
+    </template>
     <template v-for="child in menus.children">
       <template v-if="child.children">
-        <app-sub-menu :menus="child"
-                      :parent-path="formatRoutes(child.path, parentPath)"
-                      :key="formatRoutes(child.path, parentPath)" />
+        <app-sub-menu
+          :menus="child"
+          :parent-path="formatRoutes(child.path, parentPath)"
+          :key="formatRoutes(child.path, parentPath)"
+        />
       </template>
       <template v-else>
-        <router-link :key="formatRoutes(child.path, parentPath)"
-                     :to="formatRoutes(child.path, parentPath)"
-                     custom
-                     v-slot={navigate}>
+        <router-link
+          :key="formatRoutes(child.path, parentPath)"
+          :to="formatRoutes(child.path, parentPath)"
+          custom
+          v-slot="{ navigate }"
+        >
           <a-menu-item>
-            <p @click.stop="navigate">{{child.meta.title}}</p>
+            <p @click.stop="navigate">{{ child.meta.title }}</p>
           </a-menu-item>
         </router-link>
       </template>
@@ -26,9 +33,18 @@
 import { defineComponent } from "vue";
 
 import { pathResolve } from "@/helper";
-
+import {
+  DesktopOutlined,
+  PayCircleOutlined,
+  ProjectOutlined,
+} from "@ant-design/icons-vue";
 const AppSubMenu = defineComponent({
   name: "AppSubMenu",
+  components: {
+    DesktopOutlined,
+    PayCircleOutlined,
+    ProjectOutlined,
+  },
   props: {
     menus: {
       type: Object,
@@ -47,4 +63,4 @@ const AppSubMenu = defineComponent({
 });
 
 export default AppSubMenu;
-</script>
+</script>

+ 45 - 21
src/layout/index.vue

@@ -2,29 +2,42 @@
   <a-layout class="web-wrapper">
     <app-header />
     <a-layout>
-      <a-layout-sider v-if="roles.length"
-                      class="web-side"
-                      theme="light"
-                      :width="240">
-        <a-menu class="web-menu"
-                mode="inline"
-                theme="dark"
-                v-model:openKeys="openKeys"
-                :selected-keys="menuActive">
+      <a-layout-sider
+        v-if="roles.length"
+        class="web-side"
+        theme="light"
+        :width="200"
+        v-model:collapsed="collapsed"
+      >
+        <a-menu
+          class="web-menu"
+          mode="inline"
+          theme="dark"
+          :inline-collapsed="collapsed"
+          v-model:openKeys="openKeys"
+          :selected-keys="menuActive"
+        >
           <template v-for="route in filterRoutes">
             <template v-if="route.children && route.children.length">
-              <app-sub-menu class="nav-item"
-                            :menus="route"
-                            :parent-path="route.path"
-                            :key="route.path" />
+              <app-sub-menu
+                class="nav-item"
+                :menus="route"
+                :parent-path="route.path"
+                :key="route.path"
+              />
             </template>
             <template v-else>
-              <router-link :key="route.path"
-                           :to="route.path"
-                           custom
-                           v-slot="{navigate}">
+              <router-link
+                :key="route.path"
+                :to="route.path"
+                custom
+                v-slot="{ navigate }"
+              >
                 <a-menu-item>
-                  <p @click.stop="navigate">{{route.meta.title}}</p>
+                  <span @click.stop="navigate"
+                    ><component :is="route.icon" />
+                    <span>{{ route.meta.title }}</span></span
+                  >
                 </a-menu-item>
               </router-link>
             </template>
@@ -33,8 +46,7 @@
       </a-layout-sider>
       <a-layout-content class="web-container">
         <router-view v-slot="{ Component }">
-          <transition name="fade-transform"
-                      mode="out-in">
+          <transition name="fade-transform" mode="out-in">
             <component :is="Component" />
           </transition>
         </router-view>
@@ -54,11 +66,19 @@ import { pathResolve } from "@/helper/index";
 import { formatNavRoutes } from "@/helper/permission";
 
 import { RouteConfig } from "@/types/route";
+import {
+  DesktopOutlined,
+  PayCircleOutlined,
+  ProjectOutlined,
+} from "@ant-design/icons-vue";
 
 const LayoutComponent = defineComponent({
   components: {
     appHeader,
     appSubMenu,
+    PayCircleOutlined,
+    ProjectOutlined,
+    DesktopOutlined,
   },
   setup() {
     const { store, route, router } = useApp();
@@ -66,6 +86,7 @@ const LayoutComponent = defineComponent({
     const data = reactive({
       navRoutes: computed(() => store.getters.permissionRoutes),
       roles: computed(() => store.getters.userRoles),
+      collapsed: true,
       menuActive: computed(() => {
         const {
           meta: { activeMenu },
@@ -100,12 +121,15 @@ const LayoutComponent = defineComponent({
       return openKeys;
     };
     const openKeys = ref(onCalcOpenKeys());
-
+    const toggleCollapsed = () => {
+      data.collapsed = !data.collapsed;
+    };
     return {
       ...toRefs(data),
       openKeys,
       filterRoutes,
       formatRoutes,
+      toggleCollapsed,
     };
   },
 });

+ 3 - 1
src/plugins/vue-clipboard.ts

@@ -1,7 +1,7 @@
 import Clipboard from "clipboard";
 import { App, DirectiveBinding, VNode } from "vue";
 import { clipboardKey } from "./injectionKey";
-
+import { message } from 'ant-design-vue';
 // clipboard config
 const VueClipboardConfig = {
   autoSetContainer: false,
@@ -28,6 +28,7 @@ const $copyText = (
     });
 
     clipboard.on(status.success, (e: ClipboardJS.Event) => {
+     
       clipboard.destroy();
       resolve(e);
     });
@@ -59,6 +60,7 @@ const bind = (
     });
 
     clipboard.on(status.success, (e) => {
+      message.success('操作成功');
       const cb = el._vClipboard_success;
       cb && cb(e);
     });

+ 55 - 11
src/router/async.ts

@@ -3,6 +3,7 @@ import { RouteConfig } from "@/types/route";
 export const AccountManager: RouteConfig = {
   name: "AccountManager",
   path: "/account",
+  icon:'ProjectOutlined',
   meta: {
     title: "公众号管理",
   },
@@ -27,14 +28,6 @@ const PutAdAccount: RouteConfig = {
   component: () => import("@/views/put/put-ad-account.vue"),
 };
 
-const PutAdPlan: RouteConfig = {
-  name: "PutAdPlan",
-  path: "ad-plan",
-  meta: {
-    title: "广告计划",
-  },
-  component: () => import("@/views/put/put-ad-plan.vue"),
-};
 
 const PutData: RouteConfig = {
   name: "PutData",
@@ -45,7 +38,6 @@ const PutData: RouteConfig = {
   component: () => import("@/views/put/put-data.vue"),
 };
 
-
 const PutLog: RouteConfig = {
   name: "PutLog",
   path: "log",
@@ -66,16 +58,68 @@ const PutDataMore: RouteConfig = {
   component: () => import("@/views/put/put-data-more.vue"),
 };
 
+ const PutAdGroup: RouteConfig = {
+  name: "PutAdGroup",
+  path: "/put/datas/group",
+  meta: {
+    title: "广告组数据",
+  },
+  component: () => import("@/views/put/ad-group.vue"),
+};
+
+const PutAdAcountL: RouteConfig = {
+  name: "PutAdAcountL",
+  path: "/put/datas/count",
+  meta: {
+    title: "广告账号数据",
+  },
+  component: () => import("@/views/put/ad-countdata.vue"),
+};
+
+ const PutAdPlan: RouteConfig = {
+  name: "PutAdPlan",
+  path: "/put/datas/ad-plan",
+  meta: {
+    title: "广告计划数据",
+  },
+  component: () => import("@/views/put/put-ad-plan.vue"),
+};
+
+
+export const PutDataTab: RouteConfig = {
+  name: "PutDataTab",
+  path: "/put/datas",
+  meta: {
+    title: "广告数据",
+  },
+  children: [PutAdAcountL,PutAdGroup,PutAdPlan],
+  component: () => import("@/views/put/ad_datas.vue"),
+};
+
 export const PutManager: RouteConfig = {
   name: "PutManager",
   path: "/put",
+  icon:'DesktopOutlined',
   meta: {
     title: "投放管理",
   },
-  children: [PutBook, PutAdAccount, PutAdPlan, PutData, PutDataMore],
+  children: [PutBook, PutAdAccount, PutDataTab, PutData, PutDataMore],
   component: () => import("@/views/put/index.vue"),
 };
 
-const asyncRoutes: RouteConfig[] = [AccountManager, PutManager];
+
+
+
+export const Financial: RouteConfig = {
+  name: "Financial",
+  path: "/financial",
+  icon:'PayCircleOutlined',
+  meta: {
+    title: "财务管理",
+  },
+  component: () => import("@/views/financial/index.vue"),
+};
+
+const asyncRoutes: RouteConfig[] = [AccountManager, PutManager, Financial];
 
 export default asyncRoutes;

+ 1 - 0
src/router/modules/constant.ts

@@ -10,6 +10,7 @@ export const Login: RouteConfig = {
   component: () => import("@/views/Login.vue"),
 };
 
+
 export const NotFound: RouteConfig = {
   name: "NotFound",
   path: "/:pathMatch(.*)*",

+ 1 - 1
src/router/modules/index.ts

@@ -2,7 +2,7 @@ import { RouteRecordRaw } from "vue-router";
 
 // 获取所有路由模块
 const routes = require.context(".", false, /\.ts$/);
-
+console.log(routes)
 let configRoutes: RouteRecordRaw[] = [];
 
 // 合并所有模块

+ 58 - 0
src/types/api.d.ts

@@ -313,4 +313,62 @@ export interface RegisterData {
   report_register_num: number;
   report_recharge_num: number;
   report_sactive_num: number;
+}
+
+export interface FinanceData {
+  date: string;
+  advertiser_id: string;
+  balance: number;
+  cash_cost: number;
+  cost: number;
+  frozen: number;
+  income: string;
+  reward_cost: number;
+  return_goods_cost: number;
+  transfer_in: number;
+  transfer_out: number;
+  advertiser_name: string;
+  company_name: string;
+}
+
+export interface AdGroupData {
+  id: string;
+  uid: string;
+  advertiser_id: string;
+  campaign_id: string | number;
+  campaign_name: string;
+  landing_type: number | string;
+  budget : number | string;
+  status : number | string;
+  budget_mode : number | string;
+  delivery_related_num: number;
+  delivery_mode: number;
+  is_enable  : number | string | boolean;
+  cost: string;
+  show: string;
+  ctr:  string;
+  click: string;
+  avg_click_cost: string;
+  avg_show_cost: string;
+  convert: number;
+  convert_cost: number;
+  convert_rate: number;
+}
+
+export interface AdgroupList {
+  id: string;
+  advertiser_id: string;
+  advertiser_name:string;
+  budget : number | string;
+  budget_mode : number | string;
+  budget_mode_name: string;
+  cost: string;
+  show: string;
+  ctr:  string;
+  click: string;
+  avg_click_cost: string;
+  avg_show_cost: string;
+  convert: number;
+  convert_cost: number;
+  convert_rate: number;
 }

+ 1 - 0
src/types/route.d.ts

@@ -11,4 +11,5 @@ export type RouteConfig = RouteRecordRaw & {
   hidden?: boolean;
   children?: RouteConfig[];
   meta?: Partial<RouteMeta>;
+  icon?: string;
 };

+ 8 - 0
src/views/_pageOptions/table-account.ts

@@ -27,4 +27,12 @@ export const TableColumnOfAccount = [
     title: "结束时间",
     dataIndex: "end_time",
   },
+
+  {
+    title: "操作",
+    dataIndex: "operte",
+    slots: {
+      customRender: "operte",
+    },
+  },
 ];

+ 116 - 9
src/views/_pageOptions/table-put.ts

@@ -410,15 +410,6 @@ export const TableColumnOfPutAdPlan = [
   },
   {
     fixed: "left",
-    title: "邮箱",
-    dataIndex: "email",
-    slots: {
-      customRender: "email",
-    },
-    width: 180,
-  },
-  {
-    fixed: "left",
     title: "广告名",
     dataIndex: "ad_name",
     slots: {
@@ -610,4 +601,120 @@ export const MatchList = [
     dataIndex: "report_sactive_num",
     width: 100,
   }, 
+]
+
+export const AdgroupCloumn = [
+  {
+    title: "",
+    dataIndex: "check",
+    width: 100,
+    slots: {
+      customRender: "switch",
+    },
+  },
+  {
+    title: "广告组名称",
+    dataIndex: "campaign_name",
+    width: 100,
+  },
+  {
+    title: "消耗",
+    dataIndex: "cost",
+    width: 100,
+  },
+  {
+    title: "转化成本",
+    dataIndex: "convert_cost",
+    width: 100,
+  },
+  {
+    title: "展示量",
+    dataIndex: "show",
+    width: 100,
+  },
+  {
+    title: "点击量",
+    dataIndex: "click",
+    width: 100,
+  },
+  {
+    title: "点击率",
+    dataIndex: "ctr",
+    width: 100,
+  },
+  {
+    title: "转化数",
+    dataIndex: "convert",
+    width: 100,
+  },
+  {
+    title: "转化率",
+    dataIndex: "convert_rate",
+    width: 100,
+  },
+  {
+    title: "平均千次展现费用",
+    dataIndex: "avg_show_cost",
+    width: 100,
+  },
+  {
+    title: "平均点击单价",
+    dataIndex: "avg_click_cost",
+    width: 100,
+  },
+]
+
+export const AdCoundCloumn = [
+  {
+    title: "账户信息",
+    dataIndex: "campaign_name",
+    width: 150,
+    slots: {
+      customRender: "info",
+    },
+  },
+  {
+    title: "消耗",
+    dataIndex: "cost",
+    width: 100,
+  },
+  {
+    title: "转化成本",
+    dataIndex: "convert_cost",
+    width: 100,
+  },
+  {
+    title: "展示量",
+    dataIndex: "show",
+    width: 100,
+  },
+  {
+    title: "点击量",
+    dataIndex: "click",
+    width: 100,
+  },
+  {
+    title: "点击率",
+    dataIndex: "ctr",
+    width: 100,
+  },
+  {
+    title: "转化数",
+    dataIndex: "convert",
+    width: 100,
+  },
+  {
+    title: "转化率",
+    dataIndex: "convert_rate",
+    width: 100,
+  },
+  {
+    title: "账户预算(最低1000)",
+    dataIndex: "firle",
+    width: 180,
+    slots: {
+      customRender: "budget",
+    },
+  },
+
 ]

+ 50 - 0
src/views/_pageOptions/table_financial.ts

@@ -0,0 +1,50 @@
+export const TableColumnOfFinancial = [
+  {
+    title: "日期",
+    dataIndex: "date",
+  },
+  {
+    title: "(广告主/管家)ID",
+    dataIndex: "advertiser_id",
+  },
+  {
+    title: "日终结余",
+    dataIndex: "balance",
+  },
+  {
+    title: "现金支出",
+    dataIndex: "cash_cost",
+  },
+  {
+    title: "总支出",
+    dataIndex: "cost",
+  },
+  {
+    title: "总存入",
+    dataIndex: "income",
+  },
+  {
+    title: "冻结",
+    dataIndex: "frozen",
+  },
+  {
+    title: "返货支出",
+    dataIndex: "return_goods_cost",
+  },
+  {
+    title: "总转入",
+    dataIndex: "transfer_in",
+  },
+  {
+    title: "总转出",
+    dataIndex: "transfer_out",
+  },
+  {
+    title: "账户信息",
+    dataIndex: "advertiser_name",
+  },
+  {
+    title: "代理商信息",
+    dataIndex: "company_name",
+  },
+];

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

@@ -19,7 +19,13 @@
              :pagination="tablePageOptions"
              :columns="columns"
              :data-source="list"
-             @change="onLoadOfficials" />
+             @change="onLoadOfficials" >
+         <template #operte="{ text, record }">
+           <p v-clipboard="record.fans_add_monitor_link"><a>复制监测链接</a></p>
+         </template>
+
+
+    </a-table>
   </div>
 </template>
 
@@ -35,7 +41,6 @@ import {
 } from "vue";
 
 import ToolBar from "@/components/tool-bar/index.vue";
-
 import useApp from "@/hooks/useApp";
 import usePagination from "@/hooks/usePagination";
 
@@ -50,7 +55,6 @@ const Account = defineComponent({
   setup() {
     let { loading, meta, tablePageOptions } = usePagination();
     const { store } = useApp();
-
     const state = reactive({
       platforms: computed(() => store.getters.platforms),
       list: ref<IOfficials[]>([]),

+ 106 - 0
src/views/financial/index.vue

@@ -0,0 +1,106 @@
+<template>
+  <div class="page-wrap page-finacial">
+    <tool-bar
+      :text="[]"
+      :label="[]"
+      v-model:loading="inSearching"
+      @confirm="onSearch"
+    >
+      <template #picker>
+        <p class="label">日期</p>
+        <a-range-picker
+          :ranges="rangePick"
+          format="YYYY/MM/DD"
+          v-model:value="pickered"
+        />
+      </template>
+    </tool-bar>
+    <a-table :columns="columns" :data-source="list" :scroll="{ x: 3000 }" @change="handleTableChange">
+    </a-table>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  reactive,
+  ref,
+  computed,
+  toRefs,
+  onMounted,
+} from "vue";
+
+import ToolBar from "@/components/tool-bar/index.vue";
+import usePagination from "@/hooks/usePagination";
+import { getFinanceList } from "@/api";
+import { picker } from "@/helper/config/range";
+import { PageOptions,FinanceData} from "@/types/api";
+import moment from "moment";
+import {
+  TableColumnOfFinancial
+} from "../_pageOptions/table_financial";
+
+const Finance = defineComponent({
+  components: {
+    ToolBar,
+  },
+  setup() {
+    let { loading, meta, tablePageOptions } = usePagination();
+
+    const state = reactive({
+      inSearching: false,
+      open: false,
+      inConfirm: false,
+      list:ref<FinanceData[]>([]),
+      rangePick: picker,
+      pickered: [moment().subtract(30, "d"), moment()],
+      columns: TableColumnOfFinancial,
+    });
+
+    const onSearch = (fields: Record<string, string>) => {
+      getData({current: 1 });
+    };
+
+    const getData = async (query?: { current: number}) => {
+      try {
+        loading.value = true;
+        let [begin_dates, end_dates] = state.pickered;
+        let start_ymd = moment(begin_dates).format("YYYY-MM-DD");
+        let end_ymd = moment(end_dates).format("YYYY-MM-DD");
+        const { data } = await getFinanceList({
+          start_ymd,
+          end_ymd,
+          page: query?.current ?? 1,
+        });
+        state.list = data.list as Array<FinanceData>;
+        meta.value = data.meta;
+      } catch (error) {
+        console.log("on get books list error");
+      } finally {
+        state.inSearching = false;
+      }
+    };
+
+
+    const handleTableChange = (pagination: PageOptions) => {
+      const { current, pageSize, total } = pagination;
+      getData({ current: current });
+    };
+
+    onMounted(getData);
+
+    return {
+      ...toRefs(state),
+      loading,
+      tablePageOptions,
+      onSearch,
+      handleTableChange
+    };
+  },
+  methods: {
+      moment,
+  },
+});
+
+export default Finance;
+</script>

+ 142 - 0
src/views/put/ad-countdata.vue

@@ -0,0 +1,142 @@
+<template>
+  <div class="page-wrap page-wrap-put-books">
+    <tool-bar
+      :text="['advertiser_id', 'account_id']"
+      :label="['广告主/ID', '账户/ID']"
+      v-model:loading="inSearching"
+      @confirm="onSearch"
+    >
+      <template #picker>
+        <p class="label">日期</p>
+        <a-range-picker
+          v-model:value="pickered"
+          :ranges="rangePick"
+          format="YYYY/MM/DD"
+        />
+      </template>
+    </tool-bar>
+    <a-table
+      :columns="columns"
+      :data-source="list"
+      :scroll="{ x: true }"
+      @change="handleTableChange"
+    >
+      <template #info="{ text, record }">
+        <p>广告主名:{{ record.advertiser_name }}</p>
+        <p>广告主ID:{{ record.advertiser_id }}</p>
+      </template>
+
+      <template #budget="{ text, record }">
+          
+        <editable-cell
+          :text="record.budget_mode=='BUDGET_MODE_INFINITE'?'不限':record.budget"
+          title="预算"
+          :minValue="1000"
+          :muliteType="true"
+          customTitle="不限"
+          customValue="不限"
+          @change="(val) => onCellChange(record, 'budget', val)"
+        />
+      </template>
+    </a-table>
+  </div>
+</template>
+<script lang="ts">
+import { defineComponent, reactive, toRefs, ref, onMounted } from "vue";
+import { picker } from "@/helper/config/range";
+import ToolBar from "@/components/tool-bar/index.vue";
+import moment from "moment";
+import { AdCoundCloumn } from "../_pageOptions/table-put";
+
+import { getAdgroupData, setGroupStatus,setGroupDay } from "@/api";
+import usePagination from "@/hooks/usePagination";
+import EditableCell from "@/components/edit-cell/index.vue";
+import { AdgroupList, PageOptions } from "@/types/api";
+
+const Adgroup = defineComponent({
+  components: {
+    ToolBar,
+    EditableCell,
+  },
+  setup() {
+    let { loading, meta, tablePageOptions } = usePagination();
+
+    const state = reactive({
+      inSearching: false,
+      open: false,
+      inConfirm: false,
+      list: ref<AdgroupList[]>([]),
+      rangePick: picker,
+      pickered: [],
+      columns: AdCoundCloumn,
+      fields: {},
+    });
+
+    const onSearch = (fields: Record<string, string>) => {
+      const { advertiser_id, account_id } = fields;
+      state.fields = fields;
+      getData({ current: 1, advertiser_id, account_id });
+    };
+
+    const getData = async (query?: {
+      current: number;
+      advertiser_id?: string;
+      account_id?: string;
+    }) => {
+      try {
+        loading.value = true;
+        let [begin_dates, end_dates] = state.pickered;
+        let begin_date, end_date;
+        if (begin_dates && end_dates) {
+          begin_date = moment(begin_dates).format("YYYY-MM-DD");
+          end_date = moment(end_dates).format("YYYY-MM-DD");
+        }
+
+        const { data } = await getAdgroupData({
+          begin_date,
+          end_date,
+          advertiser_id: query?.advertiser_id,
+          account_id: query?.account_id,
+          page: query?.current ?? 1,
+        });
+        state.list = data.list;
+        meta.value = data.meta;
+      } catch (error) {
+        console.log("on get books list error");
+      } finally {
+        state.inSearching = false;
+      }
+    };
+    const handleTableChange = (pagination: PageOptions) => {
+      const { current, pageSize, total } = pagination;
+      let data = Object.assign({ current, ...state.fields });
+      getData(data);
+    };
+
+    onMounted(getData);
+
+    return {
+      ...toRefs(state),
+      loading,
+      tablePageOptions,
+      onSearch,
+      handleTableChange,
+    };
+  },
+  methods: {
+    moment,
+    onCellChange(record: any, dataIndex: string, value: string){
+        let data = {
+            advertiser_id:record.advertiser_id,
+            budget_mode: value == '不限'?'BUDGET_MODE_INFINITE' :'BUDGET_MODE_DAY',
+            budget: value == '不限'?'0' :Number(value)  
+        }
+        setGroupDay(data).then(res=>{
+            this.$message.success("修改成功!");
+        })   
+    }
+  },
+});
+
+export default Adgroup;
+</script>

+ 134 - 0
src/views/put/ad-group.vue

@@ -0,0 +1,134 @@
+<template>
+  <div class="page-wrap page-wrap-put-books">
+    <tool-bar
+      :text="['advertiser_id', 'campaign_id']"
+      :label="['账户名称/ID', '广告组名称/ID']"
+      v-model:loading="inSearching"
+      @confirm="onSearch"
+    >
+      <template #picker>
+        <p class="label">日期</p>
+        <a-range-picker
+          v-model:value="pickered"
+          :ranges="rangePick"
+          format="YYYY/MM/DD"
+        />
+      </template>
+    </tool-bar>
+    <a-table
+      :columns="columns"
+      :data-source="list"
+      :scroll="{ x: true }"
+      @change="handleTableChange"
+    >
+      <template #switch="{ text, record }">
+        <a-switch
+          v-model:checked="record.is_enable"
+          @change="switchMethod(record)"
+        />
+      </template>
+    </a-table>
+  </div>
+</template>
+<script lang="ts">
+import { defineComponent, reactive, toRefs, ref, onMounted } from "vue";
+import { picker } from "@/helper/config/range";
+import ToolBar from "@/components/tool-bar/index.vue";
+import moment from "moment";
+import { AdgroupCloumn } from "../_pageOptions/table-put";
+
+import { getAdgroupList, setGroupStatus } from "@/api";
+import usePagination from "@/hooks/usePagination";
+
+import { AdGroupData, PageOptions } from "@/types/api";
+
+const Adgroup = defineComponent({
+  components: {
+    ToolBar,
+  },
+  setup() {
+    let { loading, meta, tablePageOptions } = usePagination();
+
+    const state = reactive({
+      inSearching: false,
+      open: false,
+      inConfirm: false,
+      list: ref<AdGroupData[]>([]),
+      rangePick: picker,
+      pickered: [],
+      columns: AdgroupCloumn,
+      fields: {},
+    });
+
+    const onSearch = (fields: Record<string, string>) => {
+      const { advertiser_id, campaign_id } = fields;
+      state.fields = fields;
+      getData({ current: 1, advertiser_id, campaign_id });
+    };
+
+    const getData = async (query?: {
+      current: number;
+      advertiser_id?: string;
+      campaign_id?:  string;
+    }) => {
+      try {
+        loading.value = true;
+        let [begin_dates, end_dates] = state.pickered;
+        let  begin_date,end_date;
+        if(begin_dates && end_dates){
+             begin_date = moment(begin_dates).format("YYYY-MM-DD");
+             end_date = moment(end_dates).format("YYYY-MM-DD");
+        }
+        
+        const { data } = await getAdgroupList({
+          begin_date,
+          end_date,
+          advertiser_id: query?.advertiser_id,
+          campaign_id: query?.campaign_id,
+          page: query?.current ?? 1,
+        });
+        let mewList = data.list.map((item) => {
+          typeof item.is_enable;
+          item.is_enable = !!item.is_enable;
+          return item;
+        });
+        state.list = mewList;
+        meta.value = data.meta;
+      } catch (error) {
+        console.log("on get books list error");
+      } finally {
+        state.inSearching = false;
+      }
+    };
+    const handleTableChange = (pagination: PageOptions) => {
+      const { current, pageSize, total } = pagination;
+      let data = Object.assign({ current ,...state.fields} );
+      getData(data);
+    };
+
+    onMounted(getData);
+
+    return {
+      ...toRefs(state),
+      loading,
+      tablePageOptions,
+      onSearch,
+      handleTableChange,
+    };
+  },
+  methods: {
+    moment,
+    switchMethod(record:any){
+        let data = {
+        campaign_id: record.campaign_id,
+        status: Number(!record.is_enable),
+      };
+      setGroupStatus(data).then((res) => {
+        this.$message.success("修改成功!");
+      });
+    }
+  },
+});
+
+export default Adgroup;
+</script>

+ 34 - 0
src/views/put/ad_datas.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="mian-contant">
+    <div>
+      <a-tabs default-active-key="1" @change="changeTab" v-model:activeKey="defaultKey">
+        <a-tab-pane key="PutAdAcountL" tab="广告账户数据"> </a-tab-pane>
+        <a-tab-pane key="PutAdGroup" tab="广告组数据"> </a-tab-pane>
+        <a-tab-pane key="PutAdPlan" tab="广告计划数据"> </a-tab-pane>
+      </a-tabs>
+    </div>
+
+    <router-view></router-view>
+  </div>
+</template>
+
+<script lang="ts">
+import useApp from "@/hooks/useApp";
+import { defineComponent,reactive,toRefs } from "vue";
+
+const PutDataIndex = defineComponent({
+  setup() {
+    const {  route,router } = useApp();
+    const state = reactive({
+      defaultKey:route.name
+    })
+    const changeTab = (key:string) => {
+      router.replace({name:key})
+    };
+
+    return {...toRefs(state), changeTab };
+  },
+});
+
+export default PutDataIndex;
+</script>

+ 35 - 22
src/views/put/put-ad-plan.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="page-wrap page-wrap-account">
     <tool-bar
-      :text="['account_name', 'email', 'ad_name', 'campaign_name']"
-      :label="['账户名', '邮箱', '计划名称(或ID)', '广告组名称']"
+      :text="['ad_id', 'advertiser_id', 'campaign_id']"
+      :label="['计划ID', '账号', '广告组名称']"
       v-model:loading="inSearching"
       @confirm="onSearch"
     >
@@ -62,13 +62,8 @@
       <template #external_url="{ text, record }">
         <p @click="onGo(record)"><a>前往落地页链接</a></p>
       </template>
-
-      <template #email="{ text, record }">
-        <p>{{ record.email }}</p>
-        <p>{{ record.account_name }}</p>
-      </template>
-
       <template #ad_name="{ text, record }">
+        <p>账户名:{{ record.account_name }}</p>
         <p>广告名:{{ record.ad_name }}</p>
         <p>广告ID:{{ record.ad_id }}</p>
       </template>
@@ -171,7 +166,7 @@
 
       <template #cpa_bid="{ text, record }">
         <editable-cell
-          :text="text"
+          :text="`${text}`"
           title="预算"
           @change="(val) => onCellChange(record, 'cpa_bid', val)"
         />
@@ -179,7 +174,7 @@
 
       <template #budget="{ text, record }">
         <editable-cell
-          :text="text"
+          :text="`${text}`"
           title="出价"
           @change="(val) => onCellChange(record, 'budget', val)"
         />
@@ -307,6 +302,7 @@ const PutAdPlan = defineComponent({
           price: 0,
         },
       ],
+      cost_order: 0,
       optionList: opList,
       statsList: stList,
       currentStats: "paid_order_amount",
@@ -323,14 +319,13 @@ const PutAdPlan = defineComponent({
     });
     const onSearch = async (fields: Record<string, string>) => {
       try {
-        const { email, account_name, ad_name, status, campaign_name } = fields;
+        const { ad_id, advertiser_id, campaign_id, status } = fields;
         state.fields = fields;
         const data = {
-          email,
-          account_name,
-          ad_name,
+          ad_id,
+          advertiser_id,
           status: state.currentSelect,
-          campaign_name,
+          campaign_id,
           page: 1,
         };
         getData(data);
@@ -351,9 +346,14 @@ const PutAdPlan = defineComponent({
       let begin_date = moment(begin_dates).format("YYYY-MM-DD");
       let end_date = moment(end_dates).format("YYYY-MM-DD");
       let data = Object.assign(
-        { page: 1, status: "AD_STATUS_DELIVERY_OK", ...state.fields },
+        {
+          page: 1,
+          status: "AD_STATUS_DELIVERY_OK",
+          ...state.fields,
+        },
         query || {},
-        { begin_date, end_date, status: state.currentSelect }
+        { begin_date, end_date, status: state.currentSelect },
+        state.cost_order ? { cost_order:state.cost_order } : {}
       );
       getADPlanlist(data).then((res) => {
         let newList: any[] = res.data.list.map((item) => {
@@ -384,10 +384,11 @@ const PutAdPlan = defineComponent({
           dataIndex: string;
           slots?: any;
           width?: string | number;
+          sorter?: boolean;
         } = {
           title: item.desc,
           dataIndex: item.name,
-          width: 150,
+          width: 110,
         };
 
         if (item.name == "external_url") {
@@ -396,6 +397,10 @@ const PutAdPlan = defineComponent({
         if (item.name == "cpa_bid" || item.name == "budget") {
           lolumnItem.slots = { customRender: item.name };
         }
+        if (item.name == "cost") {
+          lolumnItem.sorter = true;
+        }
+
         columns.push(lolumnItem);
       });
       let newColunms = columns.filter(
@@ -420,7 +425,16 @@ const PutAdPlan = defineComponent({
       });
     });
 
-    const handleTableChange = (pagination: PageOptions) => {
+    const handleTableChange = (
+      pagination: PageOptions,
+      filters: any,
+      sorter: any
+    ) => {
+      if (sorter.columnKey == "cost") {
+        sorter.order == "ascend"
+          ? (state.cost_order = 1)
+          : (state.cost_order = 2);
+      }
       const { current, pageSize, total } = pagination;
       getData({ page: current });
     };
@@ -467,7 +481,7 @@ const PutAdPlan = defineComponent({
     onCellChange(record: any, dataIndex: string, value: string) {
       let ad_id = record.ad_id;
       if (dataIndex == "cpa_bid") {
-        adChangeCrem({ ad_id, bid: value })
+        adChangeCrem({ ad_id, bid: Number(value) })
           .then((res) => {
             this.$message.success("修改成功!");
           })
@@ -476,7 +490,7 @@ const PutAdPlan = defineComponent({
           });
       }
       if (dataIndex == "budget") {
-        adChangeMoney({ ad_id, budget: value })
+        adChangeMoney({ ad_id, budget: Number(value) })
           .then((res) => {
             this.$message.success("修改成功!");
           })
@@ -490,7 +504,6 @@ const PutAdPlan = defineComponent({
     },
     editBackConfig() {},
     switchMethod(record: any) {
-      console.log(record);
       let ad_id = record.ad_id;
       statusChange({
         ad_id,