Commit d8b5fd57 authored by 水落(YangLei)'s avatar 水落(YangLei)

feat: 更新用户信息完成

parent 5efc64b4
import { putReq } from '@/utils'; import { getReq, postReq, putReq } from '@/utils';
/**
* 退出登录
*/
export function logoutApi() { export function logoutApi() {
return putReq('/api/v1/logout'); return putReq('/api/v1/logout');
} }
/**
* 修改密码
*/
export function modifyPasswordApi(data) {
return putReq('/api/v1/users/password', data);
}
/**
* 修改用户信息
*/
export function updateUserInfoApi(data) {
return putReq('/api/v1/users/profile', data);
}
/**
* 获取当前用户信息
*/
export function getUserInfoApi() {
return getReq('/api/v1/detail');
}
/**
* 上传文件
*/
export function uploadFileApi(modelName, file) {
const formData = new FormData();
formData.append('modelName', modelName);
formData.append('file', file);
return postReq('/api/v1/upload', formData);
}
import Table from './table/index.vue'; import Table from './table/index.vue';
import WhiteCard from './white_card/index.vue';
import Upload from './upload/index.vue';
export { Table }; export { Table, WhiteCard, Upload };
<template> <template>
<div> <div>
<div :class="$style.card" v-if="$scopedSlots.search"> <my-card v-if="$scopedSlots.search">
<a-form-model layout="inline" :model="queryForm"> <a-form-model layout="inline" :model="queryForm">
<slot name="search" :query="queryForm" /> <slot name="search" :query="queryForm" />
</a-form-model> </a-form-model>
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
<a-button type="primary" @click="getData">查询</a-button> <a-button type="primary" @click="getData">查询</a-button>
</a-space> </a-space>
</div> </div>
</div> </my-card>
<div class="tw-mt-3" :class="$style.card"> <my-card class="tw-mt-3">
<a-space class="tw-mb-2.5"> <a-space class="tw-mb-2.5">
<a-button v-if="addBtn" type="primary" key="add" v-bind="addBtn.options" @click="add"> <a-button v-if="addBtn" type="primary" key="add" v-bind="addBtn.options" @click="add">
{{ addBtn.text || '新建' }} {{ addBtn.text || '新建' }}
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
> >
<slot /> <slot />
</a-table> </a-table>
</div> </my-card>
<!-- 新增 --> <!-- 新增 -->
<a-drawer <a-drawer
...@@ -196,9 +196,3 @@ export default { ...@@ -196,9 +196,3 @@ export default {
}, },
}; };
</script> </script>
<style module>
.card {
@apply tw-bg-white tw-rounded-md tw-p-4;
}
</style>
...@@ -10,85 +10,82 @@ ...@@ -10,85 +10,82 @@
</template> </template>
<script> <script>
import {globalConfig} from '@/config' import { globalConfig } from '@/config';
const animates = globalConfig.animates.preset; const animates = globalConfig.animates.preset;
export default { export default {
name: 'PageToggleTransition', name: 'PageToggleTransition',
props: { props: {
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
animate: { animate: {
type: String, type: String,
validator(value) { validator(value) {
return animates.findIndex(item => item.name == value) != -1 return animates.findIndex(item => item.name == value) != -1;
}, },
default: 'bounce' default: 'bounce',
}, },
direction: { direction: {
type: String, type: String,
}, },
reverse: { reverse: {
type: Boolean, type: Boolean,
default: true default: true,
} },
}, },
computed: { computed: {
enterAnimate() { enterAnimate() {
return this.activeClass(false) return this.activeClass(false);
}, },
leaveAnimate() { leaveAnimate() {
return this.activeClass(true) return this.activeClass(true);
} },
}, },
methods: { methods: {
activeClass(isLeave) { activeClass(isLeave) {
let animate = animates.find(item => this.animate == item.name) let animate = animates.find(item => this.animate == item.name);
if (animate == undefined) { if (animate == undefined) {
return '' return '';
} }
let direction = '' let direction = '';
if (this.direction == undefined) { if (this.direction == undefined) {
direction = animate.directions[0] direction = animate.directions[0];
} else { } else {
direction = animate.directions.find(item => item == this.direction) direction = animate.directions.find(item => item == this.direction);
} }
direction = (direction == undefined || direction === 'default') ? '' : direction direction = direction == undefined || direction === 'default' ? '' : direction;
if (direction != '') { if (direction != '') {
direction = isLeave && this.reverse ? this.reversePosition(direction, animate.directions) : direction direction =
direction = direction[0].toUpperCase() + direction.substring(1) isLeave && this.reverse ? this.reversePosition(direction, animate.directions) : direction;
direction = direction[0].toUpperCase() + direction.substring(1);
} }
let t = isLeave ? 'Out' : 'In' let t = isLeave ? 'Out' : 'In';
return animate.name + t + direction return animate.name + t + direction;
}, },
reversePosition(direction, directions) { reversePosition(direction, directions) {
if(direction.length == 0 || direction == 'x' || direction == 'y') { if (direction.length == 0 || direction == 'x' || direction == 'y') {
return direction return direction;
}
let index = directions.indexOf(direction)
index = (index % 2 == 1) ? index - 1 : index + 1
return directions[index]
}
}
} }
let index = directions.indexOf(direction);
index = index % 2 == 1 ? index - 1 : index + 1;
return directions[index];
},
},
};
</script> </script>
<style lang="less"> <style lang="less">
.page-toggle-enter-active{ .page-toggle-enter-active {
position: absolute !important; position: absolute !important;
animation-duration: 0.8s !important; animation-duration: 0.8s !important;
width: calc(100%) !important; width: calc(100%) !important;
} }
.page-toggle-leave-active{ .page-toggle-leave-active {
position: absolute !important; position: absolute !important;
animation-duration: 0.8s !important; animation-duration: 0.8s !important;
width: calc(100%) !important; width: calc(100%) !important;
} }
.page-toggle-enter{
}
.page-toggle-leave-to{
}
</style> </style>
<template>
<a-upload :customRequest="customRequest" :showUploadList="showUploadList" v-bind="$attrs">
<slot>
<a-button> <a-icon type="upload" /> 上传 </a-button>
</slot>
</a-upload>
</template>
<script>
import { uploadFileApi } from '@/api';
export default {
props: {
value: [String, Array],
modelName: {
type: String,
default: 'adminSystem',
},
showUploadList: {
type: [Object, Boolean],
default: false,
},
},
model: {
prop: 'value',
event: 'change',
},
methods: {
async customRequest(info) {
const { file } = info;
try {
const res = await uploadFileApi(this.modelName, file);
this.$message.success('上传成功');
this.$emit('change', res.fileSrc);
} catch (error) {
this.$message.error('上传失败');
}
},
},
};
</script>
<template>
<div :class="$style.card">
<slot />
</div>
</template>
<style module src="@/style/index.css" />
...@@ -6,6 +6,7 @@ import Router from 'vue-router'; ...@@ -6,6 +6,7 @@ import Router from 'vue-router';
import { initRouter } from './router'; import { initRouter } from './router';
import VueI18n from 'vue-i18n'; import VueI18n from 'vue-i18n';
import { accountModule, settingModule } from './pages/frame/store'; import { accountModule, settingModule } from './pages/frame/store';
import globalStore from '@/store';
import App from './App.vue'; import App from './App.vue';
import 'tailwindcss/tailwind.css'; import 'tailwindcss/tailwind.css';
...@@ -27,6 +28,7 @@ Vue.config.productionTip = false; ...@@ -27,6 +28,7 @@ Vue.config.productionTip = false;
Vue.use(Vuex); Vue.use(Vuex);
//加载 框架的module包括 命名空间accountModule,settingModule //加载 框架的module包括 命名空间accountModule,settingModule
const store = new Vuex.Store({ const store = new Vuex.Store({
...globalStore,
modules: { accountModule, settingModule }, modules: { accountModule, settingModule },
}); });
......
<template> <template>
<a-dropdown> <a-dropdown>
<div class="tw-inline-flex tw-cursor-pointer tw-items-center"> <div class="tw-inline-flex tw-cursor-pointer tw-items-center">
<a-avatar class="tw-mr-3" size="small" shape="circle" :src="user.avatar" /> <a-avatar class="tw-mr-3" size="small" shape="circle" :src="userInfo.userAvatar" />
<span>{{ user.name }}</span> <span>{{ userInfo.userName }}</span>
</div> </div>
<a-menu style="width: 150px" slot="overlay"> <a-menu style="width: 150px" slot="overlay">
<a-menu-item @click="toUserCenter"> <a-menu-item @click="toUserCenter">
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapState } from 'vuex';
import { logout } from '@/pages/frame/services/accountService'; import { logout } from '@/pages/frame/services/accountService';
import layoutTopHeaderI18n from './i18n'; import layoutTopHeaderI18n from './i18n';
...@@ -27,7 +27,8 @@ export default { ...@@ -27,7 +27,8 @@ export default {
name: 'LayoutTopHeaderAvatar', name: 'LayoutTopHeaderAvatar',
i18n: layoutTopHeaderI18n, i18n: layoutTopHeaderI18n,
computed: { computed: {
...mapGetters('accountModule', ['user']), ...mapState(['userInfo']),
profile() { profile() {
return this.$t('profile'); return this.$t('profile');
}, },
...@@ -38,6 +39,9 @@ export default { ...@@ -38,6 +39,9 @@ export default {
return this.$t('loginOut'); return this.$t('loginOut');
}, },
}, },
mounted() {
this.$store.dispatch('getUserInfo');
},
methods: { methods: {
logout() { logout() {
logout(); logout();
......
<template> <template>
<div :class="['tabs-head', layout, pageWidth]"> <div :class="['tabs-head', layout, pageWidth]">
<a-tabs type="editable-card" :class="['tabs-container', layout, pageWidth, {'affixed' : affixed, 'fixed-header' : fixedHeader, 'collapsed' : adminLayout.collapsed}]" :active-key="active" :hide-add="true"> <a-tabs
type="editable-card"
:class="[
'tabs-container',
layout,
pageWidth,
{ affixed: affixed, 'fixed-header': fixedHeader, collapsed: adminLayout.collapsed },
]"
:active-key="active"
:hide-add="true"
>
<a-tooltip placement="left" :title="lockTitle" slot="tabBarExtraContent"> <a-tooltip placement="left" :title="lockTitle" slot="tabBarExtraContent">
<a-icon theme="filled" @click="onLockClick" class="header-lock" :type="fixedTabs ? 'lock' : 'unlock'" /> <a-icon
theme="filled"
@click="onLockClick"
class="header-lock"
:type="fixedTabs ? 'lock' : 'unlock'"
/>
</a-tooltip> </a-tooltip>
<a-tab-pane v-for="page in pageList" :key="page.fullPath"> <a-tab-pane v-for="page in pageList" :key="page.fullPath">
<div slot="tab" class="tab" @contextmenu="e => onContextmenu(page.fullPath, e)"> <div slot="tab" class="tab" @contextmenu="e => onContextmenu(page.fullPath, e)">
<a-icon @click="onRefresh(page)" :class="['icon-sync', {'hide': page.fullPath !== active && !page.loading}]" :type="page.loading ? 'loading' : 'sync'" /> <a-icon
<div class="title" @click="onTabClick(page.fullPath)">{{pageName(page)}}</div> @click="onRefresh(page)"
<a-icon v-if="!page.unclose" @click="onClose(page.fullPath)" class="icon-close" type="close" /> :class="['icon-sync', { hide: page.fullPath !== active && !page.loading }]"
:type="page.loading ? 'loading' : 'sync'"
/>
<div class="title" @click="onTabClick(page.fullPath)">{{ pageName(page) }}</div>
<a-icon
v-if="!page.unclose"
@click="onClose(page.fullPath)"
class="icon-close"
type="close"
/>
</div> </div>
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
...@@ -72,7 +96,7 @@ export default { ...@@ -72,7 +96,7 @@ export default {
}, },
pageName(page) { pageName(page) {
const pagePath = page.fullPath.split('?')[0]; const pagePath = page.fullPath.split('?')[0];
const custom = this.customTitles.find((item) => item.path === pagePath); const custom = this.customTitles.find(item => item.path === pagePath);
return (custom && custom.title) || page.title || this.$t(getI18nKey(page.keyPath)); return (custom && custom.title) || page.title || this.$t(getI18nKey(page.keyPath));
}, },
}, },
......
<template> <template>
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction"> <page-toggle-transition
:disabled="animate.disabled"
:animate="animate.name"
:direction="animate.direction"
>
<router-view /> <router-view />
</page-toggle-transition> </page-toggle-transition>
</template> </template>
<script> <script>
import PageToggleTransition from '@/components/transition/PageToggleTransition'; import PageToggleTransition from '@/components/transition/PageToggleTransition.vue';
import { mapState } from 'vuex'; import { mapState } from 'vuex';
export default { export default {
...@@ -16,6 +20,3 @@ export default { ...@@ -16,6 +20,3 @@ export default {
}, },
}; };
</script> </script>
<style scoped>
</style>
<template> <template>
<admin-layout> <admin-layout>
<contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" /> <contextmenu :itemList="menuItemList" :visible.sync="menuVisible" @select="onMenuSelect" />
<layout-tabs-header v-if="multiPage" :active="activePage" :page-list="pageList" @change="changePage" @close="remove" @refresh="refresh" @contextmenu="onContextmenu" /> <layout-tabs-header
<div :class="['tabs-view-content', layout, pageWidth]" :style="`margin-top: ${multiPage ? -24 : 0}px`"> v-if="multiPage"
<page-toggle-transition :disabled="animate.disabled" :animate="animate.name" :direction="animate.direction"> :active="activePage"
:page-list="pageList"
@change="changePage"
@close="remove"
@refresh="refresh"
@contextmenu="onContextmenu"
/>
<div
:class="['tabs-view-content', layout, pageWidth]"
:style="`margin-top: ${multiPage ? -20 : 0}px`"
>
<page-toggle-transition
:disabled="animate.disabled"
:animate="animate.name"
:direction="animate.direction"
>
<a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches"> <a-keep-alive :exclude-keys="excludeKeys" v-if="multiPage && cachePage" v-model="clearCaches">
<router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" /> <router-view v-if="!refreshing" ref="tabContent" :key="$route.fullPath" />
</a-keep-alive> </a-keep-alive>
...@@ -15,7 +30,7 @@ ...@@ -15,7 +30,7 @@
<script> <script>
import AdminLayout from '../../layouts/AdminLayout'; import AdminLayout from '../../layouts/AdminLayout';
import Contextmenu from '@/components/menu/Contextmenu'; import Contextmenu from '@/components/menu/Contextmenu.vue';
import PageToggleTransition from '@/components/transition/PageToggleTransition'; import PageToggleTransition from '@/components/transition/PageToggleTransition';
import { mapState, mapMutations } from 'vuex'; import { mapState, mapMutations } from 'vuex';
import { getI18nKey } from '@/utils/routerUtil'; import { getI18nKey } from '@/utils/routerUtil';
...@@ -56,7 +71,7 @@ export default { ...@@ -56,7 +71,7 @@ export default {
this.loadCacheConfig(this.$router?.options?.routes); this.loadCacheConfig(this.$router?.options?.routes);
this.loadCachedTabs(); this.loadCachedTabs();
const route = this.$route; const route = this.$route;
if (this.pageList.findIndex((item) => item.fullPath === route.fullPath) === -1) { if (this.pageList.findIndex(item => item.fullPath === route.fullPath) === -1) {
this.pageList.push(this.createPage(route)); this.pageList.push(this.createPage(route));
} }
this.activePage = route.fullPath; this.activePage = route.fullPath;
...@@ -75,11 +90,11 @@ export default { ...@@ -75,11 +90,11 @@ export default {
this.correctPageMinHeight(this.tabsOffset); this.correctPageMinHeight(this.tabsOffset);
}, },
watch: { watch: {
'$router.options.routes': function (val) { '$router.options.routes': function(val) {
this.excludeKeys = []; this.excludeKeys = [];
this.loadCacheConfig(val); this.loadCacheConfig(val);
}, },
$route: function (newRoute) { $route: function(newRoute) {
this.activePage = newRoute.fullPath; this.activePage = newRoute.fullPath;
console.log('#################################'); console.log('#################################');
...@@ -87,7 +102,7 @@ export default { ...@@ -87,7 +102,7 @@ export default {
console.log(newRoute); console.log(newRoute);
console.log('#################################'); console.log('#################################');
if (this.pageList.findIndex((item) => item.fullPath === newRoute.fullPath) === -1) { if (this.pageList.findIndex(item => item.fullPath === newRoute.fullPath) === -1) {
if (!this.multiPage) { if (!this.multiPage) {
this.pageList = [this.createPage(newRoute)]; this.pageList = [this.createPage(newRoute)];
} else { } else {
...@@ -100,7 +115,7 @@ export default { ...@@ -100,7 +115,7 @@ export default {
} }
} }
}, },
multiPage: function (newVal) { multiPage: function(newVal) {
if (!newVal) { if (!newVal) {
this.pageList = [this.createPage(this.$route)]; this.pageList = [this.createPage(this.$route)];
this.removeListener(); this.removeListener();
...@@ -122,8 +137,8 @@ export default { ...@@ -122,8 +137,8 @@ export default {
return this.$message.warning(this.$t('tabs.warn')); return this.$message.warning(this.$t('tabs.warn'));
} }
//清除缓存 //清除缓存
let index = this.pageList.findIndex((item) => item.fullPath === key); let index = this.pageList.findIndex(item => item.fullPath === key);
this.clearCaches = this.pageList.splice(index, 1).map((page) => page.cachedKey); this.clearCaches = this.pageList.splice(index, 1).map(page => page.cachedKey);
if (next) { if (next) {
this.$router.push(next); this.$router.push(next);
} else if (key === this.activePage) { } else if (key === this.activePage) {
...@@ -133,7 +148,7 @@ export default { ...@@ -133,7 +148,7 @@ export default {
} }
}, },
refresh(key, page) { refresh(key, page) {
page = page || this.pageList.find((item) => item.fullPath === key); page = page || this.pageList.find(item => item.fullPath === key);
page.loading = true; page.loading = true;
this.clearCache(page); this.clearCache(page);
if (key === this.activePage) { if (key === this.activePage) {
...@@ -170,9 +185,9 @@ export default { ...@@ -170,9 +185,9 @@ export default {
}, },
closeOthers(pageKey) { closeOthers(pageKey) {
// 清除缓存 // 清除缓存
const clearPages = this.pageList.filter((item) => item.fullPath !== pageKey && !item.unclose); const clearPages = this.pageList.filter(item => item.fullPath !== pageKey && !item.unclose);
this.clearCaches = clearPages.map((item) => item.cachedKey); this.clearCaches = clearPages.map(item => item.cachedKey);
this.pageList = this.pageList.filter((item) => !clearPages.includes(item)); this.pageList = this.pageList.filter(item => !clearPages.includes(item));
// 判断跳转 // 判断跳转
if (this.activePage != pageKey) { if (this.activePage != pageKey) {
this.activePage = pageKey; this.activePage = pageKey;
...@@ -180,25 +195,25 @@ export default { ...@@ -180,25 +195,25 @@ export default {
} }
}, },
closeLeft(pageKey) { closeLeft(pageKey) {
const index = this.pageList.findIndex((item) => item.fullPath === pageKey); const index = this.pageList.findIndex(item => item.fullPath === pageKey);
// 清除缓存 // 清除缓存
const clearPages = this.pageList.filter((item, i) => i < index && !item.unclose); const clearPages = this.pageList.filter((item, i) => i < index && !item.unclose);
this.clearCaches = clearPages.map((item) => item.cachedKey); this.clearCaches = clearPages.map(item => item.cachedKey);
this.pageList = this.pageList.filter((item) => !clearPages.includes(item)); this.pageList = this.pageList.filter(item => !clearPages.includes(item));
// 判断跳转 // 判断跳转
if (!this.pageList.find((item) => item.fullPath === this.activePage)) { if (!this.pageList.find(item => item.fullPath === this.activePage)) {
this.activePage = pageKey; this.activePage = pageKey;
this.$router.push(this.activePage); this.$router.push(this.activePage);
} }
}, },
closeRight(pageKey) { closeRight(pageKey) {
// 清除缓存 // 清除缓存
const index = this.pageList.findIndex((item) => item.fullPath === pageKey); const index = this.pageList.findIndex(item => item.fullPath === pageKey);
const clearPages = this.pageList.filter((item, i) => i > index && !item.unclose); const clearPages = this.pageList.filter((item, i) => i > index && !item.unclose);
this.clearCaches = clearPages.map((item) => item.cachedKey); this.clearCaches = clearPages.map(item => item.cachedKey);
this.pageList = this.pageList.filter((item) => !clearPages.includes(item)); this.pageList = this.pageList.filter(item => !clearPages.includes(item));
// 判断跳转 // 判断跳转
if (!this.pageList.find((item) => item.fullPath === this.activePage)) { if (!this.pageList.find(item => item.fullPath === this.activePage)) {
this.activePage = pageKey; this.activePage = pageKey;
this.$router.push(this.activePage); this.$router.push(this.activePage);
} }
...@@ -259,7 +274,7 @@ export default { ...@@ -259,7 +274,7 @@ export default {
* 页面 unload 事件监听器,添加页签到 session 缓存,用于刷新时保留页签 * 页面 unload 事件监听器,添加页签到 session 缓存,用于刷新时保留页签
*/ */
unloadListener() { unloadListener() {
const tabs = this.pageList.map((item) => ({ ...item, _init_: false })); const tabs = this.pageList.map(item => ({ ...item, _init_: false }));
sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs)); sessionStorage.setItem(process.env.VUE_APP_TBAS_KEY, JSON.stringify(tabs));
}, },
createPage(route) { createPage(route) {
...@@ -276,7 +291,7 @@ export default { ...@@ -276,7 +291,7 @@ export default {
* @param route 页面对应的路由 * @param route 页面对应的路由
*/ */
setCachedKey(route) { setCachedKey(route) {
const page = this.pageList.find((item) => item.fullPath === route.fullPath); const page = this.pageList.find(item => item.fullPath === route.fullPath);
page.unclose = route.meta && route.meta.page && route.meta.page.closable === false; page.unclose = route.meta && route.meta.page && route.meta.page.closable === false;
if (!page._init_) { if (!page._init_) {
const vnode = this.$refs.tabContent.$vnode; const vnode = this.$refs.tabContent.$vnode;
...@@ -303,7 +318,7 @@ export default { ...@@ -303,7 +318,7 @@ export default {
} }
}, },
loadCacheConfig(routes, pCache = true) { loadCacheConfig(routes, pCache = true) {
routes.forEach((item) => { routes.forEach(item => {
const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true; const cacheAble = item.meta?.page?.cacheAble ?? pCache ?? true;
if (!cacheAble) { if (!cacheAble) {
this.excludeKeys.push(new RegExp(`${item.fullPath}\\d+$`)); this.excludeKeys.push(new RegExp(`${item.fullPath}\\d+$`));
......
<template>
<h1>TODO</h1>
</template>
<template>
<div class="tw-flex">
<a-form-model layout="vertical" style="flex: 0 0 400px">
<a-form-model-item label="用户账户">
<a-input disabled :value="loginId" />
</a-form-model-item>
<a-form-model-item label="姓名">
<a-input v-model="form.userName" />
</a-form-model-item>
<a-form-model-item label="固定电话">
<a-input v-model="form.fixedPhone" />
</a-form-model-item>
<a-form-model-item label="移动电话">
<a-input v-model="form.mobilePhone" />
</a-form-model-item>
<a-form-model-item label="电子邮箱">
<a-input v-model="form.userEmail" />
</a-form-model-item>
<a-form-model-item>
<a-button type="primary" :loading="loading" @click="update">更新信息</a-button>
</a-form-model-item>
</a-form-model>
<div style="flex: 0 0 300px" class="tw-flex tw-flex-col tw-items-center ">
<div>头像</div>
<img
style="width: 100px;height: 100px"
class="tw-max-w-full tw-max-h-full tw-rounded-full tw-my-4"
:src="`//${form.userAvatar}`"
/>
<my-upload v-model="form.userAvatar" />
</div>
</div>
</template>
<script>
import { updateUserInfoApi } from '@/api';
export default {
data: () => ({
form: {
userName: '',
mobilePhone: '',
fixedPhone: '',
userEmail: '',
userAvatar: '',
},
loading: false,
}),
computed: {
loginId() {
return this.$store.state.userInfo.loginId;
},
},
watch: {
'$store.state.userInfo'(userInfo) {
this.form.userName = userInfo.userName;
this.form.fixedPhone = userInfo.fixedPhone;
this.form.mobilePhone = userInfo.mobilePhone;
this.form.userEmail = userInfo.userEmail;
this.form.userAvatar = userInfo.userAvatar;
},
},
methods: {
async update() {
this.loading = true;
await updateUserInfoApi(this.form);
this.loading = false;
this.$store.commit('setUserInfo', { ...this.$store.state.userInfo, ...this.form });
this.$message.success('更新成功');
},
},
};
</script>
<template>
<h1>消息仲系</h1>
</template>
<template>
<a-form-model layout="vertical" style="width: 500px" :model="form" :rules="rules" ref="form">
<a-form-model-item label="原始密码" prop="oldPassword">
<a-input-password v-model="form.oldPassword" />
</a-form-model-item>
<a-form-model-item label="新密码" prop="newPassword">
<a-input-password v-model="form.newPassword" />
</a-form-model-item>
<a-form-model-item label="确认新密码" prop="confirmPassword">
<a-input-password v-model="form.confirmPassword" />
</a-form-model-item>
<a-form-model-item>
<a-button type="primary" @click="modifyPassword" :loading="loading">修改密码</a-button>
</a-form-model-item>
</a-form-model>
</template>
<script>
import { modifyPasswordApi } from '@/api';
import { EMPTY_FUN } from '@/utils';
import md5 from 'crypto-js/md5';
export default {
data: vm => ({
form: {
newPassword: '',
oldPassword: '',
confirmPassword: '',
},
rules: {
newPassword: [{ required: true }],
oldPassword: [{ required: true }],
confirmPassword: [
{ required: true },
{
validator(rule, value, callback) {
if (value !== vm.form.newPassword) callback('两次密码不一致');
callback();
},
},
],
},
loading: false,
}),
methods: {
modifyPassword() {
this.$refs.form
.validate()
.then(async () => {
try {
this.loading = true;
await modifyPasswordApi({
newPassword: md5(this.form.newPassword).toString(),
oldPassword: md5(this.form.oldPassword).toString(),
});
this.$message.success('修改成功');
} catch (error) {
// todo
this.$message.error('服务器异常');
}
this.loading = false;
})
.catch(EMPTY_FUN);
},
},
};
</script>
<template> <template>
<h1>用户个人中心</h1> <my-card class="tw-flex">
<a-menu style="flex: 0 0 100px" v-model="selectKeys">
<a-menu-item key="UserInfo">个人信息</a-menu-item>
<a-menu-item key="ModifyPassword">修改密码</a-menu-item>
<a-menu-item key="MessageCenter">消息中心</a-menu-item>
<a-menu-item key="ToDo">代办事宜</a-menu-item>
</a-menu>
<div class="tw-flex-1 tw-ml-6">
<component :is="currentCom" />
</div>
</my-card>
</template> </template>
<script>
import UserInfo from './components/info.vue';
import MessageCenter from './components/message.vue';
import ToDo from './components/todo.vue';
import ModifyPassword from './components/modify_password.vue';
const components = {
UserInfo,
ToDo,
MessageCenter,
ModifyPassword,
};
export default {
data() {
return {
selectKeys: ['UserInfo'],
};
},
computed: {
currentCom() {
return components[this.selectKeys[0]];
},
},
};
</script>
import VueI18nPlugin from './vueI18nPlugin'; import VueI18nPlugin from './vueI18nPlugin';
import AuthorityPlugin from './authorityPlugin'; import AuthorityPlugin from './authorityPlugin';
import TabsPagePlugin from './tabsPagePlugin'; import TabsPagePlugin from './tabsPagePlugin';
import { Table } from '@/components'; import { Table, WhiteCard, Upload } from '@/components';
const Plugins = { const Plugins = {
install: function(Vue) { install: function(Vue) {
...@@ -9,6 +9,8 @@ const Plugins = { ...@@ -9,6 +9,8 @@ const Plugins = {
Vue.use(AuthorityPlugin); Vue.use(AuthorityPlugin);
Vue.use(TabsPagePlugin); Vue.use(TabsPagePlugin);
Vue.component('my-table', Table); Vue.component('my-table', Table);
Vue.component('my-card', WhiteCard);
Vue.component('my-upload', Upload);
}, },
}; };
export default Plugins; export default Plugins;
...@@ -32,7 +32,7 @@ const options = { ...@@ -32,7 +32,7 @@ const options = {
children: [ children: [
{ {
path: 'home', path: 'home',
name: 'Home', name: '首页',
meta: { icon: 'home' }, meta: { icon: 'home' },
component: () => import('@/pages/home/index.vue'), component: () => import('@/pages/home/index.vue'),
}, },
......
import { getUserInfoApi } from '@/api';
export default {
state: {
userInfo: {},
},
mutations: {
setUserInfo(state, userInfo) {
state.userInfo = userInfo;
},
},
actions: {
async getUserInfo({ commit }) {
const userInfo = await getUserInfoApi();
commit('setUserInfo', userInfo);
},
},
};
.card {
@apply tw-bg-white tw-rounded-md tw-p-4;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment