5、页面开发
删除App.vue的默认样式,删除id为nav下的about和home
1、前端公告板功能实现
App.vue 加入container
router/index.js,删除about组件
views/home 添加公告板
- views/home
{{billborad.content}}
小问题:
Vue项目 @路径提示Module is not installed
- api.billboard.js
import request from '@/utils/request'
export function getBillboard() {
return request({
url: '/billboard/show',
method: 'get'
})
}
billboard提供数据
前后端联调
前端开始npm run serve,后端也开启
然后出现
这是由于前端是localhost:8080和后端localhost:8081,端口号不一致产生的跨域问题,去后端设置跨域,对应后端【8、跨域问题】
2、每日一句功能实现
接下我们继续完成每日一句的实现
在完成每日一句之前,我们利用bulma帮我们完成框架布局搭建3:1
链接:https://bulma.io/documentation/columns/basics/
代码:
First column
Second column
Third column
Fourth column
- 在views/Home.vue中,将下面部分分成3:1
{{billborad.content}}
- 新建views/card侧边栏相关组件
CardBar.vue
CardBar
- 新建views/post帖子相关组件
TopicList.vue
帖子列表
在Home.vue中引入
{{billborad.content}}
...
//1、侧边栏
import CardBar from "@/views/card/CardBar";
//帖子相关
import TopicList from "@/views/post/TopicList"
export default {
name: 'Home',
//2、
components: {
CardBar,TopicList
},
...
测试
利用elementui对我们的侧边栏进行美化:
https://element-plus.gitee.io/#/zh-CN/component/card
- LoginWelcome.vue
❀ 发帖
body
- Promotion.vue
推广
body
...
- Tip.vue
每日一句
十个指头按不住十个跳骚
---傣族
...
上述三个组件,script重复部分我这边就没列出来了
上述样式可能会存在重复使用的情况,这边就,建立一个公共css
- assets/app.css
/*margin和padding全部清0,初始化*/
* {
margin: 0;
padding: 0;
}
body,
html {
background-color: #f6f6f6;
color: black;
width: 100%;
font-size: 14px;
/*字体间隔*/
letter-spacing: 0.03em;
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC,
Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, WenQuanYi Micro Hei,
sans-serif, Apple Color Emoji, Segoe UI Emoji, Noto Color Emoji,
Segoe UI Symbol, Android Emoji, EmojiSymbols;
}
/*每个el-card添加下外边距*/
.el-card {
margin-bottom: 16px;
}
在main.js中引用
//引入全局样式
import '@/assets/app.css'
连接后台api
1、修改tip.vue
每日一句
{{tip.content}}}
---{{tip.author}}
2、创建api/tip.js,帮助实现request请求
import request from '@/utils/request'
export function getTodayTip() {
return request({
url: '/tip/today',
method: 'get'
})
}
3、定义异步请求
tip.vue
每日一句
{{tip.content}}
---{{tip.author}}
4、测试
3、广告推广实现
1、api/promotion.js,完成http请求
import request from '@/utils/request'
export function getlist() {
return request({
url: '/promotion/list',
method: 'get'
})
}
2、views/card/Promotion.vue
推广
4、404页面
1、定义页面
error/404.vue
UH OH! 页面丢失
您所寻找的页面不存在,{{ times }}秒后,将返回首页!
2、路由
- router/index.js
const routes = [
...
{
path: '/404',
name: '404',
//改成动态引入
component: () => import('@/views/error/404'),
//从meta元数据中读取title
meta:{title: '404-NotFound'}
},
// 如果用户输入的不是上述路由,则重定向
{
path: '*',
redirect: '/404',
//隐藏
hidden: true
}
]
...
5、用户登录、注册
1、注册的api请求
api/auth/auth.js
import request from '@/utils/request'
export function userRegister(userDTO) {
return request({
url: '/ums/user/register',
method: 'post',
data: userDTO
})
}
2、页面
views/auth/Register.vue
新用户入驻
立即注册
重置
3、路由
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
//改成动态引入
component: () => import('@/views/Home')
},
{
path: '/register',
name: 'Register',
//改成动态引入
component: () => import('@/views/auth/Register'),
meta:{title: '注册'}
}
...
6、用户登录
引入vuex ,存放组件的信息,便于各个组件的读取,有点像全局数据,但是router时存放在内存中的,我们为了方便下次登录时候记住用户的一些信息:比如token或者暗黑模式
安装js-cookie
npm install js-cookie
配置jscookie
- utils/token.js
import Cookies from 'js-cookie'
const uToken = 'u_token'
const darkMode = 'dark_mode'
//获取Token
export function getToken() {
return Cookies.get(uToken)
}
//设置Token,1天,与后端同步
export function setToken(token) {
return Cookies.set(uToken,token,{expires:1})
}
//删除Token
export function removeToken() {
return Cookies.remove(uToken)
}
export function removeAll() {
return Cookies.removeAll()
}
//设置暗黑模式
export function setDarkMode(mode) {
return Cookies.set(darkMode,mode,{expires:365})
}
//获取暗黑模式
export function getDarkMode(mode) {
return Cookies.get(darkMode)
}
用户登录
- views/auth/Login.vue
用户登录
提交
重置
分析上述代码,用户发起请求
submitForm(formName) {
//校验信息
this.$refs[formName].validate((valid) => {
if (valid) {
this.loading = true
loading是为了在请求后台的时候,解决进入等待状态 而不是可以随意点
if (valid)这里时根据rules规则,在浏览器端校验,成功后向vue的store发送请求
//向vue的store发送请求
this.$store
//指定modules:user,login方法
.dispatch("user/login", this.ruleForm)
dispatch方法
第一个参数:user
会调用store下的index.js中modules中的元素user
- store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from "@/store/modules/user";
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
//将数据模块化分类
user
}
})
user/login会调用user中的login方法
- store/moudles/user.js
import { login } from '@/api/auth/auth'
import { getToken, setToken } from '@/utils/token'
//定义全局数据
const state = {
token: getToken(), // token
user: '', // 用户对象
}
//state必须通过mutations改变,类似java中的 set
const mutations = {
SET_TOKEN_STATE: (state, token) => {
state.token = token
}
}
//mutations不能接受异步请求,后台发过来的异步请求放在actions中处理
const actions = {
// 用户登录
login({ commit }, userInfo) {
console.log(userInfo)
const { name, pass, rememberMe } = userInfo
return new Promise((resolve, reject) => {
login({ username: name.trim(), password: pass, rememberMe: rememberMe }).then(response => {
const { data } = response
//放在vuex的store下
commit('SET_TOKEN_STATE', data.token)
//放在cookie下
setToken(data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
}
export default {
namespaced: true,
state,
mutations,
actions
}
actions方法第一个login是方法定义,供外部调用.dispatch("user/login", this.ruleForm)
第二个login是
- api/auth/auth.js
import request from '@/utils/request'
//前台用户登录
export function login(userDTO) {
return request({
url: '/ums/user/login',
method: 'post',
data: userDTO
})
}
配置路由
- router/index.js
,
{
path: '/login',
name: 'Login',
//改成动态引入
component: () => import('@/views/auth/Login'),
meta:{title: '登录'}
},
7、 前边侧边栏:马上入驻
-
views/card/LoginWelcome
❀ 发帖
✍表达想法
马上入驻
社区登录
前面用户登录,通过js-cookie将用户信息token存放在cookie中,我们前端通过判断cookie的值是否存在,来变化前端侧边的信息
上述
import { mapGetters } from 'vuex'
export default {
name: 'LoginWelcome',
computed: {
//可以使用store下的token
...mapGetters([
'token'
])
},
获取store下的token代码比较固定,
接下来就是要将配置获取token的方法,这里通过
- store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import user from "@/store/modules/user";
import getters from "@/store/getters";
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
//将数据模块化分类
user
},
getters
})
export default store
加上getters就可以,
getters的定义
-
store/getters.js
const getters = {
//state =>箭头函数
token: state => state.user.token, //token
user: state => state.user.user, //用户对象
}
export default getters
其中state调用modules的user,
页面不带token的情况
页面带token的情况
如果删除掉cookie里面的u_token,再次刷新页面,我们的从getters获取token,getters又获取user.js中的token,该token是调用了js-cookie中的getToken方法,会发现我们删除了cookie中的数据
//定义全局数据
const state = {
token: getToken(), // token
8、前端在axios请求拦截中在请求头加入jwt
1、在用户登录的时候 ,加入代码,让前端发送请求给后台,请求用户信息
- views/auth/Login
methods: {
submitForm(formName) {
//校验信息
this.$refs[formName].validate((valid) => {
if (valid) {
this.loading = true
//向vue的store发送请求
this.$store
//指定modules:user,login方法
.dispatch("user/login", this.ruleForm)
.then(response =>{
console.log(response)
this.$message({
message: response.message,
type: 'success',
duration: 3000
})
//登录成功后,获取用户信息,存在store
this.$store.dispatch("user/getInfo")
同样通过this.$store.dispatch("user/getInfo"),store发送,
定义getInfo方法
- store/modules/user
1、action中加方法
// 获取用户信息
getInfo({ commit }) {
return new Promise((resolve, reject) => {
getUserInfo()
.then(response => {
const { data } = response
console.log(data)
if (!data){
commit('SET_TOKEN_STATE', '')
commit('SET_USER_STATE', '')
removeToken()
resolve()
reject('Verification failed,please Login again')
}
//放在vuex的store下
commit('SET_USER_STATE', data)
resolve(data)
})
//指定发生错误时的回调函数。
.catch(error => {
reject(error)
})
})
}
2、mutations中加函数
SET_USER_STATE: (state, user) => {
state.user = user
}
改变后的user.js
import { login ,getUserInfo} from '@/api/auth/auth'
import { getToken, setToken ,removeToken} from '@/utils/token'
import da from "element-ui/src/locale/lang/da";
//定义全局数据
const state = {
token: getToken(), // token
user: '', // 用户对象
}
//state必须通过mutations改变,类似java中的 set
const mutations = {
SET_TOKEN_STATE: (state, token) => {
state.token = token
},
SET_USER_STATE: (state, user) => {
state.user = user
}
}
//mutations不能接受异步请求,后台发过来的异步请求放在actions中处理
const actions = {
// 用户登录
login({ commit }, userInfo) {
const { name, pass, rememberMe } = userInfo
return new Promise((resolve, reject) => {
login({ username: name.trim(), password: pass, rememberMe: rememberMe })
.then(response => {
const { data } = response
//放在vuex的store下
commit('SET_TOKEN_STATE', data.token)
//放在cookie下
setToken(data.token)
resolve(response)
})
//指定发生错误时的回调函数。
.catch(error => {
reject(error)
})
})
},
// 获取用户信息
getInfo({ commit }) {
return new Promise((resolve, reject) => {
getUserInfo()
.then(response => {
const { data } = response
console.log(data)
if (!data){
commit('SET_TOKEN_STATE', '')
commit('SET_USER_STATE', '')
removeToken()
resolve()
reject('Verification failed,please Login again')
}
//放在vuex的store下
commit('SET_USER_STATE', data)
resolve(data)
})
//指定发生错误时的回调函数。
.catch(error => {
reject(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
此时我们向后台发送请求的时候,没有带Authorization信息,我们希望带上Authorization信息,后台就可以识别我们,并给我们进行授权等后续操作
- utils/request.js 加入如下代码
import { getToken } from '@/utils/token'
// 2.请求拦截器request interceptor
service.interceptors.request.use(
config => {
// 发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加
// 注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
if (store.getters.token) {
// config.params = {'token': token} // 如果要求携带在参数中
// config.headers.token = token; // 如果要求携带在请求头中
// bearer:w3c规范
config.headers['Authorization'] = 'Bearer ' + getToken()
}
return config
},
error => {
// do something with request error
// console.log(error) // for debug
return Promise.reject(error)
}
)
测试
我们希望前端登录成功之后,后台可以返回给我们用户信息
- views/auth/Login.vue
向后端请求用户信息
submitForm(formName) {
//校验信息
this.$refs[formName].validate((valid) => {
if (valid) {
this.loading = true
//向vue的store发送请求
this.$store
//指定modules:user,login方法
.dispatch("user/login", this.ruleForm)
.then(response =>{
console.log(response)
this.$message({
message: response.message,
type: 'success',
duration: 3000
})
//登录成功后,获取用户信息
this.$store.dispatch("user/getInfo")
...
用的是store,发送请求,因为这块用户信息可能会被其他模块用到
getInfo的定义
- store/modules/user.js
import { login ,getUserInfo} from '@/api/auth/auth'
import { getToken, setToken ,removeToken} from '@/utils/token'
import da from "element-ui/src/locale/lang/da";
//定义全局数据
const state = {
token: getToken(), // token
user: '', // 用户对象
}
//state必须通过mutations改变,类似java中的 set
const mutations = {
SET_TOKEN_STATE: (state, token) => {
state.token = token
},
SET_USER_STATE: (state, user) => {
state.user = user
}
}
//mutations不能接受异步请求,后台发过来的异步请求放在actions中处理
const actions = {
...
// 获取用户信息
getInfo({ commit }) {
return new Promise((resolve, reject) => {
getUserInfo()
.then(response => {
const { data } = response
console.log(data)
if (!data){
commit('SET_TOKEN_STATE', '')
commit('SET_USER_STATE', '')
removeToken()
resolve()
reject('Verification failed,please Login again')
}
//放在vuex的store下
commit('SET_USER_STATE', data)
resolve(data)
})
//指定发生错误时的回调函数。
.catch(error => {
reject(error)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
login方法
- api/auth/auth.js
import request from '@/utils/request'
...
//登录后获取前台用户信息
export function getUserInfo() {
return request({
url: '/ums/user/info',
method: 'get',
})
}
上述引入了request,我们需要在request里面加入封装后的用户信息
- utils
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/token'
// 1.创建axios实例,vue请求后台
const service = axios.create({
// 公共接口--这里注意后面会讲,url = base url + request url
baseURL: process.env.VUE_APP_SERVER_URL,
// baseURL: 'https://api.example.com',
// 超时时间 单位是ms,这里设置了5s的超时时间
timeout: 5 * 1000
})
// 2.请求拦截器request interceptor
service.interceptors.request.use(
config => {
// 发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加
// 注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
if (store.getters.token) {
// config.params = {'token': token} // 如果要求携带在参数中
// config.headers.token = token; // 如果要求携带在请求头中
// bearer:w3c规范
config.headers['Authorization'] = 'Bearer ' + getToken()
}
return config
},
error => {
// do something with request error
// console.log(error) // for debug
return Promise.reject(error)
}
)
// 设置cross跨域 并设置访问权限 允许跨域携带cookie信息,使用JWT可关闭
service.defaults.withCredentials = false
// 3.请求拦截器response interceptor
service.interceptors.response.use(
// 接收到响应数据并成功后的一些共有的处理,关闭loading等
response => {
const res = response.data
// 如果自定义代码不是200,则将其判断为错误。
if (res.code !== 200) {
// 50008: 非法Token; 50012: 异地登录; 50014: Token失效;
if (res.code === 401 || res.code === 50012 || res.code === 50014) {
// 重新登录
MessageBox.confirm('会话失效,您可以留在当前页面,或重新登录', '权限不足', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
center: true
}).then(() => {
window.location.href = '#/login'
})
} else { // 其他异常直接提示
Message({
showClose: true,
message: '⚠' + res.message || 'Error',
type: 'error',
duration: 3 * 1000
})
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
/** *** 接收到异常响应的处理开始 *****/
Message({
showClose: true,
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
config.headers['Authorization'] = 'Bearer ' + getToken()
我们将用户信息放在请求头的Authorization属性中,并加上W3C规范,注意加了空格,后台取到请求头之后也需要反过来解析
9、实现暗黑模式、页头
使用现成的库
安装darkereader
npm stall darkereader
在components下新建Loyout文件夹代表我们的布局
主页
主页
检索
{{ darkMode ? "夜" : "日" }}
个人中心
⚙ 设置中心
退出登录
我们通过监听darkMode属性的改变值,取做到切换暗黑模式,暗黑模式是借用
darkreader工具实现的,
v-if="token == null || token === ''"
这里会判断token是否存在
token是从store中取得的,store中的token是从cookie中取得的
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['token', 'user'])
}
我们需要在App.vue中引入头部
//3
我们登录页面
刷新页面
发现用户信息不见了,原因在于我们每一次刷新,
Header.vue都会取调用
...mapGetters(['token', 'user'])
通过getters.js
const getters = {
//state =>箭头函数
token: state => {
return state.user.token//token
},
user: state => state.user.user, //用户对象
}
export default getters
获得用户信息,但是在user.js中
//定义全局数据
const state = {
token: getToken(), // token
user: '', // 用户对象
}
token每次都可以重新请求获得,但是user被重置为空了,问题出在这,我们获取的时机不对
我们是在登录Login.vue通过
//登录成功后,获取用户信息
this.$store.dispatch("user/getInfo")
获取的,但是这个只执行了一次,我们应该在每次刷新的时候取执行请求用户信息
新建src.permission.js,解决用户名消失的问题
import router from './router'
import store from './store'
import getPageTitle from '@/utils/get-page-title'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'
import {getToken} from "@/utils/token"; // progress bar style
NProgress.configure({showSpinner: false}) // NProgress Configuration
router.beforeEach(async (to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken();
if (hasToken) {
if (to.path === '/login') {
// 登录,跳转首页
next({path: '/'})
NProgress.done()
} else {
// 获取用户信息
await store.dispatch('user/getInfo')
next()
}
} else {
next()
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
新建src/utils/get-page-title.js
const title = '小而美的智慧社区系统'
export default function getPageTitle(pageTitle) {
if (pageTitle) {
return `${pageTitle} - ${title}`
}
return `${title}`
}
安装nprogress,这是告诉用户刷新页面进度提示的小工具
最后在main.js中引入permission,我们再刷新,发现解决了
10、退出登录
components/layout/Header.vue添加logout方法
async logout() {
this.$store.dispatch("user/logout").then(() => {
this.$message.info("退出登录成功")
setTimeout(() => {
this.$router.push({path: this.redirect || '/'})
}, 500)
})
},
store/modules/user.js
// 用户退出
logout({ commit }) {
return new Promise((resolve, reject) => {
logout(state.token)
.then(response => {
console.log(response)
//放在vuex的store下
commit('SET_TOKEN_STATE', "")
commit('SET_USER_STATE', "")
removeToken()
resolve()
})
//指定发生错误时的回调函数。
.catch(error => {
reject(error)
})
})
},
api/auth/auth.js
//前提用户注销
export function logout() {
return request({
url: '/ums/user/logout',
method: 'get',
})
}
测试
出现这个问题 是因为我们当前就在首页,但是logout还是请求跳转到/,为了解决这个问题
我们在router/index.js中加入
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
就解决了
11、页脚
- components/layout/Footer.vue
- components/BackTop/BackTop.vue
- 在app.vue中引入
12、帖子列表
1、安装dayjs,帮助我们完成时间的格式化
npm install dayjs
2、添加列表的请求工具
- src/api/post.js
import request from '@/utils/request'
// 列表
export function getList(pageNo, size, tab) {
return request(({
url: '/post/list',
method: 'get',
params: { pageNo: pageNo, size: size, tab: tab }
}))
}
//分页参数,pageNo 页号 size 每页多少条 tab 主题:最新或者最热
3、mian.js加入dayjs
- src/main.js
//引入全局样式
import '@/assets/app.css'
import '@/permission'
import relativeTime from 'dayjs/plugin/relativeTime';
//国际化
import 'dayjs/locale/zh-cn'
const dayjs = require('dayjs')
//相对时间插件
dayjs.extend(relativeTime)
dayjs.locale('zh-cn') // use locale globally
dayjs().locale('zh-cn').format() // use locale in a specific instance
Vue.prototype.dayjs = dayjs;//可以全局使用dayjs
4、修改index.js文件
- src/views/post/TopicList.vue
{{ item.title }}
{{item.content}}
{{ item.title }}
{{item.content}}
4、添加底部分页条
- src/components/Pagination/index.vue
- src/utils/scroll-to.js
Math.easeInOutQuad = function(t, b, c, d) {
t /= d / 2
if (t < 1) {
return c / 2 * t * t + b
}
t--
return -c / 2 * (t * (t - 2) - 1) + b
}
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
var requestAnimFrame = (function() {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
})()
/**
* Because it's so fucking difficult to detect the scrolling element, just move them all
* @param {number} amount
*/
function move(amount) {
document.documentElement.scrollTop = amount
document.body.parentNode.scrollTop = amount
document.body.scrollTop = amount
}
function position() {
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
}
/**
* @param {number} to
* @param {number} duration
* @param {Function} callback
*/
export function scrollTo(to, duration, callback) {
const start = position()
const change = to - start
const increment = 20
let currentTime = 0
duration = (typeof (duration) === 'undefined') ? 500 : duration
var animateScroll = function() {
// increment the time
currentTime += increment
// find the value with the quadratic in-out easing function
var val = Math.easeInOutQuad(currentTime, start, change, duration)
// move the document.body
move(val)
// do the animation unless its over
if (currentTime < duration) {
requestAnimFrame(animateScroll)
} else {
if (callback && typeof (callback) === 'function') {
// the animation is done so lets callback
callback()
}
}
}
animateScroll()
}
- src/views/post/Index.vue
修改变成从后台取出来刷新current、total、size的
13、发表帖子
1、安装vditor
2、添加axios
- src/api/post.js
// 发布
export function post(topic) {
return request({
url: '/post/create',
method: 'post',
data: topic
})
}
3、添加路由
- src/router/index.js
// 发布
{
name: 'post-create',
path: '/post/create',
component: () => import('@/views/post/Create'),
meta: { title: '信息发布', requireAuth: true }
},
4、在登录情况下,views/card/LoginWelcome.vue
❀ 发帖
✍表达想法
会跳转到我们的create中
- src/views/post/Create.vue
主题 / 发布主题
立即创建
重置
- src/api/post.js
// 发布
export function post(topic) {
return request({
url: '/post/create',
method: 'post',
data: topic
})
}
发送请求会被request.js中的service.interceptors.request.use( 拦截,加上头部的用户信息
14、帖子详情
- community_front/src/api/post.js
})
}
// 浏览
export function getTopic(id) {
return request({
url: `/post`,
method: 'get',
params: {
id: id
}
})
}
- community_front/src/router/index.js
},
// 详情
{
name: "post-detail",
path: "/post/:id",
component: () => import("@/views/post/Detail"),
},
- community_front/src/views/post/Detail.vue
{{ topic.title }}
{{ dayjs(topic.createTime).format('YYYY/MM/DD HH:mm:ss') }}
发布者:{{ topicUser.alias }}
查看:{{ topic.view }}
作者信息
15、帖子详情---右边侧边栏作者详情
- community_front/src/api/follow.js
import request from '@/utils/request'
// 关注
export function follow(id) {
return request(({
url: `/relationship/subscribe/${id}`,
method: 'get'
}))
}
// 关注
export function unFollow(id) {
return request(({
url: '/relationship/unsubscribe/${id}',
method: 'get'
}))
}
// 验证是否关注
export function hasFollow(topicUserId) {
return request(({
url: '/relationship/validate/${topicUserId}',
method: 'get'
}))
}
- community_front/src/views/post/Author.vue
16、留言
安装date-fns,有一个时间解析工具
- community_front/src/api/comment.js
添加前端aioxs请求
- community_front/src/components/Comment/Comments.vue
添加评论组件
- community_front/src/components/Comment/CommentsItem.vue
添加评论组件的项
- community_front/src/main.js
全局定义date-fns
- community_front/src/views/post/Detail.vue
引入评论组件
17、留言---添加留言
必须是在登录的情况下才显示,不等了只显示留言信息
- community_front/src/api/comment.js
- community_front/src/components/Comment/Comments.vue
- community_front/src/components/Comment/CommentsForm.vue
18、帖子删除与更新
19、根据标签信息查出相关帖子
20、用户中心
21、个人设置
22、留言等 需要认证后才能访问
// 编辑
{
name: 'topic-edit',
path: '/topic/edit/:id',
component: () => import('@/views/post/Edit'),
meta: {
title: '编辑', requireAuth: true
}
},
在需要的路由上添加meta requireAuth: true
然后再permission中添加
} else if (!to.meta.requireAuth){
next()
}else {
//未登录
next('/login')
}