licailing 5 лет назад
Родитель
Сommit
e921171fd3

+ 10 - 13
src/main/java/com/izouma/jiashanxia/service/OrderInfoService.java

@@ -6,7 +6,6 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.izouma.jiashanxia.domain.*;
 import com.izouma.jiashanxia.domain.Package;
-import com.izouma.jiashanxia.dto.GoodsVO;
 import com.izouma.jiashanxia.dto.OrderInfoVO;
 import com.izouma.jiashanxia.dto.PageQuery;
 import com.izouma.jiashanxia.enums.OrderInfoStatus;
@@ -17,7 +16,6 @@ import com.izouma.jiashanxia.repo.*;
 import com.izouma.jiashanxia.utils.JpaUtils;
 import lombok.AllArgsConstructor;
 import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
 
@@ -45,7 +43,6 @@ public class OrderInfoService {
     private UserPackageService   userPackageService;
     private CompanyRepo          companyRepo;
     private WithdrawService      withdrawService;
-    private GoodsInfoRepo        goodsInfoRepo;
 
     public Page<OrderInfo> all(PageQuery pageQuery) {
         return orderInfoRepo.findAll(JpaUtils.toSpecification(pageQuery, OrderInfo.class), JpaUtils.toPageRequest(pageQuery));
@@ -58,11 +55,6 @@ public class OrderInfoService {
         return orderInfoRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = JpaUtils.toPredicates(pageQuery, OrderInfo.class, root, criteriaQuery, criteriaBuilder);
             if (StrUtil.isNotEmpty(pageQuery.getSearch())) {
-               /* List<Predicate> or = new ArrayList<>();
-                or.add(and.get(and.size() - 1));
-                and.remove(and.get(and.size() - 1));
-                or.add(criteriaBuilder.like(root.join("user").get("nickname"), "%" + pageQuery.getSearch() + "%"));
-                and.add(criteriaBuilder.or(or.toArray(new Predicate[0])));*/
                 withdrawService.getNickname(pageQuery.getSearch(), and, root, criteriaBuilder);
             }
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
@@ -103,12 +95,19 @@ public class OrderInfoService {
 
         // 套餐内商品
         List<PackageGoods> setGoodsList = packageGoodsRepo.findAllByPackageId(order.getPackageId());
-        // 加入套餐商品
+        // 用户
         Long userId = order.getUserId();
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+        // 设置用户为vip
+        if (!user.getIsVip()) {
+            user.setIsVip(true);
+            userRepo.save(user);
+        }
+        // 加入套餐商品
         userPackageService.joinUserPackage(userId, setGoodsList);
 
-        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
-        if (user.getParent() != null) {
+        // 用户id和上级id相同
+        if (user.getParent() != null && !userId.equals(user.getParent())) {
             // 上级分销
             this.distribution(userId, user.getParent(), transactionId);
         }
@@ -214,7 +213,6 @@ public class OrderInfoService {
             }
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
         }), pageable).map(this::toVo);
-//        return new PageImpl<>(this.toVO(all), pageable, all.size());
     }
 
     public OrderInfoVO toVo(OrderInfo orderInfo) {
@@ -249,7 +247,6 @@ public class OrderInfoService {
 //                        .build());
 //            });
             vo.setGoods(packageGoods);
-
             orderInfoVOS.add(vo);
         });
         return orderInfoVOS;

+ 10 - 6
src/main/java/com/izouma/jiashanxia/service/PackageService.java

@@ -41,9 +41,9 @@ public class PackageService {
     /*
     开通团队套餐
      */
-    public void openTeamSet(Long userId, Long setMealId) {
+    public void openTeamSet(Long userId, Long packageId) {
 
-        Package set = packageRepo.findById(setMealId).orElseThrow(new BusinessException("无套餐"));
+        Package set = packageRepo.findById(packageId).orElseThrow(new BusinessException("无套餐"));
         if (!SetType.TEAM.equals(set.getType())) {
             throw new BusinessException("不是团队套餐");
         }
@@ -52,7 +52,7 @@ public class PackageService {
         String localTime = df.format(LocalDateTime.now());
         String num = String.format("%05d", orderInfoRepo.orderNum() + 1);
         orderInfoRepo.save(OrderInfo.builder()
-                .packageId(setMealId)
+                .packageId(packageId)
                 .userId(userId)
                 .payMethod(PayMethod.OFFLINE)
                 .name(set.getName())
@@ -60,20 +60,22 @@ public class PackageService {
                 .status(OrderInfoStatus.OFFLINE_PAID)
                 .build());
 
+        // 用户
+        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
         // 加入套餐商品
-        List<PackageGoods> setGoodsList = packageGoodsRepo.findAllByPackageId(setMealId);
+        List<PackageGoods> setGoodsList = packageGoodsRepo.findAllByPackageId(packageId);
         userPackageService.joinUserPackage(userId, setGoodsList);
 
         // 新建公司
         Company company = companyRepo.findByUserId(userId);
-        if (ObjectUtil.isNotEmpty(company)) {
+        if (ObjectUtil.isEmpty(company)) {
             company = companyRepo.save(Company.builder()
                     .userId(userId)
                     .name("企业")
                     .amount(BigDecimal.ZERO)
                     .build());
         }
-        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+
         // 团队创始人
         Set<Authority> authorities = user.getAuthorities();
         if (!authorities.contains(Authority.get(AuthorityName.ROLE_CREATOR))) {
@@ -81,6 +83,8 @@ public class PackageService {
             user.setTeamFounder(true);
             authorities.add(Authority.get(AuthorityName.ROLE_CREATOR));
             user.setAuthorities(authorities);
+            user.setIsVip(true);
+            userRepo.save(user);
         }
     }
 

+ 1 - 7
src/main/java/com/izouma/jiashanxia/service/UserPackageService.java

@@ -28,7 +28,6 @@ public class UserPackageService {
 
     private UserPackageRepo     userPackageRepo;
     private UserPackageFlowRepo userPackageFlowRepo;
-    private UserRepo            userRepo;
 
     public Page<UserPackage> all(PageQuery pageQuery) {
         return userPackageRepo.findAll(JpaUtils.toSpecification(pageQuery, UserPackage.class), JpaUtils.toPageRequest(pageQuery));
@@ -62,12 +61,7 @@ public class UserPackageService {
             }
             userPackageRepo.save(goods);
         });
-        // 设置用户为vip
-        User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
-        if (!user.getIsVip()) {
-            user.setIsVip(true);
-            userRepo.save(user);
-        }
+
         // 记录套餐流水
         List<GoodsDTO> goodsDTOS = JSONObject.parseArray(JSONObject.toJSONString(packageGoodsList), GoodsDTO.class);
         userPackageFlowRepo.save(UserPackageFlow.builder()

+ 13 - 1
src/main/java/com/izouma/jiashanxia/service/UserService.java

@@ -62,6 +62,9 @@ public class UserService {
     public User create(UserRegister userRegister) {
         User user = new User();
         BeanUtils.copyProperties(userRegister, user);
+        user.setIsVip(false);
+        user.setWxAuthorized(false);
+        user.setAmount(BigDecimal.ZERO);
         if (StringUtils.isNotBlank(userRegister.getPassword())) {
             user.setPassword(new BCryptPasswordEncoder().encode(userRegister.getPassword()));
         }
@@ -234,6 +237,7 @@ public class UserService {
 
     /*
     我的推广
+    移除员工:推广列表下员工的推广就会没有
     */
     public Page<User> myPromotion(PageQuery pageQuery, Long userId) {
         User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
@@ -259,10 +263,18 @@ public class UserService {
         Set<Authority> authorities = user.getAuthorities();
         // 管理员返回所有
         if (authorities.contains(Authority.get(AuthorityName.ROLE_ADMIN))) {
+            Map<String, Object> query = pageQuery.getQuery();
+            Object companyId = query.get("companyId");
             return userRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
                 List<Predicate> and = JpaUtils
                         .toPredicates(pageQuery, User.class, root, criteriaQuery, criteriaBuilder);
-                and.add(root.get("companyId").isNotNull());
+                if (ObjectUtil.isNotEmpty(companyId)) {
+                    long id = Long.parseLong(String.valueOf(companyId));
+                    and.add(criteriaBuilder.equal(root.get("companyId"), id));
+                } else {
+                    and.add(root.get("companyId").isNotNull());
+                }
+
                 return criteriaBuilder.and(and.toArray(new Predicate[0]));
             }), JpaUtils.toPageRequest(pageQuery));
         }

+ 0 - 1
src/main/java/com/izouma/jiashanxia/web/CompanyController.java

@@ -37,7 +37,6 @@ public class CompanyController extends BaseController {
         return companyRepo.save(record);
     }
 
-
     @PreAuthorize("hasAnyRole('ADMIN','CREATOR')")
     @PostMapping("/all")
     public Page<Company> all(@RequestBody PageQuery pageQuery) {

+ 8 - 0
src/main/java/com/izouma/jiashanxia/web/StatisticController.java

@@ -1,5 +1,6 @@
 package com.izouma.jiashanxia.web;
 
+import com.izouma.jiashanxia.dto.StatisticDTO;
 import com.izouma.jiashanxia.service.StatisticService;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -7,6 +8,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
 import java.util.Map;
 
 @AllArgsConstructor
@@ -20,4 +22,10 @@ public class StatisticController {
     public Map<String, Object> dataOverview() {
         return statisticService.dataOverview();
     }
+
+    @ApiOperation("日销售额")
+    @GetMapping("/dayAdd")
+    public List<StatisticDTO> dayAdd(Integer day) {
+        return statisticService.dayData(day);
+    }
 }

+ 13 - 0
src/main/vue/src/components/BarChart.vue

@@ -0,0 +1,13 @@
+<script>
+import { Bar, mixins } from 'vue-chartjs';
+const { reactiveProp } = mixins;
+export default {
+    name: 'stat',
+    extends: Bar,
+    mixins: [reactiveProp],
+    mounted() {
+        this.renderChart(this.chartData, { responsive: true, maintainAspectRatio: false });
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 13 - 0
src/main/vue/src/components/LineChart.vue

@@ -0,0 +1,13 @@
+<script>
+import { Line, mixins } from 'vue-chartjs';
+const { reactiveProp } = mixins;
+export default {
+    name: 'stat',
+    extends: Line,
+    mixins: [reactiveProp],
+    mounted() {
+        this.renderChart(this.chartData, { responsive: true, maintainAspectRatio: false });
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 0 - 2
src/main/vue/src/components/PackageEdit.vue

@@ -160,14 +160,12 @@ export default {
         handleClose(tag) {
             this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
         },
-
         showInput() {
             this.inputVisible = true;
             this.$nextTick(_ => {
                 this.$refs.saveTagInput.$refs.input.focus();
             });
         },
-
         handleInputConfirm() {
             let inputValue = this.inputValue;
             if (inputValue) {

+ 1 - 1
src/main/vue/src/views/CommissionRecordList.vue

@@ -33,7 +33,7 @@
             :height="tableHeight"
         >
             <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
-            <el-table-column prop="id" label="ID" width="100"> </el-table-column>
+            <el-table-column prop="id" label="ID" width="80"> </el-table-column>
             <el-table-column prop="user.nickname" label="昵称"> </el-table-column>
             <el-table-column prop="transactionType" label="交易类型" :formatter="transactionTypeFormatter">
             </el-table-column>

+ 20 - 14
src/main/vue/src/views/Dashboard.vue

@@ -22,7 +22,7 @@
                 :i="item.i"
                 :key="item.i"
             >
-                <component :is="item.name"></component>
+                <component :is="item.name" :value="$data[item.key]"></component>
             </grid-item>
         </grid-layout>
         <el-button v-if="editable" @click="save">保存</el-button>
@@ -34,9 +34,10 @@
 import { GridLayout, GridItem } from 'vue-grid-layout';
 import UserWidget from '../widgets/UserWidget';
 import OrderWidget from '../widgets/OrderWidget';
-import LineChartWidget from '../widgets/LineChartWidget';
-import BarChartWidget from '../widgets/BarChartWidget';
-import PieChartWidget from '../widgets/PieChartWidget';
+import CompanyWidget from '../widgets/CompanyWidget';
+import FeeWidget from '../widgets/FeeWidget';
+import RecentSales from '../widgets/RecentSales';
+import RecentOrder from '../widgets/RecentOrder';
 
 export default {
     created() {
@@ -50,15 +51,19 @@ export default {
     data() {
         return {
             layout: [
-                { x: 0, y: 0, w: 3, h: 4, i: '0', name: 'UserWidget', key: 'user' },
-                { x: 3, y: 0, w: 3, h: 4, i: '1', name: 'OrderWidget', key: 'company' },
-                { x: 6, y: 0, w: 3, h: 4, i: '2', name: 'UserWidget', key: 'order' },
-                { x: 9, y: 0, w: 3, h: 4, i: '3', name: 'UserWidget', key: 'fee' },
-                { x: 0, y: 4, w: 12, h: 6, i: '4', name: 'BarChartWidget' },
-                { x: 0, y: 10, w: 12, h: 6, i: '5', name: 'LineChartWidget' }
+                { x: 0, y: 0, w: 3, h: 3, i: '0', name: 'UserWidget', key: 'user' },
+                { x: 3, y: 0, w: 3, h: 3, i: '1', name: 'CompanyWidget', key: 'company' },
+                { x: 6, y: 0, w: 3, h: 3, i: '2', name: 'OrderWidget', key: 'order' },
+                { x: 9, y: 0, w: 3, h: 3, i: '3', name: 'FeeWidget', key: 'fee' },
+                { x: 0, y: 4, w: 12, h: 12, i: '4', name: 'RecentOrder' },
+                { x: 0, y: 10, w: 12, h: 12, i: '5', name: 'RecentSales' }
                 /*{ x: 6, y: 4, w: 6, h: 12, i: '6', name: 'PieChartWidget' }*/
             ],
-            editable: false
+            editable: false,
+            user: 0,
+            company: 0,
+            order: 0,
+            fee: 0
         };
     },
     methods: {
@@ -72,9 +77,10 @@ export default {
         GridItem,
         UserWidget,
         OrderWidget,
-        LineChartWidget,
-        BarChartWidget,
-        PieChartWidget
+        FeeWidget,
+        CompanyWidget,
+        RecentSales,
+        RecentOrder
     }
 };
 </script>

+ 57 - 8
src/main/vue/src/views/EmployeeList.vue

@@ -11,6 +11,9 @@
                 class="filter-item"
                 >导出EXCEL
             </el-button>
+            <el-select v-model="companyId" placeholder="请选择公司" clearable filterable @change="getData">
+                <el-option v-for="item in companies" :key="item.id" :value="item.id" :label="item.name"></el-option>
+            </el-select>
         </div>
         <el-table
             :data="tableData"
@@ -24,9 +27,9 @@
         >
             <el-table-column v-if="multipleMode" align="center" type="selection" width="50"> </el-table-column>
             <!--<el-table-column prop="id" label="ID" width="100"> </el-table-column>-->
-            <el-table-column prop="username" label="用户名" min-width="100"> </el-table-column>
-            <el-table-column prop="nickname" label="昵称" min-width="100"> </el-table-column>
-            <el-table-column label="头像" min-width="100">
+            <el-table-column prop="username" label="用户名" min-width="80"> </el-table-column>
+            <el-table-column prop="nickname" label="昵称" min-width="80"> </el-table-column>
+            <el-table-column label="头像" min-width="80">
                 <template slot-scope="{ row }">
                     <el-image
                         style="width: 30px; height: 30px;"
@@ -43,11 +46,19 @@
                 </template>
             </el-table-column>
             <el-table-column prop="company.name" label="企业名称" show-overflow-tooltip> </el-table-column>
-            <!--<el-table-column label="操作" align="center" fixed="right">
+            <el-table-column label="操作" align="center" fixed="right">
                 <template slot-scope="{ row }">
-                    <el-button @click="editRow(row)" type="primary" size="mini" plain>编辑</el-button>
+                    <el-button
+                        @click="remove(row)"
+                        type="warning"
+                        size="mini"
+                        plain
+                        :loading="$store.state.fetchingData"
+                    >
+                        移除
+                    </el-button>
                 </template>
-            </el-table-column>-->
+            </el-table-column>
         </el-table>
         <div class="pagination-wrapper">
             <el-pagination
@@ -74,9 +85,21 @@ export default {
             multipleMode: false,
             search: '',
             url: '/user/myEmployee',
-            downloading: false
+            downloading: false,
+            companyId: '',
+            companies: []
         };
     },
+    created() {
+        this.$http
+            .get('/company/allList')
+            .then(res => {
+                this.companies = res;
+            })
+            .catch(e => {
+                console.log(e);
+            });
+    },
     computed: {
         ...mapState(['userInfo']),
         selection() {
@@ -85,7 +108,12 @@ export default {
     },
     methods: {
         beforeGetData() {
-            return { search: this.search };
+            return {
+                search: this.search,
+                query: {
+                    companyId: this.companyId
+                }
+            };
         },
         toggleMultipleMode(multipleMode) {
             this.multipleMode = multipleMode;
@@ -138,6 +166,27 @@ export default {
         },
         operation2() {
             this.$message('操作2');
+        },
+        remove(row) {
+            this.$alert('确认移除么?', '提示', { type: 'primary' })
+                .then(() => {
+                    return this.$http.post('/company/removeEmp', {
+                        userId: row.id,
+                        companyId: row.companyId
+                    });
+                })
+                .then(() => {
+                    this.$message.success('移除成功');
+                    history.go(0);
+                })
+                .catch(action => {
+                    if (action === 'cancel') {
+                        this.$message.info('移除取消');
+                    } else {
+                        this.$message.error('移除失败');
+                        console.log(action);
+                    }
+                });
         }
     }
 };

+ 2 - 3
src/main/vue/src/views/PackageGoodsEdit.vue

@@ -9,11 +9,10 @@
             size="small"
             style="max-width: 500px;"
         >
-            <el-form-item prop="setId" label="setId">
-                <el-input-number type="number" v-model="formData.setId"></el-input-number>
+            <el-form-item prop="套餐" label="packageId">
+                <el-input-number type="number" v-model="formData.packageId"></el-input-number>
             </el-form-item>
             <el-form-item prop="goodsInfoId" label="名称">
-                <!--<el-input v-model="formData.name"></el-input>-->
                 <el-select v-model="formData.goodsInfoId" filterable @change="optionChange">
                     <el-option v-for="item in goodsList" :key="item.id" :label="item.name" :value="item.id"></el-option>
                 </el-select>

+ 13 - 6
src/main/vue/src/views/UserEdit.vue

@@ -37,10 +37,14 @@
                     <el-option v-for="item in companies" :key="item.id" :value="item.id" :label="item.name">
                     </el-option>
                 </el-select>
-                <el-button style="margin-left: 20px" @click="showDialog = true" v-if="!formData.teamFounder">
+                <el-button
+                    style="margin-left: 20px"
+                    @click="showDialog = true"
+                    v-if="!formData.teamFounder && id !== 0"
+                >
                     新建团队
                 </el-button>
-                <el-button @click="showEmployee" v-else>
+                <el-button @click="showEmployee" v-if="formData.teamFounder">
                     我的团队
                 </el-button>
             </el-form-item>
@@ -67,9 +71,9 @@
 
         <el-dialog :visible.sync="showDialog" width="400px">
             <el-form label-width="80px" label-position="right" size="small">
-                <el-form-item prop="setMealId" label="选择套餐">
-                    <el-select v-model="setMealId">
-                        <el-option v-for="item in setMeals" :key="item.id" :value="item.id" :label="item.name" />
+                <el-form-item prop="packageId" label="选择套餐">
+                    <el-select v-model="packageId">
+                        <el-option v-for="item in packages" :key="item.id" :value="item.id" :label="item.name" />
                     </el-select>
                 </el-form-item>
             </el-form>
@@ -89,6 +93,7 @@
 export default {
     created() {
         if (this.$route.query.id) {
+            this.id = this.$route.query.id;
             this.$http
                 .get(`/user/get/${this.$route.query.id}`)
                 .then(res => {
@@ -160,7 +165,8 @@ export default {
             packageId: '',
             showDialog: false,
             userDialog: false,
-            employee: []
+            employee: [],
+            id: 0
         };
     },
     methods: {
@@ -242,6 +248,7 @@ export default {
                     this.$message.success('创建成功');
                     this.showDialog = false;
                     this.saving = false;
+                    this.getData();
                 })
                 .catch(e => {
                     if (e !== 'cancel') {

+ 42 - 0
src/main/vue/src/widgets/CompanyWidget.vue

@@ -0,0 +1,42 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle">
+        <i class="fa-fw fas fa-users fa-3x" style="color: #40c9c6;"></i>
+        <div class="info">
+            <div class="text">企业</div>
+            <div class="num">{{ value || 0 }}</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+
+export default {
+    props: ['value'],
+    data() {
+        return {
+            bodyStyle: {
+                display: 'flex',
+                alignItems: 'center'
+            }
+        };
+    },
+    components: {
+        WidgetCard
+    }
+};
+</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;
+    }
+}
+</style>

+ 42 - 0
src/main/vue/src/widgets/FeeWidget.vue

@@ -0,0 +1,42 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle">
+        <i class="fa-fw fas fa-comments-dollar fa-3x" style="color: #40c9c6;"></i>
+        <div class="info">
+            <div class="text">收益</div>
+            <div class="num">{{ value || 0 }}</div>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+
+export default {
+    props: ['value'],
+    data() {
+        return {
+            bodyStyle: {
+                display: 'flex',
+                alignItems: 'center'
+            }
+        };
+    },
+    components: {
+        WidgetCard
+    }
+};
+</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;
+    }
+}
+</style>

+ 2 - 1
src/main/vue/src/widgets/LineChartWidget.vue

@@ -14,7 +14,8 @@ export default {
             bodyStyle: {
                 display: 'flex',
                 alignItems: 'center'
-            }
+            },
+            recentDays: 7
         };
     },
     mounted() {

+ 66 - 0
src/main/vue/src/widgets/RecentOrder.vue

@@ -0,0 +1,66 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle" ref="container">
+        <div style="width:100%;min-height:80px;" :loading="loading">
+            <div style="margin-bottom:5px">
+                <el-radio-group v-model="recentDays" size="mini" @change="getData">
+                    <el-radio-button label="7">近7天</el-radio-button>
+                    <el-radio-button label="30">近30天</el-radio-button>
+                </el-radio-group>
+            </div>
+            <bar-chart :chart-data="chartData" v-if="chartData"> </bar-chart>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+import BarChart from '../components/BarChart';
+
+export default {
+    data() {
+        return {
+            bodyStyle: {
+                alignItems: 'center'
+            },
+            recentDays: 7,
+            chartData: null,
+            loading: false
+        };
+    },
+    created() {
+        this.getData();
+    },
+    methods: {
+        getData() {
+            this.loading = true;
+            this.$http
+                .get('/statistic/dayAdd', {
+                    day: this.recentDays
+                })
+                .then(res => {
+                    this.loading = false;
+                    this.chartData = {
+                        labels: res.map(i => i.date),
+                        datasets: [
+                            {
+                                label: '销售额',
+                                data: res.map(i => i.dayOrder),
+                                backgroundColor: ['rgba(54, 162, 235, 0.2)'],
+                                borderColor: ['rgba(54, 162, 235, 1)'],
+                                borderWidth: 1
+                            }
+                        ]
+                    };
+                })
+                .catch(e => {
+                    this.loading = false;
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    components: {
+        WidgetCard,
+        BarChart
+    }
+};
+</script>
+<style lang="less" scoped></style>

+ 67 - 0
src/main/vue/src/widgets/RecentSales.vue

@@ -0,0 +1,67 @@
+<template>
+    <widget-card :bodyStyle="bodyStyle" ref="container">
+        <div style="width:100%;min-height:80px;" :loading="loading">
+            <div style="margin-bottom:5px">
+                <el-radio-group v-model="recentDays" size="mini" @change="getData">
+                    <el-radio-button label="7">近7天</el-radio-button>
+                    <el-radio-button label="30">近30天</el-radio-button>
+                </el-radio-group>
+            </div>
+            <line-chart :chart-data="chartData" v-if="chartData"> </line-chart>
+        </div>
+    </widget-card>
+</template>
+<script>
+import WidgetCard from './WidgetCard';
+import LineChart from '../components/LineChart';
+
+export default {
+    data() {
+        return {
+            bodyStyle: {
+                display: 'flex',
+                alignItems: 'center'
+            },
+            recentDays: 7,
+            chartData: null,
+            loading: false
+        };
+    },
+    created() {
+        this.getData();
+    },
+    methods: {
+        getData() {
+            this.loading = true;
+            this.$http
+                .get('/statistic/dayAdd', {
+                    day: this.recentDays
+                })
+                .then(res => {
+                    this.loading = false;
+                    this.chartData = {
+                        labels: res.map(i => i.date),
+                        datasets: [
+                            {
+                                label: '销售额',
+                                data: res.map(i => i.dayFee),
+                                backgroundColor: ['rgba(54, 162, 235, 0.2)'],
+                                borderColor: ['rgba(54, 162, 235, 1)'],
+                                borderWidth: 1
+                            }
+                        ]
+                    };
+                })
+                .catch(e => {
+                    this.loading = false;
+                    this.$message.error(e.error);
+                });
+        }
+    },
+    components: {
+        WidgetCard,
+        LineChart
+    }
+};
+</script>
+<style lang="less" scoped></style>