提交 2ea5d6a3 authored 作者: lihuihui's avatar lihuihui

元数据,链接管理开发

上级 e89409f6
......@@ -113,7 +113,6 @@
"useArrayMap": true,
"useArrayReduce": true,
"useArraySome": true,
"useArrayUnique": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
......@@ -197,7 +196,6 @@
"useParallax": true,
"usePermission": true,
"usePointer": true,
"usePointerLock": true,
"usePointerSwipe": true,
"usePreferredColorScheme": true,
"usePreferredContrast": true,
......
......@@ -114,7 +114,6 @@ declare global {
const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
......@@ -198,7 +197,6 @@ declare global {
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
......
......@@ -5,6 +5,7 @@ const styleHeight = computed(() => {
})
</script>
<template>
<div class="app-card">
<div class="app-card-hd">
......
import httpRequest from '@/utils/axios'
// 链接列表
export function getConnectionList(params: { created_operator?: string; type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/connection/list', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 创建链接
export function createConnection(data: { type: string; config_attributes: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/connection/create', { experiment_id: '7025368348925886464', ...data })
}
// 链接详情
export function getConnectionDetails(params: { id?: string; }) {
return httpRequest.get('/api/experiment/v1/experiment/connection/view', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 更新链接
export function updateConnection(data: { id: string; config_attributes: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/connection/update', { experiment_id: '7025368348925886464', ...data })
}
// 删除链接
export function deleteConnection(data: { id: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/connection/delete', { experiment_id: '7025368348925886464', ...data })
}
\ No newline at end of file
<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'
const props = defineProps<{ data: DetailsProp | undefined }>()
const emit = defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
// 请求参数
const params = $ref({ type: '', config_attributes: '' })
// 提交
function handleSubmit() {
if (props.data?.id) {
const updateParams = { id: props.data?.id, config_attributes: JSON.stringify(stepTwo.value.formItem) }
updateConnection(updateParams).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '保修改成功', type: 'success' })
})
} else {
createConnection(params).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '保存成功', type: 'success' })
})
}
}
// tabs
let activeName = $ref(props.data?.id ? 2 : 1)
// 第三步成功弹窗
const openMsg = () => {
ElMessageBox.alert(`成功链接${stepOneValue.name}`, '提示', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: 'OK'
})
}
// 第一步的值
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++
}
// 第二步
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 = JSON.stringify(data)
} else {
ElMessage('请填写完整')
}
}
</script>
<template>
<el-dialog
class="connect-form"
title="新建链接"
:close-on-click-modal="false"
width="800px"
@update:modelValue="$emit('update:modelValue')"
>
<el-tabs v-model="activeName" class="demo-tabs">
<!-- 第一步 -->
<el-tab-pane disabled label="选择链接类型" :name="1" v-if="!props.data?.id">
<StepOne ref="stepOne"></StepOne>
</el-tab-pane>
<!-- 第二步 -->
<el-tab-pane disabled label="配置链接信息" :name="2">
<StepTwo ref="stepTwo" :data="stepOneValue"></StepTwo>
</el-tab-pane>
<el-tab-pane disabled label="测试链接" :name="3">
<el-button type="primary" @click="openMsg">测试链接</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>
<el-button v-else 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>
</div>
</el-dialog>
</template>
<style lang="scss">
.connect-form {
.el-dialog__body {
padding-top: 10px;
}
}
.button-flex {
display: flex;
justify-content: center;
}
</style>
差异被折叠。
<script setup lang="ts">
import { Delete, ElemeFilled } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import { Delete, Edit } from '@element-plus/icons-vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import Icon from '../components/Icon.vue'
import { deleteConnection } from '../api'
const emits = defineEmits<{
(e: 'update'): void
}>()
const props = defineProps<{ data: { id: string; type_name: string; type: string } }>()
const router = useRouter()
const emits = defineEmits(['update', 'edit'])
// 删除
function handleRemove() {
ElMessageBox.confirm('确定要删除该连接吗?', '提示').then(() => {
emits('update')
deleteConnection({ id: props.data?.id }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
emits('update')
})
})
}
// 去查看
const routerView = function () {
router.push({ path: '/connect/view', query: { id: props.data.id } })
}
const edit = function () {
emits('edit', props.data?.id)
}
</script>
<template>
<div class="connect-item">
<div class="connect-item__edit">
<el-icon @click="edit"><Edit /></el-icon>
</div>
<div class="connect-item__remove" @click="handleRemove">
<el-icon><Delete /></el-icon>
</div>
<div class="connect-item__icon">
<el-icon><ElemeFilled /></el-icon>
<div @click="routerView" style="display: flex; width: 100%; flex-direction: column; align-items: center">
<div class="connect-item__icon">
<Icon class="svg" :name="data?.type"></Icon>
</div>
<p>{{ data?.type_name }}</p>
</div>
<p>连接名称</p>
</div>
</template>
......@@ -42,6 +62,9 @@ function handleRemove() {
.connect-item__remove {
display: block;
}
.connect-item__edit {
display: block;
}
}
}
.connect-item__remove {
......@@ -49,5 +72,13 @@ function handleRemove() {
position: absolute;
right: 8px;
top: 8px;
z-index: 999;
}
.connect-item__edit {
display: none;
position: absolute;
left: 8px;
top: 8px;
z-index: 999;
}
</style>
<script setup lang="ts">
import type { IconProp } from '../types'
import Icon from '../components/Icon.vue'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
// 属性字段类型
const experimentAttributeOptions = $ref(store.getMapValuesByKey('experiment_attribute_type'))
// 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 }
])
let typeValue = ref<IconProp>({ label: '公众号', name: '1', checkbox: true })
const handleIcon = function (data: IconProp) {
iconItems.forEach((item: IconProp) => (item.checkbox = false))
data.checkbox = true
typeValue.value = data
}
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' : 'mr20-mt20'">
<div @click="handleIcon(item)" class="connect-form_icon">
<Icon class="svg" :name="item.name"></Icon>
</div>
<div class="name">{{ item.label }}</div>
</div>
</div>
</template>
<style lang="scss">
.connect-from_icon__box {
padding: 10px;
display: flex;
flex-wrap: wrap;
.mr20-mt20 {
margin-right: 20px;
margin-bottom: 20px;
&.active {
.name {
color: #ba143e;
}
.connect-form_icon {
box-shadow: 0 0 10px rgb(186, 20, 62, 0.5);
border: 1px solid #ba143e;
}
}
}
.name {
text-align: center;
margin-top: 8px;
}
.connect-form_icon {
width: 70px;
height: 70px;
border-radius: 50%;
border: 1px solid #000;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
&:hover {
box-shadow: 0 0 10px rgb(0 0 0 / 50%);
}
}
}
</style>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
const props = defineProps<{ data: { type: string; name: string; value?: string } }>()
// 用户需知
const checked = $ref(true)
// form
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: '' }
]
}
])
const formItem = computed(() => {
const [data] = formAll.value.filter(item => item.type === props.data.type)
console.log(props.data?.value, 'value')
return props.data?.value ? Object.assign(data?.form, JSON.parse(props.data?.value)) : data?.form
})
defineExpose({ formItem })
</script>
<template>
<div class="step-two_content">
<div class="content-left">
<h2>用户需知</h2>
<p>亲爱的系统用户,您即将进入链接页面,链接前请您认真阅读一下说明:</p>
<p>
1、您即将链接的系统属于第三方平台,关于此系统的一切内容以及疑问,本公司无法代表此系统提供官方的准确回复,建议您<strong
>及时联系此系统的官方客服人员;</strong
>
</p>
<p>
2、本系统是一个客户数据平台,通过链接全局客户数据,帮助企业构建第一方客户池,数据源为各个与本系统链接的第三方平台,如链接的系统出现数据异常,本公司没有权限进入该系统排查,烦请<strong
>及时联系该系统相关技术人员协助处理。</strong
>
</p>
<el-checkbox v-model="checked" label="我确认上述用户需知" size="large" />
</div>
<div class="content-right">
<el-form ref="formRef" label-suffix=":" label-width="122px">
<el-form-item label="链接类型">
<span>{{ props.data.name }}</span>
</el-form-item>
<el-form-item :label="item.label" :prop="item.prop" v-for="item in formItem">
<el-input v-model="item.value" placeholder="请输入"></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<style lang="scss">
.step-two_content {
display: flex;
padding-bottom: 20px;
.content-left {
padding: 0 20px;
flex: 1;
h2 {
font-size: 16px;
text-align: center;
padding: 20px 0 10px;
}
p {
text-indent: 2em;
margin-bottom: 10px;
strong {
font-weight: bold;
}
}
}
.content-right {
padding-top: 20px;
flex: 1;
}
}
</style>
......@@ -5,7 +5,10 @@ const routes: RouteRecordRaw[] = [
{
path: '/connect',
component: Layout,
children: [{ path: '', component: () => import('./views/Index.vue') }]
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: 'view', component: () => import('./views/View.vue') }
]
}
]
......
export interface IconProp {
label: string
name: string
checkbox: boolean
}
export interface DetailsProp {
id: string
config_attributes: string
type: string
type_name: string
}
\ No newline at end of file
<script setup lang="ts">
import type { DetailsProp } from '../types'
import { Plus } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue'
import ListItem from '../components/ListItem.vue'
import { getConnectionList, getConnectionDetails } from '../api'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置
const listOptions = computed(() => {
return {
remote: {
httpRequest: getConnectionList,
params: { created_operator: '', type: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '请输入连接名称' },
{ type: 'input', prop: 'name', placeholder: '请输入创建人姓名' }
],
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '属性ID', prop: 'id' },
{ label: '属性名称', prop: 'name' },
{ label: '属性字段类型', prop: 'name' },
{ label: '状态', prop: 'name' },
{ label: '更新人', prop: 'name' },
{ label: '更新时间', prop: 'name' },
{ label: '操作', slots: 'table-x', width: 240 }
],
data: [{}, {}]
{ type: 'input', prop: 'created_operator', placeholder: '请输入创建人姓名' },
{
type: 'select',
prop: 'type',
placeholder: '请选择类型',
options: store.getMapValuesByKey('experiment_connection_type')
}
]
}
})
......@@ -29,6 +34,22 @@ const listOptions = computed(() => {
function handleRefresh() {
appList?.refetch()
}
// 新建
let formVisible = $ref(false)
const createConnect = function () {
formData = undefined
formVisible = true
}
// 编辑
let formData = $ref<DetailsProp | undefined>()
const editConnect = function (id: string) {
getConnectionDetails({ id: id }).then(res => {
formData = res.data
formVisible = true
})
}
</script>
<template>
......@@ -36,9 +57,14 @@ function handleRefresh() {
<AppList v-bind="listOptions" ref="appList">
<template #body="{ data }">
<div class="connect-list">
<ListItem v-for="item in data" :key="item.id" @update="handleRefresh"></ListItem>
<div class="connect-item">
<ListItem
@edit="editConnect"
:data="item"
v-for="item in data"
:key="item.id"
@update="handleRefresh"
></ListItem>
<div class="connect-item" @click="createConnect">
<div class="connect-add-button">
<el-icon><Plus /></el-icon>
<span>新建连接</span>
......@@ -48,6 +74,8 @@ function handleRefresh() {
</template>
</AppList>
</AppCard>
<!-- 新建链接 -->
<FormDialog :data="formData" v-model="formVisible" v-if="formVisible" @update="handleRefresh" />
</template>
<style lang="scss">
......
差异被折叠。
import httpRequest from '@/utils/axios'
// 事件属性列表
export function getMetaEvent(params: { name?: string; status?: string; experiment_connection_id?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-event/list', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 创建事件属性
export function createMetaEvent(data: { name: string; english_name: string; experiment_connection_id: string; status: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-event/create', { experiment_id: '7025368348925886464', ...data })
}
// 链接列表
export function getConnectionsList() {
return httpRequest.get('/api/experiment/v1/experiment/meta-event/connections', { params: { experiment_id: '7025368348925886464' } })
}
// 修改事件属性
export function updateMetaEvent(data: { id?: string; name: string; english_name: string; status: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-event/update', { experiment_id: '7025368348925886464', ...data })
}
// 删除
export function deleteMetaEvent(data: { id?: string }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-event/delete', { experiment_id: '7025368348925886464', ...data })
}
// 事件属性列表
export function getMetaEventDetail(params: { id: string }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-event/view', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 保存属性
export function updateAttributes(data: { id: string; attributes: string }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-event/attributes', { experiment_id: '7025368348925886464', ...data })
}
// 事件属性列表
export function getIsDeleteAttribute(params: { id: string }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-event/can-delete-attribute', { params: { experiment_id: '7025368348925886464', ...params } })
}
\ No newline at end of file
<script setup lang="ts">
import type { EventProp, EventDetailProp, EventAttributesProp } from '../types'
import { ElMessage } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { Close } from '@element-plus/icons-vue'
import { getMetaEventDetail, updateAttributes, getIsDeleteAttribute } from '../api'
const store = useMapStore()
interface Props {
data?: EventProp
}
const props = defineProps<Props>()
const emit = defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
// 属性字段类型
const experimentAttributeOptions = $ref(store.getMapValuesByKey('experiment_attribute_type'))
// 添加字段
const addField = function () {
tableData.push({ id: '', name: '', english_name: '', type: '', format: '' })
}
// 删除字段
const deleteField = function (scope: { $index: number; row: { id: string } }) {
if (tableData[scope.$index]?.id === '') {
tableData.splice(scope.$index, 1)
} else {
// 判断当前属性是否可以删除
getIsDeleteAttribute({ id: scope.row.id }).then(res => {
res.data?.can_delete ? tableData.splice(scope.$index, 1) : ElMessage({ message: '不能删除', type: 'warning' })
})
}
}
// 事件详情
let eventDetail = $ref<EventDetailProp>()
onBeforeMount(() => {
getMetaEventDetail({ id: props.data?.id || '' }).then(res => {
eventDetail = res.data
tableData = res.data.attributes
})
})
// 字段
let tableData = $ref<EventAttributesProp[]>([])
// 提交
function handleSubmit() {
handleUpdate()
}
function handleUpdate() {
const params = {
id: eventDetail?.id || '',
attributes: JSON.stringify(tableData)
}
updateAttributes(params).then(res => {
ElMessage({ message: '保存成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
</script>
<template>
<el-dialog
title="事件属性"
:close-on-click-modal="false"
width="800px"
@update:modelValue="$emit('update:modelValue')"
>
<div style="display: flex; justify-content: space-around">
<el-form label-width="120px">
<el-form-item label="事件英文名称:">{{ eventDetail?.english_name }}</el-form-item>
<el-form-item label="事件名称:">{{ eventDetail?.name }}</el-form-item>
</el-form>
<el-form label-width="120px">
<el-form-item label="所属链接:">{{ eventDetail?.connection_name }}</el-form-item>
<el-form-item label="状态:">{{ eventDetail?.status_name }}</el-form-item>
</el-form>
</div>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>事件属性字段</span>
<el-button type="primary" @click="addField">添加</el-button>
</div>
</template>
<el-table :data="tableData" style="width: 100%">
<el-table-column label="属性英文名">
<template #default="scope">
<el-input v-model="scope.row.english_name" placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column label="属性名称">
<template #default="scope">
<el-input v-model="scope.row.name" placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column label="字段类型">
<template #default="scope">
<el-select :disabled="scope.row.id !== ''" v-model="scope.row.type" placeholder="请选择">
<el-option
:label="item.label"
:value="item.value"
:key="item.id"
v-for="item in experimentAttributeOptions"
></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="字段格式">
<template #default="scope">
<el-select
:disabled="scope.row.id !== ''"
v-if="scope.row.type === '4' || scope.row.type === '5'"
v-model="scope.row.format"
placeholder="请选择"
>
<el-option label="yyyy-mm-dd" value="yyyy-mm-dd"></el-option>
<el-option
v-if="scope.row.type !== '4'"
label="yyyy-mm-dd hh:mm:ss"
value="yyyy-mm-dd hh:mm:ss"
></el-option>
</el-select>
<el-input
v-else
:disabled="scope.row.id !== ''"
type="number"
v-model="scope.row.format"
:placeholder="scope.row.type === '1' ? '请输入字符串长度' : '请输入长度'"
></el-input>
</template>
</el-table-column>
<el-table-column width="30">
<template #default="scope">
<div @click="deleteField(scope)" style="display: flex; justify-content: center; cursor: pointer">
<el-icon size="20"><Close /></el-icon>
</div>
</template>
</el-table-column>
</el-table>
</el-card>
<template #footer>
<el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">关闭</el-button>
<el-button type="primary" round auto-insert-space @click="handleSubmit">保存</el-button>
</el-row>
</template>
</el-dialog>
</template>
<style lang="scss">
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
<script setup lang="ts">
import type { EventProp } from '../types'
import type { EventProp, ConnectionOptionProp } from '../types'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { createMetaEvent, updateMetaEvent } from '../api'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
interface Props {
data?: EventProp
option: ConnectionOptionProp[]
}
const props = defineProps<Props>()
......@@ -21,17 +26,19 @@ const title = $computed(() => {
})
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
status: ''
})
const form = reactive(
props.data || {
name: '',
english_name: '',
experiment_connection_id: '',
status: '0'
}
)
const rules = ref<FormRules>({
id: [{ required: true, message: '请输入事件ID' }],
name: [{ required: true, message: '请输入事件名称' }],
type: [{ required: true, message: '请选择属性字段类型' }]
name: [{ required: true, message: '请输入' }],
english_name: [{ required: true, message: '请输入' }],
experiment_connection_id: [{ required: true, message: '请选择' }]
})
// 提交
......@@ -43,32 +50,46 @@ function handleSubmit() {
// 新建
function handleCreate() {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
createMetaEvent(form).then(res => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate() {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
updateMetaEvent(form).then(res => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
</script>
<template>
<el-dialog :title="title" :close-on-click-modal="false" width="600px" @update:modelValue="$emit('update:modelValue')">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="100px">
<el-form-item label="事件ID" prop="id">
<el-input v-model="form.id" />
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="140px">
<el-form-item label="事件ID" prop="id" v-if="isUpdate">
<span>{{ props.data?.id }}</span>
</el-form-item>
<el-form-item label="事件英文名称" prop="english_name">
<el-input v-model="form.english_name" placeholder="请输入" />
</el-form-item>
<el-form-item label="事件名称" prop="name">
<el-input v-model="form.name" />
<el-input v-model="form.name" placeholder="请输入" />
</el-form-item>
<el-form-item label="所属连接" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
<el-form-item label="所属连接" prop="experiment_connection_id">
<el-select
:disabled="isUpdate"
v-model="form.experiment_connection_id"
style="width: 100%"
placeholder="请选择"
>
<el-option :label="item.type_name" :value="item.id" :key="item.id" v-for="item in props.option"></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-switch v-model="form.status" active-text="生效" inactive-text="失效" />
<el-switch v-model="form.status" active-text="生效" inactive-text="失效" active-value="1" inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
......
......@@ -8,18 +8,21 @@ defineProps<Props>()
<template>
<el-dialog title="查看事件属性" :close-on-click-modal="false" width="600px">
<el-form label-suffix=":" label-width="90px">
<el-form label-suffix=":" label-width="120px">
<el-form-item label="事件ID">
{{ data.id }}
</el-form-item>
<el-form-item label="事件英文名称">
{{ data.english_name }}
</el-form-item>
<el-form-item label="事件名称">
{{ data.id }}
{{ data.name }}
</el-form-item>
<el-form-item label="所属连接">
{{ data.id }}
{{ data.connection_name }}
</el-form-item>
<el-form-item label="状态">
{{ data.id }}
{{ data.status_name }}
</el-form-item>
</el-form>
<template #footer>
......
export interface EventProp {
id: string
name: string
english_name: string
experiment_connection_id: string
status: string
connection_name: string
status_name: string
}
export interface ConnectionOptionProp { type_name: string; id: string }
export interface EventDetailProp {
id: string
english_name: string
connection_name: string
name: string
status_name: string
attributes: EventAttributesProp[]
}
export interface EventAttributesProp {
id: string
name: string
english_name: string
type: string
format: string
}
<script setup lang="ts">
import type { EventProp } from '../types'
import type { EventProp, ConnectionOptionProp } from '../types'
import { Plus } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
import AppList from '@/components/base/AppList.vue'
import { getMetaEvent, getConnectionsList, deleteMetaEvent } from '../api'
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue'))
const FieldDialog = defineAsyncComponent(() => import('../components/FieldDialog.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 所属链接选项
let experimentConnectionOptions = $ref<ConnectionOptionProp[]>()
getConnectionsList().then(res => {
experimentConnectionOptions = res.data
})
// 列表配置
const listOptions = computed(() => {
return {
remote: {
httpRequest: getMetaEvent,
params: { name: '', status: '', experiment_connection_id: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '请输入事件名称' },
{
type: 'select',
prop: 'type',
placeholder: '请选择事件所属连接'
prop: 'experiment_connection_id',
placeholder: '请选择事件所属连接',
options: experimentConnectionOptions,
labelKey: 'type_name',
valueKey: 'id'
},
{
type: 'select',
prop: 'status',
placeholder: '请选择生效状态',
options: [
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
}
],
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '事件ID', prop: 'id' },
{ label: '事件英文名称', prop: 'english_name' },
{ label: '事件名称', prop: 'name' },
{ label: '所属连接', prop: 'name' },
{ label: '属性字段数量', prop: 'name' },
{ label: '状态', prop: 'name' },
{ label: '更新人', prop: 'name' },
{ label: '更新时间', prop: 'name' },
{ label: '所属连接', prop: 'connection_name' },
{ label: '属性字段数量', prop: 'attributes_count' },
{ label: '状态', prop: 'status_name' },
{ label: '更新人', prop: 'updated_operator_name' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 300 }
],
data: [{ id: 1 }, { id: 2 }]
]
}
})
......@@ -63,13 +88,25 @@ function handleView(row: EventProp) {
// 删除
function handleRemove(row: EventProp) {
ElMessageBox.confirm('确定要删除该属性吗?', '提示').then(() => {})
ElMessageBox.confirm('确定要删除该属性吗?', '提示').then(() => {
deleteMetaEvent({ id: row.id }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
handleRefresh()
})
})
}
// 字段
let fieldVisible = $ref(false)
const handleField = function (row: EventProp) {
currentRow = row
fieldVisible = true
}
</script>
<template>
<AppCard>
<AppList v-bind="listOptions">
<AppList v-bind="listOptions" ref="appList">
<template #header-buttons>
<el-space>
<el-button type="primary" :icon="Plus" @click="handleAdd">新建</el-button>
......@@ -79,12 +116,19 @@ function handleRemove(row: EventProp) {
<el-button type="primary" plain @click="handleView(row)">查看</el-button>
<el-button type="primary" plain @click="handleUpdate(row)">编辑</el-button>
<el-button type="primary" plain @click="handleRemove(row)">删除</el-button>
<el-button type="primary" plain>字段</el-button>
<el-button type="primary" plain @click="handleField(row)">字段</el-button>
</template>
</AppList>
</AppCard>
<!-- 新建/修改 -->
<FormDialog v-model="formVisible" :data="currentRow" @update="handleRefresh" v-if="formVisible" />
<FormDialog
v-model="formVisible"
:data="currentRow"
@update="handleRefresh"
:option="experimentConnectionOptions || []"
v-if="formVisible"
/>
<!-- 查看 -->
<ViewDialog v-model="viewVisible" :data="currentRow" v-if="viewVisible && currentRow" />
<FieldDialog v-model="fieldVisible" :data="currentRow" v-if="fieldVisible && currentRow"></FieldDialog>
</template>
import httpRequest from '@/utils/axios'
// 用户属性列表
export function getMemberMeta(params: { name?: string; status?: string; type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-member/list', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 用户属性详情
export function getMemberMetaDetail(params: { id: string }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-member/view', { params: { experiment_id: '7025368348925886464', ...params } })
}
// 创建用户属性
export function createMemberMeta(data: { name: string; english_name: string; type: string; format: string; status: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-member/create', { experiment_id: '7025368348925886464', ...data })
}
// 修改用户属性
export function updateMemberMeta(data: { id?: string; name: string; english_name: string; status: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-member/update', { experiment_id: '7025368348925886464', ...data })
}
// 修改用户属性
export function deleteMemberMeta(data: { id: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/meta-member/delete', { experiment_id: '7025368348925886464', ...data })
}
// 事件属性列表
export function getMetaEvent(params: { name?: string; status?: string; type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/meta-event/list', { params: { experiment_id: '7025368348925886464', ...params } })
}
\ No newline at end of file
......@@ -2,6 +2,10 @@
import type { UserProp } from '../types'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { createMemberMeta, updateMemberMeta } from '../api'
const store = useMapStore()
interface Props {
data?: UserProp
......@@ -21,19 +25,22 @@ const title = $computed(() => {
})
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
value: '',
status: ''
})
const form = reactive(
props.data || {
name: '',
english_name: '',
type: '',
format: '',
status: '0'
}
)
const rules = ref<FormRules>({
id: [{ required: true, message: '请输入属性ID' }],
name: [{ required: true, message: '请输入属性名称' }],
type: [{ required: true, message: '请选择属性字段类型' }],
value: [{ required: true, message: '请输入属性ID' }]
name: [{ required: true, message: '请输入' }],
english_name: [{ required: true, message: '请输入' }],
type: [{ required: true, message: '请选择' }],
format: [{ required: true, message: '请输入' }],
status: [{ required: true, message: '请选择' }]
})
// 提交
......@@ -45,35 +52,73 @@ function handleSubmit() {
// 新建
function handleCreate() {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
createMemberMeta(form).then(res => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate() {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
updateMemberMeta(form).then(res => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 属性字段类型
const experimentAttributeOptions = $ref(store.getMapValuesByKey('experiment_attribute_type'))
// 属性字段类型选择后->格式的placeholder改变
const formatPlaceholder = computed(() => {
return form.type === '1' ? '请输入字符串长度' : '请输入长度'
})
</script>
<template>
<el-dialog :title="title" :close-on-click-modal="false" width="600px" @update:modelValue="$emit('update:modelValue')">
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="122px">
<el-form-item label="属性ID" prop="id">
<el-input v-model="form.id" />
<el-form-item label="属性ID" v-if="isUpdate">
{{ props.data?.id }}
</el-form-item>
<el-form-item label="属性英文名称" prop="name">
<el-input v-model="form.name" placeholder="请输入" />
</el-form-item>
<el-form-item label="属性名称" prop="name">
<el-input v-model="form.name" />
<el-form-item label="属性名称" prop="english_name">
<el-input v-model="form.english_name" placeholder="请输入" />
</el-form-item>
<el-form-item label="属性字段类型" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
<el-select
:disabled="isUpdate"
@change="form.format = ''"
v-model="form.type"
style="width: 100%"
placeholder="请选择"
>
<el-option
:label="item.label"
:value="item.value"
:key="item.id"
v-for="item in experimentAttributeOptions"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="属性字段格式" prop="type">
<el-input v-model="form.value" />
<el-form-item label="属性字段格式" prop="format" v-if="form.type !== ''">
<el-select
:disabled="isUpdate"
v-if="form.type === '4' || form.type === '5'"
v-model="form.format"
style="width: 100%"
placeholder="请选择"
>
<el-option label="yyyy-mm-dd" value="yyyy-mm-dd"></el-option>
<el-option v-if="form.type !== '4'" label="yyyy-mm-dd hh:mm:ss" value="yyyy-mm-dd hh:mm:ss"></el-option>
</el-select>
<el-input :disabled="isUpdate" type="number" v-else v-model="form.format" :placeholder="formatPlaceholder" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-switch v-model="form.status" active-text="生效" inactive-text="失效" />
<el-switch v-model="form.status" active-text="生效" inactive-text="失效" active-value="1" inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
......
......@@ -12,17 +12,20 @@ defineProps<Props>()
<el-form-item label="属性ID">
{{ data.id }}
</el-form-item>
<el-form-item label="属性英文名称">
{{ data.english_name }}
</el-form-item>
<el-form-item label="属性名称">
{{ data.id }}
{{ data.name }}
</el-form-item>
<el-form-item label="属性字段类型">
{{ data.id }}
{{ data.type_name }}
</el-form-item>
<el-form-item label="属性字段格式">
{{ data.id }}
{{ data.format }}
</el-form-item>
<el-form-item label="状态">
{{ data.id }}
{{ data.status_name }}
</el-form-item>
</el-form>
<template #footer>
......
export interface UserProp {
id: string
name: string
english_name: string
type: string
format: string
status: string
type_name: string
status_name: string
}
<script setup lang="ts">
import type { UserProp } from '../types'
import { Plus } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
import AppList from '@/components/base/AppList.vue'
import { getMemberMeta, deleteMemberMeta } from '../api'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue'))
......@@ -11,25 +15,40 @@ const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置
const listOptions = computed(() => {
return {
remote: {
httpRequest: getMemberMeta,
params: { name: '', status: '', type: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '请输入用户属性名称' },
{
type: 'select',
prop: 'experiment_id',
placeholder: '请选择属性字段类型'
prop: 'type',
placeholder: '请选择属性字段类型',
options: store.getMapValuesByKey('experiment_attribute_type')
},
{
type: 'select',
prop: 'status',
placeholder: '请选择生效状态',
options: [
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
}
],
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '属性ID', prop: 'id' },
{ label: '属性名称', prop: 'name' },
{ label: '属性字段类型', prop: 'name' },
{ label: '状态', prop: 'name' },
{ label: '更新人', prop: 'name' },
{ label: '更新时间', prop: 'name' },
{ label: '属性英文名称', prop: 'english_name' },
{ label: '属性字段类型', prop: 'type_name' },
{ label: '属性字段格式', prop: 'format' },
{ label: '状态', prop: 'status_name' },
{ label: '更新人', prop: 'updated_operator_name' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 240 }
],
data: [{ id: 1 }, { id: 2 }]
]
}
})
......@@ -62,7 +81,12 @@ function handleView(row: UserProp) {
// 删除
function handleRemove(row: UserProp) {
ElMessageBox.confirm('确定要删除该属性吗?', '提示').then(() => {})
ElMessageBox.confirm('确定要删除该属性吗?', '提示').then(() => {
deleteMemberMeta({ id: row.id }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
handleRefresh()
})
})
}
</script>
......
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// interface Props {
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
value: '',
status: ''
})
const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }]
})
</script>
<template>
<el-dialog
class="connect-form"
title="新建用户"
:close-on-click-modal="false"
width="800px"
@update:modelValue="$emit('update:modelValue')"
>
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="142px">
<el-form-item label="所属实验" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
</el-form-item>
<el-form-item label="来源链接">
<el-select v-model="form.id" style="width: 100%"></el-select>
</el-form-item>
<el-form-item label="姓名">
<el-input v-model="form.id" style="width: 100%"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-radio-group v-model="form.id" class="ml-4">
<el-radio label="1" size="large">生效</el-radio>
<el-radio label="2" size="large">失效</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="性别">
<el-input v-model="form.id" style="width: 100%"></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="form.id" style="width: 100%"></el-input>
</el-form-item>
</el-form>
<div class="btn-box">
<el-button type="primary">保存</el-button>
<el-button type="primary">关闭</el-button>
</div>
</el-dialog>
</template>
<style lang="scss">
.btn-box {
text-align: center;
margin-bottom: 20px;
}
</style>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// interface Props {
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
value: '',
status: ''
})
const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }]
})
</script>
<template>
<el-dialog
title="新建用户事件数据"
:close-on-click-modal="false"
width="500px"
@update:modelValue="$emit('update:modelValue')"
>
<div class="update-event_info">
<span>姓名:王小二</span>
<span>来源链接:抖音</span>
</div>
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="122px">
<el-form-item label="请选择事件" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
</el-form-item>
<el-form-item label="订单金额" prop="type">
<el-input v-model="form.type" style="width: 100%"></el-input>
</el-form-item>
</el-form>
<div class="btn-box">
<el-button type="primary">关闭</el-button>
<el-button type="primary">保存</el-button>
</div>
</el-dialog>
</template>
<style lang="scss">
.btn-box {
text-align: center;
margin-bottom: 20px;
}
.update-event_info {
padding-left: 25px;
padding-bottom: 20px;
display: flex;
justify-content: space-between;
}
</style>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// interface Props {
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
value: '',
status: ''
})
const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }]
})
</script>
<template>
<el-dialog
class="connect-form"
title="导入用户事件数据"
:close-on-click-modal="false"
width="500px"
@update:modelValue="$emit('update:modelValue')"
>
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="122px">
<el-form-item label="请选择事件" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
<span>事件所属链接:抖音</span>
</el-form-item>
</el-form>
<div class="btn-box">
<el-button type="primary">下载事件数据模板</el-button>
<el-button type="primary">上传事件数据</el-button>
</div>
<div class="btn-box">
<el-button type="primary">关闭</el-button>
<!-- <el-button type="primary">上传事件数据</el-button> -->
</div>
</el-dialog>
</template>
<style lang="scss">
.btn-box {
text-align: center;
margin-bottom: 20px;
}
</style>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
// interface Props {
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
value: '',
status: ''
})
const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }]
})
</script>
<template>
<el-dialog
class="connect-form"
title="导入用户数据"
:close-on-click-modal="false"
width="500px"
@update:modelValue="$emit('update:modelValue')"
>
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="142px">
<el-form-item label="请选择所属链接" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
</el-form-item>
<el-form-item label="请选择静态群组">
<el-select v-model="form.id" style="width: 100%"></el-select>
</el-form-item>
</el-form>
<div class="btn-box">
<el-button type="primary">下载用户数据模板</el-button>
<el-button type="primary">上传用户数据</el-button>
</div>
<div class="btn-box">
<el-button type="primary">关闭</el-button>
<!-- <el-button type="primary">上传事件数据</el-button> -->
</div>
</el-dialog>
</template>
<style lang="scss">
.btn-box {
text-align: center;
margin-bottom: 20px;
}
</style>
......@@ -5,8 +5,10 @@ const routes: RouteRecordRaw[] = [
{
path: '/user',
component: Layout,
children: [{ path: '', component: () => import('./views/Index.vue') }]
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: 'eventDetails', component: () => import('./views/EventDetails.vue') }
]
}
]
export { routes }
<script setup lang="ts">
import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue'
import UpdateEventsDialog from '../components/UpdateEventsDialog.vue'
const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置
const listOptions = computed(() => {
return {
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '事件名称', prop: 'id' },
{ label: '链接名称', prop: 'name' },
{ label: '事件发生时间', prop: 'name' },
{ label: '操作', slots: 'table-x', width: 380 }
],
data: [{}, {}]
}
})
// 刷新
function handleRefresh() {
appList?.refetch()
}
// 事件弹窗
const eventsVisible = $ref(false)
</script>
<template>
<AppCard title="用户事件数据">
<div class="event-user_info">
<span>姓名:王小二</span>
<span>id:11111</span>
<span>来源链接:抖音</span>
<span>状态:生效</span>
</div>
</AppCard>
<AppCard>
<AppList v-bind="listOptions" ref="appList">
<template #header-buttons>
<el-button type="primary" :icon="Plus" @click="eventsVisible = true">新建用户事件</el-button>
</template>
<template #table-x>
<el-button type="primary" plain>查看</el-button>
<el-button type="primary" plain>编辑</el-button>
<el-button type="primary" plain>删除</el-button>
</template>
</AppList>
</AppCard>
<!-- 新建更新事件 -->
<UpdateEventsDialog v-model="eventsVisible"></UpdateEventsDialog>
</template>
<style lang="scss">
.event-user_info {
span {
margin-right: 50px;
}
}
</style>
<script setup lang="ts">
import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue'
import UploadEventsDialog from '../components/UploadEventsDialog.vue'
import UploadUserDialog from '../components/UploadUserDialog.vue'
import UpdateDialog from '../components/UpdateDialog.vue'
// import { getMemberMetaDetail } from '../api'
const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置
......@@ -28,6 +32,15 @@ const listOptions = computed(() => {
function handleRefresh() {
appList?.refetch()
}
// 导入事件弹窗
const eventsVisible = $ref(false)
// 导入用户弹窗
const userVisible = $ref(false)
// 新建、更新、查看
const updateVisible = $ref(false)
</script>
<template>
......@@ -49,15 +62,14 @@ function handleRefresh() {
<el-button type="primary" :icon="Upload">导入</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>用户数据</el-dropdown-item>
<el-dropdown-item>用户事件数据</el-dropdown-item>
<el-dropdown-item @click="userVisible = true">用户数据</el-dropdown-item>
<el-dropdown-item @click="eventsVisible = true">用户事件数据</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="danger" plain :icon="Delete">删除</el-button>
</el-space>
</template>
<template #table-x>
<el-button type="primary" plain>画像</el-button>
<el-button type="primary" plain>查看</el-button>
......@@ -67,4 +79,10 @@ function handleRefresh() {
</template>
</AppList>
</AppCard>
<!-- 导入事件弹窗 -->
<UploadEventsDialog v-model="eventsVisible"></UploadEventsDialog>
<!-- 导入用户弹窗 -->
<UploadUserDialog v-model="userVisible"></UploadUserDialog>
<!-- 新建、更新、查看 -->
<UpdateDialog v-model="updateVisible"></UpdateDialog>
</template>
......@@ -26,11 +26,11 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/ezijing.com.pem'))
},
proxy: {
// '/api/lab': {
// target: 'http://test-resource-api.ezijing.com:8001',
// changeOrigin: true,
// rewrite: path => path.replace(/^\/api\/lab/, '')
// },
'/api/experiment': {
target: 'http://localhost-resource-experiment.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/experiment/, '')
},
'/api': 'https://saas-lab.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论