From 9057e04efad1b7d61c77a72e5c37a504d0aee935 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期五, 26 九月 2025 09:24:03 +0800
Subject: [PATCH] H5静态化

---
 admin/src/components/common/Header.vue |  235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 235 insertions(+), 0 deletions(-)

diff --git a/admin/src/components/common/Header.vue b/admin/src/components/common/Header.vue
new file mode 100644
index 0000000..f4709ae
--- /dev/null
+++ b/admin/src/components/common/Header.vue
@@ -0,0 +1,235 @@
+<template>
+  <div class="main-header">
+    <div class="header">
+      <h2>
+        <i class="el-icon-s-unfold" v-if="menuData.collapse" @click="switchCollapseMenu(null)"></i>
+        <i class="el-icon-s-fold" v-else @click="switchCollapseMenu(null)"></i>
+        {{title}}
+      </h2>
+      <div class="user">
+        <el-dropdown trigger="click">
+          <span class="el-dropdown-link" style="color: white">
+            <img v-if="userInfo != null" :src="userInfo.avatar == null ? '@/assets/avatar/man.png' : userInfo.avatar" alt="">{{userInfo | displayName}}<i class="el-icon-arrow-down el-icon--right"></i>
+          </span>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item @click.native="changePwd">淇敼瀵嗙爜</el-dropdown-item>
+            <el-dropdown-item @click.native="logout">閫�鍑虹櫥褰�</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+      </div>
+    </div>
+    <!-- 淇敼瀵嗙爜 -->
+    <GlobalWindow
+      title="淇敼瀵嗙爜"
+      :visible.sync="visible.changePwd"
+      @confirm="confirmChangePwd"
+      @close="visible.changePwd = false"
+    >
+      <el-form :model="changePwdData.form" ref="changePwdDataForm" :rules="changePwdData.rules">
+        <el-form-item label="鍘熷瀵嗙爜" prop="oldPwd" required>
+          <el-input v-model="changePwdData.form.oldPwd" type="password" placeholder="璇疯緭鍏ュ師濮嬪瘑鐮�" maxlength="30" show-password></el-input>
+        </el-form-item>
+        <el-form-item label="鏂板瘑鐮�" prop="newPwd" required>
+          <el-input v-model="changePwdData.form.newPwd" type="password" placeholder="璇疯緭鍏ユ柊瀵嗙爜" maxlength="30" show-password></el-input>
+        </el-form-item>
+        <el-form-item label="纭鏂板瘑鐮�" prop="confirmPwd" required>
+          <el-input v-model="changePwdData.form.confirmPwd" type="password" placeholder="璇峰啀娆¤緭鍏ユ柊瀵嗙爜" maxlength="30" show-password></el-input>
+        </el-form-item>
+      </el-form>
+    </GlobalWindow>
+  </div>
+</template>
+
+<script>
+import { mapState, mapMutations } from 'vuex'
+import GlobalWindow from './GlobalWindow'
+import { logout, updatePwd } from '@/api/system/common'
+
+export default {
+  name: 'Header',
+  components: { GlobalWindow },
+  data () {
+    return {
+      visible: {
+        // 淇敼瀵嗙爜
+        changePwd: false
+      },
+      isWorking: {
+        // 淇敼瀵嗙爜
+        changePwd: false
+      },
+      // 鐢ㄦ埛鍚�
+      username: '',
+      // 淇敼瀵嗙爜寮规
+      changePwdData: {
+        form: {
+          oldPwd: '',
+          newPwd: '',
+          confirmPwd: ''
+        },
+        rules: {
+          oldPwd: [
+            { required: true, message: '璇疯緭鍏ュ師濮嬪瘑鐮�' }
+          ],
+          newPwd: [
+            { required: true, message: '璇疯緭鍏ュ瘑鐮�', trigger: 'blur' },
+            { validator: this.validatePassword, trigger: 'blur' },
+          ],
+          confirmPwd: [
+            { required: true, message: '璇峰啀娆¤緭鍏ユ柊瀵嗙爜' }
+          ]
+        }
+      }
+    }
+  },
+  computed: {
+    ...mapState(['menuData', 'userInfo']),
+    title () {
+      return this.$route.meta.title
+    }
+  },
+  filters: {
+    // 灞曠ず鍚嶇О
+    displayName (userInfo) {
+      if (userInfo == null) {
+        return ''
+      }
+      if (userInfo.realname != null && userInfo.realname.trim().length > 0) {
+        return userInfo.realname
+      }
+      return userInfo.username
+    }
+  },
+  methods: {
+    ...mapMutations(['setUserInfo', 'switchCollapseMenu']),
+    /**
+     * 淇敼瀵嗙爜锛堢偣鍑讳慨鏀瑰瘑鐮佹椂瑙﹀彂锛�
+     */
+    changePwd () {
+      this.visible.changePwd = true
+      this.$nextTick(() => {
+        this.$refs.changePwdDataForm.resetFields()
+      })
+    },
+    validatePassword(rule, value, callback) {
+      if (!value) {
+        callback(new Error('璇疯緭鍏ュ瘑鐮�'))
+      } else {
+        const lengthValid = /^.{6,20}$/.test(value)
+        const hasLetter = /[a-zA-Z]/.test(value)
+        const hasNumber = /[0-9]/.test(value)
+        const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(value)
+
+        const typesCount = [hasLetter, hasNumber, hasSpecial].filter(Boolean).length
+
+        if (!lengthValid) {
+          callback(new Error('瀵嗙爜闀垮害闇�涓�6鍒�20涓瓧绗�'))
+        } else if (typesCount < 2) {
+          callback(new Error('瀵嗙爜闇�鍖呭惈瀛楁瘝銆佹暟瀛楀強鐗规畩瀛楃涓殑鑷冲皯涓ょ'))
+        } else {
+          callback() // 楠岃瘉閫氳繃
+        }
+      }
+    },
+    /**
+     * 纭畾淇敼瀵嗙爜
+     */
+    confirmChangePwd () {
+      if (this.isWorking.changePwd) {
+        return
+      }
+      this.$refs.changePwdDataForm.validate((valid) => {
+        if (!valid) {
+          return
+        }
+        // 楠岃瘉涓ゆ瀵嗙爜杈撳叆鏄惁涓�鑷�
+        if (this.changePwdData.form.newPwd !== this.changePwdData.form.confirmPwd) {
+          this.$tip.warning('涓ゆ瀵嗙爜杈撳叆涓嶄竴鑷�')
+          return
+        }
+        // 鎵ц淇敼
+        this.isWorking.changePwd = true
+        updatePwd({
+          oldPwd: this.changePwdData.form.oldPwd,
+          newPwd: this.changePwdData.form.newPwd
+        },)
+          .then(() => {
+            this.visible.changePwd = false
+            setTimeout(() => {
+              this.$dialog.attentionConfirm('瀵嗙爜淇敼鎴愬姛锛岃閲嶆柊鐧诲綍', null, '閲嶆柊鐧诲綍').then(() => {
+                this.logout()
+              })
+            }, 300)
+          })
+          .catch(e => {
+            this.$tip.apiFailed(e)
+          })
+          .finally(() => {
+            this.isWorking.changePwd = false
+          })
+      })
+    },
+    /**
+     * 閫�鍑虹櫥褰�
+     */
+    logout () {
+      logout()
+        .then(() => {
+          this.setUserInfo(null)
+          this.$cache.twoFA.removePassword()
+          this.$router.push({ name: 'login' })
+        })
+        .catch(e => {
+          this.$tip.apiFailed(e)
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/assets/style/variables.scss";
+.header {
+  overflow: hidden;
+  padding: 0 25px;
+  background: #0c6ce3;
+  height: 100%;
+  display: flex;
+  h2 {
+    width: 50%;
+    flex-shrink: 0;
+    line-height: $header-height;
+    font-size: 19px;
+    font-weight: 600;
+    color: white;
+    display: inline;
+    & > i {
+      font-size: 20px;
+      margin-right: 12px;
+    }
+  }
+  .user {
+    width: 50%;
+    flex-shrink: 0;
+    color: white;
+    text-align: right;
+    .el-dropdown {
+      top: 2px;
+    }
+    img {
+      width: 32px;
+      position: relative;
+      top: 10px;
+      margin-right: 10px;
+    }
+  }
+}
+// 涓嬫媺鑿滃崟妗�
+.el-dropdown-menu {
+  width: 140px;
+  .el-dropdown-menu__item:hover {
+    background: #E3EDFB;
+    color: $primary-color;
+  }
+}
+</style>

--
Gitblit v1.9.3