licailing 5 سال پیش
والد
کامیت
c8eca7813d

+ 9 - 0
src/main/java/com/izouma/jiashanxia/domain/Package.java

@@ -80,10 +80,19 @@ public class Package extends BaseEntity {
     @ApiModelProperty(value = "间推奖励比例")
     private BigDecimal personalRatio1;
 
+    @ApiModelProperty(value = "大团长推大团长比例")
+    private BigDecimal personalRatio2;
+
     @ApiModelProperty(value = "可获得的优惠券id")
     @Convert(converter = LongArrayConverter.class)
     private List<Long> couponId;
 
+    @ApiModelProperty(value = "推广海报")
+    private String poster;
+
+    @ApiModelProperty(value = "小的海报")
+    private String smallPoster;
+
     @Transient
     private String attractionsName;
 

+ 1 - 0
src/main/java/com/izouma/jiashanxia/enums/AuthorityName.java

@@ -5,6 +5,7 @@ public enum AuthorityName {
     ROLE_DEV("开发者"),
     ROLE_WRITER("核销者"),
     ROLE_CREATOR("创建者"),
+    ROLE_EXPERT("团长"),
     ROLE_ADMIN("管理员");
     private final String description;
 

+ 1 - 0
src/main/java/com/izouma/jiashanxia/repo/UserRepo.java

@@ -54,4 +54,5 @@ public interface UserRepo extends JpaRepository<User, Long>, JpaSpecificationExe
 
     // 按管理员搜索
     List<User> findAllByTeamFounderTrueAndDelFalse();
+
 }

+ 2 - 1
src/main/java/com/izouma/jiashanxia/service/CompanyService.java

@@ -154,8 +154,9 @@ public class CompanyService {
         User user = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
         Set<Authority> authorities = user.getAuthorities();
         if (!authorities.contains(creator) || !user.getTeamFounder()) {
+//        if (!authorities.contains(creator)) {
             authorities.add(creator);
-            user.setTeamFounder(true);
+//            user.setTeamFounder(true);
             user.setCompanyId(companyId);
             userRepo.save(user);
         }

+ 7 - 4
src/main/java/com/izouma/jiashanxia/service/OrderInfoService.java

@@ -328,7 +328,7 @@ public class OrderInfoService {
         // 团长或大团长
         User user = null;
         // 上级为空或上级为不为普通用户停止
-        Long parent1 = user.getParent();
+
         while (ObjectUtil.isNotNull(parentUserId)) {
             user = userRepo.findById(parentUserId).orElseThrow(new BusinessException("无用户"));
             // 如果是团长/大团长 拿直推钱
@@ -348,11 +348,14 @@ public class OrderInfoService {
                 commissionRecordRepo.save(commissionRecord);
                 break;
             }
-            parentUserId = parent1;
+            parentUserId = user.getParent();
         }
-
         // 存在团长或大团长+团长或大团长上级不为空
-        if (ObjectUtil.isNotNull(user) && ObjectUtil.isNotNull(parent1)) {
+        if (ObjectUtil.isNotNull(user)) {
+            Long parent1 = user.getParent();
+            if (ObjectUtil.isNull(parent1)) {
+                return;
+            }
             // 控制间退找几级
             int i = 2;
             if (Member.EXPERT.equals(user.getMember())) {

+ 3 - 2
src/main/java/com/izouma/jiashanxia/service/StatisticService.java

@@ -27,7 +27,8 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class StatisticService {
     private final UserRepo             userRepo;
-    private final CompanyRepo          companyRepo;
+    //    private final CompanyRepo          companyRepo;
+    private final AttractionsRepo      attractionsRepo;
     private final OrderInfoRepo        orderInfoRepo;
     private final WxFeeRepo            wxFeeRepo;
     private final WithdrawRepo         withdrawRepo;
@@ -39,7 +40,7 @@ public class StatisticService {
      */
     public Map<String, Object> dataOverview() {
         long user = userRepo.count();
-        long company = companyRepo.count();
+        long company = attractionsRepo.count();
         long order = orderInfoRepo.countByStatus(OrderInfoStatus.PAID);
         BigDecimal fee = wxFeeRepo.sumByAmount();
 

+ 23 - 11
src/main/java/com/izouma/jiashanxia/service/UserService.java

@@ -137,7 +137,8 @@ public class UserService {
             if (userInfo != null) {
                 // 插入上级
                 if (ObjectUtil.isNotNull(parent)) {
-                    if (this.getParent(parent, userInfo)) {
+//                    if (this.getParent(parent, userInfo)) {
+                    if (ObjectUtil.isNull(userInfo.getParent())) {
                         userInfo.setParent(parent);
                     }
                     // 邀请成为创客
@@ -263,7 +264,7 @@ public class UserService {
         User user = userRepo.findById(SecurityUtils.getAuthenticatedUser().getId())
                 .orElseThrow(new BusinessException("用户不存在"));
         user.setPhone(phoneNoInfo.getPhoneNumber());
-        if (StrUtil.isNotBlank(phoneNoInfo.getPhoneNumber())){
+        if (StrUtil.isNotBlank(phoneNoInfo.getPhoneNumber())) {
             user.setUsername(phoneNoInfo.getPhoneNumber());
         }
         user = userRepo.save(user);
@@ -307,6 +308,7 @@ public class UserService {
         Set<User> users = new HashSet<>();
         // 如果是企业创始人,查出下级所有推广
         if (user.getTeamFounder()) {
+//        if (user.getAuthorities().contains(Authority.get(AuthorityName.ROLE_CREATOR))) {
             List<User> employees = userRepo.findAllByCompanyIdAndDelFalse(user.getCompanyId());
             List<Long> collect = employees.stream().map(User::getId).collect(Collectors.toList());
             users.addAll(userRepo.findAllByParentInAndDelFalse(collect));
@@ -321,6 +323,7 @@ public class UserService {
     */
     public Page<PromotionDTO> myPromotion(PageQuery pageQuery, Long userId) {
         User parent = userRepo.findById(userId).orElseThrow(new BusinessException("无用户"));
+//        if (parent.getAuthorities().contains(Authority.get(AuthorityName.ROLE_CREATOR))) {
         if (parent.getTeamFounder()) {
             List<User> employees = userRepo.findAllByCompanyIdAndDelFalse(parent.getCompanyId());
             Map<Long, User> userMap = employees.stream().collect(Collectors.toMap(User::getId, user -> user));
@@ -425,6 +428,7 @@ public class UserService {
 
     /*
     捞所有下级id
+    互为上级死循环
      */
     public List<Long> childrenId(Long userId) {
         List<Long> users = userRepo.findIdByParentAndDelFalse(userId);
@@ -439,10 +443,10 @@ public class UserService {
     /*
     下级
      */
-    public Page<User> children(PageQuery pageQuery) {
+    public Page<UserDTO> children(PageQuery pageQuery) {
         Map<String, Object> query = pageQuery.getQuery();
 
-        Object userId = query.get("userId");
+        Object userId = query.get("parent");
         Long parent = 0L;
         if (userId instanceof String) {
             String of = String.valueOf(userId);
@@ -452,21 +456,29 @@ public class UserService {
             Integer of = (Integer) userId;
             parent = Long.valueOf(of);
         }
+        if (userId instanceof Long) {
+            parent = (Long) userId;
+        }
 
-        List<Long> users = userRepo.findIdByParentAndDelFalse(parent);
-
-        List<Long> children = new ArrayList<>(users);
-        while (CollUtil.isNotEmpty(users)) {
-            users = userRepo.findIdByParentInAndDelFalse(users);
+//        List<Long> users = userRepo.findIdByParentAndDelFalse(parent);
+        List<User> users;
+        List<Long> ids = Collections.singletonList(parent);
+//        List<Long> children = new ArrayList<>(users);
+        List<User> children = new ArrayList<>();
+        while (CollUtil.isNotEmpty(ids)) {
+            users = userRepo.findAllByParentInAndDelFalse(ids);
+            ids = users.stream().map(User::getId).collect(Collectors.toList());
             children.addAll(users);
         }
 
+        Map<Long, String> parentMap = children.stream().collect(Collectors.toMap(User::getId, User::getNickname));
+
         query.remove("parent");
         return userRepo.findAll(((root, criteriaQuery, criteriaBuilder) -> {
             List<Predicate> and = JpaUtils.toPredicates(pageQuery, User.class, root, criteriaQuery, criteriaBuilder);
-            and.add(root.in(children));
+            and.add(root.get("parent").in(parentMap.keySet()));
             return criteriaBuilder.and(and.toArray(new Predicate[0]));
-        }), JpaUtils.toPageRequest(pageQuery));
+        }), JpaUtils.toPageRequest(pageQuery)).map(user -> new UserDTO(user, parentMap.get(user.getParent())));
     }
 
     public String shareImg(Long userId) throws IOException, WxErrorException {

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

@@ -217,7 +217,7 @@ public class UserController extends BaseController {
 
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/children")
-    public Page<User> children(@RequestBody PageQuery pageQuery) {
+    public Page<UserDTO> children(@RequestBody PageQuery pageQuery) {
         return userService.children(pageQuery);
     }
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 831 - 42
src/main/vue/package-lock.json


+ 2 - 0
src/main/vue/package.json

@@ -47,7 +47,9 @@
     "eslint-plugin-vue": "^6.2.2",
     "less": "^3.0.4",
     "less-loader": "^5.0.0",
+    "node-sass": "^5.0.0",
     "prettier": "1.19.1",
+    "sass-loader": "^10.1.1",
     "style-resources-loader": "^1.3.3",
     "vue-cli-plugin-style-resources-loader": "^0.1.4",
     "vue-template-compiler": "^2.6.10"

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

@@ -145,7 +145,27 @@
                     :step="0.01"
                 ></el-input-number>
             </el-form-item>
-            <el-form-item prop="makerRatio" label="创客比例" v-if="formData.separateDistribution">
+            <el-form-item prop="personalRatio1" label="二级比例" v-if="formData.separateDistribution">
+                <el-input-number
+                    type="number"
+                    v-model="formData.personalRatio1"
+                    class="select-width"
+                    :max="1"
+                    :min="0"
+                    :step="0.01"
+                ></el-input-number>
+            </el-form-item>
+            <el-form-item prop="personalRatio2" label="三级比例" v-if="formData.separateDistribution">
+                <el-input-number
+                    type="number"
+                    v-model="formData.personalRatio2"
+                    class="select-width"
+                    :max="1"
+                    :min="0"
+                    :step="0.01"
+                ></el-input-number>
+            </el-form-item>
+            <!-- <el-form-item prop="makerRatio" label="创客比例" v-if="formData.separateDistribution">
                 <el-input-number
                     type="number"
                     v-model="formData.makerRatio"
@@ -164,7 +184,7 @@
                     :max="1"
                     :step="0.01"
                 ></el-input-number>
-            </el-form-item>
+            </el-form-item> -->
             <el-form-item label="优惠券" prop="couponId">
                 <el-select multiple v-model="formData.couponId" class="select-width">
                     <el-option v-for="item in coupons" :key="item.id" :label="item.name" :value="item.id">
@@ -173,6 +193,22 @@
                     </el-option>
                 </el-select>
             </el-form-item>
+            <el-form-item label="分享海报" prop="poster">
+                <poster-upload
+                    v-model="formData.poster"
+                    :width="80"
+                    :height="160"
+                    :ratio="[1, 2]"
+                    :imgWidth="224"
+                    key="22"
+                    name="poster"
+                >
+                    <!-- <div slot="tips" class="tips">尺寸120x240px</div> -->
+                </poster-upload>
+            </el-form-item>
+            <el-form-item label="小程序海报" prop="smallPoster">
+                <crop-upload v-model="formData.smallPoster"></crop-upload>
+            </el-form-item>
             <el-form-item>
                 <el-button @click="onSave" :loading="saving" type="primary" v-if="$route.query.id">保存</el-button>
                 <el-button @click="onSave" :loading="saving" type="primary" v-else>下一步</el-button>

+ 192 - 0
src/main/vue/src/components/PosterUpload.vue

@@ -0,0 +1,192 @@
+<template>
+    <div>
+        <div :id="'upload-wrapper-' + name" class="upload-wrapper" :style="uploadStyle">
+            <img v-if="src" :src="src" oncontextmenu="return false;" />
+            <div v-else class="upload-default">
+                点击上传
+            </div>
+            <div v-if="loading" class="loading">
+                <i class="el-icon-loading"></i>
+            </div>
+        </div>
+        <avatar-cropper
+            ref="cropper"
+            @submit="loading = true"
+            @uploaded="handleUploaded"
+            :trigger="'#upload-wrapper-' + name"
+            :cropper-options="cropperOptions"
+            :output-options="outputOptions"
+            :output-quality="1"
+            :upload-url="uploadUrl"
+            :labels="{ submit: '确认', cancel: '取消' }"
+            :upload-headers="headers"
+        />
+
+        <div class="tips">
+            <slot name="tips"></slot>
+        </div>
+    </div>
+</template>
+<script>
+import resolveUrl from 'resolve-url';
+import AvatarCropper from 'vue-avatar-cropper';
+
+export default {
+    props: {
+        value: {},
+        width: {
+            type: Number,
+            default: 400
+        },
+        height: {
+            type: Number,
+            default: 400
+        },
+        ratio: {
+            type: Array,
+            default: () => {
+                [1, 1];
+            }
+        },
+        imgWidth: {
+            type: Number,
+            default: 100
+        },
+        name: {
+            type: String,
+            default: ''
+        }
+    },
+    created() {
+        this.uploadUrl = resolveUrl(this.$baseUrl, 'upload/file');
+        if (this.value) {
+            this.src = this.value;
+        }
+    },
+    mounted() {
+        document.body.appendChild(this.$refs.cropper.$el);
+    },
+    beforeDestroy() {
+        document.body.removeChild(this.$refs.cropper.$el);
+    },
+    data() {
+        return {
+            uploadUrl: '',
+            src: '',
+            loading: false,
+            headers: {
+                // Authorization: 'Bearer ' + localStorage.getItem('token'),
+            }
+        };
+    },
+    computed: {
+        outputOptions() {
+            return { width: this.width * 2, height: this.height * 2 };
+        },
+        cropperOptions() {
+            return {
+                aspectRatio: Number((this.ratio[0] / this.ratio[1]).toFixed(2)),
+                viewMode: 2,
+                guides: false,
+                modal: false,
+                autoCropArea: 1
+            };
+        },
+        uploadStyle() {
+            return {
+                width: this.imgWidth + 'px',
+                height: (this.imgWidth * this.ratio[1]) / this.ratio[0] + 'px'
+            };
+        }
+    },
+    watch: {
+        value() {
+            if (this.value !== this.src) {
+                this.src = this.value;
+            }
+        }
+    },
+    methods: {
+        handleUploaded(res) {
+            this.loading = false;
+            this.src = res;
+            this.$emit('input', res);
+        }
+    },
+    components: {
+        AvatarCropper
+    }
+};
+</script>
+<style lang="scss" scoped>
+.upload-wrapper {
+    width: 178px;
+    height: 178px;
+    display: block;
+    border: 1px dashed #d9d9d9;
+    // border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+
+    img {
+        width: 100%;
+        height: 100%;
+    }
+
+    &:hover {
+        border-color: #409eff;
+
+        .upload-default {
+            color: #409eff;
+        }
+    }
+}
+
+.avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 178px;
+    height: 178px;
+    line-height: 178px;
+    text-align: center;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    background-color: #fbfdff;
+}
+
+.loading {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgba(255, 255, 255, 0.6);
+    color: #333;
+    font-size: 24px;
+}
+
+.upload-default {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: #f5f7fa;
+    color: #bcc1cc;
+    font-size: 12px;
+}
+
+.tips {
+    font-size: 12px;
+    font-weight: 400;
+    color: #bcc1cc;
+    line-height: 17px;
+    margin-top: 12px;
+}
+</style>

+ 2 - 0
src/main/vue/src/main.js

@@ -13,6 +13,7 @@ import VideoUpload from '@/components/VideoUpload';
 import RichText from '@/components/RichText';
 import CropUpload from '@/components/CropUpload';
 import DistrictChoose from '@/components/DistrictChoose';
+import PosterUpload from '@/components/PosterUpload';
 import Formatters from '@/mixins/formatters';
 import 'normalize.css/normalize.css';
 import 'element-ui/lib/theme-chalk/index.css';
@@ -52,6 +53,7 @@ Vue.component('video-upload', VideoUpload);
 Vue.component('rich-text', RichText);
 Vue.component('crop-upload', CropUpload);
 Vue.component('district-choose', DistrictChoose);
+Vue.component('poster-upload', PosterUpload);
 Vue.mixin(Formatters);
 // Vue.use(DropdownMenu).use(DropdownItem);
 

+ 1 - 1
src/main/vue/src/router.js

@@ -98,7 +98,7 @@ const router = new Router({
                 {
                     path: '/childrenList',
                     name: 'childrenList',
-                    component: () => import(/* webpackChunkName: "userEdit" */ '@/views/ChildrenList.vue'),
+                    component: () => import(/* webpackChunkName: "userEdit" */ '@/views/employee/ChildrenList.vue'),
                     meta: {
                         title: '下级列表'
                     }

+ 8 - 7
src/main/vue/src/views/UserEdit.vue

@@ -108,7 +108,7 @@ export default {
                 .get(`/user/get/${this.$route.query.id}`)
                 .then(res => {
                     this.formData = res;
-                    this.getAdmin;
+                    this.getAdmin();
                 })
                 .catch(e => {
                     console.log(e);
@@ -185,11 +185,12 @@ export default {
             id: 0,
             members: [
                 { label: '普通用户', value: 'NORMAL' },
-                { label: '佳客', value: 'EXPERT' },
-                { label: '108将', value: 'GENERAL' },
-                { label: '创客', value: 'MAKER' },
-                { label: '全职', value: 'EMPLOYEE' },
-                { label: '108将/创客', value: 'GENERAL_MAKER' }
+                { label: '团长', value: 'EXPERT' },
+                { label: '大团长', value: 'BIG_EXPERT' }
+                // { label: '108将', value: 'GENERAL' },
+                // { label: '创客', value: 'MAKER' },
+                // { label: '全职', value: 'EMPLOYEE' },
+                // { label: '108将/创客', value: 'GENERAL_MAKER' }
             ],
             attractionsIdOptions: [],
             display: false
@@ -278,7 +279,7 @@ export default {
             let data = this.formData.authorities;
             this.display = false;
             for (let item in data) {
-                if (data[item].name === 'ROLE_WRITER') {
+                if (data[item].name === 'ROLE_WRITER' || data[item].name === 'ROLE_CREATOR') {
                     this.display = true;
                     break;
                 }

+ 6 - 5
src/main/vue/src/views/UserList.vue

@@ -78,11 +78,12 @@ export default {
             sortStr: 'createdAt,desc',
             members: [
                 { label: '普通用户', value: 'NORMAL' },
-                { label: '佳客', value: 'EXPERT' },
-                { label: '108将', value: 'GENERAL' },
-                { label: '创客', value: 'MAKER' },
-                { label: '全职', value: 'EMPLOYEE' },
-                { label: '108将/创客', value: 'GENERAL_MAKER' }
+                { label: '团长', value: 'EXPERT' },
+                { label: '大团长', value: 'BIG_EXPERT' }
+                // { label: '108将', value: 'GENERAL' },
+                // { label: '创客', value: 'MAKER' },
+                // { label: '全职', value: 'EMPLOYEE' },
+                // { label: '108将/创客', value: 'GENERAL_MAKER' }
             ]
         };
     },

+ 3 - 2
src/main/vue/src/views/ChildrenList.vue → src/main/vue/src/views/employee/ChildrenList.vue

@@ -37,6 +37,7 @@
                 </template>
             </el-table-column>
             <el-table-column prop="member" label="身份" :formatter="memberFormatter"></el-table-column>
+            <el-table-column prop="parentName" label="上级"></el-table-column>
             <!-- <el-table-column prop="parentNickname" label="推广人" min-width="100"> </el-table-column> -->
             <!--<el-table-column label="操作" align="center" fixed="right">
                 <template slot-scope="{ row }">
@@ -81,7 +82,7 @@ export default {
         };
     },
     computed: {
-        // ...mapState(['userInfo']),
+        ...mapState(['userInfo']),
         selection() {
             return this.$refs.table.selection.map(i => i.id);
         }
@@ -98,7 +99,7 @@ export default {
             return {
                 search: this.search,
                 query: {
-                    parent: this.$route.query.id
+                    parent: this.$route.query.id || this.userInfo.id
                 }
             };
         },

+ 1 - 1
src/main/vue/src/views/employee/EmployeeDashboard.vue

@@ -82,7 +82,7 @@ export default {
         getAdmin() {
             let data = this.userInfo.authorities;
             for (let item in data) {
-                if (data[item].name === 'ROLE_ADMIN') {
+                if (data[item].name === 'ROLE_ADMIN' || data[item].name === 'ROLE_EXPERT') {
                     this.display = true;
                     break;
                 }

+ 0 - 1
src/main/vue/src/views/employee/EmployeeList.vue

@@ -97,7 +97,6 @@ export default {
         this.getAdmin();
     },
     computed: {
-        ...mapState(['userInfo']),
         selection() {
             return this.$refs.table.selection.map(i => i.id);
         }

+ 7 - 4
src/main/vue/src/views/employee/EmployeeOrderList.vue

@@ -126,6 +126,7 @@ export default {
         };
     },
     computed: {
+        ...mapState(['userInfo']),
         selection() {
             return this.$refs.table.selection.map(i => i.id);
         }
@@ -159,16 +160,18 @@ export default {
             //         createdAt: this.dateRange[0] + ',' + this.dateRange[1]
             //     }
             // };
-            let data = { sort: 'createdAt,desc', query: {} };
+            let data = {
+                sort: 'createdAt,desc',
+                query: {
+                    userId: this.$route.query.id || this.userInfo.id
+                }
+            };
             if (this.search) {
                 data.search = this.search;
             }
             if (this.dateRange && this.dateRange.length > 0) {
                 data.query.createdAt = this.dateRange[0] + ',' + this.dateRange[1];
             }
-            if (this.$route.query.id) {
-                data.query.userId = this.$route.query.id;
-            }
             if (this.packageId) {
                 data.query.packageId = this.packageId;
             }

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

@@ -2,7 +2,7 @@
     <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="text">景区/品牌</div>
             <div class="num">{{ value || 0 }}</div>
         </div>
     </widget-card>

+ 3 - 2
src/test/java/com/izouma/jiashanxia/service/UserServiceTest.java

@@ -3,6 +3,7 @@ package com.izouma.jiashanxia.service;
 import cn.hutool.core.collection.CollUtil;
 import com.izouma.jiashanxia.domain.User;
 import com.izouma.jiashanxia.dto.PageQuery;
+import com.izouma.jiashanxia.dto.UserDTO;
 import com.izouma.jiashanxia.exception.BusinessException;
 import com.izouma.jiashanxia.repo.UserRepo;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -63,8 +64,8 @@ public class UserServiceTest {
     public void test3() {
         PageQuery pageQuery = new PageQuery();
         Map<String, Object> query = pageQuery.getQuery();
-        query.put("parent", 908L);
-        Page<User> children = userService.children(pageQuery);
+        query.put("parent", 1159L);
+        Page<UserDTO> children = userService.children(pageQuery);
         children.getContent().forEach(System.out::println);
     }
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است