优化首页展示数据

This commit is contained in:
mayongjian
2024-09-08 03:36:25 +08:00
parent 7560f209d8
commit 935387a6f7
48 changed files with 249 additions and 74 deletions

8
.env.development Executable file
View File

@@ -0,0 +1,8 @@
# 页面标题
VITE_APP_TITLE = 红薯
# 开发环境配置
VITE_APP_ENV = 'development'
# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'

11
.env.production Executable file
View File

@@ -0,0 +1,11 @@
# 页面标题
VITE_APP_TITLE = 红薯
# 生产环境配置
VITE_APP_ENV = 'production'
# 若依管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'
# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip

14
.eslintignore Normal file
View File

@@ -0,0 +1,14 @@
dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md
src/assets
.eslintrc.cjs
.prettierrc.cjs
.stylelintrc.cjs

27
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,27 @@
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-essential"
],
"overrides": [
],
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"vue"
],
"rules": {
'vue/multi-word-component-names': "off",
"@typescript-eslint/no-explicit-any": ["off"]
}
}

64
.gitignore vendored
View File

@@ -1,51 +1,23 @@
###################################################################### # Compiled class file
# Build Tools *.class
.gradle # Log file
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log *.log
*.xml.versionsBackup
*.swp
!*/build/*.java # BlueJ files
!*/build/*.html *.ctxt
!*/build/*.xml
node_modules # Mobile Tools for Java (J2ME)
*.idea .mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

10
.prettierignore Normal file
View File

@@ -0,0 +1,10 @@
dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md
src/assets

37
.prettierrc.cjs Normal file
View File

@@ -0,0 +1,37 @@
module.exports = {
// (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
arrowParens: "always",
// 开始标签的右尖括号是否跟随在最后一行属性末尾默认false
bracketSameLine: false,
// 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
bracketSpacing: true,
// 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
embeddedLanguageFormatting: "auto",
// 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
htmlWhitespaceSensitivity: "css",
// 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记默认false
insertPragma: false,
// 在 JSX 中使用单引号替代双引号默认false
jsxSingleQuote: false,
// 每行最多字符数量,超出换行(默认80)
printWidth: 120,
// 超出打印宽度 (always | never | preserve )
proseWrap: "preserve",
// 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
quoteProps: "as-needed",
// 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件默认false
requirePragma: false,
// 结尾添加分号
semi: true,
// 使用单引号 (true:单引号;false:双引号)
singleQuote: false,
// 缩进空格数默认2个空格
tabWidth: 2,
// 元素末尾是否加逗号默认es5: ES5中的 objects, arrays 等会添加逗号TypeScript 中的 type 后不加逗号
trailingComma: "es5",
// 指定缩进方式空格或tab默认false即使用空格
useTabs: false,
// vue 文件中是否缩进 <style> 和 <script> 标签,默认 false
vueIndentScriptAndStyle: false,
};

0
src/assets/images/3.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

0
src/assets/images/admin/admin-album.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

0
src/assets/images/admin/admin-category.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 781 KiB

After

Width:  |  Height:  |  Size: 781 KiB

0
src/assets/images/admin/admin-comment.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 440 KiB

After

Width:  |  Height:  |  Size: 440 KiB

0
src/assets/images/admin/admin-data.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB

0
src/assets/images/admin/admin-log.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 635 KiB

After

Width:  |  Height:  |  Size: 635 KiB

0
src/assets/images/admin/admin-login.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

0
src/assets/images/admin/admin-member.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 853 KiB

After

Width:  |  Height:  |  Size: 853 KiB

0
src/assets/images/admin/admin-note.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 862 KiB

After

Width:  |  Height:  |  Size: 862 KiB

0
src/assets/images/app/app-follow.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 3.6 MiB

0
src/assets/images/app/app-hot.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

0
src/assets/images/app/app-index.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

0
src/assets/images/app/app-login.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

0
src/assets/images/app/app-main.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 939 KiB

After

Width:  |  Height:  |  Size: 939 KiB

0
src/assets/images/app/app-message.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB

0
src/assets/images/app/app-push.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 178 KiB

0
src/assets/images/app/app-search.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

0
src/assets/images/app/app-trend.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 986 KiB

After

Width:  |  Height:  |  Size: 986 KiB

0
src/assets/images/app/app-user.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

0
src/assets/images/reward.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 731 KiB

After

Width:  |  Height:  |  Size: 731 KiB

0
src/assets/images/web/web-dashboard.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.7 MiB

After

Width:  |  Height:  |  Size: 5.7 MiB

0
src/assets/images/web/web-follow.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 467 KiB

After

Width:  |  Height:  |  Size: 467 KiB

0
src/assets/images/web/web-login.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 3.6 MiB

0
src/assets/images/web/web-message.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 326 KiB

After

Width:  |  Height:  |  Size: 326 KiB

0
src/assets/images/web/web-publish.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 304 KiB

0
src/assets/images/web/web-search.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.0 MiB

After

Width:  |  Height:  |  Size: 5.0 MiB

0
src/assets/images/web/web-trends.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1016 KiB

After

Width:  |  Height:  |  Size: 1016 KiB

0
src/assets/images/web/web-user.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.7 MiB

After

Width:  |  Height:  |  Size: 3.7 MiB

View File

@@ -27,7 +27,13 @@
v-if="oneComment.isLike" v-if="oneComment.isLike"
@click="likeComment(oneComment, -1, oneIndex, -1)" @click="likeComment(oneComment, -1, oneIndex, -1)"
> >
<i class="iconfont icon-follow-fill" style="width: 1em; height: 1em"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: oneComment.isLike ? 'red' : 'black' }"
v-if="oneComment.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
<span class="count">{{ oneComment.likeCount }}</span> <span class="count">{{ oneComment.likeCount }}</span>
</span> </span>
<span class="like-wrapper" v-else @click="likeComment(oneComment, 1, oneIndex, -1)"> <span class="like-wrapper" v-else @click="likeComment(oneComment, 1, oneIndex, -1)">
@@ -75,7 +81,13 @@
v-if="twoComment.isLike" v-if="twoComment.isLike"
@click="likeComment(twoComment, -1, oneIndex, twoIndex)" @click="likeComment(twoComment, -1, oneIndex, twoIndex)"
> >
<i class="iconfont icon-follow-fill" style="width: 1em; height: 1em"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: oneComment.isLike ? 'red' : 'black' }"
v-if="oneComment.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
<span class="count">{{ twoComment.likeCount }}</span> <span class="count">{{ twoComment.likeCount }}</span>
</span> </span>
<span class="like-wrapper" @click="likeComment(twoComment, 1, oneIndex, twoIndex)" v-else> <span class="like-wrapper" @click="likeComment(twoComment, 1, oneIndex, twoIndex)" v-else>

View File

@@ -67,7 +67,13 @@
<span class="name">{{ item.username }}</span> <span class="name">{{ item.username }}</span>
</a> </a>
<span class="like-wrapper like-active"> <span class="like-wrapper like-active">
<i class="iconfont icon-follow" style="width: 1em; height: 1em"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: item.isLike ? 'red' : 'black' }"
v-if="item.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
<span class="count">{{ item.likeCount }}</span> <span class="count">{{ item.likeCount }}</span>
</span> </span>
</div> </div>
@@ -125,7 +131,6 @@ const currentPage = ref(1);
const pageSize = 10; const pageSize = 10;
const nid = ref(""); const nid = ref("");
const mainShow = ref(false); const mainShow = ref(false);
const isCurrentUser = ref(false);
const userStore = useUserStore(); const userStore = useUserStore();
const currentUid = userStore.getUserInfo().id; const currentUid = userStore.getUserInfo().id;

View File

@@ -80,7 +80,13 @@
<span class="name">{{ item.username }}</span> <span class="name">{{ item.username }}</span>
</a> </a>
<span class="like-wrapper like-active"> <span class="like-wrapper like-active">
<i class="iconfont icon-follow" style="width: 1em; height: 1em"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: item.isLike ? 'red' : 'black' }"
v-if="item.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
<span class="count">{{ item.likeCount }}</span> <span class="count">{{ item.likeCount }}</span>
</span> </span>
</div> </div>

View File

@@ -18,28 +18,38 @@
{{ item.content }} {{ item.content }}
</div> </div>
<div class="interaction-imgs" @click="toMain(item.nid)"> <div class="interaction-imgs" @click="toMain(item.nid)">
<div class="details-box" v-for="(url, index) in item.imgUrls" :key="index"> <!-- 限制最多显示三张图片 -->
<div
class="details-box"
v-for="(url, index) in item.imgUrls.slice(0, 3)"
:key="index"
style="position: relative"
>
<el-image <el-image
v-if="!item.isLoading" v-if="!item.isLoading"
:src="url" :src="url"
@load="handleLoad(item)" @load="handleLoad(item)"
style="height: 230px; width: 100%" style="height: 230px; width: 100%"
> ></el-image>
</el-image>
<el-image <el-image
v-else v-else
:src="url" :src="url"
class="note-img animate__animated animate__fadeIn animate__delay-0.5s" class="note-img animate__animated animate__fadeIn animate__delay-0.5s"
fit="cover" fit="cover"
> style="height: 230px; width: 100%"
</el-image> ></el-image>
<!-- 在第三张图片上显示覆盖标识 -->
<div v-if="index === 2 && item.imgUrls.length > 3" class="overlay">
<span class="more-text">+{{ item.imgUrls.length - 3 }}</span>
</div>
</div> </div>
</div> </div>
<div class="interaction-footer"> <div class="interaction-footer">
<div class="icon-item"> <div class="icon-item">
<i <i
class="iconfont icon-follow-fill" class="iconfont icon-follow-fill"
style="width: 1em; height: 1em" :style="{ width: '1em', height: '1em', color: item.isLike ? 'red' : 'black' }"
@click="like(item.nid, item.uid, index, -1)" @click="like(item.nid, item.uid, index, -1)"
v-if="item.isLike" v-if="item.isLike"
> >
@@ -79,7 +89,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ChatRound, More, Refresh } from "@element-plus/icons-vue"; import { ChatRound, More } from "@element-plus/icons-vue";
import { ref } from "vue"; import { ref } from "vue";
import { getFollowTrend } from "@/api/follower"; import { getFollowTrend } from "@/api/follower";
import { formateTime, refreshTab } from "@/utils/util"; import { formateTime, refreshTab } from "@/utils/util";
@@ -185,6 +195,28 @@ initData();
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.details-box {
position: relative;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
border-radius: 10px;
}
.more-text {
color: white;
font-size: 20px;
}
.container { .container {
flex: 1; flex: 1;
padding: 0 24px; padding: 0 24px;
@@ -275,7 +307,7 @@ initData();
width: 100%; width: 100%;
height: 230px; height: 230px;
display: flex; display: flex;
border-radius: 4px; border-radius: 10px;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;

13
src/pages/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>红薯</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -202,7 +202,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { Search, Sunny, Moon, Close, House, Star, Bell, ArrowRight, More, CirclePlus } from "@element-plus/icons-vue"; import { Search, Sunny, Moon, Close, House, Star, Bell, ArrowRight, CirclePlus } from "@element-plus/icons-vue";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
import Login from "@/pages/login.vue"; import Login from "@/pages/login.vue";
import { ref, watch, onMounted, computed, watchEffect } from "vue"; import { ref, watch, onMounted, computed, watchEffect } from "vue";

View File

@@ -90,7 +90,13 @@
> >
<span class="collect-wrapper"> <span class="collect-wrapper">
<span class="like-lottie" v-if="noteInfo.isLike" @click="likeOrCollection(1, -1)"> <span class="like-lottie" v-if="noteInfo.isLike" @click="likeOrCollection(1, -1)">
<i class="iconfont icon-follow-fill" style="width: 0.8em; height: 0.8em; color: #333"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: noteInfo.isLike ? 'red' : 'black' }"
v-if="noteInfo.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
</span> </span>
<span class="like-lottie" v-else @click="likeOrCollection(1, 1)"> <span class="like-lottie" v-else @click="likeOrCollection(1, 1)">
<i class="iconfont icon-follow" style="width: 0.8em; height: 0.8em; color: #333"></i> <i class="iconfont icon-follow" style="width: 0.8em; height: 0.8em; color: #333"></i>

View File

@@ -12,14 +12,22 @@
<a class>{{ item.username }}</a> <a class>{{ item.username }}</a>
</div> </div>
<div class="interaction-hint"> <div class="interaction-hint">
<span>开始关注&nbsp;</span><span>{{ item.time }}</span> <span>开始关注&nbsp;</span><span>{{ item.time }}</span>
</div> </div>
</div> </div>
<div class="extra"> <div class="extra">
<el-button type="info" round size="large" v-if="item.isFollow" @click="follow(item.uid, index, 1)" <el-button
class="button"
type="info"
round
size="large"
v-if="item.isFollow"
@click="follow(item.uid, index, 1)"
>互相关注</el-button >互相关注</el-button
> >
<el-button type="danger" round size="large" v-else @click="follow(item.uid, index, -1)">回关</el-button> <el-button class="button" type="danger" round size="large" v-else @click="follow(item.uid, index, -1)"
>回关</el-button
>
</div> </div>
</div> </div>
</li> </li>
@@ -175,6 +183,12 @@ textarea {
} }
} }
.button {
width: 100px;
height: 40px;
font-size: 14px;
}
.extra { .extra {
min-width: 48px; min-width: 48px;
flex-shrink: 0; flex-shrink: 0;

View File

@@ -12,10 +12,10 @@
<a class>{{ item.username }}</a> <a class>{{ item.username }}</a>
</div> </div>
<div class="interaction-hint"> <div class="interaction-hint">
<span v-if="item.type == 1">赞了的笔记</span> <span v-if="item.type == 1">赞了的笔记</span>
<span v-if="item.type == 2">赞了的评论</span> <span v-if="item.type == 2">赞了的评论</span>
<span v-if="item.type == 3">收藏的笔记</span> <span v-if="item.type == 3">收藏的笔记</span>
<span v-if="item.type == 4">赞了{{ item.content }}专辑</span> <span v-if="item.type == 4">赞了{{ item.content }}专辑</span>
&nbsp;<span>{{ item.time }}</span> &nbsp;<span>{{ item.time }}</span>
</div> </div>
<!-- <div class="interaction-content"> <!-- <div class="interaction-content">

View File

@@ -107,7 +107,13 @@
<span class="name">{{ item.username }}</span> <span class="name">{{ item.username }}</span>
</a> </a>
<span class="like-wrapper like-active"> <span class="like-wrapper like-active">
<i class="iconfont icon-follow" style="width: 1em; height: 1em"></i> <i
class="iconfont icon-follow-fill"
:style="{ width: '1em', height: '1em', color: item.isLike ? 'red' : 'black' }"
v-if="item.isLike"
>
</i>
<i class="iconfont icon-follow" style="width: 1em; height: 1em" v-else></i>
<span class="count">{{ item.likeCount }}</span> <span class="count">{{ item.likeCount }}</span>
</span> </span>
</div> </div>

View File

@@ -56,7 +56,7 @@ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes, routes,
}); });
router.beforeEach((to, from, next) => { router.beforeEach((_to, _from, next) => {
next(); next();
}); });
export default router; export default router;

View File

@@ -2,7 +2,6 @@ import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
import { useUserStore } from "@/store/userStore"; import { useUserStore } from "@/store/userStore";
import { storage } from "./storage"; import { storage } from "./storage";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { baseURL } from "@/constant/constant";
// 刷新 token 后, 将缓存的接口重新请求一次 // 刷新 token 后, 将缓存的接口重新请求一次
// 是否正在刷新 token // 是否正在刷新 token
let isRefreshing: boolean = false; let isRefreshing: boolean = false;

View File

@@ -1,17 +1,20 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"; import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
import { resolve } from "path"; import { resolve } from "path";
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
resolve: { resolve: {
alias: { alias: {
"@": resolve(__dirname, "./src"), "@": resolve(__dirname, "./src"),
}, },
//extensions: [".ts", ".js", ".vue", ".json", ".mjs"],
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"], extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"],
}, },
// build: {
// rollupOptions: {
// input: resolve(__dirname, 'src/pages/index.html'), // 确保输入路径正确
// },
// },
// server: { // server: {
// port: 3000, // port: 3000,
// open: true, // open: true,