-
组件背景 : 商城项目 实现配置商品详情列表配置 不能用富文本 列表内只能上传文字描述和图片
-
实现 : 基于vue+element ui
-
<template>
<div class="phone look_my_phone">
<div class="phone_shadow">
<div class="nav">
<vab-icon class="two" :icon="['fas', 'wifi']"></vab-icon>
<vab-icon
class="three"
:icon="['fas', 'battery-three-quarters']"
></vab-icon>
</div>
<div class="nav_s">
<div class="span_title">商品详情页配置</div>
<div class="left">
<i class="el-icon-arrow-left"></i>
</div>
<div class="right"></div>
</div>
<!-- 内容区域 -->
<div class="phone_conts">
<div class="my_phones">
<div class="my_phones_cont_w">
<div class="conts_w">
<div class="conts">
<div
v-for="(item, index) in myList"
:key="index"
class="phone_item"
>
<img v-if="item.type == 'img'" :src="item.conts" alt="" />
<p v-else-if="item.type == 'text'">{{ item.conts }}</p>
<div class="config_w">
<div class="config">
<div class="config_item" @click="topGo(index)">上移</div>
<div class="config_item" @click="bottomGo(index)">
下移
</div>
<div
v-if="item.type == 'text'"
class="config_item"
@click="editShow(item, index)"
>
编辑
</div>
<div class="config_item" @click="delItem(index)">
删除
</div>
</div>
</div>
</div>
</div>
<div v-if="show" class="input_add_w">
<div>
<el-input
v-model="inputVlue"
type="textarea"
resize="none"
:rows="3"
placeholder="请输入内容..."
></el-input>
</div>
<div class="btns">
<el-button
v-if="showType == 'add'"
size="mini"
type="primary"
@click="addSubmit()"
>
添加
</el-button>
<el-button
v-else-if="showType == 'edit'"
size="mini"
type="primary"
@click="editSubmit()"
>
修改
</el-button>
<el-button size="mini" @click="hides()">取消</el-button>
</div>
</div>
</div>
</div>
<div class="my_phones_btns">
<div class="edits">
<i class="el-icon-plus"></i>
<div class="text">编辑</div>
</div>
<div class="my_phones_btns_show_w">
<div class="my_phones_btns_show">
<div class="lefts">
<i class="el-icon-picture"></i>
<span class="text">图片</span>
<input
class="files"
accept="image/*"
type="file"
@change="changeFile"
/>
</div>
<div class="rights" @click="addShow()">
<i class="el-icon-edit"></i>
<div class="text">文本</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="volume"></div>
<div class="bang">
<div class="yuan"></div>
</div>
<div class="power"></div>
<div class="power1"></div>
<div class="receiver">
<div></div>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'Phones',
props: {
lists: {
type: Array,
default() {
return []
},
},
},
data() {
return {
myList: this.lists,
inputVlue: '',
show: false,
showType: '',
INDEX: 0,
}
},
methods: {
// 添加文字显示
addShow() {
this.showType = 'add'
this.show = true
},
// 添加文字提交
addSubmit() {
this.myList.push({
type: 'text',
conts: this.inputVlue,
})
this.inputVlue = ''
this.show = false
},
// 编辑文字显示
editShow(row, index) {
this.INDEX = index
this.inputVlue = row.conts
this.showType = 'edit'
this.show = true
},
// 修改文字提交
editSubmit() {
this.myList[this.INDEX].conts = this.inputVlue
this.inputVlue = ''
this.show = false
},
// 上移
topGo(index) {
const that = this
if (index == 0) {
this.$message.error(`当前已在第一位`)
return
}
this.myList.splice(
index,
1,
...that.myList.splice(index - 1, 1, that.myList[index])
)
},
// 下移
bottomGo(index) {
const that = this
if (index == this.myList.length - 1) {
this.$message.error(`当前已在最后一位`)
return
}
this.myList.splice(
index,
1,
...that.myList.splice(index + 1, 1, that.myList[index])
)
},
// 删除
delItem(index) {
this.myList.splice(index, 1)
},
// 获取文件信息 e.target.files
async changeFile(e) {
let nums = 0
this.myList.forEach((item) => {
if (item.type == 'img') {
nums++
}
})
let file = e.target.files[0]
if (!file) {
this.$message.error('请选择图片')
return
}
if (nums >= 20) {
this.$message.error('最多上传20张图片')
return
}
let formData = new FormData()
formData.append('file', file)
formData.append('type', 'image')
axios
.post('上传图片地址', formData)
.then(({ data: res }) => {
if (res.code != 200000) {
this.$message.error(res.message)
return
}
this.myList.push({
type: 'img',
conts: res.data[0],
})
this.$message.success(res.message)
})
},
// 关闭
hides() {
this.inputVlue = ''
this.show = false
},
},
}
</script>
<style scoped lang="scss">
.my_phones {
width: 100%;
height: 600px;
height: 559px;
.my_phones_cont_w {
width: 100%;
height: 500px;
box-sizing: border-box;
.conts {
width: 100%;
height: 500px;
box-sizing: border-box;
overflow-y: scroll;
position: relative;
padding-bottom: 140px;
}
.conts_w {
width: 100%;
height: 500px;
box-sizing: border-box;
position: relative;
}
.conts::-webkit-scrollbar {
display: none;
}
}
.my_phones_btns {
width: 100%;
height: 60px;
box-sizing: border-box;
border-top: 1px solid #dcdfe6;
background-color: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
position: relative;
cursor: pointer;
.edits {
text-align: center;
font-size: 22px;
.text {
font-size: 16px;
}
}
.my_phones_btns_show_w {
display: none;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
.my_phones_btns_show {
width: 100%;
height: 100%;
background-color: #f5f5f5;
display: flex;
.lefts {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
cursor: pointer;
transition: all 1s;
.text {
font-size: 16px;
margin-left: 10px;
}
}
.lefts:hover {
background-color: #e6e6e6;
.text {
font-size: 18px;
font-weight: 700;
}
}
.rights {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 1s;
.text {
font-size: 16px;
margin-left: 10px;
}
}
.rights:hover {
background-color: #e6e6e6;
.text {
font-size: 18px;
font-weight: 700;
}
}
i {
font-size: 22px;
}
.items {
display: inline-block;
text-align: center;
}
}
}
}
.phone_item {
position: relative;
img {
width: 100%;
height: auto;
vertical-align: bottom;
}
p {
margin: 0;
line-height: 36px;
font-size: 16px;
}
}
}
.my_phones_btns:hover .my_phones_btns_show_w {
display: block;
}
.phone_item:hover .config_w {
display: block;
}
.config_w {
display: none;
position: absolute;
top: 0;
right: 0;
.config {
display: flex;
.config_item {
background-color: #f5f5f5;
padding: 10px 20px;
cursor: pointer;
}
.config_item:hover {
background-color: #e6e6e6;
}
}
}
.input_add_w {
width: 100%;
padding: 10px;
box-sizing: border-box;
position: absolute;
left: 0;
bottom: -2px;
background-color: #f5f5f5;
border: 1px solid #dcdfe6;
border-right: none;
border-left: none;
.btns {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
}
.files {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
</style>
下面是手机样式的css
.phone {
position: relative;
width: 370px;
height: 650px;
border: 15px solid #000;
border-radius: 60px;
box-sizing: border-box;
}
.phone_shadow {
content: '';
position: absolute;
width: 350px;
height: 634px;
box-shadow: 0px 0px 24px #fff;
border-radius: 51px;
left: -5px;
top: -7px;
background: #fff;
border: 10px solid #000;
box-sizing: border-box;
overflow: hidden;
.nav {
height: 25px;
color: #333333;
font-size: 16px;
display: flex;
align-items: center;
justify-content: flex-end;
box-sizing: border-box;
padding-right: 27px;
.three {
font-size: 20px;
margin-left: 8px;
}
.two {
margin-left: 5px;
}
}
.nav_s {
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
background-color: #f4f4f5;
box-sizing: border-box;
padding: 0 10px;
font-size: 16px;
.span_title {
position: absolute;
font-size: 16px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: #000;
}
.left {
color: #000;
font-size: 20px;
}
.right {
color: #83878d;
.one {
margin-right: 5px;
}
}
}
.phone_conts {
height: 559px;
overflow-y: scroll;
box-sizing: border-box;
padding: 10px;
color: #000;
.titles {
font-size: 16px;
font-weight: 700;
line-height: 30px;
}
.data {
color: #666769;
border-bottom: 1px dashed #c6c6c6;
line-height: 26px;
}
.html_conts {
margin-top: 20px;
color: #666769;
line-height: 30px;
word-break: break-all;
}
}
}
.phone_conts::-webkit-scrollbar {
display: none;
}
.volume {
width: 9px;
height: 100px;
border: #000 1px solid;
background: linear-gradient(#8c8c8c, #000 9%, #222, #000 94%, #353535 100%);
position: absolute;
right: -21px;
top: 120px;
z-index: -1;
border-radius: 20px;
}
.power {
width: 9px;
height: 46px;
border: #000 1px solid;
background: linear-gradient(#8c8c8c, #000 9%, #222, #000 94%, #353535 100%);
position: absolute;
left: -21px;
top: 100px;
z-index: -1;
border-radius: 20px;
}
.power1 {
width: 9px;
height: 46px;
border: #000 1px solid;
background: linear-gradient(#8c8c8c, #000 9%, #222, #000 94%, #353535 100%);
position: absolute;
left: -21px;
top: 160px;
z-index: -1;
border-radius: 20px;
}
.receiver {
position: absolute;
top: 4px;
left: 50%;
transform: translateX(-50%);
background: #000000;
border: #484848 1px solid;
width: 50px;
height: 8px;
z-index: 9;
border-radius: 20px;
}
.receiver ul {
list-style: none;
display: flex;
flex-wrap: wrap;
margin: 1px;
justify-content: space-around;
}
.receiver ul li {
background: #303030;
width: 1px;
height: 1.5px;
float: left;
transform: skewX(-38deg);
}
.bang {
width: 150px;
height: 25px;
background-color: #000;
position: absolute;
left: 50%;
transform: translateX(-50%);
border-radius: 0 0 13px 13px;
top: 0;
}
.yuan {
width: 10px;
height: 10px;
background-color: #070e21;
box-sizing: border-box;
position: absolute;
top: 4px;
right: 18px;
border-radius: 50%;
}
.look_my_phone .phone_conts {
overflow: hidden !important;
padding: 0 !important;
}
样式如果有错乱 请自行修改
组件使用
<my-phones :lists="phoneList"></my-phones>
数据格式
phoneList: [
{
type: 'text',
conts: '1212',
},
{
type: 'img',
conts: '图片路径',
},
],
别忘了注册组件 可以全局/局部注册
上传图片 用的formData 你们后端要什么参数 就传什么参数
代码很简单 请自行阅读