vue---museui入门开发移动端学习系统
入门学习使用museui开发移动端学习系统。界面包括登录页、注册页、课程知识地图页(首页)、课程知识图谱页、学习资源页、交流讨论专区、个人中心。界面展示如下:首先,项目目录见下图:【main.js】: 项目的核心文件,实例化vue对象,引入项目中使用到的插件/工具和路由项目中使用了museui、...
入门学习使用museui开发移动端学习系统。界面包括登录页、注册页、课程知识地图页(首页)、课程知识图谱页、学习资源页、交流讨论专区、个人中心。
界面展示如下:
首先,项目目录见下图:
【main.js】: 项目的核心文件,实例化vue对象,引入项目中使用到的插件/工具和路由
项目中使用了museui、axios(处理http请求)、iconfont、vue-ztree(生成文档树)https://www.npmjs.com/package/vue-ztree
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './components/router'
import MuseUI from 'muse-ui';
import 'muse-ui/dist/muse-ui.css';
import axios from 'axios'
import vueztree from 'vue-ztree-2.0/dist/vue-ztree-2.0.umd.min.js'
import 'vue-ztree-2.0/dist/vue-ztree-2.0.css'
import './assets/iconfont/iconfont.css'
Vue.prototype.$axios = axios;
Vue.use(MuseUI);
Vue.use(axios)
Vue.use(vueztree)
Vue.config.productionTip = false
/* eslint-disable no-new */
// 实例化vue对象
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
})
【App.vue】:项目入口文件
<template>
<div id="app">
<router-view/>
<!-- 增大底部的可视区域 -->
<div style="width:100%;height:50px;"></div>
<!-- bottom-nav 底部导航栏 -->
<bottom-nav v-show="showNav"></bottom-nav>
</div>
</template>
<script>
import BottomNav from "./components/BottomNav";
export default {
name: "App",
data() {
return {
showNav: false
};
},
components: {
"bottom-nav": BottomNav
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.header_title {
position: fixed;
width: 100%;
left: 0;
top: 0;
z-index: 1000;
}
</style>
其中,【BottomNav.vue】为底部导航栏,由于底部导航页在登录成功后的每一个页面均显示,故设置其为公共组件,在【App.vue】中引入。【showNav】为底部导航栏显示与否的标志。
【BottomNav.vue】:底部导航栏
底部导航栏分为四栏,分别对于于不同的路径。注意,底部导航栏的位置需要固定在页面底端。
#nav {
position: fixed;
width: 100%;
left: 0;
bottom: 0;
z-index: 1000;
}
<template>
<!-- 底部导航栏 -->
<div id="nav">
<mu-bottom-nav style="background-color: #2196f3;color: hsla(0,0%,100%,.7);">
<router-link to="/student">
<mu-bottom-nav-item title="首页" icon="home"></mu-bottom-nav-item>
</router-link>
<router-link to="/studyResource">
<mu-bottom-nav-item title="学习资源" icon="local_library"></mu-bottom-nav-item>
</router-link>
<router-link to="/discuss">
<mu-bottom-nav-item title="讨论交流" icon="record_voice_over"></mu-bottom-nav-item>
</router-link>
<router-link to="/PersonalCenter">
<mu-bottom-nav-item title="个人中心" icon="account_circle"></mu-bottom-nav-item>
</router-link>
</mu-bottom-nav>
</div>
</template>
<script>
export default {
data() {
return {
// shift: "index"
};
}
};
</script>
<style lang="less">
.mu-bottom-item-active {
color: white;
}
a {
color: rgba(218, 214, 214, 0.7);
}
// 固定底部导航栏位置
#nav {
position: fixed;
width: 100%;
left: 0;
bottom: 0;
z-index: 1000;
}
</style>
【Login.vue】登录及注册界面
注册页面包含用户名、邮箱及密码输入框,登录页面包含用户名和密码输入框,可选择管理员或者非管理员角色进行登录,本项目只做了非管理员登录成功界面。
<template>
<mu-container>
<mu-tabs :value.sync="active" center color="teal">
<mu-tab>
<mu-icon value="person"></mu-icon>登录
</mu-tab>
<mu-tab>
<mu-icon value="person_add"></mu-icon>注册
</mu-tab>
</mu-tabs>
<div class="demo-text" v-if="active === 0">
<!-- 1.登录窗口 -->
<mu-form ref="form" :model="user" class="mu-demo-form">
<mu-form-item label="用户名" prop="username" :rules="usernameRules">
<mu-text-field v-model="user.username" prop="username"></mu-text-field>
</mu-form-item>
<mu-form-item label="密码" prop="password" :rules="passwordRules">
<mu-text-field type="password" v-model="user.password" prop="password"></mu-text-field>
</mu-form-item>
<!-- 是否管理员 -->
<mu-form-item prop="admin" label>
<mu-switch v-model="user.admin"></mu-switch>
<span>管理员</span>
</mu-form-item>
<mu-form-item>
<mu-button color="primary" @click="submitLogin()">提交</mu-button>
<mu-button @click="clear">重置</mu-button>
</mu-form-item>
</mu-form>
</div>
<div class="demo-text" v-if="active === 1">
<!-- 2.注册窗口 -->
<mu-form ref="form" :model="user" class="mu-demo-form">
<mu-form-item label="用户名" prop="username" :rules="usernameRules">
<mu-text-field v-model="user.username" prop="username"></mu-text-field>
</mu-form-item>
<mu-form-item label="设置密码" prop="password" :rules="passwordRules">
<mu-text-field type="password" v-model="user.password" prop="password"></mu-text-field>
</mu-form-item>
<mu-form-item label="邮箱" prop="email" :rules="emailRules">
<mu-text-field v-model="user.email" prop="email"></mu-text-field>
</mu-form-item>
<mu-form-item>
<mu-button color="primary" @click="submitRegister">提交</mu-button>
<mu-button @click="clear">重置</mu-button>
</mu-form-item>
</mu-form>
</div>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
active: 0,
usernameRules: [
{ validate: val => !!val, message: "必须填写用户名" },
{ validate: val => val.length >= 2, message: "用户名长度大于2" }
],
passwordRules: [
{ validate: val => !!val, message: "必须填写密码" },
{
validate: val => val.length >= 3 && val.length <= 10,
message: "密码长度大于3小于10"
}
],
emailRules: [
{ validate: val => !!val, message: "必须填写邮箱" },
{
validate: val =>
/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(
val
),
message: "输入有效的邮箱"
}
],
user: {
admin: false,
username: "",
password: "",
email: ""
}
};
},
methods: {
// 提交登录
submitLogin() {
this.$refs.form.validate().then(result => {
if (result) {
axios.post("/api/loginUser/", this.user).then(res => {
// console.log("输出response.data", res.data);
if (res.data.status === 200) {
if (this.user.admin) {
this.$router.push({ path: "/admin" });
} else {
// 登录成功
this.$parent.showNav = true;
this.$router.push({ path: "/student" });
}
} else {
alert(res.data.msg);
}
});
}
});
},
// 提交注册账号
submitRegister() {
this.$refs.form.validate().then(result => {
if (result) {
axios.post("/api/registerUser", this.user).then(res => {
console.log("输出response.data", res.data);
// 后台校验用户名是否存在
this.active = 0;
});
}
});
},
clear() {
this.$refs.form.clear();
this.user = {
username: "",
password: "",
email: ""
};
}
}
};
</script>
<style lang="less">
.mu-demo-form {
width: 100%;
max-width: 460px;
}
.mu-form-item-label {
font-size: 16px;
line-height: 28px;
text-align: left;
font-weight: 600;
}
.demo-text {
padding: 16px;
background: #fff;
p {
margin: 8px 0;
}
}
</style>
【Student.vue】课程知识地图页(首页)
主要展示各个课程的学习进度,通过progress进度条方式展示。
<template>
<mu-container>
<mu-appbar
class="header_title"
style="width: 100%; margin-bottom:15px;"
title="课程知识地图"
color="#d81b60"
></mu-appbar>
<div style="width: 100%; margin-bottom:35px;">
<mu-list class="list" v-for="item in progressData" :key="item.id">
<mu-list-item>
<mu-list-item-title>
<mu-linear-progress mode="determinate" :value="item.currentV" :size="16" color="blue"></mu-linear-progress>
</mu-list-item-title>
</mu-list-item>
<p class="list_desc">{{item.name}}:当前进度:{{item.currentV}}%</p>
<span class="list_icon">
<mu-icon size="30" value="arrow_downward"></mu-icon>
{{item.purpose}}
</span>
</mu-list>
<!-- 复用技术 -->
<mu-list class="list" @click="goMap">
<mu-list-item>
<mu-list-item-title>
<mu-linear-progress mode="determinate" :value="tech.currentV" :size="16" color="green"></mu-linear-progress>
</mu-list-item-title>
</mu-list-item>
<p class="list_desc">{{tech.name}}:当前进度:{{tech.currentV}}%</p>
</mu-list>
</div>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
progressData: [
{
id: 0,
currentV: 10.5,
name: "物理层",
purpose: "传输什么"
},
{
id: 1,
currentV: 20.1,
name: "透明比特流传输",
purpose: "用什么传"
},
{
id: 2,
currentV: 5.9,
name: "传输介质",
purpose: "怎么传输"
},
{
id: 3,
currentV: 30.3,
name: "传输方案",
purpose: "影响因素"
},
{
id: 4,
currentV: 2.5,
name: "物理带宽",
purpose: "共享信道"
}
],
tech: {
currentV: 43,
name: "复用技术",
purpose: "共享信道"
}
};
},
methods: {
goMap() {
this.$router.push({ path: "/map" });
}
},
created() {
this.$parent.showNav = true;
}
};
</script>
<style lang="less">
.list {
margin-top: -1px;
border: 1px solid #ccc;
padding-top: 5px;
}
.list_desc {
font-size: 14px;
font-weight: 600;
color: rgb(86, 168, 235);
}
</style>
【Map.vue】课程知识地图学习树页
点击课程知识地图页复用技术可跳转至课程知识图谱页,通过vue-zue生成知识图谱
<template>
<mu-container>
<mu-appbar
class="header_title"
style="width: 100%; margin-bottom:15px;"
title="课程知识图谱"
color="#d81b60"
></mu-appbar>
<vue-ztree
:list.sync="ztreeDataSource"
:func="nodeClick"
:expand="expandClick"
:contextmenu="contextmenuClick"
:is-open="true"
></vue-ztree>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
msg: "Map界面",
ztreeDataSource: [
{
id: 1,
name: "复用技术",
children: [
{
id: 12,
name: "原理",
url: "0"
},
{
id: 13,
name: "分类",
children: [
{
id: 131,
name: "时分多路复用",
children: [
{ id: 1311, name: "原理", url: "1" },
{
id: 1312,
name: "分类",
children: [{ id: 13121, name: "STDM", url: "2" }]
},
{ id: 1213, name: "应用", url: "3" }
]
},
{
id: 132,
name: "频分多路复用",
children: [
{ id: 1321, name: "原理", url: "4" },
{
id: 1322,
name: "分类",
children: [
{ id: 13221, name: "WDM", url: "5" },
{ id: 13222, name: "OFDM", url: "6" }
]
},
{ id: 1323, name: "应用", url: "7" }
]
},
{
id: 133,
name: "码分多路复用",
children: [
{ id: 1331, name: "原理", url: "8" },
{ id: 1332, name: "应用", url: "9" }
]
}
]
}
]
}
]
};
},
methods: {
// 点击节点
nodeClick: function(m) {
console.log(" 点击节点:", JSON.parse(JSON.stringify(m)));
},
// 右击事件
contextmenuClick: function(m) {
console.log("右击事件:", m);
console.log("触发了自定义的contextmenuClick事件");
},
// 点击展开收起
expandClick: function(m) {
console.log(JSON.parse(JSON.stringify(m)));
// 点击异步加载
if (m.isExpand) {
// 动态加载子节点, 模拟ajax请求数据
// 请注意 id 不能重复哦。
if (m.hasOwnProperty("children")) {
m.loadNode = 1; // 正在加载节点
setTimeout(() => {
m.loadNode = 2; // 节点加载完毕
m.isFolder = !m.isFolder;
m.children.push({
id: +new Date(),
name: "动态加载节点1",
path: "",
clickNode: false,
isFolder: false,
isExpand: false,
loadNode: 0,
children: [
{
id: +new Date() + 1,
name: "动态加载末节点",
path: "",
clickNode: false,
isExpand: false,
isFolder: false,
loadNode: 0
}
]
});
}, 1000);
}
}
}
},
created() {
this.$parent.showNav = true;
}
};
</script>
<style lang="less">
.container {
overflow: hidden;
}
</style>
【StudyResource】:学习资源页
学习资源页设置了自定义过滤器【snippet】,作用是使得显示字数为100以内。使用mu-expansion-panel面板展示学习资源,图片通过mu-card-media展示。
<template>
<!-- 学习资源界面 -->
<mu-container>
<mu-appbar
class="header_title"
style="width: 100%; margin-bottom:15px;"
title="学习资源"
color="#d81b60"
></mu-appbar>
<mu-expansion-panel v-for="(item,index) in resources" :key="index">
<div class="title" slot="header">{{item.title}}</div>
<mu-card-media v-if="item.imgName">
<img :src="item.imgName">
</mu-card-media>
<div style="width:100%">
<router-link :to="{path:'/moreResource',query:{resourceIndex:index}}">
<p class="desc">{{item.content | snippet}}</p>
</router-link>
</div>
</mu-expansion-panel>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
msg: "学习资源界面",
resources: []
};
},
// 渲染前获取数据源
created() {
this.$parent.showNav = true;
// axios提交数据
axios
.post("/api/getResources")
.then(response => {
this.resources = response.data.data;
console.log("学习资源输出:", this.resources);
})
// 提交出错
.catch(response => {
console.log(response);
});
},
//自定义过滤器
filters: {
snippet: function(value) {
return value.slice(0, 100) + "...";
}
}
};
</script>
<style lang="less">
.title {
font-size: 16px;
font-weight: 500;
// color: rgb(33, 150, 243);
}
.desc {
color: rgb(58, 135, 187);
text-align: left;
}
</style>
【MoreResource.vue】学习资源详情页
<template>
<mu-container>
<mu-appbar class="header_title" style="width: 100%; margin-bottom:15px;" color="#d81b60">
学习资源详情
<mu-button flat slot="right" @click="goBack">
<mu-icon value="reply" color="white"></mu-icon>
</mu-button>
</mu-appbar>
<div style="margin:14px;">
<h2 class="study-title">{{item.title}}</h2>
<mu-divider></mu-divider>
<mu-card-media v-if="item.imgName">
<img :src="item.imgName">
</mu-card-media>
<div style="width:100%">
<p class="desc">{{item.content}}</p>
</div>
<!-- <div v-if="item.videoName">
<video id="myVideo" class="video-js" width="100%" height="100%">
<source src="//vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
</div>-->
</div>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
refleftUrl: "",
startTime: 0,
item: {},
rid: this.$route.query.resourceIndex
};
},
methods: {
goBack() {
this.$router.go(-1);
}
},
created() {
this.$parent.showNav = true;
this.startTime = Date.parse(new Date());
let resindex = this.$route.query.resourceIndex;
axios
.post("/api/getResource", { index: resindex })
.then(response => {
if (response.data.status == 200) {
console.log("获取学习资源详情", response);
this.item = response.data.data;
this.refleftUrl = {
path: "/reflectSelf",
query: { resourceIndex: resindex }
};
} else {
console.log(response.data.msg);
}
})
.catch(response => {
console.log(response);
});
}
// // 开始计时
// mounted: function(params) {},
// // 统计浏览时长
// beforeRouteLeave(to, from, next) {
// let currentTimeStamp = Date.parse(new Date());
// let interval = (currentTimeStamp - this.startTime) / 1000;
// this.axios
// .post("/api/submitOnlineTime", { onlineTime: interval })
// .then(response => {})
// .catch(response => {
// console.info(response);
// });
// next(true);
// }
};
</script>
<style lang="less">
.study-title {
font-size: 17px;
font-weight: 600;
margin-top: 68px;
}
</style>
【Discuss.vue】交流讨论专区
交流讨论页功能有:发布帖子,显示帖子,给帖子点赞、踩、评论。
<template>
<mu-container>
<mu-appbar
class="header_title"
style="width: 100%; margin-bottom:15px;"
title="交流讨论专区"
color="#d81b60"
>
<!-- 我要发帖按钮 点击打开我要发帖对话框 -->
<mu-button flat slot="right" @click="openDiscussDialog">
<mu-icon value="border_color" size="15" color="white"></mu-icon>
</mu-button>
</mu-appbar>
<!-- 发帖显示区域 -->
<mu-paper :z-depth="1" v-for="(item,index) in posts" :key="index">
<mu-appbar style="height:35px; font-size:16px;" color="lightBlue400">{{item.theme}}</mu-appbar>
<div
style="margin:10px;border:1px solid #d1cdcd;padding:0px 10px;border-radius:4px;"
v-for="(postItem, i) in item.data"
:key="i"
>
<h3>{{postItem.title}}</h3>
<p style="color:gray; font-size:8px;">作者: {{postItem.author}} {{postItem.createdTime}}</p>
<mu-card-media v-if="postItem.image" title sub-title>
<img :src="postItem.image">
</mu-card-media>
<p>{{postItem.content}}</p>
<!-- 点赞、踩、评论功能 -->
<div class="dicuss-icon" :itemIndex="postItem.id" :typeIndex="index" :listIndex="i">
<span @click="commentUp">
<i class="iconfont" style="color:#49bb10"></i>
</span>
<span style="color:black;">{{postItem.upCount}}</span>
<span href="javascript:;" @click="commentDown">
<i class="iconfont" style="color:#e26ba7"></i>
</span>
<span style="color:black;">{{postItem.downCount}}</span>
<span href="javascript:;" @click="commentAdd">
<i class="iconfont" style="color:#299fce"></i>
</span>
<span style="color:black;">{{postItem.commentCount}}</span>
</div>
<!-- 评论列表 -->
<mu-list style="border-top:1px solid #d1cdcd;padding-top:10px;">
<div v-for="(itemComment, ic) in postItem.comments" :key="ic">
<img class="commemtImg" src="../assets/images/girl.png">
<div class="commentContent">
<div
class="commentContent-desc"
>{{itemComment.createdTime}} {{itemComment.commenter.name}} 发表了评论</div>
<div>
<span>{{itemComment.content}}</span>
</div>
</div>
</div>
</mu-list>
</div>
</mu-paper>
<!-- 发帖对话框 -->
<mu-dialog title="我要发帖" width="360" :open.sync="createDicussVisible">
<mu-col gutter>
<mu-col span="12" lg="4" sm="6">
<mu-form
ref="form"
:model="form"
class="mu-demo-form"
:label-position="labelPosition"
label-width="100"
>
<mu-form-item prop="select" label="请选择发帖主题" :rules="selectRules">
<mu-select v-model="form.select">
<mu-option
v-for="(option,index) in options"
:key="index"
:label="option"
:value="index"
></mu-option>
</mu-select>
</mu-form-item>
<mu-form-item prop="input" label="输入帖子标题" :rules="inputRules">
<mu-text-field v-model="form.input"></mu-text-field>
</mu-form-item>
<mu-form-item prop="textarea" label="输入帖子内容" :rules="textareaRules">
<mu-text-field multi-line :rows="3" :rows-max="6" v-model="form.textarea"></mu-text-field>
</mu-form-item>
<!-- 是否添加图片 -->
<mu-checkbox label="添加图片资源" v-model="addImgFile"></mu-checkbox>
<!-- 显示添加的图片 -->
<div v-if="addImgFile">
<label for="file" style="width:100%">请在系统中选择一张图片</label>
<input
type="file"
accept="image/*"
name="file"
id="file"
style="display:none"
@change="preview($event)"
>
</div>
<br>
</mu-form>
</mu-col>
</mu-col>
<mu-button slot="actions" flat color="primary" @click="submitDicussForm">确定</mu-button>
<mu-button slot="actions" flat color="red" @click="cancleDicuss">取消</mu-button>
</mu-dialog>
<!-- 发表评论对话框 -->
<mu-dialog title="发表评论" width="360" :open.sync="commentVisible">
<mu-col gutter>
<mu-col span="12" lg="4" sm="6">
<mu-form
ref="form"
:model="form"
class="mu-demo-form"
:label-position="labelPosition"
label-width="100"
>
<mu-form-item prop="commentText" :rules="commentTextRules">
<mu-text-field multi-line :rows="1" :rows-max="6" v-model="form.commentText"></mu-text-field>
</mu-form-item>
</mu-form>
</mu-col>
</mu-col>
<mu-button slot="actions" flat color="primary" @click="submitComment">确定</mu-button>
<mu-button slot="actions" flat color="red" @click="cancleComment">取消</mu-button>
</mu-dialog>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
options: [
"透明比特流传输",
"传输介质",
"传输方案",
"物理带宽",
"物理层",
"复用技术"
],
labelPosition: "top",
form: {
input: "",
select: "",
textarea: "",
commentText: ""
},
createDicussVisible: false,
commentVisible: false,
selectRules: [{ validate: val => !!val, message: "必须选择发帖主题" }],
inputRules: [
{ validate: val => !!val, message: "必须填写帖子标题" },
{ validate: val => val.length >= 2, message: "帖子标题长度大于2" }
],
textareaRules: [
{ validate: val => !!val, message: "必须填写帖子内容" },
{ validate: val => val.length >= 2, message: "帖子内容长度大于2" }
],
commentTextRules: [
{ validate: val => !!val, message: "必须填写评论内容" },
{ validate: val => val.length >= 2, message: "评论内容长度大于2" }
],
posts: [],
currentCindex: 0,
currentType: 0,
itemIndex: 0,
typeIndex: 0,
listIndex: 0,
addImgFile: "",
imgUrl: "",
postImg: ""
};
},
methods: {
// 点赞功能
commentUp(event) {
let objNode = event.target.parentNode.parentNode;
let typeIndex = parseInt(objNode.getAttribute("typeindex"));
let listIndex = parseInt(objNode.getAttribute("listindex"));
this.posts[typeIndex].data[listIndex].upCount += 1;
let itemIndex = parseInt(objNode.getAttribute("itemIndex"));
// 上传数据到服务器
axios
.post("/api/updateUpCount", {
itemIndex: itemIndex
})
.then(response => {
console.log("点赞成功:", response);
})
.catch(response => {
console.log(response);
});
},
// 踩功能
commentDown() {
let objNode = event.target.parentNode.parentNode;
let typeIndex = parseInt(objNode.getAttribute("typeindex"));
console.log("typeIndex", this.typeIndex);
let listIndex = parseInt(objNode.getAttribute("listindex"));
this.posts[typeIndex].data[listIndex].downCount += 1;
let itemIndex = parseInt(objNode.getAttribute("itemIndex"));
// 上传数据到服务器
axios
.post("/api/updateDownCount", {
itemIndex: itemIndex
})
.then(response => {})
.catch(response => {
console.log(response);
});
},
// 增加评论
commentAdd() {
let objNode = event.target.parentNode.parentNode;
let typeIndex = parseInt(objNode.getAttribute("typeindex"));
let listIndex = parseInt(objNode.getAttribute("listindex"));
this.itemIndex = parseInt(objNode.getAttribute("itemIndex"));
this.currentCindex = listIndex;
this.currentType = typeIndex;
this.commentVisible = true;
},
// 点击打开“我要发帖”对话框
openDiscussDialog() {
this.createDicussVisible = true;
},
// 点击关闭“我要发帖”对话框,取消发帖
cancleDicuss() {
this.createDicussVisible = false;
},
// 提交“我要发帖”内容
submitDicussForm() {
this.$refs.form.validate().then(result => {
if (result) {
let formData = new FormData();
formData.append("theme", this.form.select);
formData.append("title", this.form.input);
formData.append("content", this.form.textarea);
formData.append("postImg", this.postImg);
axios
.post("/api/submitPost", formData)
.then(response => {
this.createDicussVisible = false;
console.log(response);
alert(response.data.msg);
})
.catch(response => {
console.log(response);
});
}
});
},
// “发表评论”对话框 点击提交评论
submitComment() {
this.$refs.form.validate().then(result => {
if (result) {
let commentText = this.form.commentText;
this.posts[this.currentType].data[
this.currentCindex
].commentCount += 1;
this.posts[this.currentType].data[
this.currentCindex
].comments.unshift({
commenter: {
userImg: require("../assets/images/girl.png"),
name: sessionStorage.getItem("userName")
},
content: commentText
// createdTime: "2019-01-12 09:30:12 "
});
// 关闭提交框
this.commentVisible = false;
// 上传数据到服务器
axios
.post("/api/submitCommentData", {
content: commentText,
itemIndex: this.itemIndex
})
.then(response => {
alert(response.data.msg);
})
.catch(response => {
console.log(response);
});
}
});
},
// 点击关闭“发表评论”对话框,取消评论
cancleComment() {
this.commentVisible = false;
this.form.commentText = "";
},
getObjectURL(file) {
let url = null;
if (window.createObjectURL != undefined) {
// basic
url = window.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file);
} else if (window.URL != undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file);
}
return url;
},
preview(event) {
let files = document.getElementById("file").files[0];
let imgDataUrl = this.getObjectURL(files);
this.imgUrl = imgDataUrl;
this.postImg = files;
}
},
// 页面渲染前获取交流讨论历史数据
created() {
this.$parent.showNav = true;
axios
.post("/api/getPostData")
.then(response => {
this.posts = response.data.data;
console.log("输出this.posts", this.posts);
})
.catch(response => {
console.log(response);
});
}
};
</script>
<style lang="less">
.dicuss-icon {
text-align: right;
}
.commemtImg {
position: absolute;
left: 0;
width: 50px;
}
.commentContent {
text-align: left;
margin-left: 73px;
border: 1px solid gray;
padding: 10px;
border-radius: 6px;
background-color: #faf7f9;
margin-bottom: 20px;
}
.commentContent-desc {
border-bottom: 1px solid #e2cdcd;
font-size: 10px;
margin-bottom: 10px;
}
//小箭头
.commentContent::before {
content: "";
position: absolute;
// top: 26px;
left: 68px;
width: 9px;
height: 9px;
border: 1px solid gray;
transform: rotate(45deg);
border-right: transparent;
border-top: transparent;
background: #faf7f9;
}
</style>
【PersonalCenter.vue】: 个人中心
个人中心页展示个人信息及测试、反思、发帖和评论情况。
<template>
<mu-container>
<mu-appbar
class="header_title"
style="width: 100%; margin-bottom:15px;"
title="个人中心"
color="#d81b60"
></mu-appbar>
<!-- 顶部用户信息 -->
<mu-row gutter>
<mu-col span="4">
<div class="grid-cell">
<img style="width:60px;height:60px;" src="../assets/images/girl.png">
</div>
</mu-col>
<mu-col span="8">
<div class="grid-cell">
<mu-list>
<mu-list-item button :ripple="false">
<mu-list-item-action>
<mu-icon value="perm_identity"></mu-icon>
</mu-list-item-action>
<mu-list-item-title>{{user.name}}</mu-list-item-title>
</mu-list-item>
<mu-list-item button :ripple="false">
<mu-list-item-action>
<mu-icon value="mail_outline"></mu-icon>
</mu-list-item-action>
<mu-list-item-title>{{user.email}}</mu-list-item-title>
</mu-list-item>
</mu-list>
</div>
</mu-col>
</mu-row>
<!-- 最近活动 -->
<h3 style="text-align:left; padding-left:10px;">最近的活动</h3>
<mu-divider></mu-divider>
<mu-tabs :value.sync="active1" inverse color="secondary" text-color="rgba(0, 0, 0, .54)" center>
<mu-tab>测试</mu-tab>
<mu-tab>反思</mu-tab>
<mu-tab>发帖</mu-tab>
<mu-tab>评论</mu-tab>
</mu-tabs>
<mu-divider></mu-divider>
<!-- 测试 -->
<div class="demo-text" v-if="active1 === 0">
<div v-if="testList.length > 0" style="text-align:left">
<div
v-for="(titem,index) in testList"
:key="index"
style="border:1px solid rgb(235, 228, 228);padding:5px 10px;border-radius:4px;margin:10px 0px;"
>
<h3
style="border:0px solid gray; background:#e9f6f9;width:100%;height:30px;line-height:30px;border-radius:2px;"
>测试{{index+1}}:得分:{{titem.score}} 总分:{{titem.fullScore}}</h3>
<h4 class="customTitle">开始时间:{{titem.startTime}}</h4>
<h4 class="customTitle">交卷时间:{{titem.endTime}}</h4>
<h4 class="customTitle">正确率:{{titem.score * 100 / titem.fullScore}}%</h4>
<mu-row>
<!-- 查看错题、重新测试、新建测试页面暂时没写 -->
<mu-col span="4">
<router-link class="test-router-link" to="#">查看错题</router-link>
</mu-col>
<mu-col span="4">
<router-link class="test-router-link" to="#">重新测试</router-link>
</mu-col>
<mu-col span="4">
<router-link class="test-router-link" to="#">新建测试</router-link>
</mu-col>
</mu-row>
</div>
</div>
<router-link class="test-router-link" to="#" v-else>还没有任何测试哦,赶紧测试一下吧!</router-link>
</div>
<!-- 反思 -->
<div class="demo-text" v-if="active1 === 1">
<div v-if="reflectList.length > 0" style="text-align:left">
<div
v-for="(item,index) in reflectList"
:key="index"
style="border:1px solid rgb(235, 228, 228);padding:5px 10px;border-radius:4px;margin:10px 0px;"
>
<h3
style=" text-align:center; border:0px solid gray; background:#e9f6f9;width:100%;height:30px;line-height:30px;border-radius:2px;"
>{{item.title}}</h3>
<h4 class="customTitle">{{item.content}}</h4>
<h4 class="customTitle" style="color:red; font-size:10px;">等待管理员评定反思分数!</h4>
</div>
</div>
<router-link class="test-router-link" to="/discuss" v-else>还没有任何反思,赶紧去学习反思吧!</router-link>
</div>
<!-- 发帖 -->
<div class="demo-text" v-if="active1 === 2">
<div v-if="postList.length > 0">
<div
v-for="(item,index) in postList"
:key="index"
style="border:1px solid rgb(235, 228, 228);padding:5px 10px;border-radius:4px;margin:10px 0px;"
>
<h3>{{item.title}}</h3>
<p class="customTitle">{{item.content}}</p>
<router-link to="/discuss" style="margin-right:-245px; color:#42797d">继续发帖</router-link>
</div>
</div>
<router-link class="test-router-link" to="#" v-else>还没有发表过自己的想法哦,赶紧去发帖吧!</router-link>
</div>
<!-- 评论 -->
<div class="demo-text" v-if="active1 === 3">
<div v-if="commentList.length > 0" style="text-align:center">
<div
v-for="(item,index) in commentList"
:key="index"
style="border:1px solid rgb(235, 228, 228);padding:5px 10px;border-radius:4px;margin:10px 0px;"
>
<h3>{{item.content}}</h3>
<p>{{item.createdTime}}</p>
<router-link to="/discuss" style="margin-right:-245px; color:#42797d">继续评论</router-link>
</div>
</div>
<router-link class="test-router-link" to="#" v-else>还没有评论过别人,赶紧去和别人互动吧!</router-link>
</div>
</mu-container>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
active1: 0,
user: {
name: "leimiao",
email: "12233@ds.com"
},
levelSize: 2,
testList: [
// {
// score: 90,
// fullScore: 120,
// startTime: "2019-02-05 12:05:11",
// endTime: "2019-02-05 12:15:11",
// errorRate: "5%"
// }
],
// 反思
reflectList: [],
// 发帖
postList: [],
// 评论
commentList: []
};
},
created() {
this.$parent.showNav = true;
// 请求用户信息
axios
.post("/api/getUserInfo")
.then(response => {
this.user = response.data.userInfo;
})
.catch(response => {
console.log(response);
});
// 请求考试数据
axios
.post("/api/getMyTestData")
.then(response => {
this.testList = response.data.testList;
})
.catch(response => {
console.log(response);
});
// 请求反思数据
axios
.post("/api/getMyReflectData")
.then(response => {
this.reflectList = response.data.reflectList;
console.log("请求反思数据", this.reflectList);
})
.catch(response => {
console.log(response);
});
// 请求发帖数据
axios
.post("/api/getMyPostData")
.then(response => {
this.postList = response.data.postList;
})
.catch(response => {
console.log(response);
});
// 请求评论数据
axios
.post("/api/getMyCommentData")
.then(response => {
this.commentList = response.data.commentList;
})
.catch(response => {
console.log(response);
});
}
};
</script>
<style lang="less">
.grid-cell {
border-radius: 4px;
height: 86px;
background: transparent;
padding-top: 20px;
}
.mu-list {
padding: 0px;
}
.mu-item {
height: 25px;
}
.demo-text {
padding: 16px;
background: #fff;
p {
margin: 8px 0;
}
}
.test-router-link {
color: #42797d;
}
</style>
【router】-->【index.js】路由配置
import Vue from 'vue'
import Router from 'vue-router'
import Login from '@/components/Login'
import Admin from '@/components/Admin'
import Student from '@/components/Student'
import Map from '@/components/Map'
import Discuss from '@/components/Discuss'
import StudyResource from '@/components/StudyResource'
import PersonalCenter from '@/components/PersonalCenter'
import MoreResource from '@/components/MoreResource'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/admin',
name: 'Admin',
component: Admin
},
{
path: '/student',
name: 'Student',
component: Student
},
{
path: '/map',
name: 'Map',
component: Map
},
{
path: '/discuss',
name: 'Discuss',
component: Discuss
},
{
path: '/studyResource',
name: 'StudyResource',
component: StudyResource
},
{
path: '/personalCenter',
name: 'PersonalCenter',
component: PersonalCenter
},
{
path: '/moreResource',
name: 'MoreResource',
component: MoreResource
}
],
mode: "history"
})
更多推荐
所有评论(0)