田源
2024-12-26 3457bf08eae9d9453c88dd62991c3e286eb1df4b
个人信息页面&&管理功能模块图标更改
已修改8个文件
已删除1个文件
已添加2个文件
721 ■■■■■ 文件已修改
Source/plt-web/plt-web-ui/package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/option/user/info.js 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/page/index/top/index.vue 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/router/views/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/styles/ui.scss 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/system/user/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/system/user/option.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/system/userInfo/index.vue 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/system/userInfo/userAvatar.vue 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/system/userinfo.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/src/views/systemModel/mangeModel/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Source/plt-web/plt-web-ui/package.json
@@ -30,6 +30,7 @@
    "v-charts": "^1.19.0",
    "vue": "^2.6.10",
    "vue-axios": "^2.1.2",
    "vue-cropper": "^0.6.5",
    "vue-echarts": "5.0.0-beta.0",
    "vue-flowchart-editor": "1.0.2",
    "vue-i18n": "^8.7.0",
Source/plt-web/plt-web-ui/src/option/user/info.js
@@ -5,67 +5,94 @@
    {
      label: '个人信息',
      prop: 'info',
      column: [{
        label: '头像',
        type: 'upload',
        listType: 'picture-img',
        propsHttp: {
          res: 'data',
          url: 'link',
      column: [
        {
          label: '头像',
          prop: 'avatar',
          formslot: true,
          span: 24,
        },
        canvasOption: {
          text: ' ',
          ratio: 0.1
        {
          label: '用户名',
          span: 12,
          row: true,
          prop: 'userId',
          readonly:true
        },
        action: '/api/blade-resource/oss/endpoint/put-file',
        tip: '只能上传jpg/png用户头像,且不超过500kb',
        span: 12,
        row: true,
        prop: 'avatar'
      }, {
        label: '姓名',
        span: 12,
        row: true,
        prop: 'realName'
      }, {
        label: '用户名',
        span: 12,
        row: true,
        prop: 'name'
      }, {
        label: '手机号',
        span: 12,
        row: true,
        prop: 'phone'
      }, {
        label: '邮箱',
        prop: 'email',
        span: 12,
        row: true,
      }]
        {
          label: '姓名',
          span: 12,
          row: true,
          prop: 'userName'
        },
        {
          label: '当前角色',
          span: 12,
          row: true,
          prop: 'personName',
          readonly:true,
        },
        {
          label: '当前密级',
          span: 12,
          row: true,
          prop: 'userSecretText',
          readonly:true,
        },
        {
          label: '邮箱',
          prop: 'email',
          span: 12,
          row: true,
        }]
    },
    {
      label: '修改密码',
      prop: 'password',
      column: [{
        label: '原密码',
        span: 12,
        row: true,
        type: 'password',
        prop: 'oldPassword'
      }, {
        label: '新密码',
        span: 12,
        row: true,
        type: 'password',
        prop: 'newPassword'
      }, {
        label: '确认密码',
        span: 12,
        row: true,
        type: 'password',
        prop: 'newPassword1'
      }]
      column: [
        {
          label: '登陆密码',
          prop: 'oldPassword',
          span: 24,
          labelWidth: "7%",
          type: 'password',
          rules: [
            {
              required: true,
              message: '请输入登陆密码',
              trigger: 'blur'
            }
          ]
        },
        {
          label: '新登陆密码',
          prop: 'password',
          span: 24,
          labelWidth: "7%",
          type: 'password',
          rules: [
            {
              required: true,
              message: '请输入新登陆密码',
              trigger: 'blur'
            }
          ]
        },
        {
          label: '新密码登陆确认',
          prop: 'confirmPassword',
          span: 24,
          labelWidth: "7%",
          type: 'password',
          rules: [
            {
              required: true,
              message: '请确认登陆密码',
              trigger: 'blur'
            }
          ]
        }
      ]
    }
  ],
}
Source/plt-web/plt-web-ui/src/page/index/top/index.vue
@@ -78,27 +78,30 @@
      </el-tooltip>
      <img :src="userInfo.avatar"
           class="top-bar__img">
      <el-dropdown>
      <div>
        <el-dropdown style="height: 40px">
        <span class="el-dropdown-link">
          {{ userInfo.userName }}
          <i class="el-icon-arrow-down el-icon--right"></i>
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item>
            <router-link to="/">{{ $t('navbar.dashboard') }}</router-link>
          </el-dropdown-item>
          <el-dropdown-item @click.native="changePasswordHandler">
            <!--            <router-link to="/info/index">{{ $t('navbar.userinfo') }}</router-link>-->
            ä¿®æ”¹å¯†ç 
          </el-dropdown-item>
          <el-dropdown-item v-if="this.website.switchMode" @click.native="switchDept"
          >{{ $t('navbar.switchDept') }}
          </el-dropdown-item>
          <el-dropdown-item divided
                            @click.native="logout">{{ $t('navbar.logOut') }}
          </el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item>
              <router-link to="/">{{ $t('navbar.dashboard') }}</router-link>
            </el-dropdown-item>
            <el-dropdown-item>
              <router-link to="/info/index">{{ $t('navbar.userinfo') }}</router-link>
              <!--            ä¿®æ”¹å¯†ç -->
            </el-dropdown-item>
            <el-dropdown-item v-if="this.website.switchMode" @click.native="switchDept"
            >{{ $t('navbar.switchDept') }}
            </el-dropdown-item>
            <el-dropdown-item divided
                              @click.native="logout">{{ $t('navbar.logOut') }}
            </el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
      </div>
      <el-dialog :visible.sync="userBox"
                 append-to-body
                 title="用户信息选择"
@@ -106,23 +109,11 @@
        <avue-form ref="form" v-model="userForm" :option="userOption" @submit="submitSwitch"/>
      </el-dialog>
      <!-- ä¿®æ”¹å¯†ç å¯¹è¯æ¡†     -->
      <el-dialog
        v-dialogDrag
        :visible.sync="passwordVisible"
        append-to-body="true"
        class="avue-dialog"
        style="margin-top: -15vh"
        title="修改密码"
        width="50%"
        @close="passwordClose">
        <avue-form ref="form" v-model="passwordForm" :option="passwordOption" @submit="submitSwitch"/>
      </el-dialog>
    </div>
  </div>
</template>
<script>
import {resetRouter} from '@/router/router'
import {resetRouter} from '../../../router/router'
import {mapGetters, mapState} from "vuex";
import {fullscreenToggel, listenfullscreen} from "@/util/util";
import topLock from "./top-lock";
@@ -133,8 +124,6 @@
import topColor from "./top-color";
import topNotice from './top-notice'
import topLang from "./top-lang";
import {changePassword} from "@/api/user"
import func from "@/util/func";
export default {
  components: {
@@ -150,55 +139,6 @@
  name: "top",
  data() {
    return {
      passwordVisible: false,
      passwordForm: {},
      passwordOption: {
        submitText: '保存',
        column: [
          {
            label: '登陆密码',
            prop: 'oldPassword',
            span: 24,
            labelWidth: "15%",
            type: 'password',
            rules: [
              {
                required: true,
                message: '请输入登陆密码',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '新登陆密码',
            prop: 'password',
            span: 24,
            labelWidth: "15%",
            type: 'password',
            rules: [
              {
                required: true,
                message: '请输入新登陆密码',
                trigger: 'blur'
              }
            ]
          },
          {
            label: '新密码登陆确认',
            prop: 'confirmPassword',
            span: 24,
            labelWidth: "15%",
            type: 'password',
            rules: [
              {
                required: true,
                message: '请确认登陆密码',
                trigger: 'blur'
              }
            ]
          }
        ]
      },
      userBox: false,
      userForm: {
        deptId: '',
@@ -277,10 +217,6 @@
    ])
  },
  methods: {
    // ä¿®æ”¹å¯†ç 
    changePasswordHandler() {
      this.passwordVisible = true;
    },
    handleScreen() {
      fullscreenToggel();
    },
@@ -299,29 +235,6 @@
      roleColumn.dicUrl = `/api/blade-system/role/select?userId=${userId}`;
      roleColumn.display = true;
      this.userBox = true;
    },
    submitSwitch(form, done) {
      let userInfo = JSON.parse(localStorage.getItem('saber-userInfo'));
      let params = {
        userName: userInfo.content.userId,
        oldPassword: func.encryptData(form.oldPassword, 'daliantan0v0vcip'),
        password: func.encryptData(form.password, 'daliantan0v0vcip'),
        confirmPassword: func.encryptData(form.confirmPassword, 'daliantan0v0vcip'),
      }
      changePassword(params).then(res => {
        if (res.data.code === 200) {
          this.$message.success(res.data.msg);
          this.passwordVisible = false;
          this.$store.dispatch("LogOut").then(() => {
            resetRouter();
            this.$router.push({path: "/login"});
          });
        }
      }).catch(err => {
        console.log(err);
      })
      done();
    },
    // å…³é—­ä¿®æ”¹å¯†ç å¯¹è¯æ¡†
Source/plt-web/plt-web-ui/src/router/views/index.js
@@ -80,7 +80,7 @@
      i18n: 'info'
    },
    component: () =>
      import( /* webpackChunkName: "views" */ '@/views/system/userinfo')
      import( /* webpackChunkName: "views" */ '@/views/system/userInfo/index')
  }]
}, {
  path: '/work/process/leave',
Source/plt-web/plt-web-ui/src/styles/ui.scss
@@ -536,6 +536,9 @@
  height: 20px;
  line-height: 20px;
}
.el-menu--popup-right-start{
  margin-left: 1px;
}
.font14{font-size: 14px;width: 12px;height: 12px;display: inline-block;}
.font16{font-size: 16px;width: 14px;height: 14px;display: inline-block;}
Source/plt-web/plt-web-ui/src/views/system/user/index.vue
@@ -238,9 +238,10 @@
      this.tableLoading = true;
      getDataUsers(this.page.currentPage, this.page.pageSize, this.searchParams).then(res => {
        const data = res.data.data;
        data.map(item => {item.secretGrade = item.secretGrade.toString()})
        this.tableData = data;
        this.page.total = res.data.total;
        this.tableLoading = false;
        this.tableLoading = false;s
      })
      this.departmentQueryOnLoad()
    },
Source/plt-web/plt-web-ui/src/views/system/user/option.js
@@ -84,6 +84,7 @@
    align:'center',
    type:'tree',
    dicData: [],
    hide:true,
    props: {
      label: 'name',
      value: 'oid'
@@ -94,6 +95,16 @@
    width:200,
  },
  {
    label: '所属部门',
    prop: 'pkDepartmentName',
    align:'center',
    display: false,
    search:true,
    sortable:true,
    overHidden: true,
    width:200,
  },
  {
    label: '专业',
    prop: 'specialties',
    sortable:true,
Source/plt-web/plt-web-ui/src/views/system/userInfo/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,103 @@
<template>
  <div>
    <basic-container>
      <avue-form
        ref="form"
        v-model="form"
        :option="option"
        @submit="handleSubmit"
        @tab-click="handleTabClick">
        <template slot="avatar" slot-scope="{disabled,size}">
          <div>
            <userAvatar :avatar="form.avatar"/>
          </div>
        </template>
      </avue-form>
    </basic-container>
  </div>
</template>
<script>
import option from "@/option/user/info";
import {getUserInfo, updateInfo, updatePassword} from "@/api/system/user";
import func from "../../../util/func";
import {changePassword} from "../../../api/user"
import userAvatar from "./userAvatar";
import {resetRouter} from '../../../router/router'
import {mapGetters} from "vuex";
export default {
  components: {userAvatar,},
  data() {
    return {
      index: 0,
      option: option,
      form: {}
    };
  },
  computed: {
    ...mapGetters(["userInfo"]),
  },
  created() {
    this.handleWitch();
  },
  methods: {
    handleSubmit(form, done) {
      if (this.index === 0) {
        updateInfo(form).then(res => {
          if (res.data.success) {
            this.$message({
              type: "success",
              message: "修改信息成功!"
            });
          } else {
            this.$message({
              type: "error",
              message: res.data.msg
            });
          }
          done();
        }, error => {
          window.console.log(error);
          done();
        })
      } else {
        let userInfo = JSON.parse(localStorage.getItem('saber-userInfo'));
        let params = {
          userName: userInfo.content.userId,
          oldPassword: func.encryptData(form.oldPassword, 'daliantan0v0vcip'),
          password: func.encryptData(form.password, 'daliantan0v0vcip'),
          confirmPassword: func.encryptData(form.confirmPassword, 'daliantan0v0vcip'),
        }
        changePassword(params).then(res => {
          if (res.data.code === 200) {
            this.$message.success(res.data.msg);
            this.passwordVisible = false;
            this.$store.dispatch("LogOut").then(() => {
              resetRouter();
              this.$router.push({path: "/login"});
            });
          }
        }).catch(err => {
          console.log(err);
        })
      }
    },
    handleWitch() {
      if (this.index === 0) {
        this.form = {...this.userInfo};
        console.log(this.form);
      }
    },
    handleTabClick(tabs) {
      this.index = func.toInt(tabs.index);
      this.handleWitch();
      this.$refs.form.resetFields();
    }
  }
};
</script>
<style>
</style>
Source/plt-web/plt-web-ui/src/views/system/userInfo/userAvatar.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,228 @@
<template>
  <div>
    <div class="user-info-head" @click="editCropper()">
      <div class="circular-upload-box" v-if="!options.img">
        <i class="el-icon-plus" style="font-size: 16px"></i>
      </div>
      <img v-else v-bind:src="options.img"  class="img-circle img-lg" />
    </div>
    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened"  @close="closeDialog">
      <el-row>
        <el-col :xs="24" :md="12" :style="{height: '350px'}">
          <vue-cropper
            ref="cropper"
            :img="options.img"
            :info="true"
            :autoCrop="options.autoCrop"
            :autoCropWidth="options.autoCropWidth"
            :autoCropHeight="options.autoCropHeight"
            :fixedBox="options.fixedBox"
            :outputType="options.outputType"
            @realTime="realTime"
            v-if="visible"
          />
        </el-col>
        <el-col :xs="24" :md="12" :style="{height: '350px'}">
          <div class="avatar-upload-preview">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </el-col>
      </el-row>
      <br />
      <el-row>
        <el-col :lg="2" :sm="3" :xs="3">
          <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
            <el-button size="small">
              é€‰æ‹©
              <i class="el-icon-upload el-icon--right"></i>
            </el-button>
          </el-upload>
        </el-col>
        <el-col :lg="{span: 1, offset: 2}" :sm="2" :xs="2">
          <el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button>
        </el-col>
        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
          <el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button>
        </el-col>
        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
          <el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button>
        </el-col>
        <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2">
          <el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button>
        </el-col>
        <el-col :lg="{span: 2, offset: 6}" :sm="2" :xs="2">
          <el-button type="primary" size="small" @click="uploadImg()">提 äº¤</el-button>
        </el-col>
      </el-row>
    </el-dialog>
  </div>
</template>
<script>
import store from "@/store";
import { VueCropper } from "vue-cropper";
import { uploadAvatar } from "@/api/system/user";
export default {
  components: { VueCropper },
  props:['avatar'],
  data() {
    return {
      // æ˜¯å¦æ˜¾ç¤ºå¼¹å‡ºå±‚
      open: false,
      // æ˜¯å¦æ˜¾ç¤ºcropper
      visible: false,
      // å¼¹å‡ºå±‚标题
      title: "修改头像",
      options: {
        img: this.avatar,  //裁剪图片的地址
        autoCrop: true,             // æ˜¯å¦é»˜è®¤ç”Ÿæˆæˆªå›¾æ¡†
        autoCropWidth: 200,         // é»˜è®¤ç”Ÿæˆæˆªå›¾æ¡†å®½åº¦
        autoCropHeight: 200,        // é»˜è®¤ç”Ÿæˆæˆªå›¾æ¡†é«˜åº¦
        fixedBox: true,             // å›ºå®šæˆªå›¾æ¡†å¤§å° ä¸å…è®¸æ”¹å˜
        outputType:"png",           // é»˜è®¤ç”Ÿæˆæˆªå›¾ä¸ºPNG格式
        filename: 'avatar'          // æ–‡ä»¶åç§°
      },
      previews: {},
      resizeHandler: null
    };
  },
  methods: {
    // ç¼–辑头像
    editCropper() {
      this.open = true;
    },
    // æ‰“开弹出层结束时的回调
    modalOpened() {
      this.visible = true;
      if (!this.resizeHandler) {
        this.resizeHandler = debounce(() => {
          this.refresh()
        }, 100)
      }
      window.addEventListener("resize", this.resizeHandler)
    },
    // åˆ·æ–°ç»„ä»¶
    refresh() {
      this.$refs.cropper.refresh();
    },
    // è¦†ç›–默认的上传行为
    requestUpload() {
    },
    // å‘左旋转
    rotateLeft() {
      this.$refs.cropper.rotateLeft();
    },
    // å‘右旋转
    rotateRight() {
      this.$refs.cropper.rotateRight();
    },
    // å›¾ç‰‡ç¼©æ”¾
    changeScale(num) {
      num = num || 1;
      this.$refs.cropper.changeScale(num);
    },
    // ä¸Šä¼ é¢„处理
    beforeUpload(file) {
      if (file.type.indexOf("image/") == -1) {
        this.$modal.msgError("文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。");
      } else {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          this.options.img = reader.result;
          this.options.filename = file.name;
        };
      }
    },
    // ä¸Šä¼ å›¾ç‰‡
    uploadImg() {
      this.$refs.cropper.getCropBlob(data => {
        let formData = new FormData();
        formData.append("avatarfile", data, this.options.filename);
        uploadAvatar(formData).then(response => {
          this.open = false;
          this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl;
          store.commit('SET_AVATAR', this.options.img);
          this.$modal.msgSuccess("修改成功");
          this.visible = false;
        });
      });
    },
    // å®žæ—¶é¢„览
    realTime(data) {
      this.previews = data;
    },
    // å…³é—­çª—口
    closeDialog() {
      this.options.img = store.getters.avatar
      this.visible = false;
      window.removeEventListener("resize", this.resizeHandler)
    }
  }
};
</script>
<style scoped lang="scss">
.user-info-head {
  position: relative;
  display: inline-block;
  height: 120px;
}
.user-info-head:hover:after {
  content: '+';
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); /* ä½¿åŠ å·åœ¨ä¸­å¿ƒç‚¹ */
  color: #eee;
  background: rgba(0, 0, 0, 0.5);
  font-size: 24px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  cursor: pointer;
  width: 120px; /* è®¾ç½®å®½åº¦ */
  height: 120px; /* è®¾ç½®é«˜åº¦ */
  border-radius: 50%; /* ä¿æŒåœ†å½¢ */
  display: flex; /* ä½¿ç”¨flexbox来居中 */
  align-items: center; /* åž‚直居中 */
  justify-content: center; /* æ°´å¹³å±…中 */
}
.avatar-upload-preview {
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 200px;
  height: 200px;
  border-radius: 50%;
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;
}
.img-circle {
  border-radius: 50%;
}
.img-lg {
  width: 120px;
  height: 120px;
}
.circular-upload-box {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background-color: #f3f4f6;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.circular-upload-box:hover {
  background-color: #e5e7eb;
}
</style>
Source/plt-web/plt-web-ui/src/views/system/userinfo.vue
ÎļþÒÑɾ³ý
Source/plt-web/plt-web-ui/src/views/systemModel/mangeModel/index.vue
@@ -7,7 +7,8 @@
                     @node-click="nodeClick">
          <span slot-scope="{ node, data }" class="el-tree-node__label">
           <span>
              <i :class="data.icon"></i>
<!--              <i :class="data.icon"></i>-->
             <icon-show :name="data.icon"></icon-show>
                {{ (node || {}).label }}
            </span>
          </span>
@@ -94,9 +95,8 @@
                      placeholder="数字,描述该模块在其父模块下的显示顺序"></el-input>
          </el-form-item>
          <el-form-item label="图标:">
              <avue-input-icon v-model="form.source" :disabled="!editStatus && !addStatus" :icon-list="iconList"
                               placeholder="请选择图标">
              </avue-input-icon>
              <input-icon v-model="form.source" :disabled="!editStatus && !addStatus" placeholder="请选择图标">
              </input-icon>
          </el-form-item>
          <el-form-item label="描述:">
            <el-input v-model="form.remark" :disabled="!editStatus && !addStatus" :rows="3" placeholder="请输入描述"
@@ -192,13 +192,11 @@
} from "@/api/systemModel/mangeModel/api"
import func from "@/util/func";
import basicOption from "@/util/basic-option";
import iconList from "@/config/iconList";
export default {
  name: "index",
  data() {
    return {
      iconList: iconList,
      tipList: [],
      upFileType: ['xls', 'xlsx'],
      fileUrl: 'api/hmSysModConfigController/importModule',