Vue3电影中后台开发纪实(三):数据展示
@拿到热映数据
- 使用POSTMAN提前向后台插入电影数据
配置全局代理
vite.config.js
// 配置前端服务地址和端口
server: {
host: "0.0.0.0",
port: 5173,
// 是否开启 https
https: false,
// 让开发服务器帮我们做代理
proxy: {
// http://localhost:5173/api
"/api": {
target: "http://localhost:8173", //API服务地址
changeOrigin: true, //开启跨域
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
配置网络应用层
src/api/movieApi.js
import axios from "axios";
import { doGet } from "./service/crud";
/* 获取正在热映列表 */
export async function getPlayings() {
// localhost:5173/api/film/0 => vite会将该地址代理到localhost:8173/film/0
const {arr:films} = await doGet(`/film/0`);
return films;
}
组件挂载时获取数据
src/views/film/Playing.vue
import { getPlayings } from "@api/movieApi";
/* 组件挂载完毕后发起AJAX请求 */
onMounted(async () => {
const films = await getPlayings();
console.log("films=", films);
});
@表格展示数据
分页加载
src/views/film/Playing.vue
/* 完整电影列表 */
const tableData = ref([]);
/* 要显示的分页数据 */
const currentPage = ref(1);
const computedData = computed(() =>
tableData.value.slice((currentPage.value - 1) * 10, currentPage.value * 10)
);
/* 组件挂载完毕后发起AJAX请求 */
onMounted(async () => {
const films = await getPlayings();
console.log("films=", films);
tableData.value = films;
});
表格列展示数据
<el-table
:data="computedData"
stripe
style="width: 100%"
:default-sort="{ prop: 'date', order: 'ascending' }"
@selection-change="handleSelectionChange"
>
<!-- 多选显示栏 -->
<el-table-column type="selection" width="40" />
<!-- fixed固定 sortable字段可排序 label=当前列标题 width当前列像素宽度 -->
<el-table-column sortable fixed prop="filmId" label="id" width="100" />
<!-- 片名 -->
<el-table-column sortable prop="name" label="片名" width="180" />
<!-- 海报 -->
<el-table-column prop="poster" label="海报" width="60" >
<template #default="{row:{poster}}">
<div style="display: flex; align-items: center">
<el-image :src="poster" />
</div>
</template>
</el-table-column>
<!-- 主演 -->
<el-table-column
sortable
prop="actors"
label="主演"
:formatter="formatActors"
width="200"
/>
<!-- 国家 -->
<el-table-column sortable prop="nation" label="国家" width="150" />
<!-- 类型 -->
<el-table-column sortable prop="category" label="类型" width="150" />
<!-- 片长 -->
<el-table-column sortable prop="runtime" label="片长" width="100" />
<!-- 评分 -->
<el-table-column sortable prop="grade" label="评分" width="100" />
<!-- 首映日期 -->
<el-table-column
sortable
prop="premiereAt"
label="首映日期"
:formatter="formatPremierAt"
width="150"
/>
<!-- fixed="right"右侧固定 -->
<el-table-column fixed="right" label="操作" width="90">
<!-- 覆盖为小号圆形的编辑按钮与删除按钮 -->
<template #default>
<el-button type="primary" :icon="Edit" circle size="small" />
<el-button type="danger" :icon="Delete" circle size="small" />
</template>
</el-table-column>
</el-table>
数据格式化
/* 数据格式化函数 */
const formatPremierAt = (row, column, cellValue, index) => {
// console.log("row", row);//当前行数据
// console.log("column", column);//当前列信息
// console.log("cellValue", cellValue);//当前要格式化的单元格数据
// console.log("index", index);//当前行行号
return new Date(cellValue * 1000).toLocaleDateString().replaceAll("/", "-");
};
const formatActors = (row, column, cellValue, index) => {
return (
cellValue
.map((actor) => actor.name)
.slice(0, 3)
.join(",") + "等"
);
};
展示电影海报
<!-- 海报 -->
<el-table-column prop="poster" label="海报" width="60" >
<!-- <template #default="scope"> -->
<template #default="{row:{poster}}">
<div style="display: flex; align-items: center">
<!-- 这里我们通过一个简单的测试发现scope.row.poster即要显示的海报数据 -->
<!-- <el-image :src="showScope(scope)" /> -->
<el-image :src="poster" />
</div>
</template>
</el-table-column>
@跳转详情页
定义详情页路由
src/router/index.js
{
// 规定电影id为24个数字或小写字母
path: "/film/:id(\\d+)",
name: "detail",
meta: { hideTabbar: true },
component: () => import("../views/DetailView.vue"),
},
跳转详情页
src/views/Playing.vue
<!-- 右侧固定的操作按钮区 -->
<el-table-column fixed="right" label="操作" width="90">
<!-- action按钮区作用域插槽提供的数据中含有当前行信息row -->
<!-- <template #default="scope"> -->
<!-- 可以通过简单的测试查看一下作用域插槽中携带的数据 -->
<!-- <el-button @click="showScope(scrope)"/> -->
<!-- 从作用域插槽数据中解构出当前行id -->
<template #default="{ row: { _id } }">
<!-- 点击Edit按钮 携带id跳转详情页 -->
<el-button @click="$router.push(`/film/${_id}`)" type="primary" :icon="Edit" circle size="small" />
<el-button type="danger" :icon="Delete" circle size="small" />
</template>
</el-table-column>
@详情页数据展示
获取详情数据
src/views/Detail.vue
import { onMounted } from "vue";
import { useRoute } from "vue-router";
import { getDetail } from "@api/movieApi";
/* 获取影片详情 */
onMounted(async () => {
const detail = await getDetail(route.params.id);
console.log("detail=", detail);
});
添加Loading效果
<template>
<el-card v-loading="loading">
正文内容...
</el-card>
</template>
/* 获取影片详情 */
onMounted(async () => {
loading.value = true;
const detail = await getDetail(route.params.id);
console.log("detail=", detail);
/* 将detail中的数据同步到form中 表单中自动同步数据 */
// ...
setTimeout(() => {
loading.value = false;
}, 500);
});
定义表格数据
const form = reactive({});
/* 获取影片详情 */
onMounted(async () => {
loading.value = true;
const detail = await getDetail(route.params.id);
console.log("detail=", detail);
/* 将detail中的数据同步到form中 表单中自动同步数据 */
Object.assign(form, detail, {
premiereAt: detail.premiereAt * 1000,
// 影片类型 表单复选 应双向绑定一个数组
category: detail.category.split("|"),
// 重构actcors数据
actors: detail.actors.map(({ name, role, avatarAddress }) => ({
name: `${name}-${role}`,
url: avatarAddress,
})),
});
setTimeout(() => {
loading.value = false;
}, 500);
});
表格展示数据
<template>
<el-card v-loading="loading">
<template #header>
<div class="card-header">
<span>影片详情</span>
<!-- <el-button class="button" text>Operation button</el-button> -->
</div>
</template>
<!-- 详情表单 -->
<!-- form没有数据时不渲染form -->
<el-form v-if="form[`name`]" :model="form" label-width="120px">
<!-- 片名关联form.name -->
<el-form-item label="片名">
<el-input v-model="form.name" />
</el-form-item>
<!-- 片长关联form.runtime -->
<el-form-item label="片长">
<el-col :span="7">
<el-input v-model="form.runtime" type="number" />
</el-col>
</el-form-item>
<!-- 评分关联form.grade -->
<el-form-item label="评分">
<el-col :span="7">
<el-input v-model="form.grade" />
</el-col>
</el-form-item>
<!-- 影片类型关联form.filmType.name -->
<!-- filmType?.name 如果filmType不为null/undeined 就继续读取filmType?.name 否则直接返回null/undeined -->
<el-form-item label="影片类型">
<el-select
v-model="form.filmType.name"
placeholder="please select your zone"
>
<el-option label="2D" value="2D" />
<el-option label="3D" value="3D" />
<el-option label="4D" value="4D" />
</el-select>
</el-form-item>
<!-- 影片类型关联form.premiereAt -->
<el-form-item label="首映日期">
<el-col :span="8">
<el-date-picker
v-model="form.premiereAt"
type="date"
placeholder="Pick a date"
style="width: 100%"
/>
</el-col>
</el-form-item>
<!-- 在映关联form.isPresale -->
<el-form-item label="在映">
<el-switch v-model="form.isPresale" />
</el-form-item>
<!-- 影片类型关联form.category -->
<el-form-item label="影片类型">
<el-checkbox-group v-model="form.category">
<el-checkbox label="爱情" name="category" />
<el-checkbox label="动作" name="category" />
<el-checkbox label="科幻" name="category" />
<el-checkbox label="历史" name="category" />
<el-checkbox label="悬疑" name="category" />
<el-checkbox label="喜剧" name="category" />
<el-checkbox label="战争" name="category" />
<el-checkbox label="剧情" name="category" />
<el-checkbox label="犯罪" name="category" />
<el-checkbox label="纪录片" name="category" />
</el-checkbox-group>
</el-form-item>
<!-- 国家关联form.nation -->
<el-form-item label="国家">
<el-radio-group v-model="form.nation">
<el-radio label="中国大陆" />
<el-radio label="欧美" />
<el-radio label="日韩" />
<el-radio label="其它" />
</el-radio-group>
</el-form-item>
<!-- 演职人员关联form.actors -->
<!--
:on-preview="handlePreview"
:on-remove="handleRemove"
-->
<el-form-item label="演职人员">
<el-upload
v-model:file-list="form.actors"
class="upload-demo"
list-type="picture-card"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
<!-- 海报关联form.poster -->
<el-form-item label="海报">
<el-upload
v-model:file-list="form.poster"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card"
>
<el-icon><Plus /></el-icon>
</el-upload>
</el-form-item>
<!-- 剧情摘要form.synopsis -->
<el-form-item label="剧情摘要">
<el-input v-model="form.synopsis" autosize type="textarea" />
</el-form-item>
<!-- 提交与重置 -->
<el-form-item>
<el-button class="opBtn" type="primary" @click="onSubmit">更新</el-button>
<el-button class="opBtn">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
转载自:https://juejin.cn/post/7169131209983787039