Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
mall4cloud
Commits
a21f5a9a
Commit
a21f5a9a
authored
Dec 20, 2023
by
liang.tang
Browse files
mall4cloud
parents
Pipeline
#244
canceled with stages
Changes
355
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
3224 additions
and
0 deletions
+3224
-0
front-end/mall4cloud-multishop-master/src/components/IconsSelect/index.vue
...oud-multishop-master/src/components/IconsSelect/index.vue
+72
-0
front-end/mall4cloud-multishop-master/src/components/IconsSelect/svg-icons.js
...-multishop-master/src/components/IconsSelect/svg-icons.js
+10
-0
front-end/mall4cloud-multishop-master/src/components/ImgUpload/index.vue
...cloud-multishop-master/src/components/ImgUpload/index.vue
+103
-0
front-end/mall4cloud-multishop-master/src/components/ImgsUpload/index.vue
...loud-multishop-master/src/components/ImgsUpload/index.vue
+207
-0
front-end/mall4cloud-multishop-master/src/components/LangSelect/index.vue
...loud-multishop-master/src/components/LangSelect/index.vue
+35
-0
front-end/mall4cloud-multishop-master/src/components/OfflineManage/index.vue
...d-multishop-master/src/components/OfflineManage/index.vue
+149
-0
front-end/mall4cloud-multishop-master/src/components/Pagination/index.vue
...loud-multishop-master/src/components/Pagination/index.vue
+106
-0
front-end/mall4cloud-multishop-master/src/components/PicUpload/index.vue
...cloud-multishop-master/src/components/PicUpload/index.vue
+110
-0
front-end/mall4cloud-multishop-master/src/components/PicturePreview/index.vue
...-multishop-master/src/components/PicturePreview/index.vue
+54
-0
front-end/mall4cloud-multishop-master/src/components/ProdsSelect/index.vue
...oud-multishop-master/src/components/ProdsSelect/index.vue
+367
-0
front-end/mall4cloud-multishop-master/src/components/ProductDetails/index.vue
...-multishop-master/src/components/ProductDetails/index.vue
+107
-0
front-end/mall4cloud-multishop-master/src/components/Sku/SkuBlock/index.vue
...ud-multishop-master/src/components/Sku/SkuBlock/index.vue
+276
-0
front-end/mall4cloud-multishop-master/src/components/Sku/SkuContainer/index.vue
...ultishop-master/src/components/Sku/SkuContainer/index.vue
+351
-0
front-end/mall4cloud-multishop-master/src/components/Sku/SkuGroup/index.vue
...ud-multishop-master/src/components/Sku/SkuGroup/index.vue
+218
-0
front-end/mall4cloud-multishop-master/src/components/Sku/SkuTable/index.vue
...ud-multishop-master/src/components/Sku/SkuTable/index.vue
+496
-0
front-end/mall4cloud-multishop-master/src/components/SpuCategoryAttrs/index.vue
...ultishop-master/src/components/SpuCategoryAttrs/index.vue
+105
-0
front-end/mall4cloud-multishop-master/src/components/SvgIcon/index.vue
...l4cloud-multishop-master/src/components/SvgIcon/index.vue
+62
-0
front-end/mall4cloud-multishop-master/src/components/Tinymce/components/EditorImage.vue
...-master/src/components/Tinymce/components/EditorImage.vue
+80
-0
front-end/mall4cloud-multishop-master/src/components/Tinymce/dynamicLoadScript.js
...tishop-master/src/components/Tinymce/dynamicLoadScript.js
+59
-0
front-end/mall4cloud-multishop-master/src/components/Tinymce/index.vue
...l4cloud-multishop-master/src/components/Tinymce/index.vue
+257
-0
No files found.
Too many changes to show.
To preserve performance only
355 of 355+
files are displayed.
Plain diff
Email patch
front-end/mall4cloud-multishop-master/src/components/IconsSelect/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<el-tabs
class=
"icons-container"
type=
"border-card"
>
<el-tab-pane
label=
"Icons"
>
<div
class=
"grid"
>
<el-button
v-for=
"item of svgIcons"
:key=
"item"
@
click=
"selectIcon(getIconCode(item))"
>
<div
class=
"icon-item"
>
<svg-icon
:icon-class=
"item"
class-name=
"disabled"
/>
</div>
</el-button>
</div>
</el-tab-pane>
<el-tab-pane
label=
"Element-UI Icons"
>
<div
class=
"grid"
>
<el-button
v-for=
"item of elementIcons"
:key=
"item"
@
click=
"selectIcon(getElementIconCode(item))"
>
<div
class=
"icon-item"
>
<i
:class=
"'el-icon-' + item"
/>
</div>
</el-button>
</div>
</el-tab-pane>
</el-tabs>
</
template
>
<
script
>
import
svgIcons
from
'
./svg-icons
'
import
elementIcons
from
'
./element-icons
'
export
default
{
name
:
'
Icons
'
,
data
()
{
return
{
svgIcons
,
elementIcons
}
},
methods
:
{
getIconCode
(
symbol
)
{
return
`
${
symbol
}
`
},
getElementIconCode
(
symbol
)
{
return
`el-icon-
${
symbol
}
`
},
selectIcon
(
text
)
{
this
.
$emit
(
'
selectIcon
'
,
text
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.icons-container
{
.el-tabs__content
{
height
:
200px
;
overflow
:
scroll
;
}
.grid
{
padding
:
0
;
margin
:
-8px
0
0
-8px
;
>
.el-button
{
padding
:
8px
;
margin
:
8px
0
0
8px
;
>
span
{
display
:
inline-block
;
vertical-align
:
middle
;
width
:
18px
;
height
:
18px
;
font-size
:
18px
;
}
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/IconsSelect/svg-icons.js
0 → 100644
View file @
a21f5a9a
const
req
=
require
.
context
(
'
../../icons/svg
'
,
false
,
/
\.
svg$/
)
const
requireAll
=
requireContext
=>
requireContext
.
keys
()
const
re
=
/
\.\/(
.*
)\.
svg/
const
svgIcons
=
requireAll
(
req
).
map
(
i
=>
{
return
i
.
match
(
re
)[
1
]
})
export
default
svgIcons
front-end/mall4cloud-multishop-master/src/components/ImgUpload/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div>
<div
class=
"plugin-images"
>
<div
tabindex=
"0"
class=
"el-upload el-upload--text"
@
click=
"elxImgboxHandle"
>
<img
v-if=
"value"
:src=
"getImgSrc()"
class=
"pic"
/>
<i
v-else
class=
"el-icon-plus pic-uploader-icon"
></i>
</div>
</div>
<!-- 弹窗, 新增图片 -->
<elx-imgbox
v-if=
"elxImgboxVisible"
ref=
"elxImgbox"
@
refreshPic=
"refreshPic"
></elx-imgbox>
<el-dialog
:visible.sync=
"visible"
:append-to-body=
"visible"
>
<img
width=
"100%"
:src=
"getImgSrc()"
alt
/>
</el-dialog>
</div>
</
template
>
<
script
>
import
ElxImgbox
from
'
@/components/imgbox
'
export
default
{
data
()
{
return
{
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
,
elxImgboxVisible
:
false
,
visible
:
false
}
},
props
:
{
value
:
{
default
:
''
,
type
:
String
},
disabled
:
{
default
:
false
,
type
:
Boolean
}
},
components
:
{
ElxImgbox
},
methods
:
{
// 打开图片选择窗
elxImgboxHandle
()
{
if
(
this
.
disabled
)
{
this
.
openImg
()
return
false
}
this
.
elxImgboxVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
.
elxImgbox
.
init
(
1
)
})
},
/**
* 获取图片路径
*/
getImgSrc
()
{
if
(
!
this
.
value
)
{
return
''
}
if
(
this
.
value
.
indexOf
(
'
http://
'
)
===
0
||
this
.
value
.
indexOf
(
'
https://
'
)
===
0
)
{
return
this
.
value
}
return
this
.
resourcesUrl
+
this
.
value
},
openImg
()
{
this
.
visible
=
true
},
refreshPic
(
imagePath
)
{
console
.
log
(
'
imagePath
'
,
imagePath
)
this
.
$emit
(
'
input
'
,
imagePath
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.plugin-images
{
display
:
inline-block
;
width
:
auto
;
.el-upload
{
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
.pic-uploader-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.pic
{
width
:
120px
;
height
:
120px
;
display
:
block
;
}
.el-upload
:hover
{
border-color
:
#409eff
;
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/ImgsUpload/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"mul-pic-upload"
>
<vue-draggable
v-model=
"imageList"
@
start=
"onDragStart"
@
end=
"onDragEnd"
class=
"el-upload-list el-upload-list--picture-card"
>
<!--拷贝上传图片组件生成的预览图元素代码,用绑定的model循环生成可拖拽元素-->
<li
v-for=
"(item,index) in imageList"
:key=
"index"
tabindex=
"0"
class=
"el-upload-list__item is-success"
>
<img
:src=
"item.url"
alt
class=
"el-upload-list__item-thumbnail"
/>
<a
class=
"el-upload-list__item-name"
>
<i
class=
"el-icon-document"
></i>
</a>
<label
class=
"el-upload-list__item-status-label"
>
<i
class=
"el-icon-upload-success el-icon-check"
></i>
</label>
<span
class=
"el-upload-list__item-actions"
>
<span
class=
"el-upload-list__item-preview"
>
<i
class=
"el-icon-zoom-in"
@
click=
"handlePictureCardPreview(item.url)"
></i>
</span>
<span
class=
"el-upload-list__item-delete"
@
click=
"handleRemove(index)"
v-if=
"!disabled"
>
<i
class=
"el-icon-delete"
></i>
</span>
</span>
</li>
<li
class=
"el-upload-list__item"
@
click=
"elxImgboxHandle"
v-if=
"!disabled && this.imageList.length
<
this.limit
"
>
<div
tabindex=
"0"
class=
"el-upload el-upload--picture-card"
>
<i
class=
"el-icon-plus"
></i>
</div>
<!-- 弹窗, 新增图片 -->
<elx-imgbox
v-if=
"elxImgboxVisible"
ref=
"elxImgbox"
@
refreshPic=
"refreshPic"
></elx-imgbox>
</li>
</vue-draggable>
<!--
<div
v-if=
"prompt"
>
{{
$t
(
"
biz.imgbox.PicMaxQuantity
"
)
}}{{
limit
}}
</div>
-->
<el-dialog
:visible.sync=
"dialogVisible"
:modal=
"modal"
top=
"7vh"
>
<img
width=
"100%"
:src=
"dialogImageUrl"
alt
/>
</el-dialog>
</div>
</
template
>
<
script
>
import
VueDraggable
from
'
vuedraggable
'
import
ElxImgbox
from
'
@/components/imgbox
'
export
default
{
data
()
{
return
{
dialogImageUrl
:
''
,
dialogVisible
:
false
,
elxImgboxVisible
:
false
,
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
,
imageList
:
[]
}
},
components
:
{
VueDraggable
,
ElxImgbox
},
props
:
{
value
:
{
default
:
''
,
type
:
String
},
// 最大上传数量
limit
:
{
default
:
9
,
type
:
Number
},
// false: 能对图片进行操作 true: 不能对图片进行操作
disabled
:
{
default
:
false
,
type
:
Boolean
},
modal
:
{
default
:
true
,
type
:
Boolean
},
prompt
:
{
default
:
true
,
type
:
Boolean
}
},
watch
:
{
value
:
function
(
newVal
,
oldVal
)
{
let
res
=
[]
if
(
this
.
value
)
{
let
imageArray
=
this
.
value
.
split
(
'
,
'
)
for
(
let
i
=
0
;
i
<
imageArray
.
length
;
i
++
)
{
if
(
imageArray
[
i
])
{
res
.
push
({
url
:
this
.
getImgSrc
(
imageArray
[
i
]),
response
:
imageArray
[
i
]
})
}
}
}
this
.
imageList
=
res
},
imageList
:
function
(
newVal
,
oldVal
)
{
let
pics
=
this
.
imageList
.
map
(
file
=>
{
return
file
.
response
}).
join
(
'
,
'
)
this
.
$emit
(
'
input
'
,
pics
)
}
},
methods
:
{
/**
* 获取图片路径
*/
getImgSrc
(
img
)
{
if
(
!
img
)
{
return
''
}
if
(
img
.
indexOf
(
'
http://
'
)
===
0
||
img
.
indexOf
(
'
https://
'
)
===
0
)
{
return
img
}
return
this
.
resourcesUrl
+
img
},
/**
* 删除图片
*/
handleRemove
(
index
)
{
this
.
imageList
.
splice
(
index
,
1
)
let
pics
=
this
.
imageList
.
map
(
file
=>
{
return
file
.
response
}).
join
(
'
,
'
)
this
.
$emit
(
'
input
'
,
pics
)
},
/**
* 放大图片
*/
handlePictureCardPreview
(
imgUrl
)
{
this
.
dialogImageUrl
=
imgUrl
this
.
dialogVisible
=
true
},
onDragStart
(
e
)
{
e
.
target
.
classList
.
add
(
'
hideShadow
'
)
},
onDragEnd
(
e
)
{
e
.
target
.
classList
.
remove
(
'
hideShadow
'
)
},
/**
* 打开图片选择窗
*/
elxImgboxHandle
()
{
let
num
=
this
.
limit
-
this
.
imageList
.
length
if
(
num
<
1
)
{
this
.
$message
.
error
(
'
可选择照片数量已达上限
'
)
return
}
this
.
elxImgboxVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
.
elxImgbox
.
init
(
0
,
num
)
})
},
/**
* 接收回调的图片数据
*/
refreshPic
(
imagePath
)
{
let
imageArray
=
imagePath
.
split
(
'
,
'
)
let
pics
=
imageArray
.
map
(
img
=>
{
return
img
}).
join
(
'
,
'
)
if
(
this
.
value
)
{
// let picArray = imagePath.split(',')
// console.log(picArray.length, this.value, !this.value)
pics
=
this
.
value
+
'
,
'
+
pics
}
this
.
$emit
(
'
input
'
,
pics
)
}
}
}
</
script
>
<
style
lang=
"scss"
scope
>
.mul-pic-upload
{
.upload-component
{
display
:
inline
;
}
.el-upload-list--picture-card
.el-upload-list__item
{
width
:
120px
;
height
:
120px
;
border
:
1px
dashed
#d9d9d9
;
}
.el-upload--picture-card
{
border
:
0
;
font-size
:
28px
;
color
:
#8c939d
;
background
:
#fff
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.hideShadow
{
.el-upload-list__item-actions
{
display
:
none
;
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/LangSelect/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<el-dropdown
trigger=
"click"
class=
"international"
@
command=
"handleSetLanguage"
>
<div>
<svg-icon
class-name=
"international-icon"
icon-class=
"language"
/>
</div>
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
:disabled=
"language==='zh'"
command=
"zh"
>
中文
</el-dropdown-item>
<el-dropdown-item
:disabled=
"language==='en'"
command=
"en"
>
English
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</
template
>
<
script
>
export
default
{
computed
:
{
language
()
{
return
this
.
$store
.
getters
.
language
}
},
methods
:
{
handleSetLanguage
(
lang
)
{
this
.
$i18n
.
locale
=
lang
this
.
$store
.
dispatch
(
'
app/setLanguage
'
,
lang
)
this
.
$message
({
message
:
'
Switch Language Success
'
,
type
:
'
success
'
})
}
}
}
</
script
>
front-end/mall4cloud-multishop-master/src/components/OfflineManage/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<el-dialog
:visible.sync=
"operateDialogVisible"
:close-on-click-modal=
"false"
title=
"下线管理"
:lock-scroll=
"true"
:append-to-body=
"true"
:destroy-on-close=
"true"
width=
"500px"
top=
"0"
class=
"operate-dlg"
>
<div
class=
"off-shelf-mag"
>
<div
class=
"msg"
>
<div
class=
"msg-item"
>
<div
class=
"tit"
>
处理人:
</div>
<div
class=
"int"
>
{{
offlineDetail
.
handler
}}
</div>
</div>
<div
class=
"msg-item"
>
<div
class=
"tit"
>
下线时间:
</div>
<div
class=
"int"
>
{{
offlineDetail
.
createTime
}}
</div>
</div>
<div
class=
"msg-item"
>
<div
class=
"tit"
>
处理状态:
</div>
<el-tag
v-if=
"offlineDetail.status === 1"
type=
"danger"
>
平台下线
</el-tag>
<el-tag
v-if=
"offlineDetail.status === 2"
type=
"warning"
>
等待审核
</el-tag>
<el-tag
v-if=
"offlineDetail.status === 3"
type=
"success"
>
审核通过
</el-tag>
<el-tag
v-if=
"offlineDetail.status === 4"
type=
"danger"
>
审核未通过
</el-tag>
</div>
<div
class=
"msg-item"
>
<div
class=
"tit"
>
下线原因:
</div>
<div
class=
"int"
>
{{
offlineDetail
.
offlineReason
}}
</div>
</div>
<div
class=
"msg-item"
>
<div
class=
"tit"
>
申请理由:
</div>
<div
class=
"int"
><el-input
v-model=
"reapplyReason"
type=
"textarea"
/></div>
</div>
</div>
<div
v-if=
"offlineDetail.offlineHandleEventItemList.length > 0"
class=
"log"
>
<div
class=
"log-tit"
>
申请历史
</div>
<div
v-for=
"(item,index) in offlineDetail.offlineHandleEventItemList"
:key=
"index"
class=
"log-item"
>
<p>
申请时间:
{{
item
.
reapplyTime
}}
</p>
<p>
申请理由:
{{
item
.
reapplyReason
}}
</p>
</div>
</div>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"operateDialogVisible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"rereapplyDataSubmit()"
>
确认审核
</el-button>
</div>
</div>
</el-dialog>
</
template
>
<
script
>
import
*
as
api
from
'
@/api/product/list
'
export
default
{
data
()
{
return
{
operateDialogVisible
:
false
,
// 操作对话框
offlineDetail
:
{},
// 最新下线商品
offlineReasonError
:
false
,
// 理由出错
reapplyReason
:
''
,
// 申请理由
}
},
methods
:
{
init
(
data
)
{
this
.
operateDialogVisible
=
true
this
.
offlineDetail
=
data
},
/**
* 提交上架申请
*/
rereapplyDataSubmit
()
{
if
(
!
this
.
reapplyReason
)
{
this
.
$message
({
message
:
'
请填写申请理由
'
,
type
:
'
warning
'
,
duration
:
1000
})
return
}
let
data
=
{
eventId
:
this
.
offlineDetail
.
eventId
,
reapplyReason
:
this
.
reapplyReason
}
this
.
$emit
(
'
rereapplyDataSubmit
'
,
data
)
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
// 下架管理-操作弹窗
.operate-dlg.el-dialog__wrapper
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.operate-dlg
{
.el-dialog__body
{
padding
:
10px
20px
;
.off-shelf-mag
{
.msg
{
margin-bottom
:
10px
;
.msg-item
{
display
:
flex
;
align-items
:
center
;
justify-content
:
flex-start
;
width
:
100%
;
margin-bottom
:
20px
;
.tit
{
width
:
80px
;
padding-right
:
10px
;
text-align
:
right
;
}
.int
{
width
:
380px
;
}
}
}
.log
{
border-top
:
1px
solid
#eee
;
border-bottom
:
1px
solid
#eee
;
padding
:
10px
0
;
p
{
margin
:
0
;
padding
:
0
;
line-height
:
1
.5em
;
}
.log-tit
{
font-size
:
14px
;
font-weight
:
bold
;
margin-bottom
:
10px
;
}
.log-item
:not
(
:last-child
)
{
margin-bottom
:
8px
;
}
}
.dialog-footer
{
text-align
:
right
;
margin-bottom
:
10px
;
margin-top
:
30px
;
}
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Pagination/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
:class=
"
{ hidden: hidden }" class="pagination-container">
<el-pagination
:background=
"background"
:current-page.sync=
"currentPage"
:page-size.sync=
"pageSize"
:layout=
"layout"
:page-sizes=
"pageSizes"
:total=
"total"
v-bind=
"$attrs"
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
/>
</div>
</
template
>
<
script
>
import
{
scrollTo
}
from
'
@/utils/scroll-to
'
export
default
{
name
:
'
Pagination
'
,
props
:
{
total
:
{
required
:
true
,
type
:
Number
},
page
:
{
type
:
Number
,
default
:
1
},
limit
:
{
type
:
Number
,
default
:
20
},
pageSizes
:
{
type
:
Array
,
default
()
{
return
[
this
.
limit
,
20
,
30
,
50
]
}
},
layout
:
{
type
:
String
,
default
:
'
total, sizes, prev, pager, next, jumper
'
},
background
:
{
type
:
Boolean
,
default
:
true
},
autoScroll
:
{
type
:
Boolean
,
default
:
true
},
hidden
:
{
type
:
Boolean
,
default
:
false
}
},
computed
:
{
currentPage
:
{
get
()
{
return
this
.
page
},
set
(
val
)
{
this
.
$emit
(
'
update:page
'
,
val
)
}
},
pageSize
:
{
get
()
{
return
this
.
limit
},
set
(
val
)
{
this
.
$emit
(
'
update:limit
'
,
val
)
}
}
},
methods
:
{
handleSizeChange
(
val
)
{
this
.
$emit
(
'
pagination
'
,
{
pageNum
:
this
.
currentPage
,
pageSize
:
val
})
if
(
this
.
autoScroll
)
{
scrollTo
(
0
,
800
)
}
},
handleCurrentChange
(
val
)
{
this
.
$emit
(
'
pagination
'
,
{
pageNum
:
val
,
pageSize
:
this
.
page
})
if
(
this
.
autoScroll
)
{
scrollTo
(
0
,
800
)
}
}
}
}
</
script
>
<
style
scoped
>
.pagination-container
{
background
:
#fff
;
padding
:
10px
16px
30px
;
text-align
:
right
;
}
.pagination-container.hidden
{
display
:
none
;
}
.el-pagination
{
font-weight
:
normal
;
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/PicUpload/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div>
<el-upload
class=
"pic-uploader-component"
:action=
"resourcesUrl"
:data=
"dataForm"
:show-file-list=
"false"
:on-success=
"handleUploadSuccess"
:before-upload=
"beforeUpload"
>
<img
v-if=
"value"
:src=
"getImgSrc"
class=
"pic"
>
<i
v-else
class=
"el-icon-plus pic-uploader-icon"
/>
</el-upload>
</div>
</
template
>
<
script
>
import
{
ossInfo
}
from
'
@/api/biz/oss
'
import
{
getUUID
}
from
'
@/utils/index
'
export
default
{
props
:
{
value
:
{
default
:
''
,
type
:
String
}
},
data
()
{
return
{
dataForm
:
{
policy
:
''
,
signature
:
''
,
key
:
''
,
ossaccessKeyId
:
''
,
dir
:
''
,
host
:
''
},
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
}
},
computed
:
{
getImgSrc
()
{
if
(
!
this
.
value
)
{
return
''
}
if
(
this
.
value
.
indexOf
(
'
http://
'
)
===
0
||
this
.
value
.
indexOf
(
'
https://
'
)
===
0
)
{
return
this
.
value
}
return
this
.
resourcesUrl
+
this
.
value
}
},
methods
:
{
// 图片上传
handleUploadSuccess
(
response
,
file
,
fileList
)
{
this
.
dataForm
.
key
this
.
$emit
(
'
input
'
,
'
/
'
+
this
.
dataForm
.
key
)
},
// 限制图片上传大小
beforeUpload
(
file
)
{
const
isLt2M
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isLt2M
)
{
this
.
$message
.
error
(
'
上传图片大小不能超过 2MB!
'
)
return
false
}
const
_self
=
this
return
new
Promise
((
resolve
,
reject
)
=>
{
ossInfo
().
then
(
response
=>
{
_self
.
dataForm
.
policy
=
response
.
policy
_self
.
dataForm
.
signature
=
response
.
signature
_self
.
dataForm
.
ossaccessKeyId
=
response
.
accessid
_self
.
dataForm
.
key
=
response
.
dir
+
getUUID
()
_self
.
dataForm
.
dir
=
response
.
dir
_self
.
dataForm
.
host
=
response
.
host
resolve
(
true
)
}).
catch
(
err
=>
{
console
.
log
(
err
)
reject
(
false
)
})
})
}
}
}
</
script
>
<
style
lang=
"scss"
>
.pic-uploader-component
.el-upload
{
border
:
1px
dashed
#d9d9d9
;
border-radius
:
6px
;
cursor
:
pointer
;
position
:
relative
;
overflow
:
hidden
;
.pic-uploader-icon
{
font-size
:
28px
;
color
:
#8c939d
;
width
:
120px
;
height
:
120px
;
line-height
:
120px
;
text-align
:
center
;
}
.pic
{
width
:
auto
;
height
:
120px
;
display
:
block
;
}
}
.pic-uploader-component
.el-upload
:hover
{
border-color
:
#409EFF
;
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/PicturePreview/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<el-dialog
:close-on-click-modal=
"false"
:visible.sync=
"visible"
top=
"10vh"
:append-to-body=
"true"
:lock-scroll=
"true"
class=
"img-preview"
width=
"650px"
>
<div
class=
"img-box"
>
<img
:src=
"(imgUrl).indexOf('http')===-1 ? resourcesUrl + imgUrl : imgUrl"
class=
"img"
>
</div>
</el-dialog>
</
template
>
<
script
>
export
default
{
data
()
{
return
{
imgUrl
:
''
,
visible
:
false
,
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
,
}
},
methods
:
{
init
(
imgUrl
)
{
this
.
imgUrl
=
imgUrl
this
.
visible
=
true
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.img-preview
{
.img-box
{
display
:
block
;
width
:
100%
;
max-height
:
700px
;
overflow
:
auto
;
}
.
img-box
:
:-
webkit-scrollbar
{
display
:
none
;
}
.img
{
display
:
block
;
width
:
100%
;
height
:
auto
;
}
}
</
style
>
\ No newline at end of file
front-end/mall4cloud-multishop-master/src/components/ProdsSelect/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<el-dialog
title=
"商品选择"
:modal-append-to-body=
"false"
:append-to-body=
"true"
top=
"4vh"
:close-on-click-modal=
"false"
:visible.sync=
"visible"
width=
"800px"
@
close=
"closeModule"
>
<el-form
:inline=
"true"
:model=
"dataForm"
class=
"demo-form-inline"
>
<el-form-item
label=
"商品名称"
>
<el-input
v-model.trim=
"dataForm.name"
placeholder=
"商品名称"
clearable
style=
"width: 180px"
></el-input>
</el-form-item>
<el-form-item
label=
"上级分类"
>
<el-cascader
expand-trigger=
"hover"
:options=
"categoryList"
:props=
"categoryTreeProps"
:clearable=
"true"
v-model=
"selectedCategory"
@
change=
"handleChange"
style=
"width: 180px"
></el-cascader>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"searchProd"
icon=
"el-icon-search"
>
查询
</el-button>
</el-form-item>
<el-form-item>
<el-button
@
click=
"clean"
icon=
"el-icon-delete"
>
清空
</el-button>
</el-form-item>
</el-form>
<div
class=
"prods-select-body"
>
<el-table
ref=
"prodTable"
:data=
"pageVO.list"
border
v-loading=
"dataListLoading"
highlight-current-row
@
selection-change=
"selectChangeHandle"
style=
"width: 100%"
>
<el-table-column
v-if=
"isSingle"
width=
"50"
header-align=
"center"
align=
"center"
>
<template
slot-scope=
"
{row}">
<div>
<el-radio
:label=
"row.spuId"
v-model=
"singleSelectspuId"
@
change.native=
"getSelectProdRow(row)"
>
</el-radio
>
</div>
</
template
>
</el-table-column>
<el-table-column
v-if=
"!isSingle"
type=
"selection"
header-align=
"center"
align=
"center"
width=
"50"
></el-table-column>
<el-table-column
align=
"center"
width=
"140"
label=
"商品图片"
>
<
template
slot-scope=
"{row}"
>
<img
:src=
"(row.mainImgUrl).indexOf('http')===-1 ? resourcesUrl + row.mainImgUrl : row.mainImgUrl"
width=
"100"
height=
"100"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"spuName"
header-align=
"center"
align=
"center"
label=
"商品名称"
></el-table-column>
<el-table-column
prop=
"priceFee"
header-align=
"center"
align=
"center"
label=
"商品价格"
width=
"200px"
></el-table-column>
</el-table>
</div>
<!-- 分页条 -->
<pagination
v-show=
"pageVO.total>0"
:total=
"pageVO.total"
:page.sync=
"pageQuery.pageNum"
:limit.sync=
"pageQuery.pageSize"
@
pagination=
"getDataList()"
/>
<span
slot=
"footer"
>
<el-button
@
click=
"visible = false"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitProds()"
>
确认
</el-button>
</span>
</el-dialog>
</template>
<
script
>
import
{
treeDataTranslate
,
idList
}
from
'
@/utils
'
import
{
page
}
from
'
@/api/product/list
'
import
{
shopCategoryPage
}
from
'
@/api/product/category
'
import
Pagination
from
'
@/components/Pagination
'
import
Big
from
'
big.js
'
export
default
{
components
:
{
Pagination
},
data
()
{
return
{
visible
:
false
,
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
,
// 查询的参数
pageQuery
:
{
pageSize
:
10
,
pageNum
:
1
,
spuStatus
:
1
},
// 返回参数
pageVO
:
{
list
:
[],
// 返回的列表
total
:
0
,
// 一共多少条数据
pages
:
0
// 一共多少页
},
// 查询参数
searchParam
:
{
},
dataForm
:
{
name
:
''
,
product
:
''
},
singleSelectspuId
:
0
,
allData
:
[],
selectProds
:
[],
shopCategoryId
:
null
,
pageIndex
:
1
,
pageSize
:
10
,
totalPage
:
0
,
dataListLoading
:
false
,
addOrUpdateVisible
:
false
,
dataListSelections
:
[],
categoryList
:
[],
selectedCategory
:
[],
categoryTreeProps
:
{
value
:
'
categoryId
'
,
label
:
'
name
'
}
}
},
props
:
{
isSingle
:
{
default
:
false
,
type
:
Boolean
},
prodType
:
{
default
:
null
,
type
:
Number
},
dataUrl
:
{
default
:
'
/prod/prod/page
'
,
type
:
String
}
},
activated
()
{
this
.
getDataList
()
},
methods
:
{
// 获取数据列表
init
(
selectProds
)
{
this
.
singleSelectspuId
=
0
this
.
selectProds
=
selectProds
this
.
visible
=
true
this
.
dataListLoading
=
true
this
.
clean
()
if
(
this
.
selectProds
)
{
this
.
selectProds
.
forEach
(
row
=>
{
this
.
dataListSelections
.
push
(
row
)
})
}
this
.
getDataList
()
this
.
getCategoryList
()
},
getCategoryList
()
{
shopCategoryPage
().
then
((
data
)
=>
{
this
.
categoryList
=
treeDataTranslate
(
data
,
'
categoryId
'
,
'
parentId
'
)
})
},
getDataList
()
{
page
({
...
this
.
pageQuery
,
...
this
.
searchParam
}).
then
((
pageVO
)
=>
{
this
.
pageVO
=
pageVO
this
.
pageVO
.
list
.
forEach
(
prod
=>
{
prod
.
priceFee
=
new
Big
(
prod
.
priceFee
).
div
(
100
).
toFixed
(
2
)
})
this
.
dataListLoading
=
false
if
(
this
.
selectProds
)
{
this
.
$nextTick
(()
=>
{
this
.
selectProds
.
forEach
(
row
=>
{
let
index
=
this
.
pageVO
.
list
.
findIndex
((
prodItem
)
=>
prodItem
.
spuId
===
row
.
spuId
)
this
.
$refs
.
prodTable
.
toggleRowSelection
(
this
.
pageVO
.
list
[
index
])
})
})
}
})
},
// 每页数
sizeChangeHandle
(
val
)
{
this
.
pageQuery
.
pageSize
=
val
this
.
pageQuery
.
pageNum
=
1
this
.
getDataList
()
},
// 当前页
currentChangeHandle
(
val
)
{
this
.
pageQuery
.
pageNum
=
val
this
.
getDataList
()
},
// 单选商品事件
getSelectProdRow
(
row
)
{
this
.
dataListSelections
=
[
row
]
},
// 多选点击事件
selectChangeHandle
(
selection
)
{
this
.
pageVO
.
list
.
forEach
((
tableItem
)
=>
{
let
selectedProdIndex
=
selection
.
findIndex
((
selectedProd
)
=>
{
if
(
!
selectedProd
)
{
return
false
}
return
selectedProd
.
spuId
===
tableItem
.
spuId
})
let
dataSelectedProdIndex
=
this
.
dataListSelections
.
findIndex
((
dataSelectedProd
)
=>
dataSelectedProd
.
spuId
===
tableItem
.
spuId
)
if
(
selectedProdIndex
>
-
1
&&
dataSelectedProdIndex
===
-
1
)
{
this
.
dataListSelections
.
push
(
tableItem
)
}
else
if
(
selectedProdIndex
===
-
1
&&
dataSelectedProdIndex
>
-
1
)
{
this
.
dataListSelections
.
splice
(
dataSelectedProdIndex
,
1
)
}
})
},
/**
* 获取分类id
*/
handleChange
(
val
)
{
this
.
shopCategoryId
=
val
[
val
.
length
-
1
]
},
/**
* 根据条件搜索商品
*/
searchProd
()
{
this
.
pageQuery
.
pageNum
=
1
this
.
searchParam
=
{
name
:
this
.
dataForm
.
name
,
categoryId
:
this
.
shopCategoryId
}
this
.
getDataList
()
},
/**
* 清空搜索条件
*/
clean
()
{
this
.
name
=
''
this
.
shopCategoryId
=
null
this
.
selectedCategory
=
idList
(
this
.
categoryList
,
this
.
shopCategoryId
,
'
categoryId
'
,
'
children
'
).
reverse
()
},
closeModule
()
{
this
.
name
=
''
this
.
shopCategoryId
=
null
},
// 确定事件
submitProds
()
{
let
prods
=
[]
this
.
dataListSelections
.
forEach
(
item
=>
{
let
prodIndex
=
prods
.
findIndex
((
prod
)
=>
prod
.
spuId
===
item
.
spuId
)
if
(
prodIndex
===
-
1
)
{
prods
.
push
(
{
spuId
:
item
.
spuId
,
spuName
:
item
.
spuName
,
mainImgUrl
:
item
.
mainImgUrl
,
activityId
:
item
.
activityId
,
prodType
:
item
.
prodType
}
)
}
})
// var msgInfo = ''
// // 秒杀活动选择商品的提示
// if (this.dataUrl.includes('canSekcillProdPage')) {
// msgInfo = this.$i18n.t('components.seckillWhetherToContinue')
// } else if (this.dataUrl.includes('getNotGroupProdPage')) {
// // 拼团活动选择商品的提示
// msgInfo = this.$i18n.t('components.groupWhetherToContinue')
// }
// if (msgInfo !== '' && msgInfo !== null) {
// this.prodIsSeckill(prods, msgInfo)
// }else {
this
.
$emit
(
'
refreshSelectProds
'
,
prods
)
this
.
dataListSelections
=
[]
this
.
visible
=
false
// }
},
/**
* 查询商品是否在参与秒杀活动
*/
// prodIsSeckill(prods, msgInfo) {
// let spuIds = []
// for (let index = 0; index
<
prods
.
length
;
index
++
)
{
// spuIds.push(prods[index].spuId)
// }
// this.$http({
// url: this.$http.adornUrl('/admin/discount/prodIsDiscount'),
// method: 'post',
// data: spuIds
// }).then(({ data }) => {
// var msg = data
// if (msg !== undefined && msg !== null && msg !== '') {
// this.$confirm(msgInfo, this.$i18n.t('text.tips'), {
// confirmButtonText: this.$i18n.t('crud.filter.submitBtn'),
// cancelButtonText: this.$i18n.t('crud.filter.cancelBtn'),
// type: 'warning'
// }).then(() => {
// this.$emit('refreshSelectProds', prods)
// this.dataListSelections = []
// this.visible = false
// }).catch(() => { })
// } else {
// this.$emit('refreshSelectProds', prods)
// this.dataListSelections = []
// this.visible = false
// }
// })
// }
}
}
</
script
>
<
style
lang=
"scss"
scope
>
.demo-form-inline
{
.el-form-item.el-form-item--medium
{
margin-bottom
:
22px
;
}
}
.el-dialog__body
{
padding
:
20px
;
}
.el-dialog__header
{
border-bottom
:
1px
solid
#eee
;
}
.pagination-container
{
padding
:
0
!
important
;
margin-top
:
20px
;
}
.prods-select-body
{
height
:
600px
;
overflow
:
auto
;
// border-top: 1px solid #eeeeee;
// border-right: 1px solid #eeeeee;
// border-bottom: 1px solid #eeeeee;
}
.el-dialog__footer
{
padding-top
:
0
;
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/ProductDetails/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"prod-details"
>
<el-tabs
type=
"card"
>
<el-form-item
label=
"产品详情"
>
<tiny-mce
ref=
"content"
v-model=
"dataForm.detail"
:width=
"850"
/>
</el-form-item>
<!-- 中文 -->
<!--
<el-tab-pane
label=
"中文信息"
>
<el-form-item
label=
"商品名称"
prop=
"nameCn"
>
<el-col
:span=
"8"
>
<el-input
v-model=
"dataForm.prodNameCn"
placeholder=
"请输入商品名称"
maxlength=
"50"
/>
</el-col>
</el-form-item>
<el-form-item
label=
"产品卖点"
prop=
"briefCn"
>
<el-col
:span=
"8"
>
<el-input
v-model=
"dataForm.briefCn"
type=
"textarea"
:autosize=
"
{ minRows: 2, maxRows: 4 }"
placeholder="请输入产品卖点"
/>
</el-col>
</el-form-item>
<el-form-item
label=
"产品详情"
prop=
"contentCn"
>
<tiny-mce
ref=
"content"
v-model=
"dataForm.contentCn"
style=
"width: 1000px"
/>
</el-form-item>
</el-tab-pane>
-->
<!-- 英文 -->
<!--
<el-tab-pane
label=
"English Information"
>
<el-form-item
label=
"Prod name"
prop=
"prodNameEn"
>
<el-col
:span=
"8"
>
<el-input
v-model=
"dataForm.prodNameEn"
placeholder=
"Prod name"
maxlength=
"50"
/>
</el-col>
</el-form-item>
<el-form-item
label=
"Selling point"
prop=
"briefEn"
>
<el-col
:span=
"8"
>
<el-input
v-model=
"dataForm.briefEn"
type=
"textarea"
:autosize=
"
{ minRows: 2, maxRows: 4 }"
placeholder="Selling point"
/>
</el-col>
</el-form-item>
<el-form-item
label=
"product details"
prop=
"contentEn"
>
<tiny-mce
ref=
"content"
v-model=
"dataForm.contentEn"
style=
"width: 1000px"
/>
</el-form-item>
</el-tab-pane>
-->
</el-tabs>
</div>
</
template
>
<
script
>
import
TinyMce
from
'
@/components/Tinymce
'
export
default
{
components
:
{
TinyMce
},
props
:
{
dataForm
:
{
type
:
Object
,
default
()
{
return
{}
}
},
},
data
()
{
return
{
}
}
}
</
script
>
<
style
lang=
"scss"
>
.prod-details
{
.el-tabs--card
>
.el-tabs__header
{
border-bottom
:
0
;
}
}
</
style
>
\ No newline at end of file
front-end/mall4cloud-multishop-master/src/components/Sku/SkuBlock/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"ease-sku"
>
<sku-group
v-for=
"(item, index) in data"
:key=
"index"
:index=
"index"
:sku=
"item"
:skuTree=
"skuTreeData"
:onChangeHasImg=
"onChangeHasImg"
:onSkuChange=
"rebuildSku"
:onSkuRemove=
"handleSkuRemove"
/>
<!-- 添加属性 -->
<div
class=
"part-form-item"
>
<el-button
class=
"add-btn"
size=
"mini"
@
click=
"addSku"
><i
class=
"el-icon-plus"
></i>
添加属性
</el-button>
<div
v-if=
"!categoryId && warning"
class=
"warning"
>
请先选择分类!
</div>
<div
v-if=
"!hasSkuValue"
class=
"warning"
>
请先选择已添加属性的属性值!
</div>
<div
v-if=
"!hasSkuId"
class=
"warning"
>
请先选择已添加属性!
</div>
</div>
</div>
</
template
>
<
script
>
import
skuGroup
from
'
@/components/Sku/SkuGroup
'
import
{
Message
}
from
'
element-ui
'
const
noop
=
res
=>
res
const
noopPromise
=
()
=>
Promise
.
resolve
(
noop
)
export
default
{
name
:
'
sku-block
'
,
provide
()
{
return
{
'
ease
'
:
this
}
},
components
:
{
skuGroup
},
data
()
{
return
{
data
:
this
.
salesAttrs
,
skuTreeData
:
this
.
skuTree
,
warning
:
false
,
hasSkuValue
:
this
.
hasSkuVal
,
hasSkuId
:
true
}
},
props
:
{
maxSize
:
{
type
:
Number
,
default
:
2
},
hasSkuImg
:
{
type
:
Boolean
,
default
:
false
},
showAddSkuImage
:
{
type
:
Boolean
,
default
:
true
},
salesAttrs
:
{
type
:
Array
,
default
()
{
return
[]
}
},
saveSalesAttrs
:
{
type
:
Array
,
default
()
{
return
[]
}
},
action
:
{
type
:
String
,
default
:
''
},
headers
:
{
type
:
Object
,
default
()
{
return
{}
}
},
accept
:
{
type
:
String
,
default
:
''
},
uploadName
:
{
type
:
String
,
default
:
'
resource
'
},
// 可选规格列表
skuTree
:
{
type
:
Array
,
default
()
{
return
[]
}
},
sku
:
{
type
:
Object
,
default
()
{
return
{}
}
},
categoryId
:
{
type
:
Number
,
default
:
null
},
// 自定义sku的id key
optionValue
:
{
type
:
String
,
default
:
'
id
'
},
// 自定义sku的text key
optionText
:
{
type
:
String
,
default
:
'
text
'
},
// 异步获取规格列表
onFetchGroup
:
{
type
:
Function
,
default
:
noopPromise
},
// 异步获取规格可选值
onFetchSku
:
{
type
:
Function
,
default
:
noopPromise
},
// 创建新的规格名
onCreateGroup
:
{
type
:
Function
,
default
:
noopPromise
},
// 创建新的规格值
onCreateSku
:
{
type
:
Function
,
default
:
noopPromise
},
// 图片预览
onPreviewImg
:
{
type
:
Function
,
default
:
noopPromise
},
hasSkuVal
:
{
type
:
Boolean
,
default
:
null
}
},
watch
:
{
data
:
{
deep
:
true
,
immediate
:
true
,
handler
(
salesAttrs
)
{
this
.
$emit
(
'
input
'
,
salesAttrs
)
// 已选属性值,隐藏错误提示
if
(
this
.
data
?.
some
((
item
)
=>
item
.
id
&&
item
.
leaf
?.
length
>
0
))
{
this
.
hasSkuValue
=
true
}
// 已选属性,隐藏错误提示
if
(
this
.
data
?.
some
((
item
)
=>
item
.
id
))
{
this
.
hasSkuId
=
true
}
},
},
skuTree
(
skuTree
)
{
this
.
skuTreeData
=
skuTree
},
categoryId
()
{
if
(
!
this
.
categoryId
)
{
this
.
data
.
splice
(
0
,
this
.
data
.
length
)
}
}
},
methods
:
{
onChangeHasImg
(
data
)
{
this
.
hasSkuImg
=
data
},
addSku
()
{
this
.
hasSkuValue
=
true
this
.
hasSkuId
=
true
if
(
!
this
.
categoryId
)
{
this
.
warning
=
true
return
}
// 未选属性值,提示用户并禁继续选属性
if
(
this
.
data
?.
some
((
item
)
=>
item
.
id
&&
item
.
leaf
&&
!
item
.
leaf
.
length
))
{
this
.
hasSkuValue
=
false
return
}
// 未选已添加属性,提示用户并禁止继续加选属性
if
(
this
.
data
?.
some
((
item
)
=>
!
item
.
id
))
{
this
.
hasSkuId
=
false
return
}
this
.
data
.
push
({
leaf
:
[]
})
},
rebuildSku
(
sku
,
index
)
{
let
{
skuTreeData
,
optionValue
,
optionText
}
=
this
if
(
this
.
data
.
some
(
(
item
,
idx
)
=>
item
[
optionText
]
===
sku
[
optionText
]
&&
index
!==
idx
)
)
{
this
.
$message
({
message
:
'
规格名不能重复
'
,
duration
:
800
});
return
false
}
this
.
$set
(
this
.
data
,
index
,
Object
.
assign
({},
sku
))
this
.
$emit
(
'
on-change
'
,
this
.
data
)
},
handleSkuRemove
(
sku
,
index
)
{
let
{
data
,
skuTreeData
,
optionValue
}
=
this
data
.
splice
(
index
,
1
)
if
(
index
===
0
&&
data
.
length
>
0
)
{
data
[
0
].
leaf
.
map
((
item
)
=>
{
item
.
is_show
=
sku
?.
leaf
[
0
].
is_show
})
// this.hasSkuImg = false
}
// 属性选择列表中不存在被删除的已选属性
if
(
!
skuTreeData
?.
some
(
item
=>
item
[
optionValue
]
===
sku
[
optionValue
]))
{
// 被删除的已选属性id为数字类型(即非手动创建的属性)
if
(
typeof
(
sku
[
optionValue
])
===
'
number
'
)
{
// 删除某个已选属性后,往属性选项列表中增加被删除的已选属性
skuTreeData
.
push
(
sku
)
}
}
// data[index].leaf[0].is_show = false
this
.
$emit
(
'
on-change
'
,
this
.
data
)
}
},
beforeMount
()
{
let
{
onFetchGroup
}
=
this
if
(
typeof
(
onFetchGroup
)
==
'
function
'
)
{
onFetchGroup
().
then
(
skuTree
=>
{
this
.
skuTreeData
=
skuTree
})
}
}
}
</
script
>
<
style
lang=
"scss"
>
.ease-sku
{
.add-btn.el-button
{
border-color
:
#02a1e9
;
color
:
#02a1e9
;
}
.warning
{
display
:
inline-block
;
margin-left
:
15px
;
color
:
#e43130
;
font-size
:
13px
;
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Sku/SkuContainer/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"group-container"
>
<div
class=
"spec-name"
>
<div
v-for=
"(item, index) in sku.leaf"
:key=
"index"
class=
"spec-name-int"
>
<el-tag
:type=
"item.type"
effect=
"plain"
closable
@
close=
"handleRemoveSkuLeaf(index)"
>
{{
item
[
optionText
]
}}
</el-tag>
<div
v-if=
"item.imgUrl"
class=
"spec-imgbox"
>
<img-upload
v-if=
"hasSkuImage"
v-model=
"item.imgUrl"
@
input=
"handleUploadSuccess(item, $event)"
class=
"spec-img"
/>
<div
v-if=
"hasSkuImage && item.imgUrl"
class=
"preview-btn"
@
click=
"picturePreview(item.imgUrl)"
>
预览
</div>
</div>
</div>
<!-- 新增 -->
<div
class=
"sku-item"
v-if=
"sku[optionValue] && sku[optionValue] !== 0"
>
<el-popover
placement=
"bottom"
width=
"200"
trigger=
"click"
v-model=
"visiable"
>
<el-select
class=
"popover-select"
size=
"mini"
v-model=
"leafValue"
multiple
filterable
allow-create
default-first-option
:popper-append-to-body=
"false"
style=
"width:100%"
placeholder=
"属性值"
@
change=
"createSkuLeaf"
@
visible-change=
"status => !status && this.handleSelectSku()"
>
<el-option
v-for=
"item in skuOptions"
:key=
"item[optionValue]"
:label=
"item[optionText]"
:value=
"item[optionValue]"
>
</el-option>
</el-select>
<!-- 新增 -->
<el-button
slot=
"reference"
circle
type=
"primary"
plain
size=
"mini"
class=
"cursor"
><i
class=
"el-icon-plus"
/></el-button>
</el-popover>
</div>
</div>
</div>
</
template
>
<
script
>
import
ImgUpload
from
'
@/components/ImgUpload
'
const
noop
=
res
=>
res
export
default
{
inject
:
[
'
ease
'
],
components
:
{
ImgUpload
},
data
()
{
return
{
visiable
:
false
,
leafValue
:
[],
skuOptions
:
[],
id
:
0
}
},
props
:
{
sku
:
{
type
:
Object
,
default
()
{
return
{}
}
},
hasSkuImage
:
{
type
:
Boolean
,
default
:
false
},
onSkuLeafChange
:
{
type
:
Function
,
default
:
noop
}
},
computed
:
{
optionValue
()
{
return
this
.
ease
.
optionValue
},
optionText
()
{
return
this
.
ease
.
optionText
}
},
watch
:
{
sku
:
{
deep
:
true
,
immediate
:
true
,
handler
(
sku
)
{
this
.
fetchLeafById
(
sku
[
this
.
optionValue
])
}
}
},
methods
:
{
handleHideVisiable
()
{
this
.
visiable
=
false
},
handleResetLeafValue
()
{
this
.
leafValue
=
[]
},
fetchLeafById
(
id
)
{
if
(
!
id
)
return
this
.
ease
.
onFetchSku
(
id
).
then
(
skuOptions
=>
{
this
.
id
=
id
this
.
skuOptions
=
skuOptions
let
skuList
=
[]
// 筛选未选择的属性
this
.
skuOptions
.
forEach
(
skuItem
=>
{
if
(
!
this
.
sku
.
leaf
.
find
(
item
=>
item
.
id
===
skuItem
.
id
))
{
skuList
.
push
(
skuItem
)
}
})
this
.
skuOptions
=
skuList
})
},
handleRemoveSkuLeaf
(
index
)
{
let
{
sku
}
=
this
sku
.
leaf
.
splice
(
index
,
1
)
this
.
onSkuLeafChange
(
sku
.
leaf
)
},
handleRemoveImage
(
id
)
{
let
{
sku
,
optionValue
}
=
this
sku
?.
leaf
?.
forEach
(
item
=>
{
if
(
item
[
optionValue
]
===
id
)
{
item
.
imgUrl
=
''
}
})
this
.
onSkuLeafChange
(
sku
.
leaf
)
},
filterSkuOptions
(
data
)
{
const
oldSellData
=
[];
const
addSelData
=
[]
const
skuOptions
=
this
.
skuOptions
data
.
forEach
(
item
=>
{
if
(
skuOptions
.
find
(
skuItem
=>
skuItem
.
id
===
item
))
{
oldSellData
.
push
(
item
)
}
else
{
addSelData
.
push
(
item
)
}
})
return
{
oldSellData
,
addSelData
}
},
createSkuLeaf
(
selVal
)
{
let
{
sku
,
optionValue
,
skuOptions
}
=
this
// 过滤需要新增的规格值
// data = data.filter(item => typeof (item) === 'string')
const
{
addSelData
,
oldSellData
}
=
this
.
filterSkuOptions
(
selVal
)
if
(
!
addSelData
.
length
)
return
this
.
ease
.
onCreateSku
({
data
:
addSelData
,
id
:
sku
[
optionValue
]
}).
then
((
processedNewOptions
)
=>
{
if
(
processedNewOptions
[
0
].
text
.
length
>
20
)
{
this
.
$message
({
message
:
`属性名长度不可超过20个字符`
,
duration
:
1500
})
processedNewOptions
=
[]
}
skuOptions
.
push
(...
processedNewOptions
)
this
.
$nextTick
(()
=>
{
const
values
=
processedNewOptions
.
map
(
item
=>
item
.
id
).
concat
(
oldSellData
)
this
.
leafValue
=
values
;
// const values = processedNewOptions.map(item => item.id)
// this.leafValue = this.leafValue.filter(item => typeof (item) === 'number')
// this.leafValue.push(...values)
})
})
},
handleSelectSku
(
data
)
{
let
{
sku
,
hasSkuImage
,
optionValue
,
optionText
,
skuOptions
,
leafValue
}
=
this
let
skuLeaf
=
skuOptions
.
filter
(
item
=>
leafValue
.
indexOf
(
item
[
optionValue
])
>=
0
)
skuLeaf
.
map
(
item
=>
{
item
.
is_show
=
hasSkuImage
})
let
skuLeafIds
=
sku
.
leaf
.
map
(
item
=>
item
[
optionValue
])
skuLeaf
.
forEach
(
item
=>
{
if
(
skuLeafIds
.
indexOf
(
item
[
optionValue
])
<
0
)
{
sku
.
leaf
.
push
(
item
)
}
})
// 过滤同名规格值
for
(
var
i
=
0
;
i
<
sku
.
leaf
.
length
;
i
++
)
{
for
(
var
j
=
i
+
1
;
j
<
sku
.
leaf
.
length
;
j
++
)
{
if
(
sku
.
leaf
[
i
][
optionText
]
===
sku
.
leaf
[
j
][
optionText
])
{
sku
.
leaf
.
splice
(
i
,
1
)
j
--
}
}
}
this
.
handleResetLeafValue
()
this
.
handleHideVisiable
()
this
.
onSkuLeafChange
(
sku
.
leaf
)
},
handleUploadSuccess
(
item
,
urls
)
{
this
.
onSkuLeafChange
(
this
.
sku
.
leaf
)
},
// handleUploadSuccess2(response, file, fileList, id) {
// let { sku, optionValue } = this
// sku.leaf.forEach(item => {
// if (item[optionValue] === id) {
// item.imgUrl = response.imgUrl
// }
// })
// this.onSkuLeafChange(sku.leaf)
// },
// 图片预览
picturePreview
(
imgUrl
)
{
this
.
ease
.
onPreviewImg
(
imgUrl
)
},
created
()
{
let
{
sku
,
optionValue
}
=
this
sku
[
optionValue
]
&&
this
.
fetchLeafById
(
sku
[
optionValue
])
}
},
created
()
{
let
{
sku
,
optionValue
}
=
this
sku
[
optionValue
]
&&
this
.
fetchLeafById
(
sku
[
optionValue
])
}
}
</
script
>
<
style
lang=
"scss"
>
.group-container
{
.spec-name
{
margin
:
15px
5px
;
.spec-name-int
{
display
:
inline-block
;
margin-bottom
:
15px
;
margin-right
:
15px
;
vertical-align
:
top
;
// 属性名称
.spec-imgbox
{
display
:
block
;
width
:
60px
;
height
:
60px
;
position
:
relative
;
.preview-btn
{
position
:
absolute
;
bottom
:
-1px
;
left
:
1px
;
display
:
none
;
width
:
100%
;
background
:
rgba
(
0
,
0
,
0
,
0
.2
);
line-height
:
1
.5em
;
text-align
:
center
;
font-size
:
12px
;
border-radius
:
0
0
6px
6px
;
cursor
:
pointer
;
}
.spec-img
{
// margin-left: 25px;
margin-top
:
10px
;
// sku上传图片组件大小修改
.plugin-images
{
.el-upload
{
.pic-uploader-icon
{
width
:
60px
;
height
:
60px
;
line-height
:
60px
;
font-size
:
18px
;
}
.pic
{
height
:
60px
;
}
}
}
}
}
.spec-imgbox
:hover
.preview-btn
{
display
:
block
;
}
.error-tips
{
margin-left
:
25px
;
margin-top
:
10px
;
color
:
#e43130
;
}
.el-tag--plain
{
position
:
relative
;
min-width
:
100px
;
color
:
#606266
;
border-color
:
#dcdfe6
;
padding-right
:
22px
;
}
.el-tag--plain
.el-tag__close
{
position
:
absolute
;
top
:
50%
;
transform
:
translateY
(
-50%
);
right
:
4px
;
color
:
#606266
;
}
.el-tag--plain
.el-tag__close
:hover
{
background
:
#dcdfe6
;
}
}
.add-spec-btn
{
display
:
inline-block
;
font-size
:
12px
;
line-height
:
1
.5em
;
margin-top
:
10px
;
color
:
#02a1e9
;
cursor
:
pointer
;
}
.sku-item
{
display
:
inline-block
;
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Sku/SkuGroup/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<!-- 属性组 -->
<div
class=
"part-spec-section"
>
<div
class=
"spec-box"
>
<div
class=
"spec-select"
>
<div
class=
"sel-box"
>
<el-select
size=
"mini"
v-model=
"skuValue"
placeholder=
"请选择"
allow-create
filterable
default-first-option
:popper-append-to-body=
"false"
:filter-method=
"filterMethod"
style=
"min-width:100px"
@
change=
"handleSelectSku"
>
<el-option
v-for=
"item in ease.skuTreeData"
:key=
"item[optionValue]"
:label=
"item[optionText]"
:value=
"item[optionValue]"
/>
</el-select>
</div>
<!--
<div
v-if=
"index === 0 && ease.showAddSkuImage"
class=
"sel-add-img"
>
-->
<!--
<el-checkbox
v-model=
"hasSkuImage"
@
change=
"handleCheckedSkuImage"
>
添加属性图片
</el-checkbox>
-->
<!--
</div>
-->
</div>
<div
class=
"del-btn"
@
click=
"onSkuRemove(sku, index)"
>
删除属性
</div>
</div>
<!-- sku值 -->
<sku-container
:sku=
"sku"
:hasSkuImage=
"hasSkuImage"
:onSkuLeafChange=
"handleSkuLeafChange"
/>
</div>
</
template
>
<
script
>
// import ImgUpload from '@/components/ImgUpload'
import
skuContainer
from
'
@/components/Sku/SkuContainer
'
const
noop
=
res
=>
res
export
default
{
components
:
{
skuContainer
},
inject
:
[
'
ease
'
],
props
:
{
index
:
{
type
:
Number
,
default
:
0
},
sku
:
{
type
:
Object
,
default
()
{
return
{}
}
},
// 自定义sku的id key
optionValue
:
{
type
:
String
,
default
:
'
id
'
},
// 自定义sku的text key
optionText
:
{
type
:
String
,
default
:
'
text
'
},
onSkuChange
:
{
type
:
Function
,
default
:
noop
},
onSkuRemove
:
{
type
:
Function
,
default
:
noop
}
},
data
()
{
return
{
currentValue
:
''
,
currentSku
:
''
,
skuValue
:
''
,
newsSkuText
:
''
,
skus
:
this
.
sku
,
hasSkuImage
:
this
.
sku
.
leaf
?
this
.
sku
.
leaf
.
some
(
item
=>
item
.
imgUrl
)
:
false
}
},
watch
:
{
sku
:
{
deep
:
true
,
immediate
:
true
,
handler
(
sku
)
{
if
(
sku
[
this
.
optionText
])
{
this
.
$nextTick
(()
=>
{
this
.
skuValue
=
sku
[
this
.
optionText
]
this
.
currentSku
=
sku
})
}
}
}
},
methods
:
{
filterMethod
(
keyword
)
{
// let { optionText } = this
// if (this.ease.skuTreeData.some(item => item[optionText] === keyword)) return
// this.newsSkuText = keyword
},
// 选择sku
handleSelectSku
(
value
)
{
if
(
value
.
length
>
10
)
{
this
.
$message
({
message
:
`属性名长度不可超过10个字符`
,
duration
:
1500
})
this
.
skuValue
=
''
return
}
let
{
index
,
optionValue
}
=
this
// 当切换当前属性时,把当前属性重新放入可选择列表中
console
.
log
(
value
)
console
.
log
(
this
.
currentSku
)
if
(
this
.
currentSku
!==
''
&&
value
!==
this
.
currentSku
.
id
)
{
console
.
log
(
value
)
this
.
ease
.
skuTreeData
.
push
(
this
.
currentSku
)
}
if
(
typeof
(
value
)
===
'
number
'
)
{
let
sku
=
this
.
ease
.
skuTreeData
.
find
(
item
=>
item
[
optionValue
]
===
value
)
sku
.
leaf
=
[]
if
(
this
.
onSkuChange
(
sku
,
index
)
===
false
)
{
this
.
skuValue
=
''
}
else
{
this
.
ease
.
skuTreeData
.
some
((
item
,
idx
)
=>
{
// 列表删除已选中属性
if
(
item
[
optionValue
]
===
value
)
{
console
.
log
(
this
.
ease
)
this
.
currentSku
=
this
.
ease
.
skuTreeData
[
idx
]
this
.
ease
.
skuTreeData
.
splice
(
idx
,
1
)
}
return
false
})
}
return
}
this
.
createSku
(
value
)
},
// 创建sku
createSku
(
text
)
{
let
{
sku
,
index
,
optionValue
,
optionText
}
=
this
this
.
ease
.
onCreateGroup
(
text
).
then
(
data
=>
{
if
(
data
>
0
)
{
sku
=
{
[
optionValue
]:
data
,
[
optionText
]:
text
,
leaf
:
[],
}
this
.
onSkuChange
(
sku
,
index
)
}
})
},
// 添加图片复选框
handleCheckedSkuImage
(
checked
)
{
let
{
sku
,
index
}
=
this
sku
.
leaf
=
sku
.
leaf
.
map
(
item
=>
{
item
.
is_show
=
checked
return
item
})
this
.
onSkuChange
(
sku
,
index
)
},
handleSkuLeafChange
(
leaf
)
{
let
{
sku
,
index
}
=
this
sku
.
leaf
=
leaf
this
.
onSkuChange
(
sku
,
index
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
/* 商品属性 */
.part-spec-section
{
margin-top
:
10px
;
margin-bottom
:
20px
;
.spec-box
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
width
:
100%
;
min-width
:
400px
;
padding
:
8px
10px
;
background
:
#f4f5f9
;
.spec-select
{
display
:
flex
;
align-items
:
center
;
}
.spec-select
.sel-add-img
{
margin-left
:
20px
;
}
.del-btn
{
font-size
:
13px
;
color
:
#02a1e9
;
cursor
:
pointer
;
}
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Sku/SkuTable/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"ease-sku-table"
>
<!-- 批量设置 -->
<div
class=
"batch-settings"
v-if=
"lists[0] && lists[0].spuSkuAttrValues"
>
<div
class=
"batch"
>
<div>
<span
class=
"bat-tit"
>
批量设置
</span>
<span
class=
"set-tips"
>
在下方栏中选择内容进行批量填充
</span>
</div>
<el-button
size=
"mini"
plain
@
click=
"setNow"
class=
"set"
>
立即设置
</el-button>
</div>
<div
class=
"bat-set-sel"
>
<el-select
v-if=
"firstSkuValOptions.length>0"
v-model=
"firstSkuVal"
size=
"mini"
class=
"bat-set-item"
placeholder=
"请选择"
style=
"width:90px"
>
<el-option
v-for=
"item in firstSkuValOptions"
:key=
"item.id"
:label=
"item.text"
:value=
"item.id"
/>
</el-select>
<el-select
v-if=
"secondSkuValOptions.length>0"
v-model=
"secondSkuVal"
size=
"mini"
class=
"bat-set-item"
placeholder=
"全部"
style=
"width:90px"
>
<el-option
v-for=
"item in secondSkuValOptions"
:key=
"item.id"
:label=
"item.text"
:value=
"item.id"
/>
</el-select>
<!-- 库存 -->
<el-input
class=
"bat-set-item"
size=
"mini"
v-model.number=
"stockIntVal"
:mini=
"0 "
oninput=
"this.value=this.value.replace(/^\.+|[^\d.]/g,'')"
placeholder=
"库存"
style=
"width:90px"
/>
<!-- 市场价 -->
<el-input-number
class=
"bat-set-item"
type=
'number'
controls-position=
"right"
:precision=
"2"
:step=
"0.1"
:min=
"0"
:max=
"1000000000"
size=
"mini"
v-model.number=
"markedPriceIntVal"
placeholder=
"市场价"
style=
"width:90px"
/>
<!-- 销售价 -->
<el-input-number
class=
"bat-set-item"
type=
'number'
controls-position=
"right"
:precision=
"2"
:step=
"0.1"
:min=
"0.01"
:max=
"1000000000"
size=
"mini"
v-model.number=
"priceIntVal"
placeholder=
"销售价"
style=
"width:90px"
/>
<!-- 商品条形码 -->
<el-input
class=
"bat-set-item"
size=
"mini"
v-model.number=
"barCodeIntVal"
oninput=
"this.value=this.value.replace(/^\.+|[^\d.]/g,'')"
placeholder=
"商品条形码"
style=
"width:90px"
/>
<!-- 商品编码 -->
<el-input
class=
"bat-set-item"
size=
"mini"
v-model.number=
"skuCodeIntVal"
oninput=
"this.value=this.value.replace(/^\.+|[^\d.]/g,'')"
placeholder=
"商品编码"
style=
"width:90px"
/>
</div>
</div>
<!-- 表格 -->
<el-table
border
size=
"mini"
:data=
"lists"
:span-method=
"handleSpanMethod"
class=
"tab-con"
>
<template
v-for=
"(label, index) in columns"
>
<!-- 为什么要判断label: 动态添加规格名的时候规格名不为undefiend时未动态显示, 没有看table-column实现暂时这么解决 -->
<el-table-column
v-if=
"label"
:label=
"label"
:key=
"index"
>
<template
slot-scope=
"scope"
>
{{
scope
.
row
.
spuSkuAttrValues
[
index
]
&&
scope
.
row
.
spuSkuAttrValues
[
index
].
attrValueName
}}
</
template
>
</el-table-column>
</template>
<el-table-column
prop=
"stock"
label=
"库存"
class=
"tab-int"
>
<
template
slot-scope=
"scope"
>
<el-input-number
:min=
"0"
@
blur=
"stockValidAndChange(scope)"
v-model.number=
"scope.row.stock"
:disabled=
"scope.row.status===0"
controls-position=
"right"
class=
"tab-int"
></el-input-number>
</
template
>
</el-table-column>
<el-table-column
prop=
"marketPriceFee"
label=
"市场价(元)"
class=
"tab-int"
>
<
template
slot-scope=
"scope"
>
<el-input-number
:min=
"0"
:max=
"1000000000"
v-model=
"scope.row.marketPriceFee"
:disabled=
"scope.row.status===0"
controls-position=
"right"
:precision=
"2"
class=
"tab-int"
></el-input-number>
</
template
>
</el-table-column>
<el-table-column
prop=
"priceFee"
label=
"销售价(元)"
class=
"tab-int"
>
<
template
slot-scope=
"scope"
>
<el-input-number
:min=
"0.01"
:max=
"1000000000"
v-model=
"scope.row.priceFee"
:disabled=
"scope.row.status===0"
controls-position=
"right"
:precision=
"2"
class=
"tab-int"
></el-input-number>
</
template
>
</el-table-column>
<el-table-column
prop=
"barCode"
label=
"商品条形码"
class=
"tab-int"
>
<
template
slot-scope=
"scope"
>
<el-input
:min=
"0"
v-model.number=
"scope.row.modelId"
:disabled=
"scope.row.status===0"
oninput=
"this.value=this.value.replace(/^\.+|[^\d.]/g,'')"
class=
"tab-int"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"skuCode"
label=
"商品编码"
class=
"tab-int"
>
<
template
slot-scope=
"scope"
>
<el-input
:min=
"0"
v-model.number=
"scope.row.partyCode"
:disabled=
"scope.row.status===0"
oninput=
"this.value=this.value.replace(/^\.+|[^\d.]/g,'')"
class=
"tab-int"
></el-input>
</
template
>
</el-table-column>
<el-table-column
prop=
"skuCode"
label=
"sku状态"
v-if=
"spuId && !isNoSkuValue"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"text"
@
click=
"skuStatusOperation(scope)"
>
{{
scope
.
row
.
status
===
1
?
'
禁用
'
:
'
启用
'
}}
</el-button>
</
template
>
</el-table-column>
</el-table>
</div>
</template>
<
script
>
import
{
flatten
as
genFlatten
}
from
'
@/utils
'
export
default
{
name
:
'
sku-table
'
,
props
:
{
data
:
{
type
:
Array
,
default
()
{
return
[]
}
},
// 需要附加的字段
flatten
:
{
type
:
Array
,
default
()
{
return
[]
}
},
// 自定义sku的id key
optionValue
:
{
type
:
String
,
default
:
'
id
'
},
// 自定义sku的text key
optionText
:
{
type
:
String
,
default
:
'
text
'
},
spuId
:
{
type
:
Number
,
default
:
null
},
isNoSkuValue
:
{
type
:
Boolean
,
default
:
false
}
},
originList
:
[],
data
()
{
return
{
rowspan
:
[],
lists
:
[],
firstSkuVal
:
-
1
,
secondSkuVal
:
-
1
,
stockIntVal
:
''
,
// 库存
markedPriceIntVal
:
''
,
priceIntVal
:
''
,
barCodeIntVal
:
''
,
// 条形码
skuCodeIntVal
:
''
,
}
},
computed
:
{
filter
()
{
return
this
.
data
.
filter
(
item
=>
item
.
text
&&
item
.
leaf
.
length
)
},
columns
()
{
return
this
.
filter
.
map
(
item
=>
item
[
this
.
optionText
])
},
firstSkuValOptions
()
{
const
{
data
}
=
this
if
(
data
[
0
])
{
if
(
data
[
0
].
leaf
)
{
return
[{
id
:
-
1
,
is_show
:
true
,
text
:
'
全部
'
},
...
data
[
0
].
leaf
]
}
}
else
{
return
[]
}
},
secondSkuValOptions
()
{
const
{
data
}
=
this
if
(
data
[
1
])
{
if
(
data
[
1
].
leaf
)
{
return
[{
id
:
-
1
,
is_show
:
true
,
text
:
'
全部
'
},
...
data
[
1
].
leaf
]
}
}
else
{
return
[]
}
},
},
watch
:
{
filter
:
{
deep
:
true
,
immediate
:
true
,
handler
()
{
const
lists
=
this
.
genLists
(
this
.
filter
,
this
.
flatten
)
this
.
lists
=
lists
this
.
computeRowspan
()
}
},
flatten
()
{
const
lists
=
this
.
genLists
(
this
.
filter
,
this
.
flatten
)
this
.
originList
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
genLists
(
this
.
filter
,
this
.
flatten
)))
if
(
this
.
lists
.
length
===
1
&&
!
this
.
lists
[
0
].
spuSkuAttrValues
)
{
this
.
flatten
.
forEach
(
el
=>
{
let
baseData
=
{
stock
:
el
.
stock
,
// 库存
marketPriceFee
:
el
.
marketPriceFee
,
// 市场价
priceFee
:
el
.
priceFee
,
// 销售价
partyCode
:
el
.
partyCode
,
// 商品编码
modelId
:
el
.
modelId
,
// 条形码
}
this
.
lists
=
[
baseData
]
})
}
},
lists
:
{
deep
:
true
,
immediate
:
true
,
handler
(
data
)
{
this
.
$emit
(
'
on-change-data
'
,
data
)
}
}
},
methods
:
{
genLists
:
(
filter
,
flatten
)
=>
{
let
baseData
=
{
stock
:
0
,
// 库存
marketPriceFee
:
''
,
// 市场价
priceFee
:
0.01
,
// 销售价
partyCode
:
''
,
// 商品编码
modelId
:
''
,
// 条形码
}
if
(
filter
.
length
&&
genFlatten
(
filter
,
flatten
).
length
)
{
return
genFlatten
(
filter
,
flatten
,
{
extraData
:
baseData
})
}
else
{
return
[
baseData
]
}
},
computeRowspan
()
{
this
.
rowspan
=
[]
const
rowspan
=
(
index
)
=>
{
let
span
=
[]
let
dot
=
0
this
.
lists
.
map
((
item
,
idx
)
=>
{
if
(
idx
===
0
)
{
span
.
push
(
1
)
}
else
{
if
(
item
.
spuSkuAttrValues
?.[
index
].
attrValueName
===
this
.
lists
[
idx
-
1
].
spuSkuAttrValues
?.[
index
].
attrValueName
)
{
span
[
dot
]
+=
1
span
.
push
(
0
)
}
else
{
dot
=
idx
span
.
push
(
1
)
}
}
})
this
.
rowspan
.
push
(
span
)
}
this
.
filter
.
map
((
item
,
index
)
=>
{
rowspan
(
index
)
})
},
handleSpanMethod
({
row
,
column
,
rowIndex
,
columnIndex
})
{
for
(
let
i
=
0
;
i
<
this
.
filter
.
length
;
i
++
)
{
if
(
columnIndex
===
i
)
{
if
(
this
.
rowspan
[
i
]
&&
this
.
rowspan
[
i
][
rowIndex
])
{
return
{
rowspan
:
this
.
rowspan
[
i
][
rowIndex
],
colspan
:
1
}
}
else
{
return
{
rowspan
:
0
,
colspan
:
0
}
}
}
}
},
// 库存修改与验证
stockValidAndChange
(
scope
)
{
const
{
$index
,
row
}
=
scope
;
const
originStock
=
this
.
originList
?.[
$index
]?.
stock
;
if
(
!
this
.
lists
[
$index
].
stock
)
{
this
.
lists
[
$index
].
stock
=
0
}
if
(
originStock
!==
undefined
)
{
if
(
originStock
>
row
.
stock
)
{
// 用户输入错误
// row.stock = originStock;
this
.
lists
[
$index
].
stock
=
originStock
this
.
$message
({
message
:
`输入库存不得小于原有库存`
,
duration
:
1000
})
return
}
this
.
$set
(
this
.
lists
[
$index
],
'
changeStock
'
,
parseInt
(
row
.
stock
)
-
parseInt
(
originStock
))
}
},
// 立即设置
setNow
()
{
const
{
lists
,
firstSkuVal
=
''
,
secondSkuVal
=
''
,
spuId
,
stockIntVal
=
parseInt
(
stockIntVal
),
markedPriceIntVal
=
parseInt
(
markedPriceIntVal
),
priceIntVal
=
parseFloat
(
priceIntVal
),
skuCodeIntVal
=
parseInt
(
skuCodeIntVal
),
barCodeIntVal
=
parseInt
(
barCodeIntVal
)
}
=
this
let
newItem
=
{}
const
setItem
=
(
item
,
index
)
=>
{
// item.stock = stockIntVal ? parseInt(stockIntVal) : item.stock || 0 // 库存,正整数
item
.
marketPriceFee
=
markedPriceIntVal
>=
0
?
markedPriceIntVal
:
item
.
marketPriceFee
||
0
item
.
priceFee
=
priceIntVal
?
priceIntVal
:
item
.
priceFee
||
0.01
// 销售价
item
.
partyCode
=
skuCodeIntVal
?
skuCodeIntVal
:
item
.
partyCode
||
''
// 商品编码
item
.
modelId
=
barCodeIntVal
?
barCodeIntVal
:
item
.
modelId
||
''
// 商品条形码
// 回显 && 原库存 > 0
if
(
spuId
&&
item
.
stock
>=
0
)
{
// 输入库存 是否>=0 且 是否>=原有库存
if
(
stockIntVal
>=
item
.
stock
)
{
item
.
stock
=
stockIntVal
this
.
$set
(
this
.
lists
[
index
],
'
changeStock
'
,
stockIntVal
-
parseInt
(
this
.
originList
[
index
].
stock
))
// 改变的库存数量(新增-原有)
}
}
else
{
item
.
stock
=
stockIntVal
>=
0
?
stockIntVal
:
item
.
stock
||
0
}
return
item
}
const
vaildSkuValArr
=
[
firstSkuVal
,
secondSkuVal
]
lists
.
forEach
((
item
,
index
)
=>
{
const
{
spuSkuAttrValues
}
=
item
;
// secondSkuVal
if
(
spuSkuAttrValues
.
every
((
attr
,
idx
)
=>
vaildSkuValArr
[
idx
]
===
-
1
||
attr
.
attrValueId
===
vaildSkuValArr
[
idx
])
)
{
setItem
(
item
,
index
)
}
})
this
.
lists
=
lists
},
/**
* sku状态
*/
skuStatusOperation
(
scope
)
{
const
{
$index
,
row
}
=
scope
const
currentStatus
=
this
.
lists
?.[
$index
]?.
status
let
newStatus
=
currentStatus
===
0
?
1
:
0
this
.
lists
[
$index
].
status
=
newStatus
}
}
}
</
script
>
<
style
lang=
"scss"
>
.ease-sku-table
{
.el-table__row
{
.el-input-number
{
display
:
block
;
width
:
100%
;
}
.el-input-number.is-controls-right
[
class
*=
"medium"
]
[
class
*=
"increase"
],
.el-input-number.is-controls-right
[
class
*=
"medium"
]
[
class
*=
"decrease"
]
{
display
:
none
;
border
:
0
;
background
:
#fff
;
}
}
// 批量设置
.batch-settings
{
margin-bottom
:
15px
;
.batch
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
margin-bottom
:
10px
;
.set-now
{
font-size
:
14px
;
line-height
:
1em
;
padding
:
6px
10px
;
color
:
#02a1e9
;
border
:
1px
solid
#02a1e9
;
cursor
:
pointer
;
}
.set.el-button
{
border-color
:
#02a1e9
;
color
:
#02a1e9
;
}
.set.el-button
:active
{
background
:
#ecf5ff
;
}
.set-tips
{
font-size
:
13px
;
color
:
#999
;
margin-left
:
15px
;
}
}
.bat-set-item
{
margin-right
:
10px
;
}
.el-input
.el-input__inner
{
padding
:
0
8px
;
}
.el-input-number.is-controls-right
.el-input__inner
{
text-align
:
left
;
padding
:
0
8px
;
}
.el-input-number.is-controls-right
[
class
*=
mini
]
[
class
*=
increase
],
.el-input-number.is-controls-right
[
class
*=
mini
]
[
class
*=
decrease
]
{
display
:
none
;
}
}
.el-table
.cell
{
padding
:
0
;
text-align
:
center
;
}
.el-table--border
th
:first-child
.cell
,
.el-table--border
td
:first-child
.cell
{
padding-left
:
0
;
}
.el-input-number.is-controls-right
.el-input__inner
{
text-align
:
center
;
}
.el-table--mini
td
{
padding
:
0
;
}
.el-input--medium
.el-input__inner
{
width
:
100%
;
height
:
50px
;
border
:
0
;
outline
:
none
;
padding
:
0
10px
;
font-size
:
13px
;
text-align
:
center
;
}
.el-table--enable-row-hover
.el-table__body
tr
:hover
>
td
{
background
:
transparent
;
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/SpuCategoryAttrs/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"spu-catagory-attrs"
>
<div
class=
"part-section"
>
<div
v-for=
"(attrs, attrIdx) in attrsList"
:key=
"attrIdx"
class=
"part-sec-item"
>
<div
class=
"flx"
>
<div
class=
"sec-tit"
>
<span
v-if=
"attrs.searchType == 1"
class=
"stars-icon"
/>
<span
class=
"name"
>
{{
attrs
.
name
}}
</span>
</div>
<el-select
v-if=
"attrs.attrValues && attrs.attrValues.length > 0"
v-model=
"attrs.attrValue"
placeholder=
"请选择"
@
change=
"getValueOfBasicAttrs(attrs, 0)"
style=
"min-width: 150px; width:60%"
>
<el-option
v-for=
"item in attrs.attrValues"
:key=
"item.attrValueId"
:label=
"item.value"
:value=
"item.attrValueId"
/>
</el-select>
<el-input
v-else
v-model=
"attrs.attrValue"
:placeholder=
"'请输入'+attrs.name"
@
blur=
"getValueOfBasicAttrs(attrs, 1)"
style=
"min-width: 150px; width:60%"
/>
</div>
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
props
:
{
attrsList
:
{
type
:
Array
,
default
()
{
return
[]
}
},
},
data
()
{
return
{
}
},
methods
:
{
// 获取数据
getValueOfBasicAttrs
(
attrs
,
st
)
{
this
.
$emit
(
'
getValueOfBasicAttrs
'
,
this
.
attrsList
,
attrs
,
st
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.spu-catagory-attrs
{
.part-section
{
background
:
#f9f9f9
;
padding
:
20px
;
padding-bottom
:
0
;
text-align
:
left
;
width
:
100%
;
max-width
:
100%
;
overflow
:
hidden
;
.part-sec-item
{
display
:
inline-block
;
width
:
48%
;
margin-bottom
:
20px
;
margin-right
:
10px
;
.flx
{
display
:
flex
;
align-items
:
center
;
.sec-tit
{
position
:
relative
;
margin-right
:
15px
;
width
:
auto
;
text-align
:
right
;
line-height
:
1
.5em
;
// 三角形样式
.stars-icon
{
display
:
inline-block
;
width
:
12px
;
height
:
8px
;
}
.
stars-icon
:
:
before
{
position
:
absolute
;
top
:
16px
;
left
:
0
;
content
:
""
;
width
:
0
;
height
:
0
;
margin-top
:
-10px
;
border-left
:
4px
solid
transparent
;
border-right
:
4px
solid
transparent
;
border-bottom
:
8px
solid
#ff7300
;
}
}
}
.int-box
{
width
:
300px
;
}
}
.part-sec-item
:nth-child
(
2n
)
{
margin-right
:
0
;
}
}
}
</
style
>
\ No newline at end of file
front-end/mall4cloud-multishop-master/src/components/SvgIcon/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
v-if=
"isExternal"
:style=
"styleExternalIcon"
class=
"svg-external-icon svg-icon"
v-on=
"$listeners"
/>
<svg
v-else
:class=
"svgClass"
aria-hidden=
"true"
v-on=
"$listeners"
>
<use
:xlink:href=
"iconName"
/>
</svg>
</
template
>
<
script
>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import
{
isExternal
}
from
'
@/utils/validate
'
export
default
{
name
:
'
SvgIcon
'
,
props
:
{
iconClass
:
{
type
:
String
,
required
:
true
},
className
:
{
type
:
String
,
default
:
''
}
},
computed
:
{
isExternal
()
{
return
isExternal
(
this
.
iconClass
)
},
iconName
()
{
return
`#icon-
${
this
.
iconClass
}
`
},
svgClass
()
{
if
(
this
.
className
)
{
return
'
svg-icon
'
+
this
.
className
}
else
{
return
'
svg-icon
'
}
},
styleExternalIcon
()
{
return
{
mask
:
`url(
${
this
.
iconClass
}
) no-repeat 50% 50%`
,
'
-webkit-mask
'
:
`url(
${
this
.
iconClass
}
) no-repeat 50% 50%`
}
}
}
}
</
script
>
<
style
scoped
>
.svg-icon
{
width
:
1em
;
height
:
1em
;
vertical-align
:
-0.15em
;
fill
:
currentColor
;
overflow
:
hidden
;
}
.svg-external-icon
{
background-color
:
currentColor
;
mask-size
:
cover
!important
;
display
:
inline-block
;
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Tinymce/components/EditorImage.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
class=
"upload-container"
>
<el-button
:style=
"
{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click="clickUpload()">
upload
</el-button>
<!-- 弹窗, 新增图片 -->
<elx-imgbox
v-if=
"elxImgboxVisible"
ref=
"elxImgbox"
@
refreshPic=
"refreshPic"
></elx-imgbox>
</div>
</
template
>
<
script
>
// import { getToken } from 'api/qiniu'
import
ImgsUpload
from
'
@/components/ImgsUpload
'
import
ElxImgbox
from
'
@/components/imgbox
'
export
default
{
name
:
'
EditorSlideUpload
'
,
props
:
{
color
:
{
type
:
String
,
default
:
'
#1890ff
'
}
},
data
()
{
return
{
elxImgboxVisible
:
false
,
maxNum
:
15
,
// 可选择的最大图片数量
imgUrls
:
[],
resourcesUrl
:
process
.
env
.
VUE_APP_RESOURCES_URL
,
}
},
components
:
{
ImgsUpload
,
ElxImgbox
},
methods
:
{
/**
* 打开图片选择窗
*/
clickUpload
()
{
this
.
imgUrls
=
''
this
.
elxImgboxVisible
=
true
this
.
$nextTick
(()
=>
{
this
.
$refs
.
elxImgbox
.
init
(
0
,
this
.
maxNum
)
})
},
/**
* 接收回调的图片数据
*/
refreshPic
(
imagePath
)
{
let
imageArray
=
imagePath
.
split
(
'
,
'
)
var
data
=
[]
imageArray
.
forEach
(
img
=>
{
data
.
push
(
this
.
resourcesUrl
+
img
)
})
this
.
imgUrls
=
''
this
.
dialogVisible
=
false
this
.
$emit
(
'
successCBK
'
,
data
)
}
// handleSubmit() {
// let imageArray = this.imgUrls.split(',')
// var data = []
// imageArray.forEach(img => {
// data.push(this.resourcesUrl + img)
// })
// this.imgUrls = ''
// this.dialogVisible = false
// this.$emit('successCBK', data)
// }
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.editor-slide-upload
{
margin-bottom
:
20px
;
::v-deep
.el-upload--picture-card
{
width
:
100%
;
}
}
</
style
>
front-end/mall4cloud-multishop-master/src/components/Tinymce/dynamicLoadScript.js
0 → 100644
View file @
a21f5a9a
let
callbacks
=
[]
function
loadedTinymce
()
{
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
// check is successfully downloaded script
return
window
.
tinymce
}
const
dynamicLoadScript
=
(
src
,
callback
)
=>
{
const
existingScript
=
document
.
getElementById
(
src
)
const
cb
=
callback
||
function
()
{}
if
(
!
existingScript
)
{
const
script
=
document
.
createElement
(
'
script
'
)
script
.
src
=
src
// src url for the third-party library being loaded.
script
.
id
=
src
document
.
body
.
appendChild
(
script
)
callbacks
.
push
(
cb
)
const
onEnd
=
'
onload
'
in
script
?
stdOnEnd
:
ieOnEnd
onEnd
(
script
)
}
if
(
existingScript
&&
cb
)
{
if
(
loadedTinymce
())
{
cb
(
null
,
existingScript
)
}
else
{
callbacks
.
push
(
cb
)
}
}
function
stdOnEnd
(
script
)
{
script
.
onload
=
function
()
{
// this.onload = null here is necessary
// because even IE9 works not like others
this
.
onerror
=
this
.
onload
=
null
for
(
const
cb
of
callbacks
)
{
cb
(
null
,
script
)
}
callbacks
=
null
}
script
.
onerror
=
function
()
{
this
.
onerror
=
this
.
onload
=
null
cb
(
new
Error
(
'
Failed to load
'
+
src
),
script
)
}
}
function
ieOnEnd
(
script
)
{
script
.
onreadystatechange
=
function
()
{
if
(
this
.
readyState
!==
'
complete
'
&&
this
.
readyState
!==
'
loaded
'
)
return
this
.
onreadystatechange
=
null
for
(
const
cb
of
callbacks
)
{
cb
(
null
,
script
)
// there is no way to catch loading errors in IE8
}
callbacks
=
null
}
}
}
export
default
dynamicLoadScript
front-end/mall4cloud-multishop-master/src/components/Tinymce/index.vue
0 → 100644
View file @
a21f5a9a
<
template
>
<div
:class=
"
{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
<textarea
:id=
"tinymceId"
class=
"tinymce-textarea"
/>
<div
class=
"editor-custom-btn-container"
>
<editorImage
color=
"#1890ff"
class=
"editor-upload-btn"
@
successCBK=
"imageSuccessCBK"
/>
</div>
</div>
</
template
>
<
script
>
/**
* docs:
* https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
*/
import
editorImage
from
'
./components/EditorImage
'
import
plugins
from
'
./plugins
'
import
toolbar
from
'
./toolbar
'
import
load
from
'
./dynamicLoadScript
'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const
tinymceCDN
=
'
https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js
'
export
default
{
name
:
'
Tinymce
'
,
components
:
{
editorImage
},
props
:
{
id
:
{
type
:
String
,
default
:
function
()
{
return
'
vue-tinymce-
'
+
+
new
Date
()
+
((
Math
.
random
()
*
1000
).
toFixed
(
0
)
+
''
)
}
},
value
:
{
type
:
String
,
default
:
''
},
toolbar
:
{
type
:
Array
,
required
:
false
,
default
()
{
return
[]
}
},
menubar
:
{
type
:
String
,
default
:
'
file edit insert view format table
'
},
height
:
{
type
:
[
Number
,
String
],
required
:
false
,
default
:
360
},
width
:
{
type
:
[
Number
,
String
],
required
:
false
,
default
:
'
auto
'
}
},
data
()
{
return
{
hasChange
:
false
,
hasInit
:
false
,
tinymceId
:
this
.
id
,
fullscreen
:
false
,
languageTypeList
:
{
'
en
'
:
'
en
'
,
'
zh
'
:
'
zh_CN
'
,
'
es
'
:
'
es_MX
'
,
'
ja
'
:
'
ja
'
}
}
},
computed
:
{
language
()
{
return
this
.
languageTypeList
[
this
.
$store
.
getters
.
language
]
},
containerWidth
()
{
const
width
=
this
.
width
if
(
/^
[\d]
+
(\.[\d]
+
)?
$/
.
test
(
width
))
{
// matches `100`, `'100'`
return
`
${
width
}
px`
}
return
width
}
},
watch
:
{
value
(
val
)
{
if
(
!
this
.
hasChange
&&
this
.
hasInit
)
{
this
.
$nextTick
(()
=>
window
.
tinymce
.
get
(
this
.
tinymceId
).
setContent
(
val
||
''
))
}
},
language
()
{
this
.
destroyTinymce
()
this
.
$nextTick
(()
=>
this
.
initTinymce
())
}
},
mounted
()
{
this
.
init
()
},
activated
()
{
if
(
window
.
tinymce
)
{
this
.
initTinymce
()
}
},
deactivated
()
{
this
.
destroyTinymce
()
},
destroyed
()
{
this
.
destroyTinymce
()
},
methods
:
{
init
()
{
// dynamic load tinymce from cdn
load
(
tinymceCDN
,
(
err
)
=>
{
if
(
err
)
{
this
.
$message
.
error
(
err
.
message
)
return
}
this
.
initTinymce
()
})
},
initTinymce
()
{
const
_this
=
this
window
.
tinymce
.
init
({
language
:
this
.
language
,
selector
:
`#
${
this
.
tinymceId
}
`
,
height
:
this
.
height
,
body_class
:
'
panel-body
'
,
object_resizing
:
false
,
toolbar
:
this
.
toolbar
.
length
>
0
?
this
.
toolbar
:
toolbar
,
menubar
:
this
.
menubar
,
plugins
:
plugins
,
end_container_on_empty_block
:
true
,
powerpaste_word_import
:
'
clean
'
,
code_dialog_height
:
450
,
code_dialog_width
:
1000
,
advlist_bullet_styles
:
'
square
'
,
advlist_number_styles
:
'
default
'
,
imagetools_cors_hosts
:
[
'
www.tinymce.com
'
,
'
codepen.io
'
],
default_link_target
:
'
_blank
'
,
link_title
:
false
,
nonbreaking_force_tab
:
true
,
// inserting nonbreaking space need Nonbreaking Space Plugin
init_instance_callback
:
editor
=>
{
if
(
_this
.
value
)
{
editor
.
setContent
(
_this
.
value
)
}
_this
.
hasInit
=
true
editor
.
on
(
'
NodeChange Change KeyUp SetContent
'
,
()
=>
{
this
.
hasChange
=
true
this
.
$emit
(
'
input
'
,
editor
.
getContent
())
})
},
setup
(
editor
)
{
editor
.
on
(
'
FullscreenStateChanged
'
,
(
e
)
=>
{
_this
.
fullscreen
=
e
.
state
})
},
// it will try to keep these URLs intact
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
convert_urls
:
false
// 整合七牛上传
// images_dataimg_filter(img) {
// setTimeout(() => {
// const $image = $(img);
// $image.removeAttr('width');
// $image.removeAttr('height');
// if ($image[0].height && $image[0].width) {
// $image.attr('data-wscntype', 'image');
// $image.attr('data-wscnh', $image[0].height);
// $image.attr('data-wscnw', $image[0].width);
// $image.addClass('wscnph');
// }
// }, 0);
// return img
// },
// images_upload_handler(blobInfo, success, failure, progress) {
// progress(0);
// const token = _this.$store.getters.token;
// getToken(token).then(response => {
// const url = response.data.qiniu_url;
// const formData = new FormData();
// formData.append('token', response.data.qiniu_token);
// formData.append('key', response.data.qiniu_key);
// formData.append('file', blobInfo.blob(), url);
// upload(formData).then(() => {
// success(url);
// progress(100);
// })
// }).catch(err => {
// failure('出现未知问题,刷新页面,或者联系程序员')
// console.log(err);
// });
// },
})
},
destroyTinymce
()
{
const
tinymce
=
window
.
tinymce
.
get
(
this
.
tinymceId
)
if
(
this
.
fullscreen
)
{
tinymce
.
execCommand
(
'
mceFullScreen
'
)
}
if
(
tinymce
)
{
tinymce
.
destroy
()
}
},
setContent
(
value
)
{
window
.
tinymce
.
get
(
this
.
tinymceId
).
setContent
(
value
)
},
getContent
()
{
window
.
tinymce
.
get
(
this
.
tinymceId
).
getContent
()
},
imageSuccessCBK
(
arr
)
{
const
_this
=
this
arr
.
forEach
(
v
=>
{
window
.
tinymce
.
get
(
_this
.
tinymceId
).
insertContent
(
`<img class="wscnph" src="
${
v
}
" >`
)
})
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.tinymce-container
{
position
:
relative
;
line-height
:
normal
;
}
.tinymce-container
{
::v-deep
{
.mce-fullscreen
{
z-index
:
10000
;
}
}
}
.tinymce-textarea
{
visibility
:
hidden
;
z-index
:
-1
;
}
.editor-custom-btn-container
{
position
:
absolute
;
right
:
4px
;
top
:
4px
;
/*z-index: 2005;*/
}
.fullscreen
.editor-custom-btn-container
{
z-index
:
10000
;
position
:
fixed
;
}
.editor-upload-btn
{
display
:
inline-block
;
}
</
style
>
Prev
1
…
7
8
9
10
11
12
13
14
15
…
18
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment