持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
前言
废话不多少,开始发车了,那么今天主要带来的前端作品,主要是这个:
还有这个
一个是我们WhiteHole项目里面的博文Pull审核的页面,还有一个是咱们社区的页面。 那么这里咱们主要是用到了两个东西,一个是我们diff的插件,其实这里我本来是想要使用vscode的那个网页vue插件的,但是我的初衷是做一个博文网站,没必要搞那么重,因为用户只需要查看差异,然后同意即可,因为同意合并之后,我们还是会跳转到markdown的编辑页面,所以的话,我们不需要那个。
之后是我们的特效插件。
那么我们一一到来。
vue-code-diff
我们需要做出这样的效果:
所以我们需要引用到这个。
cnpm install vue-code-diff
我们直接安装即可。
之后的话,我们只需要这样:
然后在对应的未知使用就好了:
<code-diff :old-string="oldStr"
:new-string="newStr" :context="10"
outputFormat="side-by-side"
diffStyle="word"
/>
那么对应的数据也简单:
这个我们待会再说。
vue-particles
之后是我们的这个组件,这个是我们的背景的例子特效。
cnpm install vue-particles --save-dev
之后再main.js引入
import Vue from 'vue'
import VueParticles from 'vue-particles'
Vue.use(VueParticles)
使用的话也简单
<template>
<div id="app">
<vue-particles
class="login-background"
color="#97D0F2"
:particleOpacity="0.7"
:particlesNumber="50"
shapeType="circle"
:particleSize="4"
linesColor="#97D0F2"
:linesWidth="1"
:lineLinked="true"
:lineOpacity="0.4"
:linesDistance="150"
:moveSpeed="3"
:hoverEffect="true"
hoverMode="grab"
:clickEffect="true"
clickMode="push">
</vue-particles>
</div>
</template>
这个具体的咱们后面再说。
那么到此的话,我们需要使用到的两个组件就说完了,那么接下来我们来看看我们具体的页面是怎么使用到这个的。
文本差异对比页面
背景
首先是背景,我们导入刚刚的特效组件。
<vue-particles
class="login-background"
color="#97D0F2"
:particleOpacity="0.7"
:particlesNumber="50"
shapeType="circle"
:particleSize="4"
linesColor="#97D0F2"
:linesWidth="1"
:lineLinked="true"
:lineOpacity="0.8"
:linesDistance="150"
:moveSpeed="3"
:hoverEffect="true"
hoverMode="grab"
:clickEffect="true"
clickMode="push">
</vue-particles>
之后写一下样式,让这个作为背景。
.login-background {
width: 96%;
margin: 0 auto;
height: 100%; /**宽高100%是为了图片铺满屏幕 */
z-index: 0;
position: absolute;
}
差异组件
之后是我们的插件组件的使用,这个咱们引用就好了。
<div>
<code-diff :old-string="oldStr"
:new-string="newStr" :context="10"
outputFormat="side-by-side"
diffStyle="word"
/>
</div>
右侧边栏
之后是咱们的右侧的边栏,这个主要是看看有那些用户的提交,当点击的时候,在显示出来。
这个实现也简单。主要是说用这个属性。
<el-aside width="25%" style="height: 600px" class="show">
<p>Pull</p>
<el-timeline v-if="Message.length>0" v-infinite-scroll="load"
v-bind:infinite-scroll-distance="long"
infinite-scroll-disabled="busy"
class="infinite-list">
<el-timeline-item
v-for="(message, index) in Message"
:key="index"
:color=message.color
:timestamp="message.data"
>
<el-button @click="loadContent(message.contentID)" type="primary" plain>
<el-avatar :src="message.userpic"></el-avatar>
contentID:<span style="font-size: smaller;color: #00c4ff">{{message.contentID}}</span>
</el-button>
</el-timeline-item>
</el-timeline>
</el-aside>
完整代码
拿接下来就是咱们这个页面的完整代码了。
<template>
<div style="width: 95%;margin: 0 auto">
<vue-particles
class="login-background"
color="#97D0F2"
:particleOpacity="0.7"
:particlesNumber="50"
shapeType="circle"
:particleSize="4"
linesColor="#97D0F2"
:linesWidth="1"
:lineLinked="true"
:lineOpacity="0.8"
:linesDistance="150"
:moveSpeed="3"
:hoverEffect="true"
hoverMode="grab"
:clickEffect="true"
clickMode="push">
</vue-particles>
<el-container >
<el-main class="show" style="height: 600px;z-index: 1">
<div>
<span>当前内容</span>
<span style="margin-left: 43%">提交内容</span>
</div>
<div>
<code-diff :old-string="oldStr"
:new-string="newStr" :context="10"
outputFormat="side-by-side"
diffStyle="word"
/>
</div>
<div>
<el-tooltip content="确定合并后将跳转至文章编辑页面,可进一步修改" placement="bottom" effect="light">
<el-button @click="submit"
plain type="primary" round
style="margin-left: 90%"
>
确定合并
</el-button>
</el-tooltip>
</div>
</el-main>
<el-aside width="25%" style="height: 600px" class="show">
<p>Pull</p>
<el-timeline v-if="Message.length>0" v-infinite-scroll="load"
v-bind:infinite-scroll-distance="long"
infinite-scroll-disabled="busy"
class="infinite-list">
<el-timeline-item
v-for="(message, index) in Message"
:key="index"
:color=message.color
:timestamp="message.data"
>
<el-button @click="loadContent(message.contentID)" type="primary" plain>
<el-avatar :src="message.userpic"></el-avatar>
contentID:<span style="font-size: smaller;color: #00c4ff">{{message.contentID}}</span>
</el-button>
</el-timeline-item>
</el-timeline>
</el-aside>
</el-container>
</div>
</template>
<script>
import CodeDiff from 'vue-code-diff'
export default {
name: "blogshowMerge",
components: {CodeDiff},
data() {
return {
oldStr: '这里是测试数据\n用于测试',
newStr: '',
long: 2,
Message: [
{
//颜色由后端传递
contentID: 'asdasds',
userpic: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
data: '2022-10-2',
color:'#28c90f'
}, {
contentID: 'sadaasd',
userpic: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
data: '2022-05-02',
color:'#e5d681'
},
],
}
},
methods:{
submit(){
alert("即将进入博文编辑页面微调")
this.$router.push({path:'/writeblog',query: {id:'1'}})
},
loadContent(val){
// 先去服务端获取到内容,然后给到这里
this.newStr="模拟是服务端获取到的Pull内容"+val;
},
load () {
//这部分让你的axios去动态加载
// let temp=[
// {
// content: '加载了',
// data: '2022-03-27',
// },
// {
// content: '加载了',
// data: '2022-03-27',
// }
//
// ]
// for (let i = 0; i < temp.length; i++) {
// this.Message.push(temp[i])
// }
},
},
}
</script>
<style scoped>
.login-background {
width: 96%;
margin: 0 auto;
height: 100%; /**宽高100%是为了图片铺满屏幕 */
z-index: 0;
position: absolute;
}
.show{
width: 90%;
border: 0px solid #81badc;
transition: all 0.9s;
border-radius: 10px;
}
.show:hover{
box-shadow: 0px 15px 30px rgb(12, 132, 224);
margin-top: 10px;
}
</style>
社区页面
这个社区页面的话,其实也是类似的。而且我们先前写过不少。
这里我们一共有两个自定义的组件,用来显示列表的,一个问答,一个是博文,问答和博文的具体的页面我们在昨天已经做好了。
博客列表
这个没啥好说的,就是以前的代码改过来的,其实我可以直接做进一步的封装,但是我这里还是要拆开来,原因很简单,现在只是懒,页面可能直接copy改一下,但是后面等有时间了,保不齐是需要重新设计的,总不能都长一样吧,所以这个时候先单独分开了的好处就出来了。
<template>
<div style="background-color: rgba(239,250,246,0.53)">
<br>
<br>
<div style="width: 100%;margin-left: 1%" class="main">
<el-card shadow="hover" v-for="(message,index) in Messages" :key="index">
<div style="height:100px">
<div style="width:14%;height: 100%;border-radius: 100px;display:inline-block;">
<img
style="width:100%;height: 100%;border-radius: 100px"
src="/static/temporary/headpic.jpg"
class="image"
>
</div>
<div style="display:inline-block;margin-left: 5%;width: 60%">
<p class="message" style="font-weight:bold">
<router-link class="alink" to="/blogshow">
{{message.name}}
</router-link>
</p>
<p style="font-weight: lighter" class="message"
>
{{message.info}}
</p>
<p class="message">
阅读:
<i class="el-icon-view"></i>
{{message.number}}
收藏:
<i class="el-icon-star-off"></i>
{{message.favorite}}
<i>fork:{{message.fork}}</i>
</p>
</div>
<div style="width:18%;height: 100%;
display:inline-block;
"
>
<span style="text-align: center">{{message.data}}</span>
</div>
</div>
<br>
</el-card>
</div>
<br>
<div class="footer" style="margin: 0 auto;width: 100%;">
<div class="block" >
<el-pagination
background
layout="total, prev, pager, next, jumper"
:total=total>
</el-pagination>
</div>
</div>
</div>
</template>
<script>
export default {
name: "unityBlogList",
data(){
return{
total: 999,
Messages:[
{"info":"Spring 是一个轻量级的开发框架",
"name":"Spring 5 核心原理解析",
"number": 999,"data":"2022-3-27",favorite: 999,
"fork": 2
},
{"info":"Spring 是一个轻量级的开发框架",
"name":"Spring 5 核心原理解析",
"number": 999,"data":"2022-3-27",favorite: 999,
"fork": 2
},
{"info":"Spring 是一个轻量级的开发框架",
"name":"Spring 5 核心原理解析",
"number": 999,"data":"2022-3-27",favorite: 999,
"fork": 2
},
{"info":"Spring 是一个轻量级的开发框架",
"name":"Spring 5 核心原理解析",
"number": 999,"data":"2022-3-27",favorite: 999,
"fork": 22
},
]
}
},
}
</script>
<style scoped>
.message{
width: 25em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.alink{
text-decoration: none;
color: #333333;
}
</style>
问答列表
这个问答页面也是一样的。
<template>
<div style="width: 100%">
<br>
<br>
<div style="width: 100%;margin-left: 1%" class="main">
<el-card shadow="hover" v-for="(message,index) in Messages" :key="index">
<div style="height:100px">
<div style="display:inline-block;margin-left: 5%;width: 60%">
<p class="message" style="font-weight:bold">
<router-link class="alink" to="/quiz/quizshow">
{{message.name}}
</router-link>
</p>
<p style="font-weight: lighter" class="message"
>
{{message.info}}
</p>
<p class="message">
阅读:
<i class="el-icon-view"></i>
{{message.number}}
收藏:
<i class="el-icon-star-off"></i>
{{message.favorite}}
</p>
</div>
<div style="width:18%;height: 100%;
display:inline-block;
"
>
<p style="text-align: center">{{message.data}}</p>
<br><br>
</div>
</div>
<br>
</el-card>
</div>
<br>
<div class="footer" style="margin: 0 auto;width: 100%;">
<div class="block" >
<el-pagination
background
layout="total, prev, pager, next, jumper"
:total=total>
</el-pagination>
</div>
</div>
</div>
</template>
<script>
export default {
name: "unityQuizList",
data(){
return{
total: 9,
Messages:[
{"info":"为什么中国会出现女拳",
"name":"女拳主义如何打击",
"number": 999,"data":"2022-3-27",favorite: 999
},
{"info":"Java与Python如何取舍",
"name":"会Java还要不要Python",
"number": 999,"data":"2022-3-27",favorite: 999
},
{"info":"Spring 是一个轻量级的开发框架,我要对它复现",
"name":"造轮子的重要性",
"number": 999,"data":"2022-3-27",favorite: 999
},
{"info":"小白一枚,不知道如何准备",
"name":"数学建模如何准备",
"number": 999,"data":"2022-3-27",favorite: 999
},
]
}
},
}
</script>
<style scoped>
.message{
width: 25em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.alink{
text-decoration: none;
color: #333333;
}
</style>
社区页面
之后就是咱们的社区页面了。这个页面我还搞了不少悬浮效果,我是挺喜欢的。
<template>
<div>
<vue-particles
class="login-background"
color="#97D0F2"
:particleOpacity="0.7"
:particlesNumber="50"
shapeType="circle"
:particleSize="4"
linesColor="#97D0F2"
:linesWidth="1"
:lineLinked="true"
:lineOpacity="0.8"
:linesDistance="150"
:moveSpeed="3"
:hoverEffect="true"
hoverMode="grab"
:clickEffect="true"
clickMode="push">
</vue-particles>
<div style="width: 80%;margin: 0 auto">
<el-row :gutter="20">
<br>
<el-col :span="16">
<div class="grid-content bg-purple show">
<div style="margin-left: 2%">
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/unityshow'}">文章</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/unityshow/unityQuizList'}">问答</el-breadcrumb-item>
<el-breadcrumb-item ></el-breadcrumb-item>
</el-breadcrumb>
</div>
<br><br>
<div style="width: 98%;margin: 0 auto">
<router-view></router-view>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple aside" style="background-color: whitesmoke">
<el-card class="show">
<div>
<div style="width:30%;height: 100px;border-radius: 100px;display:inline-block;">
<img
style="width:100%;height: 100%;border-radius: 100px"
src="/static/temporary/headpic.jpg"
class="image"
>
</div>
<div>
<p style="font-size: larger;font-family: 楷体">简介</p>
<span style="font-size: smaller">
社区页面展示社区页面展示社区页面展示社区页面展示社区页面展示社区页面展示
社区页面展示社区页面展示社区页面展示社区页面展示社区页面展示社区页面展示
</span>
</div>
<div>
<p>文章数:12</p>
<p>问答数:24</p>
</div>
</div>
</el-card>
<el-card class="show">
<router-link class="alink" to="/writeblog">
<el-button type="primary" icon="el-icon-edit">
发文
</el-button>
</router-link>
<el-button @click="submit" type="primary" icon="el-icon-edit" >
提问
</el-button>
</el-card>
<br>
<el-card class="show">
<div class="show" style="height: 300px">
<p>
<el-button icon="el-icon-s-custom" type="primary" round size="big">社区成员</el-button>
</p>
<div>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-avatar src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-avatar>
<el-avatar src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"></el-avatar>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-avatar src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-avatar>
<el-avatar src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"></el-avatar>
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>
<el-avatar src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-avatar>
<el-avatar src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"></el-avatar>
</div>
</div>
</el-card>
</div>
</el-col>
</el-row>
<el-dialog
style="width:80%;margin: 0 auto"
title="创建提问"
:visible.sync="dialogFormVisible"
>
<el-form :model="ruleForm"
:rules="rules"
ref="ruleForm"
label-width="100px"
class="demo-ruleForm">
<el-form-item label="问题" prop="que" >
<el-input v-model="ruleForm.que"></el-input>
</el-form-item>
<el-form-item label="问题描述" prop="desc">
<el-input type="textarea" :rows="10" v-model="ruleForm.desc"></el-input>
</el-form-item>
</el-form>
<div style="margin: 0 auto" slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
export default {
name: "unityshow",
data(){
return {
dialogFormVisible: false,
ruleForm: {
que: '',
desc: '',
},
rules: {
que: [
{required: true, message: '请输入问题标题', trigger: 'blur'},
{min: 5, max: 50, message: '长度在 5 到 50 个字符', trigger: 'blur'}
],
desc: [
{required: true, message: '请输入问题描述', trigger: 'blur'},
{min: 10, max: 500, message: '长度在 10 到 500 个字符', trigger: 'blur'}
],
}
}
},
methods: {
// 提交
submit(){
//点击提交后既可以获取html内容,又可以获得markdown的内容,之后存入到服务端就可以了
this.dialogFormVisible=true;
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.ruleForm.que===""){
alert("标题不能为空")
return
}
alert('submit!');
this.dialogFormVisible = false;
} else {
return false;
}
});
},
},
}
</script>
<style scoped>
.aside{
text-align: center;
}
.login-background {
width: 96%;
margin: 0 auto;
height: 100%; /**宽高100%是为了图片铺满屏幕 */
z-index: 0;
position: absolute;
}
.message{
width: 25em;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.alink{
text-decoration: none;
color: #333333;
}
.show{
margin: 20px auto;
width: 100%;
border: 0px solid #81badc;
transition: all 0.9s;
border-radius: 10px;
}
.show:hover{
box-shadow: 0px 15px 30px rgb(12, 132, 224);
margin-top: 10px;
}
</style>
总结
那么今天就到这里了,偷了点懒,哈哈,不过进度也快了,很快咱们的前端就快基本完成了,那么剩下的部分就是咱们后端+前端的联调,说实话,前端我都是写的最慢的,因为我实在是想不到要怎么设计,最重要的是很多时候我都需要做出一点妥协,因为我前端确实比较菜。