├── .idea
├── .gitignore
├── MessageWall.iml
├── inspectionProfiles
│ └── Project_Default.xml
├── modules.xml
└── vcs.xml
├── API
├── app.js
├── config
│ ├── default.js
│ └── wall.sql
├── controller
│ └── dbServe.js
├── lib
│ └── db.js
├── package-lock.json
├── package.json
└── routes
│ ├── files.js
│ └── index.js
├── README.md
└── Web
├── .gitignore
├── index.html
├── package-lock.json
├── package.json
├── public
└── favicon.ico
├── src
├── App.vue
├── assets
│ ├── api
│ │ └── index.js
│ ├── fonts
│ │ └── icon
│ │ │ ├── demo.css
│ │ │ ├── demo_index.html
│ │ │ ├── iconfont.css
│ │ │ ├── iconfont.js
│ │ │ ├── iconfont.json
│ │ │ ├── iconfont.ttf
│ │ │ ├── iconfont.woff
│ │ │ └── iconfont.woff2
│ ├── images
│ │ ├── card.svg
│ │ ├── favicon.ico
│ │ ├── favicon.svg
│ │ ├── loading.json
│ │ ├── photo.svg
│ │ └── qm1.mp4
│ ├── router
│ │ └── index.js
│ ├── store
│ │ └── index.js
│ ├── styles
│ │ ├── common.css
│ │ └── common.less
│ ├── utils
│ │ ├── axios.js
│ │ ├── data.js
│ │ ├── env.js
│ │ └── methods.js
│ └── views
│ │ ├── WallMessage.vue
│ │ └── index.vue
├── components
│ ├── KMR
│ │ ├── index.js
│ │ └── message
│ │ │ ├── IMessage.vue
│ │ │ └── message.js
│ ├── mobile
│ │ ├── CardDetail.vue
│ │ ├── IModal.vue
│ │ ├── Ibutton.vue
│ │ ├── NewCard.vue
│ │ ├── NodeCard.vue
│ │ ├── PhotoCard.vue
│ │ ├── TopBar.vue
│ │ ├── WallMessage.vue
│ │ └── index.vue
│ └── pc
│ │ ├── CardDetail.vue
│ │ ├── FootBar.vue
│ │ ├── IModal.vue
│ │ ├── Ibutton.vue
│ │ ├── NewCard.vue
│ │ ├── NodeCard.vue
│ │ ├── PhotoCard.vue
│ │ ├── TopBar.vue
│ │ └── Viewer.vue
└── main.js
└── vite.config.js
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/MessageWall.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 |
21 |
22 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/API/app.js:
--------------------------------------------------------------------------------
1 | const express = require('express')
2 | const path = require('path')
3 | const ejs = require('ejs')
4 | const config = require('./config/default')
5 | const router = require('./routes/files')
6 | const routerApi = require('./routes/index')
7 | const app = express()
8 | const fs = require('fs')
9 | // 递归创建路径
10 | const mkdirs = (dirpath) => {
11 | console.log(path.dirname(dirpath))
12 | if (!fs.existsSync(path.dirname(dirpath))) {
13 | mkdirs(path.dirname(dirpath))
14 | }
15 | fs.mkdirSync(dirpath)
16 | console.log('路径创建成功')
17 | }
18 | var img_dir = path.join(__dirname, './assets/wallimgs/')
19 | fs.existsSync(img_dir) == false ? mkdirs(img_dir) : console.log('路径已经存在')
20 | app.use('/assets/wallimgs',express.static(path.join(__dirname,'./assets/wallimgs')))
21 | //配置跨域
22 | app.all('*',(req,res,next) => {
23 | res.header('Access-Control-Allow-Origin','*')
24 | res.header('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type, Accept')
25 | res.header('Access-Control-Allow-Credentials',true)
26 | res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS')
27 |
28 | //返回json
29 | res.header('Content-Type','application/json;charset=utf-8')
30 | if(req.method == 'OPTIONS'){
31 | //让options请求快速返回
32 | res.sendStatus(200)
33 | }else{
34 | next()
35 | }
36 | })
37 |
38 |
39 | //加入html视图
40 | app.engine('html',ejs.__express)
41 | app.set('view engine','html')
42 |
43 | //解析前端数据
44 | app.use(express.json())
45 | app.use(express.urlencoded({ extended : true }))
46 | //引入路由
47 | app.use('/walls',routerApi)
48 | app.use('/walls',router)
49 | // require('./routes/files')(app)
50 | app.listen(config.port,() => {
51 | console.log(`我启动了端口${config.port}`)
52 | })
--------------------------------------------------------------------------------
/API/config/default.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | //node程序启动端口
3 | port : 3000,
4 | database : {
5 | HOST : '',//数据库地址
6 | USER : '',//数据库用户名
7 | PASSWORD : '',//数据库密码
8 | WALL : ''//数据库表名
9 | }
10 | }
11 | module.exports = config
--------------------------------------------------------------------------------
/API/config/wall.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : 苦苦的码人
5 | Source Server Type : MySQL
6 | Source Server Version : 80024
7 | Source Host : 111.180.204.169:3306
8 | Source Schema : wall
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 80024
12 | File Encoding : 65001
13 |
14 | Date: 05/02/2023 15:06:38
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for comments
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `comments`;
24 | CREATE TABLE `comments` (
25 | `id` int NOT NULL AUTO_INCREMENT,
26 | `wallId` int NOT NULL COMMENT '墙留言ID',
27 | `userId` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '评论者ID',
28 | `imgurl` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像路径',
29 | `comment` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '评论内容',
30 | `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
31 | `moment` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '时间',
32 | PRIMARY KEY (`id`) USING BTREE
33 | ) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
34 |
35 | -- ----------------------------
36 | -- Table structure for feedbacks
37 | -- ----------------------------
38 | DROP TABLE IF EXISTS `feedbacks`;
39 | CREATE TABLE `feedbacks` (
40 | `id` int NOT NULL AUTO_INCREMENT,
41 | `wallId` int NOT NULL COMMENT '墙留言ID',
42 | `userId` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '反馈者ID',
43 | `type` int NOT NULL COMMENT '反馈类型0喜欢1举报2撤销',
44 | `moment` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '时间',
45 | PRIMARY KEY (`id`) USING BTREE
46 | ) ENGINE = InnoDB AUTO_INCREMENT = 114 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
47 |
48 | -- ----------------------------
49 | -- Table structure for walls
50 | -- ----------------------------
51 | DROP TABLE IF EXISTS `walls`;
52 | CREATE TABLE `walls` (
53 | `id` int NOT NULL AUTO_INCREMENT,
54 | `type` int NOT NULL COMMENT '类型0信息1图片',
55 | `message` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '留言',
56 | `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
57 | `userId` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '创建者ID',
58 | `moment` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '时间',
59 | `label` int NOT NULL COMMENT '标签',
60 | `color` int NULL DEFAULT NULL COMMENT '颜色',
61 | `imgurl` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图片路径',
62 | PRIMARY KEY (`id`) USING BTREE
63 | ) ENGINE = InnoDB AUTO_INCREMENT = 84 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
64 |
65 | SET FOREIGN_KEY_CHECKS = 1;
66 |
--------------------------------------------------------------------------------
/API/controller/dbServe.js:
--------------------------------------------------------------------------------
1 |
2 | const dbModel = require('../lib/db')
3 | //新建walls
4 | exports.insertWall = async (req,res) =>{
5 | let data = req.body
6 | await dbModel.insertWall([data.type,data.message,data.name,data.userId,data.moment,data.label,data.color,data.imgurl])
7 | .then(result => {
8 | res.send({
9 | code : 200,
10 | message : result
11 | })
12 | })
13 | }
14 | //新建反馈
15 | exports.insertFeedback = async (req,res) =>{
16 | let data = req.body
17 | await dbModel.insertFeedback([data.wallId,data.userId,data.type,data.moment])
18 | .then(result => {
19 | res.send({
20 | code : 200,
21 | message : result
22 | })
23 | })
24 | }
25 | //新建评论
26 | exports.insertComment = async (req,res) =>{
27 | let data = req.body
28 | await dbModel.insertComment([data.wallId,data.userId,data.imgurl,data.moment,data.comment,data.name])
29 | .then(result => {
30 | res.send({
31 | code : 200,
32 | message : result
33 | })
34 | })
35 | }
36 | //删除墙
37 | exports.deleteWall = async(req,res) => {
38 | let data = req.body
39 | // if(data.imgurl){
40 |
41 | // }
42 | await dbModel.deleteWall(data.id).then(result=>{
43 | res.send({
44 | code : 200,
45 | message : result
46 | })
47 | })
48 | }
49 | //删除反馈
50 | exports.deleteFeedback = async(req,res) => {
51 | let data = req.body
52 | await dbModel.deleteFeedback(data.id).then(result=>{
53 | res.send({
54 | code : 200,
55 | message : result
56 | })
57 | })
58 | }
59 | //删除评论
60 | exports.deleteComment = async(req,res) => {
61 | let data = req.body
62 | await dbModel.deleteComment(data.id).then(result=>{
63 | res.send({
64 | code : 200,
65 | message : result
66 | })
67 | })
68 | }
69 | //分页查询wall并获取赞、举报、撤销数据
70 | exports.findWallPage = async(req,res) => {
71 | let data = req.body
72 | await dbModel.findWallPage(data.page,data.pagesize,data.type,data.label)
73 | .then(async result=>{
74 | for(let i = 0;i < result.length;i++){
75 | //查找相应wall的赞、举报、撤销数据
76 | //喜欢
77 | result[i].like = await dbModel.feedbackCount(result[i].id,0)
78 | //举报
79 | result[i].report = await dbModel.feedbackCount(result[i].id,1)
80 | //撤销
81 | result[i].revoke = await dbModel.feedbackCount(result[i].id,2)
82 | //是否点赞
83 | result[i].islike = await dbModel.likeCount(result[i].id,data.userId)
84 | //评论数
85 | result[i].comcount = await dbModel.commentCount(result[i].id)
86 | }
87 | res.send({
88 | code : 200,
89 | message : result
90 | })
91 | })
92 | }
93 | // 倒序分页查询墙的评论
94 | exports.findCommentPage = async(req,res) => {
95 | let data = req.body
96 | await dbModel.findCommentPage(data.page,data.pagesize,data.id).
97 | then(result=>{
98 | res.send({
99 | code : 200,
100 | message : result
101 | })
102 | })
103 | }
--------------------------------------------------------------------------------
/API/lib/db.js:
--------------------------------------------------------------------------------
1 | const mysql = require('mysql')
2 | const config = require('../config/default')
3 | const db = mysql.createConnection({
4 | host: config.database.HOST,
5 | user: config.database.USER,
6 | password: config.database.PASSWORD,
7 | port: 3306
8 | })
9 | //链接指定数据库
10 | const pool = mysql.createPool({
11 | host: config.database.HOST,
12 | user: config.database.USER,
13 | password: config.database.PASSWORD,
14 | database: config.database.WALL,
15 | port: 3306
16 | })
17 | //直接使用
18 | let bdbs = (sql, values) => {
19 | return new Promise((resolve, reject) => {
20 | db.query(sql, values, (err, res) => {
21 | if (err) {
22 | reject(err)
23 |
24 | } else {
25 | resolve(res)
26 | }
27 | })
28 | })
29 | }
30 | //通过pool.getConnection获取链接
31 | let query = (sql, values) => {
32 | return new Promise((resolve, reject) => {
33 | pool.getConnection((err, connection) => {
34 | if (err) {
35 | reject(err)
36 | } else {
37 | connection.query(sql, values, (err, res) => {
38 | if (err) {
39 | reject(err)
40 | } else {
41 | resolve(res)
42 | }
43 | //释放链接
44 | connection.release()
45 | })
46 | }
47 | })
48 | })
49 | }
50 |
51 | //创建数据库
52 | let WALL = 'create database if not exists WALL default charset utf8 collate utf8_general_ci;'
53 | let createDatabase = (db) => {
54 | return bdbs(db, [])
55 | }
56 |
57 | //创建数据表
58 | //留言/照片
59 | let walls = `create table if not exists walls(
60 | id INT NOT NULL AUTO_INCREMENT,
61 | type INT NOT NULL COMMENT '类型0信息1图片',
62 | message VARCHAR(1000) COMMENT '留言',
63 | name VARCHAR(100) NOT NULL COMMENT '用户名',
64 | userId VARCHAR(100) NOT NULL COMMENT '创建者ID',
65 | moment VARCHAR(100) NOT NULL COMMENT '时间',
66 | label INT NOT NULL COMMENT "标签",
67 | color INT COMMENT '颜色',
68 | imgurl VARCHAR(100) COMMENT '图片路径',
69 | PRIMARY KEY ( id )
70 | );`
71 | //留言反馈
72 | let feedbacks = `create table if not exists feedbacks(id INT NOT NULL AUTO_INCREMENT,wallId INT NOT NULL COMMENT '墙留言ID',userId VARCHAR(100) NOT NULL COMMENT '反馈者ID',type INT NOT NULL COMMENT '反馈类型0喜欢1举报2撤销',moment VARCHAR(100) NOT NULL COMMENT '时间',PRIMARY KEY ( id )
73 | );`
74 | //评论
75 | let comments = `create table if not exists comments(id INT NOT NULL AUTO_INCREMENT,
76 | wallId INT NOT NULL COMMENT '墙留言ID',
77 | userId VARCHAR(100) NOT NULL COMMENT '评论者ID',
78 | imgurl VARCHAR(100) COMMENT '头像路径',
79 | comment VARCHAR(1000) COMMENT '评论内容',
80 | name VARCHAR(100) NOT NULL COMMENT '用户名',
81 | moment VARCHAR(100) NOT NULL COMMENT '时间',
82 | PRIMARY KEY ( id )
83 | );`
84 | let createTable = (sql) => {
85 | return query(sql, [])
86 | }
87 | //先创建数据库 再创建表
88 | async function create() {
89 | await createDatabase(WALL)
90 | createTable(walls)
91 | createTable(feedbacks)
92 | createTable(comments)
93 | }
94 | create()
95 |
96 | //新建wall
97 | exports.insertWall = (value) => {
98 | let _sql = 'insert into walls set type=?,message=?,name=?,userId=?,moment=?,label=?,color=?,imgurl=?'
99 | return query(_sql, value)
100 | }
101 | //新增反馈
102 | exports.insertFeedback = (value) => {
103 | let _sql = 'insert feedbacks set wallId=?,userId=?,type=?,moment=?;'
104 | return query(_sql, value)
105 | }
106 | //新增评论
107 | exports.insertComment = (value) => {
108 | let _sql = 'insert comments set wallId=?,userId=?,imgurl=?,moment=?,comment=?,name=?;'
109 | return query(_sql, value)
110 | }
111 | //删除墙,主表对应多条子表一起删除
112 | exports.deleteWall = (id) => {
113 | let _sql = `delete a,b,c from walls a left join feedbacks b on a.id = b.wallId left join comments c on a.id = c.wallId where a.id='${id}'`
114 | return query(_sql)
115 | }
116 | //删除反馈
117 | exports.deleteFeedback = (id) => {
118 | let _sql = `delete from feedbacks where id = '${id}';`
119 | return query(_sql)
120 | }
121 | //删除评论
122 | exports.deleteFeedback = (id) => {
123 | let _sql = `delete from comments where id = '${id}';`
124 | return query(_sql)
125 | }
126 | //分页查询墙
127 | exports.findWallPage = (page, pagesize, type, label) => {
128 | let _sql;
129 | if (label == -1) {
130 | _sql = `select * from walls where type = ${type} order by id desc limit ${(page - 1) * pagesize}, ${pagesize};`
131 | } else {
132 | _sql = `select * from walls where type = ${type} and label='${label}' order by id desc limit ${(page - 1) * pagesize}, ${pagesize};`
133 | }
134 | return query(_sql)
135 | }
136 | //倒序分页查墙的评论
137 | exports.findCommentPage = (page, pagesize, id) => {
138 | let _sql = `select * from comments where wallId = '${id}' order by id desc limit ${(page - 1) * pagesize}, ${pagesize};`
139 | return query(_sql)
140 | }
141 | //查询各反馈总数据
142 | exports.feedbackCount = (wid, type) => {
143 | let _sql = `select count(*) as count from feedbacks where wallId = '${wid}' and type = '${type}';`
144 | return query(_sql)
145 | }
146 | //查询评论总数
147 | exports.commentCount = (wid) => {
148 | let _sql = `select count(*) as count from comments where wallId = '${wid}';`
149 | return query(_sql)
150 | }
151 | //查询点赞
152 | exports.likeCount = (wid, uid) => {
153 | let _sql = ` select count(*) as count from feedbacks where wallId ='${wid}' and userId='${uid}' and type=0;`
154 | return query(_sql)
155 | }
--------------------------------------------------------------------------------
/API/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "cors": "^2.8.5",
4 | "ejs": "^3.1.8",
5 | "express": "^4.18.2",
6 | "multer": "^1.4.5-lts.1",
7 | "mysql": "^2.18.1"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/API/routes/files.js:
--------------------------------------------------------------------------------
1 | const multer = require('multer')
2 | const express = require('express')
3 | const router = express.Router()
4 | //生成随机数
5 | const random = (min,max) => {
6 | return Math.floor(Math.random()*(max-min)) + min;
7 | }
8 | const storage = multer.diskStorage({
9 | //保存路径
10 | destination : function(req,file,cb){
11 | cb(null,'./assets/wallimgs')
12 | //不是相对路径
13 | },
14 | filename : (req,file,cb) => {
15 | //正则匹配后缀名
16 | let type = file.originalname.replace(/.+\./,'.')
17 | cb(null,Date.now() + random(1,100) + type)
18 | }
19 | })
20 | const upload = multer({storage : storage })
21 | router.post('/profile',upload.single('file'),(req,res)=>{
22 | let imgurl = `/assets/wallimgs/${req.file.filename}`
23 | res.send(imgurl)
24 | })
25 |
26 | module.exports = router
--------------------------------------------------------------------------------
/API/routes/index.js:
--------------------------------------------------------------------------------
1 | const controller = require('../controller/dbServe')
2 | const express = require('express')
3 | const router = express.Router()
4 | router.get('/test',(req,res) => {
5 | res.type('html')
6 | res.render('test')
7 | })
8 | //新建数据
9 | router.post('/insertwall',(req,res)=>{
10 | controller.insertWall(req,res)
11 | })
12 | //新建反馈
13 | router.post('/insertfeedback',(req,res)=>{
14 | controller.insertFeedback(req,res)
15 | })
16 | //新建评论
17 | router.post('/insertcomment',(req,res)=>{
18 | controller.insertComment(req,res)
19 | })
20 | //删除墙
21 | router.post('/deletewall',(req,res)=>{
22 | controller.deleteWall(req,res)
23 | })
24 | //删除反馈
25 | router.post('/deletefeedback',(req,res)=>{
26 | controller.deleteFeedback(req,res)
27 | })
28 | //删除评论
29 | router.post('/deletecomment',(req,res)=>{
30 | controller.deleteComment(req,res)
31 | })
32 | //分页查询wall并获取赞、举报、撤销数据
33 | router.post('/findwallpage',(req,res)=>{
34 | controller.findWallPage(req,res)
35 | })
36 | // 倒序分页查询墙的评论
37 | router.post('/findcommentpage',(req,res)=>{
38 | controller.findCommentPage(req,res)
39 | })
40 |
41 | //查询IP
42 | router.post('/signip',(req,res)=>{
43 | var ip = req.ip
44 | res.send({
45 | code : 200,
46 | ip : ip
47 | })
48 | })
49 | module.exports = router
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 留言墙
2 | 本留言墙来源自B站UP主yike陈,分为留言墙与照片墙两部分
3 | [视频链接](https://www.bilibili.com/video/BV11t4y157L2/?spm_id_from=333.999.0.0&vd_source=290b6b566a6de4759a1517c89cdae2c8)
4 |
5 | **Web文件夹为前端,API文件夹为后端,前端配置文件位置为:src/assets/utils/env.js,后端配置文件位置为:config/default.js,并且需要导入相关sql文件,与配置反向代理**
6 |
7 |
8 | **由于本项目后端使用Nodejs编写,请在Web/src/assets/utils/env.js中修改后端API地址,其中的avatarUrl为留言墙右上方小图标**
9 |
10 | - 本项目采用前后端分离方式编写,前端使用Vue3改写,后端使用Nodejs编写
11 | - 本项目改写自B站UP主**yike陈**,并在其视频基础上增添移动端与适当改写
12 | - 如果喜欢该项目就给个Star吧!
13 |
14 | ## 部署教程
15 | ### 后端
16 | - 将后端文件导入网站,使用npm install命令安装模块
17 | 
18 | 
19 | - 将config文件夹中的walls数据库文件导入后端数据库
20 | 
21 | - 之后配置反向代理(防火墙放行)
22 | 
23 | - 之后使用pm2持久化运行
24 | 
25 |
26 | ## 前端
27 | - 首先npm install安装相关包,之后修改env.js文件的baseUrl与baseImgPath为后端API地址、avatarUrl为头像地址
28 | 
29 | - 之后npm run build构建后直接上传服务器即可使用
30 |
31 | ## 项目地址
32 | **Demo地址:[一刻时空-苦苦的码人](https://wall.5i21.cn/)**
33 | ## 项目截图
34 | ### PC端
35 | 
36 | 
37 | 
38 | 
39 |
40 | ### 移动端
41 | 
42 | 
43 |
--------------------------------------------------------------------------------
/Web/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/Web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 一刻时光-苦苦的码人
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
--------------------------------------------------------------------------------
/Web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "axios": "^1.2.2",
13 | "less": "^4.1.3",
14 | "less-loader": "^11.1.0",
15 | "lottie-web": "^5.10.1",
16 | "mockjs": "^1.1.0",
17 | "vue": "^3.2.45",
18 | "vue-axios": "^3.5.2",
19 | "vue-router": "^4.1.6",
20 | "vuex": "^4.0.2"
21 | },
22 | "devDependencies": {
23 | "@types/node": "^18.11.18",
24 | "@vitejs/plugin-vue": "^4.0.0",
25 | "vite": "^4.0.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/public/favicon.ico
--------------------------------------------------------------------------------
/Web/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
27 |
--------------------------------------------------------------------------------
/Web/src/assets/api/index.js:
--------------------------------------------------------------------------------
1 | import fetch from '../utils/axios'
2 | //新建数据
3 | export function insertWallApi(data){
4 | return fetch.post('/insertwall',data)
5 | }
6 | //获取IP
7 | export function signIpApi(){
8 | return fetch.post('/signip')
9 | }
10 | //查询墙
11 | export function findWallPageApi(data){
12 | return fetch.post('/findwallpage',data)
13 | }
14 | //新建反馈
15 | export function insertFeedBackApi(data){
16 | return fetch.post('/insertfeedback',data)
17 | }
18 | //新建评论
19 | export function insertCommentApi(data){
20 | return fetch.post('/insertcomment',data)
21 | }
22 | //获取评论
23 | export function findCommentPage(data){
24 | return fetch.post('/findcommentpage',data)
25 | }
26 | //上传图片
27 | export function proFileApi(data){
28 | return fetch.post('/profile',data)
29 | }
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/demo.css:
--------------------------------------------------------------------------------
1 | /* Logo 字体 */
2 | @font-face {
3 | font-family: "iconfont logo";
4 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
5 | src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
6 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
7 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
8 | url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
9 | }
10 |
11 | .logo {
12 | font-family: "iconfont logo";
13 | font-size: 160px;
14 | font-style: normal;
15 | -webkit-font-smoothing: antialiased;
16 | -moz-osx-font-smoothing: grayscale;
17 | }
18 |
19 | /* tabs */
20 | .nav-tabs {
21 | position: relative;
22 | }
23 |
24 | .nav-tabs .nav-more {
25 | position: absolute;
26 | right: 0;
27 | bottom: 0;
28 | height: 42px;
29 | line-height: 42px;
30 | color: #666;
31 | }
32 |
33 | #tabs {
34 | border-bottom: 1px solid #eee;
35 | }
36 |
37 | #tabs li {
38 | cursor: pointer;
39 | width: 100px;
40 | height: 40px;
41 | line-height: 40px;
42 | text-align: center;
43 | font-size: 16px;
44 | border-bottom: 2px solid transparent;
45 | position: relative;
46 | z-index: 1;
47 | margin-bottom: -1px;
48 | color: #666;
49 | }
50 |
51 |
52 | #tabs .active {
53 | border-bottom-color: #f00;
54 | color: #222;
55 | }
56 |
57 | .tab-container .content {
58 | display: none;
59 | }
60 |
61 | /* 页面布局 */
62 | .main {
63 | padding: 30px 100px;
64 | width: 960px;
65 | margin: 0 auto;
66 | }
67 |
68 | .main .logo {
69 | color: #333;
70 | text-align: left;
71 | margin-bottom: 30px;
72 | line-height: 1;
73 | height: 110px;
74 | margin-top: -50px;
75 | overflow: hidden;
76 | *zoom: 1;
77 | }
78 |
79 | .main .logo a {
80 | font-size: 160px;
81 | color: #333;
82 | }
83 |
84 | .helps {
85 | margin-top: 40px;
86 | }
87 |
88 | .helps pre {
89 | padding: 20px;
90 | margin: 10px 0;
91 | border: solid 1px #e7e1cd;
92 | background-color: #fffdef;
93 | overflow: auto;
94 | }
95 |
96 | .icon_lists {
97 | width: 100% !important;
98 | overflow: hidden;
99 | *zoom: 1;
100 | }
101 |
102 | .icon_lists li {
103 | width: 100px;
104 | margin-bottom: 10px;
105 | margin-right: 20px;
106 | text-align: center;
107 | list-style: none !important;
108 | cursor: default;
109 | }
110 |
111 | .icon_lists li .code-name {
112 | line-height: 1.2;
113 | }
114 |
115 | .icon_lists .icon {
116 | display: block;
117 | height: 100px;
118 | line-height: 100px;
119 | font-size: 42px;
120 | margin: 10px auto;
121 | color: #333;
122 | -webkit-transition: font-size 0.25s linear, width 0.25s linear;
123 | -moz-transition: font-size 0.25s linear, width 0.25s linear;
124 | transition: font-size 0.25s linear, width 0.25s linear;
125 | }
126 |
127 | .icon_lists .icon:hover {
128 | font-size: 100px;
129 | }
130 |
131 | .icon_lists .svg-icon {
132 | /* 通过设置 font-size 来改变图标大小 */
133 | width: 1em;
134 | /* 图标和文字相邻时,垂直对齐 */
135 | vertical-align: -0.15em;
136 | /* 通过设置 color 来改变 SVG 的颜色/fill */
137 | fill: currentColor;
138 | /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
139 | normalize.css 中也包含这行 */
140 | overflow: hidden;
141 | }
142 |
143 | .icon_lists li .name,
144 | .icon_lists li .code-name {
145 | color: #666;
146 | }
147 |
148 | /* markdown 样式 */
149 | .markdown {
150 | color: #666;
151 | font-size: 14px;
152 | line-height: 1.8;
153 | }
154 |
155 | .highlight {
156 | line-height: 1.5;
157 | }
158 |
159 | .markdown img {
160 | vertical-align: middle;
161 | max-width: 100%;
162 | }
163 |
164 | .markdown h1 {
165 | color: #404040;
166 | font-weight: 500;
167 | line-height: 40px;
168 | margin-bottom: 24px;
169 | }
170 |
171 | .markdown h2,
172 | .markdown h3,
173 | .markdown h4,
174 | .markdown h5,
175 | .markdown h6 {
176 | color: #404040;
177 | margin: 1.6em 0 0.6em 0;
178 | font-weight: 500;
179 | clear: both;
180 | }
181 |
182 | .markdown h1 {
183 | font-size: 28px;
184 | }
185 |
186 | .markdown h2 {
187 | font-size: 22px;
188 | }
189 |
190 | .markdown h3 {
191 | font-size: 16px;
192 | }
193 |
194 | .markdown h4 {
195 | font-size: 14px;
196 | }
197 |
198 | .markdown h5 {
199 | font-size: 12px;
200 | }
201 |
202 | .markdown h6 {
203 | font-size: 12px;
204 | }
205 |
206 | .markdown hr {
207 | height: 1px;
208 | border: 0;
209 | background: #e9e9e9;
210 | margin: 16px 0;
211 | clear: both;
212 | }
213 |
214 | .markdown p {
215 | margin: 1em 0;
216 | }
217 |
218 | .markdown>p,
219 | .markdown>blockquote,
220 | .markdown>.highlight,
221 | .markdown>ol,
222 | .markdown>ul {
223 | width: 80%;
224 | }
225 |
226 | .markdown ul>li {
227 | list-style: circle;
228 | }
229 |
230 | .markdown>ul li,
231 | .markdown blockquote ul>li {
232 | margin-left: 20px;
233 | padding-left: 4px;
234 | }
235 |
236 | .markdown>ul li p,
237 | .markdown>ol li p {
238 | margin: 0.6em 0;
239 | }
240 |
241 | .markdown ol>li {
242 | list-style: decimal;
243 | }
244 |
245 | .markdown>ol li,
246 | .markdown blockquote ol>li {
247 | margin-left: 20px;
248 | padding-left: 4px;
249 | }
250 |
251 | .markdown code {
252 | margin: 0 3px;
253 | padding: 0 5px;
254 | background: #eee;
255 | border-radius: 3px;
256 | }
257 |
258 | .markdown strong,
259 | .markdown b {
260 | font-weight: 600;
261 | }
262 |
263 | .markdown>table {
264 | border-collapse: collapse;
265 | border-spacing: 0px;
266 | empty-cells: show;
267 | border: 1px solid #e9e9e9;
268 | width: 95%;
269 | margin-bottom: 24px;
270 | }
271 |
272 | .markdown>table th {
273 | white-space: nowrap;
274 | color: #333;
275 | font-weight: 600;
276 | }
277 |
278 | .markdown>table th,
279 | .markdown>table td {
280 | border: 1px solid #e9e9e9;
281 | padding: 8px 16px;
282 | text-align: left;
283 | }
284 |
285 | .markdown>table th {
286 | background: #F7F7F7;
287 | }
288 |
289 | .markdown blockquote {
290 | font-size: 90%;
291 | color: #999;
292 | border-left: 4px solid #e9e9e9;
293 | padding-left: 0.8em;
294 | margin: 1em 0;
295 | }
296 |
297 | .markdown blockquote p {
298 | margin: 0;
299 | }
300 |
301 | .markdown .anchor {
302 | opacity: 0;
303 | transition: opacity 0.3s ease;
304 | margin-left: 8px;
305 | }
306 |
307 | .markdown .waiting {
308 | color: #ccc;
309 | }
310 |
311 | .markdown h1:hover .anchor,
312 | .markdown h2:hover .anchor,
313 | .markdown h3:hover .anchor,
314 | .markdown h4:hover .anchor,
315 | .markdown h5:hover .anchor,
316 | .markdown h6:hover .anchor {
317 | opacity: 1;
318 | display: inline-block;
319 | }
320 |
321 | .markdown>br,
322 | .markdown>p>br {
323 | clear: both;
324 | }
325 |
326 |
327 | .hljs {
328 | display: block;
329 | background: white;
330 | padding: 0.5em;
331 | color: #333333;
332 | overflow-x: auto;
333 | }
334 |
335 | .hljs-comment,
336 | .hljs-meta {
337 | color: #969896;
338 | }
339 |
340 | .hljs-string,
341 | .hljs-variable,
342 | .hljs-template-variable,
343 | .hljs-strong,
344 | .hljs-emphasis,
345 | .hljs-quote {
346 | color: #df5000;
347 | }
348 |
349 | .hljs-keyword,
350 | .hljs-selector-tag,
351 | .hljs-type {
352 | color: #a71d5d;
353 | }
354 |
355 | .hljs-literal,
356 | .hljs-symbol,
357 | .hljs-bullet,
358 | .hljs-attribute {
359 | color: #0086b3;
360 | }
361 |
362 | .hljs-section,
363 | .hljs-name {
364 | color: #63a35c;
365 | }
366 |
367 | .hljs-tag {
368 | color: #333333;
369 | }
370 |
371 | .hljs-title,
372 | .hljs-attr,
373 | .hljs-selector-id,
374 | .hljs-selector-class,
375 | .hljs-selector-attr,
376 | .hljs-selector-pseudo {
377 | color: #795da3;
378 | }
379 |
380 | .hljs-addition {
381 | color: #55a532;
382 | background-color: #eaffea;
383 | }
384 |
385 | .hljs-deletion {
386 | color: #bd2c00;
387 | background-color: #ffecec;
388 | }
389 |
390 | .hljs-link {
391 | text-decoration: underline;
392 | }
393 |
394 | /* 代码高亮 */
395 | /* PrismJS 1.15.0
396 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
397 | /**
398 | * prism.js default theme for JavaScript, CSS and HTML
399 | * Based on dabblet (http://dabblet.com)
400 | * @author Lea Verou
401 | */
402 | code[class*="language-"],
403 | pre[class*="language-"] {
404 | color: black;
405 | background: none;
406 | text-shadow: 0 1px white;
407 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
408 | text-align: left;
409 | white-space: pre;
410 | word-spacing: normal;
411 | word-break: normal;
412 | word-wrap: normal;
413 | line-height: 1.5;
414 |
415 | -moz-tab-size: 4;
416 | -o-tab-size: 4;
417 | tab-size: 4;
418 |
419 | -webkit-hyphens: none;
420 | -moz-hyphens: none;
421 | -ms-hyphens: none;
422 | hyphens: none;
423 | }
424 |
425 | pre[class*="language-"]::-moz-selection,
426 | pre[class*="language-"] ::-moz-selection,
427 | code[class*="language-"]::-moz-selection,
428 | code[class*="language-"] ::-moz-selection {
429 | text-shadow: none;
430 | background: #b3d4fc;
431 | }
432 |
433 | pre[class*="language-"]::selection,
434 | pre[class*="language-"] ::selection,
435 | code[class*="language-"]::selection,
436 | code[class*="language-"] ::selection {
437 | text-shadow: none;
438 | background: #b3d4fc;
439 | }
440 |
441 | @media print {
442 |
443 | code[class*="language-"],
444 | pre[class*="language-"] {
445 | text-shadow: none;
446 | }
447 | }
448 |
449 | /* Code blocks */
450 | pre[class*="language-"] {
451 | padding: 1em;
452 | margin: .5em 0;
453 | overflow: auto;
454 | }
455 |
456 | :not(pre)>code[class*="language-"],
457 | pre[class*="language-"] {
458 | background: #f5f2f0;
459 | }
460 |
461 | /* Inline code */
462 | :not(pre)>code[class*="language-"] {
463 | padding: .1em;
464 | border-radius: .3em;
465 | white-space: normal;
466 | }
467 |
468 | .token.comment,
469 | .token.prolog,
470 | .token.doctype,
471 | .token.cdata {
472 | color: slategray;
473 | }
474 |
475 | .token.punctuation {
476 | color: #999;
477 | }
478 |
479 | .namespace {
480 | opacity: .7;
481 | }
482 |
483 | .token.property,
484 | .token.tag,
485 | .token.boolean,
486 | .token.number,
487 | .token.constant,
488 | .token.symbol,
489 | .token.deleted {
490 | color: #905;
491 | }
492 |
493 | .token.selector,
494 | .token.attr-name,
495 | .token.string,
496 | .token.char,
497 | .token.builtin,
498 | .token.inserted {
499 | color: #690;
500 | }
501 |
502 | .token.operator,
503 | .token.entity,
504 | .token.url,
505 | .language-css .token.string,
506 | .style .token.string {
507 | color: #9a6e3a;
508 | background: hsla(0, 0%, 100%, .5);
509 | }
510 |
511 | .token.atrule,
512 | .token.attr-value,
513 | .token.keyword {
514 | color: #07a;
515 | }
516 |
517 | .token.function,
518 | .token.class-name {
519 | color: #DD4A68;
520 | }
521 |
522 | .token.regex,
523 | .token.important,
524 | .token.variable {
525 | color: #e90;
526 | }
527 |
528 | .token.important,
529 | .token.bold {
530 | font-weight: bold;
531 | }
532 |
533 | .token.italic {
534 | font-style: italic;
535 | }
536 |
537 | .token.entity {
538 | cursor: help;
539 | }
540 |
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/demo_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | iconfont Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
36 |
37 |
38 |
39 |
43 |
44 |
45 | - Unicode
46 | - Font class
47 | - Symbol
48 |
49 |
50 |
查看项目
51 |
52 |
53 |
54 |
55 |
56 |
57 | -
58 |
59 |
太阳
60 | 
61 |
62 |
63 | -
64 |
65 |
月亮
66 | 
67 |
68 |
69 | -
70 |
71 |
修改
72 | 
73 |
74 |
75 | -
76 |
77 |
yksg
78 | 
79 |
80 |
81 | -
82 |
83 |
爱心
84 | 
85 |
86 |
87 | -
88 |
89 |
添加
90 | 
91 |
92 |
93 | -
94 |
95 |
留言
96 | 
97 |
98 |
99 | -
100 |
101 |
向右1
102 | 
103 |
104 |
105 | -
106 |
107 |
向左1
108 | 
109 |
110 |
111 | -
112 |
113 |
关 闭
114 | 
115 |
116 |
117 | -
118 |
119 |
失败报错-
120 | 
121 |
122 |
123 | -
124 |
125 |
信息提示-
126 | 
127 |
128 |
129 | -
130 |
131 |
成功已解决-
132 | 
133 |
134 |
135 |
136 |
137 |
Unicode 引用
138 |
139 |
140 |
Unicode 是字体在网页端最原始的应用方式,特点是:
141 |
142 | - 支持按字体的方式去动态调整图标大小,颜色等等。
143 | - 默认情况下不支持多色,直接添加多色图标会自动去色。
144 |
145 |
146 | 注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)
147 |
148 |
Unicode 使用步骤如下:
149 |
第一步:拷贝项目下面生成的 @font-face
150 |
@font-face {
152 | font-family: 'iconfont';
153 | src: url('iconfont.woff2?t=1673919549404') format('woff2'),
154 | url('iconfont.woff?t=1673919549404') format('woff'),
155 | url('iconfont.ttf?t=1673919549404') format('truetype');
156 | }
157 |
158 |
第二步:定义使用 iconfont 的样式
159 |
.iconfont {
161 | font-family: "iconfont" !important;
162 | font-size: 16px;
163 | font-style: normal;
164 | -webkit-font-smoothing: antialiased;
165 | -moz-osx-font-smoothing: grayscale;
166 | }
167 |
168 |
第三步:挑选相应图标并获取字体编码,应用于页面
169 |
170 | <span class="iconfont">3</span>
172 |
173 |
174 | "iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
175 |
176 |
177 |
178 |
179 |
180 |
181 | -
182 |
183 |
184 | 太阳
185 |
186 | .icon-taiyang
187 |
188 |
189 |
190 | -
191 |
192 |
193 | 月亮
194 |
195 | .icon-yueliang
196 |
197 |
198 |
199 | -
200 |
201 |
202 | 修改
203 |
204 | .icon-xiugai
205 |
206 |
207 |
208 | -
209 |
210 |
211 | yksg
212 |
213 | .icon-yksg
214 |
215 |
216 |
217 | -
218 |
219 |
220 | 爱心
221 |
222 | .icon-aixin1
223 |
224 |
225 |
226 | -
227 |
228 |
229 | 添加
230 |
231 | .icon-tianjia
232 |
233 |
234 |
235 | -
236 |
237 |
238 | 留言
239 |
240 | .icon-liuyan
241 |
242 |
243 |
244 | -
245 |
246 |
247 | 向右1
248 |
249 | .icon-xiangyou
250 |
251 |
252 |
253 | -
254 |
255 |
256 | 向左1
257 |
258 | .icon-xiangzuo
259 |
260 |
261 |
262 | -
263 |
264 |
265 | 关 闭
266 |
267 | .icon-guanbi
268 |
269 |
270 |
271 | -
272 |
273 |
274 | 失败报错-
275 |
276 | .icon-error
277 |
278 |
279 |
280 | -
281 |
282 |
283 | 信息提示-
284 |
285 | .icon-warning
286 |
287 |
288 |
289 | -
290 |
291 |
292 | 成功已解决-
293 |
294 | .icon-success
295 |
296 |
297 |
298 |
299 |
300 |
font-class 引用
301 |
302 |
303 |
font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。
304 |
与 Unicode 使用方式相比,具有如下特点:
305 |
306 | - 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
307 | - 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
308 |
309 |
使用步骤如下:
310 |
第一步:引入项目下面生成的 fontclass 代码:
311 |
<link rel="stylesheet" href="./iconfont.css">
312 |
313 |
第二步:挑选相应图标并获取类名,应用于页面:
314 |
<span class="iconfont icon-xxx"></span>
315 |
316 |
317 | "
318 | iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。
319 |
320 |
321 |
322 |
323 |
324 |
325 | -
326 |
329 |
太阳
330 | #icon-taiyang
331 |
332 |
333 | -
334 |
337 |
月亮
338 | #icon-yueliang
339 |
340 |
341 | -
342 |
345 |
修改
346 | #icon-xiugai
347 |
348 |
349 | -
350 |
353 |
yksg
354 | #icon-yksg
355 |
356 |
357 | -
358 |
361 |
爱心
362 | #icon-aixin1
363 |
364 |
365 | -
366 |
369 |
添加
370 | #icon-tianjia
371 |
372 |
373 | -
374 |
377 |
留言
378 | #icon-liuyan
379 |
380 |
381 | -
382 |
385 |
向右1
386 | #icon-xiangyou
387 |
388 |
389 | -
390 |
393 |
向左1
394 | #icon-xiangzuo
395 |
396 |
397 | -
398 |
401 |
关 闭
402 | #icon-guanbi
403 |
404 |
405 | -
406 |
409 |
失败报错-
410 | #icon-error
411 |
412 |
413 | -
414 |
417 |
信息提示-
418 | #icon-warning
419 |
420 |
421 | -
422 |
425 |
成功已解决-
426 | #icon-success
427 |
428 |
429 |
430 |
431 |
Symbol 引用
432 |
433 |
434 |
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章
435 | 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:
436 |
437 | - 支持多色图标了,不再受单色限制。
438 | - 通过一些技巧,支持像字体那样,通过
font-size
, color
来调整样式。
439 | - 兼容性较差,支持 IE9+,及现代浏览器。
440 | - 浏览器渲染 SVG 的性能一般,还不如 png。
441 |
442 |
使用步骤如下:
443 |
第一步:引入项目下面生成的 symbol 代码:
444 |
<script src="./iconfont.js"></script>
445 |
446 |
第二步:加入通用 CSS 代码(引入一次就行):
447 |
<style>
448 | .icon {
449 | width: 1em;
450 | height: 1em;
451 | vertical-align: -0.15em;
452 | fill: currentColor;
453 | overflow: hidden;
454 | }
455 | </style>
456 |
457 |
第三步:挑选相应图标并获取类名,应用于页面:
458 |
<svg class="icon" aria-hidden="true">
459 | <use xlink:href="#icon-xxx"></use>
460 | </svg>
461 |
462 |
463 |
464 |
465 |
466 |
467 |
486 |
487 |
488 |
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "iconfont"; /* Project id 3395343 */
3 | src: url('iconfont.woff2?t=1673919549404') format('woff2'),
4 | url('iconfont.woff?t=1673919549404') format('woff'),
5 | url('iconfont.ttf?t=1673919549404') format('truetype');
6 | }
7 |
8 | .iconfont {
9 | font-family: "iconfont" !important;
10 | font-size: 16px;
11 | font-style: normal;
12 | -webkit-font-smoothing: antialiased;
13 | -moz-osx-font-smoothing: grayscale;
14 | }
15 |
16 | .icon-taiyang:before {
17 | content: "\e60f";
18 | }
19 |
20 | .icon-yueliang:before {
21 | content: "\e6b8";
22 | }
23 |
24 | .icon-xiugai:before {
25 | content: "\e696";
26 | }
27 |
28 | .icon-yksg:before {
29 | content: "\e68b";
30 | }
31 |
32 | .icon-aixin1:before {
33 | content: "\e663";
34 | }
35 |
36 | .icon-tianjia:before {
37 | content: "\e622";
38 | }
39 |
40 | .icon-liuyan:before {
41 | content: "\e606";
42 | }
43 |
44 | .icon-xiangyou:before {
45 | content: "\e775";
46 | }
47 |
48 | .icon-xiangzuo:before {
49 | content: "\e779";
50 | }
51 |
52 | .icon-guanbi:before {
53 | content: "\e639";
54 | }
55 |
56 | .icon-error:before {
57 | content: "\e6c6";
58 | }
59 |
60 | .icon-warning:before {
61 | content: "\e6ce";
62 | }
63 |
64 | .icon-success:before {
65 | content: "\e6d4";
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.js:
--------------------------------------------------------------------------------
1 | window._iconfont_svg_string_3395343='',function(e){var t=(t=document.getElementsByTagName("script"))[t.length-1],c=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var o,i,l,n,a,s=function(t,c){c.parentNode.insertBefore(t,c)};if(c&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}o=function(){var t,c=document.createElement("div");c.innerHTML=e._iconfont_svg_string_3395343,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(t=document.body).firstChild?s(c,t.firstChild):t.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(l=o,n=e.document,a=!1,m(),n.onreadystatechange=function(){"complete"==n.readyState&&(n.onreadystatechange=null,d())})}function d(){a||(a=!0,l())}function m(){try{n.documentElement.doScroll("left")}catch(t){return void setTimeout(m,50)}d()}}(window);
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "3395343",
3 | "name": "yike基础版",
4 | "font_family": "iconfont",
5 | "css_prefix_text": "icon-",
6 | "description": "",
7 | "glyphs": [
8 | {
9 | "icon_id": "1724889",
10 | "name": "太阳",
11 | "font_class": "taiyang",
12 | "unicode": "e60f",
13 | "unicode_decimal": 58895
14 | },
15 | {
16 | "icon_id": "3402343",
17 | "name": "月亮",
18 | "font_class": "yueliang",
19 | "unicode": "e6b8",
20 | "unicode_decimal": 59064
21 | },
22 | {
23 | "icon_id": "421237",
24 | "name": "修改",
25 | "font_class": "xiugai",
26 | "unicode": "e696",
27 | "unicode_decimal": 59030
28 | },
29 | {
30 | "icon_id": "30295631",
31 | "name": "yksg",
32 | "font_class": "yksg",
33 | "unicode": "e68b",
34 | "unicode_decimal": 59019
35 | },
36 | {
37 | "icon_id": "918722",
38 | "name": "爱心",
39 | "font_class": "aixin1",
40 | "unicode": "e663",
41 | "unicode_decimal": 58979
42 | },
43 | {
44 | "icon_id": "1304889",
45 | "name": "添加",
46 | "font_class": "tianjia",
47 | "unicode": "e622",
48 | "unicode_decimal": 58914
49 | },
50 | {
51 | "icon_id": "1418212",
52 | "name": "留言",
53 | "font_class": "liuyan",
54 | "unicode": "e606",
55 | "unicode_decimal": 58886
56 | },
57 | {
58 | "icon_id": "577402",
59 | "name": "向右1",
60 | "font_class": "xiangyou",
61 | "unicode": "e775",
62 | "unicode_decimal": 59253
63 | },
64 | {
65 | "icon_id": "577406",
66 | "name": "向左1",
67 | "font_class": "xiangzuo",
68 | "unicode": "e779",
69 | "unicode_decimal": 59257
70 | },
71 | {
72 | "icon_id": "9430532",
73 | "name": "关 闭",
74 | "font_class": "guanbi",
75 | "unicode": "e639",
76 | "unicode_decimal": 58937
77 | },
78 | {
79 | "icon_id": "250681",
80 | "name": "失败报错-",
81 | "font_class": "error",
82 | "unicode": "e6c6",
83 | "unicode_decimal": 59078
84 | },
85 | {
86 | "icon_id": "250689",
87 | "name": "信息提示-",
88 | "font_class": "warning",
89 | "unicode": "e6ce",
90 | "unicode_decimal": 59086
91 | },
92 | {
93 | "icon_id": "250695",
94 | "name": "成功已解决-",
95 | "font_class": "success",
96 | "unicode": "e6d4",
97 | "unicode_decimal": 59092
98 | }
99 | ]
100 | }
101 |
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/src/assets/fonts/icon/iconfont.ttf
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/src/assets/fonts/icon/iconfont.woff
--------------------------------------------------------------------------------
/Web/src/assets/fonts/icon/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/src/assets/fonts/icon/iconfont.woff2
--------------------------------------------------------------------------------
/Web/src/assets/images/card.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Web/src/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/src/assets/images/favicon.ico
--------------------------------------------------------------------------------
/Web/src/assets/images/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Web/src/assets/images/loading.json:
--------------------------------------------------------------------------------
1 | {"v":"4.10.1","fr":24,"ip":0,"op":60,"w":400,"h":400,"nm":"Comp 1","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Capa de formas 12","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":24,"s":[81.5,370.25,0],"e":[445.5,199.25,0],"to":[60.6666679382324,-28.5,0],"ti":[-60.6666679382324,28.5,0]},{"t":48}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.198431351606,0.588595042509,0.733333333333,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":144,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Capa de formas 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":24,"s":[-133,374,0],"e":[231,203,0],"to":[60.6666679382324,-28.5,0],"ti":[-60.6666679382324,28.5,0]},{"t":48}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[43,43,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[28,0],[34.935,-19.483],[31.619,18.821],[33,-14],[57,29],[0,0],[0,0],[0,0]],"o":[[-28,0],[-52,29],[-42,-25],[-28.892,12.257],[-57,-29],[0,0],[0,0],[0,0]],"v":[[367.75,-97],[277,-75],[155,-82],[35,-82],[-94,-82.326],[-200,-74],[-352.07,320.209],[499.162,354.093]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.2,0.588235294118,0.733333333333,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":144,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Capa de formas 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":15,"s":[100],"e":[0]},{"t":16}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[199,-14,0],"e":[199,156,0],"to":[0,28.3333339691162,0],"ti":[0,-28.9375,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":12,"s":[199,156,0],"e":[199,164.066,0],"to":[0,4.54861259460449,0],"ti":[0,-2.45892143249512,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":13,"s":[199,164.066,0],"e":[199,166.125,0],"to":[0,13.1843204498291,0],"ti":[0,-1.72074222564697,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":14,"s":[199,166.125,0],"e":[199,168.375,0],"to":[0,2.04166674613953,0],"ti":[0,-0.04166666790843,0]},{"t":15}],"ix":2},"a":{"a":0,"k":[-1,-182.375,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[50,50,100],"e":[50,94,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":12,"s":[50,94,100],"e":[70,43.333,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":13,"s":[70,43.333,100],"e":[104.258,32,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":14,"s":[104.258,32,100],"e":[212,18,100]},{"t":15}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.938,0],[0,-5.25],[-4.563,0.125],[0.108,4.624]],"o":[[-0.813,0.125],[0,4.813],[4.563,-0.125],[-0.125,-5.375]],"v":[[-1.344,-193.078],[-8.75,-180.5],[-1.063,-172.313],[6.938,-180.188]],"c":true},"ix":2},"nm":"Trazado 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.317647058824,0.325490196078,0.341176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Forma 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Capa de formas 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":46,"s":[0],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":47,"s":[100],"e":[100]},{"t":48}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":47,"s":[199.98,168.25,0],"e":[199.98,158.037,0],"to":[0,-0.20375619828701,0],"ti":[0,17.58864402771,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":48,"s":[199.98,158.037,0],"e":[199.98,-10,0],"to":[-2.8421709430404e-14,-50.4047393798828,0],"ti":[0,1.17485654354095,0]},{"t":53}],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":47,"s":[-4,1,100],"e":[1.5,4,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":48,"s":[1.5,4,100],"e":[2,3,100]},{"t":53}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.317647058824,0.325490196078,0.341176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Capa de formas 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[199,253,0],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[55,55,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.317093434053,0.325121112898,0.341176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"nm":"Trazo 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[50],"e":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":24,"s":[100],"e":[50]},{"t":48}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":12,"s":[50],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":24,"s":[0],"e":[50]},{"t":48}],"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Recortar trazados 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Capa de formas 1","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[199,253,0],"ix":2},"a":{"a":0,"k":[-32,-31,0],"ix":1},"s":{"a":0,"k":[50,50,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[308,308],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Trazado elíptico 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.913725490196,0.347995563582,0.03941561007,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"nm":"Relleno 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"Precomp. 1","tt":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[200,200,0],"ix":2},"a":{"a":0,"k":[200,200,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":400,"h":400,"ip":0,"op":144,"st":0,"bm":0}]}
--------------------------------------------------------------------------------
/Web/src/assets/images/photo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Web/src/assets/images/qm1.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy05240/MessageWall/4f6fbd2c4c963fc47e46260af1ff1ddb49914050/Web/src/assets/images/qm1.mp4
--------------------------------------------------------------------------------
/Web/src/assets/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory } from "vue-router";
2 | const routes = [
3 | {
4 | path : '/',
5 | redirect : '/wall?id=0',
6 | name : 'index',
7 | components : {
8 | default : () => import('@/views/index.vue'),
9 | pc : () => import('@/views/index.vue'),
10 | mobile : () => import('~/components/mobile/index.vue')
11 | },
12 | children : [{
13 | path : 'wall',
14 | components : {
15 | default: () => import('@/views/WallMessage.vue'),
16 | pc : () => import('@/views/WallMessage.vue'),
17 | mobile : () => import('~/components/mobile/WallMessage.vue')
18 | }}
19 | ]
20 | }
21 | ]
22 | const router = createRouter({
23 | history : createWebHashHistory(),
24 | routes
25 | })
26 | export default router
--------------------------------------------------------------------------------
/Web/src/assets/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore } from "vuex";
2 | const store = createStore(
3 | {
4 | states (){
5 | return {
6 | count : 0,
7 | user : ''
8 | }
9 | },
10 | mutations : {
11 | increament(state){
12 | state.count++
13 | },
14 | getUser(state,n){
15 | state.user = n
16 | }
17 | },
18 | actions : {
19 |
20 | }
21 | }
22 | )
23 | export default store
24 |
25 |
--------------------------------------------------------------------------------
/Web/src/assets/styles/common.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0px;
3 | margin: 0px;
4 | line-height: 1.5;
5 | color: #202020;
6 | font-size: 14px;
7 | background-color: #FFFFFF;
8 | transition: all 0.3s;
9 | font-family: Avenir, Arial, Helvetica, sans-serif;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | }
13 | p {
14 | padding: 0;
15 | margin: 0;
16 | }
17 | li {
18 | list-style: none;
19 | }
20 | img {
21 | padding: 0;
22 | margin: 0;
23 | display: block;
24 | }
25 | a {
26 | text-decoration: none;
27 | }
28 | a:hover {
29 | text-decoration: none;
30 | }
31 | input,
32 | textarea {
33 | outline: none;
34 | }
35 |
--------------------------------------------------------------------------------
/Web/src/assets/styles/common.less:
--------------------------------------------------------------------------------
1 | // ----------Colors----------
2 | @primary-color : #3B73F0; //全局主色
3 | @link-color : #1890ff ; //链接色
4 | @success-color : #22BF87; //成功色
5 | @warning-color : #F67770; //警告色
6 | @error-color : #F35248; //错误色
7 | @like : #F67770;//喜欢
8 | // ----------中性色----------
9 | @gray-1 : #202020;
10 | @gray-2 : #5B5B5B;
11 | @gray-3 : #949494;
12 | @gray-9 : #F6F6F8;
13 | @gray-10 : #FFFFFF;
14 |
15 | // ----------Font----------
16 | @size-12 : 12px;
17 | @size-14 : 14px;
18 | @size-16 : 16px;
19 |
20 | // ----------间距----------
21 | @padding-4 : 4px;
22 | @padding-8 : 8px;
23 | @padding-12 : 12px;
24 | @padding-20 : 20px;
25 |
26 | // ----------动画----------
27 | @tr : all 0.3s;
28 | // ----------全局控制----------
29 | body{
30 | padding: 0px;
31 | margin: 0px;
32 | line-height: 1.5;
33 | color : @gray-1;
34 | font-size: @size-14;
35 | background-color: @gray-10;
36 | transition: all .3s;
37 | font-family: Avenir,Arial, Helvetica, sans-serif;
38 | -webkit-font-smoothing: antialiased;
39 | -moz-osx-font-smoothing: grayscale;
40 | }
41 |
42 | p{
43 | padding: 0;
44 | margin: 0;
45 | }
46 |
47 | li{
48 | list-style: none;
49 | }
50 |
51 | img{
52 | padding: 0;
53 | margin: 0;
54 | display: block;
55 | }
56 |
57 | a{
58 | text-decoration: none;
59 | &:hover{
60 | text-decoration: none;
61 | }
62 | }
63 |
64 | input,textarea{
65 | outline: none;
66 | }
67 |
--------------------------------------------------------------------------------
/Web/src/assets/utils/axios.js:
--------------------------------------------------------------------------------
1 | import { baseUrl } from "./env";
2 | import axios from "axios";
3 | const service = axios.create({
4 | baseURL : baseUrl,
5 | })
6 |
7 | //请求拦截器
8 | service.interceptors.request.use(
9 | config => {
10 | return config
11 | },
12 | error => {
13 | console.log(error)
14 | return Promise.reject()
15 | }
16 | )
17 |
18 | //相应拦截器
19 | service.interceptors.response.use(
20 | response => {
21 | if(response.status == 200){
22 | return response.data
23 | }else{
24 | Promise.reject()
25 | }
26 | },
27 | error => {
28 | console.log(error)
29 | return Promise.reject()
30 | }
31 | )
32 | export default service
--------------------------------------------------------------------------------
/Web/src/assets/utils/data.js:
--------------------------------------------------------------------------------
1 | //墙的性质
2 | export const wallType = [{
3 | name : '留言墙',
4 | slogan : '很多事情值得记录,当然也值得回味'
5 | },{
6 | name : '照片墙',
7 | slogan : '多事情值得记录,当然也值得回味'
8 | }]
9 | //分类标签
10 | export const label = [
11 | ['留言','目标','理想','过去','将来','爱情','亲情','友情','秘密','信条','无题'],
12 | ['我','ta','喜欢的','有意义的','值得纪念的','母校','生活','天空','我在的城市','大海','无题']
13 | ]
14 | //卡片背景色
15 | export const cardColor = [
16 | 'rgba(252,175,162,0.30)',
17 | 'rgba(255,227,148,0.30)',
18 | 'rgba(146,230,245,0.30)',
19 | 'rgba(168,237,138,0.30)',
20 | 'rgba(202,167,247,0.30)',
21 | 'rgba(212,212,212,0.30)',
22 |
23 | ]
24 | export const cardColorBlock = [
25 | 'rgba(252,175,162,0.30)',
26 | 'rgba(255,227,148,0.30)',
27 | 'rgba(146,230,245,0.30)',
28 | 'rgba(168,237,138,0.30)',
29 | 'rgba(202,167,247,0.30)',
30 |
31 | ]
32 | //评论头像背景
33 | export const portrait = [
34 | 'linear-gradient(180deg,#FFA9D9 0%,#E83D3D 100%)',
35 | 'linear-gradient(180deg,#FFA7EB 0%,#F026A8 100%)',
36 | 'linear-gradient(180deg,#F5A8FF 0%,#BF23E5 100%)',
37 | 'linear-gradient(180deg,#DFA1FF 0%,#9A36F0 100%)',
38 | 'linear-gradient(180deg,#C9AAFF 0%,#6D3CF5 100%)',
39 | 'linear-gradient(180deg,#9EAAFF 0%,#3846F4 100%)',
40 | 'linear-gradient(180deg,#8CD8FF 0%,#2A6AF0 100%)',
41 | 'linear-gradient(180deg,#7BE7FF 2%,#1E85E2 100%)',
42 | 'linear-gradient(180deg,#92FDFF 0%,#14B2DD 100%)',
43 | 'linear-gradient(180deg,#89FED8 0%,#18C997 100%)',
44 | 'linear-gradient(180deg,#D7FFA7 0%,#5ED52A 100%)',
45 | 'linear-gradient(180deg,#FFED48 0%,#FD9E16 100%)',
46 | 'linear-gradient(180deg,#FFDC83 0%,#F88816 100%)',
47 | 'linear-gradient(180deg,#FFVA8D 1%,#EB6423 100%)',
48 | ]
49 |
50 |
51 | export const none = [
52 | {
53 | url : './assets/images/card.svg',
54 | msg : '还没有留言,快贴上第一张吧'
55 | },
56 | {
57 | url : './assets/images/photo.svg',
58 | msg : '还没有照片,快贴上第一张吧'
59 | }
60 | ]
61 | // //开发环境配置
62 | // export const none = [
63 | // {
64 | // url : '/src/assets/images/card.svg',
65 | // msg : '还没有留言,快贴上第一张吧'
66 | // },
67 | // {
68 | // url : '/src/assets/images/photo.svg',
69 | // msg : '还没有照片,快贴上第一张吧'
70 | // }
71 | // ]
--------------------------------------------------------------------------------
/Web/src/assets/utils/env.js:
--------------------------------------------------------------------------------
1 | let baseUrl = ''
2 | let routerMode = 'hash'
3 | let avatarUrl = ''
4 | let baseImgPath
5 | if(process.env.NODE_ENV == 'development'){
6 | baseUrl = 'http://localhost:3000/walls'
7 | baseImgPath = 'http://localhost:3000'
8 | avatarUrl = 'http://img.5i21.cn/LightPicture/2022/10/eeaaaa6df26aefe5.jpg'
9 | }else{
10 | // 此处只需要修改api.5i21.cn为你的后端地址
11 | baseUrl = 'https://api.5i21.cn/walls'
12 | // 此处只需要修改api.5i21.cn为你的后端地址
13 | baseImgPath = 'https://api.5i21.cn'
14 | // 此处需要修改为自己的头像地址
15 | avatarUrl = 'http://img.5i21.cn/LightPicture/2022/10/eeaaaa6df26aefe5.jpg'
16 | }
17 | export {
18 | baseUrl,
19 | routerMode,
20 | baseImgPath,
21 | avatarUrl
22 | }
--------------------------------------------------------------------------------
/Web/src/assets/utils/methods.js:
--------------------------------------------------------------------------------
1 | //时间方法
2 | export const dateTransform = (e) => {
3 | let d = new Date(e)
4 |
5 | let Y = d.getFullYear()
6 | let M = d.getMonth() + 1
7 | let D = d.getDate()
8 | if (D < 10) {
9 | D = '0' + D
10 | }
11 | if (M < 10) {
12 | M = '0' + M
13 | }
14 | let date = Y + '.' + M + '.' + D
15 | return date
16 | }
17 | //时间方法
18 | export const getObjectURL = (file) => {
19 | var url = null
20 | if (window.createObjectURL != undefined) {
21 | url = window.createObjectURL(file)
22 | } else if (window.URL != undefined) {
23 | url = window.URL.createObjectURL(file)
24 | } else if (window.webkitURL != undefined) {
25 | url = window.webkitURL.createObjectURL(file)
26 | }
27 | return url
28 | }
--------------------------------------------------------------------------------
/Web/src/assets/views/WallMessage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ wallType[ids].name }}
4 |
{{ wallType[ids].slogan }}
5 |
6 |
全部
7 |
10 | {{ e }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
![]()
25 |
{{ none[ids].msg }}
26 |
27 |
28 |
29 |
30 |
31 |
加载中....
32 |
33 |
34 |
35 | 没有更多....
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
292 |
--------------------------------------------------------------------------------
/Web/src/assets/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
29 |
--------------------------------------------------------------------------------
/Web/src/components/KMR/index.js:
--------------------------------------------------------------------------------
1 | import Message from './message/message'
2 | export default {
3 | install(app){
4 | app.config.globalProperties.Modal = Message
5 | }
6 | }
--------------------------------------------------------------------------------
/Web/src/components/KMR/message/IMessage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ message }}
7 |
8 |
9 |
10 |
11 |
44 |
--------------------------------------------------------------------------------
/Web/src/components/KMR/message/message.js:
--------------------------------------------------------------------------------
1 | import { createVNode,render } from "vue";
2 | import iMessage from './iMessage.vue'
3 | const divVNode = createVNode('div',{class : 'xtx-message-container'})
4 | render(divVNode,document.body)
5 | const div = divVNode.el
6 | const IMessage = ({message,type}) => {
7 | const comVNode = createVNode(iMessage,{message,type})
8 | render(comVNode,div)
9 | setTimeout(()=>{
10 | render(null,div)
11 | },6000)
12 | }
13 | export default IMessage
--------------------------------------------------------------------------------
/Web/src/components/mobile/CardDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
11 |
12 |
19 |
评论{{ cards.comcount[0].count }}
20 |
33 |
34 |
35 |
36 |
37 |
127 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/IModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
29 |
30 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/Ibutton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/NewCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
30 |
31 |
免责声明
32 |
33 | 一刻时光是本人独自开发的,为便于与用户交流的留言平台。请不要利用此平台服务制作、上传、下载、复制、发布、传播或者转载如下内容:
34 | 1、反对宪法所确定的基本原则的;
35 | 2、危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家 统一的;
36 | 3、损害国家荣誉和利益的;
37 | 4、煽动民族仇恨、民族歧视,破坏民族团结的;
38 | 5、破坏国家宗教政策,宣扬邪教和封建迷信的;
39 | 6、散布谣言,扰乱社会秩序,破坏社会稳定的;
40 | 7、散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
41 | 8、侮辱或者诽谤他人,侵害他人合法权益的;
42 | 9、含有法律、行政法规禁止的其他内容的信息。
43 |
44 |
45 |
46 | 丢弃
47 | 确定
48 |
49 |
50 |
51 |
180 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/NodeCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ dateTransform(card.moment) }}
5 |
{{ label[card.type][card.label]}}
6 |
7 |
8 | {{ card.message }}
9 |
10 |
25 |
26 |
27 |
68 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/PhotoCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
8 | {{ photo.like[0].count }}
9 |
10 |
11 |
12 |
13 |
52 |
53 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/TopBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
19 |
34 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/WallMessage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
全部
5 |
7 | {{ e }}
8 |
9 |
10 |
{{ wallType[ids].name }}
11 |
{{ wallType[ids].slogan }}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
![]()
28 |
{{ none[ids].msg }}
29 |
30 |
31 |
32 |
33 |
34 |
加载中....
35 |
36 |
37 |
38 | 没有更多....
39 |
40 |
41 |
42 |
43 |
44 |
233 |
234 |
387 |
--------------------------------------------------------------------------------
/Web/src/components/mobile/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
26 |
--------------------------------------------------------------------------------
/Web/src/components/pc/CardDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
16 |
评论{{ cards.comcount[0].count }}
17 |
30 |
31 |
32 |
33 |
34 |
123 |
--------------------------------------------------------------------------------
/Web/src/components/pc/FootBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/Web/src/components/pc/IModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
29 |
30 |
--------------------------------------------------------------------------------
/Web/src/components/pc/Ibutton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/Web/src/components/pc/NewCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
30 |
31 |
免责声明
32 |
33 | 一刻时光是本人独自开发的,为便于与用户交流的留言平台。请不要利用此平台服务制作、上传、下载、复制、发布、传播或者转载如下内容:
34 | 1、反对宪法所确定的基本原则的;
35 | 2、危害国家安全,泄露国家秘密,颠覆国家政权,破坏国家 统一的;
36 | 3、损害国家荣誉和利益的;
37 | 4、煽动民族仇恨、民族歧视,破坏民族团结的;
38 | 5、破坏国家宗教政策,宣扬邪教和封建迷信的;
39 | 6、散布谣言,扰乱社会秩序,破坏社会稳定的;
40 | 7、散布淫秽、色情、赌博、暴力、凶杀、恐怖或者教唆犯罪的;
41 | 8、侮辱或者诽谤他人,侵害他人合法权益的;
42 | 9、含有法律、行政法规禁止的其他内容的信息。
43 |
44 |
45 |
46 | 丢弃
47 | 确定
48 |
49 |
50 |
51 |
180 |
--------------------------------------------------------------------------------
/Web/src/components/pc/NodeCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ dateTransform(card.moment) }}
5 |
{{ label[card.type][card.label]}}
6 |
7 |
8 | {{ card.message }}
9 |
10 |
25 |
26 |
27 |
68 |
--------------------------------------------------------------------------------
/Web/src/components/pc/PhotoCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
6 |
8 | {{ photo.like[0].count }}
9 |
10 |
11 |
12 |
13 |
52 |
53 |
--------------------------------------------------------------------------------
/Web/src/components/pc/TopBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
一刻时光
6 |
7 |
11 |
12 |
13 |
![苦苦的码人]()
14 |
15 |
16 |
17 |
18 |
19 |
36 |
--------------------------------------------------------------------------------
/Web/src/components/pc/Viewer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
![]()
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
52 |
--------------------------------------------------------------------------------
/Web/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from '@/router'
4 | import store from '@/store'
5 | import KMR from './components/KMR/index'
6 | const app = createApp(App)
7 | app.use(router)
8 | app.use(store)
9 | app.use(KMR)
10 | app.mount('#app')
11 |
--------------------------------------------------------------------------------
/Web/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import path from 'path'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | base : './',
8 | plugins: [vue()],
9 | resolve : {
10 | alias : {
11 | '@' : path.resolve(__dirname,'./src/assets'),
12 | '~' : path.resolve(__dirname,'./src')
13 | }
14 | },
15 | css: {
16 | // css预处理器
17 | preprocessorOptions: {
18 | less: {
19 | charset: false,
20 | additionalData: '@import "./src/assets/styles/common.less";',
21 | },
22 | },
23 | },
24 |
25 | })
26 |
--------------------------------------------------------------------------------
{{ e.name }}
26 |{{ dateTransform(e.moment)}}
27 |