소스 검색

新增许愿树校验

tanlie 1 개월 전
부모
커밋
9bed6bf738

+ 1 - 1
wishing-admin/src/api/wishing/tree.js

@@ -17,7 +17,7 @@ export function queryTreePage(params = {}, headers = {}) {
  * @param params 请求参数
  * @param headers 请求头
  */
-export function createRole(params = {}, headers = {}) {
+export function creatTree(params = {}, headers = {}) {
   return post({
     url: '/admin/tree/create',
     params: params,

+ 0 - 322
wishing-admin/src/components/import-file.vue

@@ -1,322 +0,0 @@
-<template>
-  <div>
-    <el-dialog :close-on-click-modal="false" :width="dialogWidth" :visible="visible" :title="title" @close="close">
-      <div class="import-file-box">
-        <div class="box-left">
-          <div class="box-tips">
-            <div class="box-text">
-              <slot name="tipText"></slot>
-            </div>
-          </div>
-          <div class="box-btn" style="padding-top: 10px">
-            <div class="btn-s">
-              <el-button style="width: 100%" type="success" @click="downloadFn">模板下载</el-button>
-            </div>
-            <div class="btn-s" style="padding-top: 10px">
-              <div class="upload-box">
-                <el-upload
-                  :file-list="fileList"
-                  :headers="upload.headers"
-                  :action="upload.action"
-                  :data="upload.extraData"
-                  :name="upload.fieldName"
-                  :on-success="handleSuccess"
-                  :on-error="handleError"
-                  :before-upload="handleBeforeUpload"
-                >
-                  <el-button style="width: 100%" type="primary">导入文件</el-button>
-                </el-upload>
-              </div>
-              <div class="error-show-btn">
-                <el-button style="width: 100%" plain type="primary" @click="viewShowError(!errorTable)">
-                  {{ errorBtnText }}
-                  <i class="el-icon-arrow-right el-icon--right"></i>
-                </el-button>
-              </div>
-            </div>
-          </div>
-        </div>
-        <div class="box-right" v-if="errorTable">
-          <div class="process-msg">
-            总记录数:{{ totalSize }}, 已处理记录数: {{ processedSize }}, 保存成功记录数: {{ savedSize }}
-          </div>
-          <el-table class="error-table-box" ref="errorTable" stripe border tooltip-effect="dark" :data="data">
-            <el-table-column type="index" label="序号" align="center" width="50" />
-            <el-table-column prop="errorPosition" label="错误位置" align="left" width="200" />
-            <el-table-column prop="errorMessage" label="错误信息" align="left" />
-          </el-table>
-        </div>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import { download } from '@api/api';
-import { uuid } from '@utils/util';
-export default {
-  name: 'importFile',
-  props: {
-    title: {
-      type: String,
-      default: '导入功能'
-    },
-    visible: {
-      type: Boolean,
-      default: false
-    },
-    tips: {
-      type: String,
-      default: ''
-    },
-    uploadParams: {
-      type: Object,
-      default: () => {
-        return {};
-      }
-    }
-  },
-  computed: {
-    upload() {
-      return {
-        action: `${process.env.VUE_APP_API_PREFIX}` + this.uploadParams.url || '',
-        headers: {
-          Authorization: `Bearer ${this.$store.getters.accessToken}`
-        },
-        extraData: this.uploadParams.extraData || {},
-        fieldName: this.uploadParams.fieldName || 'file',
-        showProcess: this.uploadParams.showProcess || false
-      };
-    },
-    template() {
-      return {
-        templateUrl: this.uploadParams.templateUrl || '',
-        templateParams: this.uploadParams.templateParams || {}
-      };
-    }
-  },
-  data() {
-    return {
-      data: [],
-      columns: [
-        {
-          type: 'index',
-          width: 60,
-          align: 'center'
-        },
-        {
-          title: '错误位置',
-          width: 300,
-          key: 'errorPosition'
-        },
-        {
-          title: '错误信息',
-          tooltip: true,
-          key: 'errorMessage'
-        }
-      ],
-      fileList: [],
-      errorTable: false,
-      errorBtnText: '打开导入情况详情',
-      dialogWidth: '400px',
-      wsClient: null,
-      totalSize: 0,
-      processedSize: 0,
-      savedSize: 0
-    };
-  },
-  methods: {
-    close() {
-      this.data = [];
-      this.$emit('close');
-    },
-    downloadFn() {
-      download({
-        url: this.template.templateUrl,
-        params: this.template.templateParams
-      });
-    },
-    handleBeforeUpload(file) {
-      let vm = this;
-      vm.upload.headers['x-requestId'] = uuid();
-      vm.upload.headers['x-timestamp'] = new Date().getTime();
-      vm.totalSize = 0;
-      vm.processedSize = 0;
-      vm.savedSize = 0;
-      vm.data = [];
-      if (vm.upload.showProcess) {
-        vm.wsInit();
-      }
-    },
-    handleSuccess(res, file, fileList) {
-      let vm = this;
-      vm.fileList = [file];
-      let result = res.data;
-      if (result instanceof Object) {
-        vm.totalSize = result.totalSize;
-        vm.processedSize = result.totalSize;
-        vm.savedSize = result.savedSize;
-        let hasErrors = result.tableErrorMessages.length > 0;
-        vm.$message({
-          showClose: true,
-          duration: 10000,
-          message: hasErrors ? '导入完成, 有数据错误' : res.msg,
-          type: hasErrors ? 'warning' : 'success'
-        });
-        vm.data = result.tableErrorMessages;
-        vm.viewShowError(hasErrors);
-      }
-      if (typeof result === 'boolean' && result) {
-        vm.$message({
-          showClose: true,
-          duration: 10000,
-          message: '上传完成,正在处理数据,请稍候....',
-          type: 'success'
-        });
-        vm.viewShowError(result);
-      }
-    },
-    handleError(e, file, fileList) {
-      let vm = this;
-      let error = JSON.parse(e.message);
-      vm.$message.error(error.data);
-      if (vm.upload.showProcess) {
-        vm.wsClose();
-      }
-    },
-    async wsInit() {
-      let vm = this;
-      let wsToken = vm.$store.getters.wsToken;
-      let token = vm.$store.getters.accessToken;
-      // 获取域名和端口, 然后做处理
-      let wsProtocol = 'ws://';
-      if (window.location.protocol === 'https:') {
-        wsProtocol = 'wss://';
-      }
-      let httpUrl = `${wsProtocol}${window.location.host}${process.env.VUE_APP_API_PREFIX}/recruit-common/ws/file/${wsToken}?token=${token}`;
-      // httpUrl替换成wsUrl
-      let wsUrl = httpUrl;
-      vm.wsClient = new WebSocket(wsUrl);
-      vm.wsClient.onopen = await vm.wsOpen;
-      vm.wsClient.onclose = vm.wsClose;
-      vm.wsClient.onerror = vm.wsError;
-      vm.wsClient.onmessage = vm.wsMessage;
-    },
-    // 开始连接
-    wsOpen() {
-      let vm = this;
-      // 监听事件
-      console.log('websocket 已连接 ...');
-      // 发送心跳
-      vm.wsSend({ type: 'ping' });
-    },
-    // 关闭连接
-    wsClose(e) {
-      console.log('websocket 已关闭 ...', e);
-    },
-    // 连接错误
-    wsError() {
-      console.log('websocket 连接错误...');
-    },
-    // 接收信息, 并处理
-    wsMessage(res) {
-      let vm = this;
-      console.log(res.data);
-      let result = JSON.parse(res.data);
-      if (result.data === 'pong') {
-        return;
-      }
-      vm.data.push(...result.data.tableErrorMessages);
-      vm.totalSize = result.data.totalSize;
-      vm.processedSize++;
-      vm.savedSize += result.data.savedSize;
-      if (vm.totalSize === vm.processedSize) {
-        vm.wsClient.close();
-      }
-    },
-    wsSend(message) {
-      let vm = this;
-      vm.wsClient.send(JSON.stringify(message));
-    },
-    viewShowError(isOpen) {
-      if (isOpen) {
-        this.errorBtnText = '关闭导入情况详情';
-        this.dialogWidth = '1000px';
-      } else {
-        this.errorBtnText = '打开导入情况详情';
-        this.dialogWidth = '400px';
-      }
-      this.errorTable = isOpen;
-    }
-  },
-  destroyed() {
-    if (this.wsClient) {
-      this.wsClient.close();
-    }
-  }
-};
-</script>
-
-<style lang="less" scoped>
-:deep(.el-dialog__body) {
-  padding-top: 0;
-}
-
-.import-file-box {
-  display: flex;
-
-  .box-left {
-    display: flex;
-    flex-direction: column;
-    max-width: 400px;
-
-    .box-tips {
-      max-height: 300px;
-      padding: 10px 16px;
-      background-color: @theme-light-color + 10;
-      border: 1px solid @theme-gray-color + 50;
-      border-radius: 4px;
-      overflow: auto;
-
-      .box-text {
-        line-height: 1.8;
-        text-align: justify;
-      }
-    }
-
-    .box-btn {
-      flex: 1;
-
-      .btn-s {
-        display: flex;
-
-        .upload-box {
-          flex: 1;
-
-          :deep(.el-upload) {
-            width: 100%;
-          }
-        }
-
-        .error-show-btn {
-          flex: 1;
-          padding-left: 10px;
-        }
-      }
-    }
-  }
-
-  .box-right {
-    flex: 1;
-    padding-left: 20px;
-
-    .process-msg {
-      font-size: 18px;
-      margin-bottom: 10px;
-    }
-    .error-table-box {
-      height: 92%;
-    }
-  }
-}
-</style>

+ 0 - 152
wishing-admin/src/components/upload-pic.vue

@@ -1,152 +0,0 @@
-<template>
-  <div>
-    <el-upload
-      ref="upload"
-      list-type="picture-card"
-      accept="image/jpeg, image/jpg, image/png"
-      :disabled="disabled"
-      :class="['uploader', uploadDisabled ? 'disabled' : '']"
-      :file-list="upload.fileList"
-      :headers="upload.headers"
-      :action="upload.action"
-      :data="upload.extraData"
-      :name="upload.fieldName"
-      :limit="upload.limit"
-      :on-success="handleSuccess"
-      :on-error="handleError"
-      :on-preview="handlePreview"
-      :on-remove="handleRemove"
-      :before-remove="handleBeforeRemove"
-      :before-upload="handleBeforeUpload"
-    >
-      <i :class="disabled ? 'el-icon-picture-outline' : 'el-icon-plus'"></i>
-    </el-upload>
-    <el-image-viewer
-      v-if="imgDialog.visible"
-      :on-close="() => (imgDialog.visible = false)"
-      :url-list="viewList"
-      :zIndex="10000"
-    />
-  </div>
-</template>
-
-<script>
-import { getStore } from '@utils/store';
-import { uuid } from '@utils/util';
-import { removeAttachment } from '@api/api-login';
-import elImageViewer from 'element-ui/packages/image/src/image-viewer';
-export default {
-  name: 'uploadPic',
-  components: {
-    elImageViewer
-  },
-  props: {
-    disabled: {
-      type: Boolean,
-      default: false
-    },
-    uploadParams: {
-      type: Object,
-      default: () => {
-        return {};
-      }
-    }
-  },
-  computed: {
-    uploadDisabled() {
-      return this.files.length >= this.upload.limit;
-    }
-  },
-  data() {
-    return {
-      files: [],
-      viewList: [],
-      upload: {
-        action: `${process.env.VUE_APP_API_PREFIX + this.uploadParams.url || ''}`,
-        headers: {
-          Authorization: 'Bearer ' + getStore('accessToken'),
-          'x-upload-type': this.uploadParams.uploadType
-        },
-        extraData: this.uploadParams.extraData || {},
-        fieldName: this.uploadParams.fieldName || 'file',
-        fileList: this.uploadParams.fileList || [],
-        limit: this.uploadParams.limit || 1
-      },
-      imgDialog: {
-        visible: false,
-        title: '查看',
-        url: ''
-      }
-    };
-  },
-  methods: {
-    handleBeforeUpload(file) {
-      let vm = this;
-      vm.upload.headers['x-requestId'] = uuid();
-      vm.upload.headers['x-timestamp'] = new Date().getTime();
-    },
-    handleSuccess(res, file, fileList) {
-      let params = {
-        id: res.data.id,
-        name: res.data.name,
-        url: res.data.url,
-        virtualName: res.data.virtualName
-      };
-      this.files.push(params);
-      this.$emit('uploadFiles', this.files);
-    },
-    handleError(e, file, fileList) {
-      this.$message.error(JSON.parse(e.message).data);
-    },
-    handlePreview(file) {
-      let vm = this;
-      vm.imgDialog.visible = true;
-      vm.imgDialog.url = file.url;
-      vm.viewList = [file.url];
-    },
-    handleRemove(file, fileList) {
-      let params = {
-        id: file.id || file.response.data.id
-      };
-      removeAttachment(params, { 'x-upload-type': this.uploadParams.uploadType }).then(() => {
-        this.files = this.files.filter((o) => o.id !== params.id);
-        this.$emit('uploadFiles', this.files);
-      });
-    },
-    handleBeforeRemove(file, fileList) {
-      return this.$confirm(`此操作将删除${file.name}, 是否继续?`, '提示', { type: 'warning' });
-    }
-  },
-  created() {
-    this.files = [];
-    this.files.push(...this.upload.fileList);
-  }
-};
-</script>
-
-<style lang="less">
-.uploader {
-  display: flex;
-  // width: 187px;
-  // height: 187px;
-}
-.uploader .el-upload {
-  width: 187px;
-  height: 187px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
-
-.uploader .el-upload:hover {
-  border-color: #409eff;
-}
-.disabled .el-upload--picture-card {
-  display: none;
-}
-
-.el-upload-list--picture-card .el-upload-list__item {
-  width: 187px;
-  height: 187px;
-}
-</style>

+ 22 - 20
wishing-admin/src/utils/validate.js

@@ -187,25 +187,27 @@ export function isArray(o) {
 }
 
 /**
- * 检测密码强度
- * @param str
+ * 检查是否是数字(包含小数),支持整数、带小数点的数字以及以点开头的小数(如 .5),不允许带 + 或 - 号
+ * @param val
  */
-export function checkPwdStrength(pwd) {
-  let lv = 0;
-  if (pwd.length < 8) {
-    return lv;
-  }
-  if (/[0-9]/.test(pwd)) {
-    lv++;
-  }
-  if (/[a-z]/.test(pwd)) {
-    lv++;
-  }
-  if (/[A-Z]/.test(pwd)) {
-    lv++;
-  }
-  if (/[.|-|_]/.test(pwd)) {
-    lv++;
-  }
-  return lv;
+export function isNumber(val) {
+  if (val === null || val === undefined || val === '') return false;
+  // 若已为数字类型且为有限数值,则必须为非负数(不允许负数)
+  if (typeof val === 'number' && isFinite(val)) return val >= 0;
+  // 字符串形式的数字:仅允许不带符号的整数或小数(例如 123, 123.45, .5),不允许 + 或 -
+  return /^(?:\d+(?:\.\d+)?|\.\d+)$/.test(String(val).trim());
+}
+
+/**
+ * 检查是否是整数(支持 number 类型和字符串形式的整数)
+ * 例如:123, -42, +7, "0" 都返回 true;"3.0", 3.5, ".5", "abc" 返回 false
+ * @param val
+ */
+export function isInteger(val) {
+  // 不允许带有 + 或 - 符号(对字符串和 number 都不允许负数或带符号)
+  if (val === null || val === undefined || val === '') return false;
+  // 若为 number 类型且为有限数值,则必须是整数且非负
+  if (typeof val === 'number' && isFinite(val)) return Number.isInteger(val) && val >= 0;
+  // 字符串形式的整数:仅允许不带符号的纯数字(允许前后空白)
+  return /^\d+$/.test(String(val).trim());
 }

+ 25 - 22
wishing-admin/src/views/layout/bread.vue

@@ -19,27 +19,30 @@ export default {
 
 <style scoped lang="less">
 .header_title {
-  // Apply to breadcrumb items and any internal nodes (a, span, router-link's root)
-  :deep(.el-breadcrumb__item),
-  :deep(.el-breadcrumb__item *),
-  :deep(.el-breadcrumb),
-  :deep(.el-breadcrumb a),
-  :deep(.el-breadcrumb a *),
-  :deep(.el-breadcrumb__inner) {
-    -webkit-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-    -webkit-touch-callout: none;
-    caret-color: transparent;
-    cursor: pointer;
-    outline: none;
-  }
+  // keep breadcrumb container scoped, specifics handled below
+}
+// Prevent text caret and focus outline on breadcrumb items (apply deeply into child components)
+/deep/ .el-breadcrumb__item,
+/deep/ .el-breadcrumb__item *,
+/deep/ .el-breadcrumb,
+/deep/ .el-breadcrumb a,
+/deep/ .el-breadcrumb a *,
+/deep/ .el-breadcrumb__inner,
+/deep/ .el-breadcrumb * {
+  -webkit-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  -webkit-touch-callout: none;
+  caret-color: transparent;
+  cursor: pointer;
+  outline: none;
+}
 
-  :deep(.el-breadcrumb__item:focus),
-  :deep(.el-breadcrumb__item *:focus),
-  :deep(.el-breadcrumb a:focus) {
-    outline: none;
-    caret-color: transparent;
-  }
+/deep/ .el-breadcrumb__item:focus,
+/deep/ .el-breadcrumb__item *:focus,
+/deep/ .el-breadcrumb a:focus,
+/deep/ .el-breadcrumb *:focus,
+/deep/ .el-breadcrumb__inner:focus {
+  outline: none;
+  caret-color: transparent;
 }
-</style>

+ 23 - 15
wishing-admin/src/views/personal/personal-setting.vue

@@ -24,12 +24,7 @@
       </div>
       <div class='avatar-box'>
         <el-form-item label='头像' prop='avatar'>
-          <uploadPic v-if='curState !== 1' ref='uploadPic' :uploadParams='uploadParams' :disabled='picDisabled'
-                     @uploadFiles='uploadFiles' />
-          <div v-else>
-            <img style='border-radius: 10px;width: 187px; height: 187px;' :src='userInfo.avatar' alt=''>
-          </div>
-
+          <div>hi</div>
         </el-form-item>
       </div>
     </el-form>
@@ -44,15 +39,12 @@
 </template>
 
 <script>
-import uploadPic from '@comp/upload-pic';
 import { isMobile } from '@utils/validate';
-import { uploadUserAvatar, updateSelfUserDetail, fetchUserInfo, fetchUserById } from '@api/upms/api-user';
+import { fetchUserById, fetchUserInfo, updateSelfUserDetail, uploadUserAvatar } from '@api/upms/api-user';
 
 export default {
   name: 'PersonalSetting',
-  components: {
-    uploadPic
-  },
+  components: {},
   props: {
     userInfo: {
       type: Object,
@@ -94,11 +86,27 @@ export default {
       },
       uploadParams: {},
       formRules: {
-        fullName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+        fullName: [{
+          required: true,
+          message: '请输入姓名',
+          trigger: 'blur'
+        }],
         mobile: [
-          { required: true, message: '请输入手机号码', trigger: 'blur' },
-          { len: 11, message: '长度11个字符', trigger: 'blur' },
-          { required: true, validator: validateMobile, trigger: 'blur' }
+          {
+            required: true,
+            message: '请输入手机号码',
+            trigger: 'blur'
+          },
+          {
+            len: 11,
+            message: '长度11个字符',
+            trigger: 'blur'
+          },
+          {
+            required: true,
+            validator: validateMobile,
+            trigger: 'blur'
+          }
         ],
         email: [
           {

+ 1 - 31
wishing-admin/src/views/system/dictionary.vue

@@ -51,34 +51,6 @@
     >
       <dictionaryOption ref='dictionaryOption' :dictId='optionFormDialog.dictId' />
     </el-dialog>
-    <importFile
-      :title='importFile.title'
-      :visible='importFile.visible'
-      :uploadParams='uploadParams'
-      @search='searchFn'
-      @close='importCloseFn'
-    >
-      <div slot='tipText'>
-        <div>
-          1、在边栏中,选择提醒事项列表,或按下 Command
-          键并点按以选择多个列表。如果边栏没有显示,请选取“显示”>“显示边栏”。
-        </div>
-        <div>2、选取“文件”>“导出”。</div>
-        <div>3、输入名称,选取位置,然后点按“导出”。列表以 ICS 文件格式导出。</div>
-        <div>
-          1、在边栏中,选择提醒事项列表,或按下 Command
-          键并点按以选择多个列表。如果边栏没有显示,请选取“显示”>“显示边栏”。
-        </div>
-        <div>2、选取“文件”>“导出”。</div>
-        <div>3、输入名称,选取位置,然后点按“导出”。列表以 ICS 文件格式导出。</div>
-        <div>
-          1、在边栏中,选择提醒事项列表,或按下 Command
-          键并点按以选择多个列表。如果边栏没有显示,请选取“显示”>“显示边栏”。
-        </div>
-        <div>2、选取“文件”>“导出”。</div>
-        <div>3、输入名称,选取位置,然后点按“导出”。列表以 ICS 文件格式导出。</div>
-      </div>
-    </importFile>
   </div>
 </template>
 
@@ -91,13 +63,11 @@ import {
   removeDictionary,
   updateDictionary
 } from '@api/upms/api-dictionary';
-import importFile from '@comp/import-file';
 
 export default {
   name: 'Dictionary',
   components: {
-    dictionaryOption,
-    importFile
+    dictionaryOption
   },
   data() {
     return {

+ 78 - 49
wishing-admin/src/views/wishing/tree/list.vue

@@ -12,10 +12,10 @@
     >
       <template slot='search'>
         <el-form-item label='手机号'>
-          <el-input v-model.trim='searchParams.mobile' />
+          <el-input v-model.trim='searchParams.name' />
         </el-form-item>
         <el-form-item label='内容关键字'>
-          <el-input v-model.trim='searchParams.name' />
+          <el-input v-model.trim='searchParams.discription' />
         </el-form-item>
       </template>
     </baseTable>
@@ -29,19 +29,20 @@
         :rules="formDialog.formRules"
       >
         <el-row>
-          <el-form-item label="用户名" prop="username" v-if="formDialog.isAdd">
-            <el-input v-model.trim="formDialog.formData.username" />
+          <el-form-item label="许愿树名称" prop="name">
+            <el-input v-model.trim="formDialog.formData.name" />
           </el-form-item>
-          <el-form-item label="姓名" prop="fullName">
-            <el-input v-model.trim="formDialog.formData.fullName" />
+          <el-form-item label="经度" prop="longitude">
+            <el-input v-model.trim="formDialog.formData.longitude" />
           </el-form-item>
-          <el-form-item label="手机号码" prop="mobile">
-            <el-input v-model.trim="formDialog.formData.mobile" />
+          <el-form-item label="纬度" prop="latitude">
+            <el-input v-model.trim="formDialog.formData.latitude" />
           </el-form-item>
-          <el-form-item label="电子邮箱" prop="email">
-            <el-input v-model.trim="formDialog.formData.email" />
+          <el-form-item label="可许愿半径" prop="radius">
+            <el-input type="number" v-model.trim="formDialog.formData.radius" />
           </el-form-item>
-          <el-form-item label='头像1' prop='avatar'>
+          <el-form-item label='封面图片' prop='coverImage'>
+            <el-input style="display: none" v-model.trim="formDialog.formData.coverImage" />
             <el-upload
               class="avatar-uploader"
               :action="upload.action"
@@ -49,10 +50,13 @@
               :show-file-list="false"
               :on-success="handleSuccess"
             >
-              <img v-if="imageUrl" :src="imageUrl" class="avatar" />
-                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+              <img v-if="imageUrl" :src="imageUrl" class="avatar" alt="" />
+              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
             </el-upload>
           </el-form-item>
+          <el-form-item label="许愿树描述" prop="description">
+            <el-input type='textarea' v-model.trim='formDialog.formData.description' :rows='4' />
+          </el-form-item>
         </el-row>
       </el-form>
       <div slot="footer" class="dialog-footer">
@@ -64,13 +68,30 @@
 </template>
 
 <script>
-import { queryTreePage } from '@api/wishing/tree';
-import { createUser, removeUser, updateUserDetail } from '@api/upms/api-user';
+import { creatTree, queryTreePage } from '@api/wishing/tree';
+import { removeUser, updateUserDetail } from '@api/upms/api-user';
+import { isNumber,isInteger } from '@utils/validate';
 
 export default {
   name: 'WishingTree',
 
   data() {
+    let validateNumber = (rule, value, callback) => {
+      if (!isNumber(value)) {
+        return callback(new Error('经纬度只能是数字'));
+      } else {
+        return callback();
+      }
+    };
+
+    let validateInteger = (rule, value, callback) => {
+      if (!isInteger(value)) {
+        return callback(new Error('可许愿半径只能是整数'));
+      } else {
+        return callback();
+      }
+    };
+
     return {
       tableHeader: [
         {
@@ -139,54 +160,51 @@ export default {
         isAdd: false,
         formData: {
           id: 0,
-          username: '',
-          fullName: '',
-          email: '',
-          avatar: '',
-          coverImage: ''
-        },
-        defaultData: {
-          sex: '3',
-          attachDataList: []
+          address: '',
+          coverImage: '',
+          description: '',
+          latitude: null,
+          longitude: null,
+          name: '',
+          radius: 100,
+          totalWishes: 0
         },
         formRules: {
-          username: [
+          name: [
             {
               required: true,
-              message: '请输入用户名',
+              message: '请输入许愿树名称',
               trigger: 'blur'
             }
           ],
-          fullName: [{
-            required: true,
-            message: '请输入姓名',
-            trigger: 'blur'
-          }],
-          mobile: [
+          latitude: [
             {
               required: true,
-              message: '请输入手机号码',
+              message: '请输入纬度',
               trigger: 'blur'
             },
             {
-              len: 11,
-              message: '长度11个字符',
+              validator: validateNumber,
               trigger: 'blur'
             }
           ],
-          email: [
+          longitude: [
             {
-              required: false,
-              type: 'email',
-              message: '请输入正确的电子邮箱',
+              required: true,
+              message: '请输入经度',
+              trigger: 'blur'
+            },
+            {
+              validator: validateNumber,
               trigger: 'blur'
             }
           ],
-          roleIds: [{
-            required: true,
-            message: '请选择对应的角色',
-            trigger: 'change'
-          }]
+          radius: [
+            {
+              validator: validateInteger,
+              trigger: 'blur'
+            }
+          ]
         }
       }
     };
@@ -227,25 +245,30 @@ export default {
       vm.formDialog.visible = true;
       vm.formDialog.loading = false;
       vm.formDialog.isAdd = true;
-      vm.formDialog.formData = Object.assign({}, vm.formDialog.defaultData);
+      vm.formDialog.formData = {};
     },
     cancelFn() {
       let vm = this;
       vm.formDialog.visible = false;
       vm.formDialog.loading = false;
       vm.formDialog.isAdd = false;
-      vm.formDialog.formData = Object.assign({}, vm.formDialog.defaultData);
+      vm.formDialog.formData = {};
       vm.$refs.userForm.resetFields();
     },
     submitFn() {
       let vm = this;
       vm.formDialog.loading = true;
+      if (!vm.formDialog.formData.coverImage || vm.formDialog.formData.coverImage === '') {
+        vm.$message.error('请上传封面图片');
+        vm.formDialog.loading = false;
+        return;
+      }
       vm.$refs.userForm.validate((valid) => {
         if (!valid) {
           vm.formDialog.loading = false;
           return;
         }
-        if (vm.formDialog.formData.id) {
+        if (this.formDialog.formData.id) {
           let formData = vm.formDialog.formData;
           updateUserDetail(formData).then(
             (res) => {
@@ -264,11 +287,12 @@ export default {
           );
         } else {
           let formData = vm.formDialog.formData;
-          createUser(formData).then(
+          creatTree(formData).then(
             (res) => {
               vm.$message.success('新增成功');
               vm.formDialog.visible = false;
               vm.formDialog.loading = false;
+              vm.formDialog.formData = {};
               vm.searchFn(true);
             },
             (error) => {
@@ -303,7 +327,12 @@ export default {
       });
     },
     handleSuccess(res, file, fileList) {
-      console.log(res);
+      if (res.code === 200) {
+        this.imageUrl = res.data.url;
+        this.formDialog.formData.coverImage = res.data.url;
+      } else {
+        this.$message.error(res.msg);
+      }
     }
   }
 };

+ 2 - 1
wishing-platform/platform-service/platform-service-admin/src/main/java/cn/qinys/platform/admin/controller/WishTreeController.java

@@ -7,6 +7,7 @@ import cn.qinys.platform.admin.service.WishTreeService;
 import cn.qinys.platform.base.response.UnifyResponse;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
 import org.springframework.web.bind.annotation.*;
 
 /**
@@ -29,7 +30,7 @@ public class WishTreeController {
     }
 
     @PostMapping("/create")
-    public UnifyResponse<Long> createWishTree(@RequestBody WishingTreeCreateReq req) {
+    public UnifyResponse<Long> createWishTree(@RequestBody @Valid WishingTreeCreateReq req) {
         Long id = wishTreeService.createWishTree(req);
         return new UnifyResponse<>("created", id);
     }