Browse Source

修改密码

licailing 5 năm trước cách đây
mục cha
commit
65e480642d
23 tập tin đã thay đổi với 701 bổ sung243 xóa
  1. 1 1
      src/main/java/com/izouma/dingdong/Application.java
  2. 2 1
      src/main/java/com/izouma/dingdong/repo/OrderInfoRepo.java
  3. 3 0
      src/main/java/com/izouma/dingdong/repo/merchant/MerchantRepo.java
  4. 5 3
      src/main/java/com/izouma/dingdong/repo/rider/RiderRepo.java
  5. 31 0
      src/main/java/com/izouma/dingdong/service/PlatformFlowService.java
  6. 12 0
      src/main/java/com/izouma/dingdong/service/UserService.java
  7. 4 10
      src/main/java/com/izouma/dingdong/service/merchant/MerchantService.java
  8. 2 0
      src/main/java/com/izouma/dingdong/service/sms/TencentSmsService.java
  9. 6 0
      src/main/java/com/izouma/dingdong/web/PlatformFlowController.java
  10. 6 0
      src/main/java/com/izouma/dingdong/web/UserController.java
  11. 0 5
      src/main/java/com/izouma/dingdong/web/merchant/AutomaticResponseController.java
  12. 3 0
      src/main/java/com/izouma/dingdong/web/user/AddressController.java
  13. 0 70
      src/main/vue/src/views/Categories.vue
  14. 139 47
      src/main/vue/src/views/Dashboard.vue
  15. 52 45
      src/main/vue/src/widgets/BarChartWidget.vue
  16. 51 0
      src/main/vue/src/widgets/GoodsWidget.vue
  17. 136 32
      src/main/vue/src/widgets/LineChartWidget.vue
  18. 79 0
      src/main/vue/src/widgets/OrderListWidget.vue
  19. 49 0
      src/main/vue/src/widgets/OrderWidget.vue
  20. 37 28
      src/main/vue/src/widgets/UserWidget.vue
  21. 50 0
      src/main/vue/src/widgets/VipUserWidget.vue
  22. 1 1
      src/main/vue/src/widgets/WidgetCard.vue
  23. 32 0
      src/test/java/com/izouma/dingdong/contorller/AddressControllerTest.java

+ 1 - 1
src/main/java/com/izouma/dingdong/Application.java

@@ -7,7 +7,7 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
 
 @SpringBootApplication
 @EnableJpaAuditing
-@EnableSwagger2
+//@EnableSwagger2
 public class Application {
 
     public static void main(String[] args) {

+ 2 - 1
src/main/java/com/izouma/dingdong/repo/OrderInfoRepo.java

@@ -28,7 +28,7 @@ public interface OrderInfoRepo extends JpaRepository<OrderInfo, Long>, JpaSpecif
     List<OrderInfo> findAllByUserId(Long userId);
 
     //按骑手查找
-    List<OrderInfo> findAllByRiderId(Long riderId);
+//    List<OrderInfo> findAllByRiderId(Long riderId);
 
     //按骑手查找状态不为完成的订单
     List<OrderInfo> findAllByRiderIdAndRiderStatusIsNot(Long riderId, RiderStatus riderStatus);
@@ -55,4 +55,5 @@ public interface OrderInfoRepo extends JpaRepository<OrderInfo, Long>, JpaSpecif
 
     //按商家和时间内的订单泪飙
     List<OrderInfo> findAllByMerchantIdAndOrderTimeAfter(Long merchantId, LocalDateTime dateTime);
+
 }

+ 3 - 0
src/main/java/com/izouma/dingdong/repo/merchant/MerchantRepo.java

@@ -1,6 +1,7 @@
 package com.izouma.dingdong.repo.merchant;
 
 import com.izouma.dingdong.domain.merchant.Merchant;
+import com.izouma.dingdong.enums.ApplyStatus;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
@@ -29,4 +30,6 @@ public interface MerchantRepo extends JpaRepository<Merchant, Long>, JpaSpecific
 
     //按口碑联盟筛选
     List<Merchant> findAllByBuyAllianceTrue();
+
+    Long countAllByStatus(ApplyStatus status);
 }

+ 5 - 3
src/main/java/com/izouma/dingdong/repo/rider/RiderRepo.java

@@ -1,9 +1,9 @@
 package com.izouma.dingdong.repo.rider;
 
 import com.izouma.dingdong.domain.rider.Rider;
+import com.izouma.dingdong.enums.ApplyStatus;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.data.jpa.repository.Query;
 
 import java.util.Optional;
 
@@ -14,6 +14,8 @@ public interface RiderRepo extends JpaRepository<Rider, Long>, JpaSpecificationE
     Rider findByJobNumber(String jobNumber);
 
     //骑手Id找出用户Id
-    @Query("select t.userId from Rider t where t.id = ?1")
-    Long findUserIdById(Long id);
+//    @Query("select t.userId from Rider t where t.id = ?1")
+//    Long findUserIdById(Long id);
+
+    Long countAllByStatus(ApplyStatus status);
 }

+ 31 - 0
src/main/java/com/izouma/dingdong/service/PlatformFlowService.java

@@ -1,14 +1,45 @@
 package com.izouma.dingdong.service;
 
 import com.izouma.dingdong.domain.PlatformFlow;
+import com.izouma.dingdong.domain.User;
+import com.izouma.dingdong.enums.ApplyStatus;
+import com.izouma.dingdong.enums.Identity;
+import com.izouma.dingdong.enums.OrderStatus;
+import com.izouma.dingdong.repo.OrderInfoRepo;
 import com.izouma.dingdong.repo.PlatformFlowRepo;
+import com.izouma.dingdong.repo.UserRepo;
+import com.izouma.dingdong.repo.merchant.MerchantRepo;
+import com.izouma.dingdong.repo.rider.RiderRepo;
 import lombok.AllArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @Service
 @AllArgsConstructor
 public class PlatformFlowService {
 
     private PlatformFlowRepo platformFlowRepo;
+    private UserRepo         userRepo;
+    private MerchantRepo     merchantRepo;
+    private RiderRepo        riderRepo;
+    private OrderInfoRepo    orderInfoRepo;
+
+    /*
+    报表
+     */
+    public Map<String, Object> getDashboard() {
+        Map<String, Object> map = new HashMap<>();
+        Long user = userRepo.countAllByIdentity(Identity.USER);
+        Long merchant = merchantRepo.countAllByStatus(ApplyStatus.PASS);
+        Long rider = riderRepo.countAllByStatus(ApplyStatus.PASS);
+        Long order = orderInfoRepo.count();
+        map.put("user", user);
+        map.put("merchant", merchant);
+        map.put("rider", rider);
+        map.put("order", order);
+        return map;
+    }
 
 }

+ 12 - 0
src/main/java/com/izouma/dingdong/service/UserService.java

@@ -251,4 +251,16 @@ public class UserService {
         userRepo.save(user);
     }
 
+    /*
+    更新密码
+     */
+    public String setPassword(Long userId, String key, String code, String password) {
+        try {
+            smsService.verify(key, code);
+        } catch (SmsService.SmsVerifyException e) {
+            e.printStackTrace();
+            throw new BusinessException("验证码错误");
+        }
+        return setPassword(userId, password);
+    }
 }

+ 4 - 10
src/main/java/com/izouma/dingdong/service/merchant/MerchantService.java

@@ -239,19 +239,13 @@ public class MerchantService {
      * @return 分页列表
      */
     public Page<MerchantDTO> backAll(PageQuery pageQuery) {
-
-        List<MerchantDTO> merchantDTOS = CollUtil.newArrayList();
         Page<Merchant> merchants = merchantRepo.findAll(toSpecification(pageQuery, Merchant.class), toPageRequest(pageQuery));
-        for (Merchant merchant : merchants) {
-            MerchantSettings merchantSettings = merchantSettingsRepo.findByMerchantId(merchant.getId())
-                    .orElseThrow(new BusinessException("商户不存在"));
-
-            merchantDTOS.add(new MerchantDTO(merchant, merchantSettings));
-        }
-        return new PageImpl<>(merchantDTOS, toPageRequest(pageQuery), merchantDTOS.size());
+        return merchants.map(merchant ->
+                new MerchantDTO(merchant, merchantSettingsRepo.findByMerchantId(merchant.getId())
+                        .orElseThrow(new BusinessException("商户不存在")))
+        );
     }
 
-
     /**
      * 显示个人的商户信息
      *

+ 2 - 0
src/main/java/com/izouma/dingdong/service/sms/TencentSmsService.java

@@ -18,6 +18,7 @@ import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
+import java.util.Arrays;
 
 /**
  * Tencent Cloud Sms Sendsms
@@ -66,6 +67,7 @@ public class TencentSmsService {
             req.setSenderId("Qcloud");
             //回调
             SendSmsResponse resp = client.SendSms(req);
+            log.info("send sms response {}", Arrays.toString(resp.getSendStatusSet()));
             //String s = SendSmsResponse.toJsonString(resp);
             SendStatus status = resp.getSendStatusSet()[0];
             if (!status.getCode().equals("Ok")) {

+ 6 - 0
src/main/java/com/izouma/dingdong/web/PlatformFlowController.java

@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/platformFlow")
@@ -56,5 +57,10 @@ public class PlatformFlowController extends BaseController {
         List<PlatformFlow> data = all(pageQuery).getContent();
         ExcelUtils.export(response, data);
     }
+
+    @GetMapping("/getDashboard")
+    public Map<String,Object> getDashboard(){
+        return platformFlowService.getDashboard();
+    }
 }
 

+ 6 - 0
src/main/java/com/izouma/dingdong/web/UserController.java

@@ -129,4 +129,10 @@ public class UserController extends BaseController {
         userService.cashAuthority(userId, can);
     }
 
+    @PostMapping("/changePassword")
+    @ApiOperation("修改密码")
+    public String changePassword(@RequestParam String password, @RequestParam String key, @RequestParam String code) {
+        return userService.setPassword(SecurityUtils.getAuthenticatedUser().getId(), key, code, password);
+    }
+
 }

+ 0 - 5
src/main/java/com/izouma/dingdong/web/merchant/AutomaticResponseController.java

@@ -1,11 +1,9 @@
 package com.izouma.dingdong.web.merchant;
 
 import com.izouma.dingdong.repo.merchant.MerchantRepo;
-import com.izouma.dingdong.service.merchant.MerchantService;
 import com.izouma.dingdong.utils.SecurityUtils;
 import com.izouma.dingdong.web.BaseController;
 import com.izouma.dingdong.domain.merchant.AutomaticResponse;
-import com.izouma.dingdong.service.merchant.AutomaticResponseService;
 import com.izouma.dingdong.dto.PageQuery;
 import com.izouma.dingdong.exception.BusinessException;
 import com.izouma.dingdong.repo.merchant.AutomaticResponseRepo;
@@ -15,7 +13,6 @@ import com.izouma.dingdong.utils.excel.ExcelUtils;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletResponse;
@@ -26,9 +23,7 @@ import java.util.List;
 @RequestMapping("/automaticResponse")
 @AllArgsConstructor
 public class AutomaticResponseController extends BaseController {
-    private AutomaticResponseService automaticResponseService;
     private AutomaticResponseRepo automaticResponseRepo;
-    private MerchantService merchantService;
     private MerchantRepo merchantRepo;
 
     //@PreAuthorize("hasRole('ADMIN')")

+ 3 - 0
src/main/java/com/izouma/dingdong/web/user/AddressController.java

@@ -36,6 +36,9 @@ public class AddressController extends BaseController {
             ObjUtils.merge(orig, record);
             record = addressRepo.save(orig);
         } else {
+            if (record.getIsDefault() == null) {
+                record.setIsDefault(false);
+            }
             record = addressRepo.save(record);
         }
         if (record.getIsDefault()) {

+ 0 - 70
src/main/vue/src/views/Categories.vue

@@ -12,25 +12,8 @@
                               :rules="[{required: true, message: '请填写分类名', trigger: 'blur'}]">
                     <el-input v-model="menu.name"></el-input>
                 </el-form-item>
-<!--                <el-form-item label="菜单地址" prop="path">-->
-<!--                    <el-input v-model="menu.path"></el-input>-->
-<!--                </el-form-item>-->
-
                 <el-form-item prop="icon" label="图标">
-<!--                    <template slot="label">图片
-                        <a href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"
-                           target="_blank"
-                           class="available-icons">查看所有可用图标</a></template>-->
-<!--                    <el-input v-model="icon">-->
-<!--                        <template slot="append">-->
-<!--                            <span ref="iconContainer" style="font-size: 10px">-->
-<!--                                <el-button @click="">上传</el-button>-->
-                                <!--<i
-                                class="fas fa-"></i>-->
-<!--                            </span>-->
-<!--                        </template>-->
                         <crop-upload v-model="menu.icon"></crop-upload>
-<!--                    </el-input>-->
                 </el-form-item>
 
             </el-form>
@@ -79,9 +62,6 @@
                 this.parent = 1;
                 this.icon = "";
                 this.dialogVisible = true;
-                // setTimeout(() => {
-                //     this.showIcon("bars");
-                // }, 100);
             },
             showAddDialog(node, data) {
                 this.edit = false;
@@ -89,40 +69,20 @@
                 this.menu = {
                     parent: node.data.id,
                     name: "",
-                    // path: "",
                     active: true,
-                    // root: false,
                     icon: ""
                 };
                 this.icon = "";
                 this.dialogVisible = true;
-                // setTimeout(() => {
-                //     this.showIcon("");
-                // }, 100);
             },
             showEditDialog(node, data) {
                 this.edit = true;
                 this.currentRef = node.data;
                 this.icon = data.icon
-                // const getIconName = icon => {
-                //     let iconName = "";
-                //     if (icon) {
-                //         iconName = icon
-                //             .replace("fas ", "")
-                //             .replace("fab ", "")
-                //             .replace("fa-", "");
-                //     }
-                //     return iconName || null;
-                // };
-                // let iconName = getIconName(data.icon);
                 this.menu = {
                     ...data
                 };
-                // this.icon = iconName;
                 this.dialogVisible = true;
-                // setTimeout(() => {
-                //     this.showIcon(iconName);
-                // }, 100);
             },
             addMenu() {
                 this.$refs.form.validate(valid => {
@@ -306,37 +266,7 @@
                     </span>
             );
             },
-            // showIcon(val) {
-            //     if (!this.$refs.iconContainer) return;
-            //     if (FontAwesome.icon({ prefix: "fas", iconName: val })) {
-            //         this.$refs.iconContainer.innerHTML = "";
-            //         let i = document.createElement("i");
-            //         i.className = "fas fa-" + val;
-            //         this.$refs.iconContainer.append(i);
-            //         FontAwesome.dom.i2svg();
-            //         this.menu.icon = "fas fa-" + val;
-            //     } else if (FontAwesome.icon({ prefix: "fab", iconName: val })) {
-            //         this.$refs.iconContainer.innerHTML = "";
-            //         let i = document.createElement("i");
-            //         i.className = "fab fa-" + val;
-            //         this.$refs.iconContainer.append(i);
-            //         FontAwesome.dom.i2svg();
-            //         this.menu.icon = "fab fa-" + val;
-            //     } else {
-            //         this.$refs.iconContainer.innerHTML = "";
-            //         let i = document.createElement("i");
-            //         i.className = "fab fa-" + val;
-            //         this.$refs.iconContainer.append(i);
-            //         FontAwesome.dom.i2svg();
-            //         this.menu.icon = "";
-            //     }
-            // }
         },
-        // watch: {
-        //     icon(val) {
-        //         this.showIcon(val);
-        //     }
-        // }
     };
 </script>
 <style lang="less">

+ 139 - 47
src/main/vue/src/views/Dashboard.vue

@@ -1,63 +1,155 @@
 <template>
     <div>
-        <grid-layout style="margin:0 -10px;" :layout="layout" :col-num="12"
-            :row-height="30" :is-draggable="editable" :is-resizable="editable"
-            :is-mirrored="false" :vertical-compact="true" :margin="[10, 10]"
-            :use-css-transforms="true">
-            <grid-item v-for="item in layout" class="widget-wrapper" :x="item.x"
-                :y="item.y" :w="item.w" :h="item.h" :i="item.i" :key="item.i">
-                <component :is="item.name"></component>
+        <grid-layout
+                style="margin:0 -10px;"
+                :layout="layout"
+                :col-num="12"
+                :row-height="30"
+                :is-draggable="editable"
+                :is-resizable="editable"
+                :is-mirrored="false"
+                :vertical-compact="true"
+                :margin="[10, 10]"
+                :use-css-transforms="true"
+        >
+            <grid-item
+                    v-for="item in layout"
+                    class="widget-wrapper"
+                    :x="item.x"
+                    :y="item.y"
+                    :w="item.w"
+                    :h="item.h"
+                    :i="item.i"
+                    :key="item.i"
+            >
+                <component :is="item.name" :value="$data[item.key]"></component>
             </grid-item>
         </grid-layout>
         <el-button v-if="editable" @click="save">保存</el-button>
-        <el-button v-else @click="editable=true">编辑</el-button>
+        <!--        <el-button v-else @click="editable=true">编辑</el-button>-->
     </div>
 </template>
 
 <script>
-import { GridLayout, GridItem } from "vue-grid-layout";
-import UserWidget from "../widgets/UserWidget";
-import LineChartWidget from "../widgets/LineChartWidget";
-import BarChartWidget from "../widgets/BarChartWidget";
-import PieChartWidget from "../widgets/PieChartWidget";
+    import { GridLayout, GridItem } from "vue-grid-layout";
+    import UserWidget from "../widgets/UserWidget";
+    import VipUserWidget from "../widgets/VipUserWidget";
+    import GoodsWidget from "../widgets/GoodsWidget";
+    import OrderWidget from "../widgets/OrderWidget";
+    import LineChartWidget from "../widgets/LineChartWidget";
+    import BarChartWidget from "../widgets/BarChartWidget";
+    import OrderListWidget from "../widgets/OrderListWidget";
 
-export default {
-    created() {},
-    data() {
-        return {
-            layout: [
-                { x: 0, y: 0, w: 6, h: 4, i: "0", name: "UserWidget" },
-                { x: 6, y: 0, w: 6, h: 4, i: "1", name: "UserWidget" },
-                { x: 0, y: 4, w: 6, h: 6, i: "2", name: "BarChartWidget" },
-                { x: 0, y: 10, w: 6, h: 6, i: "3", name: "LineChartWidget" },
-                { x: 6, y: 4, w: 6, h: 12, i: "4", name: "PieChartWidget" }
-            ],
-            editable: false
-        };
-    },
-    methods: {
-        save() {
-            console.log(JSON.stringify(this.layout));
-            this.editable = false;
+    export default {
+        created() {
+            // 请求数据
+            this.$axios.get("/platformFlow/getDashboard").then(res => {
+                this.tableList = res.data["今日商品销量排行"];
+                this.vipNum = res.data["merchant"];
+                this.goodsNum = res.data["rider"];
+                this.orderNum = res.data["order"];
+                this.userNum = res.data["user"];
+                this.LineChartInfo = res.data["月份新入会员统计"];
+            });
+        },
+        data() {
+            return {
+                layout: [
+                    {
+                        x: 0,
+                        y: 0,
+                        w: 3,
+                        h: 4,
+                        i: "0",
+                        name: "UserWidget",
+                        key: "userNum"
+                    },
+                    {
+                        x: 3,
+                        y: 0,
+                        w: 3,
+                        h: 4,
+                        i: "1",
+                        name: "VipUserWidget",
+                        key: "vipNum"
+                    },
+                    {
+                        x: 6,
+                        y: 0,
+                        w: 3,
+                        h: 4,
+                        i: "2",
+                        name: "GoodsWidget",
+                        key: "goodsNum"
+                    },
+                    {
+                        x: 9,
+                        y: 0,
+                        w: 3,
+                        h: 4,
+                        i: "3",
+                        name: "OrderWidget",
+                        key: "orderNum"
+                    },
+                    {
+                        x: 0,
+                        y: 4,
+                        w: 6,
+                        h: 12,
+                        i: "5",
+                        name: "LineChartWidget",
+                        key: "LineChartInfo"
+                    },
+                    // { x: 0, y: 10, w: 6, h: 6, i: "4", name: "BarChartWidget" },
+                    {
+                        x: 6,
+                        y: 4,
+                        w: 6,
+                        h: 12,
+                        i: "6",
+                        name: "OrderListWidget",
+                        key: "tableList"
+                    }
+                ],
+                editable: false,
+                tableList: [],
+                vipNum: 0,
+                goodsNum: 0,
+                userNum: 0,
+                orderNum: 0,
+                LineChartInfo: {}
+            };
+        },
+        methods: {
+            save() {
+                console.log(JSON.stringify(this.layout));
+                this.editable = false;
+            },
+            getValue(key) {
+                console.log(this.$data);
+                return this[key];
+            }
+        },
+        components: {
+            GridLayout,
+            GridItem,
+            UserWidget,
+            VipUserWidget,
+            OrderWidget,
+            GoodsWidget,
+            LineChartWidget,
+            BarChartWidget,
+            OrderListWidget
         }
-    },
-    components: {
-        GridLayout,
-        GridItem,
-        UserWidget,
-        LineChartWidget,
-        BarChartWidget,
-        PieChartWidget
-    }
-};
+    };
 </script>
 
 <style lang="less">
-.widget-wrapper {
-    display: flex;
-    flex-direction: column;
-    .el-card {
-        flex-grow: 1;
+    .widget-wrapper {
+        display: flex;
+        flex-direction: column;
+        .el-card {
+            flex-grow: 1;
+        }
     }
-}
 </style>

+ 52 - 45
src/main/vue/src/widgets/BarChartWidget.vue

@@ -1,67 +1,74 @@
 <template>
     <widget-card :bodyStyle="bodyStyle" ref="container">
+        <div slot="header" class="clearfix">
+            <span>数据统计</span>
+        </div>
         <canvas ref="chart" class="chart"></canvas>
     </widget-card>
 </template>
 <script>
-    import WidgetCard from './WidgetCard'
-    import VueCharts from 'vue-chartjs'
+import WidgetCard from "./WidgetCard";
+import VueCharts from "vue-chartjs";
 
-    export default {
-        data() {
-            return {
-                myChart: null,
-                bodyStyle: {
-                    display: 'flex',
-                    alignItems: 'center'
-                }
+export default {
+    data() {
+        return {
+            myChart: null,
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center"
             }
-        },
-        mounted() {
-            this.$refs.chart.width = this.$refs.container.$el.offsetWidth - 20;
-            this.$refs.chart.height = this.$refs.container.$el.offsetHeight - 20;
-            this.myChart = new Chart(this.$refs.chart.getContext('2d'), {
-                type: 'bar',
-                data: {
-                    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
-                    datasets: [{
-                        label: '# of Votes',
+        };
+    },
+    mounted() {
+        this.$refs.chart.width = this.$refs.container.$el.offsetWidth - 20;
+        this.$refs.chart.height = this.$refs.container.$el.offsetHeight - 90;
+        this.myChart = new Chart(this.$refs.chart.getContext("2d"), {
+            type: "bar",
+            data: {
+                labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
+                datasets: [
+                    {
+                        label: "# of Votes",
                         data: [12, 19, 3, 5, 2, 3],
                         backgroundColor: [
-                            'rgba(255, 99, 132, 0.2)',
-                            'rgba(54, 162, 235, 0.2)',
-                            'rgba(255, 206, 86, 0.2)',
-                            'rgba(75, 192, 192, 0.2)',
-                            'rgba(153, 102, 255, 0.2)',
-                            'rgba(255, 159, 64, 0.2)'
+                            "rgba(255, 99, 132, 0.2)",
+                            "rgba(54, 162, 235, 0.2)",
+                            "rgba(255, 206, 86, 0.2)",
+                            "rgba(75, 192, 192, 0.2)",
+                            "rgba(153, 102, 255, 0.2)",
+                            "rgba(255, 159, 64, 0.2)"
                         ],
                         borderColor: [
-                            'rgba(255,99,132,1)',
-                            'rgba(54, 162, 235, 1)',
-                            'rgba(255, 206, 86, 1)',
-                            'rgba(75, 192, 192, 1)',
-                            'rgba(153, 102, 255, 1)',
-                            'rgba(255, 159, 64, 1)'
+                            "rgba(255,99,132,1)",
+                            "rgba(54, 162, 235, 1)",
+                            "rgba(255, 206, 86, 1)",
+                            "rgba(75, 192, 192, 1)",
+                            "rgba(153, 102, 255, 1)",
+                            "rgba(255, 159, 64, 1)"
                         ],
                         borderWidth: 1
-                    }]
-                },
-                options: {
-                    maintainAspectRatio: false,
-                    scales: {
-                        yAxes: [{
+                    }
+                ]
+            },
+            options: {
+                maintainAspectRatio: false,
+                scales: {
+                    yAxes: [
+                        {
                             ticks: {
                                 beginAtZero: false
                             }
-                        }]
-                    }
+                        }
+                    ]
                 }
-            });
-        },
-        components: {
-            WidgetCard
-        }
+            }
+        });
+    },
+    components: {
+        WidgetCard
     }
+};
 </script>
 <style lang="less" scoped>
 </style>

+ 51 - 0
src/main/vue/src/widgets/GoodsWidget.vue

@@ -0,0 +1,51 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle">
+        <i class="fa-fw fas fa-shopping-bag fa-3x" style="color: #fff;"></i>
+        <div class="info">
+            <div class="num">{{ value||0 }}</div>
+            <div class="text">骑手总数量</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from "./WidgetCard";
+import { mapState } from "vuex";
+
+export default {
+    
+    props: ["value"],
+    data() {
+        return {
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center",
+                backgroundColor: "#239BF0"
+            },
+            number: 0
+        };
+    },
+    created() {
+    },
+    components: {
+        WidgetCard
+    },
+    computed: {
+        ...mapState(["userInfo"])
+    }
+};
+</script>
+<style lang="less" scoped>
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #fff;
+        font-size: 14px;
+    }
+    .num {
+        font-size: 44px;
+        color: #fff;
+        line-height: 62px;
+    }
+}
+</style>

+ 136 - 32
src/main/vue/src/widgets/LineChartWidget.vue

@@ -1,50 +1,154 @@
 <template>
     <widget-card :bodyStyle="bodyStyle" ref="container">
+        <div slot="header" class="clearfix">
+            <span>会员新增趋势</span>
+            <el-radio-group v-model="radio1" size="mini" @change="getStart">
+                <el-radio-button label="MONTH">按月显示</el-radio-button>
+                <el-radio-button label="DATE">按天显示</el-radio-button>=
+            </el-radio-group>
+        </div>
         <canvas ref="chart" class="chart"></canvas>
     </widget-card>
 </template>
 <script>
-    import WidgetCard from './WidgetCard'
-    import VueCharts from 'vue-chartjs'
+import WidgetCard from "./WidgetCard";
+import VueCharts from "vue-chartjs";
+import { format } from "date-fns";
 
-    export default {
-        data() {
-            return {
-                myChart: null,
-                bodyStyle: {
-                    display: 'flex',
-                    alignItems: 'center'
-                }
+export default {
+    props: ["value"],
+    data() {
+        return {
+            myChart: null,
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center"
+            },
+            radio1: "MONTH",
+            dataMap: new Map(),
+            labels: [],
+            colorMap: new Map([
+                [
+                    "线上会员",
+                    {
+                        mainColor: "#E4B100",
+                        startColor: "rgba(228,177,0,0.7)",
+                        stopColor: "rgba(228,177,0,0)"
+                    }
+                ],
+                [
+                    "线下会员",
+                    {
+                        mainColor: "#20a0ff",
+                        startColor: "rgba(32,160,255,0.7)",
+                        stopColor: "rgba(32,160,255,0)"
+                    }
+                ]
+            ])
+        };
+    },
+    mounted() {
+        this.$refs.chart.width = this.$refs.container.$el.offsetWidth - 20;
+        this.$refs.chart.height = this.$refs.container.$el.offsetHeight - 90;
+        this.getStart();
+    },
+    methods: {
+        labelFormat(value) {
+            if (this.radio1 === "MONTH") {
+                return value + "月";
+            } else {
+                return format(new Date(value), "MM-dd");
             }
         },
-        mounted() {
-            this.$refs.chart.width = this.$refs.container.$el.offsetWidth - 20;
-            this.$refs.chart.height = this.$refs.container.$el.offsetHeight - 20;
-            var gradient = this.$refs.chart.getContext('2d').createLinearGradient(0, 0, 0, 200);
+        getStart() {
+            this.getLineInfo().then(() => {
+                this.drawChart();
+            });
+        },
+        getLineInfo() {
+            return this.$http
+                .get("/summary/getVipSummary", {
+                    type: this.radio1,
+                    isShare: true
+                })
+                .then(res => {
+                    let map = new Map();
+                    Object.keys(res).forEach(item => {
+                        map.set(this.labelFormat(item), res[item]);
+                    });
+                    let list = Array.from(map);
+                    list.sort((a, b) => {
+                        return a[0].localeCompare(b[0]);
+                    });
+                    map = new Map(list);
+                    this.labels = Array.from(map.keys());
+                    this.dataMap.set("线上会员", Array.from(map.values()));
 
-            gradient.addColorStop(0, 'rgba(32,160,255,0.7)');
-            gradient.addColorStop(1, 'rgba(32,160,255,0)');
-            this.myChart = new Chart(this.$refs.chart.getContext('2d'), {
-                type: 'line',
+                    return this.$http.get("/summary/getVipSummary", {
+                        type: this.radio1,
+                        isShare: false
+                    });
+                })
+                .then(res => {
+                    let map = new Map();
+                    Object.keys(res).forEach(item => {
+                        map.set(this.labelFormat(item), res[item]);
+                    });
+                    let list = Array.from(map);
+                    list.sort((a, b) => {
+                        return a[0].localeCompare(b[0]);
+                    });
+                    map = new Map(list);
+                    this.labels = Array.from(map.keys());
+                    this.dataMap.set("线下会员", Array.from(map.values()));
+                });
+        },
+        drawChart() {
+            let datasets = [];
+            this.dataMap.forEach((value, key) => {
+                let color = this.colorMap.get(key);
+                let data = Array.from(value.values());
+                let gradient = this.$refs.chart
+                    .getContext("2d")
+                    .createLinearGradient(0, 0, 0, 500);
+
+                gradient.addColorStop(0, color.startColor);
+                gradient.addColorStop(1, color.stopColor);
+                datasets.push({
+                    label: key,
+                    backgroundColor: gradient,
+                    borderColor: color.mainColor,
+                    borderWidth: "1px",
+                    data: data
+                });
+            });
+
+            if (this.myChart) {
+                this.myChart.destroy();
+            }
+
+            this.myChart = new Chart(this.$refs.chart.getContext("2d"), {
+                type: "line",
                 data: {
-                    labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
-                    datasets: [
-                        {
-                            label: 'Data One',
-                            backgroundColor: gradient,
-                            borderColor: '#20a0ff',
-                            borderWidth: '1px',
-                            data: [40, 39, 10, 40, 39, 80, 40]
-                        }
-                    ]
+                    labels: this.labels,
+                    datasets: datasets
                 },
-                options: {responsive: true, maintainAspectRatio: false}
+                options: { responsive: true, maintainAspectRatio: false }
             });
-        },
-        components: {
-            WidgetCard
         }
+    },
+    components: {
+        WidgetCard
     }
+};
 </script>
 <style lang="less" scoped>
+.clearfix {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    height: 20px;
+    box-sizing: border-box;
+    padding: 0 !important;
+}
 </style>

+ 79 - 0
src/main/vue/src/widgets/OrderListWidget.vue

@@ -0,0 +1,79 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle" ref="container">
+        <div slot="header" class="clearfix">
+            <span>销量统计</span>
+            <el-radio-group v-model="radio1" size="mini" @change="getTable">
+                <el-radio-button label="DATE">当日</el-radio-button>
+                <el-radio-button label="WEEK">本周</el-radio-button>
+                <el-radio-button label="MONTH">本月</el-radio-button>
+            </el-radio-group>
+        </div>
+        <el-table
+            :data="tableData"
+            height="100%"
+            style="width: 100%;"
+            size="mini"
+            border
+        >
+            <el-table-column prop="name" label="商品名称" align="center">
+            </el-table-column>
+            <el-table-column prop="num" label="销量" align="center">
+            </el-table-column>
+        </el-table>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from "./WidgetCard";
+
+export default {
+    data() {
+        return {
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center"
+            },
+            height: 200,
+            radio1: "DATE",
+            data: {}
+        };
+    },
+    computed: {
+        tableData() {
+            var info = { ...this.data };
+            return Object.keys(info).map(item => {
+                return {
+                    name: item,
+                    num: info[item]
+                };
+            });
+        }
+    },
+    mounted() {
+        this.getTable();
+    },
+    methods: {
+        getTable() {
+            this.$http
+                .get("/summary/getGoods", {
+                    type: this.radio1
+                })
+                .then(res => {
+                    this.data = res;
+                });
+        }
+    },
+    components: {
+        WidgetCard
+    }
+};
+</script>
+<style lang="less" scoped>
+.clearfix {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    height: 20px;
+    box-sizing: border-box;
+    padding: 0 !important;
+}
+</style>

+ 49 - 0
src/main/vue/src/widgets/OrderWidget.vue

@@ -0,0 +1,49 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle">
+        <i class="fa-fw fas fa-file fa-3x" style="color: #fff;"></i>
+        <div class="info">
+            <div class="num">{{ value || 0 }}</div>
+            <div class="text">订单总数量</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from "./WidgetCard";
+import { mapState } from "vuex";
+
+export default {
+    props: ["value"],
+    data() {
+        return {
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center",
+                backgroundColor: "#08D99A"
+            },
+            number: 0
+        };
+    },
+    created() {},
+    components: {
+        WidgetCard
+    },
+    computed: {
+        ...mapState(["userInfo"])
+    }
+};
+</script>
+<style lang="less" scoped>
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #fff;
+        font-size: 14px;
+    }
+    .num {
+        font-size: 44px;
+        color: #fff;
+        line-height: 62px;
+    }
+}
+</style>

+ 37 - 28
src/main/vue/src/widgets/UserWidget.vue

@@ -1,41 +1,50 @@
 <template>
     <widget-card :bodyStyle="bodyStyle">
-        <i class="fa-fw fas fa-user fa-3x" style="color: #40c9c6;"></i>
+        <i class="fa-fw fas fa-user fa-3x" style="color: #fff;"></i>
         <div class="info">
-            <div class="text">User</div>
-            <div class="num">4,258</div>
+            <div class="num">{{ value||0 }}</div>
+            <div class="text">用户总数量</div>
         </div>
     </widget-card>
 </template>
 <script>
-    import WidgetCard from './WidgetCard'
+import WidgetCard from "./WidgetCard";
+import { mapState } from "vuex";
 
-    export default {
-        data() {
-            return {
-                bodyStyle: {
-                    display: 'flex',
-                    alignItems: 'center'
-                }
-            }
-        },
-        components: {
-            WidgetCard
-        }
+export default {
+    props: ["value"],
+    data() {
+        return {
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center",
+                backgroundColor: "#E4B100"
+            },
+            number: 0
+        };
+    },
+    created() {
+    },
+    components: {
+        WidgetCard
+    },
+    computed: {
+        ...mapState(["userInfo"])
     }
+};
 </script>
 <style lang="less" scoped>
-    .info {
-        flex-grow: 1;
-        text-align: right;
-        .text {
-            color: #999;
-            font-size: 16px;
-            margin-bottom: 12px;
-        }
-        .num {
-            font-size: 20px;
-            color: #333;
-        }
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #fff;
+        font-size: 14px;
     }
+    .num {
+        font-size: 44px;
+        color: #fff;
+        line-height: 62px;
+    }
+}
 </style>

+ 50 - 0
src/main/vue/src/widgets/VipUserWidget.vue

@@ -0,0 +1,50 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle">
+        <i class="fa-fw fas fa-user fa-3x" style="color: #fff;"></i>
+        <div class="info">
+            <div class="num">{{ value||0 }}</div>
+            <div class="text">商家总数量</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from "./WidgetCard";
+import { mapState } from "vuex";
+
+export default {
+     props: ["value"],
+    data() {
+        return {
+            bodyStyle: {
+                display: "flex",
+                alignItems: "center",
+                backgroundColor: "#F06C23"
+            },
+            number: 0
+        };
+    },
+    created() {
+    },
+    components: {
+        WidgetCard
+    },
+    computed: {
+        ...mapState(["userInfo"])
+    }
+};
+</script>
+<style lang="less" scoped>
+.info {
+    flex-grow: 1;
+    text-align: right;
+    .text {
+        color: #fff;
+        font-size: 14px;
+    }
+    .num {
+        font-size: 44px;
+        color: #fff;
+        line-height: 62px;
+    }
+}
+</style>

+ 1 - 1
src/main/vue/src/widgets/WidgetCard.vue

@@ -14,7 +14,7 @@
         data() {
             return {
                 mBodyStyle: {
-                    flexGrow: 1
+                    flexGrow: 1,
                 }
             }
         }

+ 32 - 0
src/test/java/com/izouma/dingdong/contorller/AddressControllerTest.java

@@ -0,0 +1,32 @@
+package com.izouma.dingdong.contorller;
+
+import com.izouma.dingdong.domain.user.Address;
+import com.izouma.dingdong.web.user.AddressController;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class AddressControllerTest {
+    @Autowired
+    private AddressController addressController;
+
+    @Test
+    public void test(){
+        Address address = Address.builder()
+                .addressName("江苏省南京市建邺区嘉陵江东街与广聚路交汇处南京国家广告产业园")
+                .enabled(true)
+                .userId(188L)
+                .phone("1231")
+                .name("阿不")
+                .latitude(31.98161100)
+                .longitude(118.73562700)
+                .isDefault(false)
+                .build();
+        addressController.save(address);
+    }
+
+}