Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1b2c7ceb
authored
Dec 31, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' of
https://gitee.com/yudaocode/yudao-ui-admin-vue3
parents
51cffa4e
25484a94
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
367 additions
and
137 deletions
+367
-137
src/api/mall/trade/brokerage/user/index.ts
+5
-0
src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue
+17
-14
src/components/DiyEditor/components/mobile/TitleBar/config.ts
+1
-3
src/components/DiyEditor/components/mobile/TitleBar/index.vue
+17
-9
src/components/DiyEditor/components/mobile/TitleBar/property.vue
+22
-27
src/components/DiyEditor/index.vue
+46
-30
src/components/RouterSearch/index.vue
+2
-0
src/views/mall/promotion/diy/template/decorate.vue
+52
-18
src/views/mall/trade/brokerage/user/BrokerageOrderListDialog.vue
+42
-34
src/views/mall/trade/brokerage/user/BrokerageUserCreateForm.vue
+161
-0
src/views/mall/trade/brokerage/user/BrokerageUserUpdateForm.vue
+2
-2
src/views/mall/trade/brokerage/user/index.vue
+0
-0
No files found.
src/api/mall/trade/brokerage/user/index.ts
View file @
1b2c7ceb
...
...
@@ -13,6 +13,11 @@ export interface BrokerageUserVO {
avatar
:
string
}
// 创建分销用户
export
const
createBrokerageUser
=
(
data
:
any
)
=>
{
return
request
.
post
({
url
:
'/trade/brokerage-user/create'
,
data
})
}
// 查询分销用户列表
export
const
getBrokerageUserPage
=
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/trade/brokerage-user/page`
,
params
})
...
...
src/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue
View file @
1b2c7ceb
...
...
@@ -2,17 +2,17 @@
<div
class=
"h-40px flex items-center justify-center"
>
<MagicCubeEditor
v-model=
"cellList"
class=
"m-b-16px"
:rows=
"1"
:cols=
"cellCount"
:cube-size=
"38"
:rows=
"1"
class=
"m-b-16px"
@
hot-area-selected=
"handleHotAreaSelected"
/>
<img
src=
"@/assets/imgs/diy/app-nav-bar-mp.png"
alt=
""
class=
"h-30px w-76px"
v-if=
"isMp
"
/>
<img
v-if=
"isMp"
alt=
""
class=
"h-30px w-76px"
src=
"@/assets/imgs/diy/app-nav-bar-mp.png
"
/>
</div>
<template
v-for=
"(cell, cellIndex) in cellList"
:key=
"cellIndex"
>
<template
v-if=
"selectedHotAreaIndex === cellIndex"
>
<el-form-item
label=
"类型"
:prop=
"`cell[$
{cellIndex}].type`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].type`" label="类型
">
<el-radio-group
v-model=
"cell.type"
>
<el-radio
value=
"text"
>
文字
</el-radio>
<el-radio
value=
"image"
>
图片
</el-radio>
...
...
@@ -21,37 +21,40 @@
</el-form-item>
<!-- 1. 文字 -->
<template
v-if=
"cell.type === 'text'"
>
<el-form-item
label=
"内容"
:prop=
"`cell[$
{cellIndex}].text`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].text`" label="内容
">
<el-input
v-model=
"cell!.text"
maxlength=
"10"
show-word-limit
/>
</el-form-item>
<el-form-item
label=
"颜色"
:prop=
"`cell[$
{cellIndex}].text`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].text`" label="颜色
">
<ColorInput
v-model=
"cell!.textColor"
/>
</el-form-item>
<el-form-item
:prop=
"`cell[$
{cellIndex}].url`" label="链接">
<AppLinkInput
v-model=
"cell.url"
/>
</el-form-item>
</
template
>
<!-- 2. 图片 -->
<
template
v-else-if=
"cell.type === 'image'"
>
<el-form-item
label=
"图片"
:prop=
"`cell[$
{cellIndex}].imgUrl`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].imgUrl`" label="图片
">
<UploadImg
v-model=
"cell.imgUrl"
:limit=
"1"
height=
"56px"
width=
"56px"
>
<template
#
tip
>
建议尺寸 56*56
</
template
>
</UploadImg>
</el-form-item>
<el-form-item
label=
"链接"
:prop=
"`cell[${cellIndex}].url`
"
>
<el-form-item
:prop=
"`cell[${cellIndex}].url`"
label=
"链接
"
>
<AppLinkInput
v-model=
"cell.url"
/>
</el-form-item>
</template>
<!-- 3. 搜索框 -->
<
template
v-else
>
<el-form-item
label=
"提示文字"
:prop=
"`cell[$
{cellIndex}].placeholder`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].placeholder`" label="提示文字
">
<el-input
v-model=
"cell.placeholder"
maxlength=
"10"
show-word-limit
/>
</el-form-item>
<el-form-item
label=
"圆角"
:prop=
"`cell[$
{cellIndex}].borderRadius`
">
<el-form-item
:prop=
"`cell[$
{cellIndex}].borderRadius`" label="圆角
">
<el-slider
v-model=
"cell.borderRadius"
:max=
"100"
:min=
"0"
show-input
input-size=
"small"
:show-input-controls=
"false"
input-size=
"small"
show-input
/>
</el-form-item>
</
template
>
...
...
@@ -59,7 +62,7 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
lang=
"ts"
setup
>
import
{
NavigationBarCellProperty
}
from
'../config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
// 导航栏属性面板
...
...
@@ -87,4 +90,4 @@ const handleHotAreaSelected = (cellValue: NavigationBarCellProperty, index: numb
}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/DiyEditor/components/mobile/TitleBar/config.ts
View file @
1b2c7ceb
import
{
ComponentStyle
,
DiyComponent
}
from
'@/components/DiyEditor/util'
import
{
ComponentStyle
,
DiyComponent
}
from
'@/components/DiyEditor/util'
/** 标题栏属性 */
export
interface
TitleBarProperty
{
// 背景图
bgImgUrl
:
string
// 偏移
marginLeft
:
number
// 显示位置
...
...
src/components/DiyEditor/components/mobile/TitleBar/index.vue
View file @
1b2c7ceb
<
template
>
<div
class=
"title-bar"
>
<el-image
v-if=
"property.bgImgUrl"
:src=
"property.bgImgUrl"
fit=
"cover"
class=
"w-full"
/>
<div
class=
"absolute left-0 top-0 w-full"
>
<div
:style=
"
{
background:
property.style.bgType === 'color' ? property.style.bgColor : `url(${property.style.bgImg})`,
backgroundSize: '100% 100%',
backgroundRepeat: 'no-repeat'
}"
class="title-bar"
>
<!-- 内容 -->
<div>
<!-- 标题 -->
<div
v-if=
"property.title"
:style=
"
{
fontSize: `${property.titleSize}px`,
fontWeight: property.titleWeight,
color: property.titleColor,
textAlign: property.textAlign
}"
v-if="property.title"
>
{{
property
.
title
}}
</div>
<!-- 副标题 -->
<div
v-if=
"property.description"
:style=
"
{
fontSize: `${property.descriptionSize}px`,
fontWeight: property.descriptionWeight,
...
...
@@ -23,25 +32,24 @@
textAlign: property.textAlign
}"
class="m-t-8px"
v-if="property.description"
>
{{
property
.
description
}}
</div>
</div>
<!-- 更多 -->
<div
class=
"more"
v-show=
"property.more.show"
:style=
"
{
color: property.descriptionColor
}"
class="more"
>
<span
v-if=
"property.more.type !== 'icon'"
>
{{
property
.
more
.
text
}}
</span>
<Icon
icon=
"ep:arrow-right"
v-if=
"property.more.type !== 'text'
"
/>
<Icon
v-if=
"property.more.type !== 'text'"
icon=
"ep:arrow-right
"
/>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
lang=
"ts"
setup
>
import
{
TitleBarProperty
}
from
'./config'
/** 标题栏 */
...
...
@@ -49,7 +57,7 @@ defineOptions({ name: 'TitleBar' })
defineProps
<
{
property
:
TitleBarProperty
}
>
()
</
script
>
<
style
scoped
lang=
"scss"
>
<
style
lang=
"scss"
scoped
>
.title-bar
{
position
:
relative
;
width
:
100%
;
...
...
src/components/DiyEditor/components/mobile/TitleBar/property.vue
View file @
1b2c7ceb
<
template
>
<ComponentContainerProperty
v-model=
"formData.style"
>
<el-form
label-width=
"85px"
:model=
"formData"
:rules=
"rules"
>
<el-card
header=
"风格"
class=
"property-group"
shadow=
"never"
>
<el-form-item
label=
"背景图片"
prop=
"bgImgUrl"
>
<UploadImg
v-model=
"formData.bgImgUrl"
width=
"100%"
height=
"40px"
>
<template
#
tip
>
建议尺寸 750*80
</
template
>
</UploadImg>
</el-form-item>
<el-form
:model=
"formData"
:rules=
"rules"
label-width=
"85px"
>
<el-card
class=
"property-group"
header=
"风格"
shadow=
"never"
>
<el-form-item
label=
"标题位置"
prop=
"textAlign"
>
<el-radio-group
v-model=
"formData!.textAlign"
>
<el-tooltip
content=
"居左"
placement=
"top"
>
...
...
@@ -22,65 +17,65 @@
</el-radio-group>
</el-form-item>
</el-card>
<el-card
header=
"主标题"
class=
"property-group
"
shadow=
"never"
>
<el-form-item
label=
"文字"
prop=
"title"
label-width=
"40px
"
>
<el-card
class=
"property-group"
header=
"主标题
"
shadow=
"never"
>
<el-form-item
label=
"文字"
label-width=
"40px"
prop=
"title
"
>
<InputWithColor
v-model=
"formData.title"
v-model:color=
"formData.titleColor"
show-word-limit
maxlength=
"20"
show-word-limit
/>
</el-form-item>
<el-form-item
label=
"大小"
prop=
"titleSize"
label-width=
"40px
"
>
<el-form-item
label=
"大小"
label-width=
"40px"
prop=
"titleSize
"
>
<el-slider
v-model=
"formData.titleSize"
:max=
"60"
:min=
"10"
show-input
input-size=
"small"
show-input
/>
</el-form-item>
<el-form-item
label=
"粗细"
prop=
"titleWeight"
label-width=
"40px
"
>
<el-form-item
label=
"粗细"
label-width=
"40px"
prop=
"titleWeight
"
>
<el-slider
v-model=
"formData.titleWeight"
:min=
"100"
:max=
"900"
:min=
"100"
:step=
"100"
show-input
input-size=
"small"
show-input
/>
</el-form-item>
</el-card>
<el-card
header=
"副标题"
class=
"property-group
"
shadow=
"never"
>
<el-form-item
label=
"文字"
prop=
"description"
label-width=
"40px
"
>
<el-card
class=
"property-group"
header=
"副标题
"
shadow=
"never"
>
<el-form-item
label=
"文字"
label-width=
"40px"
prop=
"description
"
>
<InputWithColor
v-model=
"formData.description"
v-model:color=
"formData.descriptionColor"
show-word-limit
maxlength=
"50"
show-word-limit
/>
</el-form-item>
<el-form-item
label=
"大小"
prop=
"descriptionSize"
label-width=
"40px
"
>
<el-form-item
label=
"大小"
label-width=
"40px"
prop=
"descriptionSize
"
>
<el-slider
v-model=
"formData.descriptionSize"
:max=
"60"
:min=
"10"
show-input
input-size=
"small"
show-input
/>
</el-form-item>
<el-form-item
label=
"粗细"
prop=
"descriptionWeight"
label-width=
"40px
"
>
<el-form-item
label=
"粗细"
label-width=
"40px"
prop=
"descriptionWeight
"
>
<el-slider
v-model=
"formData.descriptionWeight"
:min=
"100"
:max=
"900"
:min=
"100"
:step=
"100"
show-input
input-size=
"small"
show-input
/>
</el-form-item>
</el-card>
<el-card
header=
"查看更多"
class=
"property-group
"
shadow=
"never"
>
<el-card
class=
"property-group"
header=
"查看更多
"
shadow=
"never"
>
<el-form-item
label=
"是否显示"
prop=
"more.show"
>
<el-checkbox
v-model=
"formData.more.show"
/>
</el-form-item>
...
...
@@ -93,7 +88,7 @@
<el-radio
value=
"all"
>
文字+图标
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"更多文字"
prop=
"more.text"
v-show=
"formData.more.type !== 'icon'
"
>
<el-form-item
v-show=
"formData.more.type !== 'icon'"
label=
"更多文字"
prop=
"more.text
"
>
<el-input
v-model=
"formData.more.text"
/>
</el-form-item>
<el-form-item
label=
"跳转链接"
prop=
"more.url"
>
...
...
@@ -104,7 +99,7 @@
</el-form>
</ComponentContainerProperty>
</template>
<
script
setup
lang=
"ts"
>
<
script
lang=
"ts"
setup
>
import
{
TitleBarProperty
}
from
'./config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
// 导航栏属性面板
...
...
@@ -118,4 +113,4 @@ const { formData } = usePropertyForm(props.modelValue, emit)
const
rules
=
{}
</
script
>
<
style
scoped
lang=
"scss"
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/DiyEditor/index.vue
View file @
1b2c7ceb
...
...
@@ -12,17 +12,17 @@
<el-button-group
class=
"header-right"
>
<el-tooltip
content=
"重置"
>
<el-button
@
click=
"handleReset"
>
<Icon
icon=
"system-uicons:reset-alt"
:size=
"24
"
/>
<Icon
:size=
"24"
icon=
"system-uicons:reset-alt
"
/>
</el-button>
</el-tooltip>
<el-tooltip
content=
"预览"
v-if=
"previewUrl
"
>
<el-tooltip
v-if=
"previewUrl"
content=
"预览
"
>
<el-button
@
click=
"handlePreview"
>
<Icon
icon=
"ep:view"
:size=
"24
"
/>
<Icon
:size=
"24"
icon=
"ep:view
"
/>
</el-button>
</el-tooltip>
<el-tooltip
content=
"保存"
>
<el-button
@
click=
"handleSave"
>
<Icon
icon=
"ep:check"
:size=
"24
"
/>
<Icon
:size=
"24"
icon=
"ep:check
"
/>
</el-button>
</el-tooltip>
</el-button-group>
...
...
@@ -31,21 +31,21 @@
<!-- 中心区域 -->
<el-container
class=
"editor-container"
>
<!-- 左侧:组件库(ComponentLibrary) -->
<ComponentLibrary
ref=
"componentLibrary"
:list=
"libs"
v-if=
"libs && libs.length > 0
"
/>
<ComponentLibrary
v-if=
"libs && libs.length > 0"
ref=
"componentLibrary"
:list=
"libs
"
/>
<!-- 中心:设计区域(ComponentContainer) -->
<div
class=
"editor-center page-prop-area"
@
click=
"handlePageSelected"
>
<!-- 手机顶部 -->
<div
class=
"editor-design-top"
>
<!-- 手机顶部状态栏 -->
<img
src=
"@/assets/imgs/diy/statusBar.png"
alt=
""
class=
"status-bar
"
/>
<img
alt=
""
class=
"status-bar"
src=
"@/assets/imgs/diy/statusBar.png
"
/>
<!-- 手机顶部导航栏 -->
<ComponentContainer
v-if=
"showNavigationBar"
:active=
"selectedComponent?.id === navigationBarComponent.id"
:component=
"navigationBarComponent"
:show-toolbar=
"false"
:active=
"selectedComponent?.id === navigationBarComponent.id"
@
click=
"handleNavigationBarSelected"
class=
"cursor-pointer!"
@
click=
"handleNavigationBarSelected"
/>
</div>
<!-- 绝对定位的组件:例如 弹窗、浮动按钮等 -->
...
...
@@ -55,43 +55,43 @@
@
click=
"handleComponentSelected(component, index)"
>
<component
v-if=
"component.position === 'fixed' && selectedComponent?.uid === component.uid"
:is=
"component.id"
v-if=
"component.position === 'fixed' && selectedComponent?.uid === component.uid"
:property=
"component.property"
/>
</div>
<!-- 手机页面编辑区域 -->
<el-scrollbar
height=
"100%"
wrap-class=
"editor-design-center page-prop-area"
view-class=
"phone-container"
:view-style=
"
{
backgroundColor: pageConfigComponent.property.backgroundColor,
backgroundImage: `url(${pageConfigComponent.property.backgroundImage})`
}"
height="100%"
view-class="phone-container"
wrap-class="editor-design-center page-prop-area"
>
<draggable
class=
"page-prop-area drag-area"
v-model=
"pageComponents"
item-key=
"index"
:animation=
"200"
:force-fallback=
"true"
class=
"page-prop-area drag-area"
filter=
".component-toolbar"
ghost-class=
"draggable-ghost"
:force-fallback=
"true"
group=
"component"
item-key=
"index"
@
change=
"handleComponentChange"
>
<template
#
item=
"
{ element, index }">
<ComponentContainer
v-if=
"!element.position || element.position === 'center'"
:component=
"element"
:active=
"selectedComponentIndex === index"
:can-move-up=
"index > 0"
:can-move-down=
"index
<
pageComponents
.
length
-
1
"
@
move=
"(direction) => handleMoveComponent(index, direction)"
:can-move-up=
"index > 0"
:component=
"element"
@
click=
"handleComponentSelected(element, index)"
@
copy=
"handleCopyComponent(index)"
@
delete=
"handleDeleteComponent(index)"
@
click=
"handleComponentSelected(element, index
)"
@
move=
"(direction) => handleMoveComponent(index, direction
)"
/>
</
template
>
</draggable>
...
...
@@ -99,9 +99,9 @@
<!-- 手机底部导航 -->
<div
v-if=
"showTabBar"
:class=
"['editor-design-bottom', 'component', 'cursor-pointer!']"
>
<ComponentContainer
:active=
"selectedComponent?.id === tabBarComponent.id"
:component=
"tabBarComponent"
:show-toolbar=
"false"
:active=
"selectedComponent?.id === tabBarComponent.id"
@
click=
"handleTabBarSelected"
/>
</div>
...
...
@@ -109,9 +109,9 @@
<div
class=
"fixed-component-action-group"
>
<el-tag
v-if=
"showPageConfig"
size=
"large"
:effect=
"selectedComponent?.uid === pageConfigComponent.uid ? 'dark' : 'plain'"
:type=
"selectedComponent?.uid === pageConfigComponent.uid ? '' : 'info'"
size=
"large"
@
click=
"handleComponentSelected(pageConfigComponent)"
>
<Icon
:icon=
"pageConfigComponent.icon"
:size=
"12"
/>
...
...
@@ -120,10 +120,10 @@
<
template
v-for=
"(component, index) in pageComponents"
:key=
"index"
>
<el-tag
v-if=
"component.position === 'fixed'"
size=
"large"
closable
:effect=
"selectedComponent?.uid === component.uid ? 'dark' : 'plain'"
:type=
"selectedComponent?.uid === component.uid ? '' : 'info'"
closable
size=
"large"
@
click=
"handleComponentSelected(component)"
@
close=
"handleDeleteComponent(index)"
>
...
...
@@ -134,11 +134,11 @@
</div>
</div>
<!-- 右侧:属性面板(ComponentContainerProperty) -->
<el-aside
class=
"editor-right"
width=
"350px"
v-if=
"selectedComponent?.property
"
>
<el-aside
v-if=
"selectedComponent?.property"
class=
"editor-right"
width=
"350px
"
>
<el-card
shadow=
"never"
body-class=
"h-[calc(100%-var(--el-card-padding)-var(--el-card-padding))]"
class=
"h-full"
shadow=
"never"
>
<!-- 组件名称 -->
<
template
#
header
>
...
...
@@ -152,8 +152,8 @@
view-class=
"p-[var(--el-card-padding)] p-b-[calc(var(--el-card-padding)+var(--el-card-padding))] property"
>
<component
:key=
"selectedComponent?.uid || selectedComponent?.id"
:is=
"selectedComponent?.id + 'Property'"
:key=
"selectedComponent?.uid || selectedComponent?.id"
v-model=
"selectedComponent.property"
/>
</el-scrollbar>
...
...
@@ -166,8 +166,8 @@
<Dialog
v-model=
"previewDialogVisible"
title=
"预览"
width=
"700"
>
<div
class=
"flex justify-around"
>
<IFrame
class=
"w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
:src=
"previewUrl"
class=
"w-375px border-4px border-rounded-8px border-solid p-2px h-667px!"
/>
<div
class=
"flex flex-col"
>
<el-text>
手机扫码预览
</el-text>
...
...
@@ -179,6 +179,7 @@
<
script
lang=
"ts"
>
// 注册所有的组件
import
{
components
}
from
'./components/mobile/index'
export
default
{
components
:
{
...
components
}
}
...
...
@@ -257,6 +258,11 @@ watch(
// 保存
const
handleSave
=
()
=>
{
// 发送保存通知
emits
(
'save'
)
}
// 监听配置修改
const
pageConfigChange
=
()
=>
{
const
pageConfig
=
{
page
:
pageConfigComponent
.
value
.
property
,
navigationBar
:
navigationBarComponent
.
value
.
property
,
...
...
@@ -272,10 +278,19 @@ const handleSave = () => {
// 发送数据更新通知
const
modelValue
=
isString
(
props
.
modelValue
)
?
JSON
.
stringify
(
pageConfig
)
:
pageConfig
emits
(
'update:modelValue'
,
modelValue
)
// 发送保存通知
emits
(
'save'
,
pageConfig
)
}
watch
(
()
=>
[
pageConfigComponent
.
value
.
property
,
navigationBarComponent
.
value
.
property
,
tabBarComponent
.
value
.
property
,
pageComponents
.
value
],
()
=>
{
pageConfigChange
()
},
{
deep
:
true
}
)
// 处理页面选中:显示属性表单
const
handlePageSelected
=
(
event
:
any
)
=>
{
if
(
!
props
.
showPageConfig
)
return
...
...
@@ -547,6 +562,7 @@ $toolbar-height: 42px;
:deep(.el-tag)
{
box-shadow
:
0
2px
8px
0
rgba
(
0
,
0
,
0
,
0.1
);
border
:
none
;
.el-tag__content
{
width
:
100%
;
display
:
flex
;
...
...
src/components/RouterSearch/index.vue
View file @
1b2c7ceb
...
...
@@ -99,6 +99,8 @@ onUnmounted(() => {
// 监听 ctrl + k
function
listenKey
(
event
)
{
if
((
event
.
ctrlKey
||
event
.
metaKey
)
&&
event
.
key
===
'k'
)
{
// 阻止触发浏览器默认事件
event
.
preventDefault
()
showSearch
.
value
=
!
showSearch
.
value
// 这里可以执行相应的操作(例如打开搜索框等)
}
...
...
src/views/mall/promotion/diy/template/decorate.vue
View file @
1b2c7ceb
...
...
@@ -2,18 +2,18 @@
<DiyEditor
v-if=
"formData && !formLoading"
v-model=
"currentFormData!.property"
:title=
"templateItems[selectedTemplateItem].name"
:libs=
"libs"
:preview-url=
"previewUrl"
:show-navigation-bar=
"selectedTemplateItem !== 0"
:show-page-config=
"selectedTemplateItem !== 0"
:show-tab-bar=
"selectedTemplateItem === 0"
:show-navigation-bar=
"selectedTemplateItem !== 0"
:preview-url=
"previewUrl"
@
save=
"submitForm"
:title=
"templateItems[selectedTemplateItem].name"
@
reset=
"handleEditorReset"
@
save=
"submitForm"
>
<template
#
toolBarLeft
>
<el-radio-group
v-model
=
"selectedTemplateItem"
:model-value
=
"selectedTemplateItem"
class=
"h-full!"
@
change=
"handleTemplateItemChange"
>
...
...
@@ -26,13 +26,14 @@
</
template
>
</DiyEditor>
</template>
<
script
setup
lang=
"ts"
>
<
script
lang=
"ts"
setup
>
// TODO @疯狂:要不要建个 decorate 目录,然后挪进去,改成 index.vue,这样可以更明确看到是个独立界面哈,更好找
import
*
as
DiyTemplateApi
from
'@/api/mall/promotion/diy/template'
import
*
as
DiyPageApi
from
'@/api/mall/promotion/diy/page'
import
{
useTagsViewStore
}
from
'@/store/modules/tagsView'
import
{
DiyComponentLibrary
,
PAGE_LIBS
}
from
'@/components/DiyEditor/util'
// 商城的 DIY 组件,在 DiyEditor 目录下
import
{
toNumber
}
from
'lodash-es'
import
{
isEmpty
}
from
'@/utils/is'
/** 装修模板表单 */
defineOptions
({
name
:
'DiyTemplateDecorate'
})
...
...
@@ -52,6 +53,10 @@ const formData = ref<DiyTemplateApi.DiyTemplatePropertyVO>()
const
formRef
=
ref
()
// 表单 Ref
// 当前编辑的属性
const
currentFormData
=
ref
<
DiyTemplateApi
.
DiyTemplatePropertyVO
|
DiyPageApi
.
DiyPageVO
>
()
// templateItem 对应的缓存
const
currentFormDataMap
=
ref
<
Map
<
string
,
DiyTemplateApi
.
DiyTemplatePropertyVO
|
DiyPageApi
.
DiyPageVO
>
>
(
new
Map
())
// 商城 H5 预览地址
const
previewUrl
=
ref
(
''
)
...
...
@@ -60,8 +65,6 @@ const getPageDetail = async (id: any) => {
formLoading
.
value
=
true
try
{
formData
.
value
=
await
DiyTemplateApi
.
getDiyTemplateProperty
(
id
)
currentFormData
.
value
=
formData
.
value
// 拼接手机预览链接
const
domain
=
import
.
meta
.
env
.
VITE_MALL_H5_DOMAIN
previewUrl
.
value
=
`
${
domain
}
/#/pages/index/index?templateId=
${
formData
.
value
.
id
}
`
...
...
@@ -75,19 +78,31 @@ const templateLibs = [] as DiyComponentLibrary[]
// 当前组件库
const
libs
=
ref
<
DiyComponentLibrary
[]
>
(
templateLibs
)
// 模板选项切换
const
handleTemplateItemChange
=
()
=>
{
const
handleTemplateItemChange
=
(
val
:
number
)
=>
{
// 缓存模版编辑数据
currentFormDataMap
.
value
.
set
(
templateItems
[
selectedTemplateItem
.
value
].
name
,
currentFormData
.
value
!
)
// 读取模版缓存
const
data
=
currentFormDataMap
.
value
.
get
(
templateItems
[
val
].
name
)
// 切换模版
selectedTemplateItem
.
value
=
val
// 编辑模板
if
(
selectedTemplateItem
.
value
===
0
)
{
if
(
val
===
0
)
{
libs
.
value
=
templateLibs
currentFormData
.
value
=
formData
.
value
currentFormData
.
value
=
isEmpty
(
data
)
?
formData
.
value
:
data
return
}
// 编辑页面
libs
.
value
=
PAGE_LIBS
currentFormData
.
value
=
formData
.
value
!
.
pages
.
find
(
(
page
:
DiyPageApi
.
DiyPageVO
)
=>
page
.
name
===
templateItems
[
selectedTemplateItem
.
value
].
name
currentFormData
.
value
=
isEmpty
(
data
)
?
formData
.
value
!
.
pages
.
find
(
(
page
:
DiyPageApi
.
DiyPageVO
)
=>
page
.
name
===
templateItems
[
val
].
name
)
:
data
}
// 提交表单
...
...
@@ -97,12 +112,25 @@ const submitForm = async () => {
// 提交请求
formLoading
.
value
=
true
try
{
if
(
selectedTemplateItem
.
value
===
0
)
{
// 对所有的 templateItems 都进行保存,有缓存则保存缓存,解决都有修改时只保存了当前所编辑的 templateItem,导致装修效果存在差异
for
(
let
i
=
0
;
i
<
templateItems
.
length
;
i
++
)
{
const
data
=
currentFormDataMap
.
value
.
get
(
templateItems
[
i
].
name
)
as
any
// 情况一:基础设置
if
(
i
===
0
)
{
// 提交模板属性
await
DiyTemplateApi
.
updateDiyTemplateProperty
(
unref
(
formData
)
!
)
}
else
{
await
DiyTemplateApi
.
updateDiyTemplateProperty
(
isEmpty
(
data
)
?
unref
(
formData
)
!
:
data
)
continue
}
// 提交页面属性
// 情况二:提交当前正在编辑的页面
if
(
currentFormData
.
value
?.
name
.
includes
(
templateItems
[
i
].
name
))
{
await
DiyPageApi
.
updateDiyPageProperty
(
unref
(
currentFormData
)
!
)
continue
}
// 情况三:提交页面编辑缓存
if
(
!
isEmpty
(
data
))
{
await
DiyPageApi
.
updateDiyPageProperty
(
data
!
)
}
}
message
.
success
(
'保存成功'
)
}
finally
{
...
...
@@ -140,10 +168,16 @@ const recoverPageIndex = () => {
const
pageIndex
=
toNumber
(
sessionStorage
.
getItem
(
DIY_PAGE_INDEX_KEY
))
||
0
// 移除标记
sessionStorage
.
removeItem
(
DIY_PAGE_INDEX_KEY
)
// 重新初始化数据
currentFormData
.
value
=
formData
.
value
currentFormDataMap
.
value
=
new
Map
<
string
,
DiyTemplateApi
.
DiyTemplatePropertyVO
|
DiyPageApi
.
DiyPageVO
>
()
// 切换页面
if
(
pageIndex
!==
selectedTemplateItem
.
value
)
{
selectedTemplateItem
.
value
=
pageIndex
handleTemplateItemChange
()
handleTemplateItemChange
(
pageIndex
)
}
}
//#endregion
...
...
src/views/mall/trade/brokerage/user/BrokerageOrderListDialog.vue
View file @
1b2c7ceb
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"推广
人
列表"
width=
"75%"
>
<Dialog
v-model=
"dialogVisible"
title=
"推广
订单
列表"
width=
"75%"
>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"85px"
>
<el-form-item
label=
"用户类型"
prop=
"
l
evel"
>
<el-radio-group
v-model=
"queryParams.
l
evel"
@
change=
"handleQuery"
>
<el-radio-button
checked
>
全部
</el-radio-button>
<el-radio-button
value=
"1"
>
一级推广人
</el-radio-button>
<el-radio-button
value=
"2"
>
二级推广人
</el-radio-button>
<el-form-item
label=
"用户类型"
prop=
"
sourceUserL
evel"
>
<el-radio-group
v-model=
"queryParams.
sourceUserL
evel"
@
change=
"handleQuery"
>
<el-radio-button
:value=
"0"
>
全部
</el-radio-button>
<el-radio-button
:
value=
"1"
>
一级推广人
</el-radio-button>
<el-radio-button
:
value=
"2"
>
二级推广人
</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"状态"
prop=
"status"
>
<el-select
v-model=
"queryParams.status"
placeholder=
"请选择状态"
clearable
class=
"!w-240px"
clearable
placeholder=
"请选择状态"
>
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.BROKERAGE_RECORD_STATUS)"
...
...
@@ -34,64 +34,70 @@
<el-form-item
label=
"绑定时间"
prop=
"createTime"
>
<el-date-picker
v-model=
"queryParams.createTime"
value-format=
"YYYY-MM-DD HH:mm:ss"
type=
"daterange"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class=
"!w-240px"
end-placeholder=
"结束日期"
start-placeholder=
"开始日期"
type=
"daterange"
value-format=
"YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:s
tripe=
"true"
:show-overflow-tooltip
=
"true"
>
<el-table-column
label=
"订单编号"
align=
"center"
prop=
"bizId"
min-width=
"80px
"
/>
<el-table-column
label=
"用户编号"
align=
"center"
prop=
"sourceUserId"
min-width=
"80px
"
/>
<el-table-column
label=
"头像"
align=
"center
"
prop=
"sourceUserAvatar"
width=
"70px"
>
<el-table
v-loading=
"loading"
:data=
"list"
:s
how-overflow-tooltip=
"true"
:stripe
=
"true"
>
<el-table-column
align=
"center"
label=
"订单编号"
min-width=
"80px"
prop=
"bizId
"
/>
<el-table-column
align=
"center"
label=
"用户编号"
min-width=
"80px"
prop=
"sourceUserId
"
/>
<el-table-column
align=
"center"
label=
"头像
"
prop=
"sourceUserAvatar"
width=
"70px"
>
<template
#
default=
"scope"
>
<el-avatar
:src=
"scope.row.sourceUserAvatar"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"昵称"
align=
"center"
prop=
"sourceUserNickname"
min-width=
"80px
"
/>
<el-table-column
align=
"center"
label=
"昵称"
min-width=
"80px"
prop=
"sourceUserNickname
"
/>
<el-table-column
label=
"佣金
"
:formatter=
"fenToYuanFormat
"
align=
"center"
prop=
"price
"
label=
"佣金
"
min-width=
"100px"
:formatter=
"fenToYuanFormat
"
prop=
"price
"
/>
<el-table-column
label=
"状态"
align=
"center"
prop=
"status"
min-width=
"85
"
>
<el-table-column
align=
"center"
label=
"状态"
min-width=
"85"
prop=
"status
"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.BROKERAGE_RECORD_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"创建时间
"
:formatter=
"dateFormatter
"
align=
"center"
label=
"创建时间"
prop=
"createTime"
:formatter=
"dateFormatter"
width=
"180px"
/>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
v-model:page=
"queryParams.pageNo"
:total=
"total"
@
pagination=
"getList"
/>
</ContentWrap>
</Dialog>
</template>
<
script
setup
lang=
"ts"
>
<
script
lang=
"ts"
setup
>
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
*
as
BrokerageRecordApi
from
'@/api/mall/trade/brokerage/record'
import
{
BrokerageRecordBizTypeEnum
}
from
'@/utils/constants'
...
...
@@ -101,8 +107,6 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
/** 推广订单列表 */
defineOptions
({
name
:
'BrokerageOrderListDialog'
})
const
message
=
useMessage
()
// 消息弹窗
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
...
...
@@ -111,7 +115,7 @@ const queryParams = reactive({
pageSize
:
10
,
userId
:
null
,
bizType
:
BrokerageRecordBizTypeEnum
.
ORDER
.
type
,
level
:
''
,
sourceUserLevel
:
0
,
createTime
:
[],
status
:
null
})
...
...
@@ -130,7 +134,11 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
BrokerageRecordApi
.
getBrokerageRecordPage
(
queryParams
)
// 处理全部的情况
const
data
=
await
BrokerageRecordApi
.
getBrokerageRecordPage
({
...
queryParams
,
sourceUserLevel
:
queryParams
.
sourceUserLevel
===
0
?
undefined
:
queryParams
.
sourceUserLevel
})
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
...
...
src/views/mall/trade/brokerage/user/BrokerageUserCreateForm.vue
0 → 100644
View file @
1b2c7ceb
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"创建分销员"
width=
"800"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"formRules"
label-width=
"90"
>
<el-row
:gutter=
"20"
>
<el-col
:span=
"12"
:xs=
"24"
>
<el-form-item
label=
"分销员"
prop=
"userId"
>
<el-input
v-model=
"formData.userId"
v-loading=
"formLoading"
placeholder=
"请输入分销员编号"
>
<template
#
append
>
<el-button
@
click=
"handleGetUser(formData.userId, '分销员')"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
</el-button>
</
template
>
</el-input>
</el-form-item>
<!-- 展示分销员的信息 -->
<el-descriptions
v-if=
"userInfo.user"
:column=
"1"
border
>
<el-descriptions-item
label=
"头像"
>
<el-avatar
:src=
"userInfo.user?.avatar"
/>
</el-descriptions-item>
<el-descriptions-item
label=
"昵称"
>
{{ userInfo.user?.nickname }}
</el-descriptions-item>
</el-descriptions>
</el-col>
<el-col
:span=
"12"
:xs=
"24"
>
<el-form-item
label=
"上级推广人"
prop=
"bindUserId"
>
<el-input
v-model=
"formData.bindUserId"
v-loading=
"formLoading"
placeholder=
"请输入推广员编号"
>
<
template
#
append
>
<el-button
@
click=
"handleGetUser(formData.bindUserId, '推广员')"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
</el-button>
</
template
>
</el-input>
</el-form-item>
<!-- 展示上级推广人的信息 -->
<el-descriptions
v-if=
"userInfo.bindUser"
:column=
"1"
border
>
<el-descriptions-item
label=
"头像"
>
<el-avatar
:src=
"userInfo.bindUser?.avatar"
/>
</el-descriptions-item>
<el-descriptions-item
label=
"昵称"
>
{{ userInfo.bindUser?.nickname }}
</el-descriptions-item>
<el-descriptions-item
label=
"推广资格"
>
<el-tag
v-if=
"userInfo.bindUser?.brokerageEnabled"
>
有
</el-tag>
<el-tag
v-else
type=
"info"
>
无
</el-tag>
</el-descriptions-item>
<el-descriptions-item
label=
"成为推广员的时间"
>
{{ formatDate(userInfo.bindUser?.brokerageTime) }}
</el-descriptions-item>
</el-descriptions>
</el-col>
</el-row>
</el-form>
<
template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
BrokerageUserApi
from
'@/api/mall/trade/brokerage/user'
import
*
as
UserApi
from
'@/api/member/user'
import
{
formatDate
}
from
'@/utils/formatTime'
defineOptions
({
name
:
'BrokerageUserCreateForm'
})
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formData
=
ref
({
userId
:
undefined
,
bindUserId
:
undefined
})
const
formRef
=
ref
()
// 表单 Ref
const
formRules
=
reactive
({
userId
:
[{
required
:
true
,
message
:
'分销员不能为空'
,
trigger
:
'blur'
}]
})
/** 打开弹窗 */
const
open
=
async
()
=>
{
resetForm
()
dialogVisible
.
value
=
true
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
/** 创建分销员 */
const
submitForm
=
async
()
=>
{
if
(
formLoading
.
value
)
return
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
// 发起修改
await
BrokerageUserApi
.
createBrokerageUser
(
formData
.
value
)
message
.
success
(
t
(
'common.createSuccess'
))
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formRef
.
value
?.
resetFields
()
formData
.
value
=
{
userId
:
undefined
,
bindUserId
:
undefined
}
userInfo
.
bindUser
=
undefined
userInfo
.
user
=
undefined
}
/** 查询推广员和分销员 */
const
userInfo
=
reactive
<
{
bindUser
:
BrokerageUserApi
.
BrokerageUserVO
|
undefined
user
:
BrokerageUserApi
.
BrokerageUserVO
|
undefined
}
>
({
bindUser
:
undefined
,
user
:
undefined
})
const
handleGetUser
=
async
(
id
:
any
,
userType
:
string
)
=>
{
if
(
!
id
)
{
message
.
warning
(
`请先输入
${
userType
}
编号后重试!!!`
)
return
}
if
(
userType
===
'推广员'
&&
formData
.
value
.
bindUserId
==
formData
.
value
.
userId
)
{
message
.
error
(
'不能绑定自己为推广人'
)
return
}
const
user
=
userType
===
'推广员'
?
await
BrokerageUserApi
.
getBrokerageUser
(
id
)
:
await
UserApi
.
getUser
(
id
)
userType
===
'推广员'
?
(
userInfo
.
bindUser
=
user
)
:
(
userInfo
.
user
=
user
)
if
(
!
user
)
{
message
.
warning
(
`
${
userType
}
不存在`
)
}
}
</
script
>
src/views/mall/trade/brokerage/user/
UpdateBindUser
Form.vue
→
src/views/mall/trade/brokerage/user/
BrokerageUserUpdate
Form.vue
View file @
1b2c7ceb
...
...
@@ -43,8 +43,8 @@
import
*
as
BrokerageUserApi
from
'@/api/mall/trade/brokerage/user'
import
{
formatDate
}
from
'@/utils/formatTime'
/** 修改
上级推广人表单
*/
defineOptions
({
name
:
'
UpdateBindUser
Form'
})
/** 修改
分销用户
*/
defineOptions
({
name
:
'
BrokerageUserUpdate
Form'
})
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
...
...
src/views/mall/trade/brokerage/user/index.vue
View file @
1b2c7ceb
This diff is collapsed.
Click to expand it.
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