Skip to content

Commit 91655b1

Browse files
committed
feature(管理后台): 商品添加视频
1 parent 752285e commit 91655b1

File tree

2 files changed

+240
-10
lines changed

2 files changed

+240
-10
lines changed

src/components/VideoUpload/index.vue

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<template>
2+
<div class="editPage__video">
3+
<el-upload
4+
class="uploader"
5+
list-type="picture-card"
6+
:action="uploadUrl"
7+
:on-success="handleSuccess"
8+
:before-upload="beforeUpload"
9+
:headers="headers"
10+
:on-error="handleError"
11+
:show-file-list="false"
12+
>
13+
14+
<div v-if="uploadFlag" @mouseenter="mouseover" @mouseleave="mouseout">
15+
<i class="el-icon-success success-icon"></i>
16+
<div :class="{'hide': activeHover, 'success': !activeHover}">
17+
<span class="item-actions">
18+
<span
19+
class="item-preview"
20+
@click.stop="handlePreview()"
21+
>
22+
<i class="el-icon-zoom-in"></i>
23+
</span>
24+
<span
25+
class="item-delete"
26+
@click.stop="handleRemove()"
27+
>
28+
<i class="el-icon-delete"></i>
29+
</span>
30+
</span>
31+
</div>
32+
</div>
33+
<i v-else-if="uploadFlag === null" class="el-icon-plus uploader-icon"></i>
34+
<i v-else-if="!uploadFlag" class="el-icon-circle-close uploader-icon" style="color: red"></i>
35+
</el-upload>
36+
<!-- 上传提示 -->
37+
<div class="el-upload__tip" slot="tip" v-if="showTip">
38+
请上传
39+
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
40+
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
41+
的文件
42+
</div>
43+
44+
<el-dialog :visible.sync="dialogVisible" append-to-body width="800" title="预览">
45+
<video width="100%" v-if="videoUrl" controls="controls" :key="menuKey">
46+
<source :src="videoUrl" type="video/mp4" />
47+
</video>
48+
</el-dialog>
49+
50+
</div>
51+
</template>
52+
53+
<script>
54+
55+
import { getAccessToken } from "@/utils/auth";
56+
57+
export default {
58+
props: {
59+
value: [String, Object],
60+
// 大小限制(MB)
61+
fileSize: {
62+
type: Number,
63+
default: 300,
64+
},
65+
// 文件类型, 例如"video/mp4"
66+
fileType: {
67+
type: [String, Array],
68+
default: () =>["video/mp4"],
69+
},
70+
// 是否显示提示
71+
isShowTip: {
72+
type: Boolean,
73+
default: true
74+
}
75+
},
76+
data() {
77+
return {
78+
uploadFlag: null,
79+
activeHover: true,
80+
dialogVisible: false,
81+
videoUrl: null,
82+
// 视频上传
83+
uploadUrl: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址
84+
headers: { Authorization: "Bearer " + getAccessToken() }, // 设置上传的请求头部
85+
// 应付多个组件的情况 记录当前组件的key值
86+
menuKey: 1, // 用来强制刷新,
87+
}
88+
},
89+
watch: {
90+
value: {
91+
handler(val) {
92+
if (val) {
93+
this.videoUrl = val;
94+
this.uploadFlag = true;
95+
}
96+
},
97+
deep: true,
98+
immediate: true
99+
}
100+
},
101+
computed: {
102+
// 是否显示提示
103+
showTip() {
104+
return this.isShowTip && (this.fileType || this.fileSize);
105+
},
106+
},
107+
methods: {
108+
// 上传成功的函数
109+
handleSuccess(res) {
110+
++this.menuKey;
111+
if(res.code === 0){
112+
this.uploadFlag = true;
113+
this.videoUrl = res.data;
114+
this.$emit("input", this.videoUrl);
115+
}else{
116+
this.uploadFlag = false;
117+
this.$message.error("错误!"+ res.msg);
118+
}
119+
},
120+
handleError(){
121+
this.uploadFlag = false;
122+
},
123+
beforeUpload(file) {
124+
const isMp4 = this.fileType.includes(file.type);
125+
const isLt300MB = file.size / 1024 / 1024 < 300;
126+
if (!isMp4) {
127+
this.$message.error("视频只能是"+ this.fileType.join("/") +"格式!");
128+
}
129+
if (!isLt300MB) {
130+
this.$message.error("上传视频大小不能超过 300MB!");
131+
}
132+
return isMp4 && isLt300MB;
133+
},
134+
// 预览
135+
handlePreview() {
136+
this.dialogVisible = true;
137+
},
138+
// 删除视频
139+
handleRemove() {
140+
this.videoUrl = null;
141+
this.uploadFlag = null;
142+
this.$emit("input", null);
143+
},
144+
mouseover(){
145+
this.activeHover = false;
146+
},
147+
mouseout(){
148+
this.activeHover = true;
149+
}
150+
}
151+
}
152+
</script>
153+
154+
155+
<style lang="scss">
156+
157+
.editPage__video {
158+
.hide{
159+
visibility:hidden;
160+
}
161+
.success{
162+
position: relative;
163+
width: 78px;
164+
height: 78px;
165+
line-height: 78px;
166+
background-color: rgba(0,0,0,.5);
167+
transition: opacity .3s;
168+
cursor: default;
169+
170+
.item-preview .el-icon-zoom-in{
171+
width: 30px;
172+
font-size: 20px;
173+
color: #f2f2f2;
174+
cursor: pointer;
175+
}
176+
.item-delete .el-icon-delete{
177+
width: 30px;
178+
font-size: 20px;
179+
color: #f2f2f2;
180+
cursor: pointer;
181+
}
182+
}
183+
184+
.uploader-icon {
185+
font-size: 28px;
186+
color: #8c939d;
187+
width: 80px;
188+
height: 80px;
189+
line-height: 80px;
190+
text-align: center;
191+
position: absolute;
192+
left: 0;
193+
}
194+
.success-icon {
195+
font-size: 28px;
196+
color: green;
197+
width: 80px;
198+
height: 80px;
199+
line-height: 80px;
200+
text-align: center;
201+
position: absolute;
202+
left: 0;
203+
}
204+
205+
.el-upload{
206+
width: 80px;
207+
height: 80px;
208+
}
209+
210+
}
211+
</style>

src/views/mall/product/spu/save.vue

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
<el-form-item label="商品卖点">
1111
<el-input type="textarea" v-model="baseForm.sellPoint" placeholder="请输入商品卖点"/>
1212
</el-form-item>
13-
<!-- TODO @Luowenfeng:商品主图,80 x 80 即可 -->
1413
<el-form-item label="商品主图" prop="picUrls">
15-
<ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" />
14+
<ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" class="mall-image" />
1615
</el-form-item>
17-
<!-- TODO @Luowenfeng:商品视频 -->
16+
<el-form-item label="商品视频" prop="videoUrl">
17+
<VideoUpload v-model="baseForm.videoUrl" :value="baseForm.videoUrl" />
18+
</el-form-item>
19+
1820
<el-form-item label="商品品牌" prop="brandId">
1921
<el-select v-model="baseForm.brandId" placeholder="请选择商品品牌">
2022
<el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
@@ -37,7 +39,6 @@
3739
<el-tab-pane label="价格库存" name="rates" class="rates">
3840
<el-form ref="rates" :model="ratesForm" :rules="rules">
3941
<el-form-item label="启用多规格">
40-
<!-- TODO @Luowenfeng:改成开关的按钮;关闭,单规格;开启,多规格 -->
4142
<el-switch v-model="activeSwitch" @change="changeRadio"></el-switch>
4243
</el-form-item>
4344

@@ -149,7 +150,7 @@
149150
</template>
150151
</el-table>
151152
</el-form-item>
152-
<el-form-item label="虚拟销量" prop="virtualSalesCount">
153+
<el-form-item label="虚拟销量" prop="virtualSalesCount" >
153154
<el-input v-model="baseForm.virtualSalesCount" placeholder="请输入虚拟销量" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/>
154155
</el-form-item>
155156
</el-form>
@@ -196,11 +197,13 @@ import {createSpu, updateSpu, getSpuDetail} from "@/api/mall/product/spu";
196197
import {getPropertyListAndValue,} from "@/api/mall/product/property";
197198
import Editor from "@/components/Editor";
198199
import ImageUpload from "@/components/ImageUpload";
200+
import VideoUpload from "@/components/VideoUpload";
199201
200202
export default {
201203
components: {
202204
Editor,
203-
ImageUpload
205+
ImageUpload,
206+
VideoUpload
204207
},
205208
props:{
206209
obj: Object
@@ -223,11 +226,13 @@ export default {
223226
sort: null,
224227
description: null,
225228
picUrls: null,
229+
videoUrl: null,
226230
status: 0,
227231
virtualSalesCount: 0,
228232
showStock: true,
229-
brandId: null
233+
brandId: null,
230234
},
235+
231236
categoryList: [],
232237
// 价格库存
233238
ratesForm: {
@@ -255,8 +260,8 @@ export default {
255260
description: [{required: true, message: "描述不能为空", trigger: "blur"},],
256261
categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"},],
257262
status: [{required: true, message: "商品状态不能为空", trigger: "blur"}],
263+
brandId: [{required: true, message: "商品品牌不能为空", trigger: "blur"}],
258264
picUrls: [{required: true, message: "商品轮播图地址不能为空", trigger: "blur"}],
259-
virtualSalesCount: [{required: true, message: "虚拟销量不能为空", trigger: "blur"}],
260265
},
261266
};
262267
},
@@ -379,7 +384,6 @@ export default {
379384
rates[0].status = this.baseForm.status;
380385
}
381386
let form = this.baseForm
382-
383387
if(form.picUrls instanceof Array){
384388
form.picUrls = form.picUrls.flatMap(m=>m.split(','))
385389
}else if(form.picUrls.split(',') instanceof Array){
@@ -428,6 +432,7 @@ export default {
428432
this.baseForm.name=data.name;
429433
this.baseForm.sellPoint=data.sellPoint;
430434
this.baseForm.categoryIds=data.categoryIds;
435+
this.baseForm.videoUrl = data.videoUrl;
431436
this.baseForm.sort=data.sort;
432437
this.baseForm.description=data.description;
433438
this.baseForm.picUrls=data.picUrls;
@@ -460,7 +465,8 @@ export default {
460465
}
461466
this.ratesForm.rates=data.skus
462467
})
463-
}
468+
},
469+
464470
},
465471
};
466472
</script>
@@ -550,4 +556,17 @@ export default {
550556
margin-left: 15px;
551557
}
552558
}
559+
560+
.mall-image{
561+
.el-upload--picture-card{
562+
width: 80px;
563+
height: 80px;
564+
line-height: 90px;
565+
}
566+
.el-upload-list__item{
567+
width: 80px;
568+
height: 80px;
569+
}
570+
}
571+
553572
</style>

0 commit comments

Comments
 (0)