PersonalCenterIndex.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. <!--
  2. * @Description: 个人中心
  3. * @Author: 空白格
  4. * @Date: 2022-08-15 10:09:03
  5. * @LastEditors: 空白格
  6. * @LastEditTime: 2022-11-16 18:04:06
  7. * @FilePath: \veterans_client_web\src\views\PersonalCenter\PersonalCenterIndex.vue
  8. * @Copyright: Copyright (c) 2016~2022 by 空白格, All Rights Reserved.
  9. -->
  10. <template>
  11. <div class="app-main personal-center">
  12. <div class="personal-center-header">
  13. <div class="app-main-box personal-center-header-box">
  14. <el-row>
  15. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  16. <div class="pchb-left">
  17. <div class="pchb-left-avatar hexagon" @click="avatarClick">
  18. <div
  19. class="pchb-left-avatar-box hexagon-box"
  20. :style="{
  21. backgroundImage: `url('${
  22. userInfo.avatar
  23. ? userInfo.avatar
  24. : 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
  25. }')`,
  26. }"
  27. ></div>
  28. </div>
  29. <div class="pchb-left-user">
  30. <div class="pchb-left-user-item">
  31. <div class="plui-username">{{ userInfo.name || "-" }}</div>
  32. <div
  33. class="plui-integral"
  34. @click="jumpPage('/personalcenter/progresspoints')"
  35. >
  36. <div class="plui-integral-item">进步<br />积分</div>
  37. <div class="plui-integral-item">
  38. {{ integralTotal || 0 }}
  39. </div>
  40. <div class="plui-integral-item">
  41. <span class="el-icon-arrow-right"></span>
  42. </div>
  43. </div>
  44. </div>
  45. <div class="pchb-left-user-item">
  46. <div class="plui-auth">
  47. <div class="plui-auth-item">退役军人</div>
  48. <div class="plui-auth-item">
  49. <template v-if="userInfo.auditStatus === 0"
  50. >认证中</template
  51. >
  52. <template v-else-if="userInfo.auditStatus === 2"
  53. >已认证</template
  54. >
  55. <template v-else>
  56. <router-link to="/applyeducationauth"
  57. >未认证</router-link
  58. >
  59. </template>
  60. </div>
  61. </div>
  62. <div class="plui-train">
  63. <div class="plui-train-item">适应性培训</div>
  64. <div
  65. class="plui-train-item link"
  66. @click="jumpPage('/adaptivetraining')"
  67. >
  68. <template v-if="userInfo.adaptTrainIsPass === 1"
  69. >已通过</template
  70. >
  71. <template v-else>未通过</template>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. </div>
  77. </el-col>
  78. <el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
  79. <div class="pchb-right">
  80. <div
  81. class="pchb-right-item"
  82. v-for="(item, index) in statisticsList"
  83. :key="index"
  84. >
  85. <p>{{ item.label }}</p>
  86. <p>
  87. <span v-if="item.key === 'learnTime'">{{
  88. learnObj[item.key]
  89. ? (Number(learnObj[item.key]) / 3600).toFixed(2)
  90. : 0
  91. }}</span>
  92. <span v-else>{{ learnObj[item.key] || 0 }}</span
  93. >{{ item.unit }}
  94. </p>
  95. </div>
  96. </div>
  97. </el-col>
  98. </el-row>
  99. </div>
  100. </div>
  101. <div class="app-main-box personal-center-main">
  102. <el-row :gutter="20">
  103. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  104. <div class="personal-center-main-left">
  105. <div
  106. class="pcml-item"
  107. v-for="(item, index) in menuList"
  108. :key="index"
  109. @click="jumpPage(item.path)"
  110. >
  111. <div class="pcml-item-icon">
  112. <el-image :src="item.icon"></el-image>
  113. </div>
  114. <div class="pcml-item-label">{{ item.label }}</div>
  115. <div class="pcml-item-right">
  116. <span class="el-icon-arrow-right"></span>
  117. </div>
  118. </div>
  119. <div class="logout-btn" @click="logout">退出登录</div>
  120. </div>
  121. </el-col>
  122. <!-- <el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
  123. <div class="personal-center-main-right">
  124. <div class="pcmr-top">
  125. <h4>附件管理</h4>
  126. <div class="pcmr-top-btn upload-btn">上传简历</div>
  127. <div class="pcmr-top-btn make-btn">制作简历</div>
  128. </div>
  129. <div class="pcmr-bottom">
  130. <h4>我的技能培训</h4>
  131. <div class="pcmr-bottom-list">
  132. <template v-if="skillTrainList.length">
  133. <div
  134. class="pcmr-bottom-list-item"
  135. v-for="(item, index) in skillTrainList"
  136. :key="index"
  137. >
  138. <div class="pbli-left">
  139. <el-image
  140. class="image"
  141. :src="
  142. item.img ||
  143. require('@/assets/images/default-news.jpg')
  144. "
  145. fit="fill"
  146. >
  147. <div slot="placeholder" class="image-slot">
  148. 加载图片中<span class="dot">...</span>
  149. </div>
  150. <div slot="error" class="image-slot">
  151. <el-image
  152. class="image"
  153. :src="require('@/assets/images/default-news.jpg')"
  154. fit="fill"
  155. ></el-image>
  156. </div>
  157. </el-image>
  158. </div>
  159. <div class="pbli-right">
  160. <div class="pbli-right-item">{{ item.name }}</div>
  161. <div class="pbli-right-item">
  162. 培训学校:{{ item.schoolName }}
  163. </div>
  164. <div class="pbli-right-item">
  165. <div>难度:</div>
  166. <div>
  167. <el-rate
  168. v-model="item.difficult"
  169. disabled
  170. text-color="#ff9900"
  171. />
  172. </div>
  173. </div>
  174. <div class="pbli-right-item">
  175. 开始时间:{{ item.applyTime }}
  176. </div>
  177. <div class="pbli-right-item">
  178. 培训周期:{{ item.cycle || 0 }}个月
  179. </div>
  180. </div>
  181. </div>
  182. </template>
  183. <template v-else>
  184. <el-empty description="列表数据为空"></el-empty>
  185. </template>
  186. </div>
  187. </div>
  188. </div>
  189. </el-col> -->
  190. </el-row>
  191. </div>
  192. <!-- 上传头像弹框 -->
  193. <el-dialog
  194. :title="dialogObj.title"
  195. :visible.sync="dialogObj.open"
  196. width="400px"
  197. :before-close="handleClose"
  198. >
  199. <div class="dialog">
  200. <el-upload
  201. :action="uploadObj.action"
  202. :headers="uploadObj.headers"
  203. :on-success="uploadSuccess"
  204. :on-error="uploadError"
  205. :on-remove="fileRemove"
  206. :limit="1"
  207. >
  208. <div class="dialog-avatar hexagon">
  209. <div
  210. class="dialog-avatar-box hexagon-box"
  211. :style="{
  212. backgroundImage: `url('${
  213. dialogObj.avatarUrl ||
  214. 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
  215. }')`,
  216. }"
  217. ></div>
  218. </div>
  219. </el-upload>
  220. </div>
  221. <span slot="footer" class="dialog-footer">
  222. <el-button @click="handleClose">取 消</el-button>
  223. <el-button
  224. type="primary"
  225. :disabled="
  226. dialogObj.avatarUrl === userInfo.avatar || !dialogObj.avatarUrl
  227. "
  228. :loading="dialogObj.loading"
  229. @click="submitUpdate"
  230. >确 定</el-button
  231. >
  232. </span>
  233. </el-dialog>
  234. </div>
  235. </template>
  236. <script>
  237. import {
  238. getPersonInfoData,
  239. getPersonIntegralData,
  240. getPersonStaticisData,
  241. updateUserInfo,
  242. } from "@/api/PersonalCenter";
  243. export default {
  244. name: "PersonalCenterIndex",
  245. data() {
  246. return {
  247. userInfo: {},
  248. integralTotal: 0,
  249. statisticsList: [
  250. { label: "技能培训", key: "classCount", unit: "个" },
  251. { label: "学习时长", key: "learnTime", unit: "小时" },
  252. { label: "获得面试", key: "interviewTimes", unit: "次" },
  253. ],
  254. learnObj: {},
  255. menuList: [
  256. {
  257. icon: require("@/assets/images/personal-center-icon/jianlitongguo.svg"),
  258. label: "我的简历",
  259. path: "/personalcenter/resume",
  260. },
  261. {
  262. icon: require("@/assets/images/personal-center-icon/toudimoren.svg"),
  263. label: "我的投递",
  264. path: "/personalcenter/deliver",
  265. },
  266. {
  267. icon: require("@/assets/images/personal-center-icon/mianshi-houxuanren.svg"),
  268. label: "我的面试",
  269. path: "/personalcenter/interview",
  270. },
  271. // {
  272. // icon: require("@/assets/images/personal-center-icon/_jiuyechuangye.svg"),
  273. // label: "我的创业计划",
  274. // path: "",
  275. // },
  276. {
  277. icon: require("@/assets/images/personal-center-icon/jinengx.svg"),
  278. label: "我的技能培训",
  279. path: "/personalcenter/skilltraining",
  280. },
  281. {
  282. icon: require("@/assets/images/personal-center-icon/pingjia.svg"),
  283. label: "我的评价",
  284. path: "/personalcenter/evaluate",
  285. },
  286. // {
  287. // icon: require("@/assets/images/personal-center-icon/shezhi.svg"),
  288. // label: "设置",
  289. // path: "/personalcenter/setting",
  290. // },
  291. ],
  292. skillTrainList: [],
  293. dialogObj: {
  294. open: false,
  295. title: "个人资料修改",
  296. loading: false,
  297. avatarUrl: "",
  298. },
  299. uploadObj: {
  300. action: process.env.VUE_APP_BASE_API + "/file/upload/single/minio",
  301. headers: {
  302. Authorization: `Bearer ${this.$store.state.user.token}`,
  303. },
  304. },
  305. };
  306. },
  307. created() {
  308. this.getPersonInfo();
  309. this.getPersonIntegral();
  310. this.getPersonStaticis();
  311. },
  312. methods: {
  313. /**
  314. * 获取个人信息
  315. * @date 2022-08-15
  316. * @returns {any}
  317. */
  318. getPersonInfo() {
  319. getPersonInfoData().then((res) => {
  320. if (res.code === 200) {
  321. this.userInfo = res?.data;
  322. }
  323. });
  324. },
  325. /**
  326. * 获取个人积分
  327. * @date 2022-08-15
  328. * @returns {any}
  329. */
  330. getPersonIntegral() {
  331. getPersonIntegralData().then((res) => {
  332. if (res.code === 200) {
  333. this.integralTotal = res?.data;
  334. }
  335. });
  336. },
  337. /**
  338. * 获取个人统计
  339. * @date 2022-08-15
  340. * @returns {any}
  341. */
  342. getPersonStaticis() {
  343. getPersonStaticisData().then((res) => {
  344. if (res.code === 200) {
  345. this.learnObj = res?.data;
  346. }
  347. });
  348. },
  349. /**
  350. * 跳转指定页面
  351. * @date 2022-08-22
  352. * @param {any} path
  353. * @param {any} query
  354. * @returns {any}
  355. */
  356. jumpPage(path, query) {
  357. if (path) {
  358. this.$router.push(path, query);
  359. }
  360. },
  361. /**
  362. * 退出登录
  363. * @date 2022-08-25
  364. * @returns {any}
  365. */
  366. logout() {
  367. this.$confirm("您确认要退出登录吗?", "提示", {
  368. confirmButtonText: "确定",
  369. cancelButtonText: "取消",
  370. type: "warning",
  371. })
  372. .then(() => {
  373. this.$store.dispatch("Logout", {}).then((res) => {
  374. if (res.code === 200) {
  375. this.$message({
  376. type: "success",
  377. message: "退出登录成功!",
  378. });
  379. this.$router.push("/login");
  380. } else {
  381. this.$message({
  382. type: "error",
  383. message: res.msg || "退出登录失败!",
  384. });
  385. }
  386. });
  387. })
  388. .catch(() => {
  389. this.$message({
  390. type: "info",
  391. message: "已取消退出登录!",
  392. });
  393. });
  394. },
  395. /**
  396. * 头像点击
  397. * @date 2022-08-30
  398. * @returns {any}
  399. */
  400. avatarClick() {
  401. this.dialogObj.avatarUrl = this.userInfo.avatar;
  402. this.dialogObj.open = true;
  403. },
  404. /**
  405. * 关闭修改资料弹框
  406. * @date 2022-08-30
  407. * @returns {any}
  408. */
  409. handleClose() {
  410. this.dialogObj.avatarUrl = "";
  411. this.dialogObj.open = false;
  412. },
  413. /**
  414. * 上传成功
  415. * @date 2022-08-30
  416. * @param {any} res
  417. * @returns {any}
  418. */
  419. uploadSuccess(res) {
  420. if (res.code === 200) {
  421. this.dialogObj.avatarUrl = res.data.url;
  422. }
  423. },
  424. /**
  425. * 上传失败
  426. * @date 2022-08-30
  427. * @param {any} err
  428. * @returns {any}
  429. */
  430. uploadError(err) {
  431. this.$message.error(err.msg || "上传失败!");
  432. },
  433. /**
  434. * 文件移除触发
  435. * @date 2022-08-30
  436. * @param {any} file
  437. * @returns {any}
  438. */
  439. fileRemove(file) {
  440. this.dialogObj.avatarUrl = "";
  441. },
  442. /**
  443. * 提交头像修改
  444. * @date 2022-08-30
  445. * @returns {any}
  446. */
  447. submitUpdate() {
  448. if (
  449. this.dialogObj.avatarUrl &&
  450. this.dialogObj.avatarUrl !== this.userInfo.avatar
  451. ) {
  452. this.dialogObj.loading = true;
  453. updateUserInfo({ avatar: this.dialogObj.avatarUrl })
  454. .then((res) => {
  455. if (res.code === 200) {
  456. this.dialogObj.avatarUrl = "";
  457. this.$message.success("修改个人信息成功!");
  458. this.getPersonInfo();
  459. this.dialogObj.open = false;
  460. } else {
  461. this.$message.error("修改个人信息失败!");
  462. }
  463. this.dialogObj.loading = false;
  464. })
  465. .catch(() => {
  466. this.dialogObj.loading = false;
  467. });
  468. }
  469. },
  470. },
  471. };
  472. </script>
  473. <style lang="scss" scoped>
  474. .personal-center {
  475. &-header {
  476. width: 100%;
  477. background-color: #181c1e;
  478. &-box {
  479. margin: 0 auto;
  480. .pchb-left {
  481. padding-top: 30px;
  482. display: flex;
  483. align-items: center;
  484. &-avatar {
  485. padding-top: 30px;
  486. width: 138px;
  487. height: 138px;
  488. background-color: rgba($color: #fff, $alpha: 0.7);
  489. padding: 7px;
  490. margin-right: 20px;
  491. cursor: pointer;
  492. }
  493. &-user {
  494. &-item {
  495. display: flex;
  496. .plui-username {
  497. color: #fff;
  498. font-size: 40px;
  499. margin-right: 20px;
  500. line-height: 40px;
  501. }
  502. .plui-integral {
  503. height: 40px;
  504. display: flex;
  505. justify-content: space-between;
  506. align-content: center;
  507. border: solid 3px rgba($color: #fff, $alpha: 0.4);
  508. padding: 0 14px;
  509. background-image: linear-gradient(
  510. 270deg,
  511. #ff6100 16%,
  512. #fe7c02 100%
  513. );
  514. border-radius: 40px;
  515. cursor: pointer;
  516. &-item {
  517. color: #fff;
  518. &:first-child {
  519. font-size: 11px;
  520. padding: 4px 0;
  521. }
  522. &:nth-child(2) {
  523. font-size: 30px;
  524. padding: 0 20px;
  525. }
  526. &:last-child {
  527. line-height: 40px;
  528. }
  529. }
  530. }
  531. .plui-auth,
  532. .plui-train {
  533. display: flex;
  534. align-items: center;
  535. margin-top: 20px;
  536. &-item {
  537. color: rgba($color: #fff, $alpha: 0.6);
  538. font-size: 16px;
  539. &:last-child {
  540. margin-left: 15px;
  541. background-color: rgba($color: #fff, $alpha: 0.4);
  542. padding: 5px 20px;
  543. font-size: 14px;
  544. border-radius: 14px;
  545. }
  546. a {
  547. text-decoration: none;
  548. color: rgba($color: #fff, $alpha: 0.6);
  549. }
  550. }
  551. .link {
  552. cursor: pointer;
  553. }
  554. }
  555. .plui-train {
  556. margin-left: 30px;
  557. }
  558. }
  559. }
  560. }
  561. .pchb-right {
  562. height: 160px;
  563. padding-bottom: 40px;
  564. display: flex;
  565. justify-content: flex-end;
  566. align-items: flex-end;
  567. &-item {
  568. text-align: center;
  569. margin-left: 60px;
  570. color: #fff;
  571. font-size: 18px;
  572. &:first-child {
  573. margin-left: 0;
  574. }
  575. p {
  576. font-family: PingFangSC-Regular;
  577. span {
  578. color: #fe7b02;
  579. font-size: 36px;
  580. }
  581. }
  582. p:first-child {
  583. margin-bottom: 10px;
  584. font-weight: 500;
  585. font-family: PingFangSC-Medium;
  586. }
  587. }
  588. }
  589. }
  590. }
  591. &-main {
  592. &-left {
  593. background-color: #fff;
  594. padding: 20px 20px 200px;
  595. .pcml-item {
  596. display: flex;
  597. justify-content: space-between;
  598. align-items: center;
  599. margin-bottom: 20px;
  600. border-bottom: 1px solid #d5d5d5;
  601. padding: 5px 0 15px;
  602. cursor: pointer;
  603. &-icon {
  604. width: 30px;
  605. height: 30px;
  606. margin-right: 20px;
  607. image {
  608. width: 100%;
  609. height: 100%;
  610. }
  611. }
  612. &-label {
  613. flex: 1;
  614. font-size: 18px;
  615. color: #333333;
  616. }
  617. }
  618. .logout-btn {
  619. margin: 54px auto 24px;
  620. width: 240px;
  621. height: 38px;
  622. line-height: 38px;
  623. text-align: center;
  624. border: 1px solid #ff0000;
  625. color: #f00;
  626. border-radius: 7px;
  627. cursor: pointer;
  628. letter-spacing: 1.34px;
  629. }
  630. }
  631. &-right {
  632. .pcmr-top {
  633. background-color: #fff;
  634. padding: 20px;
  635. margin-bottom: 20px;
  636. h4 {
  637. color: #1a1a1a;
  638. font-size: 26px;
  639. font-family: SourceHanSansCN;
  640. margin-bottom: 20px;
  641. }
  642. &-btn {
  643. width: 100%;
  644. height: 52px;
  645. line-height: 52px;
  646. text-align: center;
  647. font-size: 18px;
  648. cursor: pointer;
  649. }
  650. .upload-btn {
  651. background-color: #659789;
  652. color: #fff;
  653. margin-bottom: 10px;
  654. }
  655. .make-btn {
  656. border: solid 1px #659789;
  657. color: #659789;
  658. margin-bottom: 30px;
  659. }
  660. }
  661. .pcmr-bottom {
  662. background: #fff;
  663. padding: 20px 20px 100px;
  664. h4 {
  665. color: #1a1a1a;
  666. font-size: 26px;
  667. font-family: SourceHanSansCN;
  668. margin-bottom: 20px;
  669. }
  670. &-list {
  671. &-item {
  672. display: flex;
  673. align-items: center;
  674. cursor: pointer;
  675. padding-bottom: 10px;
  676. border-bottom: 1px solid #d5d5d5;
  677. margin-bottom: 20px;
  678. .pbli-left {
  679. width: 110px;
  680. height: 104px;
  681. border: solid 1px #e0e0e0;
  682. border-radius: 5px;
  683. margin-right: 15px;
  684. .image {
  685. width: 98%;
  686. height: 100%;
  687. }
  688. }
  689. .pbli-right {
  690. &-item {
  691. color: #747474;
  692. font-size: 14px;
  693. display: flex;
  694. margin-bottom: 5px;
  695. &:first-child {
  696. font-size: 18px;
  697. color: #1a1a1a;
  698. }
  699. }
  700. }
  701. }
  702. }
  703. }
  704. }
  705. }
  706. }
  707. .dialog {
  708. display: flex;
  709. justify-content: center;
  710. &-avatar {
  711. padding-top: 30px;
  712. width: 138px;
  713. height: 138px;
  714. background-color: rgba($color: #000, $alpha: 0.5);
  715. padding: 7px;
  716. margin-right: 20px;
  717. cursor: pointer;
  718. }
  719. }
  720. </style>