提交 339f967c authored 作者: 王鹏飞's avatar 王鹏飞

feat: 新增公众号授权

上级 4ad890e2
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,7 +6,7 @@ export function getConnectionList(params: { created_operator?: string; type?: st
}
// 创建链接
export function createConnection(data: { type: string; config_attributes: string }) {
export function createConnection(data: { type: string; config_attributes: any }) {
return httpRequest.post('/api/lab/v1/experiment/connection/create', data)
}
......@@ -16,7 +16,7 @@ export function getConnectionDetails(params: { id?: string }) {
}
// 更新链接
export function updateConnection(data: { id: string; config_attributes: string }) {
export function updateConnection(data: { id: string; config_attributes: any }) {
return httpRequest.post('/api/lab/v1/experiment/connection/update', data)
}
......@@ -39,3 +39,18 @@ export function getSurveyForm(params: { form_id: string }) {
export function submitSurveyForm(data: { id: string; form_id: string; form: string }) {
return httpRequest.post('/api/lab/v1/experiment/connection/save-survey-form-view', data)
}
// 获取公众号第三方授权操作地址
export function getWechatAuth(params: { connection_id: string; auth_type?: 1 | 2 | 3; redirect_uri: string }) {
return httpRequest.get('/api/lab/v1/experiment/wechat-platform/auth', { params })
}
// 同步授权方公众号信息到本地
export function asyncOfficialAccountInfo(params: { connection_id: string; appid: string }) {
return httpRequest.get('/api/lab/v1/experiment/wechat-platform/async-official-account', { params })
}
// 同步微信公众号用户到本地
export function asyncOfficialAccountUsers(params: { connection_id: string; appid: string }) {
return httpRequest.get('/api/lab/v1/experiment/wechat-platform/async-official-account', { params })
}
<script setup lang="ts">
import StepOne from '../components/StepOne.vue'
import StepTwo from '../components/StepTwo.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { createConnection, updateConnection } from '../api'
import type { DetailsProp } from '../types'
import { createConnection, updateConnection, getWechatAuth } from '../api'
import type { DetailsProp, PlatformItem, ConfigAttribute } from '../types'
const props = defineProps<{ data: DetailsProp | undefined }>()
const StepOne = defineAsyncComponent(() => import('../components/StepOne.vue'))
const StepTwo = defineAsyncComponent(() => import('../components/StepTwo.vue'))
const props = defineProps<{ data?: DetailsProp }>()
const emit = defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
// 请求参数
const params = $ref({ type: '', config_attributes: '' })
const platformList: PlatformItem[] = [
{
type: '1',
type_name: '公众号',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' }
// { label: '公众号类型', prop: 'type', value: '' },
// { label: '授权方昵称', prop: 'nikeName', value: '' }
],
async onBeforeNext(stepActive) {
if (stepActive === 2) {
const res = await handleSubmit()
const { data } = await getWechatAuth({ connection_id: res.id, redirect_uri: location.href, auth_type: 1 })
location.href = data.url
return false
}
return true
}
},
{
type: '2',
type_name: '钉钉',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'AgentId', prop: 'agentId', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '3',
type_name: '小鹅通',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'app_id', prop: 'app_id', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'secret_key', prop: 'secret_key', value: '' }
]
},
{
type: '4',
type_name: '问卷星',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{ type: '5', type_name: '今日头条', config_attributes: [{ label: '连接名称', prop: 'name', value: '' }] },
{
type: '6',
type_name: '抖音',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: '应用类别', prop: 'dyInput1', value: '' },
{ label: '授权域回调', prop: 'dyInput2', value: '' },
{ label: '网站应用简介', prop: 'dyInput3', value: '' },
{ label: '应用官网', prop: 'dyInput4', value: '' },
{ label: '联系人姓名', prop: 'dyInput5', value: '' }
]
},
{
type: '7',
type_name: '微博',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '8',
type_name: '小红书',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '9',
type_name: '邮箱',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'client_secret', prop: 'client_secret', value: '' },
{ label: 'token URL', prop: 'token', value: '' },
{ label: 'API URL', prop: 'apiUrl', value: '' }
]
},
{
type: '10',
type_name: '短信',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'SdkAppId', prop: 'sdkAppId', value: '' },
{ label: 'token URL', prop: 'token', value: '' },
{ label: 'API URL', prop: 'apiUrl', value: '' }
]
},
{ type_name: '内部消息', type: '11', config_attributes: [{ label: '连接名称', prop: 'name', value: '' }] },
{
type: '12',
type_name: '自定义',
config_attributes: [
{ label: '连接名称', prop: 'name', value: '' },
{ label: 'APP类型', prop: 'appType', value: '' },
{ label: 'AppId', prop: 'appId', value: '' }
]
},
{ type: '13', type_name: '卷王', icon: '99', config_attributes: [{ label: '连接名称', prop: 'name', value: '' }] },
{
type: '14',
type_name: '小程序',
icon: '100',
config_attributes: [{ label: '连接名称', prop: 'name', value: '' }],
async onBeforeNext(stepActive) {
if (stepActive === 2) {
const res = await handleSubmit()
const { data } = await getWechatAuth({ connection_id: res.id, redirect_uri: location.href, auth_type: 2 })
location.href = data.url
return false
}
return true
}
}
]
// 提交
function handleSubmit() {
if (props.data?.id) {
const updateParams = { id: props.data?.id, config_attributes: stepTwo.value.formItem }
updateConnection(updateParams).then(() => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '保修改成功', type: 'success' })
})
} else {
createConnection(params).then(() => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '保存成功', type: 'success' })
})
// 请求参数
const params: { type: string; config_attributes: ConfigAttribute[] } = reactive({ type: '1', config_attributes: [] })
watchEffect(() => {
if (!props.data) return
const { type, config_attributes } = props.data
let attributes = []
if (Array.isArray(config_attributes)) {
attributes = config_attributes
} else if (typeof config_attributes === 'string') {
attributes = JSON.parse(config_attributes)
}
Object.assign(params, { type, config_attributes: attributes })
})
const selectedItem = computed(() => platformList.find(item => item.type === params.type))
const defaultStepActive = props.data?.id ? 2 : 1
const stepActive = ref(defaultStepActive)
const stepLength = 3
function handleChange(data: PlatformItem) {
params.config_attributes = data.config_attributes || []
}
// tabs
let activeName = $ref(props.data?.id ? 2 : 1)
// 上一步
function handlePrev() {
stepActive.value--
}
// 第三步成功弹窗
const openMsg = () => {
ElMessageBox.alert(`成功链接${stepOneValue.name}`, '提示', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: 'OK'
})
// 下一步
async function handleNext() {
const isEmpty = params.config_attributes.find(item => item.value === '')
if (isEmpty && stepActive.value === 2) {
ElMessage('请填写完整')
return
}
if (selectedItem.value?.onBeforeNext) {
const next = await selectedItem.value?.onBeforeNext(stepActive.value, selectedItem.value)
if (!next) return
}
stepActive.value++
}
// 第一步的值
const stepOneValue = $ref({
type: props.data?.type || '',
name: props.data?.type_name || '',
value: props.data?.config_attributes
})
const stepOne = ref()
const handleStepOneNext = function () {
const data = stepOne.value.getData()
params.type = data.name
stepOneValue.type = data.name
stepOneValue.name = data.label
activeName++
// 第三步成功弹窗
function handleTest() {
const typeName = selectedItem.value?.type_name
if (typeName) ElMessageBox.alert(`成功连接${typeName}`, '提示', { confirmButtonText: 'OK' })
}
// 第二步
const stepTwo = ref()
const handleStepTwoNext = function () {
const data = stepTwo.value.formItem
const isData = data.find((item: { label: string; value: string; prop: string }) => item.value === '')
if (!isData) {
activeName++
params.config_attributes = data
// 提交
async function handleSubmit() {
if (props.data?.id) {
await updateConnection({ id: props.data.id, ...params })
return props.data
} else {
ElMessage('请填写完整')
const res = await createConnection(params)
return res.data.detail
}
}
async function handleSave() {
await handleSubmit()
ElMessage({ message: props.data?.id ? '保存成功' : '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
}
</script>
<template>
<el-dialog class="connect-form" :title="props.data?.id ? '编辑链接' : '新建链接'" :close-on-click-modal="false" width="1050px" @update:modelValue="$emit('update:modelValue')">
<el-tabs v-model="activeName" class="demo-tabs">
<el-dialog class="connect-form" :title="props.data?.id ? '编辑连接' : '新建连接'" :close-on-click-modal="false" width="1050px" @update:modelValue="$emit('update:modelValue')">
<el-tabs v-model="stepActive" class="demo-tabs">
<!-- 第一步 -->
<el-tab-pane disabled label="选择链接类型" :name="1" v-if="!props.data?.id">
<StepOne ref="stepOne"></StepOne>
<el-tab-pane disabled lazy label="选择连接类型" :name="1" v-if="!props.data?.id">
<StepOne :platformList="platformList" v-model="params.type" @change="handleChange"></StepOne>
</el-tab-pane>
<!-- 第二步 -->
<el-tab-pane disabled label="配置链接信息" :name="2">
<StepTwo ref="stepTwo" :data="stepOneValue"></StepTwo>
<el-tab-pane disabled lazy label="配置连接信息" :name="2">
<StepTwo :platform="selectedItem" v-model="params.config_attributes" v-if="selectedItem"></StepTwo>
</el-tab-pane>
<el-tab-pane disabled label="测试链接" :name="3">
<el-button type="primary" @click="openMsg">测试链</el-button>
<el-tab-pane disabled lazy label="测试连接" :name="3">
<el-button type="primary" @click="handleTest">测试连</el-button>
</el-tab-pane>
</el-tabs>
<div class="button-flex">
<template v-if="props.data?.id">
<el-button type="primary" @click="activeName--" v-if="activeName === 3">上一步</el-button>
</template>
<template v-else>
<el-button type="primary" @click="activeName--" v-if="activeName === 2 || activeName === 3">上一步</el-button>
<el-button type="primary" @click="handleStepOneNext" v-if="activeName === 1">下一步</el-button>
<el-button type="primary" @click="handleStepTwoNext" v-if="activeName === 2">下一步</el-button>
<el-button type="primary" v-if="activeName === 3" @click="handleSubmit">保存</el-button>
</template>
<el-button type="primary" @click="handlePrev" v-if="stepActive !== defaultStepActive">上一步</el-button>
<el-button type="primary" @click="handleNext" v-if="stepActive < stepLength">下一步</el-button>
<el-button type="primary" @click="handleSave" v-if="stepActive === stepLength">保存</el-button>
</div>
</el-dialog>
</template>
......@@ -109,6 +238,7 @@ const handleStepTwoNext = function () {
}
}
.button-flex {
margin-top: 40px;
display: flex;
justify-content: center;
}
......
......@@ -27,6 +27,10 @@ const routerView = function () {
const edit = function () {
emits('edit', props.data.id)
}
const iconMap = {
'13': '99',
'14': '100'
}
</script>
<template>
......@@ -40,7 +44,7 @@ const edit = function () {
<el-icon size="20" color="#333"><Delete /></el-icon>
</div>
<div class="connect-item__icon">
<Icon w="40" h="40" :multicolour="true" class="svg" :name="data.type"></Icon>
<Icon w="40" h="40" :multiColor="true" class="svg" :name="iconMap[data.type] || data.type"></Icon>
</div>
<p>
{{ data.type === '12' ? data.config_attributes[0].value : data.type_name }}
......
<script setup lang="ts">
import type { IconProp } from '../types'
import type { PlatformItem } from '../types'
import Icon from '@/components/ConnectionIcon.vue'
// icon
const iconItems = $ref<IconProp[]>([
{ label: '公众号', name: '1', checkbox: true },
{ label: '钉钉', name: '2', checkbox: false },
{ label: '小鹅通', name: '3', checkbox: false },
{ label: '问卷星', name: '4', checkbox: false },
{ label: '今日头条', name: '5', checkbox: false },
{ label: '抖音', name: '6', checkbox: false },
{ label: '微博', name: '7', checkbox: false },
{ label: '小红书', name: '8', checkbox: false },
{ label: '邮箱', name: '9', checkbox: false },
{ label: '短信', name: '10', checkbox: false },
{ label: '内部消息', name: '11', checkbox: false },
{ label: '自定义', name: '12', checkbox: false },
{ label: '卷王', name: '13', checkbox: false }
])
defineProps<{ platformList: PlatformItem[] }>()
const modelValue = defineModel<string>({ default: '1' })
let typeValue = ref<IconProp>({ label: '公众号', name: '1', checkbox: true })
const emit = defineEmits<{
change: [data: PlatformItem]
}>()
const handleIcon = function (data: IconProp) {
iconItems.forEach((item: IconProp) => (item.checkbox = false))
data.checkbox = true
typeValue.value = data
function handleChange(item: PlatformItem) {
modelValue.value = item.type
emit('change', item)
}
const getData = function () {
return typeValue.value
}
defineExpose({ getData })
</script>
<template>
<div class="connect-from_icon__box">
<div v-for="item in iconItems" :key="item.name" :class="item.checkbox ? 'mr20-mt20 active box' : 'mr20-mt20 box'">
<div @click="handleIcon(item)" class="connect-form_icon" :style="`background: ${item.checkbox ? '#AA1941' : ''}`">
<Icon :multicolour="!item.checkbox" :color="item.checkbox ? '#fff' : ''" class="svg" :name="item.name"></Icon>
<div class="box" v-for="item in platformList" :key="item.type" :class="{ active: item.type === modelValue }" @click="handleChange(item)">
<div class="connect-form_icon">
<Icon :multiColor="item.type !== modelValue" :color="item.type === modelValue ? '#fff' : ''" class="svg" :name="item.icon || item.type"></Icon>
</div>
<div class="name">{{ item.label }}</div>
<div class="name">{{ item.type_name }}</div>
</div>
</div>
</template>
<style lang="scss">
.connect-from_icon__box {
display: grid;
grid-template-columns: repeat(4, 1fr);
row-gap: 20px;
column-gap: 20px;
.box {
padding: 10px 20px;
width: 180px;
height: 100px;
border: 1px dashed#ddd;
}
padding: 10px;
display: flex;
flex-wrap: wrap;
.mr20-mt20 {
margin-right: 20px;
margin-bottom: 20px;
cursor: pointer;
&.active {
.name {
color: #ba143e;
}
.connect-form_icon {
background: #aa1941;
box-shadow: 2px 2px 10px 0px rgba(0, 0, 0, 0.2);
}
}
......
<script setup lang="ts">
import type { FormInstance } from 'element-plus'
import type { PlatformItem, ConfigAttribute } from '../types'
const props = defineProps<{ data: { type: string; name: string; value?: string | Array<any> } }>()
const props = defineProps<{ platform: PlatformItem }>()
const modelValue = defineModel<ConfigAttribute[]>()
// 用户需知
const checked = $ref(true)
const checked = ref(true)
// form
const formRef = $ref<FormInstance>()
const formRef = ref<FormInstance>()
const formAll = ref([
{
type: '1',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: '公众号类型', prop: 'type', value: '' },
{ label: '授权方昵称', prop: 'nikeName', value: '' }
]
},
{
type: '2',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'AgentId', prop: 'agentId', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '3',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'app_id', prop: 'app_id', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'secret_key', prop: 'secret_key', value: '' }
]
},
{
type: '4',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '5',
form: [{ label: '链接名称', prop: 'name', value: '' }]
},
{
type: '6',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: '应用类别', prop: 'dyInput1', value: '' },
{ label: '授权域回调', prop: 'dyInput2', value: '' },
{ label: '网站应用简介', prop: 'dyInput3', value: '' },
{ label: '应用官网', prop: 'dyInput4', value: '' },
{ label: '联系人姓名', prop: 'dyInput5', value: '' }
]
},
{
type: '6',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: '应用类别', prop: 'dyInput1', value: '' },
{ label: '授权域回调', prop: 'dyInput2', value: '' },
{ label: '网站应用简介', prop: 'dyInput3', value: '' },
{ label: '应用官网', prop: 'dyInput4', value: '' },
{ label: '联系人姓名', prop: 'dyInput5', value: '' }
]
},
{
type: '7',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '8',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'AppKey', prop: 'appKey', value: '' },
{ label: 'AppSecret', prop: 'appSecret', value: '' }
]
},
{
type: '9',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'client_secret', prop: 'client_secret', value: '' },
{ label: 'token URL', prop: 'token', value: '' },
{ label: 'API URL', prop: 'apiUrl', value: '' }
]
},
{
type: '10',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'client_id', prop: 'client_id', value: '' },
{ label: 'SdkAppId', prop: 'sdkAppId', value: '' },
{ label: 'token URL', prop: 'token', value: '' },
{ label: 'API URL', prop: 'apiUrl', value: '' }
]
},
{
type: '11',
form: [{ label: '链接名称', prop: 'name', value: '' }]
},
{
type: '12',
form: [
{ label: '链接名称', prop: 'name', value: '' },
{ label: 'APP类型', prop: 'appType', value: '' },
{ label: 'AppId', prop: 'appId', value: '' }
]
},
{
type: '13',
form: [{ label: '名称', prop: 'name', value: '' }]
}
])
const formItem = computed(() => {
const [data] = formAll.value.filter(item => item.type === props.data.type)
let dataValue = []
try {
dataValue = Array.isArray(props.data?.value) ? props.data?.value : JSON.parse(props.data?.value || '')
} catch (error) {
console.log(error)
}
return props.data?.value ? Object.assign(data?.form, dataValue) : data?.form
const configList = computed(() => {
return props.platform.config_attributes || []
})
onMounted(() => {
modelValue.value = modelValue.value ? Object.assign([], configList.value, modelValue.value) : configList.value
})
defineExpose({ formItem })
function showItem(data: ConfigAttribute) {
return !!configList.value.find(item => item.prop === data.prop)
}
</script>
<template>
......@@ -154,11 +39,13 @@ defineExpose({ formItem })
<div class="content-right">
<el-form ref="formRef" label-suffix=":" label-width="122px">
<el-form-item label="链接类型">
<span>{{ props.data.name }}</span>
<span>{{ platform.type_name }}</span>
</el-form-item>
<el-form-item :label="item.label" :prop="item.prop" v-for="item in formItem" :key="item.prop">
<template v-for="item in modelValue" :key="item.prop">
<el-form-item :label="item.label" :prop="item.prop" v-if="showItem(item)">
<el-input v-model="item.value" placeholder="请输入"></el-input>
</el-form-item>
</template>
</el-form>
</div>
</div>
......
......@@ -10,3 +10,17 @@ export interface DetailsProp {
type: string
type_name: string
}
export interface ConfigAttribute {
label: string
prop: string
value: string
}
export interface PlatformItem {
type: string
type_name: string
icon?: string
config_attributes?: ConfigAttribute[]
onBeforeNext?: (index: number, data: PlatformItem) => Promise<boolean> | boolean
}
<script setup lang="ts">
import type { ConfigAttribute } from '../types'
import { ElMessage, ElMessageBox } from 'element-plus'
import Icon from '@/components/ConnectionIcon.vue'
// import { ElMessageBox } from 'element-plus'
import { getConnectionDetails } from '../api'
import { getConnectionDetails, asyncOfficialAccountInfo, asyncOfficialAccountUsers } from '../api'
const router = useRouter()
const route = useRoute()
// 点击标签弹出详情文案(产品还没提供)
// const openMsg = () => {
// // ElMessageBox.alert('成功链接xxxx', '提示', {
// // confirmButtonText: '关闭'
// // })
// }
const connectId = computed<string>(() => (route.query.id as string) || '')
let dataDetail = $ref<any>()
onMounted(() => {
getConnectionDetails({ id: route.query.id as '' }).then(res => {
dataDetail = res.data
})
let detail = ref<any>()
async function fetchInfo() {
const res = await getConnectionDetails({ id: connectId.value })
detail.value = res.data
}
onMounted(fetchInfo)
const attributes = computed<ConfigAttribute[]>(() => {
const config_attributes = detail.value.config_attributes || []
if (typeof config_attributes === 'string') {
return JSON.parse(config_attributes)
} else {
return config_attributes || []
}
})
function getAttributeValueByProp(prop: string) {
return attributes.value.find(item => item.prop === prop)?.value || ''
}
const ability = [
const platformList = [
{
type: 1,
type_name: '公众号',
data: [
{
title: '1.从公众号同步',
child: [
{ title: '重新获取公众号信息', msg: '' },
{ title: '重新获取公众号粉丝', msg: '' },
{ title: '获取公众号统计数据', msg: '' },
{ title: '获取图文群发评论数据', msg: '' }
children: [
{
title: '重新获取公众号信息',
async onClick() {
await asyncOfficialAccountInfo({ connection_id: connectId.value, appid: getAttributeValueByProp('appid') })
ElMessage.success('重新获取公众号信息成功')
}
},
{
title: '重新获取公众号粉丝',
async onClick() {
const nikeName = getAttributeValueByProp('nikeName')
await ElMessageBox.confirm(`同步微信公众号粉丝能够将微信粉丝的最新信息同步到本系统中,您确定现在要开始同步公众号“${nikeName}”的粉丝吗?`, '同步微信公众号粉丝')
await asyncOfficialAccountUsers({ connection_id: connectId.value, appid: getAttributeValueByProp('appid') })
ElMessage.success(`已经开始同步公众号“${nikeName}”的粉丝,完成时间取决于您公众号的粉丝数量,请耐心等待。`)
}
}
// { title: '获取公众号统计数据', msg: '' },
// { title: '获取图文群发评论数据', msg: '' }
]
},
{
title: '2.向公众号同步',
child: [{ title: '批量为用户打标签', msg: '' }]
children: [{ title: '批量为用户打标签', msg: '' }]
},
{
title: '3.其他设置',
child: [
children: [
{ title: '客服会话设置', msg: '' },
{ title: '删除GDPR数据', msg: '' }
]
},
{
title: '4.客户旅程能力:触发条件',
child: [
{ title: '注公众号', msg: '' },
children: [
{ title: '注公众号', msg: '' },
{ title: '留言文本', msg: '' },
{ title: '留言图片', msg: '' },
{ title: '留言语音', msg: '' },
......@@ -64,7 +88,7 @@ const ability = [
},
{
title: '5.客户旅程能力:执行动作',
child: [
children: [
{ title: '发送文本', msg: '' },
{ title: '发送模版消息', msg: '' },
{ title: '发送菜单会话', msg: '' },
......@@ -82,35 +106,37 @@ const ability = [
},
{
type: 2,
type_name: '钉钉',
data: [
{
title: '1.从钉钉同步',
child: [{ title: '获取用户信息', msg: '' }]
children: [{ title: '获取用户信息', msg: '' }]
},
{
title: '2.向钉钉同步',
child: [{ title: '导入用户信息', msg: '' }]
children: [{ title: '导入用户信息', msg: '' }]
},
{
title: '3.其他设置',
child: [{ title: '访问钉钉官方网站', msg: '' }]
children: [{ title: '访问钉钉官方网站', msg: '' }]
},
{
title: '4.客户旅程能力:触发条件',
child: []
children: []
},
{
title: '5.客户旅程能力:执行动作',
child: [{ title: '发送消息', msg: '' }]
children: [{ title: '发送消息', msg: '' }]
}
]
},
{
type: 3,
type_name: '小鹅通',
data: [
{
title: '1.从小鹅通同步',
child: [
children: [
{ title: '消息推送', msg: '' },
{ title: '同步历史用户', msg: '' },
{ title: '同步直播学员签到事件', msg: '' }
......@@ -118,11 +144,11 @@ const ability = [
},
{
title: '2.向小鹅通同步',
child: []
children: []
},
{
title: '3.其他设置',
child: [
children: [
{ title: '访问小鹅通官方网站', msg: '' },
{ title: '配置用户属性字段映射', msg: '' },
{ title: '配置事件属性字段映射', msg: '' },
......@@ -131,82 +157,85 @@ const ability = [
},
{
title: '4.客户旅程能力:触发条件',
child: [{ title: '新用户注册', msg: '' }]
children: [{ title: '新用户注册', msg: '' }]
},
{
title: '5.客户旅程能力:执行动作',
child: []
children: []
}
]
},
{
type: 4,
type_name: '问卷星',
data: [
{
title: '1.从问卷星同步',
child: [{ title: '同步填写者信息', msg: '' }]
children: [{ title: '同步填写者信息', msg: '' }]
},
{
title: '2.向问卷星同步',
child: []
children: []
},
{
title: '3.其他设置',
child: [
children: [
{ title: '访问问卷星官方网站', msg: '' },
{ title: '管理表单字段映射', msg: '' }
]
},
{
title: '4.客户旅程能力:触发条件',
child: [{ title: '提交表单', msg: '' }]
children: [{ title: '提交表单', msg: '' }]
},
{
title: '5.客户旅程能力:执行动作',
child: []
children: []
}
]
},
{
type: 5,
type_name: '今日头条',
data: [
{
title: '1.从今日头条同步',
child: [
children: [
{ title: '同步头条推广基础数据', msg: '' },
{ title: '同步头条推广展点消数据', msg: '' }
]
},
{
title: '2.向今日头条同步',
child: [
children: [
{ title: '飞鱼线索表格导入', msg: '' },
{ title: '设置返点系数', msg: '' }
]
},
{
title: '3.其他设置',
child: [
children: [
{ title: '访问今日头条投放管理平台', msg: '' },
{ title: '广告效果分析', msg: '' }
]
},
{
title: '4.客户旅程能力:触发条件',
child: []
children: []
},
{
title: '5.客户旅程能力:执行动作',
child: []
children: []
}
]
},
{
type: 6,
type_name: '抖音',
data: [
{
title: '1.从抖音同步',
child: [
children: [
{ title: '获取用户视频情况', msg: '' },
{ title: '获取用户粉丝数', msg: '' },
{ title: '获取用户点赞数', msg: '' },
......@@ -217,15 +246,15 @@ const ability = [
},
{
title: '2.向抖音同步',
child: []
children: []
},
{
title: '3.其他设置',
child: []
children: []
},
{
title: '4.客户旅程能力:触发条件',
child: [
children: [
{ title: '用户发送文本私信', msg: '' },
{ title: '用户发送表情私信', msg: '' },
{ title: '用户发送卡片私信', msg: '' },
......@@ -234,7 +263,7 @@ const ability = [
},
{
title: '5.客户旅程能力:执行动作',
child: [
children: [
{ title: '向用户发送文本私信', msg: '' },
{ title: '向用户发送图片私信', msg: '' },
{ title: '向用户发送视频私信', msg: '' }
......@@ -244,10 +273,11 @@ const ability = [
},
{
type: 7,
type_name: '微博',
data: [
{
title: '1.从微博同步',
child: [
children: [
{ title: '获取用户信息', msg: '' },
{ title: '获取用户私信数', msg: '' },
{ title: '获取用户关注数', msg: '' }
......@@ -255,22 +285,22 @@ const ability = [
},
{
title: '2.向微博同步',
child: []
children: []
},
{
title: '3.其他设置',
child: []
children: []
},
{
title: '4.客户旅程能力:触发条件',
child: [
children: [
{ title: '关注微博', msg: '' },
{ title: '发送私信', msg: '' }
]
},
{
title: '5.客户旅程能力:执行动作',
child: [
children: [
{ title: '发送私信', msg: '' },
{ title: '发送图片', msg: '' }
]
......@@ -279,10 +309,11 @@ const ability = [
},
{
type: 8,
type_name: '小红书',
data: [
{
title: '1.从小红书同步',
child: [
children: [
{ title: '获取小红书用户信息', msg: '' },
{ title: '获取主页粉丝数', msg: '' },
{ title: '获取主页赞藏数', msg: '' },
......@@ -295,15 +326,15 @@ const ability = [
},
{
title: '2.向小红书同步',
child: []
children: []
},
{
title: '3.其他设置',
child: []
children: []
},
{
title: '4.客户旅程能力:触发条件',
child: [
children: [
{ title: '被用户关注', msg: '' },
{ title: '主页被点赞', msg: '' },
{ title: '主页被收藏', msg: '' },
......@@ -314,94 +345,98 @@ const ability = [
},
{
title: '5.客户旅程能力:执行动作',
child: []
children: []
}
]
},
{
type: 9,
type_name: '邮箱',
data: [
{
title: '1.从邮件同步',
child: []
children: []
},
{
title: '2.向邮件同步',
child: []
children: []
},
{
title: '3.其他设置',
child: []
children: []
},
{
title: '4.客户旅程能力:触发条件',
child: []
children: []
},
{
title: '5.客户旅程能力:执行动作',
child: [{ title: '发送邮件', msg: '' }]
children: [{ title: '发送邮件', msg: '' }]
}
]
},
{
type: 10,
type_name: '短信',
data: [
{
title: '1.从短信同步',
child: []
children: []
},
{
title: '2.向短信同步',
child: []
children: []
},
{
title: '3.其他设置',
child: [
children: [
{ title: '管理签名', msg: '' },
{ title: '管理模板', msg: '' }
]
},
{
title: '4.客户旅程能力:触发条件',
child: []
children: []
},
{
title: '5.客户旅程能力:执行动作',
child: [{ title: '发送短信', msg: '' }]
children: [{ title: '发送短信', msg: '' }]
}
]
},
{
type: 11,
type_name: '内部消息',
data: [
{
title: '1.从内部消息同步',
child: []
children: []
},
{
title: '2.向内部消息同步',
child: []
children: []
},
{
title: '3.其他设置',
child: []
children: []
},
{
title: '4.客户旅程能力:触发条件',
child: []
children: []
},
{
title: '5.客户旅程能力:执行动作',
child: [{ title: '发送内部消息', msg: '' }]
children: [{ title: '发送内部消息', msg: '' }]
}
]
},
{
type: 12,
type_name: '自定义',
data: [
{
title: '1.从自定义同步',
child: [
children: [
{ title: 'IOS移动应用接入', msg: '' },
{ title: '安卓移动应用接入', msg: '' },
{ title: 'JS SDK接入', msg: '' },
......@@ -411,11 +446,11 @@ const ability = [
},
{
title: '2.向自定义同步',
child: []
children: []
},
{
title: '3.其他设置',
child: [
children: [
{ title: '自定义图元', msg: '' },
{ title: '事件元数据', msg: '' },
{ title: '删除用户', msg: '' }
......@@ -423,7 +458,7 @@ const ability = [
},
{
title: '4.客户旅程能力:触发条件',
child: [
children: [
{ title: '访问网页', msg: '' },
{ title: '激活APP', msg: '' },
{ title: '启动APP', msg: '' },
......@@ -437,16 +472,17 @@ const ability = [
{
title: '5.客户旅程能力:执行动作',
child: []
children: []
}
]
},
{
type: 13,
type_name: '卷王',
data: [
{
title: '',
child: [
children: [
{
title: '访问卷王表单网站',
onClick() {
......@@ -462,39 +498,50 @@ const ability = [
]
}
]
},
{
type: 14,
type_name: '小程序',
data: []
}
]
const abilityItem = computed(() => {
const [data] = ability.filter(item => item.type === parseInt(dataDetail?.type))
return data?.data
const platformDataList = computed(() => {
return platformList.find(item => item.type == detail.value?.type)?.data || []
})
function handleClick(item: any) {
item.onClick && item.onClick()
}
const iconMap: any = {
'13': '99',
'14': '100'
}
</script>
<template>
<AppCard title="查看链接">
<div class="view-info">
<div class="view-info" v-if="detail">
<div class="view-info_icon">
<Icon :multicolour="true" :name="dataDetail?.type || '0'" w="50" h="50"></Icon>
<Icon :multiColor="true" :name="iconMap[detail.type] || detail.type" w="50" h="50" />
</div>
<div class="view-info_content">
<p>链接名称:{{ dataDetail?.type_name }}</p>
<!-- <p>公众号类型:订阅号</p> -->
<p>创始人:{{ dataDetail?.created_operator_name }}</p>
<!-- <p>授权方:xxxxxxxx</p> -->
<p>创建时间:{{ dataDetail?.created_time }}</p>
<p>连接名称:{{ getAttributeValueByProp('name') || detail.type_name }}</p>
<template v-if="detail.type === '1' || detail.type === '14'">
<p>公众号类型:{{ getAttributeValueByProp('level') }}</p>
<p>授权方:{{ getAttributeValueByProp('nikeName') }}</p>
</template>
<p>创建人:{{ detail.created_operator_name }}</p>
<p>创建时间:{{ detail.created_time }}</p>
</div>
</div>
</AppCard>
<AppCard title="链接能力">
<el-tabs class="tabs-box" v-for="(item, index) in abilityItem" :key="index">
<el-tabs class="tabs-box" v-for="(item, index) in platformDataList" :key="index">
<el-tab-pane :label="item.title">
<div class="tag-box" v-if="item.child.length">
<div class="tag" v-for="cItem in item.child" :key="cItem.title" @click="handleClick(cItem)">{{ cItem.title }}</div>
<div class="tag-box" v-if="item.children.length">
<div class="tag" v-for="cItem in item.children" :key="cItem.title" @click="handleClick(cItem)">{{ cItem.title }}</div>
</div>
<div class="tag-null" v-else>无数据</div>
</el-tab-pane>
......
......@@ -96,17 +96,8 @@ function handleViewEvent(item: any) {
<div class="home-right_content">
<AppCard class="card" title="最近活跃用户跟踪">
<div class="content-user">
<div
:class="item.isActive ? 'content-user_item active' : 'content-user_item'"
v-for="item in userList"
:key="item.id"
@click="handleUser(item)">
<img
:src="
item.gender === '1'
? 'https://webapp-pub.ezijing.com/pages/assa/dml_boy.png'
: 'https://webapp-pub.ezijing.com/pages/assa/dml_girl.png'
" />
<div :class="item.isActive ? 'content-user_item active' : 'content-user_item'" v-for="item in userList" :key="item.id" @click="handleUser(item)">
<img :src="item.gender === '1' ? 'https://webapp-pub.ezijing.com/pages/assa/dml_boy.png' : 'https://webapp-pub.ezijing.com/pages/assa/dml_girl.png'" />
<div class="name">{{ item.name }}</div>
</div>
</div>
......@@ -120,7 +111,7 @@ function handleViewEvent(item: any) {
</div>
<!-- <Icon :name="item.connection_type" w="30" h="30"></Icon> -->
<div class="event">
<Icon class="icon" :name="item.connection_type" :multicolour="true" w="24" h="24"></Icon>
<Icon class="icon" :name="item.connection_type" :multiColor="true" w="24" h="24"></Icon>
<span>"{{ item.connection_name }}"</span>
<span style="cursor: pointer" @click="handleViewEvent(item)">"{{ item.event_name }}"</span>
......@@ -131,11 +122,7 @@ function handleViewEvent(item: any) {
</div>
</div>
<!-- 事件详情 -->
<ViewEvent
v-model="viewEventVisible"
:event="currentViewEvent"
:user="currentUser"
v-if="viewEventVisible && currentViewEvent"></ViewEvent>
<ViewEvent v-model="viewEventVisible" :event="currentViewEvent" :user="currentUser" v-if="viewEventVisible && currentViewEvent"></ViewEvent>
</template>
<style lang="scss" scoped>
......
......@@ -49,31 +49,11 @@ function handleSave() {
<template>
<el-dialog title="配置连接" width="800px" append-to-body @update:modelValue="$emit('update:modelValue')">
<div class="connection-list">
<div
class="connection-item"
v-for="item in connectionList"
:key="item.id"
:class="{ 'is-active': isActive(item) }"
@click="toggleSelection(item)"
>
<div class="connection-item" v-for="item in connectionList" :key="item.id" :class="{ 'is-active': isActive(item) }" @click="toggleSelection(item)">
<el-checkbox @change="toggleSelection(item)" :model-value="isActive(item)" />
<div :class="isActive(item) ? 'connection-item__icon active' : 'connection-item__icon'">
<ConnectionIcon
style="transform: translateY(3px)"
v-if="isActive(item)"
color="#fff"
:name="item.type + ''"
w="20"
h="20"
/>
<ConnectionIcon
style="transform: translateY(3px)"
v-else
:multicolour="true"
:name="item.type + ''"
w="20"
h="20"
/>
<ConnectionIcon style="transform: translateY(3px)" v-if="isActive(item)" color="#fff" :name="item.type + ''" w="20" h="20" />
<ConnectionIcon style="transform: translateY(3px)" v-else :multiColor="true" :name="item.type + ''" w="20" h="20" />
</div>
<p :style="`color: ${isActive(item) && '#ba143e'}`">{{ item.name }}</p>
</div>
......
......@@ -130,7 +130,7 @@ function handleViewEvent(item: any) {
{{ item.updated_time?.slice(item.updated_time.indexOf(' '), item.updated_time.length - 3) }}
{{ getDate(item.updated_time) }}
</div>
<Icon class="icon" :multicolour="true" :name="item.connection_type" w="20" h="20"></Icon>
<Icon class="icon" :multiColor="true" :name="item.connection_type" w="20" h="20"></Icon>
<div class="event">
<span>"{{ item.connection_name }}"</span>
<span style="cursor: pointer" @click="handleViewEvent(item)">"{{ item.event_name }}"</span>
......
......@@ -10,7 +10,7 @@ import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig(({ mode }) => ({
base: mode === 'prod' ? 'https://webapp-pub.ezijing.com/website/prod/saas-dml/' : '/',
plugins: [
vue({ reactivityTransform: true }),
vue({ script: { defineModel: true }, reactivityTransform: true }),
AutoImport({
imports: ['vue', 'vue/macros', 'vue-router', '@vueuse/core'],
dts: true,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论