lex-xin пре 3 година
родитељ
комит
5c43b1f9e8

+ 1 - 1
package.json

@@ -49,7 +49,7 @@
     "vue-amap": "^0.5.10",
     "vue-awesome-swiper": "^4.1.1",
     "vue-count-to": "^1.0.13",
-    "vue-cropper": "^0.5.8",
+    "vue-cropper": "^0.4.9",
     "vue-drag-resize": "^1.5.4",
     "vue-lunar-calendar-pro": "^1.0.14",
     "vue-qr": "^2.2.1",

BIN
src/assets/images/base/icon_rate.png


+ 81 - 31
src/components/ImageCropper/CropperModal.vue

@@ -1,19 +1,31 @@
 <template>
-    <el-dialog :visible.sync="visible" :title="options.title" :close-on-click-modal="false" width="800" @close="cancelHandel">
+    <el-dialog :visible.sync="visible" :title="options.title" :close-on-click-modal="false" width="800px" @close="cancelHandel">
         <el-row>
-            <el-col :xs="24" :md="12" :style="{ height: '350px' }">
+            <el-col :xs="24" :md="12" :style="{ height: '350px', width: '350px' }">
                 <vue-cropper ref="cropper" :img="options.img" :info="true" :autoCrop="options.autoCrop" :autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight" :fixedBox="options.fixedBox" @realTime="realTime">
                 </vue-cropper>
+
+                <div class="operation">
+                  <i class="el-icon-circle-plus-outline" @click="changeScale(1)"></i>
+                  <i class="el-icon-remove-outline" @click="changeScale(-1)"></i>
+                  <i class="icon-rate" @click="rotateRight"></i>
+                </div>
             </el-col>
             <el-col :xs="24" :md="12" :style="{ height: '350px' }">
-                <div :class="options.previewsCircle ? 'avatar-upload-preview' : 'avatar-upload-preview_range'">
+              <div class="previewImg">
+                <span>预览图片</span>
+                <div :class="options.previewsCircle ? 'avatar-upload-preview' : 'avatar-upload-preview_range'"
+                  :style="{ width: options.autoCropWidth + 'px', height: options.autoCropHeight + 'px', }">
                     <img :src="previews.url" :style="previews.img" />
                 </div>
+              </div>
             </el-col>
         </el-row>
         <template slot="footer">
-            <el-button size="mini" @click="cancelHandel">取消</el-button>
-            <el-button size="mini" type="primary" :loading="confirmLoading" @click="okHandel">保存</el-button>
+            <div style="text-align: center">
+              <el-button size="mini" @click="cancelHandel">取消</el-button>
+              <el-button size="mini" type="primary" :loading="confirmLoading" @click="okHandel">保存</el-button>
+            </div>
         </template>
     </el-dialog>
 </template>
@@ -26,11 +38,6 @@ export default {
     VueCropper
   },
   props: {
-    //图片存储在oss上的上级目录名
-    imgType: {
-      type: String,
-      default: ''
-    }
   },
   data() {
     return {
@@ -45,7 +52,9 @@ export default {
         autoCropHeight: 180, //默认生成截图框高度
         fixedBox: true, //是否固定截图框大小 不允许改变
         previewsCircle: true, //预览图是否是原圆形
-        title: '修改头像'
+        centerBox: true,
+        title: '修改头像',
+        name: null, // 文件名称
       },
       previews: {},
       url: {
@@ -77,31 +86,16 @@ export default {
       // 获取截图的base64 数据
       this.$refs.cropper.getCropBlob(async (data) => {
         let form = new FormData()
-        let file = this.blobToFile(data, 'filename.jpg')
-	      form.append('img_file', file)
+	      form.append('file', data, this.options.name || 'aa.jpg')
         console.log(data, 'blob', form)
         try {
-          const res = await uploadFile({ file: form })
-          console.log(res)
+          const res = await uploadFile(form)
           that.$emit('cropper-ok', res)
         } catch(err) {
           that.$message.error(err)
         } finally {
           that.cancelHandel()
         }
-        // UpPic({
-        //   img_type: this.imgType,
-        //   img_byte: data
-        // })
-        //   .then(res => {
-        //     that.$emit('cropper-ok', res)
-        //   })
-        //   .catch(err => {
-        //     that.$message.error(err)
-        //   })
-        //   .finally(() => {
-        //     that.cancelHandel()
-        //   })
       })
     },
     //转成blob
@@ -113,17 +107,31 @@ export default {
     //移动框的事件
     realTime(data) {
       this.previews = data
+    },
+    //图片缩放
+    changeScale (num) {
+      num = num || 1
+      this.$refs.cropper.changeScale(num)
+    },
+    //向左旋转
+    rotateLeft () {
+      this.$refs.cropper.rotateLeft()
+    },
+    //向右旋转
+    rotateRight () {
+      this.$refs.cropper.rotateRight()
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
+* { touch-action: pan-y; touch-action: none; }
 .avatar-upload-preview_range,
 .avatar-upload-preview {
-  position: absolute;
-  top: 50%;
-  transform: translate(50%, -50%);
+  // position: absolute;
+  // top: 50%;
+  // transform: translate(50%, -50%);
   width: 180px;
   height: 180px;
   border-radius: 50%;
@@ -137,6 +145,48 @@ export default {
 .avatar-upload-preview_range {
   border-radius: 0;
 }
+.previewImg {
+  padding-left: 50px;
+  padding-top: 10px;
+}
+.operation {
+  font-size: 24px;
+  display: flex;
+  align-items: center;
+  margin-top: 20px;
+  & > i {
+    margin-left: 12px;
+    cursor: pointer;
+  }
+  .icon-rate {
+    display: inline-block;
+    width: 20px;
+    height: 20px;
+    background: url('../../assets/images/base/icon_rate.png') no-repeat center;
+    background-size: contain;
+  }
+}
+.vue-cropper {
+  border-radius: 5px;
+  overflow: hidden;
+}
+/deep/.el-dialog {
+  margin-bottom: 10vh;
+  .el-dialog__header {
+    // background: #363d55;
+    background: #fff;
+    padding: 15px 20px 15px;
+    .el-dialog__title {
+      color: #212121;
+    }
+    .el-dialog__headerbtn .el-dialog__close {
+      color: #212121;
+    }
+  }
+  .el-dialog__body {
+    padding-top: 0;
+  }
+}
 </style>
 
 

+ 24 - 11
src/components/ImageCropper/index.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="ant-upload-preview">
         <div style="width: 100%">
-            <el-upload class="avatar-uploader" :show-file-list="false" action :before-upload="beforeUpload" :http-request="handleChange">
+            <el-upload class="avatar-uploader" :class="[disabled ? 'uploadDisabled' : null]" :disabled="disabled" :accept="accept" :show-file-list="false" action :before-upload="beforeUpload" :http-request="handleChange">
                 <img v-if="imageUrl" :src="imageUrl" class="avatar" />
                 <span v-else>
                     <i v-if="loading" class="el-icon-loading avatar-uploader-icon"></i>
@@ -11,7 +11,7 @@
             </el-upload>
         </div>
         <!-- modal -->
-        <cropper-modal ref="CropperModal" :imgType="imgType" @cropper-no="handleCropperClose" @cropper-ok="handleCropperSuccess"></cropper-modal>
+        <cropper-modal ref="CropperModal" @cropper-no="handleCropperClose" @cropper-ok="handleCropperSuccess"></cropper-modal>
     </div>
 </template>
 <script>
@@ -28,11 +28,11 @@ export default {
       default: function() {
         return {
           autoCrop: true, //是否默认生成截图框
-          autoCropWidth: 72, //默认生成截图框宽度
-          autoCropHeight: 72, //默认生成截图框高度
+          autoCropWidth: 200, //默认生成截图框宽度
+          autoCropHeight: 200, //默认生成截图框高度
           fixedBox: false, //是否固定截图框大小 不允许改变
           previewsCircle: true, //预览图是否是原圆形
-          title: '修改头像'
+          title: '上传图片'
         }
       }
     },
@@ -41,15 +41,18 @@ export default {
       type: Number,
       default: 2
     },
-    //图片存储在oss上的上级目录名
-    imgType: {
-      type: String,
-      default: ''
-    },
     // 图片地址
     imageUrl: {
       type: String,
       default: ''
+    },
+    accept: {
+      type: String,
+      default: '.png,.jpg,.jpeg'
+    },
+    disabled: {
+      type: Boolean,
+      default: false
     }
   },
   data() {
@@ -70,7 +73,8 @@ export default {
       console.log(info)
       this.getBase64(info.file, imageUrl => {
         const target = Object.assign({}, options, {
-          img: imageUrl
+          img: imageUrl,
+          name: info.file.name // 上传文件名
         })
         this.$refs.CropperModal.edit(target)
       })
@@ -141,6 +145,14 @@ export default {
   position: relative;
   overflow: hidden;
 }
+::v-deep .avatar-uploader.uploadDisabled {
+  .el-upload--text {
+    cursor: not-allowed;
+  }
+  .el-upload:hover {
+    border-color: #d9d9d9;
+  }
+}
 ::v-deep .avatar-uploader .el-upload:hover {
   border-color: #409eff;
 }
@@ -157,6 +169,7 @@ export default {
   height: 108px;
   display: block;
 }
+
 </style>
 
 

+ 3 - 1
src/router/index.js

@@ -522,8 +522,10 @@ export const asyncRoutes = {
   mailInfoManager:()=>import('@/views/mailInfoManager'),
   // 机构协议管理
   protocolManagement:()=>import('@/views/protocolManagement'),
-  // 机构协议管理
+  //
   studentGroupPractice:()=>import('@/views/studentManager/studentGroupPractice'),
+  // 团练宝缴费记录
+  studentGroupRecord:()=>import('@/views/studentManager/studentGroupRecord'),
 }
 
 export default router

+ 1 - 2
src/views/HumanResources/index.vue

@@ -587,7 +587,7 @@ export default {
   },
   async mounted() {
     await this.$store.dispatch("setOrganRole");
-    this.roleList = this.selects.roles.hrId;
+    this.roleList = this.selects.roles.HRBP || [];
     this.getList();
     // this.getTreeList()
     getEmployeeOrgan().then((res) => {
@@ -722,7 +722,6 @@ export default {
     },
     getList() {
       const { dates, ...rest } = this.searchForm;
-      console.log(dates);
       let params = {
         ...rest,
         ...getTimes(dates, ["startDate", "endDate"]),

+ 8 - 8
src/views/categroyManager/generalSettings/groupMarkPrice.vue

@@ -16,7 +16,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
             ]"
@@ -34,7 +34,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
               { validator: validateMonthMax, trigger: 'blur' }
@@ -55,7 +55,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
             ]"
@@ -73,7 +73,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
               { validator: validateQuarterlyMax, trigger: 'blur' }
@@ -94,7 +94,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
             ]"
@@ -112,7 +112,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
               { validator: validateHalfYearMax, trigger: 'blur' }
@@ -133,7 +133,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
             ]"
@@ -151,7 +151,7 @@
             :rules="[
               {
                 required: false,
-                pattern: /^[1-9][0-9]*$/,
+                pattern: /^[0-9][0-9]*$/,
                 message: '请输入正确的价格',
               },
               { validator: validateYearMax, trigger: 'blur' }

+ 148 - 71
src/views/organManager/components/organInfo.vue

@@ -28,7 +28,7 @@
           ]"
         >
           <div style="width: 300px !important">
-            <el-upload
+            <!-- <el-upload
               class="avatar-uploader"
               action="/api-web/uploadFile"
               accept=".png"
@@ -40,27 +40,17 @@
             >
               <img v-if="form.logo" :src="form.logo" class="avatar" />
               <i v-else class="el-icon-plus avatar-uploader-icon"></i>
-            </el-upload>
-            <!-- <image-cropper :options="cropperOptions" :imgSize="3" :imgType="imgType" :imageUrl="imgUrl" @crop-upload-close="cropClose" @crop-upload-success="cropSuccess" /> -->
+            </el-upload> -->
+            <image-cropper :options="cropperOptions" :disabled="isDisabled" :imgSize="2" :accept="acceptUpload" :imageUrl="form.logo" @crop-upload-close="cropClose" @crop-upload-success="cropSuccess" />
             <div
               class="tips"
               v-show="!isDisabled"
               style="line-height: 1;color: red;"
             >
-              仅支持图片尺寸:72x72;格式:png;
+              仅支持图片格式:png,大小:2MB
             </div>
           </div>
         </el-form-item>
-        <el-form-item label="机构简介" prop="remark">
-          <el-input
-            type="textarea"
-            show-word-limit
-            :max="200"
-            :disabled="isDisabled"
-            v-model.trim="form.remark"
-            placeholder="请输入机构简介"
-          ></el-input>
-        </el-form-item>
         <!-- <el-form-item label="主题" v-if="tenantInfo == 'SETTING'" prop="theme" :rules="[{ required: true, message: '请选择主题', trigger: 'change' }]">
             <el-select
               v-model="form.theme"
@@ -72,6 +62,92 @@
             </el-select>
           </el-form-item> -->
         <el-form-item
+          label="企业公章"
+          prop="corporateChops"
+          :rules="[
+            {
+              required: true,
+              message: '请上企业公章',
+              trigger: 'blur, change'
+            }
+          ]"
+        >
+          <div style="width: 300px !important" class="ant-upload-preview">
+            <el-upload
+              class="avatar-uploader"
+              :class="[isDisabled || tenantInfo == 'SETTING' ? 'uploadDisabled' : null]"
+              action="/api-web/uploadFile"
+              accept=".png"
+              :headers="headers"
+              :show-file-list="false"
+              :disabled="isDisabled || tenantInfo == 'SETTING'"
+              :on-success="handleAvatarSuccess"
+              :before-upload="beforeAvatarUpload"
+            >
+              <img v-if="form.corporateChops" :src="form.corporateChops" class="avatar" />
+              <span v-else>
+                  <i class="el-icon-plus avatar-uploader-icon"></i>
+                  <span class="upload-desc">添加上传图片</span>
+              </span>
+            </el-upload>
+            <div
+              class="tips"
+              v-show="!isDisabled && tenantInfo != 'SETTING'"
+              style="line-height: 1;color: red;"
+            >
+              仅支持图片格式:png,大小:2MB;
+            </div>
+          </div>
+        </el-form-item>
+        <el-form-item
+          label="企业财务公章"
+          prop="corporateFinanceChops"
+          :rules="[
+            {
+              required: true,
+              message: '请上传企业财务公章',
+              trigger: 'blur, change'
+            }
+          ]"
+        >
+          <div style="width: 300px !important" class="ant-upload-preview">
+            <el-upload
+              class="avatar-uploader"
+              :class="[isDisabled || tenantInfo == 'SETTING' ? 'uploadDisabled' : null]"
+              action="/api-web/uploadFile"
+              accept=".png"
+              :headers="headers"
+              :show-file-list="false"
+              :disabled="isDisabled || tenantInfo == 'SETTING'"
+              :on-success="handleAvatarSuccess2"
+              :before-upload="beforeAvatarUpload"
+            >
+              <img v-if="form.corporateFinanceChops" :src="form.corporateFinanceChops" class="avatar" />
+              <span v-else>
+                  <i class="el-icon-plus avatar-uploader-icon"></i>
+                  <span class="upload-desc">添加上传图片</span>
+              </span>
+            </el-upload>
+            <div
+              class="tips"
+              v-show="!isDisabled && tenantInfo != 'SETTING'"
+              style="line-height: 1;color: red;"
+            >
+              仅支持图片格式:png,大小:2MB;
+            </div>
+          </div>
+        </el-form-item>
+        <el-form-item label="机构简介" prop="remark">
+          <el-input
+            type="textarea"
+            show-word-limit
+            :max="200"
+            :disabled="isDisabled"
+            v-model.trim="form.remark"
+            placeholder="请输入机构简介"
+          ></el-input>
+        </el-form-item>
+        <el-form-item
           label="主题"
           v-if="tenantInfo == 'SETTING'"
           prop="theme"
@@ -332,7 +408,9 @@ export default {
         customerServicePhone: null,
         remark: null,
         theme: "adenGreen",
-        themeColor: "#00A79D"
+        themeColor: "#00A79D",
+        corporateChops: null,
+        corporateFinanceChops: null,
       },
       errorPhone: null, // 手机号存在错误信息
       payState: null,
@@ -342,14 +420,13 @@ export default {
       cityList: [],
       cropperOptions: {
         autoCrop: true, //是否默认生成截图框
-        autoCropWidth: 200, //默认生成截图框宽度
-        autoCropHeight: 200, //默认生成截图框高度
-        fixedBox: false, //是否固定截图框大小 不允许改变
+        autoCropWidth: 72, //默认生成截图框宽度
+        autoCropHeight: 72, //默认生成截图框高度
+        fixedBox: true, //是否固定截图框大小 不允许改变
         previewsCircle: false, //预览图是否是圆形
-        title: '上传广告图片' //模态框上显示的标题
+        title: '上传机构LOGO', //模态框上显示的标题
       },
-      imgType: 'testUp', //图片存储在oss上的上级目录名
-      imgUrl: '', //上传图片所得到的地址
+      acceptUpload: '.png', // 上传支持格式
     };
   },
   async mounted() {
@@ -401,8 +478,9 @@ export default {
     },
     //上传图片成功
     cropSuccess(data) {
-      this.imgUrl = data.data.avatar
-      console.log(this.imgUrl)
+      // this.imgUrl = data.data.avatar
+      this.form.logo = data.data.url;
+      console.log(this.form.logo)
     },
     themeChange(item) {
       // 切换主题时设置跟主题对应的主题色
@@ -480,7 +558,10 @@ export default {
       return this.form;
     },
     handleAvatarSuccess(res) {
-      this.form.logo = res.data.url;
+      this.form.corporateChops = res.data.url;
+    },
+    handleAvatarSuccess2(res) {
+      this.form.corporateFinanceChops = res.data.url;
     },
     // handleAvatarSuccess(res, file, fileList) {
     //   //上传成功后将图片地址赋值给裁剪框显示图片
@@ -512,40 +593,7 @@ export default {
         this.$message.error("上传头像图片大小不能超过 2MB!");
         return false;
       }
-      const imageWidth = this.imageWidthM;
-      const imageHeigh = this.imageHeightM;
-      const _URL = window.URL || window.webkitURL;
-      const isSize = new Promise((resolve, reject) => {
-        const img = new Image();
-        img.onload = function() {
-          if (imageWidth && imageHeigh) {
-            this.width === imageWidth && this.height === imageHeigh
-              ? resolve()
-              : reject(`请上传${imageWidth}x${imageHeigh}尺寸图片`);
-          } else if (imageWidth && !imageHeigh) {
-            this.width === imageWidth
-              ? resolve()
-              : reject(`请上传宽为${imageWidth}的图片`);
-          } else if (!imageWidth && imageHeigh) {
-            this.height === imageHeigh
-              ? resolve()
-              : reject(`请上传高为${imageHeigh}的图片`);
-          } else {
-            resolve();
-          }
-        };
-        img.src = _URL.createObjectURL(file);
-      }).then(
-        () => {
-          return file;
-        },
-        src => {
-          this.$message.error(src);
-          this.uploadImgLoading = false;
-          return Promise.reject();
-        }
-      );
-      return isImage && isLt2M && isSize;
+      return isImage && isLt2M;
     },
     validatePhone(rule, value, callback) {
       if (this.errorPhone) {
@@ -558,33 +606,62 @@ export default {
 };
 </script>
 <style lang="scss" scoped>
-/deep/.avatar-uploader .el-upload {
+.ant-upload-preview {
+  background-color: #fff;
+  .avatar-uploader {
+    .upload-desc {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      color: #ccc;
+      font-size: 8px;
+      right: 0;
+    }
+  }
+}
+::v-deep .avatar-uploader .el-upload--text {
   border: 1px dashed #d9d9d9;
   border-radius: 6px;
+  margin-right: 20px;
   cursor: pointer;
   position: relative;
   overflow: hidden;
-  background: #e7e7e7;
 }
-.avatar-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 72px;
-  height: 72px;
-  line-height: 72px;
+::v-deep .avatar-uploader.uploadDisabled {
+  .el-upload--text {
+    cursor: not-allowed;
+  }
+  .el-upload:hover {
+    border-color: #d9d9d9;
+  }
+}
+::v-deep .avatar-uploader .el-upload:hover {
+  border-color: #409eff;
+}
+::v-deep .avatar-uploader-icon {
+  font-size: 22px;
+  color: #ccc;
+  width: 108px;
+  height: 108px;
+  line-height: 108px;
   text-align: center;
 }
+::v-deep.avatar {
+  width: 108px;
+  height: 108px;
+  display: block;
+}
 
 .el-input,
 .el-select,
 .el-textarea {
   width: 300px !important;
 }
-.avatar {
-  width: 72px;
-  height: 72px;
-  display: block;
-}
+// .avatar {
+//   width: 72px;
+//   height: 72px;
+//   display: block;
+// }
 .themeColor-block {
   width: 30px;
   height: 30px;

+ 5 - 3
src/views/organManager/index.vue

@@ -22,8 +22,8 @@
           type="daterange"
           value-format="yyyy-MM-dd"
           range-separator="至"
-          start-placeholder="入驻开始时间"
-          end-placeholder="入驻结束时间"
+          start-placeholder="开始时间"
+          end-placeholder="结束时间"
           :picker-options="{ firstDayOfWeek: 1 }"
         ></el-date-picker>
       </el-form-item>
@@ -63,7 +63,6 @@
     <div class="tableWrap">
       <el-table
         :data="tableList"
-        
         :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
       >
         <el-table-column align="center" prop="id" label="机构编号">
@@ -82,6 +81,9 @@
           </template>
         </el-table-column>
         <el-table-column align="center" label="有效期到期时间" prop="expireDate">
+          <template slot-scope="scope">
+            {{ scope.row.expireDate | formatTimer }}
+          </template>
         </el-table-column>
         <!-- <el-table-column align="center" label="网络教室剩余时长" prop="productName">
         </el-table-column> -->

+ 15 - 5
src/views/organManager/organOperation.vue

@@ -69,10 +69,10 @@ export default {
         }
         const res = await tenantInfoInfo({ id: this.id })
         const { config, productInfo, ...other } = res.data
-        const { theme, themeColor, ...con } = config
+        const { theme, themeColor, corporateChops, corporateFinanceChops, ...con } = config
         this.config = { ...con }
         this.productInfo = productInfo
-        this.info = { ...other, theme, themeColor }
+        this.info = { ...other, theme, themeColor, corporateChops, corporateFinanceChops }
         this.productInfo.payState = this.info.payState
       } catch(e) {}
     }
@@ -97,8 +97,16 @@ export default {
         const ruleStatus = await this.$refs.roomRules.onSubmit()
         const rateStatus = await this.$refs.rateSetting.onSubmit()
         if(openStatus && memberStatus && ruleStatus && rateStatus) {
-          this.goTo()
-          this.active += 1
+          // this.$dialog
+          // 请确认以上信息填写正确
+          this.$confirm(`请确认以上信息填写正确?`, "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          }).then( async() => {
+            this.goTo()
+            this.active += 1
+          });
         }
       } else if(this.active == 2) {
         // 处理提交
@@ -108,7 +116,7 @@ export default {
         const ruleData = await this.$refs.roomRules.getValues()
         const rateData = await this.$refs.rateSetting.getValues()
         const { member_config, teachingMaterialId } = memberData
-        const { theme, themeColor, ...con } = organData
+        const { theme, themeColor, corporateChops, corporateFinanceChops, ...con } = organData
         let config = {
           member_config,
           ...ruleData
@@ -119,6 +127,8 @@ export default {
           config: {
             theme,
             themeColor,
+            corporateChops,
+            corporateFinanceChops,
             config: JSON.stringify(config),
             teachingMaterialId: teachingMaterialId.join(','),
             ...rateData

+ 15 - 0
src/views/studentManager/api.js

@@ -6,3 +6,18 @@ export const getMusicMemberList = data => request2({
   params: data,
   method: 'get',
 })
+
+
+// 添加
+export const add = (data) => request2({
+  url: '/api-web/cloudCoachPaymentProgram/add',
+  method: 'post',
+  data
+})
+
+// 
+export const cloudCoachPaymentProgramQueryPage = (data) => request2({
+  url: '/api-web/cloudCoachPaymentProgram/queryPage',
+  method: 'get',
+  params: data
+})

+ 232 - 0
src/views/studentManager/modals/createMember.vue

@@ -0,0 +1,232 @@
+<template>
+  <div>
+    <!-- <p class="title">已选择{{ multipleSelection.length }}名学员</p> -->
+    <el-form :model="memberForm" label-width="100px" ref="memberForm">
+      <el-form-item
+        label="团练宝单位"
+        prop="period"
+        :rules="[
+          { required: true, message: '请选择团练宝单位', trigger: 'blur' },
+        ]"
+      >
+        <el-select
+          placeholder="团练宝单位"
+          clearable
+          v-model.trim="memberForm.period"
+          style="width: 100% !important"
+        >
+          <el-option label="月度" value="MONTH"></el-option>
+          <el-option label="季度" value="QUARTERLY"></el-option>
+          <el-option label="半年" value="YEAR_HALF"></el-option>
+          <el-option label="年度" value="YEAR"></el-option>
+          <!-- <el-option label="固定天数" value="DAY"></el-option> -->
+        </el-select>
+      </el-form-item>
+      <el-form-item
+        label="团练宝周期"
+        prop="memberNum"
+        :rules="[
+          { required: true, message: '请输入团练宝周期', trigger: 'blur' },
+        ]"
+      >
+        <el-input
+          type="number"
+          onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"
+          v-model="memberForm.memberNum"
+          placeholder="请输入团练宝周期"
+        >
+        </el-input>
+      </el-form-item>
+      <el-form-item
+        label="缴费金额"
+        prop="amount"
+        v-show="false"
+      >
+        <el-input
+          type="number"
+          v-model="amount"
+          placeholder="请输入缴费金额"
+        >
+        </el-input>
+      </el-form-item>
+      <el-form-item
+        label="缴费金额"
+        prop="actualAmount"
+        :rules="[
+          { required: true, message: '请输入缴费金额', trigger: 'blur' },
+          { validator: validateMember, trigger: 'blur' },
+        ]"
+      >
+        <el-input
+          type="number"
+          onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"
+          v-model="memberForm.actualAmount"
+          placeholder="请输入缴费金额"
+        >
+          <div slot="append">元/人</div>
+        </el-input>
+      </el-form-item>
+      <p style="color: red; padding: 0 0 20px 100px">若修改为0元则无需学员缴费,创建后即可进行激活操作</p>
+      <el-form-item label="备注" prop="remark"
+        :rules="[
+          { required: true, message: '请输入备注', trigger: 'blur' },
+        ]">
+        <el-input
+          type="textarea"
+          show-word-limit
+          :max="200"
+          v-model.trim="memberForm.remark"
+          placeholder="请输入备注"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+<script>
+import { add } from "../api";
+import { getmemberRankOrganizationFeeMapper } from '@/views/categroyManager/productSystem/api'
+import { sysConfigList } from "@/api/generalSettings"; // 平台的修改和查
+export default {
+  props: ["multipleSelection"],
+  data() {
+    return {
+      memberForm: {
+        memberNum: null,
+        actualAmount: null,
+        period: null,
+        remark: null
+      },
+      userIds: [],
+      organId: null,
+      rulesForm: null,// 范围
+      memberFeeSetting: null
+    };
+  },
+  mounted() {
+    this.userIds = this.multipleSelection
+      .map((stu) => {
+        return stu.userId;
+      });
+    this.organId = this.multipleSelection[0].organId //
+    this.__init()
+  },
+  computed: {
+    amount() {
+      let money = 0
+      const memberForm = this.memberForm
+      const memberFeeSetting = this.memberFeeSetting
+      switch (memberForm?.period) {
+        case "MONTH": {
+          money = Number(memberFeeSetting.groupPurchaseMonthFee * memberForm.memberNum)
+          break;
+        }
+        case "QUARTERLY": {
+          money = Number(memberFeeSetting.groupPurchaseQuarterlyFee * memberForm.memberNum)
+          break;
+        }
+        case "YEAR_HALF": {
+          money = Number(memberFeeSetting.groupPurchaseHalfYearFee * memberForm.memberNum)
+          break;
+        }
+        case "YEAR": {
+          money = Number(memberFeeSetting.groupPurchaseYearFee * memberForm.memberNum)
+          break;
+        }
+      }
+      if(memberForm.memberNum && memberForm.period) {
+        this.memberForm.actualAmount = money
+      }
+      return money
+    }
+  },
+  methods: {
+    async __init() {
+      try {
+        const res = await sysConfigList({ group: "DEFAULT" });
+        const paramName = 'cloud_price_range'
+        res.data.forEach((item) => {
+          if(item.paramName == paramName) {
+            const itemValue = item.paranValue ? JSON.parse(item.paranValue) : null
+            if(itemValue) {
+              this.rulesForm = itemValue
+            }
+          }
+        });
+
+        const rankInfo = await getmemberRankOrganizationFeeMapper({ page: 1, rows: 10, organId: this.organId })
+        console.log(rankInfo)
+        const { rows } = rankInfo.data
+        this.memberFeeSetting = rows[0]?.memberFeeSetting
+      } catch(e) {
+
+      }
+    },
+    submit() {
+      this.$refs.memberForm.validate(async (res) => {
+        if (res) {
+          try {
+            await add({
+              ...this.memberForm,
+              userIds: this.userIds,
+              organId: this.organId
+            });
+            this.$message.success('添加会员成功')
+            this.$emit("close");
+            this.$emit("submited");
+          } catch (e) {
+            console.log(e);
+          }
+        }
+      });
+    },
+    validateMember(rule, value, callback) {
+      const one = Number(value);
+      let min = 0;
+      let max = 0;
+      console.log(value)
+      switch (this.memberForm?.period) {
+        case "MONTH": {
+          min =
+            Number(this.rulesForm.minMonthFee) * this.memberForm.memberNum;
+          max =
+            Number(this.rulesForm.maxMonthFee) * this.memberForm.memberNum;
+          break;
+        }
+        case "QUARTERLY": {
+          min =
+            Number(this.rulesForm.minQuarterlyFee) *
+            this.memberForm.memberNum;
+          max =
+            Number(this.rulesForm.maxQuarterlyFee) *
+            this.memberForm.memberNum;
+          break;
+        }
+        case "YEAR_HALF": {
+          min =
+            Number(this.rulesForm.minHalfYearFee) * this.memberForm.memberNum;
+          max =
+            Number(this.rulesForm.maxHalfYearFee) * this.memberForm.memberNum;
+          break;
+        }
+        case "YEAR": {
+          min = Number(this.rulesForm.minYearFee) * this.memberForm.memberNum;
+          max = Number(this.rulesForm.maxYearFee) * this.memberForm.memberNum;
+          break;
+        }
+      }
+
+      if (one >= min && one <= max) {
+        return callback();
+      }
+      return callback(new Error(`定价应在${min}-${max}之间`));
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.title {
+  margin-bottom: 30px;
+  font-size: 16px;
+  color: #000;
+}
+</style>

+ 56 - 0
src/views/studentManager/modals/recordDetail.vue

@@ -0,0 +1,56 @@
+<template>
+  <div>
+    <el-alert title="基础信息" :closable="false" class="alert" type="info" />
+    <descriptions :column="2">
+      <descriptions-item label="团练宝单位">121212</descriptions-item>
+      <descriptions-item label="周期数">梅赫梅特阿里通克fsdf</descriptions-item>
+      <descriptions-item label="缴费金额(元)">梅赫梅特阿里通克fsdf</descriptions-item>
+      <descriptions-item label="已缴费人数/总人数">梅赫梅特阿里通克fsdf</descriptions-item>
+      <descriptions-item label="创建人">梅赫梅特阿里通克fsdf</descriptions-item>
+      <descriptions-item label="创建时间">梅赫梅特阿里通克fsdf</descriptions-item>
+      <descriptions-item label="备注">梅赫梅特阿里通克fsdf</descriptions-item>
+    </descriptions>
+
+    <el-alert title="订单详情" :closable="false" class="alert" style="margin-top: 20px;" type="info" />
+    <el-table
+        :data="tableList"
+        :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
+      >
+      <el-table-column align="center" prop="id" label="产品名称">
+      </el-table-column>
+      <el-table-column align="center" label="产品类型" prop="name">
+      </el-table-column>
+      <el-table-column align="center" label="数量" prop="contacts">
+      </el-table-column>
+      <el-table-column align="center" label="单价" prop="phone">
+      </el-table-column>
+      <el-table-column align="center" label="支付价格" prop="payState">
+        <template slot-scope="scope">
+          {{ scope.row.payState | organPayState }}
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      tableList: []
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.alert {
+  margin-bottom: 10px;
+}
+.description-title {
+  margin-bottom: 0;
+}
+.description-label {
+  width: 120px !important;
+}
+</style>

+ 180 - 0
src/views/studentManager/studentGroupRecord.vue

@@ -0,0 +1,180 @@
+<template>
+  <div class="m-container">
+    <h2>
+      <div class="squrt"></div>
+      团练宝缴费记录
+    </h2>
+    <el-form :inline="true" :model="searchForm">
+      <el-form-item>
+        <el-select
+          placeholder="团练宝单位"
+          clearable
+          v-model.trim="searchForm.period"
+          style="width: 100% !important"
+        >
+          <el-option label="月度" value="MONTH"></el-option>
+          <el-option label="季度" value="QUARTERLY"></el-option>
+          <el-option label="半年" value="YEAR_HALF"></el-option>
+          <el-option label="年度" value="YEAR"></el-option>
+          <!-- <el-option label="固定天数" value="DAY"></el-option> -->
+        </el-select>
+      </el-form-item>
+      <el-form-item prop="visitTime">
+          <el-date-picker
+            v-model.trim="searchForm.visitTime"
+            style="width: 410px"
+            type="daterange"
+            :picker-options="{
+              firstDayOfWeek: 1,
+            }"
+            :default-time="['00:00:00', '23:59:59']"
+            range-separator="至"
+            start-placeholder="创建开始日期"
+            end-placeholder="创建结束日期"
+          ></el-date-picker>
+        </el-form-item>
+      <el-form-item>
+        <el-button @click="search" type="danger">搜索</el-button>
+        <el-button @click="onReSet" type="primary">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <div class="tableWrap">
+      <el-table
+        style="width: 100%"
+        :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
+        :data="tableList"
+      >
+        <el-table-column
+          align="center"
+          prop="id"
+          label="续费编号"
+        ></el-table-column>
+        <el-table-column align="center" prop="name" label="团练宝单位">
+          <template slot-scope="scope">
+            {{ scope.row.period | memberEnumType }}
+          </template>
+        </el-table-column>
+        <el-table-column align="center" prop="memberNum" label="周期数">
+        </el-table-column>
+        <el-table-column
+          align="center"
+          prop="subjectName"
+          label="缴费金额(元)"
+        >
+          <template slot-scope="scope">
+            {{ scope.row.actualAmount | hasMoneyFormat }}
+          </template>
+        </el-table-column>
+        <el-table-column
+          align="center"
+          prop="type"
+          label="已缴费人数/总人数"
+        >
+          <template slot-scope="scope">
+            {{ scope.row.paymentUserNum }}/{{ scope.row.userNum }}
+          </template>
+        </el-table-column>
+        <el-table-column
+          align="center"
+          prop="remark"
+          label="备注"
+        ></el-table-column>
+        <el-table-column
+          align="center"
+          label="创建人"
+          prop="operatorName"
+        >
+        </el-table-column>
+        <el-table-column
+          align="center"
+          prop="createTime"
+          label="创建时间"
+        ></el-table-column>
+        <el-table-column align="center"
+                         label="操作">
+          <template slot-scope="scope">
+            <el-button type="text" @click="onDetail(scope.row)">详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        sync
+        :total.sync="rules.total"
+        :page.sync="rules.page"
+        :limit.sync="rules.limit"
+        :page-sizes="rules.page_size"
+        @pagination="getList"
+      />
+    </div>
+
+    <el-dialog
+      title="激活会员"
+      :visible.sync="recordVisible"
+      width="1000px"
+      v-if="recordVisible"
+      append-to-body
+    >
+      <recordDetail :tableList="selectStudentList" @getList="getList" @close="recordVisible = false" />
+    </el-dialog>
+  </div>
+</template>
+<script>
+import pagination from "@/components/Pagination/index";
+import { queryInactive } from '@/views/resetTeaming/api'
+import recordDetail from '@/views/studentManager/modals/recordDetail'
+import { cloudCoachPaymentProgramQueryPage } from './api'
+import { getTimes } from "@/utils";
+export default {
+  components: { pagination, recordDetail },
+  data() {
+    return {
+      recordVisible: false,
+      searchForm: {
+        visitTime: [],
+        period: null,
+      },
+      soundList: [],
+      tableList: [],
+      rules: {
+        // 分页规则
+        limit: 10, // 限制显示条数
+        page: 1, // 当前页
+        total: 0, // 总条数
+        page_size: [10, 20, 40, 50], // 选择限制显示条数
+      },
+      selectStudentList: [], // 选中的学生列表
+    };
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      try {
+        const { visitTime, ...search } = this.searchForm
+        const res = await cloudCoachPaymentProgramQueryPage({
+          ...search,
+          ...getTimes(visitTime, ["startTime", "endTime"]),
+          page: this.rules.page,
+          rows: this.rules.limit,
+        });
+        this.rules.total = res.data.total;
+        this.tableList = res.data.rows;
+      } catch (e) { }
+      queryInactive
+    },
+    search() {
+      this.rules.page = 1;
+      this.getList();
+    },
+    onReSet() {
+      this.searchForm = { search: "", subjectId: "" };
+      this.search()
+    },
+    onDetail(row) {
+      this.recordVisible = true
+    }
+  },
+};
+</script>

+ 17 - 6
src/views/studentManager/studentList.vue

@@ -175,7 +175,7 @@
         </el-form-item>
       </save-form>
       <el-button  style="margin-bottom: 20px;" type="primary"
-        @click="addStudentMember" icon="el-icon-plus">添加会员</el-button>
+        @click="addStudentMember" icon="el-icon-plus">创建团练宝缴费</el-button>
       <el-button
         v-permission="'studentManage/register'"
         @click="addStudent"
@@ -885,9 +885,9 @@
     </el-dialog>
 
     <el-dialog
-      title="添加会员"
+      title="创建团练宝缴费"
       width="500px"
-      :visible.sync="memberVisible" 
+      :visible.sync="memberVisible"
     >
       <createMember
         ref="addMember"
@@ -916,12 +916,12 @@ import { queryByOrganId } from "@/api/systemManage";
 import qrCode from "@/components/QrCode/index";
 import { vaildStudentUrl } from "@/utils/validate";
 import { resetPassword2, getTeacher } from "@/api/buildTeam";
-import { subjectListTree } from "@/api/specialSetting";
+import { organizationCloudTeacherFeeQueryPage, subjectListTree } from "@/api/specialSetting";
 import axios from "axios";
 import qs from "qs";
 import { getToken, getTenantId } from "@/utils/auth";
 import load from "@/utils/loading";
-import createMember from "@/views/teamDetail/components/modals/createMember";
+import createMember from "./modals/createMember";
 export default {
   name: "studentManagerList",
   components: { pagination, qrCode, createMember },
@@ -1039,7 +1039,18 @@ export default {
     },
     addStudentMember() {
       if (this.multipleSelection.length > 0) {
-        this.memberVisible = true;
+        let organIds = []
+        this.multipleSelection.forEach(m => {
+          if(!organIds.includes(m.organId)) {
+            organIds.push(m.organId)
+          }
+        })
+
+        if(organIds.length == 1) {
+          this.memberVisible = true;
+        } else {
+          this.$message.error("所选学员只能是同一分部");
+        }
       } else {
         this.$message.error("请至少选择一名学员");
       }

+ 2 - 0
src/views/teachManager/modals/addRoot.vue

@@ -86,6 +86,7 @@
           :imageHeightM="imageHeightM"
           ref="uploadImg"
         ></upload>
+        <!-- <image-cropper :options="cropperOptions" :disabled="isDisabled" :imgSize="2" :accept="acceptUpload" :imageUrl="form.logo" @crop-upload-close="cropClose" @crop-upload-success="cropSuccess" /> -->
         <p style="color: red">
           请上传{{ imageWidthM }}*{{ imageHeightM }}像素,大小2M以内,格式为jpg、png、gif图片
         </p>
@@ -99,6 +100,7 @@
 </template>
 <script>
 import Upload from "@/components/Upload/index";
+import ImageCropper from '@/components/ImageCropper'
 import {
   addsysMusicScore,
   getSysMusicScoreDetail,

+ 0 - 91
src/views/teamDetail/components/modals/createMember.vue

@@ -1,91 +0,0 @@
-<template>
-  <div>
-    <!-- <p class="title">已选择{{ multipleSelection.length }}名学员</p> -->
-    <el-form :model="memberForm" label-width="120px" ref="memberForm">
-      <el-form-item
-        label="赠送会员类型"
-        prop="addType"
-        :rules="[
-          { required: true, message: '请选择赠送会员类型', trigger: 'blur' },
-        ]"
-      >
-        <el-select
-          placeholder="赠送会员类型"
-          clearable
-          v-model.trim="memberForm.addType"
-          style="width: 100% !important"
-        >
-          <el-option label="月度" value="MONTH"></el-option>
-          <el-option label="季度" value="QUARTERLY"></el-option>
-          <el-option label="半年" value="YEAR_HALF"></el-option>
-          <el-option label="年度" value="YEAR"></el-option>
-          <el-option label="固定天数" value="DAY"></el-option>
-        </el-select>
-      </el-form-item>
-      <el-form-item
-        label="赠送数量"
-        prop="times"
-        :rules="[
-          { required: true, message: '请输入赠送数量', trigger: 'blur' },
-        ]"
-      >
-        <el-input
-          type="number"
-          onKeypress="return (/[\d]/.test(String.fromCharCode(event.keyCode)))"
-          v-model="memberForm.times"
-          placeholder="请输入赠送数量"
-        >
-        </el-input>
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-<script>
-import { cloudAddStudents } from "../../api";
-export default {
-  props: ["multipleSelection"],
-  data() {
-    return {
-      memberForm: {
-        times: null,
-        addType: null,
-      },
-      studentIds: [],
-    };
-  },
-  mounted() {
-    this.studentIds = this.multipleSelection
-      .map((stu) => {
-        return stu.userId;
-      });
-  },
-  methods: {
-    submit() {
-      this.$refs.memberForm.validate(async (res) => {
-        if (res) {
-          try {
-            const { times, addType } = this.memberForm
-            await cloudAddStudents({
-              times: Number(times),
-              addType,
-              studentIds: this.studentIds,
-            });
-            this.$message.success('添加会员成功')
-            this.$emit("close");
-            this.$emit("submited");
-          } catch (e) {
-            console.log(e);
-          }
-        }
-      });
-    },
-  },
-};
-</script>
-<style lang="scss" scoped>
-.title {
-  margin-bottom: 30px;
-  font-size: 16px;
-  color: #000;
-}
-</style>