feat: 新增钓鱼日志组件并优化钓鱼页面交互
新增钓鱼日志组件,用于展示钓鱼记录。优化钓鱼页面的交互体验,增加动画效果和状态提示。同时,修复了请求拦截器中的错误处理逻辑,并改进了登录和注册页面的UI设计。main
parent
5cde67672b
commit
709cf29b6d
@ -0,0 +1,29 @@
|
|||||||
|
# 构建阶段
|
||||||
|
FROM node:18-alpine as builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制项目文件
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# 复制源代码
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 构建项目
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# 生产阶段
|
||||||
|
FROM nginx:1.25.3-alpine
|
||||||
|
|
||||||
|
# 从构建阶段复制构建结果到nginx目录
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# 复制nginx配置
|
||||||
|
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# 启用gzip压缩
|
||||||
|
gzip on;
|
||||||
|
gzip_min_length 1k;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_disable "MSIE [1-6]\.";
|
||||||
|
|
||||||
|
# 设置根目录
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# 启用 CORS
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
add_header 'Access-Control-Allow-Origin' '*';
|
||||||
|
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||||
|
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
|
||||||
|
}
|
||||||
|
|
||||||
|
# 处理 404 页面
|
||||||
|
error_page 404 /index.html;
|
||||||
|
|
||||||
|
# 缓存静态资源
|
||||||
|
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|json)$ {
|
||||||
|
expires max;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,170 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="400" height="300" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- 渐变定义 -->
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="skyGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#87CEEB"/>
|
||||||
|
<stop offset="100%" style="stop-color:#4FC3F7"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="waterGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#29B6F6" stop-opacity="0.8"/>
|
||||||
|
<stop offset="100%" style="stop-color:#0288D1" stop-opacity="0.9"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="groundGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#8D6E63"/>
|
||||||
|
<stop offset="100%" style="stop-color:#5D4037"/>
|
||||||
|
</linearGradient>
|
||||||
|
<!-- 水波纹动画效果 -->
|
||||||
|
<filter id="water-ripple">
|
||||||
|
<feTurbulence type="turbulence" baseFrequency="0.01" numOctaves="3" result="turbulence">
|
||||||
|
<animate attributeName="baseFrequency" dur="30s" values="0.01;0.015;0.01" repeatCount="indefinite"/>
|
||||||
|
</feTurbulence>
|
||||||
|
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="10" xChannelSelector="R" yChannelSelector="G"/>
|
||||||
|
</filter>
|
||||||
|
<!-- 光影效果 -->
|
||||||
|
<filter id="soft-light">
|
||||||
|
<feGaussianBlur in="SourceGraphic" stdDeviation="2" result="blur"/>
|
||||||
|
<feComposite in="SourceGraphic" in2="blur" operator="arithmetic" k1="1" k2="0.5" k3="0" k4="0"/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- 天空背景 -->
|
||||||
|
<rect x="0" y="0" width="400" height="200" fill="url(#skyGradient)"/>
|
||||||
|
|
||||||
|
<!-- 云朵 -->
|
||||||
|
<g>
|
||||||
|
<path d="M50,50 q20,-20 40,0 t40,0 t40,0 q20,20 0,40 h-120 q-20,-20 0,-40" fill="white" opacity="0.8">
|
||||||
|
<animateTransform attributeName="transform" type="translate" from="-100,0" to="500,0" dur="60s" repeatCount="indefinite"/>
|
||||||
|
</path>
|
||||||
|
<path d="M80,80 q15,-15 30,0 t30,0 t30,0 q15,15 0,30 h-90 q-15,-15 0,-30" fill="white" opacity="0.6">
|
||||||
|
<animateTransform attributeName="transform" type="translate" from="-100,0" to="500,0" dur="45s" repeatCount="indefinite"/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 远处的树木和山丘 -->
|
||||||
|
<g transform="translate(20,150)">
|
||||||
|
<path d="M0,0 c-20,-40 -15,-45 0,-60 c15,15 20,20 0,60" fill="#2E7D32"/>
|
||||||
|
<rect x="-2" y="0" width="4" height="10" fill="#5D4037"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(350,140)">
|
||||||
|
<path d="M0,0 c-25,-50 -20,-55 0,-70 c20,15 25,20 0,70" fill="#2E7D32"/>
|
||||||
|
<rect x="-3" y="0" width="6" height="15" fill="#5D4037"/>
|
||||||
|
</g>
|
||||||
|
<path d="M320,160 Q360,140 400,160" fill="#8D6E63" opacity="0.6"/>
|
||||||
|
|
||||||
|
<!-- 河岸和石头 -->
|
||||||
|
<path d="M0,180 Q100,170 200,180 T400,180 L400,200 L0,200 Z" fill="url(#groundGradient)"/>
|
||||||
|
<g transform="translate(100,175)">
|
||||||
|
<path d="M0,0 Q5,-5 10,0 Q15,-3 20,0" fill="#795548"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(250,178)">
|
||||||
|
<path d="M0,0 Q8,-8 16,0 Q24,-5 32,0" fill="#795548"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 草丛装饰 -->
|
||||||
|
<g transform="translate(30,170)">
|
||||||
|
<path d="M0,0 Q5,-12 10,0 M5,0 Q10,-18 15,0 M10,0 Q15,-10 20,0" stroke="#4CAF50" stroke-width="2" fill="none"/>
|
||||||
|
<path d="M2,-2 Q7,-8 12,-2" stroke="#81C784" stroke-width="1.5" fill="none"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(150,175)">
|
||||||
|
<path d="M0,0 Q5,-15 10,0 M5,0 Q10,-20 15,0 M10,0 Q15,-12 20,0" stroke="#4CAF50" stroke-width="2" fill="none"/>
|
||||||
|
<path d="M3,-3 Q8,-10 13,-3" stroke="#81C784" stroke-width="1.5" fill="none"/>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(280,172)">
|
||||||
|
<path d="M0,0 Q5,-12 10,0 M5,0 Q10,-18 15,0 M10,0 Q15,-10 20,0" stroke="#4CAF50" stroke-width="2" fill="none"/>
|
||||||
|
<path d="M2,-2 Q7,-8 12,-2" stroke="#81C784" stroke-width="1.5" fill="none"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 水面 -->
|
||||||
|
<g>
|
||||||
|
<rect x="0" y="200" width="400" height="100" fill="url(#waterGradient)" filter="url(#water-ripple)"/>
|
||||||
|
<!-- 水面反光效果 -->
|
||||||
|
<path d="M50,220 Q200,210 350,220" stroke="white" stroke-width="1" fill="none" opacity="0.3">
|
||||||
|
<animate attributeName="d" dur="5s" repeatCount="indefinite"
|
||||||
|
values="M50,220 Q200,210 350,220;M50,220 Q200,230 350,220;M50,220 Q200,210 350,220"/>
|
||||||
|
</path>
|
||||||
|
<path d="M80,240 Q200,235 320,240" stroke="white" stroke-width="0.8" fill="none" opacity="0.2">
|
||||||
|
<animate attributeName="d" dur="7s" repeatCount="indefinite"
|
||||||
|
values="M80,240 Q200,235 320,240;M80,240 Q200,245 320,240;M80,240 Q200,235 320,240"/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 钓鱼的人 -->
|
||||||
|
<g transform="translate(150,160)">
|
||||||
|
<!-- 腿 -->
|
||||||
|
<path d="M-8,0 C-8,5 -7,10 -5,15 M8,0 C8,5 7,10 5,15" stroke="#5D4037" stroke-width="4" stroke-linecap="round"/>
|
||||||
|
<!-- 鞋子 -->
|
||||||
|
<path d="M-7,15 Q-5,14 -3,15 L-3,17 L-7,17 Q-8,16 -7,15 Z" fill="#3E2723"/>
|
||||||
|
<path d="M3,15 Q5,14 7,15 L7,17 L3,17 Q2,16 3,15 Z" fill="#3E2723"/>
|
||||||
|
<!-- 身体 -->
|
||||||
|
<path d="M-5,-25 C-8,-20 -8,-10 -5,0 L5,0 C8,-10 8,-20 5,-25 Z" fill="#795548">
|
||||||
|
<!-- 衣服褶皱和纹理 -->
|
||||||
|
<path d="M-3,-20 C-1,-19 1,-19 3,-20" stroke="#6D4C41" stroke-width="0.5" fill="none"/>
|
||||||
|
<path d="M-4,-15 C-2,-14 2,-14 4,-15" stroke="#6D4C41" stroke-width="0.5" fill="none"/>
|
||||||
|
<path d="M-3,-10 C-1,-9 1,-9 3,-10" stroke="#6D4C41" stroke-width="0.5" fill="none"/>
|
||||||
|
<path d="M-2,-5 C0,-4 2,-4 4,-5" stroke="#6D4C41" stroke-width="0.5" fill="none"/>
|
||||||
|
</path>
|
||||||
|
<!-- 头 -->
|
||||||
|
<circle cx="0" cy="-35" r="10" fill="#FFA726"/>
|
||||||
|
<!-- 表情 -->
|
||||||
|
<path d="M-3,-37 Q0,-35 3,-37" stroke="#5D4037" stroke-width="0.5" fill="none">
|
||||||
|
<animate attributeName="d" dur="4s" repeatCount="indefinite"
|
||||||
|
values="M-3,-37 Q0,-35 3,-37;M-3,-36 Q0,-34 3,-36;M-3,-37 Q0,-35 3,-37"/>
|
||||||
|
</path>
|
||||||
|
<circle cx="-4" cy="-38" r="0.8" fill="#5D4037"/>
|
||||||
|
<circle cx="4" cy="-38" r="0.8" fill="#5D4037"/>
|
||||||
|
<!-- 帽子 -->
|
||||||
|
<path d="M-12,-38 C-8,-45 8,-45 12,-38 L0,-45 Z" fill="#8D6E63">
|
||||||
|
<path d="M-8,-41 L8,-41" stroke="#6D4C41" stroke-width="0.5" fill="none"/>
|
||||||
|
</path>
|
||||||
|
<!-- 手臂 -->
|
||||||
|
<path d="M5,-20 Q15,-18 20,-15" stroke="#795548" stroke-width="4" stroke-linecap="round">
|
||||||
|
<animate attributeName="d" dur="4s" repeatCount="indefinite"
|
||||||
|
values="M5,-20 Q15,-18 20,-15;M5,-20 Q15,-17 20,-14;M5,-20 Q15,-18 20,-15"/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 钓鱼竿 -->
|
||||||
|
<g transform="translate(170,145)">
|
||||||
|
<!-- 手柄 -->
|
||||||
|
<path d="M0,0 L10,-5" stroke="#5D4037" stroke-width="3" stroke-linecap="round"/>
|
||||||
|
<!-- 主杆 -->
|
||||||
|
<line x1="10" y1="-5" x2="30" y2="-20" stroke="#8D6E63" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<!-- 导环 -->
|
||||||
|
<circle cx="15" cy="-8" r="1" fill="none" stroke="#424242" stroke-width="0.5"/>
|
||||||
|
<circle cx="22" cy="-13" r="1" fill="none" stroke="#424242" stroke-width="0.5"/>
|
||||||
|
<!-- 鱼线轮 -->
|
||||||
|
<path d="M5,-3 A3,3 0 1,1 5,3" fill="#424242"/>
|
||||||
|
<!-- 伸出部分 -->
|
||||||
|
<line x1="30" y1="-20" x2="60" y2="40" stroke="#8D6E63" stroke-width="1.5" stroke-linecap="round">
|
||||||
|
<animate attributeName="x2" dur="4s" repeatCount="indefinite"
|
||||||
|
values="60;61;60"/>
|
||||||
|
<animate attributeName="y2" dur="4s" repeatCount="indefinite"
|
||||||
|
values="40;41;40"/>
|
||||||
|
</line>
|
||||||
|
<!-- 鱼线 -->
|
||||||
|
<path d="M60,40 C60,45 60,50 60,60" stroke="#A7FFEB" stroke-width="0.5" fill="none">
|
||||||
|
<animate attributeName="d" dur="2s" repeatCount="indefinite"
|
||||||
|
values="M60,40 C60,45 60,50 60,60;M60,40 C61,45 61,50 61,65;M60,40 C60,45 60,50 60,60"/>
|
||||||
|
</path>
|
||||||
|
<!-- 浮标 -->
|
||||||
|
<circle cx="60" cy="55" r="1.5" fill="#F44336">
|
||||||
|
<animate attributeName="cy" dur="2s" repeatCount="indefinite"
|
||||||
|
values="55;60;55"/>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- 水中的鱼 -->
|
||||||
|
<g transform="translate(250,250)">
|
||||||
|
<path d="M0,0 C2,-3 8,-3 10,0 L12,0 L10,2 C8,5 2,5 0,2 L-2,0 Z" fill="#FFB74D">
|
||||||
|
<animateTransform attributeName="transform" type="translate" values="-50,0;50,0;-50,0" dur="10s" repeatCount="indefinite"/>
|
||||||
|
<animate attributeName="opacity" values="0.6;0.8;0.6" dur="10s" repeatCount="indefinite"/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
<g transform="translate(180,270)">
|
||||||
|
<path d="M0,0 C1,-2 4,-2 5,0 L6,0 L5,1 C4,3 1,3 0,1 L-1,0 Z" fill="#FFB74D">
|
||||||
|
<animateTransform attributeName="transform" type="translate" values="-30,0;30,0;-30,0" dur="8s" repeatCount="indefinite"/>
|
||||||
|
<animate attributeName="opacity" values="0.4;0.6;0.4" dur="8s" repeatCount="indefinite"/>
|
||||||
|
</path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 8.1 KiB |
@ -0,0 +1,87 @@
|
|||||||
|
<template>
|
||||||
|
<div class="fishing-log">
|
||||||
|
<h2>钓鱼日志</h2>
|
||||||
|
<el-scrollbar height="300px">
|
||||||
|
<div v-if="logs.length > 0" class="log-list">
|
||||||
|
<div v-for="(log, index) in logs" :key="index" class="log-item" :class="{ rare: log.isRare }">
|
||||||
|
<div class="log-time">{{ formatTime(log.time) }}</div>
|
||||||
|
<div class="log-content">
|
||||||
|
<el-tag :type="log.isRare ? 'warning' : 'info'" effect="plain">
|
||||||
|
{{ log.fishName }}
|
||||||
|
</el-tag>
|
||||||
|
<span class="log-weight">{{ log.weight }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-empty v-else description="暂无钓鱼记录" />
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
logs: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatTime = (time) => {
|
||||||
|
return new Date(time).toLocaleString()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.fishing-log {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-item:hover {
|
||||||
|
transform: translateX(5px);
|
||||||
|
background: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-time {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-weight {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rare {
|
||||||
|
background: #fdf6ec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rare:hover {
|
||||||
|
background: #faecd8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue