Browse Source

添加优惠券统计

wangningfei 2 years ago
parent
commit
b0f1f74d71

+ 13 - 0
vue-admin-template-master/Dockerfile

@@ -0,0 +1,13 @@
+FROM registry.cn-shanghai.aliyuncs.com/nowwa/nginx:1.17-alpine
+
+ARG DIST_ROOT=./dist
+ARG APP_ROOT=/usr/share/nginx/html
+WORKDIR ${APP_ROOT}
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
+
+RUN apk update \
+    && apk add tzdata \
+    && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
+    && echo "Asia/Shanghai" > /etc/timezone
+ADD ${DIST_ROOT} .
+CMD ["/bin/sh", "-c", "nginx -g 'daemon off;'"]

+ 18 - 0
vue-admin-template-master/src/api/order.js

@@ -122,3 +122,21 @@ export function sendmsg(data) {
     data
   });
 }
+
+//优惠券领取统计
+export function getStatistics(data) {
+  return request({
+    url: "/dashboard/ticket/statistics",
+    method: "post",
+    data
+  });
+}
+
+//优惠券使用统计
+export function statisticsbytitle(data) {
+  return request({
+    url: "/dashboard/ticket/statistics/bytitle",
+    method: "post",
+    data
+  });
+}

+ 49 - 45
vue-admin-template-master/src/layout/index.vue

@@ -1,9 +1,13 @@
 <template>
   <div :class="classObj" class="app-wrapper">
-    <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
+    <!-- <div
+      v-if="device === 'mobile' && sidebar.opened"
+      class="drawer-bg"
+      @click="handleClickOutside"
+    /> -->
     <sidebar class="sidebar-container" />
     <div class="main-container">
-      <div :class="{'fixed-header':fixedHeader}">
+      <div :class="{ 'fixed-header': fixedHeader }">
         <navbar />
       </div>
       <app-main />
@@ -12,11 +16,11 @@
 </template>
 
 <script>
-import { Navbar, Sidebar, AppMain } from './components'
-import ResizeMixin from './mixin/ResizeHandler'
+import { Navbar, Sidebar, AppMain } from "./components";
+import ResizeMixin from "./mixin/ResizeHandler";
 
 export default {
-  name: 'Layout',
+  name: "Layout",
   components: {
     Navbar,
     Sidebar,
@@ -25,69 +29,69 @@ export default {
   mixins: [ResizeMixin],
   computed: {
     sidebar() {
-      return this.$store.state.app.sidebar
+      return this.$store.state.app.sidebar;
     },
     device() {
-      return this.$store.state.app.device
+      return this.$store.state.app.device;
     },
     fixedHeader() {
-      return this.$store.state.settings.fixedHeader
+      return this.$store.state.settings.fixedHeader;
     },
     classObj() {
       return {
         hideSidebar: !this.sidebar.opened,
         openSidebar: this.sidebar.opened,
         withoutAnimation: this.sidebar.withoutAnimation,
-        mobile: this.device === 'mobile'
-      }
+        mobile: this.device === "mobile"
+      };
     }
   },
   methods: {
     handleClickOutside() {
-      this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
+      this.$store.dispatch("app/closeSideBar", { withoutAnimation: false });
     }
   }
-}
+};
 </script>
 
 <style lang="scss" scoped>
-  @import "~@/styles/mixin.scss";
-  @import "~@/styles/variables.scss";
+@import "~@/styles/mixin.scss";
+@import "~@/styles/variables.scss";
 
-  .app-wrapper {
-    @include clearfix;
-    position: relative;
-    height: 100%;
-    width: 100%;
-    &.mobile.openSidebar{
-      position: fixed;
-      top: 0;
-    }
-  }
-  .drawer-bg {
-    background: #000;
-    opacity: 0.3;
-    width: 100%;
-    top: 0;
-    height: 100%;
-    position: absolute;
-    z-index: 999;
-  }
-
-  .fixed-header {
+.app-wrapper {
+  @include clearfix;
+  position: relative;
+  height: 100%;
+  width: 100%;
+  &.mobile.openSidebar {
     position: fixed;
     top: 0;
-    right: 0;
-    z-index: 9;
-    width: calc(100% - #{$sideBarWidth});
-    transition: width 0.28s;
   }
+}
+.drawer-bg {
+  background: #000;
+  opacity: 0.3;
+  width: 100%;
+  top: 0;
+  height: 100%;
+  position: absolute;
+  z-index: 999;
+}
 
-  .hideSidebar .fixed-header {
-    width: calc(100% - 54px)
-  }
+.fixed-header {
+  position: fixed;
+  top: 0;
+  right: 0;
+  z-index: 9;
+  width: calc(100% - #{$sideBarWidth});
+  transition: width 0.28s;
+}
 
-  .mobile .fixed-header {
-    width: 100%;
-  }
+.hideSidebar .fixed-header {
+  width: calc(100% - 54px);
+}
+
+.mobile .fixed-header {
+  width: 100%;
+}
 </style>

+ 6 - 0
vue-admin-template-master/src/router/index.js

@@ -224,6 +224,12 @@ export const constantRoutes = [
         name: "Sendmsg",
         component: () => import("@/views/coupon/sendmsg"),
         meta: { title: "短信" }
+      },
+      {
+        path: "statistics",
+        name: "statistics",
+        component: () => import("@/views/coupon/statistics"),
+        meta: { title: "优惠券统计" }
       }
     ]
   },

+ 12 - 13
vue-admin-template-master/src/styles/sidebar.scss

@@ -1,8 +1,7 @@
 #app {
-
   .main-container {
     min-height: 100%;
-    transition: margin-left .28s;
+    transition: margin-left 0.28s;
     margin-left: $sideBarWidth;
     position: relative;
   }
@@ -22,7 +21,8 @@
 
     // reset element-ui css
     .horizontal-collapse-transition {
-      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+      transition: 0s width ease-in-out, 0s padding-left ease-in-out,
+        0s padding-right ease-in-out;
     }
 
     .scrollbar-wrapper {
@@ -76,11 +76,11 @@
       }
     }
 
-    .is-active>.el-submenu__title {
+    .is-active > .el-submenu__title {
       color: $subMenuActiveText !important;
     }
 
-    & .nest-menu .el-submenu>.el-submenu__title,
+    & .nest-menu .el-submenu > .el-submenu__title,
     & .el-submenu .el-menu-item {
       min-width: $sideBarWidth !important;
       background-color: $subMenuBg !important;
@@ -120,7 +120,7 @@
     .el-submenu {
       overflow: hidden;
 
-      &>.el-submenu__title {
+      & > .el-submenu__title {
         padding: 0 !important;
 
         .svg-icon {
@@ -139,8 +139,8 @@
 
     .el-menu--collapse {
       .el-submenu {
-        &>.el-submenu__title {
-          &>span {
+        & > .el-submenu__title {
+          & > span {
             height: 0;
             width: 0;
             overflow: hidden;
@@ -163,7 +163,7 @@
     }
 
     .sidebar-container {
-      transition: transform .28s;
+      transition: transform 0.28s;
       width: $sideBarWidth !important;
     }
 
@@ -177,7 +177,6 @@
   }
 
   .withoutAnimation {
-
     .main-container,
     .sidebar-container {
       transition: none;
@@ -187,7 +186,7 @@
 
 // when menu collapsed
 .el-menu--vertical {
-  &>.el-menu {
+  & > .el-menu {
     .svg-icon {
       margin-right: 16px;
     }
@@ -197,7 +196,7 @@
     }
   }
 
-  .nest-menu .el-submenu>.el-submenu__title,
+  .nest-menu .el-submenu > .el-submenu__title,
   .el-menu-item {
     &:hover {
       // you can use $subMenuHover
@@ -206,7 +205,7 @@
   }
 
   // the scroll bar appears when the subMenu is too long
-  >.el-menu--popup {
+  > .el-menu--popup {
     max-height: 100vh;
     overflow-y: auto;
 

+ 8 - 7
vue-admin-template-master/src/styles/variables.scss

@@ -1,15 +1,16 @@
 // sidebar
-$menuText:#bfcbd9;
-$menuActiveText:#409EFF;
-$subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951
+$menuText: #bfcbd9;
+$menuActiveText: #409eff;
+$subMenuActiveText: #f4f4f5; //https://github.com/ElemeFE/element/issues/12951
 
-$menuBg:#304156;
-$menuHover:#263445;
+$menuBg: #304156;
+$menuHover: #263445;
 
-$subMenuBg:#1f2d3d;
-$subMenuHover:#001528;
+$subMenuBg: #1f2d3d;
+$subMenuHover: #001528;
 
 $sideBarWidth: 210px;
+// $sideBarWidth: 0;
 
 // the :export directive is the magic sauce for webpack
 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass

+ 166 - 0
vue-admin-template-master/src/views/coupon/statistics/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="wrapper">
+    <!-- 查询 -->
+    <div>
+      <el-date-picker
+        :picker-options="pickeroptions"
+        value-format="yyyy-MM-dd"
+        v-model="time"
+        type="daterange"
+        range-separator="至"
+        start-placeholder="开始日期"
+        end-placeholder="结束日期"
+      >
+      </el-date-picker>
+      <el-button
+        class="mr-10"
+        type="primary"
+        @click="query"
+        :loading="queryLoading"
+        >查 询</el-button
+      >
+    </div>
+    <div class="mt-20">
+      <h4>领取统计</h4>
+      <el-table :data="receiveTableData" border style="width: 100%">
+        <el-table-column prop="title" label="券名称"> </el-table-column>
+        <el-table-column prop="value" label="券数量"> </el-table-column>
+      </el-table>
+    </div>
+    <div class="mt-20">
+      <h4>使用统计</h4>
+      <el-table :data="useTableData" border style="width: 100%">
+        <el-table-column prop="title" label="券名称"> </el-table-column>
+        <el-table-column prop="value" label="券数量"> </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- 搜索 -->
+    <div class="mt-40">
+      <div class="search">
+        <el-input
+          class="input"
+          v-model="input"
+          clearable
+          placeholder="请输入券名称"
+        ></el-input>
+        <el-button
+          class="mr-10"
+          type="primary"
+          @click="search"
+          :loading="searchLoading"
+          >查 询</el-button
+        >
+      </div>
+      <div class="mt-20">
+        <el-row :gutter="12">
+          <el-col :span="8">
+            <el-card shadow="hover">
+              领取: <span class="num">{{ receiveNum }}</span>
+            </el-card>
+          </el-col>
+          <el-col :span="8">
+            <el-card shadow="hover">
+              使用:<span class="num">{{ useNum }}</span>
+            </el-card>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getStatistics, statisticsbytitle } from "@/api/order";
+export default {
+  data() {
+    return {
+      queryLoading: false,
+      time: "",
+      pickeroptions: {
+        disabledDate: time => {
+          return time.getTime() > Date.now() - 8.64e6;
+        }
+      },
+      receiveTableData: [],
+      useTableData: [],
+
+      input: "",
+      searchLoading: false,
+      receiveNum: 0,
+      useNum: 0
+    };
+  },
+  methods: {
+    async query() {
+      if (!this.time) return this.$message.error("请选择日期范围");
+      this.queryLoading = true;
+      let res = await getStatistics({
+        startdate: this.time[0],
+        enddate: this.time[1]
+      });
+
+      console.log(res);
+      let dget = [];
+      for (let key in res.dget) {
+        dget.push({
+          title: key,
+          value: res.dget[key]
+        });
+      }
+
+      let duse = [];
+      for (let key in res.duse) {
+        duse.push({
+          title: key,
+          value: res.dget[key]
+        });
+      }
+      this.receiveTableData = dget;
+      this.useTableData = duse;
+      this.queryLoading = false;
+
+      // this.$message.success(JSON.stringify(this.time));
+    },
+    async search() {
+      if (!this.input) return this.$message.error("请输入券名称");
+      this.searchLoading = true;
+      let res = await statisticsbytitle({
+        title: this.input
+      });
+      this.receiveNum = res.total;
+      this.useNum = res.used;
+      this.searchLoading = false;
+    }
+  }
+};
+</script>
+
+<style>
+.wrapper {
+  width: 100%;
+  height: 100%;
+  box-sizing: border-box;
+  padding: 20px;
+  overflow-y: scroll;
+}
+.mr-10 {
+  margin-left: 20px;
+}
+.mt-20 {
+  margin: 20px 0;
+}
+.mt-40 {
+  margin: 40px 0;
+}
+.search {
+  margin-bottom: 20px;
+}
+.search .input {
+  width: 350px;
+}
+.num {
+  font-size: 36px;
+  font-weight: bold;
+}
+</style>