软件工程学习日志2025.11.25
今日完成了BS实验报告
【实验编号】
10003809548j Web界面设计
【实验学时】
8学时
【实验环境】
所需硬件环境为微机;
所需软件环境为dreamweaver
【实验内容】
聚焦 B/S 架构的前端侧实现:浏览器负责渲染、交互与状态管理,服务器以静态资源与未来 API 接入为目标。
基于 Vue 3 构建 SPA 风格页面:分类筛选、搜索结果页切换、分页、夜间模式等交互均在浏览器端完成。
【关键步骤】
资源加载与初始化
通过 CDN 加载 Vue 和 Bootstrap ,页面就绪后在浏览器端挂载应用。
视图与状态管理
分类视图与首页视图切换:使用 searchActive 控制首页板块显隐,返回首页方法 goHome。
搜索与结果页:绑定输入与提交,执行关键词匹配并展示独立“搜索结果”。
分页: 猜你喜欢 按页展示,计算安全页码与切。
布局与样式
三列等高:统一用 heroh 控制高度,轮播与左右列对齐。
夜间模式:按钮触发切换 databstheme 与 body.dark ,背景与组件样式切换(按钮 bs.html:101 , 方法 bs.html:720728 , 初始化 bs.html:812821 , 深色选择。
交互与体验
平滑滚动至结果或分类区锚点。
本地存储持久化主题偏
【程序运行截图】
首页视图:顶部导航与搜索框、三列等高布。
分类筛选视图:点击侧栏分类后显示“分类商品”内容区。
猜你喜欢分页:页码指示与上一页/下一页操作。
搜索结果页:输入关键词点击“搜索”后只展示“搜索结果”及数量统计。
夜间模式:点击右上角月亮按钮切换到深色背景,再次点击恢复。
【实验体会】
B/S 的浏览器侧实现能快速交付原型,前后端天然解耦,便于后续把本地数据替换为服务端接口响应。
通过状态驱动视图切换可在无路由的前提下实现“页面感”的单页体验,降低复杂度。
客户端分页/筛选对小数据量交互顺畅;接入后端后应将分页与搜索下沉到服务器以减少带宽与浏览器负载。
主题切换与持久化体现良好的用户体验;注意在深色模式下的对比度与可读性、阴影强度等细节优化。
<!doctype html>
<div class="search-wrap mb-3">
<div class="input-group input-group-lg">
<select class="form-select" style="max-width:140px" v-model="searchType">
<option>宝贝</option>
<option>店铺</option>
</select>
<input class="form-control" type="search" placeholder="搜索商品" aria-label="Search" v-model="searchQuery">
<button class="btn btn-primary px-4" @click="doSearch">搜索</button>
</div>
</div>
<div class="my-4" id="search-results" v-if="searchActive">
<div class="d-flex align-items-center mb-2">
<div class="section-title mb-0">搜索结果</div>
<span class="ms-2 badge text-bg-light">{{ searchQuery }}</span>
<span class="ms-2 text-secondary small">共 {{ searchedProducts.length }} 件</span>
<button class="btn btn-sm btn-outline-secondary ms-auto" @click="clearSearch">清除</button>
</div>
<div class="products-grid" v-if="searchedProducts.length">
<div v-for="p in searchedProducts" :key="p.title">
<div class="card product-card h-100 position-relative">
<div class="position-absolute top-0 end-0 p-2">
<button class="btn btn-sm fav-btn shadow-sm" data-bs-toggle="tooltip" data-bs-title="收藏">
<i class="bi bi-heart"></i>
</button>
</div>
<img :src="p.img" class="card-img-top" :alt="p.title">
<div class="card-body d-flex flex-column">
<h6 class="card-title">{{ p.title }}</h6>
<p class="text-danger fw-bold mb-3">{{ formatCurrency(p.price) }}</p>
<div class="mt-auto d-flex gap-2">
<button class="btn btn-primary btn-sm" @click="addToCart(p.title,p.price)"><i class="bi bi-cart-plus"></i> 加入购物车</button>
<button class="btn btn-outline-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#quickViewModal" :data-title="p.title" :data-img="p.img">快速查看</button>
</div>
</div>
</div>
</div>
</div>
<div v-else class="text-muted">未找到相关商品</div>
</div>
<div class="bg-white border rounded px-3 py-2 mb-3 cat-band" v-if="!searchActive">
<ul class="nav flex-wrap">
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-percent"></i> 全场9折起 <span class="text-secondary">抢省钱补贴</span></a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-laptop"></i> 电脑 配件 办公 文具</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-device-hdd"></i> 家电 手机 通信 数码</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-building"></i> 工业品 商业 农业 定制</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-house-door"></i> 家具 家装 家居 厨具</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-person-bounding-box"></i> 女装 男装 内衣 配饰</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-universal-access"></i> 女鞋 男鞋 运动 户外</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-car-front"></i> 汽车 珠宝 文玩 箱包</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-basket"></i> 食品 生鲜 酒类 健康</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-emoji-smile"></i> 母婴 童装 玩具 宠物</a></li>
<li class="nav-item"><a class="nav-link" href="#"><i class="bi bi-brush"></i> 美妆 个护 娱乐 图书</a></li>
</ul>
</div>
<div class="row align-items-stretch mb-4 equal-row" v-if="!searchActive">
<div class="col-lg-2 d-none d-lg-block">
<div class="card h-100 sidebar">
<div class="card-body p-2">
<div class="list-group category-list">
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('家用电器')">家用电器</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('手机数码')">手机数码</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('电脑办公')">电脑办公</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('服饰')">服饰鞋包</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('美妆个护')">美妆个护</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('家居家装')">家居家装</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('母婴玩具')">母婴玩具</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('食品饮料')">食品饮料</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('运动户外')">运动户外</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('汽车用品')">汽车用品</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('宠物生活')">宠物生活</a>
<a href="#" class="list-group-item list-group-item-action" @click.prevent="setCategory('生鲜好物')">生鲜好物</a>
</div>
</div>
</div>
</div>
<div class="col-lg-8 mb-3 mb-lg-0">
<div id="heroCarousel" class="carousel slide h-100" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner rounded-4 overflow-hidden shadow">
<div class="carousel-item active">
<img src="https://picsum.photos/seed/hero1/1200/360" class="d-block w-100" alt="">
<div class="carousel-caption text-start hero-caption">
<h5>初冬上新</h5>
<a href="#products" class="btn btn-gradient">立即抢购</a>
</div>
</div>
<div class="carousel-item">
<img src="https://picsum.photos/seed/hero2/1200/360" class="d-block w-100" alt="">
<div class="carousel-caption hero-caption">
<h5>精选好物</h5>
<button class="btn btn-light" data-bs-toggle="modal" data-bs-target="#loginModal">立即注册</button>
</div>
</div>
<div class="carousel-item">
<img src="https://picsum.photos/seed/hero3/1200/360" class="d-block w-100" alt="">
<div class="carousel-caption text-end hero-caption">
<h5>品质生活</h5>
<a href="#faq" class="btn btn-success">了解我们</a>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#heroCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">上一张</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#heroCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">下一张</span>
</button>
</div>
</div>
<div class="col-lg-2 d-none d-lg-flex flex-column gap-3 promo-col">
<div class="card promo-card orange text-white">
<div class="card-body d-flex align-items-center gap-3">
<div class="rounded-circle bg-white text-orange d-flex align-items-center justify-content-center" style="width:44px;height:44px"><i class="bi bi-gem"></i></div>
<div>
<div class="fw-bold">品质家居 超值优惠</div>
<div class="small opacity-75">精选好物一站购</div>
</div>
</div>
</div>
<div class="card promo-card pink text-white">
<div class="card-body d-flex align-items-center gap-3">
<div class="rounded-circle bg-white text-orange d-flex align-items-center justify-content-center" style="width:44px;height:44px"><i class="bi bi-bag-heart"></i></div>
<div>
<div class="fw-bold">精致美妆 品质之选</div>
<div class="small opacity-75">焕新你的妆容</div>
</div>
</div>
</div>
<div class="card promo-card blue text-white">
<div class="card-body d-flex align-items-center gap-3">
<div class="rounded-circle bg-white text-orange d-flex align-items-center justify-content-center" style="width:44px;height:44px"><i class="bi bi-capsule"></i></div>
<div>
<div class="fw-bold">超值自营 省钱放心</div>
<div class="small opacity-75">爆品低价购</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-4">
<div class="section-title">上新好物</div>
<div class="scroll-controls">
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="prev" data-target="#newBooks"><i class="bi bi-chevron-left"></i></button>
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="next" data-target="#newBooks"><i class="bi bi-chevron-right"></i></button>
</div>
<div id="newBooks" class="h-scroll">
<div class="h-item card mini-card" v-for="p in newArrivals" :key="p.title">
<img :src="p.img" class="card-img-top" :alt="p.title">
<div class="card-body p-2">
<div class="small text-truncate">{{ p.title }}</div>
<div class="text-danger fw-bold">{{ formatCurrency(p.price) }}</div>
</div>
</div>
</div>
</div>
<div class="my-4">
<div class="section-title">精选推荐</div>
<div class="row g-3">
<div class="col-lg-6">
<div class="border rounded p-3">
<div class="scroll-controls">
<span class="small text-secondary">热销榜单</span>
<div class="ms-auto d-flex gap-2">
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="prev" data-target="#bestSellers"><i class="bi bi-chevron-left"></i></button>
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="next" data-target="#bestSellers"><i class="bi bi-chevron-right"></i></button>
</div>
</div>
<div id="bestSellers" class="h-scroll">
<div class="h-item card mini-card" v-for="p in bestSellers" :key="p.title">
<img :src="p.img" class="card-img-top" :alt="p.title">
<div class="card-body p-2"><div class="small text-truncate">{{ p.title }}</div><div class="text-danger fw-bold">{{ formatCurrency(p.price) }}</div></div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="border rounded p-3">
<div class="scroll-controls">
<span class="small text-secondary">人气推荐</span>
<div class="ms-auto d-flex gap-2">
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="prev" data-target="#editorPicks"><i class="bi bi-chevron-left"></i></button>
<button class="btn btn-outline-secondary btn-sm" data-scroll-dir="next" data-target="#editorPicks"><i class="bi bi-chevron-right"></i></button>
</div>
</div>
<div id="editorPicks" class="h-scroll">
<div class="h-item card mini-card" v-for="p in editorPicks" :key="p.title">
<img :src="p.img" class="card-img-top" :alt="p.title">
<div class="card-body p-2"><div class="small text-truncate">{{ p.title }}</div><div class="text-danger fw-bold">{{ formatCurrency(p.price) }}</div></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-4" id="guess" v-if="!searchActive">
<div class="section-title">猜你喜欢</div>
<div class="products-grid">
<div v-for="p in pagedRecommendations" :key="p.title">
<div class="card product-card h-100 position-relative">
<div class="position-absolute top-0 end-0 p-2">
<button class="btn btn-sm fav-btn shadow-sm" data-bs-toggle="tooltip" data-bs-title="收藏">
<i class="bi bi-heart"></i>
</button>
</div>
<img :src="p.img" class="card-img-top" alt="">
<div class="card-body d-flex flex-column">
<h6 class="card-title">{{ p.title }}</h6>
<p class="text-danger fw-bold mb-3">{{ formatCurrency(p.price) }}</p>
<div class="mt-auto d-flex gap-2">
<button class="btn btn-gradient" @click="addToCart(p.title,p.price)"><i class="bi bi-cart-plus"></i></button>
<button class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#quickViewModal" :data-title="p.title" :data-img="p.img"><i class="bi bi-eye"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-center mt-3">
<ul class="pagination pagination-sm mb-0">
<li class="page-item" :class="{disabled: guessPageSafe<=1}">
<a class="page-link" href="#" @click.prevent="prevGuess"><i class="bi bi-chevron-left"></i></a>
</li>
<li class="page-item disabled"><span class="page-link">第 {{ guessPageSafe }} / {{ guessTotalPages }} 页</span></li>
<li class="page-item" :class="{disabled: guessPageSafe>=guessTotalPages}">
<a class="page-link" href="#" @click.prevent="nextGuess"><i class="bi bi-chevron-right"></i></a>
</li>
</ul>
</div>
</div>
<div class="my-4" id="category-products" v-if="!searchActive && activeCategory!=='全部'">
<div class="d-flex align-items-center mb-2">
<div class="section-title mb-0">分类商品</div>
<span class="ms-2 badge text-bg-light">{{ activeCategory }}</span>
</div>
<div class="products-grid">
<div v-for="p in filteredProducts" :key="p.title">
<div class="card product-card h-100 position-relative">
<div class="position-absolute top-0 end-0 p-2">
<button class="btn btn-sm fav-btn shadow-sm" data-bs-toggle="tooltip" data-bs-title="收藏">
<i class="bi bi-heart"></i>
</button>
</div>
<img :src="p.img" class="card-img-top" :alt="p.title">
<div class="card-body d-flex flex-column">
<h6 class="card-title">{{ p.title }}</h6>
<p class="text-danger fw-bold mb-3">{{ formatCurrency(p.price) }}</p>
<div class="mt-auto d-flex gap-2">
<button class="btn btn-gradient" @click="addToCart(p.title,p.price)"><i class="bi bi-cart-plus"></i></button>
<button class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#quickViewModal" :data-title="p.title" :data-img="p.img"><i class="bi bi-eye"></i></button>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="faq" class="my-4" v-if="!searchActive">
<div class="d-flex gap-2">
<span class="badge text-bg-light"><i class="bi bi-question-circle me-1"></i>帮助</span>
<span class="badge text-bg-light"><i class="bi bi-shield-check me-1"></i>保障</span>
</div>
</div>
购物车
- {{ item.title }} {{ formatCurrency(item.price) }}

浙公网安备 33010602011771号