浏览代码

feat: 个人中心

lanceJiang 1 年之前
父节点
当前提交
d5d72f4122

+ 138 - 0
src/views/profile/index.vue

@@ -0,0 +1,138 @@
+<template>
+	<el-container class="page-user">
+		<el-aside style="width: 240px">
+			<el-container>
+				<el-header style="height: auto; display: block">
+					<div class="user-info-top">
+						<el-avatar :size="70" src="img/avatar.jpg"></el-avatar>
+						<h2>{{ user.userName }}</h2>
+						<p>
+							<el-tag effect="dark" round size="large" disable-transitions>{{ user.role }}</el-tag>
+						</p>
+					</div>
+				</el-header>
+				<el-main class="nopadding">
+					<el-menu class="menu" :default-active="page">
+						<el-menu-item-group v-for="group in menu" :key="group.groupName" :title="group.groupName">
+							<el-menu-item v-for="item in group.list" :key="item.component" :index="item.component" @click="openPage">
+								<el-icon v-if="item.icon"><component :is="item.icon" /></el-icon>
+								<template #title>
+									<span>{{ item.title }}</span>
+								</template>
+							</el-menu-item>
+						</el-menu-item-group>
+					</el-menu>
+				</el-main>
+			</el-container>
+		</el-aside>
+		<el-main>
+			<Suspense>
+				<template #default>
+					<component :is="page" />
+				</template>
+				<template #fallback>
+					<el-skeleton :rows="3" />
+				</template>
+			</Suspense>
+		</el-main>
+	</el-container>
+</template>
+
+<script lang="ts" name="profileIndex">
+import { defineAsyncComponent } from 'vue'
+// setup
+export default {
+	name: 'ProfileIndex',
+	components: {
+		account: defineAsyncComponent(() => import('./user/account')),
+		setting: defineAsyncComponent(() => import('./user/setting')),
+		pushSettings: defineAsyncComponent(() => import('./user/pushSettings')),
+		password: defineAsyncComponent(() => import('./user/password')),
+		space: defineAsyncComponent(() => import('./user/space')),
+		logs: defineAsyncComponent(() => import('./user/logs')),
+		upToEnterprise: defineAsyncComponent(() => import('./user/upToEnterprise'))
+	},
+	//路由跳转进来 判断from是否有特殊标识做特殊处理
+	beforeRouteEnter(to, from, next) {
+		next(vm => {
+			if (from.is) {
+				//删除特殊标识,防止标签刷新重复执行
+				delete from.is
+				//执行特殊方法
+				vm.$alert('路由跳转过来后含有特殊标识,做特殊处理', '提示', {
+					type: 'success',
+					center: true
+				})
+					.then(() => {})
+					.catch(() => {})
+			}
+		})
+	},
+	data() {
+		return {
+			menu: [
+				{
+					groupName: '基本设置',
+					list: [
+						{
+							icon: 'el-icon-postcard',
+							title: '账号信息',
+							component: 'account'
+						},
+						{
+							icon: 'el-icon-operation',
+							title: '个人设置',
+							component: 'setting'
+						},
+						{
+							icon: 'el-icon-lock',
+							title: '密码',
+							component: 'password'
+						},
+						{
+							icon: 'el-icon-bell',
+							title: '通知设置',
+							component: 'pushSettings'
+						}
+					]
+				},
+				{
+					groupName: '数据管理',
+					list: [
+						{
+							icon: 'el-icon-coin',
+							title: '存储空间信息',
+							component: 'space'
+						},
+						{
+							icon: 'el-icon-clock',
+							title: '操作日志',
+							component: 'logs'
+						}
+					]
+				},
+				{
+					groupName: '账号升级',
+					list: [
+						{
+							icon: 'el-icon-office-building',
+							title: '升级为企业账号',
+							component: 'upToEnterprise'
+						}
+					]
+				}
+			],
+			user: {
+				userName: 'Sakuya',
+				role: '超级管理员'
+			},
+			page: 'account'
+		}
+	},
+	methods: {
+		openPage(item) {
+			this.page = item.index
+		}
+	}
+}
+</script>

+ 46 - 0
src/views/profile/user/account.vue

@@ -0,0 +1,46 @@
+<template>
+	<el-alert title="异步组件动态加载使用了正处于试验阶段的<Suspense>组件, 其API和使用方式可能会改变. <Suspense> is an experimental feature and its API will likely change." type="warning" show-icon style="margin-bottom: 15px;"/>
+
+	<el-card shadow="never" header="个人信息">
+		<el-form ref="form" :model="form" label-width="120px" style="margin-top:20px;">
+			<el-form-item label="账号">
+				<el-input v-model="form.user" disabled></el-input>
+				<div class="el-form-item-msg">账号信息用于登录,系统不允许修改</div>
+			</el-form-item>
+			<el-form-item label="姓名">
+				<el-input v-model="form.name"></el-input>
+			</el-form-item>
+			<el-form-item label="性别">
+				<el-select v-model="form.sex" placeholder="请选择">
+					<el-option label="保密" value="0"></el-option>
+					<el-option label="男" value="1"></el-option>
+					<el-option label="女" value="2"></el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item label="个性签名">
+				<el-input v-model="form.about" type="textarea"></el-input>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary">保存</el-button>
+			</el-form-item>
+		</el-form>
+	</el-card>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				form: {
+					user: "administrator@scuiadmin.com",
+					name: "Sakuya",
+					sex: "0",
+					about: "正所谓富贵险中求"
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 40 - 0
src/views/profile/user/logs.vue

@@ -0,0 +1,40 @@
+<template>
+	<el-card shadow="never" header="近7天操作记录">
+		<scTable ref="table" :data="data" height="auto" paginationLayout="total, prev, pager, next" hideDo>
+			<sc-table-column label="序号" type="index"></sc-table-column>
+			<sc-table-column label="业务名称" prop="title" min-width="240"></sc-table-column>
+			<sc-table-column label="IP" prop="ip" width="150"></sc-table-column>
+			<sc-table-column label="结果" prop="code" width="150">
+				<el-tag type="success">成功</el-tag>
+			</sc-table-column>
+			<sc-table-column label="操作时间" prop="time" width="150"></sc-table-column>
+
+		</scTable>
+	</el-card>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				data: [
+					{
+						title: "修改用户 lolowan",
+						ip: "211.187.11.18",
+						code: "成功",
+						time: "2022-10-10 08:41:17"
+					},
+					{
+						title: "用户登录",
+						ip: "211.187.11.18",
+						code: "成功",
+						time: "2022-10-10 08:21:51"
+					}
+				]
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 80 - 0
src/views/profile/user/password.vue

@@ -0,0 +1,80 @@
+<template>
+	<el-card shadow="never" header="修改密码">
+		<el-alert title="密码更新成功后,您将被重定向到登录页面,您可以使用新密码重新登录。" type="info" show-icon style="margin-bottom: 15px;"/>
+		<el-form ref="form" :model="form" :rules="rules" label-width="120px" style="margin-top:20px;">
+			<el-form-item label="当前密码" prop="userPassword">
+				<el-input v-model="form.userPassword" type="password" show-password placeholder="请输入当前密码"></el-input>
+				<div class="el-form-item-msg">必须提供当前登录用户密码才能进行更改</div>
+			</el-form-item>
+			<el-form-item label="新密码" prop="newPassword">
+				<el-input v-model="form.newPassword" type="password" show-password placeholder="请输入新密码"></el-input>
+				<sc-password-strength v-model="form.newPassword"></sc-password-strength>
+				<div class="el-form-item-msg">请输入包含英文、数字的8位以上密码</div>
+			</el-form-item>
+			<el-form-item label="确认新密码" prop="confirmNewPassword">
+				<el-input v-model="form.confirmNewPassword" type="password" show-password placeholder="请再次输入新密码"></el-input>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" @click="save">保存密码</el-button>
+			</el-form-item>
+		</el-form>
+	</el-card>
+</template>
+
+<script>
+	import scPasswordStrength from '@/components/scPasswordStrength'
+
+	export default {
+		components: {
+			scPasswordStrength
+		},
+		data() {
+			return {
+				form: {
+					userPassword: "",
+					newPassword: "",
+					confirmNewPassword: ""
+				},
+				rules: {
+					userPassword: [
+						{ required: true, message: '请输入当前密码'}
+					],
+					newPassword: [
+						{ required: true, message: '请输入新密码'}
+					],
+					confirmNewPassword: [
+						{ required: true, message: '请再次输入新密码'},
+						{validator: (rule, value, callback) => {
+							if (value !== this.form.newPassword) {
+								callback(new Error('两次输入密码不一致'));
+							}else{
+								callback();
+							}
+						}}
+					]
+				}
+			}
+		},
+		methods: {
+			save(){
+				this.$refs.form.validate(valid => {
+					if (valid) {
+						this.$alert("密码修改成功,是否跳转至登录页使用新密码登录", "修改成功", {
+							type: 'success',
+							center: true
+						}).then(() => {
+							this.$router.replace({
+								path: '/login'
+							})
+						}).catch(() => {})
+					}else{
+						return false
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 30 - 0
src/views/profile/user/pushSettings.vue

@@ -0,0 +1,30 @@
+<template>
+	<el-card shadow="never" header="事务待办">
+		<el-form ref="form" label-width="180px" label-position="left" style="margin-top:20px;">
+			<el-form-item label="有新的待办">
+				<el-checkbox v-model="form.new">短信推送</el-checkbox>
+				<el-checkbox v-model="form.new_wx">微信推送</el-checkbox>
+			</el-form-item>
+			<el-form-item label="待办有效时剩24小时">
+				<el-checkbox v-model="form.timeout">短信推送</el-checkbox>
+				<el-checkbox v-model="form.timeout_wx">微信推送</el-checkbox>
+			</el-form-item>
+		</el-form>
+	</el-card>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				form: {
+					new: true,
+					timeout: true
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 99 - 0
src/views/profile/user/setting.vue

@@ -0,0 +1,99 @@
+<template>
+	<el-card shadow="never" header="语言主题">
+		<el-form ref="form" label-width="120px" style="margin-top: 20px">
+			<el-form-item :label="$t('user.nightmode')">
+				<el-switch v-model="config.dark" inline-prompt active-icon="el-icon-moon" inactive-icon="el-icon-sunny"></el-switch>
+				<div class="el-form-item-msg">{{ $t('user.nightmode_msg') }}</div>
+			</el-form-item>
+			<el-form-item label="主题颜色">
+				<el-color-picker v-model="config.colorPrimary" :predefine="colorList">></el-color-picker>
+			</el-form-item>
+			<el-form-item :label="$t('user.language')">
+				<el-select v-model="config.lang">
+					<el-option label="简体中文" value="zh-cn"></el-option>
+					<el-option label="English" value="en"></el-option>
+				</el-select>
+				<div class="el-form-item-msg">{{ $t('user.language_msg') }}</div>
+			</el-form-item>
+		</el-form>
+	</el-card>
+	<el-card shadow="never" header="个人设置" style="margin-top: 20px">
+		<el-form ref="form" label-width="120px" style="margin-top: 20px">
+			<el-form-item label="自动登出">
+				<el-select v-model="config.autoExit">
+					<el-option label="从不" :value="0"></el-option>
+					<el-option label="1分钟" :value="1"></el-option>
+					<el-option label="5分钟" :value="5"></el-option>
+					<el-option label="10分钟" :value="10"></el-option>
+					<el-option label="15分钟" :value="15"></el-option>
+					<el-option label="20分钟" :value="20"></el-option>
+					<el-option label="25分钟" :value="25"></el-option>
+					<el-option label="30分钟" :value="30"></el-option>
+					<el-option label="35分钟" :value="35"></el-option>
+					<el-option label="40分钟" :value="40"></el-option>
+					<el-option label="45分钟" :value="45"></el-option>
+					<el-option label="50分钟" :value="50"></el-option>
+					<el-option label="55分钟" :value="55"></el-option>
+					<el-option label="60分钟" :value="60"></el-option>
+				</el-select>
+				<div class="el-form-item-msg">自动登出设置将在下次登录时生效</div>
+			</el-form-item>
+		</el-form>
+	</el-card>
+</template>
+
+<script>
+import colorTool from '@/utils/color'
+
+export default {
+	data() {
+		return {
+			colorList: ['#409EFF', '#009688', '#536dfe', '#ff5c93', '#c62f2f', '#fd726d'],
+			config: {
+				lang: this.$TOOL.data.get('APP_LANG') || this.$CONFIG.LANG,
+				dark: this.$TOOL.data.get('APP_DARK') || false,
+				colorPrimary: this.$TOOL.data.get('APP_COLOR') || this.$CONFIG.COLOR || '#409EFF',
+				autoExit: this.$TOOL.data.get('AUTO_EXIT') || 0
+			}
+		}
+	},
+	watch: {
+		'config.dark'(val) {
+			if (val) {
+				document.documentElement.classList.add('dark')
+				this.$TOOL.data.set('APP_DARK', val)
+			} else {
+				document.documentElement.classList.remove('dark')
+				this.$TOOL.data.remove('APP_DARK')
+			}
+		},
+		'config.lang'(val) {
+			this.$i18n.locale = val
+			this.$TOOL.data.set('APP_LANG', val)
+		},
+		'config.colorPrimary'(val) {
+			if (!val) {
+				val = '#409EFF'
+				this.config.colorPrimary = '#409EFF'
+			}
+			document.documentElement.style.setProperty('--el-color-primary', val)
+			for (let i = 1; i <= 9; i++) {
+				document.documentElement.style.setProperty(`--el-color-primary-light-${i}`, colorTool.lighten(val, i / 10))
+			}
+			for (let i = 1; i <= 9; i++) {
+				document.documentElement.style.setProperty(`--el-color-primary-dark-${i}`, colorTool.darken(val, i / 10))
+			}
+			this.$TOOL.data.set('APP_COLOR', val)
+		},
+		'config.autoExit'(val) {
+			if (val == 0) {
+				this.$TOOL.data.remove('AUTO_EXIT')
+			} else {
+				this.$TOOL.data.set('AUTO_EXIT', val)
+			}
+		}
+	}
+}
+</script>
+
+<style></style>

+ 55 - 0
src/views/profile/user/space.vue

@@ -0,0 +1,55 @@
+<template>
+	<el-card shadow="never" header="当前已用量">
+		<el-progress :text-inside="true" :stroke-width="20" :color="color" :percentage="value" :format="format"/>
+		<el-row :gutter="15" style="margin-top: 20px;">
+			<el-col :lg="6">
+				<el-card shadow="never">
+					<sc-statistic title="文档" value="7.41" suffix="GB" groupSeparator></sc-statistic>
+				</el-card>
+			</el-col>
+			<el-col :lg="6">
+				<el-card shadow="never">
+					<sc-statistic title="图片" value="12.90" suffix="GB" groupSeparator></sc-statistic>
+				</el-card>
+			</el-col>
+			<el-col :lg="6">
+				<el-card shadow="never">
+					<sc-statistic title="视音频" value="68.79" suffix="MB" groupSeparator></sc-statistic>
+				</el-card>
+			</el-col>
+			<el-col :lg="6">
+				<el-card shadow="never">
+					<sc-statistic title="其他" value="17.58" suffix="GB" groupSeparator></sc-statistic>
+				</el-card>
+			</el-col>
+		</el-row>
+	</el-card>
+</template>
+
+<script>
+	import scStatistic from '@/components/scStatistic';
+
+	export default {
+		components: {
+			scStatistic
+		},
+		data() {
+			return {
+				value: 39.58,
+				color: [
+					{ color: '#67C23A', percentage: 40 },
+					{ color: '#E6A23C', percentage: 60 },
+					{ color: '#F56C6C', percentage: 80 },
+				]
+			}
+		},
+		methods: {
+			format(percentage){
+				return percentage + "G"
+			}
+		}
+	}
+</script>
+
+<style>
+</style>

+ 18 - 0
src/views/profile/user/upToEnterprise.vue

@@ -0,0 +1,18 @@
+<template>
+	<el-empty image="img/404.png" :image-size="280" description="当前账号未满足开通企业账号权限">
+		<el-button type="primary" size="large" round disabled>立即升级为企业账号</el-button>
+	</el-empty>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		}
+	}
+</script>
+
+<style>
+</style>