index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="10">
  4. <el-col :xs="24" :sm="12">
  5. <el-card class="user-center">
  6. <div slot="header" class="clearfix">
  7. <span>关于我</span>
  8. </div>
  9. <div class="user-profile">
  10. <div class="box-center">
  11. <pan-thumb :image="avatar" :height="'100px'" :width="'100px'" :hoverable="false">
  12. <el-link type="primary" class="change-avatar" @click="dialogVisible = true">更换头像</el-link>
  13. </pan-thumb>
  14. </div>
  15. <div class="box-center">
  16. <div class="user-name text-center">{{ user.username }}</div>
  17. <div class="user-role text-center text-muted">
  18. <span>{{ user.deptName ? user.deptName : '没有' }}</span> · <span>{{ user.roleName ? user.roleName : '没有' }}</span>
  19. </div>
  20. </div>
  21. </div>
  22. <div class="user-bio">
  23. <!-- <div class="user-education user-bio-section">
  24. <div class="user-bio-section-header"><el-icon class="el-icon-connection" /><span>第三方账号</span></div>
  25. <div class="user-bio-section-body">
  26. <div class="text-muted">
  27. <template v-for="(l, index) in logo">
  28. <div :key="index" class="logo-wrapper">
  29. <img v-if="l.bind" :src="resolveLogo(l.img)" :class="{ 'radius': l.radius }" alt="" title="1" @click="unbind(l.name)">
  30. <img v-else :src="resolveLogo(l.img)" :class="{ 'radius': l.radius }" alt="" title="2" class="unbind" @click="bind(l.name)">
  31. </div>
  32. </template>
  33. </div>
  34. </div>
  35. </div> -->
  36. </div>
  37. </el-card>
  38. </el-col>
  39. <el-col :xs="24" :sm="12">
  40. <el-card class="user-center">
  41. <el-tabs v-model="activeName" @tab-click="handleClick">
  42. <el-tab-pane label="个人信息" name="first">
  43. <div class="user" style="width: 600px">
  44. <el-form ref="form" :model="user" label-width="80px">
  45. <el-form-item label="用户名">
  46. <el-input v-model="user.username" />
  47. </el-form-item>
  48. <el-form-item label="头像">
  49. <el-upload
  50. class="avatar-uploader"
  51. action="https://jsonplaceholder.typicode.com/posts/"
  52. :show-file-list="false"
  53. :before-upload="beforeAvatarUpload"
  54. >
  55. <img v-if="user.avatar" :src="user.avatar" class="avatar" alt="">
  56. <i v-else class="el-icon-plus avatar-uploader-icon" />
  57. </el-upload>
  58. </el-form-item>
  59. <el-form-item label="手机号">
  60. <el-input v-model="user.phone" />
  61. </el-form-item>
  62. <!-- <el-form-item label="用户邮箱">
  63. <el-input v-model="user.email" :disabled="true" />
  64. </el-form-item> -->
  65. <el-form-item label="所属部门">
  66. <el-input v-model="user.deptName" :disabled="true" />
  67. </el-form-item>
  68. <el-form-item>
  69. <el-button type="primary">提交</el-button>
  70. <el-button>取消</el-button>
  71. </el-form-item>
  72. </el-form>
  73. </div>
  74. </el-tab-pane>
  75. <el-tab-pane label="修改密码" name="second">
  76. <div style="width: 400px">
  77. <el-form
  78. ref="passForm"
  79. :model="passForm"
  80. status-icon
  81. :rules="rules"
  82. label-width="100px"
  83. class="demo-ruleForm"
  84. >
  85. <el-form-item label="原密码" prop="oldPass">
  86. <el-input v-model="passForm.oldPass" type="password" autocomplete="off" />
  87. </el-form-item>
  88. <el-form-item label="密码" prop="newPass">
  89. <el-input v-model="passForm.newPass" type="password" autocomplete="off" />
  90. </el-form-item>
  91. <el-form-item label="确认密码" prop="checkPass">
  92. <el-input v-model="passForm.checkPass" type="password" autocomplete="off" />
  93. </el-form-item>
  94. <el-form-item>
  95. <el-button type="primary" @click="updatePass('passForm')">修改</el-button>
  96. <el-button @click="resetForm('passForm')">重置</el-button>
  97. </el-form-item>
  98. </el-form>
  99. </div>
  100. </el-tab-pane>
  101. <!-- <el-tab-pane label="修改邮箱" name="third">
  102. <div style="width: 500px">
  103. <el-form ref="mailForm" :model="mailForm" label-width="100px" class="demo-ruleForm">
  104. <el-form-item
  105. prop="email"
  106. label="邮箱"
  107. :rules="[{ required: true, message: '请输入邮箱地址', trigger: 'blur' },
  108. { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }]"
  109. >
  110. <el-input v-model="mailForm.email" style="width: 250px;" />
  111. <el-button :loading="codeLoading" :disabled="isDisabled" @click="sendCode">{{ buttonName }}
  112. </el-button>
  113. </el-form-item>
  114. <el-form-item
  115. label="验证码"
  116. prop="code"
  117. :rules="[{ required: true, message: '验证码不能为空'}]"
  118. >
  119. <el-input v-model="mailForm.code" type="age" autocomplete="off" />
  120. </el-form-item>
  121. <el-form-item
  122. label="密码"
  123. prop="pass"
  124. :rules="[{ required: true, message: '密码不能为空'}]"
  125. >
  126. <el-input v-model="mailForm.pass" type="age" autocomplete="off" />
  127. </el-form-item>
  128. <el-form-item>
  129. <el-button type="primary" @click="updateEmail('mailForm')">提交</el-button>
  130. <el-button @click="resetForm('mailForm')">重置</el-button>
  131. </el-form-item>
  132. </el-form>
  133. </div>
  134. </el-tab-pane> -->
  135. </el-tabs>
  136. </el-card>
  137. </el-col>
  138. </el-row>
  139. </div>
  140. </template>
  141. <script>
  142. import PanThumb from '@/components/PanThumb'
  143. import { getUserInfo, updatePass, resetEmail, updateEmail } from '@/api/user'
  144. export default {
  145. name: 'Index',
  146. components: { PanThumb },
  147. data() {
  148. const validatePass = (rule, value, callback) => {
  149. if (value === '') {
  150. callback(new Error('请输入密码'))
  151. } else {
  152. if (this.passForm.checkPass !== '') {
  153. this.$refs.passForm.validateField('checkPass')
  154. }
  155. callback()
  156. }
  157. }
  158. const validatePass2 = (rule, value, callback) => {
  159. if (value === '') {
  160. callback(new Error('请再次输入密码'))
  161. } else if (value !== this.passForm.newPass) {
  162. callback(new Error('两次输入密码不一致!'))
  163. } else {
  164. callback()
  165. }
  166. }
  167. return {
  168. user: {
  169. avatar: '',
  170. username: '',
  171. phone: 0,
  172. email: '',
  173. deptName: '',
  174. jobName: '',
  175. createTime: ''
  176. },
  177. activeName: 'first',
  178. passForm: {
  179. oldPass: '',
  180. newPass: '',
  181. checkPass: ''
  182. },
  183. rules: {
  184. oldPass: [{ required: true, message: '原密码不能为空', trigger: 'blur' }],
  185. newPass: [{ validator: validatePass, trigger: 'blur' }],
  186. checkPass: [{ validator: validatePass2, trigger: 'blur' }]
  187. },
  188. mailForm: {
  189. email: '',
  190. code: '',
  191. pass: ''
  192. },
  193. buttonName: '发送验证码',
  194. isDisabled: false,
  195. codeLoading: false,
  196. time: 60,
  197. logo: [
  198. { img: 'gitee.png', name: 'gitee', bind: false, radius: true },
  199. { img: 'github.png', name: 'github', bind: false, radius: true },
  200. { img: 'tencent_cloud.png', name: 'tencent_cloud', bind: false, radius: true },
  201. { img: 'qq.png', name: 'qq', bind: false, radius: false },
  202. { img: 'dingtalk.png', name: 'dingtalk', bind: false, radius: true },
  203. { img: 'microsoft.png', name: 'microsoft', bind: false, radius: false }
  204. ]
  205. }
  206. },
  207. computed: {
  208. avatar() {
  209. return require(`@/assets/avatar/c7c4ee7be3eb4e73a19887dc713505145.jpg`)
  210. }
  211. },
  212. created() {
  213. this.findUserInfo()
  214. },
  215. methods: {
  216. // parseTime,
  217. // formatEmail(mail) {
  218. // return regEmail(mail)
  219. // },
  220. resolveLogo(logo) {
  221. return require(`@/assets/logo/${logo}`)
  222. },
  223. // 加载用户个人信息
  224. findUserInfo: function() {
  225. getUserInfo().then((res) => {
  226. this.user = res.data.data
  227. // console.log(res)
  228. })
  229. },
  230. // 修改密码
  231. updatePass: function(formName) {
  232. this.$refs[formName].validate((valid) => {
  233. if (valid) {
  234. const params = new URLSearchParams()
  235. params.append('oldPass', this.passForm.oldPass)
  236. params.append('newPass', this.passForm.newPass)
  237. updatePass(params).then((res) => {
  238. if (res.data.code === 200) {
  239. this.$message({
  240. type: 'success',
  241. message: '操作成功'
  242. })
  243. this.activeName = 'second'
  244. this.$refs['passForm'].resetFields()
  245. } else {
  246. this.$message({
  247. type: 'error',
  248. message: res.data.msg
  249. })
  250. }
  251. })
  252. } else {
  253. return false
  254. }
  255. })
  256. },
  257. // 修改邮箱
  258. updateEmail: function(formName) {
  259. this.$refs[formName].validate((valid) => {
  260. if (valid) {
  261. const params = new URLSearchParams()
  262. params.append('mail', this.mailForm.email)
  263. params.append('code', this.mailForm.code)
  264. params.append('pass', this.mailForm.pass)
  265. updateEmail(params).then((res) => {
  266. if (res.data.code === 200) {
  267. this.$message({
  268. type: 'success',
  269. message: '操作成功'
  270. })
  271. this.activeName = 'third'
  272. this.$refs['mailForm'].resetFields()
  273. } else {
  274. this.$message({
  275. type: 'error',
  276. message: res.data.msg
  277. })
  278. }
  279. })
  280. } else {
  281. return false
  282. }
  283. })
  284. },
  285. // 发送邮箱验证码
  286. sendCode() {
  287. if (this.mailForm.email && this.mailForm.email !== '') {
  288. this.codeLoading = true
  289. this.buttonName = '验证码发送中'
  290. const params = new URLSearchParams()
  291. params.append('to', this.mailForm.email)
  292. const _this = this
  293. resetEmail(params).then(res => {
  294. if (res.data.code === 200) {
  295. this.$message({
  296. showClose: true,
  297. message: '发送成功,验证码有效期5分钟',
  298. type: 'success'
  299. })
  300. this.codeLoading = false
  301. this.isDisabled = true
  302. this.buttonName = this.time-- + '秒后重新发送'
  303. this.timer = window.setInterval(function() {
  304. _this.buttonName = _this.time + '秒后重新发送'
  305. --_this.time
  306. if (_this.time < 0) {
  307. _this.buttonName = '重新发送'
  308. _this.time = 60
  309. _this.isDisabled = false
  310. window.clearInterval(_this.timer)
  311. }
  312. }, 1000)
  313. }
  314. }).catch(err => {
  315. this.resetForm()
  316. this.codeLoading = false
  317. console.log(err.data.message)
  318. })
  319. }
  320. },
  321. // handleSuccess(response, file, fileList) {
  322. // this.$notify({
  323. // title: '头像修改成功',
  324. // type: 'success',
  325. // duration: 2500
  326. // })
  327. // store.dispatch('GetInfo').then(() => {
  328. // })
  329. // },
  330. // 监听上传失败
  331. // handleError(e, file, fileList) {
  332. // const msg = JSON.parse(e.message)
  333. // this.$notify({
  334. // title: msg.message,
  335. // type: 'error',
  336. // duration: 2500
  337. // })
  338. // },
  339. refresh() {
  340. this.ico = 'el-icon-loading'
  341. this.$refs.log.init()
  342. setTimeout(() => {
  343. this.ico = 'el-icon-refresh'
  344. }, 300)
  345. },
  346. submitForm(formName) {
  347. this.$refs[formName].validate((valid) => {
  348. if (valid) {
  349. alert('submit!')
  350. } else {
  351. console.log('error submit!!')
  352. return false
  353. }
  354. })
  355. },
  356. resetForm(formName) {
  357. if (this.$refs[formName] !== undefined) {
  358. this.$refs[formName].resetFields()
  359. }
  360. },
  361. handleClick(tab, event) {
  362. console.log(tab, event)
  363. },
  364. // handleAvatarSuccess(res, file) {
  365. // // this.imageUrl = URL.createObjectURL(file.raw)
  366. // const data = new FormData()
  367. // data.append('token', '')
  368. // data.append('file', file[0])
  369. // axiosInstance({
  370. // method: 'POST',
  371. // url: 'http://up.qiniu.com',
  372. // data: data
  373. // })
  374. // .then(function(res) {
  375. // // console.log('res',res)
  376. // const { base_url, path } = res.data
  377. // // 页面所用字段
  378. // self.previewAvatar = `${base_url}${path}?imageView2/1/w/154/h/154`
  379. // // 传给后台不完整
  380. // self.formData.avatar = `${path}`
  381. // })
  382. // .catch(function(err) {
  383. // console.log('err', err)
  384. // })
  385. // },
  386. beforeAvatarUpload(file) {
  387. const isJPG = file.type === 'image/jpeg'
  388. const isLt2M = file.size / 1024 / 1024 < 2
  389. if (!isJPG) {
  390. this.$message.error('上传头像图片只能是 JPG 格式!')
  391. }
  392. if (!isLt2M) {
  393. this.$message.error('上传头像图片大小不能超过 2MB!')
  394. }
  395. return isJPG && isLt2M
  396. }
  397. }
  398. }
  399. </script>
  400. <style lang="scss" scoped>
  401. .user-center{
  402. height: 440px;
  403. }
  404. .box-center {
  405. margin: 0 auto;
  406. display: table;
  407. }
  408. .text-muted {
  409. color: #777;
  410. }
  411. .user-profile {
  412. .user-name {
  413. font-weight: bold;
  414. }
  415. .box-center {
  416. padding-top: 10px;
  417. }
  418. .user-role {
  419. padding-top: 10px;
  420. font-weight: 400;
  421. font-size: 14px;
  422. }
  423. .box-social {
  424. padding-top: 30px;
  425. .el-table {
  426. border-top: 1px solid #dfe6ec;
  427. }
  428. }
  429. .user-follow {
  430. padding-top: 20px;
  431. }
  432. }
  433. .user-bio {
  434. margin-top: 20px;
  435. color: #606266;
  436. span {
  437. padding-left: 4px;
  438. }
  439. .logo-wrapper {
  440. display: inline-block;
  441. margin: 10px 0;
  442. img {
  443. width: 1.4rem;
  444. display: inline-block;
  445. margin: 0 .6rem;
  446. cursor: pointer;
  447. &.unbind {
  448. -webkit-filter: grayscale(100%);
  449. -moz-filter: grayscale(100%);
  450. -o-filter: grayscale(100%);
  451. filter: grayscale(100%);
  452. }
  453. &.radius {
  454. border-radius: 50%;
  455. }
  456. }
  457. }
  458. .user-bio-section {
  459. font-size: 14px;
  460. padding: 15px 0;
  461. .user-bio-section-header {
  462. border-bottom: 1px solid #dfe6ec;
  463. padding-bottom: 10px;
  464. margin-bottom: 10px;
  465. font-weight: bold;
  466. }
  467. }
  468. }
  469. </style>