作品集代码初版

This commit is contained in:
xiaowang 2025-07-09 20:08:15 +08:00
parent 1d113e78ed
commit 475e0461e2
5 changed files with 288 additions and 80 deletions

View File

@ -1,6 +1,6 @@
<template>
<div class="nav-bar">
<van-nav-bar title="标题" left-text="返回" :placeholder="true" :safe-area-inset-top="true" z-index="99">
<van-nav-bar title="屿" left-text="" :placeholder="true" :safe-area-inset-top="true" z-index="99">
<template #right>
<van-icon name="search" size="18" />
</template>

View File

@ -1,17 +1,24 @@
import Vue from "vue";
import Vuex from 'vuex'
import Vuex from "vuex";
import App from "./App.vue";
import router from "./router";
import store from "./store";
Vue.config.productionTip = false;
import { Tabbar, TabbarItem } from "vant";
import { NavBar } from "vant";
import { Toast } from 'vant';
import { Popup } from 'vant';
import { Icon } from 'vant';
import { Button } from 'vant';
import { Toast } from "vant";
import { Popup } from "vant";
import { Icon } from "vant";
import { Button } from "vant";
import { Image as VanImage } from "vant";
import { Lazyload } from "vant";
import { Card } from "vant";
import { Tag } from "vant";
Vue.use(Tag);
Vue.use(Card);
Vue.use(Lazyload);
Vue.use(VanImage);
Vue.use(Button);
Vue.use(Icon);
Vue.use(Popup);
@ -22,7 +29,6 @@ Vue.use(TabbarItem);
Vue.use(Vuex);
new Vue({
store,
router,
render: (h) => h(App),
}).$mount("#app");

View File

@ -1,25 +1,284 @@
<template>
<div class="portfolio-page">
<h1>作品集</h1>
<div class="container">
<div class="card-grid">
<!-- 卡片列表 -->
<div
v-for="(card, index) in cards"
:key="index"
class="card"
:class="{ 'card-active': activeCardIndex === index }"
@touchstart="handleTouchStart(index)"
@touchend="handleTouchEnd(index)"
@click="handleCardClick(card)"
>
<div class="card-image-container">
<img
:src="card.image"
:alt="card.title"
class="card-image"
>
<div
v-if="card.tag"
class="card-tag"
:style="card.tagStyle"
>
{{ card.tag }}
</div>
</div>
<div class="card-content">
<h2 class="card-title">{{ card.title }}</h2>
<p class="card-description">{{ card.description }}</p>
<div class="card-footer">
<span class="card-meta">
<i class="fa fa-calendar-o mr-1"></i> {{ card.duration }}
</span>
<button
class="card-button"
@click.stop="handleButtonClick(card)"
>
了解更多
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "PortfolioPage",
components: {},
props: {},
name: 'PortfolioPage',
data() {
return {
cards: [
{
title: "探索自然之美",
description: "深入原始森林,感受大自然的鬼斧神工。这里有清澈的溪流、茂密的树木和各种珍稀野生动物。",
image: "https://picsum.photos/seed/card1/600/800",
duration: "3天2晚",
tag: "热门",
tagStyle: {
backgroundColor: "#F97316",
color: "#fff"
}
},
{
title: "城市探险之旅",
description: "穿梭于现代都市与历史古迹之间,体验城市独特的文化氛围和美食特色。",
image: "https://picsum.photos/seed/card2/600/800",
duration: "2天1晚",
tag: "热门",
tagStyle: {
backgroundColor: "#F97316",
color: "#fff"
}
},
{
title: "美食文化体验",
description: "跟随当地厨师学习传统美食的制作方法,品尝地道佳肴,感受美食背后的文化故事。",
image: "https://picsum.photos/seed/card3/600/800",
duration: "1天",
tag: "新品",
tagStyle: {
backgroundColor: "#22c55e",
color: "#fff"
}
},
{
title: "海洋生态探索",
description: "潜入蔚蓝深海,探索神秘的海底世界,与海龟、珊瑚和热带鱼共舞。",
image: "https://picsum.photos/seed/card4/600/800",
duration: "4天3晚",
tag: "推荐",
tagStyle: {
backgroundColor: "#3b82f6",
color: "#fff"
}
}
],
activeCardIndex: -1
};
},
watch: {},
computed: {
methods: {
handleTouchStart(index) {
this.activeCardIndex = index;
},
methods: {},
created() { },
mounted() { }
handleTouchEnd() {
setTimeout(() => {
this.activeCardIndex = -1;
}, 300);
},
handleCardClick(card) {
console.log('点击了卡片:', card.title);
},
handleButtonClick(card) {
console.log('点击了了解更多:', card.title);
}
},
mounted() {
//
const buttons = document.querySelectorAll('.card-button');
buttons.forEach(button => {
button.addEventListener('touchstart', () => {
button.classList.add('button-active');
});
button.addEventListener('touchend', () => {
setTimeout(() => {
button.classList.remove('button-active');
}, 200);
});
});
}
};
</script>
<style lang="less" scoped></style>
<style scoped>
/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Inter', system-ui, sans-serif;
}
body {
background-color: #f9fafb;
min-height: 100vh;
padding: 20px 0;
}
/* 容器样式 - 限制最大宽度为800px双列布局的合理宽度 */
.container {
max-width: 800px; /* 双列布局的最佳最大宽度 */
margin: 0 auto;
padding: 0 20px;
}
.page-title {
font-size: clamp(1.5rem, 3vw, 2rem);
font-weight: bold;
color: #1f2937;
margin-bottom: 32px;
text-align: center;
}
/* 卡片网格布局 - 固定双列 */
.card-grid {
display: grid;
grid-template-columns: repeat(2, 1fr); /* 固定双列布局 */
gap: 24px; /* 卡片间距 */
}
/* 移动端适配 - 屏幕小于600px时改为单列 */
@media (max-width: 600px) {
.card-grid {
grid-template-columns: 1fr;
}
}
/* 卡片样式 */
.card {
background-color: white;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
cursor: pointer;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.card-active {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
/* 卡片图片 */
.card-image-container {
position: relative;
}
.card-image {
width: 100%;
display: block;
/* 3:4 比例 */
aspect-ratio: 3 / 4;
object-fit: cover;
}
/* 卡片标签 */
.card-tag {
position: absolute;
top: 16px;
right: 16px;
padding: 4px 12px;
border-radius: 9999px;
font-size: 14px;
font-weight: 500;
}
/* 卡片内容 */
.card-content {
padding: 20px;
}
.card-title {
font-size: 18px;
font-weight: bold;
color: #1f2937;
margin-bottom: 8px;
}
.card-description {
color: #6b7280;
text-wrap: balance;
margin-bottom: 12px;
line-height: 1.5;
font-size: 14px;
}
/* 卡片底部 */
.card-footer {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 12px;
}
.card-meta {
color: #3b82f6;
font-weight: 500;
font-size: 13px;
}
/* 按钮样式 */
.card-button {
background-color: #3b82f6;
color: white;
border: none;
padding: 6px 12px;
border-radius: 8px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
font-size: 13px;
}
.card-button:hover {
background-color: #2563eb;
transform: scale(1.05);
}
.button-active {
transform: scale(0.95);
}
</style>

View File

@ -3,7 +3,6 @@ import VueRouter from "vue-router";
import HomePage from "@/pages/HomePage.vue";
import PortfolioPage from "@/pages/PortfolioPage.vue";
import SampleCollectionPage from "@/pages/SampleCollectionPage.vue";
import {store} from "@/store";
Vue.use(VueRouter);
const routes = [
@ -34,10 +33,6 @@ const router = new VueRouter({
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 避免重复记录相同路径(如刷新页面)
if (to.path !== from.path) {
store.dispatch("routeHistory/pushRoute", to);
}
next();
});

View File

@ -1,52 +0,0 @@
const state = {
history: [], // 存储路由历史
};
const mutations = {
// 添加路由到历史记录
PUSH_ROUTE(state, route) {
state.history.push(route);
},
// 重置历史记录
RESET_HISTORY(state) {
state.history = [];
},
};
const actions = {
pushRoute({ commit }, route) {
commit("PUSH_ROUTE", route);
},
resetHistory({ commit }) {
commit("RESET_HISTORY");
},
};
const getters = {
// 判断当前是否为后退操作
isBack(state) {
if (state.history.length < 2) return false;
const current = state.history[state.history.length - 1];
const previous = state.history[state.history.length - 2];
// 通过比较路径判断是否为后退
return previous.path === current.path;
},
// 获取历史记录长度
historyLength(state) {
return state.history.length;
},
};
export default {
namespaced: true, // 使用命名空间
state,
mutations,
actions,
getters,
};