Browse Source

登录新增校验账号有效期需求

hezhanp 8 months ago
parent
commit
cb2b532525
5 changed files with 560 additions and 488 deletions
  1. 12 0
      src/api/login/index.js
  2. 156 110
      src/layout/components/header-tools.vue
  3. 82 69
      src/layout/components/password-modal.vue
  4. 1 0
      src/views/login/index.vue
  5. 309 309
      yarn.lock

+ 12 - 0
src/api/login/index.js

@@ -22,6 +22,18 @@ export async function getLoginUser(data) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+
+/**
+ * 验证当前账号有效期
+ */
+
+export async function getExpiryDate(accountId) {
+  const res = await request.get(`/system/account/checkPasswordPeriod/${accountId}`);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 /**
  * 获取验证码
  */

+ 156 - 110
src/layout/components/header-tools.vue

@@ -1,4 +1,3 @@
-<!-- 顶栏右侧区域 -->
 <template>
   <div class="ele-admin-header-tool">
     <!-- 全屏切换 -->
@@ -9,14 +8,12 @@
       <i v-if="fullscreen" class="el-icon-_screen-restore"></i>
       <i v-else class="el-icon-_screen-full"></i>
     </div>
-    <!-- 语言切换 -->
-    <!-- <div class="ele-admin-header-tool-item">
-      <i18n-icon />
-    </div> -->
+
     <!-- 消息通知 -->
     <div class="ele-admin-header-tool-item">
       <header-notice />
     </div>
+
     <div
       class="ele-admin-header-tool-item"
       style="font-size: 14px"
@@ -25,6 +22,7 @@
       {{ loginUser?.factoryName }}
     </div>
 
+    <!-- 部门下拉选择 -->
     <div class="ele-admin-header-tool-item">
       <el-select
         v-model="groupId"
@@ -40,6 +38,8 @@
         </el-option>
       </el-select>
     </div>
+
+    <!-- 角色下拉选择 -->
     <div class="ele-admin-header-tool-item">
       <el-select
         v-model="roleId"
@@ -55,20 +55,15 @@
         </el-option>
       </el-select>
     </div>
-    <!-- 用户信息 -->
+
+    <!-- 用户信息下拉 -->
     <div class="ele-admin-header-tool-item">
       <el-dropdown @command="onUserDropClick">
         <div class="ele-admin-header-avatar">
           <el-avatar
-            :src="
-              loginUser && loginUser.avatarAddress
-                ? loginUser.avatarAddress
-                : ''
-            "
+            :src="loginUser && loginUser.avatarAddress ? loginUser.avatarAddress : ''"
           />
-          <span class="hidden-xs-only">{{
-            loginUser && loginUser.name ? loginUser.name : ''
-          }}</span>
+          <span class="hidden-xs-only">{{ loginUser && loginUser.name ? loginUser.name : '' }}</span>
           <i class="el-icon-arrow-down"></i>
         </div>
         <template v-slot:dropdown>
@@ -90,6 +85,7 @@
         </template>
       </el-dropdown>
     </div>
+
     <!-- 主题设置 -->
     <div
       class="ele-admin-header-tool-item"
@@ -98,114 +94,164 @@
     >
       <i class="el-icon-_more"></i>
     </div>
-    <!-- 修改密码弹窗 -->
-    <password-modal :visible.sync="passwordVisible" />
+
+    <!-- 修改密码弹窗:传递来源标识 + 监听过期取消事件 -->
+    <password-modal
+      :visible.sync="passwordVisible"
+      :is-from-expiry="isFromExpiryConfirm"
+      @on-expiry-cancel="handleExpiryCancel"
+    />
+
     <!-- 主题设置抽屉 -->
     <setting-drawer :visible.sync="settingVisible" />
   </div>
 </template>
 
 <script>
-  import HeaderNotice from './header-notice.vue';
-  import PasswordModal from './password-modal.vue';
-  import SettingDrawer from './setting-drawer.vue';
-  import { logout } from '@/utils/page-tab-util';
-  import { userLogout } from '@/api/system/user';
-  import router from '@/router/index';
-  import { getCurrentUser, setCurrentUser } from '@/utils/token-util';
-  export default {
-    components: { HeaderNotice, PasswordModal, SettingDrawer },
-    props: {
-      // 是否是全屏
-      fullscreen: Boolean
+import HeaderNotice from './header-notice.vue';
+import PasswordModal from './password-modal.vue';
+import SettingDrawer from './setting-drawer.vue';
+import { logout } from '@/utils/page-tab-util';
+import { userLogout } from '@/api/system/user';
+import router from '@/router/index';
+import { getExpiryDate } from '@/api/login';
+import { MessageBox, Message } from 'element-ui';
+import { getCurrentUser, setCurrentUser } from '@/utils/token-util';
+
+export default {
+  components: { HeaderNotice, PasswordModal, SettingDrawer },
+  props: {
+    fullscreen: Boolean
+  },
+  data() {
+    return {
+      passwordVisible: false,
+      settingVisible: false,
+      groupId: '',
+      roleId: '',
+      currentUser: { currentGroupId: '', currentRoleId: '' },
+      type: '',
+      isFromExpiryConfirm: false,
+      accountId: localStorage.getItem('accountId')
+    };
+  },
+  created() {
+    this.currentUser = getCurrentUser();
+    this.groupId = this.currentUser.currentGroupId;
+    this.roleId = this.currentUser.currentRoleId;
+    this.type = localStorage.getItem('singleUserInfo');
+    this.checkPasswordExpiry();
+  },
+  computed: {
+    loginUser() {
+      return this.$store.state.user.info;
     },
-    data() {
-      return {
-        // 是否显示修改密码弹窗
-        passwordVisible: false,
-        // 是否显示主题设置抽屉
-        settingVisible: false,
-        groupId: '',
-        roleId: '',
-        currentUser: {
-          currentGroupId: '',
-          currentRoleId: ''
-        },
-        type: ''
-      };
+    loginChangeGroupVOList() {
+      return this.$store.state.user?.info?.loginChangeGroupVOList;
     },
-    created() {
-      this.currentUser = getCurrentUser();
-      this.groupId = this.currentUser.currentGroupId;
-      this.roleId = this.currentUser.currentRoleId;
-      this.type = localStorage.getItem('singleUserInfo');
+    loginChangeRoleVOList() {
+      return this.$store.state.user?.info?.loginChangeGroupVOList.find(
+        item => item.groupId === this.groupId
+      )?.loginChangeRoleVOList;
+    }
+  },
+  methods: {
+    // 密码有效期校验主逻辑:校验账号ID → 调用接口 → 弹窗交互 → 错误处理
+    async checkPasswordExpiry() {
+      if (!this.accountId) {
+        Message.warning('账号ID缺失,无法校验密码有效期');
+        return;
+      }
+
+      try {
+        const isExpired = await getExpiryDate(this.accountId);
+        if (!isExpired) {
+          await this.showExpiryConfirm();
+        }
+      } catch (error) {
+        const errorMsg = error?.response?.data?.message || '密码有效期校验失败,请稍后重试';
+        Message.error(errorMsg);
+        console.error('密码有效期校验错误:', error);
+      }
     },
 
-    computed: {
-      // 当前用户信息
-      loginUser() {
-        return this.$store.state.user.info;
-      },
-      // 部门下拉
-      loginChangeGroupVOList() {
-        return this.$store.state.user?.info?.loginChangeGroupVOList;
-      },
-      // 角色下拉
-      loginChangeRoleVOList() {
-        return this.$store.state.user?.info?.loginChangeGroupVOList.find(
-          (item) => item.groupId == this.groupId
-        )?.loginChangeRoleVOList;
+    // 密码过期提醒弹窗:强制用户选择“修改”或“退出”
+    async showExpiryConfirm() {
+      const confirmConfig = {
+        title: '密码修改提醒',
+        message: '您的登录密码已长时间未做修改,请修改密码后重新登录!',
+        confirmButtonText: '确认修改',
+        cancelButtonText: '取消',
+        type: 'warning',
+        closeOnClickModal: false,
+        showClose: false
+      };
+
+      try {
+        await MessageBox.confirm(confirmConfig.message, confirmConfig.title, confirmConfig);
+        this.isFromExpiryConfirm = true;
+        this.passwordVisible = true;
+      } catch {
+        this.handleLogout();
       }
     },
-    methods: {
-      groupIdChange(val) {
-        this.roleChange(this.loginChangeRoleVOList[0].roleId);
-      },
-      roleChange(val) {
-        this.roleId = val;
-        this.currentUser.currentGroupId = this.groupId;
-        this.currentUser.currentRoleId = val;
-        setCurrentUser(this.currentUser);
-        this.$store
-          .dispatch('user/fetchUserInfo')
-          .then(({ menus, homePath, authoritiesRouter }) => {
-            router.roleChange({ menus, homePath, authoritiesRouter });
-          });
-      },
-      /* 用户信息下拉点击事件 */
-      onUserDropClick(command) {
-        if (command === 'password') {
-          this.passwordVisible = true;
-        } else if (command === 'profile') {
-          if (this.$route.fullPath !== '/user/profile') {
-            // this.$router.push('/user/profile');
-            window.history.pushState(null, '', '/page-wt/user/profile');
-          }
-        } else if (command === 'logout') {
-          // 退出登录
-          this.$confirm(
-            this.$t('layout.logout.message'),
-            this.$t('layout.logout.title'),
-            { type: 'warning' }
-          )
-            .then(() => {
-              userLogout().then((res) => {
-                localStorage.removeItem('userId');
-                localStorage.removeItem('LogoName');
-                logout();
-              });
-            })
-            .catch(() => {});
+
+    // 过期弹窗取消:关闭弹窗并重新触发校验
+    handleExpiryCancel() {
+      this.passwordVisible = false;
+      this.checkPasswordExpiry();
+    },
+
+    // 统一退出登录逻辑
+    handleLogout() {
+      userLogout().then(() => {
+        localStorage.removeItem('userId');
+        localStorage.removeItem('LogoName');
+        logout();
+      });
+    },
+
+    // 部门切换:自动选中第一个角色
+    groupIdChange() {
+      this.roleChange(this.loginChangeRoleVOList[0].roleId);
+    },
+
+    // 角色切换:更新用户角色并重新拉取权限
+    roleChange(val) {
+      this.roleId = val;
+      this.currentUser.currentGroupId = this.groupId;
+      this.currentUser.currentRoleId = val;
+      setCurrentUser(this.currentUser);
+      this.$store
+        .dispatch('user/fetchUserInfo')
+        .then(({ menus, homePath, authoritiesRouter }) => {
+          router.roleChange({ menus, homePath, authoritiesRouter });
+        });
+    },
+
+    // 用户下拉菜单点击事件
+    onUserDropClick(command) {
+      if (command === 'password') {
+        this.isFromExpiryConfirm = false;
+        this.passwordVisible = true;
+      } else if (command === 'profile') {
+        if (this.$route.fullPath !== '/user/profile') {
+          window.history.pushState(null, '', '/page-wt/user/profile');
         }
-      },
-      /* 全屏切换 */
-      toggleFullscreen() {
-        this.$emit('fullscreen');
-      },
-      /* 打开设置抽屉 */
-      openSetting() {
-        this.settingVisible = true;
+      } else if (command === 'logout') {
+        this.handleLogout();
       }
+    },
+
+    // 全屏切换:向父组件传递事件
+    toggleFullscreen() {
+      this.$emit('fullscreen');
+    },
+
+    // 打开主题设置抽屉
+    openSetting() {
+      this.settingVisible = true;
     }
-  };
-</script>
+  }
+};
+</script>

+ 82 - 69
src/layout/components/password-modal.vue

@@ -1,11 +1,11 @@
-<!-- 修改密码弹窗 -->
 <template>
   <ele-modal
     width="420px"
     title="修改密码"
     :visible="visible"
     :append-to-body="true"
-    :close-on-click-modal="true"
+    :close-on-click-modal="!isFromExpiry"
+    :show-close="!isFromExpiry"
     @update:visible="updateVisible"
     @closed="onClose"
   >
@@ -39,69 +39,81 @@
       </el-form-item>
     </el-form>
     <template v-slot:footer>
-      <el-button @click="updateVisible(false)">取消</el-button>
-      <el-button type="primary" @click="save">确定</el-button>
+      <el-button @click="handleCancel">取消</el-button>
+      <el-button type="primary" @click="save" :loading="loading">确定</el-button>
     </template>
   </ele-modal>
 </template>
 
 <script>
-  import { updatePassword } from '@/api/system/user';
-  export default {
-    props: {
-      visible: Boolean
-    },
-    data() {
-      return {
-        // 按钮 loading
-        loading: false,
-        // 表单数据
-        form: {
-          oldPassword: '',
-          newPassword: '',
-          newPassword1: ''
-        },
-        // 表单验证
-        rules: {
-          oldPassword: [
-            {
-              required: true,
-              message: '请输入旧密码',
-              trigger: 'blur'
-            }
-          ],
-          newPassword: [
-            {
-              required: true,
-              message: '请输入新密码',
-              trigger: 'blur'
-            }
-          ],
-          newPassword1: [
-            {
-              required: true,
-              trigger: 'blur',
-              validator: (_rule, value, callback) => {
-                if (!value) {
-                  return callback(new Error('请再次输入新密码'));
-                }
-                if (value !== this.form.newPassword) {
-                  return callback(new Error('两次输入密码不一致'));
-                }
-                callback();
+import { updatePassword } from '@/api/system/user';
+export default {
+  props: {
+    visible: Boolean,
+    isFromExpiry: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      // 按钮 loading
+      loading: false,
+      // 表单数据
+      form: {
+        oldPassword: '',
+        newPassword: '',
+        newPassword1: ''
+      },
+      // 表单验证
+      rules: {
+        oldPassword: [
+          {
+            required: true,
+            message: '请输入旧密码',
+            trigger: 'blur'
+          }
+        ],
+        newPassword: [
+          {
+            required: true,
+            message: '请输入新密码',
+            trigger: 'blur'
+          }
+        ],
+        newPassword1: [
+          {
+            required: true,
+            trigger: 'blur',
+            validator: (_rule, value, callback) => {
+              if (!value) {
+                return callback(new Error('请再次输入新密码'));
+              }
+              if (value !== this.form.newPassword) {
+                return callback(new Error('两次输入密码不一致'));
               }
+              callback();
             }
-          ]
-        }
-      };
+          }
+        ]
+      }
+    };
+  },
+  methods: {
+    handleCancel() {
+      if (this.isFromExpiry) {
+        this.$emit('on-expiry-cancel');
+      } else {
+        this.$emit('update:visible', false);
+      }
     },
-    methods: {
-      /* 修改 visible */
-      updateVisible(value) {
-        this.$emit('update:visible', value);
-      },
-      /* 保存修改 */
-      save() {
+
+    updateVisible(value) {
+      this.$emit('update:visible', value);
+    },
+
+    /* 保存修改 */
+    save() {
         this.$refs.form.validate((valid) => {
           if (valid) {
             this.loading = true;
@@ -122,16 +134,17 @@
           }
         });
       },
-      /* 关闭回调 */
-      onClose() {
-        this.form = {
-          oldPassword: '',
-          newPassword: '',
-          newPassword1: ''
-        };
-        this.$refs.form.resetFields();
-        this.loading = false;
-      }
+
+    /* 关闭回调:重置表单 */
+    onClose() {
+      this.form = {
+        oldPassword: '',
+        newPassword: '',
+        newPassword1: ''
+      };
+      if (this.$refs.form) this.$refs.form.resetFields();
+      this.loading = false;
     }
-  };
-</script>
+  }
+};
+</script>

+ 1 - 0
src/views/login/index.vue

@@ -221,6 +221,7 @@
           login(this.form)
             .then(async (res) => {
               localStorage.setItem('userId', res.data.userId);
+              localStorage.setItem('accountId', res.data.accountId);
               // 用户信息
               if (res.data?.loginChangeGroupVOList.length > 0) {
                 setCurrentUser(

File diff suppressed because it is too large
+ 309 - 309
yarn.lock


Some files were not shown because too many files changed in this diff