|
|
@@ -266,10 +266,36 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
<!-- 跳转链接 -->
|
|
|
- <el-form-item v-if="btn.actionType === 'link'" label="跳转链接 *">
|
|
|
- <el-input v-model="btn.link" size="small" placeholder="必填,输入跳转URL" @input="isModified = true">
|
|
|
- </el-input>
|
|
|
- </el-form-item>
|
|
|
+ <div v-if="btn.actionType === 'link'" class="jump-config-panel">
|
|
|
+ <div class="jump-config-title"><el-icon><Link /></el-icon> 跳转链接配置</div>
|
|
|
+ <el-form-item class="jump-type-item" label-width="0">
|
|
|
+ <el-radio-group v-model="btn.linkType" @change="handleButtonJumpTypeChange(btn)">
|
|
|
+ <el-radio label="h5">H5链接跳转</el-radio>
|
|
|
+ <el-radio label="fixed">固定链接跳转</el-radio>
|
|
|
+ <el-radio label="miniProgram">小程序跳转</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="btn.linkType === 'fixed'" label="目标链接">
|
|
|
+ <el-select v-model="btn.fixedLink" size="small" placeholder="请选择目标链接" style="width:100%" @change="handleButtonJumpFieldChange(btn)">
|
|
|
+ <el-option v-for="opt in fixedJumpOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="btn.linkType === 'h5'" label="配置链接">
|
|
|
+ <el-input v-model="btn.linkH5" size="small" placeholder="例如:https://hsbc.com" @input="handleButtonJumpFieldChange(btn)" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-row v-if="btn.linkType === 'miniProgram'" :gutter="16">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="AppID">
|
|
|
+ <el-input v-model="btn.miniAppId" size="small" placeholder="例如:wx1234567890abcdef" @input="handleButtonJumpFieldChange(btn)" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="页面路径">
|
|
|
+ <el-input v-model="btn.miniAppPath" size="small" placeholder="例如:pages/index/index" @input="handleButtonJumpFieldChange(btn)" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
<!-- 弹窗配置 -->
|
|
|
<div v-if="btn.actionType === 'dialog' && btn.dialog" class="dialog-config">
|
|
|
<div class="dialog-config-title"><el-icon><Document /></el-icon> 弹窗内容配置</div>
|
|
|
@@ -286,18 +312,49 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
- <el-row :gutter="16">
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="右侧确认按钮文案">
|
|
|
- <el-input v-model="btn.dialog.confirmText" size="small" placeholder="确认" @input="isModified = true" />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- <el-col :span="12">
|
|
|
- <el-form-item label="确认按钮跳转链接">
|
|
|
- <el-input v-model="btn.dialog.confirmLink" size="small" placeholder="选填,无链接则仅关闭弹窗" @input="isModified = true" />
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
+ <div class="dialog-button-config">
|
|
|
+ <div class="confirm-config-header">
|
|
|
+ <span>左侧取消按钮配置</span>
|
|
|
+ </div>
|
|
|
+ <el-input v-model="btn.dialog.cancelText" size="small" placeholder="取消" @input="isModified = true" />
|
|
|
+ </div>
|
|
|
+ <div class="dialog-button-config confirm-button-config">
|
|
|
+ <div class="confirm-config-header">
|
|
|
+ <span>右侧确认按钮配置</span>
|
|
|
+ <el-checkbox v-model="btn.dialog.showConfirm" @change="isModified = true">展示</el-checkbox>
|
|
|
+ </div>
|
|
|
+ <el-input v-if="btn.dialog.showConfirm" v-model="btn.dialog.confirmText" size="small" placeholder="确认" @input="isModified = true" />
|
|
|
+ </div>
|
|
|
+ <div v-if="btn.dialog.showConfirm" class="jump-config-panel dialog-jump-config">
|
|
|
+ <div class="jump-config-title"><el-icon><Link /></el-icon> 确认按钮跳转链接配置</div>
|
|
|
+ <el-form-item class="jump-type-item" label-width="0">
|
|
|
+ <el-radio-group v-model="btn.dialog.confirmLinkType" @change="handleDialogJumpTypeChange(btn.dialog)">
|
|
|
+ <el-radio label="h5">H5链接跳转</el-radio>
|
|
|
+ <el-radio label="fixed">固定链接跳转</el-radio>
|
|
|
+ <el-radio label="miniProgram">小程序跳转</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="btn.dialog.confirmLinkType === 'fixed'" label="目标链接">
|
|
|
+ <el-select v-model="btn.dialog.confirmFixedLink" size="small" placeholder="请选择目标链接" style="width:100%" @change="handleDialogJumpFieldChange(btn.dialog)">
|
|
|
+ <el-option v-for="opt in fixedJumpOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="btn.dialog.confirmLinkType === 'h5'" label="配置链接">
|
|
|
+ <el-input v-model="btn.dialog.confirmLinkH5" size="small" placeholder="例如:https://hsbc.com" @input="handleDialogJumpFieldChange(btn.dialog)" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-row v-if="btn.dialog.confirmLinkType === 'miniProgram'" :gutter="16">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="AppID">
|
|
|
+ <el-input v-model="btn.dialog.confirmMiniAppId" size="small" placeholder="例如:wx1234567890abcdef" @input="handleDialogJumpFieldChange(btn.dialog)" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="页面路径">
|
|
|
+ <el-input v-model="btn.dialog.confirmMiniAppPath" size="small" placeholder="例如:pages/index/index" @input="handleDialogJumpFieldChange(btn.dialog)" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
@@ -383,7 +440,7 @@
|
|
|
<script>
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import request from '@/utils/request'
|
|
|
-import { fetchLinkOptions } from '@/utils/linkOptions'
|
|
|
+import { FIXED_JUMP_OPTIONS, fetchLinkOptions } from '@/utils/linkOptions'
|
|
|
|
|
|
let blockIdCounter = 0
|
|
|
function genBlockId() {
|
|
|
@@ -406,6 +463,7 @@ export default {
|
|
|
linkForm: { campaignId: '', channelId: '' },
|
|
|
campaignOptions: [],
|
|
|
channelOptions: [],
|
|
|
+ fixedJumpOptions: FIXED_JUMP_OPTIONS,
|
|
|
linkTargetId: '',
|
|
|
linkTargetPublished: false,
|
|
|
quillOptions: {
|
|
|
@@ -446,8 +504,36 @@ export default {
|
|
|
this.fetchList()
|
|
|
},
|
|
|
methods: {
|
|
|
+ createDefaultJumpConfig(overrides = {}) {
|
|
|
+ return {
|
|
|
+ linkType: 'h5',
|
|
|
+ fixedLink: '',
|
|
|
+ linkH5: '',
|
|
|
+ miniAppId: '',
|
|
|
+ miniAppPath: '',
|
|
|
+ ...overrides
|
|
|
+ }
|
|
|
+ },
|
|
|
+ createDefaultDialogJumpConfig(overrides = {}) {
|
|
|
+ return {
|
|
|
+ confirmLinkType: 'h5',
|
|
|
+ confirmFixedLink: '',
|
|
|
+ confirmLinkH5: '',
|
|
|
+ confirmMiniAppId: '',
|
|
|
+ confirmMiniAppPath: '',
|
|
|
+ ...overrides
|
|
|
+ }
|
|
|
+ },
|
|
|
createDefaultButtonDialog() {
|
|
|
- return { title: '', desc: '', confirmText: '确认', confirmLink: '' }
|
|
|
+ return {
|
|
|
+ title: '',
|
|
|
+ desc: '',
|
|
|
+ cancelText: '取消',
|
|
|
+ showConfirm: true,
|
|
|
+ confirmText: '确认',
|
|
|
+ confirmLink: '',
|
|
|
+ ...this.createDefaultDialogJumpConfig()
|
|
|
+ }
|
|
|
},
|
|
|
createDefaultButton(overrides = {}) {
|
|
|
return {
|
|
|
@@ -455,6 +541,7 @@ export default {
|
|
|
link: '',
|
|
|
style: 'secondary',
|
|
|
actionType: 'link',
|
|
|
+ ...this.createDefaultJumpConfig(),
|
|
|
...overrides,
|
|
|
dialog: {
|
|
|
...this.createDefaultButtonDialog(),
|
|
|
@@ -478,12 +565,89 @@ export default {
|
|
|
target[key] = value
|
|
|
}
|
|
|
},
|
|
|
+ isFixedJumpValue(value) {
|
|
|
+ return FIXED_JUMP_OPTIONS.some(opt => opt.value === value)
|
|
|
+ },
|
|
|
+ inferButtonJumpType(btn = {}) {
|
|
|
+ if (btn.linkType) return btn.linkType
|
|
|
+ if (btn.miniAppId || btn.miniAppPath) return 'miniProgram'
|
|
|
+ if (this.isFixedJumpValue(btn.link)) return 'fixed'
|
|
|
+ return 'h5'
|
|
|
+ },
|
|
|
+ inferDialogJumpType(dialog = {}) {
|
|
|
+ if (dialog.confirmLinkType) return dialog.confirmLinkType
|
|
|
+ if (dialog.confirmMiniAppId || dialog.confirmMiniAppPath) return 'miniProgram'
|
|
|
+ if (this.isFixedJumpValue(dialog.confirmLink)) return 'fixed'
|
|
|
+ if (dialog.confirmLinkH5 || dialog.confirmLink) return 'h5'
|
|
|
+ return 'h5'
|
|
|
+ },
|
|
|
+ syncButtonLegacyLink(btn) {
|
|
|
+ if (btn.linkType === 'fixed') btn.link = btn.fixedLink || ''
|
|
|
+ if (btn.linkType === 'h5') btn.link = btn.linkH5 || ''
|
|
|
+ if (btn.linkType === 'miniProgram') btn.link = ''
|
|
|
+ },
|
|
|
+ syncDialogLegacyLink(dialog) {
|
|
|
+ if (dialog.confirmLinkType === 'fixed') dialog.confirmLink = dialog.confirmFixedLink || ''
|
|
|
+ if (dialog.confirmLinkType === 'h5') dialog.confirmLink = dialog.confirmLinkH5 || ''
|
|
|
+ if (dialog.confirmLinkType === 'miniProgram') dialog.confirmLink = ''
|
|
|
+ },
|
|
|
+ clearInactiveButtonJumpFields(btn) {
|
|
|
+ if (btn.linkType !== 'fixed') btn.fixedLink = ''
|
|
|
+ if (btn.linkType !== 'h5') btn.linkH5 = ''
|
|
|
+ if (btn.linkType !== 'miniProgram') {
|
|
|
+ btn.miniAppId = ''
|
|
|
+ btn.miniAppPath = ''
|
|
|
+ }
|
|
|
+ this.syncButtonLegacyLink(btn)
|
|
|
+ },
|
|
|
+ clearInactiveDialogJumpFields(dialog) {
|
|
|
+ if (dialog.confirmLinkType !== 'fixed') dialog.confirmFixedLink = ''
|
|
|
+ if (dialog.confirmLinkType !== 'h5') dialog.confirmLinkH5 = ''
|
|
|
+ if (dialog.confirmLinkType !== 'miniProgram') {
|
|
|
+ dialog.confirmMiniAppId = ''
|
|
|
+ dialog.confirmMiniAppPath = ''
|
|
|
+ }
|
|
|
+ this.syncDialogLegacyLink(dialog)
|
|
|
+ },
|
|
|
+ normalizeButtonJumpConfig(btn) {
|
|
|
+ const linkType = this.inferButtonJumpType(btn)
|
|
|
+ const legacyLink = btn.link || ''
|
|
|
+ const normalized = this.createDefaultJumpConfig({
|
|
|
+ ...btn,
|
|
|
+ linkType,
|
|
|
+ fixedLink: btn.fixedLink || (this.isFixedJumpValue(legacyLink) ? legacyLink : '太古地产'),
|
|
|
+ linkH5: btn.linkH5 || (!this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
|
|
|
+ miniAppId: btn.miniAppId || '',
|
|
|
+ miniAppPath: btn.miniAppPath || ''
|
|
|
+ })
|
|
|
+ Object.keys(normalized).forEach(key => {
|
|
|
+ btn[key] = normalized[key]
|
|
|
+ })
|
|
|
+ this.clearInactiveButtonJumpFields(btn)
|
|
|
+ },
|
|
|
+ normalizeDialogJumpConfig(dialog) {
|
|
|
+ const confirmLinkType = this.inferDialogJumpType(dialog)
|
|
|
+ const legacyLink = dialog.confirmLink || ''
|
|
|
+ const normalized = this.createDefaultDialogJumpConfig({
|
|
|
+ ...dialog,
|
|
|
+ confirmLinkType,
|
|
|
+ confirmFixedLink: dialog.confirmFixedLink || (this.isFixedJumpValue(legacyLink) ? legacyLink : '太古地产'),
|
|
|
+ confirmLinkH5: dialog.confirmLinkH5 || (!this.isFixedJumpValue(legacyLink) ? legacyLink : ''),
|
|
|
+ confirmMiniAppId: dialog.confirmMiniAppId || '',
|
|
|
+ confirmMiniAppPath: dialog.confirmMiniAppPath || ''
|
|
|
+ })
|
|
|
+ Object.keys(normalized).forEach(key => {
|
|
|
+ dialog[key] = normalized[key]
|
|
|
+ })
|
|
|
+ this.clearInactiveDialogJumpFields(dialog)
|
|
|
+ },
|
|
|
normalizeButton(btn) {
|
|
|
if (!btn) return
|
|
|
if (!btn.text) this.ensureReactiveField(btn, 'text', '')
|
|
|
if (!btn.style) this.ensureReactiveField(btn, 'style', 'secondary')
|
|
|
if (!btn.actionType) this.ensureReactiveField(btn, 'actionType', 'link')
|
|
|
if (!Object.prototype.hasOwnProperty.call(btn, 'link')) this.ensureReactiveField(btn, 'link', '')
|
|
|
+ this.normalizeButtonJumpConfig(btn)
|
|
|
if (!btn.dialog) {
|
|
|
this.ensureReactiveField(btn, 'dialog', this.createDefaultButtonDialog())
|
|
|
} else {
|
|
|
@@ -494,6 +658,7 @@ export default {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
+ this.normalizeDialogJumpConfig(btn.dialog)
|
|
|
},
|
|
|
normalizeAssemblyData(data) {
|
|
|
data.shareConfig = this.createDefaultShareConfig(data.shareConfig || {})
|
|
|
@@ -562,12 +727,13 @@ export default {
|
|
|
data.blocks.forEach(block => {
|
|
|
if (block.type === 'buttonGroup') {
|
|
|
block.data.buttons.forEach(btn => {
|
|
|
- if (btn.actionType === 'link' && !(btn.link || '').trim()) hasError = true
|
|
|
+ if (btn.actionType === 'link' && !this.validateButtonJumpConfig(btn)) hasError = true
|
|
|
+ if (btn.actionType === 'dialog' && btn.dialog && btn.dialog.showConfirm !== false && !this.validateDialogJumpConfig(btn.dialog)) hasError = true
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
if (hasError) {
|
|
|
- ElMessage.error('保存失败:按钮模块中存在未填写的跳转链接!')
|
|
|
+ ElMessage.error('保存失败:按钮模块中存在未填写完整的跳转链接配置!')
|
|
|
return
|
|
|
}
|
|
|
if (data.shareConfig.enabled) {
|
|
|
@@ -662,6 +828,40 @@ export default {
|
|
|
this.normalizeButton(btn)
|
|
|
this.isModified = true
|
|
|
},
|
|
|
+ handleButtonJumpTypeChange(btn) {
|
|
|
+ if (btn.linkType === 'fixed' && !btn.fixedLink) btn.fixedLink = '太古地产'
|
|
|
+ this.clearInactiveButtonJumpFields(btn)
|
|
|
+ this.isModified = true
|
|
|
+ },
|
|
|
+ handleButtonJumpFieldChange(btn) {
|
|
|
+ this.syncButtonLegacyLink(btn)
|
|
|
+ this.isModified = true
|
|
|
+ },
|
|
|
+ handleDialogJumpTypeChange(dialog) {
|
|
|
+ if (dialog.confirmLinkType === 'fixed' && !dialog.confirmFixedLink) dialog.confirmFixedLink = '太古地产'
|
|
|
+ this.clearInactiveDialogJumpFields(dialog)
|
|
|
+ this.isModified = true
|
|
|
+ },
|
|
|
+ handleDialogJumpFieldChange(dialog) {
|
|
|
+ this.syncDialogLegacyLink(dialog)
|
|
|
+ this.isModified = true
|
|
|
+ },
|
|
|
+ validateButtonJumpConfig(btn) {
|
|
|
+ if (btn.linkType === 'fixed') return !!btn.fixedLink
|
|
|
+ if (btn.linkType === 'h5') return !!(btn.linkH5 || '').trim()
|
|
|
+ if (btn.linkType === 'miniProgram') {
|
|
|
+ return !!(btn.miniAppId || '').trim() && !!(btn.miniAppPath || '').trim()
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ },
|
|
|
+ validateDialogJumpConfig(dialog) {
|
|
|
+ if (dialog.confirmLinkType === 'fixed') return !!dialog.confirmFixedLink
|
|
|
+ if (dialog.confirmLinkType === 'h5') return !!(dialog.confirmLinkH5 || '').trim()
|
|
|
+ if (dialog.confirmLinkType === 'miniProgram') {
|
|
|
+ return !!(dialog.confirmMiniAppId || '').trim() && !!(dialog.confirmMiniAppPath || '').trim()
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ },
|
|
|
removeButton(bIdx, btnIdx) {
|
|
|
this.editData.blocks[bIdx].data.buttons.splice(btnIdx, 1)
|
|
|
this.isModified = true
|
|
|
@@ -732,6 +932,23 @@ export default {
|
|
|
.info-item { display: flex; align-items: center; gap: 8px; }
|
|
|
.info-label { font-size: 13px; color: #909399; white-space: nowrap; }
|
|
|
|
|
|
+.page-assembly :deep(.el-input:not(.el-textarea)) {
|
|
|
+ --el-input-height: 32px;
|
|
|
+}
|
|
|
+.page-assembly :deep(.el-input:not(.el-textarea) .el-input__wrapper),
|
|
|
+.page-assembly :deep(.el-select__wrapper) {
|
|
|
+ height: 32px;
|
|
|
+ min-height: 32px;
|
|
|
+}
|
|
|
+.page-assembly :deep(.el-input:not(.el-textarea) .el-input__inner) {
|
|
|
+ height: 30px;
|
|
|
+ line-height: 30px;
|
|
|
+}
|
|
|
+.page-assembly :deep(.el-select .el-select__placeholder),
|
|
|
+.page-assembly :deep(.el-select .el-select__selected-item) {
|
|
|
+ line-height: 30px;
|
|
|
+}
|
|
|
+
|
|
|
.required-star { color: #F56C6C; }
|
|
|
.dialog-desc-editor {
|
|
|
width: 100%;
|
|
|
@@ -902,6 +1119,49 @@ export default {
|
|
|
font-size: 14px; font-weight: 500; color: #303133;
|
|
|
border-bottom: 1px solid #ebeef5; padding-bottom: 12px; margin-bottom: 14px;
|
|
|
}
|
|
|
+.dialog-button-config {
|
|
|
+ width: 33.333%;
|
|
|
+ min-width: 280px;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+.confirm-config-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ height: 22px;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ color: #303133;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 20px;
|
|
|
+}
|
|
|
+.confirm-config-header :deep(.el-checkbox) {
|
|
|
+ height: 20px;
|
|
|
+ margin-right: 0;
|
|
|
+}
|
|
|
+.jump-config-panel {
|
|
|
+ background: #fff;
|
|
|
+ padding: 16px 18px 4px;
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ border-radius: 4px;
|
|
|
+ margin-top: 4px;
|
|
|
+}
|
|
|
+.dialog-jump-config {
|
|
|
+ margin-top: 2px;
|
|
|
+}
|
|
|
+.jump-config-title {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+.jump-type-item {
|
|
|
+ margin-bottom: 18px;
|
|
|
+}
|
|
|
+.jump-config-panel :deep(.el-radio) {
|
|
|
+ margin-right: 22px;
|
|
|
+}
|
|
|
|
|
|
.add-block-bar {
|
|
|
display: flex; gap: 16px; justify-content: center;
|