Ver código fonte

feat 更新用户密码功能,添加密码验证规则,优化用户信息编辑页面,增加表单验证和提交逻辑

Mr.Qin 3 semanas atrás
pai
commit
ee257601fd

+ 21 - 21
fuintAdmin/src/plugins/modal.js

@@ -1,43 +1,43 @@
-import { Message, MessageBox, Notification, Loading } from 'element-ui'
+import { Message, MessageBox, Notification, Loading } from "element-ui";
 
 let loadingInstance;
 
 export default {
   // 消息提示
   msg(content) {
-    Message.info(content)
+    Message.info(content);
   },
   // 错误消息
   msgError(content) {
-    Message.error(content)
+    Message.error(content);
   },
   // 成功消息
   msgSuccess(content) {
-    Message.success(content)
+    Message.success(content);
   },
   // 警告消息
   msgWarning(content) {
-    Message.warning(content)
+    Message.warning(content);
   },
   // 弹出提示
   alert(content) {
-    MessageBox.alert(content, "系统提示")
+    MessageBox.alert(content, "系统提示");
   },
   // 错误提示
   alertError(content) {
-    MessageBox.alert(content, "系统提示", { type: 'error' })
+    return MessageBox.alert(content, "系统提示", { type: "error" });
   },
   // 成功提示
   alertSuccess(content) {
-    MessageBox.alert(content, "系统提示", { type: 'success' })
+    return MessageBox.alert(content, "系统提示", { type: "success" });
   },
   // 警告提示
   alertWarning(content) {
-    MessageBox.alert(content, "系统提示", { type: 'warning' })
+    return MessageBox.alert(content, "系统提示", { type: "warning" });
   },
   // 通知提示
   notify(content) {
-    Notification.info(content)
+    Notification.info(content);
   },
   // 错误通知
   notifyError(content) {
@@ -45,27 +45,27 @@ export default {
   },
   // 成功通知
   notifySuccess(content) {
-    Notification.success(content)
+    Notification.success(content);
   },
   // 警告通知
   notifyWarning(content) {
-    Notification.warning(content)
+    Notification.warning(content);
   },
   // 确认窗体
   confirm(content) {
     return MessageBox.confirm(content, "系统提示", {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
       type: "warning",
-    })
+    });
   },
   // 提交内容
   prompt(content) {
     return MessageBox.prompt(content, "系统提示", {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
       type: "warning",
-    })
+    });
   },
   // 打开遮罩层
   loading(content) {
@@ -74,10 +74,10 @@ export default {
       text: content,
       spinner: "el-icon-loading",
       background: "rgba(0, 0, 0, 0.7)",
-    })
+    });
   },
   // 关闭遮罩层
   closeLoading() {
     loadingInstance.close();
-  }
-}
+  },
+};

+ 22 - 21
fuintAdmin/src/store/getters.js

@@ -1,22 +1,23 @@
 const getters = {
-  sidebar: state => state.app.sidebar,
-  size: state => state.app.size,
-  device: state => state.app.device,
-  visitedViews: state => state.tagsView.visitedViews,
-  cachedViews: state => state.tagsView.cachedViews,
-  token: state => state.user.token,
-  avatar: state => state.user.avatar,
-  name: state => state.user.name,
-  introduction: state => state.user.introduction,
-  roles: state => state.user.roles,
-  permissions: state => state.user.permissions,
-  merchantId: state => state.user.merchantId,
-  merchantName: state => state.user.merchantName,
-  storeId: state => state.user.storeId,
-  storeName: state => state.user.storeName,
-  permission_routes: state => state.permission.routes,
-  topbarRouters:state => state.permission.topbarRouters,
-  defaultRoutes:state => state.permission.defaultRoutes,
-  sidebarRouters:state => state.permission.sidebarRouters,
-}
-export default getters
+  sidebar: (state) => state.app.sidebar,
+  size: (state) => state.app.size,
+  device: (state) => state.app.device,
+  visitedViews: (state) => state.tagsView.visitedViews,
+  cachedViews: (state) => state.tagsView.cachedViews,
+  token: (state) => state.user.token,
+  avatar: (state) => state.user.avatar,
+  name: (state) => state.user.name,
+  introduction: (state) => state.user.introduction,
+  roles: (state) => state.user.roles,
+  permissions: (state) => state.user.permissions,
+  merchantId: (state) => state.user.merchantId,
+  merchantName: (state) => state.user.merchantName,
+  userId: (state) => state.user.userId,
+  storeId: (state) => state.user.storeId,
+  storeName: (state) => state.user.storeName,
+  permission_routes: (state) => state.permission.routes,
+  topbarRouters: (state) => state.permission.topbarRouters,
+  defaultRoutes: (state) => state.permission.defaultRoutes,
+  sidebarRouters: (state) => state.permission.sidebarRouters,
+};
+export default getters;

+ 82 - 67
fuintAdmin/src/store/modules/user.js

@@ -1,111 +1,126 @@
-import { login, logout, getInfo } from '@/api/login'
-import { getToken, setToken, removeToken } from '@/utils/auth'
+import { login, logout, getInfo } from "@/api/login";
+import { getToken, setToken, removeToken } from "@/utils/auth";
 
 const user = {
   state: {
     token: getToken(),
-    name: '',
-    avatar: '',
+    name: "",
+    avatar: "",
+    userId: "",
     roles: [],
     permissions: [],
-    merchantId: '',
-    merchantName: '',
-    storeId: '',
-    storeName: ''
+    merchantId: "",
+    merchantName: "",
+    storeId: "",
+    storeName: "",
   },
 
   mutations: {
     SET_TOKEN: (state, token) => {
-      state.token = token
+      state.token = token;
     },
     SET_NAME: (state, name) => {
-      state.name = name
+      state.name = name;
     },
     SET_AVATAR: (state, avatar) => {
-      state.avatar = avatar
+      state.avatar = avatar;
     },
     SET_ROLES: (state, roles) => {
-      state.roles = roles
+      state.roles = roles;
     },
     SET_PERMISSIONS: (state, permissions) => {
-      state.permissions = permissions
+      state.permissions = permissions;
     },
     SET_MERCHANT_ID: (state, merchantId) => {
-      state.merchantId = merchantId
+      state.merchantId = merchantId;
     },
     SET_MERCHANT_NAME: (state, merchantName) => {
-      state.merchantName = merchantName
+      state.merchantName = merchantName;
     },
     SET_STORE_ID: (state, storeId) => {
-      state.storeId = storeId
+      state.storeId = storeId;
+    },
+    SET_USER_ID: (state, userId) => {
+      state.userId = userId;
     },
     SET_STORE_NAME: (state, storeName) => {
-      state.storeName = storeName
+      state.storeName = storeName;
     },
   },
 
   actions: {
     // 登录
     Login({ commit }, userInfo) {
-      const username = userInfo.username.trim()
-      const password = userInfo.password
-      const captchaCode = userInfo.captchaCode
-      const uuid = userInfo.uuid
+      const username = userInfo.username.trim();
+      const password = userInfo.password;
+      const captchaCode = userInfo.captchaCode;
+      const uuid = userInfo.uuid;
       return new Promise((resolve, reject) => {
-        login(username, password, captchaCode, uuid).then(res => {
-          setToken(res.data.token)
-          commit('SET_TOKEN', res.data.token)
-          resolve()
-        }).catch(error => {
-          reject(error)
-        })
-      })
+        login(username, password, captchaCode, uuid)
+          .then((res) => {
+            setToken(res.data.token);
+            commit("SET_TOKEN", res.data.token);
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
     },
 
     // 获取用户信息
     GetInfo({ commit, state }) {
       return new Promise((resolve, reject) => {
-        getInfo().then(res => {
-          const user = res.data.accountInfo
-          const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/avatar.png") : process.env.VUE_APP_BASE_API + user.avatar;
-          if (res.data.roles && res.data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
-              commit('SET_ROLES', res.data.roles);
-              commit('SET_PERMISSIONS', res.data.permissions);
-          } else {
-              commit('SET_ROLES', ['ROLE_DEFAULT']);
-          }
-          commit('SET_NAME', user.accountName);
-          commit('SET_AVATAR', avatar);
-          commit('SET_MERCHANT_ID',  user.merchantId);
-          commit('SET_MERCHANT_NAME',  user.merchantName);
-          commit('SET_STORE_ID',  user.storeId);
-          commit('SET_STORE_NAME',  user.storeName);
-          resolve(res);
-        }).catch(error => {
-          reject(error)
-        })
-      })
+        getInfo()
+          .then((res) => {
+            const user = res.data.accountInfo;
+            const avatar =
+              user.avatar == "" || user.avatar == null
+                ? require("@/assets/images/avatar.png")
+                : process.env.VUE_APP_BASE_API + user.avatar;
+            if (res.data.roles && res.data.roles.length > 0) {
+              // 验证返回的roles是否是一个非空数组
+              commit("SET_ROLES", res.data.roles);
+              commit("SET_PERMISSIONS", res.data.permissions);
+            } else {
+              commit("SET_ROLES", ["ROLE_DEFAULT"]);
+            }
+            commit("SET_NAME", user.accountName);
+            commit("SET_AVATAR", avatar);
+            commit("SET_MERCHANT_ID", user.merchantId);
+            commit("SET_MERCHANT_NAME", user.merchantName);
+            commit("SET_STORE_ID", user.storeId);
+            commit("SET_USER_ID", user.id);
+            commit("SET_STORE_NAME", user.storeName);
+            resolve(res);
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
     },
 
     // 退出系统
     LogOut({ commit, state }) {
       return new Promise((resolve, reject) => {
-        logout(state.token).then(() => {
-          commit('SET_TOKEN', '')
-          commit('SET_ROLES', [])
-          commit('SET_PERMISSIONS', [])
-          commit('SET_MERCHANT_ID',  '')
-          commit('SET_MERCHANT_NAME',  '')
-          commit('SET_STORE_ID', '')
-          commit('SET_STORE_NAME', '')
-          removeToken()
-          resolve()
-        }).catch(error => {
-          reject(error)
-        })
-      })
-    }
-  }
-}
+        logout(state.token)
+          .then(() => {
+            commit("SET_TOKEN", "");
+            commit("SET_ROLES", []);
+            commit("SET_PERMISSIONS", []);
+            commit("SET_MERCHANT_ID", "");
+            commit("SET_MERCHANT_NAME", "");
+            commit("SET_STORE_ID", "");
+            commit("SET_STORE_NAME", "");
+            removeToken();
+            resolve();
+          })
+          .catch((error) => {
+            reject(error);
+          });
+      });
+    },
+  },
+};
 
-export default user
+export default user;

+ 48 - 19
fuintAdmin/src/utils/validate.js

@@ -3,7 +3,7 @@
  * @returns {Boolean}
  */
 export function isExternal(path) {
-  return /^(https?:|mailto:|tel:)/.test(path)
+  return /^(https?:|mailto:|tel:)/.test(path);
 }
 
 /**
@@ -11,8 +11,8 @@ export function isExternal(path) {
  * @returns {Boolean}
  */
 export function validUsername(str) {
-  const valid_map = ['admin', 'editor']
-  return valid_map.indexOf(str.trim()) >= 0
+  const valid_map = ["admin", "editor"];
+  return valid_map.indexOf(str.trim()) >= 0;
 }
 
 /**
@@ -20,8 +20,9 @@ export function validUsername(str) {
  * @returns {Boolean}
  */
 export function validURL(url) {
-  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
-  return reg.test(url)
+  const reg =
+    /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
+  return reg.test(url);
 }
 
 /**
@@ -29,8 +30,8 @@ export function validURL(url) {
  * @returns {Boolean}
  */
 export function validLowerCase(str) {
-  const reg = /^[a-z]+$/
-  return reg.test(str)
+  const reg = /^[a-z]+$/;
+  return reg.test(str);
 }
 
 /**
@@ -38,8 +39,8 @@ export function validLowerCase(str) {
  * @returns {Boolean}
  */
 export function validUpperCase(str) {
-  const reg = /^[A-Z]+$/
-  return reg.test(str)
+  const reg = /^[A-Z]+$/;
+  return reg.test(str);
 }
 
 /**
@@ -47,8 +48,8 @@ export function validUpperCase(str) {
  * @returns {Boolean}
  */
 export function validAlphabets(str) {
-  const reg = /^[A-Za-z]+$/
-  return reg.test(str)
+  const reg = /^[A-Za-z]+$/;
+  return reg.test(str);
 }
 
 /**
@@ -56,8 +57,9 @@ export function validAlphabets(str) {
  * @returns {Boolean}
  */
 export function validEmail(email) {
-  const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
-  return reg.test(email)
+  const reg =
+    /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+  return reg.test(email);
 }
 
 /**
@@ -65,10 +67,10 @@ export function validEmail(email) {
  * @returns {Boolean}
  */
 export function isString(str) {
-  if (typeof str === 'string' || str instanceof String) {
-    return true
+  if (typeof str === "string" || str instanceof String) {
+    return true;
   }
-  return false
+  return false;
 }
 
 /**
@@ -76,8 +78,35 @@ export function isString(str) {
  * @returns {Boolean}
  */
 export function isArray(arg) {
-  if (typeof Array.isArray === 'undefined') {
-    return Object.prototype.toString.call(arg) === '[object Array]'
+  if (typeof Array.isArray === "undefined") {
+    return Object.prototype.toString.call(arg) === "[object Array]";
   }
-  return Array.isArray(arg)
+  return Array.isArray(arg);
+}
+
+/**
+ *
+ * @param {String} str
+ * @returns {Boolean}
+ */
+export function validatePassword(str) {
+  const reg = /^[A-Za-z0-9]{6,}$/; // 至少 6 个字母或数字
+  return reg.test(str);
+}
+
+// 把上面的函数包装成element表单的自定义验证函数
+/**
+ *
+ * @param {*} func
+ * @param {*} message
+ * @returns
+ */
+export function validateForm(func, message = "格式不正确") {
+  return function (rule, value, callback) {
+    if (!func(value)) {
+      callback(new Error(message));
+    } else {
+      callback();
+    }
+  };
 }

+ 93 - 24
fuintAdmin/src/views/person/account.vue

@@ -1,44 +1,113 @@
 <template>
-  <div class="app-container main-panel">
-    <el-form ref="form" size="mini">
-      <el-descriptions title="基本信息" :column="1">
-        <template slot="extra">
-          <el-button type="primary" size="small" @click="handleSwitch"
-            >操作</el-button
-          >
-        </template>
-        <el-descriptions-item label="账号"> kooriookami </el-descriptions-item>
-        <el-descriptions-item label="密码"> 18100000000 </el-descriptions-item>
-        <el-descriptions-item label="头像">
-          <ImageUpload :isShowTip="false">
-            <template #tip>
-              支持格式:png、jpg、jpeg、bmp,单个文件不超过2mb,最多上传五个文件
-            </template>
-          </ImageUpload>
-        </el-descriptions-item>
-      </el-descriptions>
-    </el-form>
+  <div class="app-container">
+    <el-descriptions title="基本信息" :column="1">
+      <template slot="extra">
+        <el-button type="primary" size="small" @click="handleEdit"
+          >编辑</el-button
+        >
+      </template>
+      <el-descriptions-item label="账号"> {{ name }} </el-descriptions-item>
+      <el-descriptions-item label="密码"> ****** </el-descriptions-item>
+      <el-descriptions-item label="头像">
+        <el-avatar :src="avatar"></el-avatar>
+      </el-descriptions-item>
+    </el-descriptions>
+    <!-- 用户信息弹出层 -->
+    <el-dialog
+      title="用户信息"
+      :visible.sync="userDialog"
+      class="common-dialog"
+    >
+      <el-form
+        ref="form"
+        :rules="rules"
+        :model="form"
+        size="mini"
+        label-width="80px"
+      >
+        <el-form-item label="账号" prop="name">
+          {{ name }}
+        </el-form-item>
+        <el-form-item label="密码" prop="password">
+          <el-input
+            style="width: 15rem"
+            v-model.trim="form.password"
+            show-password
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="头像" prop="avatar">
+          <ImageUpload class="upload" :isShowTip="false" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" :loading="loading" @click="handleSubmit"
+          >保存</el-button
+        >
+        <el-button @click="close">关闭</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 <script>
 import ImageUpload from "@/components/ImageUpload";
+import { mapGetters } from "vuex";
+import { validateForm, validatePassword } from "@/utils/validate";
+import { resetAccountPwd } from "@/api/system/account";
 export default {
   name: "Account",
   components: { ImageUpload },
   data() {
     return {
-      isEdit: false,
+      userDialog: false,
+      loading: false,
+      form: {
+        password: "",
+        avatar: "",
+      },
+      rules: {
+        password: [
+          { required: true, message: "请输入密码", trigger: "blur" },
+          {
+            validator: validateForm(
+              validatePassword,
+              "密码至少由6个字母或数字"
+            ),
+            trigger: "blur",
+          },
+        ],
+      },
     };
   },
+  computed: {
+    ...mapGetters(["avatar", "name", "userId"]),
+  },
+
   methods: {
-    handleSwitch() {
-      this.isEdit = !this.isEdit;
+    handleEdit() {
+      this.userDialog = true;
+    },
+    close() {
+      this.userDialog = false;
+    },
+    async handleSubmit() {
+      await this.$refs["form"].validate();
+      this.loading = true;
+      await resetAccountPwd(this.userId, this.form.password)?.finally(() => {
+        this.loading = false;
+      });
+      await this.$modal.alertSuccess("密码修改成功");
+      this.$store.dispatch("LogOut").then(() => {
+        location.href = "/";
+      });
     },
   },
 };
 </script>
 <style lang="scss" scoped>
-.main-panel {
-  border: none;
+::v-deep .upload .el-upload {
+  width: 80px;
+  height: 80px;
+  line-height: 88px;
+  border-radius: 10%;
 }
 </style>