目录
- 前言:
- 具体实现思路:
- 步骤:
- 1. 展示美食杰发布菜谱页效果
- 2. 引入element-ui
- 3. 代码
- 总结:
前言:
本文给大家讲解,美食杰项目中 实现发布菜谱页的效果,和具体代码。
具体实现思路:
- 按照效果图实现静态页面布局
- 可以使用element-ui框架
- 实现上传图片功能
- 默认为3个可以增加,删除,最少为1个
- 点击提交,成功发布菜谱
步骤:
1. 展示美食杰发布菜谱页效果
美食杰发布菜谱
2. 引入element-ui
点击跳转至 element-ui 中 Upload 上传使用方法:https://element.eleme.cn/#/zh-CN/component/upload
点击跳转至 element-ui 中 input 输入框使用方法:https://element.eleme.cn/#/zh-CN/component/input
点击跳转至 element-ui 中 Select 选择器使用方法:https://element.eleme.cn/#/zh-CN/component/select
3. 代码
element-ui 中 Upload 上传 功能要单独封装一个组件,因为它还需要在编辑个人资料页面中使用
其他的在代码中写有注释,按注释理解即可,不了解的也可以在评论区里问我,或者私聊我询问
上传功能实现代码在编辑个人资料页中 点击跳转至编辑个人资料页
- 主页面
<template>
<div class="box">
<p class="title">欢迎发布新菜谱,先介绍一下你的大作</p>
<div class="top">
<div class="headline">
<p>标题</p>
<input type="text" placeholder="请输入内容" v-model="backData.title" />
</div>
<div class="property">
<p>属性</p>
<el-select
v-for="item in property"
:key="item.parent_type"
:placeholder="item.parent_name"
v-model="backData.property[item.title]"
>
<el-option
v-for="option in item.list"
:key="option.type"
:label="option.name"
:value="option.type"
></el-option>
</el-select>
</div>
<div class="classify">
<p>菜谱分类</p>
<el-select v-model="backData.classify" placeholder="请选择">
<el-option-group
v-for="item in classify"
:key="item.parent_type"
:label="item.parent_name"
>
<el-option
v-for="option in item.list"
:key="option.type"
:label="option.name"
:value="option.type"
>
</el-option>
</el-option-group>
</el-select>
</div>
<div class="articles">
<p>成品图(328*440)</p>
<div>
<upload-img
action="/api/upload/?type=product"
class="image"
v-model="backData.product_pic_url"
@res-url="(data) => (backData.product_pic_url = data.resImgUrl)"
:imageUrl="backData.product_pic_url"
></upload-img>
<el-input
type="textarea"
:rows="5"
:cols="500"
placeholder="请输入内容"
class="textarea"
v-model="backData.product_story"
>
</el-input>
</div>
</div>
</div>
<p class="title">记录所有原材料</p>
<div class="center">
<div class="one">
<p>主料</p>
<Material
v-model="backData.raw_material.main_material"
@remove="(item) => (backData.raw_material.main_material = item)"
></Material>
</div>
<div class="two">
<p>辅料</p>
<Material
v-model="backData.raw_material.accessories_material"
@remove="
(item) => (backData.raw_material.accessories_material = item)
"
></Material>
</div>
</div>
<p class="title">开始写步骤了!能否简单易学就看你怎么写了,加油!</p>
<div class="bottom">
<div v-for="(item, index) in backData.steps" :key="index">
<b>{{ index }}.</b>
<upload-img
v-model="item.img_url"
:imageUrl="avatar"
:imgMaxWidth="184"
class="image"
action="/api/upload/?type=step"
@res-url="
(data) => (
(item.img_url = data.resImgUrl), (avatar = data.resImgUrl)
)
"
></upload-img>
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="item.describe"
>
</el-input>
<i
class="delete-icon el-icon-close"
v-show="backData.steps.length !== 1"
@click="remove(index, id)"
></i>
</div>
<el-button
class="eaeaea"
type="primary"
size="medium"
icon="el-icon-plus"
@click="add"
>增加一项</el-button
>
<p>烹饪小技巧</p>
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
:style="{ height: '150px' }"
v-model="backData.skill"
>
</el-input>
</div>
<div class="btn">
<button @click="submit">搞定,提交审核</button>
</div>
</div>
</template>
<script>
import { getProperty, getClassify, publish } from "@/connector/api";
import UploadImg from "@/views/uploadImg/upload_img.vue";
import Material from "@/views/PublishRecipes/material.vue";
// const backData = {
// //向后端发生的数据
// title: "",
// property: {
// craft: 0, // 工艺 enum: [1,2,3,4],
// flavor: 0, // 口味 enum: [1,2,3,4],
// hard: 0, // 难度 enum: [1,2,3,4],
// pepole: 0, // pepole 人数: [1,2,3,4],
// },
// //分类
// classify: "",
// //成品图
// product_pic_url:
// "https://s1.c.meishij.net/n/images/upload_big_img.png?_=1561906961", // 成品图URL
// product_story: "", // 成品图故事
// raw_material: {
// // 料
// main_material: [{ name: "", specs: "" }], // 主料
// accessories_material: [{ name: "", specs: "" }], // 辅料
// },
// // steps: [{img_url: '',describe: '',}], // 步骤
// steps: Array(3)
// .fill(1)
// .map(() => ({ ...steps_struct, customeId: this.uuid() })),
// skill: "", //心得
// };
const material = {
name: "",
specs: "",
};
const steps_struct = {
img_url: "",
describe: "",
};
export default {
components: {
UploadImg,
Material,
},
data() {
return {
// 向后端发送的数据
backData: {
// 标题
title: "",
property: {
// craft: 0, // 工艺 enum: [1,2,3,4],
// flavor: 0, // 口味 enum: [1,2,3,4],
// hard: 0, // 难度 enum: [1,2,3,4],
// pepole: 0, // pepole 人数: [1,2,3,4],
},
classify: "",
// 成品图
product_pic_url:
"https://s1.c.meishij.net/n/images/upload_big_img.png?_=1561906961",
product_story: "",
raw_material: {
// Array(3):数组长度为3,fill(1):数组的值为1,map:循环添加值
main_material: Array(3)
.fill(1)
.map(() => ({ ...material })), // 主料
accessories_material: Array(3)
.fill(1)
.map(() => ({ ...material })), // 辅料
},
steps: Array(3)
.fill(1)
.map(() => ({ ...steps_struct })),
skill: "",
},
property: [],
classify: [],
avatar: "https://s1.c.meishij.net/n/images/upload_step_img.png",
};
},
mounted() {
// 获取所有属性分类
getProperty().then(({ data }) => {
// console.log(data);
this.property = data;
});
// 获取所有菜谱分类
getClassify().then(({ data }) => {
// console.log(data);
this.classify = data;
});
},
methods: {
// 点击删除
remove(index) {
this.backData.steps.splice(index, 1);
},
// 点击添加
add() {
this.backData.steps.push({
img_url: "",
describe: "",
});
},
// 点击发布新的菜品
submit() {
// console.log(this.backData);
// 发布新菜品的请求头
publish(this.backData).then((data) => {
// console.log(data);
// 发布成功后跳转至首页
window.location.href = "/";
});
},
},
};
</script>
<style lang="scss" scoped>
.box {
width: 990px;
margin: 0 auto;
.title {
text-align: center;
font-size: 22px;
}
.top {
background-color: #fff;
padding: 20px;
div {
p {
font-size: 14px;
}
input {
width: 400px;
height: 50px;
}
}
.articles {
div {
display: flex;
}
.textarea {
width: 50%;
}
}
}
.center {
background-color: #fff;
padding: 20px;
}
.bottom {
background-color: #fff;
padding: 20px;
div {
display: flex;
b {
font-size: 50px;
color: gainsboro;
}
.image {
margin: 10px 20px;
}
}
}
.btn {
text-align: center;
margin: 20px 0;
button {
background-color: red;
padding: 30px 40px;
color: #fff;
border: none;
}
}
}
</style>
- input框页
<template>
<div>
<div class="raw-item" v-for="(item, index) in value" :key="index">
<el-input
placeholder="请输入内容"
style="width: 200px"
v-model="item.name"
></el-input>
<el-input
placeholder="请输入内容"
style="width: 100px"
v-model="item.specs"
></el-input>
<!-- 只要input不等于1,删除功能就一直显示 -->
<i
class="delete-icon el-icon-close"
v-show="value.length !== 1"
@click="remove(index, id)"
></i>
</div>
<el-button
class="eaeaea"
type="primary"
size="medium"
icon="el-icon-plus"
@click="add"
>增加一项</el-button
>
</div>
</template>
<script>
export default {
props: {
// 接收数据v-model传递数据
value: {
type: Array,
default: () => [],
},
},
methods: {
// 点击删除
remove(index) {
const newValue = this.value.filter((item, i) => {
// console.log(index, item, i);
return i !== index;
});
// console.log(newValue);
this.$emit("remove", newValue);
},
add() {
// 子传父触发数据
this.$emit("input", [...this.value, { name: "", specs: "" }]);
},
},
};
</script>
<style></style>
总结:
以上就是 美食杰项目 中 发布菜谱页的具体实现方法,不懂得也可以在评论区里问我或私聊我询问,以后会持续发布一些新的功能,敬请关注。
我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog