Skip to content

《web前端应用开发》期末大作业需求文档

1. 项目背景与目标

1.1 项目背景

电影推荐项目

1.2 考核目标

本项目旨在综合考核学生对本学期 uni-app 课程核心知识点的掌握情况,具体包括:

  • 基础能力:熟练搭建 uni-app 项目,掌握 Vue 3 组合式 API (Script Setup) 的使用。
  • 组件化开发:能够封装通用组件(如电影卡片),并使用 Props 和 Events 进行通信。
  • 网络与数据:掌握网络请求 (uni.request) 的封装与拦截器 (Interceptor) 的使用,理解前后端分离开发模式。
  • 用户体验:能实现下拉刷新、上拉加载更多等移动端常见交互。
  • UI 美化:熟练使用 uni-ui 组件库快速构建美观的界面。

2. 核心功能需求

学生需完成以下两大核心页面及相关逻辑:

2.1 首页 (Home Page)

  1. 搜索栏:顶部需包含一个搜索框和公告栏(样式展示即可,推荐使用uni-search-bar、uni-notice-bar)。
  2. 轮播图 (Banner)
    • 位于顶部,自动轮播展示热门电影海报。(推荐使用swiper)
    • 数据来源:调用 Mock 接口 /home/banner
  3. 电影列表 (Movie List)
    • 以列表形式展示电影信息。
    • 展示内容:需包含电影海报、中文标题、副标题(年份/导演)、评分、标签(如“科幻/灾难”)。(推荐封装通用组件MovieCard.vue)(内部标签推荐uni-card、uni-rate)。
    • 数据来源:调用 Mock 接口 /movie/list
  4. 交互要求
    • 下拉刷新:下拉页面时,清空当前列表,重新请求第一页数据,并重置加载状态。
    • 上拉加载:滑动到底部时,自动加载下一页数据并追加到列表中。如果无更多数据,需显示“没有更多了”的提示。
    • 点击跳转:点击任意电影卡片,跳转至详情页,并将电影 ID 作为参数传递。

2.2 详情页 (Detail Page)

  1. 电影信息头
    • 展示大幅背景图(可做模糊处理)、清晰海报、电影标题、评分、上映年份、国家/地区。
    • 数据来源:调用 Mock 接口 /movie/detail,需根据首页传来的 ID 请求对应数据。
  2. 主创团队
    • 使用标签或列表形式展示导演和主演信息。(推荐用uni-card包括)
  3. 剧情简介
    • 使用 rich-text 组件解析并展示带有 HTML 格式的剧情简介(Mock 数据中包含 HTML 标签)。(推荐用uni-card包括,mock数据会返回的数据中,包含富文本信息summary,推荐 rich-text
  4. 收藏功能 核心
    • 页面底部或导航栏需包含“收藏”按钮。(推荐uni-goods-nav,官网uni-ui组件教程有)
    • 逻辑要求:点击按钮切换收藏状态(已收藏/未收藏),并更新图标或文字。(只需实现这个功能就行,其他三个暂不用实现)
    • 数据持久化:必须使用 uni.setStorageSync 将收藏列表保存到本地,退出应用后再进入,收藏状态应保持不变。

3. 技术栈要求

  • 开发工具:HBuilderX
  • 框架:uni-app + Vue 3 (使用 <script setup> 语法)
  • UI 组件库:uni-ui (官方组件库)
  • 核心 API
    • uni.request (网络请求)
    • uni.addInterceptor 核心考点 (用于拦截请求并返回 Mock 数据)
    • uni.navigateTo (页面跳转与传参)
    • uni.showToast / uni.showLoading (交互反馈)
    • uni.setStorageSync / uni.getStorageSync (数据缓存)
  • 生命周期onLoad, onPullDownRefresh, onReachBottom, onMounted

4. 项目资源包与接口文档

4.1 必装插件:uni-ui

本项目要求使用 uni-ui 进行界面美化。

  • 安装方式:打开 HBuilderX -> 顶部菜单“工具” -> “插件安装” -> “uni-ui (官方组件库)” -> 点击安装。
  • 使用方式:安装后无需 import,直接在 <template> 中使用即可,如 <uni-card>, <uni-tag> 等。

4.2 核心资源:Mock 数据脚本

由于本项目不依赖真实的后端服务器,我们提供了一个 mock.js 文件来模拟后端接口。

  • 资源获取:请复制老师提供的 utils/mock.js 代码并在项目中新建同名文件。
  • 使用方式
    1. 在项目根目录下新建 utils 文件夹,新建 mock.js文件,将代码放入 mock.js
    2. 首页 (pages/index/index.vue) 中引入并启动拦截器:
    import { onLoad } from 'vue';
    import { initMock } from '@/utils/mock.js';
    // 必须在页面挂载时启动拦截器,否则请求无法被拦截
    onLoad(() => {
        initMock();
    });
点击展开/折叠 utils/mock.js 源代码
// utils/mock.js

const HOST = '[https://api.movie-daily.com](https://api.movie-daily.com)';
const DELAY = 600; // 稍微加快一点模拟速度

// 国产热门电影数据池
const MOVIES = [
	{ title: "流浪地球2", director: "郭帆", cast: "吴京 / 刘德华 / 李雪健", tags: ["科幻", "灾难"], year: 2023 },
	{ title: "哪吒之魔童降世", director: "饺子", cast: "吕艳婷 / 囧森瑟夫", tags: ["动画", "奇幻"], year: 2019 },
	{ title: "我不是药神", director: "文牧野", cast: "徐峥 / 王传君", tags: ["剧情", "喜剧"], year: 2018 },
	{ title: "让子弹飞", director: "姜文", cast: "姜文 / 葛优 / 周润发", tags: ["剧情", "喜剧"], year: 2010 },
	{ title: "战狼2", director: "吴京", cast: "吴京 / 弗兰克·格里罗", tags: ["动作", "战争"], year: 2017 },
	{ title: "你好,李焕英", director: "贾玲", cast: "贾玲 / 张小斐", tags: ["喜剧", "亲情"], year: 2021 },
	{ title: "长津湖", director: "陈凯歌 / 徐克 / 林超贤", cast: "吴京 / 易烊千玺", tags: ["战争", "历史"], year: 2021 },
	{ title: "红海行动", director: "林超贤", cast: "张译 / 黄景瑜", tags: ["动作", "战争"], year: 2018 },
	{ title: "夏洛特烦恼", director: "闫非 / 彭大魔", cast: "沈腾 / 马丽", tags: ["喜剧", "爱情"], year: 2015 },
	{ title: "西游记之大圣归来", director: "田晓鹏", cast: "张磊 / 林子杰", tags: ["动画", "奇幻"], year: 2015 }
];

// 接口路由表
const API_ROUTES = {
	
	// 1. 首页轮播图 (改为展示热门档期)
	[`${HOST}/home/banner`]: () => {
		return [
			{ id: 101, image: '[https://picsum.photos/800/400?random=101](https://picsum.photos/800/400?random=101)', title: '春节档票房冠军回顾' },
			{ id: 102, image: '[https://picsum.photos/800/400?random=102](https://picsum.photos/800/400?random=102)', title: '中国科幻电影的里程碑' },
			{ id: 103, image: '[https://picsum.photos/800/400?random=103](https://picsum.photos/800/400?random=103)', title: '必看!豆瓣高分华语片' }
		];
	},

	// 2. 电影列表接口
	[`${HOST}/movie/list`]: (options) => {
		// console.log(options)
		const page = options.data?.page || 1;
		const pageSize = 10;
		if (page > 3) return []; // 模拟只有3页

		return Array.from({ length: pageSize }).map((_, index) => {
			const dataIndex = (page - 1) * pageSize + index;
			const movie = MOVIES[dataIndex % MOVIES.length];
			// 随机评分 8.0 - 9.8
			const score = (8.0 + Math.random() * 1.8).toFixed(1); 
			
			return {
				id: 2000 + dataIndex,
				title: movie.title,
				// 拼接副标题:年份 / 导演
				subTitle: `${movie.year} / ${movie.director}`,
				cover: `https://picsum.photos/300/400?random=${dataIndex + 200}`,
				rating: Number(score), // 转为数字供 uni-rate 使用
				tags: movie.tags,
				reviews: Math.floor(Math.random() * 50000 + 1000)
			};
		});
	},

	// 3. 电影详情接口
	[`${HOST}/movie/detail`]: (options) => {
		const id = Number(options.data?.id || 0);
		const index = (id - 2000) % MOVIES.length;
		const movie = MOVIES[index >= 0 ? index : 0]; // 防止索引越界
		
		return {
			id: id,
			title: movie.title,
			year: movie.year,
			country: "中国大陆",
			rating: 9.5, // 详情页给个高分
			cover: `https://picsum.photos/300/400?random=${id}`,
			director: movie.director,
			casts: movie.cast,
			// 富文本简介
			summary: `
				<div style="color:#333; line-height:1.8; font-size:15px;">
    <p><b>【剧情简介】</b></p>
    <p>《${movie.title}》是一部备受观众喜爱的国产佳作。影片讲述了主角在经历了重重磨难后,最终寻找到了自我与真情的故事。</p>
    <p>该片上映期间口碑爆棚,成为了年度现象级电影。</p>
    <br>
    <p><b>【幕后花絮】</b></p>
    <p>导演${movie.director.split('/')[0]}在接受采访时表示,这部电影的拍摄过程非常艰辛...</p>
    <img src="[https://picsum.photos/600/350?random=$](https://picsum.photos/600/350?random=$){id+999}" style="width:100%; border-radius:8px; margin:10px 0;" />
</div>
			`
		};
	}
};

export const initMock = () => {
	console.log('Mock: 国产电影数据库已加载...');
	uni.addInterceptor('request', {
		invoke(args) {
			const handler = API_ROUTES[args.url];
			if (handler) {
				setTimeout(() => {
					const res = {
						data: { code: 200, msg: 'success', data: handler(args) },
						statusCode: 200
					};
					args.success && args.success(res);
					args.complete && args.complete(res);
				}, DELAY);
				return false;
			}
			return args;
		}
	});
};

4.3 Mock 接口文档

基础域名 (Base URL): https://api.movie-daily.com

以下接口均通过 uni.request 调用,请求不会真的发往互联网,而是直接返回模拟数据。

接口 1:获取首页轮播图

  • 地址: /home/banner
  • 方式: GET
  • 描述: 获取首页顶部的热门电影宣传图。

接口 2:获取电影列表 (分页)

  • 地址: /movie/list
  • 方式: GET
  • 参数:
参数名类型必填说明
pageNumber页码,默认 1。Mock 数据预设了 3 页数据。

返回示例:

{
  "code": 200,
  "data": [
    {
      "id": 2001,
      "title": "流浪地球2",
      "subTitle": "2023 / 郭帆",
      "cover": "http://...",
      "rating": 8.5,
      "tags": ["科幻", "灾难"]
    },
    ...
  ]
}

接口 3:获取电影详情

  • 地址: /movie/detail
  • 方式: GET
  • 参数:
参数名类型必填说明
idNumber电影 ID (从列表页获取)

5. 评分标准

维度分值评分点说明
基础功能60分1. 项目能正常运行,无报错 (20分)2. 首页轮播图和列表能展示 Mock 数据 (20分)3. 点击列表能跳转到详情页,且内容显示正确 (ID传参正确) (20分)
交互逻辑20分1. 下拉刷新逻辑正确 (数据重置) (10分)2. 上拉加载逻辑正确 (分页追加,无数据提示) (10分)
界面美观10分1. 使用了 uni-ui 组件 (如 uni-card, uni-tag 等) (5分)2. 页面布局整洁,图片无变形,文字排版清晰 (5分)
进阶加分10分1. 收藏功能:实现了收藏状态的本地持久化存储 (5分)2. 代码规范:代码结构清晰,关键逻辑有注释,组件封装合理 (5分)

6. 提交方式

  • 提交内容
    • 完整的项目源码文件夹(请删除 unpackage 目录以减小体积)。
    • 一份简短的 .txt 说明文档,注明姓名、学号以及已完成的功能点。
  • 提交截止时间:202512.26
  • 提交渠道:学委收齐

祝同学们开发顺利!遇到问题请先查阅 uni-app 官方文档或使用 console.log 进行调试。