图书馆综合管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

382 lines
12 KiB

7 months ago
7 months ago
7 months ago
  1. <template>
  2. <div class="app-container category-container">
  3. <div class="container-main">
  4. <div class="elect-cont-left">
  5. <div class="container-left">
  6. <span class="right-top-line" />
  7. <span class="left-bottom-line" />
  8. <div class="user-content">
  9. <h4 class="info-title">个人信息</h4>
  10. <div class="el-upload">
  11. <div class="user-img-cover">
  12. <img :src="user.avatarName ? baseApi + '/avatar/' + user.avatarName : Avatar" title="点击上传头像" class="avatar" :onerror="defaultImg" @click="toggleShow">
  13. </div>
  14. <myUpload
  15. v-model="show"
  16. :headers="headers"
  17. :url="updateAvatarApi"
  18. @crop-upload-success="cropUploadSuccess"
  19. />
  20. </div>
  21. <ul class="user-info">
  22. <li><p><i class="iconfont icon-zhanghao" />账号</p><div class="user-right">{{ user.username }}</div></li>
  23. <li><p><i class="iconfont icon-yonghuming" style="font-size: 13px;" />用户名</p><div class="user-right">{{ user.nickName }}</div></li>
  24. <li><p><i class="iconfont icon-xingbie" />性别</p><div class="user-right">{{ user.gender ? user.gender : '-' }}</div></li>
  25. <li><p><i class="iconfont icon-yonghujiaose" style="font-size: 12px;" />用户角色</p><div class="user-right"><span v-for="item in user.roles" :key="item.id">{{ item.name }}</span></div></li>
  26. <li><p><i class="iconfont icon-suoshuquanzong" />所属机构</p><div class="user-right">{{ user.fonds ? user.fonds.fondsName : '/' }}</div></li>
  27. <li><p><i class="iconfont icon-suoshubumen" />所属部门</p><div class="user-right">{{ user.dept ? user.dept.deptsName : '/' }}</div></li>
  28. <li><p><i class="iconfont icon-shoujihaoma" />手机号码</p><div class="user-right">{{ user.email ? user.phone : '-' }}</div></li>
  29. <li><p><i class="iconfont icon-yonghuyouxiang" style="font-size: 12px;" />用户邮箱</p><div class="user-right">{{ user.email ? user.email : '-' }}</div></li>
  30. <li><p><i class="iconfont icon-yanzhengma" />安全设置</p><div class="user-right"><a @click="$refs.pass.dialog = true">修改密码</a></div></li>
  31. </ul>
  32. </div>
  33. </div>
  34. </div>
  35. <div class="elect-cont-right">
  36. <div class="container-right tab-content">
  37. <span class="right-top-line" />
  38. <span class="left-bottom-line" />
  39. <ul class="tab-nav">
  40. <li :class="{'active-tab-nav': activeIndex == 0}" @click="handleClick(0)">用户资料<i /></li>
  41. <li :class="{'active-tab-nav': activeIndex == 1}" @click="handleClick(1)">消息中心<i /></li>
  42. <li :class="{'active-tab-nav': activeIndex == 2}" @click="handleClick(2)">操作日志<i /></li>
  43. <!-- 最右侧装饰img -->
  44. <span class="tab-right-img" />
  45. </ul>
  46. <div v-if="activeIndex == 0" class="tab-item">
  47. <el-form ref="form" class="tab-form" :model="form" :rules="rules" size="small" label-width="100px">
  48. <el-form-item label="用户名" prop="nickName">
  49. <el-input v-model="form.nickName" style="width: 324px" />
  50. <span class="form-tip">用户昵称不作为登录使用</span>
  51. </el-form-item>
  52. <el-form-item label="手机号码" prop="phone">
  53. <el-input v-model="form.phone" style="width: 324px" />
  54. <span class="form-tip">手机号码不能重复</span>
  55. </el-form-item>
  56. <el-form-item label="用户邮箱" prop="email">
  57. <el-input v-model="form.email" style="width: 324px" />
  58. </el-form-item>
  59. <el-form-item label="性别" prop="gender">
  60. <el-radio-group v-model="form.gender" style="width: 178px">
  61. <el-radio label="男"></el-radio>
  62. <el-radio label="女"></el-radio>
  63. </el-radio-group>
  64. </el-form-item>
  65. <el-form-item>
  66. <el-button class="user-submit" :loading="saveLoading" size="mini" type="primary" @click="doSubmit">保存</el-button>
  67. </el-form-item>
  68. </el-form>
  69. </div>
  70. <!-- 消息中心 -->
  71. <div v-if="activeIndex == 1" class="tab-item">
  72. <messageCenter />
  73. </div>
  74. <!-- 操作日志 -->
  75. <div v-if="activeIndex == 2" class="tab-item" style="padding-left: 20px;">
  76. <OperateLog :is-center="isCenter" />
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. <updateEmail ref="email" :email="user.email" />
  82. <updatePass ref="pass" />
  83. </div>
  84. </template>
  85. <script>
  86. import myUpload from 'vue-image-crop-upload/upload-2.vue'
  87. import { mapGetters } from 'vuex'
  88. import updatePass from './center/updatePass'
  89. import updateEmail from './center/updateEmail'
  90. import { getToken } from '@/utils/auth'
  91. import store from '@/store'
  92. import { isvalidPhone } from '@/utils/validate'
  93. import { editUser } from '@/api/system/user'
  94. import Avatar from '@/assets/images/avatar.png'
  95. import messageCenter from './messageCenter/index'
  96. import OperateLog from '@/views/system/log/operateLog/index'
  97. export default {
  98. name: 'Center',
  99. components: { updatePass, updateEmail, myUpload, messageCenter, OperateLog },
  100. data() {
  101. // 自定义验证
  102. const validPhone = (rule, value, callback) => {
  103. if (!value) {
  104. callback(new Error('请输入电话号码'))
  105. } else if (!isvalidPhone(value)) {
  106. callback(new Error('请输入正确的11位手机号码'))
  107. } else {
  108. callback()
  109. }
  110. }
  111. return {
  112. isCenter: true,
  113. defaultImg: 'this.src="' + require('@/assets/images/avatar.png') + '"',
  114. show: false,
  115. Avatar: Avatar,
  116. activeIndex: 0,
  117. saveLoading: false,
  118. headers: {
  119. 'Authorization': getToken()
  120. },
  121. form: {},
  122. query: {
  123. keyword: null,
  124. createTime: []
  125. },
  126. rules: {
  127. nickName: [
  128. { required: true, message: '请输入用户昵称', trigger: 'blur' },
  129. { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
  130. ],
  131. phone: [
  132. { required: true, trigger: 'blur', validator: validPhone }
  133. ],
  134. gender: [
  135. { required: true, message: '请选择性别', trigger: 'change' }
  136. ]
  137. }
  138. }
  139. },
  140. computed: {
  141. ...mapGetters([
  142. 'user',
  143. 'updateAvatarApi',
  144. 'baseApi'
  145. ])
  146. },
  147. watch: {
  148. '$route'(val, from) { // 监听到路由(参数)改变
  149. if (this.$route.query) {
  150. this.activeIndex = this.$route.query.activeIndex
  151. }
  152. }
  153. },
  154. created() {
  155. this.form = { userId: this.user.id, nickName: this.user.nickName, gender: this.user.gender, phone: this.user.phone, email: this.user.email }
  156. store.dispatch('GetInfo').then(() => {})
  157. if (this.$route.query) {
  158. this.activeIndex = this.$route.query.activeIndex
  159. }
  160. },
  161. methods: {
  162. toggleShow() {
  163. this.show = !this.show
  164. },
  165. handleClick(index) {
  166. this.activeIndex = index
  167. },
  168. beforeInit() {
  169. this.url = 'api/logs/user'
  170. return true
  171. },
  172. cropUploadSuccess(jsonData, field) {
  173. store.dispatch('GetInfo').then(() => {})
  174. },
  175. doSubmit() {
  176. if (this.$refs['form']) {
  177. this.$refs['form'].validate((valid) => {
  178. if (valid) {
  179. this.saveLoading = true
  180. editUser(this.form).then(() => {
  181. this.editSuccessNotify()
  182. store.dispatch('GetInfo').then(() => {})
  183. this.saveLoading = false
  184. }).catch(() => {
  185. this.saveLoading = false
  186. })
  187. }
  188. })
  189. }
  190. }
  191. }
  192. }
  193. </script>
  194. <style lang="scss" scoped>
  195. @import "~@/assets/styles/mixin.scss";
  196. .app-container{
  197. margin: 0 20px !important;
  198. }
  199. @mixin info-title-style{
  200. [data-theme="dark"] & {
  201. color: #fff;
  202. background-color: #02255F;
  203. }
  204. [data-theme="light"] & {
  205. color: #0C0E1E;
  206. border-bottom: 1px solid #EDEFF3;
  207. }
  208. }
  209. .container-main{
  210. position: relative;
  211. margin-top: 90px;
  212. z-index: 9;
  213. }
  214. .operateLog-main{
  215. height: calc(100vh - 300px);
  216. }
  217. .elect-cont-left{
  218. width: 368px !important;
  219. padding: 0 !important;
  220. }
  221. [data-theme=dark] .elect-cont-left .container-left{
  222. min-height: calc(100vh - 247px) !important;
  223. }
  224. [data-theme=dark] .elect-cont-right .container-right {
  225. min-height: calc(100vh - 288px) !important;
  226. }
  227. [data-theme=light] .elect-cont-right {
  228. padding: 20px 20px 0 0 !important;
  229. }
  230. [data-theme=light] .elect-cont-left .container-left{
  231. min-height: calc(100vh - 260px) !important;
  232. }
  233. [data-theme=light] .elect-cont-right .container-right {
  234. min-height: calc(100vh - 250px) !important;
  235. }
  236. [data-theme=dark] .category-container .tab-content .head-container{
  237. margin: 20px 0 !important;
  238. }
  239. .user-content{
  240. color: #fff;
  241. .iconfont{
  242. margin-right: 12px;
  243. }
  244. }
  245. .info-title{
  246. height: 56px;
  247. line-height: 56px;
  248. font-size: 16px;
  249. font-weight: bold;
  250. text-align: center;
  251. @include info-title-style;
  252. }
  253. .el-upload{
  254. display: block;
  255. width: 148px;
  256. height: 148px;
  257. border-radius: 50%;
  258. margin: 40px auto 60px auto;
  259. overflow: hidden;
  260. .user-img-cover{
  261. width: 148px;
  262. height: 148px;
  263. line-height: 148px;
  264. }
  265. .avatar {
  266. width: 100%;
  267. height: 100%;
  268. }
  269. }
  270. @mixin user-info-list-style{
  271. [data-theme="dark"] & {
  272. color: #fff;
  273. & li{
  274. border-bottom: 1px solid #113D72;
  275. }
  276. & .user-right {
  277. a{
  278. color: #3A99FD;
  279. }
  280. }
  281. }
  282. [data-theme="light"] & {
  283. color: #545B65;
  284. & li{
  285. border-bottom: 1px solid #F5F9FC;
  286. }
  287. & .user-right {
  288. color: #0C0E1E;
  289. a{
  290. color: #0348F3;
  291. }
  292. }
  293. }
  294. }
  295. .user-info {
  296. padding: 0 20px;
  297. list-style: none;
  298. @include user-info-list-style;
  299. li{
  300. display: flex;
  301. justify-content: space-between;
  302. align-items: center;
  303. font-size: 14px;
  304. // height: 41px;
  305. line-height: 34px;
  306. }
  307. .user-right {
  308. a{
  309. margin-left: 20px;
  310. }
  311. span{
  312. display: block;
  313. text-align: right;
  314. line-height: 30px;
  315. }
  316. }
  317. }
  318. [data-theme=light] .tab-item {
  319. ::v-deep .el-form.tab-form{
  320. margin-top: 40px;
  321. }
  322. .user-submit{
  323. color: #fff;
  324. background-color: #0348F3;
  325. }
  326. }
  327. .tab-item{
  328. ::v-deep .el-form{
  329. .el-form-item__label.el-form-item__label{
  330. @include setting-item-font;
  331. }
  332. .form-tip{
  333. margin-left: 11px;
  334. font-size: 12px;
  335. color: #A6ADB6;
  336. }
  337. .user-submit{
  338. width: 76px;
  339. }
  340. }
  341. }
  342. .user-header-search{
  343. margin-bottom: 20px;
  344. .filter-search{
  345. margin-right: 0;
  346. @include btn_blue_style;
  347. &:hover{
  348. @include btn_blue_hover;
  349. }
  350. }
  351. .filter-refresh{
  352. @include btn_white_style;
  353. &:hover{
  354. @include btn_white_hover;
  355. }
  356. }
  357. }
  358. input:-webkit-autofill,
  359. textarea:-webkit-autofill,
  360. select:-webkit-autofill {
  361. -webkit-text-fill-color: #fff !important;
  362. background-color: transparent;
  363. transition: background-color 50000s ease-in-out 0s;
  364. }
  365. input {
  366. background-color: transparent;
  367. }
  368. ::v-deep .vue-image-crop-upload .vicp-wrap .vicp-operate a{
  369. border: 1px solid #e6e8ed;
  370. background-color: transparent;
  371. color: #545b65;
  372. border-radius: 3px;
  373. }
  374. </style>