sunlupeng 1 год назад
Родитель
Сommit
7654ed6edc

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/assets/icons/svg/success.svg


+ 137 - 0
src/components/MessageTable/index.vue

@@ -0,0 +1,137 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索工作栏 -->
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="是否已读" prop="readStatus">
+        <el-select v-model="queryParams.readStatus" placeholder="请选择状态" clearable>
+          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+                     :key="dict.value" :label="dict.label" :value="dict.value"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="发送时间" prop="createTime">
+        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
+                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作工具栏 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleUpdateList">标记已读</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleUpdateAll">全部已读</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <!-- 列表 -->
+    <el-table v-loading="loading" ref="tables" :data="list">
+      <el-table-column type="selection" width="55" />
+      <el-table-column label="发送人" align="center" prop="templateNickname" width="120" />
+      <el-table-column label="发送时间" align="center" prop="createTime" width="180">
+        <template v-slot="scope">
+          <span>{{ parseTime(scope.row.createTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="类型" align="center" prop="templateType" width="80">
+        <template v-slot="scope">
+          <dict-tag :type="DICT_TYPE.SYSTEM_NOTIFY_TEMPLATE_TYPE" :value="scope.row.templateType" />
+        </template>
+      </el-table-column>
+      <el-table-column label="内容" align="center" prop="templateContent" />
+      <el-table-column label="是否已读" align="center" prop="readStatus" width="80">
+        <template v-slot="scope">
+          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.readStatus"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
+        <template v-slot="scope">
+          <el-button v-show="!scope.row.readStatus" size="mini" type="text" icon="el-icon-check" @click="handleUpdateSingle(scope.row)">已读</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页组件 -->
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
+                @pagination="getList"/>
+
+  </div>
+</template>
+
+<script>
+import {getMyNotifyMessagePage, updateAllNotifyMessageRead, updateNotifyMessageRead} from "@/api/system/notify/message";
+
+export default {
+  name: "SystemMyNotify",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 我的站内信列表
+      list: [],
+      // 查询参数
+      queryParams: {
+        pageNo: 1,
+        pageSize: 10,
+        readStatus: null,
+        createTime: []
+      },
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询列表 */
+    getList() {
+      this.loading = true;
+      // 执行查询
+      getMyNotifyMessagePage(this.queryParams).then(response => {
+        this.list = response.data.list;
+        this.total = response.data.total;
+        this.loading = false;
+      });
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNo = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleUpdateList() {
+      let list = this.$refs["tables"].selection;
+      if (list.length === 0) {
+        return;
+      }
+      this.handleUpdate(list.map(v => v.id))
+    },
+    handleUpdateSingle(row) {
+      this.handleUpdate([row.id])
+    },
+    handleUpdate(ids) {
+      updateNotifyMessageRead(ids).then(response => {
+        this.$modal.msgSuccess("标记已读成功!");
+        this.getList();
+      });
+    },
+    handleUpdateAll(){
+      updateAllNotifyMessageRead().then(response => {
+        this.$modal.msgSuccess("全部已读成功!");
+        this.getList();
+      });
+    }
+  }
+}
+</script>

+ 1 - 1
src/permission.js

@@ -64,7 +64,7 @@ NProgress.configure({ showSpinner: false })
 // ]
 
 // 增加三方登陆 update by 芋艿
-const whiteList = ['/login','/social-login',  '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee']
+const whiteList = ['/login','/register','/password/forget','/password/reset','/social-login',  '/auth-redirect', '/bind',  '/oauthLogin/gitee']
 
 router.beforeEach((to, from, next) => {
   NProgress.start()

+ 15 - 0
src/router/index.js

@@ -39,6 +39,21 @@ export const constantRoutes = [
       }
     ]
   },
+  {
+    path: '/password/forget',
+    component: (resolve) => require(['@/views/password/forget'], resolve),
+    hidden: true
+  },
+  {
+    path: '/password/reset',
+    component: (resolve) => require(['@/views/password/reset'], resolve),
+    hidden: true
+  },
+  // {
+  //   path: '/password/forget',
+  //   component: (resolve) => require(['@/views/password/forget'], resolve),
+  //   hidden: true
+  // },
   {
     path: '/login',
     component: (resolve) => require(['@/views/login'], resolve),

Разница между файлами не показана из-за своего большого размера
+ 252 - 129
src/views/index.vue


+ 20 - 4
src/views/login.vue

@@ -14,6 +14,7 @@
 
         <!-- 表单 -->
         <div class="form-cont">
+          <div class="login-title">账号登录</div>
           <el-tabs class="form" v-model="loginForm.loginType" style=" float:none;">
             <el-tab-pane label="密码登录" name="uname">
             </el-tab-pane>
@@ -22,11 +23,11 @@
           </el-tabs>
           <div>
             <el-form ref="loginForm" :model="loginForm" :rules="LoginRules" class="login-form">
-              <el-form-item prop="tenantName" v-if="tenantEnable">
+              <!-- <el-form-item prop="tenantName" v-if="tenantEnable">
                 <el-input v-model="loginForm.tenantName" type="text" auto-complete="off" placeholder='租户'>
                   <svg-icon slot="prefix" icon-class="tree" class="el-input__icon input-icon"/>
                 </el-input>
-              </el-form-item>
+              </el-form-item> -->
               <!-- 账号密码登录 -->
               <div v-if="loginForm.loginType === 'uname'">
                 <el-form-item prop="username">
@@ -40,7 +41,8 @@
                     <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon"/>
                   </el-input>
                 </el-form-item>
-                <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;">记住密码</el-checkbox>
+                <el-checkbox v-model="loginForm.rememberMe" style="margin:0 0 25px 0;">下次自动登录</el-checkbox>
+                <a class="forget-password" href="/password/forget">忘记密码?</a>
               </div>
 
               <!-- 短信验证码登录 -->
@@ -334,7 +336,21 @@ export default {
 </script>
 <style lang="scss" scoped>
 @import "~@/assets/styles/login.scss";
-
+.forget-password {
+  float: right;
+    color: #1890ff;
+    font-size: 14px;
+}
+a {
+    outline: none;
+    text-decoration: none;
+}
+.login-title{
+  color: #141e31;
+    font-size: 32px;
+    font-weight: 500;
+    line-height: 48px;
+}
 .register-tip{
   color: #141e31;
     font-size: 14px;

+ 211 - 0
src/views/password/forget.vue

@@ -0,0 +1,211 @@
+<template>
+  <div class="fx-account-layout jdy-page-password-forget">
+    <!-- <a class="account-logo" href="/">
+      <img class="official-logo" src="https://g.jdycdn.com/shared/images/logo/logo_text.png" alt="">
+    </a> -->
+    <div class="account-pane-container hide-banner">
+      <div class="account-pane">
+        <div class="account-container password-forget-container">
+          <div class="account-header">忘记密码</div>
+          <div class="account-content">
+            <el-form ref="loginForm" :model="loginForm" :rules="LoginRules" class="login-form">
+              <el-form-item prop="mobile">
+                 <el-input v-model="loginForm.mobile" type="text" auto-complete="off" placeholder="请输入手机号">
+                 </el-input>
+               </el-form-item>
+               <el-form-item prop="mobileCode">
+                 <el-input v-model="loginForm.mobileCode" type="text" auto-complete="off" placeholder="短信验证码"
+                           class="sms-login-mobile-code-prefix"
+                           @keyup.enter.native="handleLogin">
+                   <template>
+                   </template>
+                   <template slot="append">
+                     <span v-if="mobileCodeTimer <= 0" class="getMobileCode" @click="getSmsCode" style="cursor: pointer;">获取验证码</span>
+                     <span v-if="mobileCodeTimer > 0" class="getMobileCode">{{ mobileCodeTimer }}秒后可重新获取</span>
+                   </template>
+                 </el-input>
+               </el-form-item>
+               <el-form-item>
+                 <el-button size="medium" type="primary" style="width:100%;"
+                 @click="submitForm('loginForm')">
+                  重置密码
+                 </el-button>
+                 <el-button style="margin-left: 0;margin-top: 10px;width: 100%;" type="text" @click="backLogin()">返回登录</el-button>
+               </el-form-item>
+           </el-form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { sendSmsCode } from "@/api/login";
+export default {
+  data() {
+    return {
+      mobileCodeTimer: 0,
+      loginForm: {
+        mobile: "",
+        mobileCode: "",
+      },
+      LoginRules: {
+        username: [
+          {required: true, trigger: "blur", message: "用户名不能为空"}
+        ],
+        password: [
+          {required: true, trigger: "blur", message: "密码不能为空"}
+        ],
+        mobile: [
+          {required: true, trigger: "blur", message: "手机号不能为空"},
+          {
+            validator: function (rule, value, callback) {
+              if (/^(?:(?:\+|00)86)?1(?:3[\d]|4[5-79]|5[0-35-9]|6[5-7]|7[0-8]|8[\d]|9[189])\d{8}$/.test(value) === false) {
+                callback(new Error("手机号格式错误"));
+              } else {
+                callback();
+              }
+            }, trigger: "blur"
+          }
+        ],
+        tenantName: [
+          {required: true, trigger: "blur", message: "租户不能为空"},
+          {
+            validator: (rule, value, callback) => {
+              // debugger
+              getTenantIdByName(value).then(res => {
+                const tenantId = res.data;
+                if (tenantId && tenantId >= 0) {
+                  // 设置租户
+                  setTenantId(tenantId)
+                  callback();
+                } else {
+                  callback('租户不存在');
+                }
+              });
+            },
+            trigger: 'blur'
+          }
+        ]
+      },
+      scene: 21,
+    };
+  },
+  methods: {
+    backLogin(){
+      this.$router.push({path: '/login'})
+    },
+    /** ========== 以下为升级短信登录 ========== */
+    getSmsCode() {
+      if (this.mobileCodeTimer > 0) return;
+      this.$refs.loginForm.validate(valid => {
+        if (!valid) return;
+        sendSmsCode(this.loginForm.mobile, this.scene, this.loginForm.code).then(res => {
+          this.$modal.msgSuccess("获取验证码成功")
+          this.mobileCodeTimer = 60;
+          let msgTimer = setInterval(() => {
+            this.mobileCodeTimer = this.mobileCodeTimer - 1;
+            if (this.mobileCodeTimer <= 0) {
+              clearInterval(msgTimer);
+            }
+          }, 1000);
+        });
+      });
+    },
+    submitForm(formName) {
+        this.$refs[formName].validate((valid) => {
+          if (valid) {
+            alert('submit!');
+            this.$router.push({path: '/password/reset'})
+          } else {
+            console.log('error submit!!');
+            return false;
+          }
+        });
+      },
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.fx-account-layout {
+    background: #f5f6f8;
+    bottom: 0;
+    left: 0;
+    min-height: 500px;
+    position: absolute;
+    right: 0;
+    top: 0;
+}
+.fx-account-layout .account-logo {
+    left: 60px;
+    position: absolute;
+    top: 40px;
+}
+a {
+    outline: none;
+    text-decoration: none;
+}
+.fx-account-layout .account-logo>img.official-logo {
+    height: 24px;
+}
+.fx-account-layout .account-logo>img {
+    display: block;
+    max-height: 200px;
+    max-width: 200px;
+}
+img {
+    border: 0;
+    outline: none;
+}
+.fx-account-layout .account-pane-container {
+    height: 100%;
+    width: 100%;
+}
+.fx-account-layout .account-pane, .fx-account-layout .signin-container-banner {
+    -webkit-box-align: center;
+    -webkit-box-pack: center;
+    align-items: center;
+    display: flex;
+    height: 100%;
+    justify-content: center;
+}
+.fx-account-layout .account-pane {
+    -ms-flex-align: center;
+    -ms-flex-pack: center;
+    width: 100%;
+}
+.fx-account-layout .account-pane-container.hide-banner .account-container {
+    -webkit-box-flex: 0;
+    display: block;
+    -ms-flex: none;
+    flex: none;
+}
+.jdy-page-password-forget .password-forget-container {
+    padding: 0;
+    width: 320px;
+}
+.fx-account-layout .account-container {
+   
+    align-items: center;
+    background: #fff;
+    display: flex;
+    -ms-flex: 0.42;
+    flex: 0.42;
+    justify-content: center;
+    position: relative;
+}
+.jdy-page-password-forget .password-forget-container .account-header {
+    border-bottom: 1px solid #ebecee;
+    color: #141e31;
+    font-size: 16px;
+    font-weight: 500;
+    height: 60px;
+    line-height: 60px;
+    text-align: center;
+}
+.jdy-page-password-forget .password-forget-container .account-content {
+    padding: 15px 40px 20px;
+}
+</style>

+ 250 - 0
src/views/password/reset.vue

@@ -0,0 +1,250 @@
+<template>
+  <div class="fx-account-layout jdy-page-password-forget">
+    <!-- <a class="account-logo" href="/">
+      <img class="official-logo" src="https://g.jdycdn.com/shared/images/logo/logo_text.png" alt="">
+    </a> -->
+    <div class="account-pane-container hide-banner">
+      <div class="account-pane">
+        <div class="account-container password-forget-container">
+          <div class="account-header">重置密码</div>
+          <div class="account-content">
+            <el-form v-if="!resetStatus" ref="ruleForm" :model="ruleForm" :rules="rules" class="login-form">
+              <el-form-item prop="pass">
+                 <el-input type="password" show-password v-model="ruleForm.pass" placeholder="密码">
+                 </el-input>
+               </el-form-item>
+               <el-form-item prop="checkPass">
+                <el-input type="password" show-password v-model="ruleForm.checkPass" placeholder="确认密码">
+                </el-input>
+               </el-form-item>
+               <el-form-item>
+                 <el-button size="medium" type="primary" style="width:100%;"
+                 @click="submitForm('ruleForm')">
+                  确定
+                 </el-button>
+                 <el-button style="margin-left: 0;margin-top: 10px;width: 100%;" type="text" @click="backLogin()">返回登录</el-button>
+               </el-form-item>
+            </el-form>
+            <div class="success-box" v-else>
+              <div class="success-box-content">
+                <svg-icon class="success-icon" icon-class="success" />
+                <div class="success-box-content-text">
+                  <span class="success-text">密码重置成功</span>
+                  <el-button class="success-btn" type="text" @click="backLogin()">立即登录</el-button>
+                </div>
+              </div>
+              <div class="success-box-footer">
+                {{ numberTimer }}秒后自动跳转登录页
+              </div>
+            </div>
+          </div>
+
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { sendSmsCode } from "@/api/login";
+export default {
+  data() {
+    var validatePass = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('请输入密码'));
+      } else {
+        if (this.ruleForm.checkPass !== '') {
+          this.$refs.ruleForm.validateField('checkPass');
+        }
+        callback();
+      }
+    };
+    var validatePass2 = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('请再次输入密码'));
+      } else if (value !== this.ruleForm.pass) {
+        callback(new Error('两次输入密码不一致!'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      resetStatus: false,
+      numberTimer: 3,
+      countdown: 3,
+      ruleForm: {
+        pass: '',
+        checkPass: '',
+      },
+      rules: {
+        pass: [
+          { validator: validatePass, trigger: 'blur' }
+        ],
+        checkPass: [
+          { validator: validatePass2, trigger: 'blur' }
+        ],
+      },
+    };
+  },
+  methods: {
+    myTimer() {
+      let msgTimer = setInterval(() => {
+        this.numberTimer = this.numberTimer - 1;
+        if (this.numberTimer <= 0) {
+          clearInterval(msgTimer);
+          this.$router.push({ path: '/login' })
+        }
+      }, 1000);
+    },
+    backLogin() {
+      this.$router.push({ path: '/login' })
+    },
+    submitForm(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          alert('submit!');
+          this.resetStatus = true;
+          this.myTimer();
+        } else {
+          console.log('error submit!!');
+          return false;
+        }
+      });
+    },
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.success-box {
+  .success-box-content {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+
+    .success-icon {
+      font-size: 80px;
+      color: #67C23A;
+    }
+
+    .success-box-content-text {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+
+      .success-text {
+        font-size: 24px;
+        color: #303133;
+        margin: 20px 0;
+      }
+
+      .success-btn {
+        font-size: 16px;
+        color: #409EFF
+      }
+    }
+  }
+
+  .success-box-footer {
+    text-align: center;
+    font-size: 16px;
+    color: gray;
+  }
+}
+
+.fx-account-layout {
+  background: #f5f6f8;
+  bottom: 0;
+  left: 0;
+  min-height: 500px;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.fx-account-layout .account-logo {
+  left: 60px;
+  position: absolute;
+  top: 40px;
+}
+
+a {
+  outline: none;
+  text-decoration: none;
+}
+
+.fx-account-layout .account-logo>img.official-logo {
+  height: 24px;
+}
+
+.fx-account-layout .account-logo>img {
+  display: block;
+  max-height: 200px;
+  max-width: 200px;
+}
+
+img {
+  border: 0;
+  outline: none;
+}
+
+.fx-account-layout .account-pane-container {
+  height: 100%;
+  width: 100%;
+}
+
+.fx-account-layout .account-pane,
+.fx-account-layout .signin-container-banner {
+  -webkit-box-align: center;
+  -webkit-box-pack: center;
+  align-items: center;
+  display: flex;
+  height: 100%;
+  justify-content: center;
+}
+
+.fx-account-layout .account-pane {
+  -ms-flex-align: center;
+  -ms-flex-pack: center;
+  width: 100%;
+}
+
+.fx-account-layout .account-pane-container.hide-banner .account-container {
+  -webkit-box-flex: 0;
+  display: block;
+  -ms-flex: none;
+  flex: none;
+}
+
+.jdy-page-password-forget .password-forget-container {
+  padding: 0;
+  width: 320px;
+}
+
+.fx-account-layout .account-container {
+
+  align-items: center;
+  background: #fff;
+  display: flex;
+  -ms-flex: 0.42;
+  flex: 0.42;
+  justify-content: center;
+  position: relative;
+}
+
+.jdy-page-password-forget .password-forget-container .account-header {
+  border-bottom: 1px solid #ebecee;
+  color: #141e31;
+  font-size: 16px;
+  font-weight: 500;
+  height: 60px;
+  line-height: 60px;
+  text-align: center;
+}
+
+.jdy-page-password-forget .password-forget-container .account-content {
+  padding: 15px 40px 20px;
+}
+</style>

+ 11 - 3
src/views/register.vue

@@ -14,12 +14,13 @@
 
         <!-- 表单 -->
         <div class="form-cont">
-          <div class="form" style=" float:none;margin-bottom: 20px;">
+          <div class="login-title">账号注册</div>
+          <!-- <div class="form" style=" float:none;margin-bottom: 20px;">
             <el-steps :active="loginForm.loginType" simple>
               <el-step title="注册账号" icon="el-icon-user"></el-step>
               <el-step title="创建团队" icon="el-icon-edit"></el-step>
             </el-steps>
-          </div>
+          </div> -->
           
           <div style="width: 320px;">
             <el-form ref="loginForm" :model="loginForm" :rules="LoginRules" class="login-form">
@@ -54,7 +55,7 @@
                 <el-form-item style="width:100%;">
                   <el-button :loading="loading" size="medium" type="primary" style="width:100%;"
                       @click.native.prevent="getNext()">
-                    <span v-if="!loading">下 一 步</span>
+                    <span v-if="!loading">注 册</span>
                     <span v-else>操 作 中...</span>
                   </el-button>
                 </el-form-item>
@@ -331,6 +332,13 @@ export default {
 </script>
 <style lang="scss" scoped>
 @import "~@/assets/styles/login.scss";
+.login-title{
+  color: #141e31;
+    font-size: 32px;
+    font-weight: 500;
+    line-height: 48px;
+    margin-bottom: 20px;
+}
 .service-laws {
     color: #525967;
     font-size: 14px;