新增:旅拍模块

新增:看板娘
优化:聊天室脚本过滤
优化:每个IP和账号限制每天接口保存次数
优化:个别Bug修复
master
Sara 1 year ago
parent 02ec91ea1e
commit 012d5c9b91

@ -1,4 +1,4 @@
# poetry-uiVue2 # PoetizeVue2
## 网站示例 ## 网站示例
[poetize.cn](https://poetize.cn) [poetize.cn](https://poetize.cn)
@ -32,6 +32,13 @@
- 优化:前端美化 - 优化:前端美化
- 优化:资源整合 - 优化:资源整合
### 2023年7月20日更新
- 新增:旅拍模块
- 新增:看板娘
- 优化:聊天室脚本过滤
- 优化每个IP和账号限制每天接口保存次数
- 优化个别Bug修复
### 首页 ### 首页
![首页](首页.jpg) ![首页](首页.jpg)
@ -94,7 +101,7 @@ npm run build
4. 漏洞反馈欢迎提交BUG 4. 漏洞反馈欢迎提交BUG
5. 迭代升级:欢迎提好的创意 5. 迭代升级:欢迎提好的创意
群名片七天有效,如果需要请加作者好友,然后拉进交流群(请按需加群,退群后删除好友) 群名片七天有效,如果需要请加作者好友请务必Star并注明来源,然后拉进交流群(请按需加群,有问题先看文档再咨询网友,退群后删除好友)
![个人名片](Sara.jpg) ![个人名片](Sara.jpg)

@ -3,8 +3,8 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service serve",
"build": "vue-cli-service build", "build": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {

@ -8,32 +8,34 @@
unique-opened unique-opened
router> router>
<template v-for="item in items"> <template v-for="item in items">
<template v-if="item.subs"> <template v-if="isBoss || !item.isBoss">
<el-submenu :index="item.index" :key="item.index"> <template v-if="item.subs">
<template slot="title"> <el-submenu :index="item.index" :key="item.index">
<i :class="item.icon"></i> <template slot="title">
<span>{{ item.title }}</span> <i :class="item.icon"></i>
</template> <span>{{ item.title }}</span>
<template v-for="subItem in item.subs"> </template>
<el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index"> <template v-for="subItem in item.subs">
<template slot="title"> <el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
<template slot="title">
{{ subItem.title }}
</template>
<el-menu-item v-for="threeItem in subItem.subs" :key="threeItem.index" :index="threeItem.index">
{{ threeItem.title }}
</el-menu-item>
</el-submenu>
<el-menu-item v-else :index="subItem.index" :key="subItem.index">
{{ subItem.title }} {{ subItem.title }}
</template>
<el-menu-item v-for="threeItem in subItem.subs" :key="threeItem.index" :index="threeItem.index">
{{ threeItem.title }}
</el-menu-item> </el-menu-item>
</el-submenu> </template>
<el-menu-item v-else :index="subItem.index" :key="subItem.index"> </el-submenu>
{{ subItem.title }} </template>
</el-menu-item> <template v-else>
</template> <el-menu-item :index="item.index" :key="item.index">
</el-submenu> <i :class="item.icon"></i>
</template> {{ item.title }}
<template v-else> </el-menu-item>
<el-menu-item :index="item.index" :key="item.index"> </template>
<i :class="item.icon"></i>
{{ item.title }}
</el-menu-item>
</template> </template>
</template> </template>
</el-menu> </el-menu>
@ -44,46 +46,57 @@
export default { export default {
data() { data() {
return { return {
isBoss: this.$store.state.currentAdmin.isBoss,
items: [{ items: [{
icon: "el-icon-s-home", icon: "el-icon-s-home",
index: "/main", index: "/main",
title: "系统首页", title: "系统首页",
isBoss: true
}, { }, {
icon: "el-icon-s-tools", icon: "el-icon-s-tools",
index: "/webEdit", index: "/webEdit",
title: "网站设置", title: "网站设置",
isBoss: true
}, { }, {
icon: "el-icon-user-solid", icon: "el-icon-user-solid",
index: "/userList", index: "/userList",
title: "用户管理" title: "用户管理",
isBoss: true
}, { }, {
icon: "el-icon-postcard", icon: "el-icon-postcard",
index: "/postList", index: "/postList",
title: "文章管理" title: "文章管理",
isBoss: false
}, { }, {
icon: "el-icon-notebook-2", icon: "el-icon-notebook-2",
index: "/sortList", index: "/sortList",
title: "分类管理" title: "分类管理",
isBoss: true
}, { }, {
icon: "el-icon-edit-outline", icon: "el-icon-edit-outline",
index: "/commentList", index: "/commentList",
title: "评论管理" title: "评论管理",
isBoss: false
}, { }, {
icon: "el-icon-s-comment", icon: "el-icon-s-comment",
index: "/treeHoleList", index: "/treeHoleList",
title: "留言管理" title: "留言管理",
isBoss: true
}, { }, {
icon: "el-icon-paperclip", icon: "el-icon-paperclip",
index: "/resourceList", index: "/resourceList",
title: "资源管理" title: "资源管理",
isBoss: true
}, { }, {
icon: "el-icon-bank-card", icon: "el-icon-bank-card",
index: "/resourcePathList", index: "/resourcePathList",
title: "资源路径管理" title: "资源路径管理",
isBoss: true
}, { }, {
icon: "el-icon-sugar", icon: "el-icon-sugar",
index: "/loveList", index: "/loveList",
title: "表白墙管理" title: "表白墙管理",
isBoss: true
}] }]
} }
}, },

@ -70,7 +70,7 @@
destroy-on-close destroy-on-close
center> center>
<div> <div>
<uploadPicture :isAdmin="true" :prefix="resourcePath.type" @addPicture="addPicture" :maxSize="5" <uploadPicture :isAdmin="true" :prefix="resourcePath.type + 'Cover'" @addPicture="addPicture" :maxSize="5"
:maxNumber="1"></uploadPicture> :maxNumber="1"></uploadPicture>
</div> </div>
</el-dialog> </el-dialog>

@ -2,7 +2,7 @@
<div class="myFooter-wrap" v-show="showFooter"> <div class="myFooter-wrap" v-show="showFooter">
<div class="myFooter"> <div class="myFooter">
<div class="footer-title">{{$store.state.webInfo.footer}}</div> <div class="footer-title">{{$store.state.webInfo.footer}}</div>
<div class="icp">本网站由 <a href="https://poetize.cn" target="_blank">寻国记</a> 强力支持</div> <div class="icp">本网站由 <a href="https://poetize.cn" target="_blank">Poetize</a> 强力支持</div>
</div> </div>
</div> </div>
</template> </template>

@ -6,7 +6,7 @@
<div v-show="toolbar.visible" <div v-show="toolbar.visible"
@mouseenter="hoverEnter = true" @mouseenter="hoverEnter = true"
@mouseleave="hoverEnter = false" @mouseleave="hoverEnter = false"
:class="[{ enter: toolbar.enter }, { hoverEnter: (hoverEnter || this.$route.path === '/favorite') && !toolbar.enter }]" :class="[{ enter: toolbar.enter }, { hoverEnter: (hoverEnter || this.$route.path === '/favorite' || this.$route.path === '/travel') && !toolbar.enter }]"
class="toolbar-content myBetween"> class="toolbar-content myBetween">
<!-- 网站名称 --> <!-- 网站名称 -->
<div class="toolbar-title"> <div class="toolbar-title">
@ -45,6 +45,13 @@
</div> </div>
</li> </li>
<!-- 旅拍 -->
<li @click="$router.push({path: '/travel'})">
<div class="my-menu">
🌏 <span>旅拍</span>
</div>
</li>
<!-- 百宝箱 --> <!-- 百宝箱 -->
<li @click="$router.push({path: '/favorite'})"> <li @click="$router.push({path: '/favorite'})">
<div class="my-menu"> <div class="my-menu">
@ -185,6 +192,13 @@
</div> </div>
</li> </li>
<!-- 旅拍 -->
<li @click="smallMenu({path: '/travel'})">
<div>
🌏 <span>旅拍</span>
</div>
</li>
<!-- 百宝箱 --> <!-- 百宝箱 -->
<li @click="smallMenu({path: '/favorite'})"> <li @click="smallMenu({path: '/favorite'})">
<div> <div>

@ -19,6 +19,37 @@
</a> </a>
</div> </div>
<!-- 推荐文章 -->
<div v-if="!$common.isEmpty(recommendArticles)"
style="padding: 25px;border-radius: 10px;margin-top: 40px;animation: hideToShow 1s ease-in-out"
class="shadow-box background-opacity wow">
<div class="card-content2-title">
<i class="el-icon-reading card-content2-icon"></i>
<span>推荐文章</span>
</div>
<div v-for="(article, index) in recommendArticles"
:key="index"
@click="$router.push({path: '/article', query: {id: article.id}})">
<div class="aside-post-detail">
<div class="aside-post-image">
<el-image lazy class="my-el-image" :src="article.articleCover" fit="cover">
<div slot="error" class="image-slot">
<div class="error-aside-image">
{{article.username}}
</div>
</div>
</el-image>
</div>
<div class="aside-post-title">
{{ article.articleTitle }}
</div>
</div>
<div class="aside-post-date">
<i class="el-icon-date" style="color: var(--greyFont)"></i>{{ article.createTime }}
</div>
</div>
</div>
<!-- 赞赏 --> <!-- 赞赏 -->
<div class="shadow-box-mini background-opacity wow admire-box" <div class="shadow-box-mini background-opacity wow admire-box"
v-if="!$common.isEmpty(admires)"> v-if="!$common.isEmpty(admires)">
@ -78,37 +109,6 @@
</div> </div>
</div> </div>
<!-- 推荐文章 -->
<div v-if="!$common.isEmpty(recommendArticles)"
style="padding: 25px;border-radius: 10px;margin-top: 40px;animation: hideToShow 1s ease-in-out"
class="shadow-box background-opacity wow">
<div class="card-content2-title">
<i class="el-icon-reading card-content2-icon"></i>
<span>推荐文章</span>
</div>
<div v-for="(article, index) in recommendArticles"
:key="index"
@click="$router.push({path: '/article', query: {id: article.id}})">
<div class="aside-post-detail">
<div class="aside-post-image">
<el-image lazy class="my-el-image" :src="article.articleCover" fit="cover">
<div slot="error" class="image-slot">
<div class="error-aside-image">
{{article.username}}
</div>
</div>
</el-image>
</div>
<div class="aside-post-title">
{{ article.articleTitle }}
</div>
</div>
<div class="aside-post-date">
<i class="el-icon-date" style="color: var(--greyFont)"></i>{{ article.createTime }}
</div>
</div>
</div>
<!-- 微信 --> <!-- 微信 -->
<el-dialog title="赞赏" <el-dialog title="赞赏"
:visible.sync="showAdmireDialog" :visible.sync="showAdmireDialog"

@ -0,0 +1,234 @@
<template>
<div>
<div class="travel-container">
<!-- 封面 -->
<div class="travel-header my-animation-slide-top">
<!-- 背景图片 -->
<video class="index-video" autoplay="autoplay" muted="muted" loop="loop"
:src="$constant.favoriteVideo">
</video>
<div style="position: absolute;left: 20px;top: 20px">
<!-- 标题 -->
<div style="margin: 10px">
<div>
旅拍集
</div>
<div style="font-size: 36px;font-weight: bold;line-height: 1.5;margin-top: 20px">
这里是我的旅拍哦
</div>
</div>
</div>
<div style="position: absolute;left: 20px;bottom: 40px;margin: 10px">
每一张照片都是一次美好的记忆
</div>
</div>
<div class="travel-content my-animation-slide-bottom">
<!-- 标签 -->
<div class="photo-title-warp" v-if="!$common.isEmpty(photoTitleList)">
<div v-for="(item, index) in photoTitleList" :key="index"
:class="{isActive: photoPagination.classify === item.classify}"
@click="changePhotoTitle(item.classify)">
<proTag :info="item.classify+' '+item.count"
:color="$constant.before_color_list[Math.floor(Math.random() * 6)]"
style="margin: 12px">
</proTag>
</div>
</div>
<div class="photo-title">
{{photoPagination.classify}}
</div>
<photo :resourcePathList="photoList"></photo>
<div class="pagination-wrap">
<div @click="pagePhotos()" class="pagination" v-if="photoPagination.total !== photoList.length">
下一页
</div>
<div v-else style="user-select: none">
~~到底啦~~
</div>
</div>
</div>
</div>
<!-- 页脚 -->
<div style="background: var(--favoriteBg)">
<myFooter></myFooter>
</div>
</div>
</template>
<script>
const myFooter = () => import( "./common/myFooter");
const photo = () => import( "./common/photo");
const proTag = () => import( "./common/proTag");
export default {
components: {
photo,
proTag,
myFooter
},
data() {
return {
photoPagination: {
current: 1,
size: 10,
total: 0,
resourceType: "lovePhoto",
classify: ""
},
photoTitleList: [],
photoList: []
}
},
computed: {},
watch: {},
created() {
this.getPhotoTitles();
},
mounted() {
},
methods: {
getPhotoTitles() {
this.$http.get(this.$constant.baseURL + "/webInfo/listAdminLovePhoto")
.then((res) => {
if (!this.$common.isEmpty(res.data)) {
this.photoTitleList = res.data;
this.photoPagination = {
current: 1,
size: 10,
total: 0,
resourceType: "lovePhoto",
classify: this.photoTitleList[0].classify
};
this.changePhoto();
}
})
.catch((error) => {
this.$message({
message: error.message,
type: "error"
});
});
},
changePhotoTitle(classify) {
if (classify !== this.photoPagination.classify) {
this.photoPagination = {
current: 1,
size: 10,
total: 0,
resourceType: "lovePhoto",
classify: classify
};
this.photoList = [];
this.changePhoto();
}
},
pagePhotos() {
this.photoPagination.current = this.photoPagination.current + 1;
this.changePhoto();
},
changePhoto() {
this.$http.post(this.$constant.baseURL + "/webInfo/listResourcePath", this.photoPagination)
.then((res) => {
if (!this.$common.isEmpty(res.data)) {
this.photoList = this.photoList.concat(res.data.records);
this.photoPagination.total = res.data.total;
}
})
.catch((error) => {
this.$message({
message: error.message,
type: "error"
});
});
}
}
}
</script>
<style scoped>
.travel-container {
padding: 25px;
background: var(--favoriteBg);
}
.travel-header {
margin: 60px auto 30px;
height: 300px;
position: relative;
overflow: hidden;
border-radius: 20px;
max-width: 1200px;
color: var(--white);
user-select: none;
}
.index-video {
width: 100%;
height: 100%;
object-fit: cover;
background: var(--lightGreen);
}
.travel-content {
margin: 0 auto;
max-width: 1200px;
}
.photo-title-warp {
max-width: 1150px;
margin: 50px auto;
padding: 20px;
border-radius: 10px;
display: flex;
flex-wrap: wrap;
}
.isActive {
animation: scale 2.5s ease-in-out infinite;
}
.photo-title {
text-align: center;
font-size: 30px;
font-weight: 700;
line-height: 80px;
letter-spacing: 2px;
}
.pagination-wrap {
display: flex;
justify-content: center;
margin-top: 40px;
}
.pagination {
padding: 13px 15px;
border: 1px solid var(--lightGray);
border-radius: 3rem;
color: var(--greyFont);
width: 100px;
user-select: none;
cursor: pointer;
text-align: center;
}
@media screen and (max-width: 1150px) {
.photo-title-warp {
max-width: 780px;
}
}
</style>

@ -8,7 +8,7 @@ import common from './utils/common'
import constant from './utils/constant' import constant from './utils/constant'
import mavonEditor from 'mavon-editor' import mavonEditor from 'mavon-editor'
//引入js //引入js
//import './utils/live2d' import './utils/live2d'
import './utils/title' import './utils/title'
//引入css //引入css
import './assets/css/animation.css' import './assets/css/animation.css'

@ -36,6 +36,10 @@ const routes = [
path: "/favorite", path: "/favorite",
name: "favorite", name: "favorite",
component: () => import('../components/favorite') component: () => import('../components/favorite')
}, {
path: "/travel",
name: "travel",
component: () => import('../components/travel')
}, { }, {
path: "/message", path: "/message",
name: "message", name: "message",

@ -0,0 +1,98 @@
if (document.querySelector(".author-content.author-content-item.single")) {
const canvas = document.createElement("canvas");
canvas.id = "header_canvas";
canvas.style.position = "absolute";
canvas.style.bottom = "0";
canvas.width = 844;
canvas.height = 346;
document.querySelector(".author-content.author-content-item.single").appendChild(canvas);
const parent = document.querySelector(".author-content.author-content-item.single").parentNode;
parent.className = "thumbnail_canvas";
(function () {
var canvas,
ctx,
width,
height,
bubbles,
animateHeader = true;
initHeader();
function initHeader() {
canvas = document.getElementById("header_canvas");
window_resize();
if (canvas) {
ctx = canvas.getContext("2d");
//建立泡泡
bubbles = [];
var num = width * 0.04; //气泡数量
for (var i = 0; i < num; i++) {
var c = new Bubble();
bubbles.push(c);
}
animate();
}
}
function animate() {
if (animateHeader) {
ctx.clearRect(0, 0, width, height);
for (var i in bubbles) {
bubbles[i].draw();
}
}
requestAnimationFrame(animate);
}
function window_resize() {
//canvas铺满窗口
//width = window.innerWidth;
//height = window.innerHeight;
//如果需要铺满内容可以换下面这个
const panel = document.querySelector(".thumbnail_canvas");
if (panel) {
width = panel.offsetWidth;
height = panel.offsetHeight;
canvas.width = width;
canvas.height = height;
}
}
window.onresize = function () {
window_resize();
};
function Bubble() {
var _this = this;
(function () {
_this.pos = {};
init();
})();
function init() {
_this.pos.x = Math.random() * width;
_this.pos.y = height + Math.random() * 100;
_this.alpha = 0.1 + Math.random() * 0.5; //气泡透明度
_this.alpha_change = 0.0002 + Math.random() * 0.0005; //气泡透明度变化速度
_this.scale = 0.2 + Math.random() * 0.8; //气泡大小
_this.scale_change = Math.random() * 0.002; //气泡大小变化速度
_this.speed = 0.1 + Math.random() * 0.4; //气泡上升速度
}
//气泡
this.draw = function () {
if (_this.alpha <= 0) {
init();
}
_this.pos.y -= _this.speed;
_this.alpha -= _this.alpha_change;
_this.scale += _this.scale_change;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.scale * 10, 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(255,255,255," + _this.alpha + ")";
ctx.fill();
};
}
})();
}

@ -1,5 +1,6 @@
module.exports = { module.exports = {
devServer: { devServer: {
port: 80 port: 80
} },
productionSourceMap: false
} }

Loading…
Cancel
Save