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

元数据,链接管理开发

上级 e89409f6
...@@ -113,7 +113,6 @@ ...@@ -113,7 +113,6 @@
"useArrayMap": true, "useArrayMap": true,
"useArrayReduce": true, "useArrayReduce": true,
"useArraySome": true, "useArraySome": true,
"useArrayUnique": true,
"useAsyncQueue": true, "useAsyncQueue": true,
"useAsyncState": true, "useAsyncState": true,
"useAttrs": true, "useAttrs": true,
...@@ -197,7 +196,6 @@ ...@@ -197,7 +196,6 @@
"useParallax": true, "useParallax": true,
"usePermission": true, "usePermission": true,
"usePointer": true, "usePointer": true,
"usePointerLock": true,
"usePointerSwipe": true, "usePointerSwipe": true,
"usePreferredColorScheme": true, "usePreferredColorScheme": true,
"usePreferredContrast": true, "usePreferredContrast": true,
......
...@@ -114,7 +114,6 @@ declare global { ...@@ -114,7 +114,6 @@ declare global {
const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
const useArraySome: typeof import('@vueuse/core')['useArraySome'] const useArraySome: typeof import('@vueuse/core')['useArraySome']
const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs'] const useAttrs: typeof import('vue')['useAttrs']
...@@ -198,7 +197,6 @@ declare global { ...@@ -198,7 +197,6 @@ declare global {
const useParallax: typeof import('@vueuse/core')['useParallax'] const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission'] const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer'] const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']
......
...@@ -5,6 +5,7 @@ const styleHeight = computed(() => { ...@@ -5,6 +5,7 @@ const styleHeight = computed(() => {
}) })
</script> </script>
<template> <template>
<div class="app-card"> <div class="app-card">
<div class="app-card-hd"> <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"> <script setup lang="ts">
import { Delete, ElemeFilled } from '@element-plus/icons-vue' import { Delete, Edit } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import Icon from '../components/Icon.vue'
import { deleteConnection } from '../api'
const emits = defineEmits<{ const props = defineProps<{ data: { id: string; type_name: string; type: string } }>()
(e: 'update'): void
}>() const router = useRouter()
const emits = defineEmits(['update', 'edit'])
// 删除 // 删除
function handleRemove() { function handleRemove() {
ElMessageBox.confirm('确定要删除该连接吗?', '提示').then(() => { ElMessageBox.confirm('确定要删除该连接吗?', '提示').then(() => {
deleteConnection({ id: props.data?.id }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
emits('update') emits('update')
}) })
})
}
// 去查看
const routerView = function () {
router.push({ path: '/connect/view', query: { id: props.data.id } })
}
const edit = function () {
emits('edit', props.data?.id)
} }
</script> </script>
<template> <template>
<div class="connect-item"> <div class="connect-item">
<div class="connect-item__edit">
<el-icon @click="edit"><Edit /></el-icon>
</div>
<div class="connect-item__remove" @click="handleRemove"> <div class="connect-item__remove" @click="handleRemove">
<el-icon><Delete /></el-icon> <el-icon><Delete /></el-icon>
</div> </div>
<div @click="routerView" style="display: flex; width: 100%; flex-direction: column; align-items: center">
<div class="connect-item__icon"> <div class="connect-item__icon">
<el-icon><ElemeFilled /></el-icon> <Icon class="svg" :name="data?.type"></Icon>
</div>
<p>{{ data?.type_name }}</p>
</div> </div>
<p>连接名称</p>
</div> </div>
</template> </template>
...@@ -42,6 +62,9 @@ function handleRemove() { ...@@ -42,6 +62,9 @@ function handleRemove() {
.connect-item__remove { .connect-item__remove {
display: block; display: block;
} }
.connect-item__edit {
display: block;
}
} }
} }
.connect-item__remove { .connect-item__remove {
...@@ -49,5 +72,13 @@ function handleRemove() { ...@@ -49,5 +72,13 @@ function handleRemove() {
position: absolute; position: absolute;
right: 8px; right: 8px;
top: 8px; top: 8px;
z-index: 999;
}
.connect-item__edit {
display: none;
position: absolute;
left: 8px;
top: 8px;
z-index: 999;
} }
</style> </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[] = [ ...@@ -5,7 +5,10 @@ const routes: RouteRecordRaw[] = [
{ {
path: '/connect', path: '/connect',
component: Layout, 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"> <script setup lang="ts">
import type { DetailsProp } from '../types'
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue' import AppList from '@/components/base/AppList.vue'
import ListItem from '../components/ListItem.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 appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置 // 列表配置
const listOptions = computed(() => { const listOptions = computed(() => {
return { return {
remote: {
httpRequest: getConnectionList,
params: { created_operator: '', type: '' }
},
filters: [ filters: [
{ type: 'input', prop: 'name', placeholder: '请输入连接名称' }, { type: 'input', prop: 'created_operator', placeholder: '请输入创建人姓名' },
{ type: 'input', prop: 'name', placeholder: '请输入创建人姓名' } {
], type: 'select',
columns: [ prop: 'type',
{ label: '序号', type: 'index', width: 60 }, placeholder: '请选择类型',
{ label: '属性ID', prop: 'id' }, options: store.getMapValuesByKey('experiment_connection_type')
{ label: '属性名称', prop: 'name' }, }
{ label: '属性字段类型', prop: 'name' }, ]
{ label: '状态', prop: 'name' },
{ label: '更新人', prop: 'name' },
{ label: '更新时间', prop: 'name' },
{ label: '操作', slots: 'table-x', width: 240 }
],
data: [{}, {}]
} }
}) })
...@@ -29,6 +34,22 @@ const listOptions = computed(() => { ...@@ -29,6 +34,22 @@ const listOptions = computed(() => {
function handleRefresh() { function handleRefresh() {
appList?.refetch() 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> </script>
<template> <template>
...@@ -36,9 +57,14 @@ function handleRefresh() { ...@@ -36,9 +57,14 @@ function handleRefresh() {
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #body="{ data }"> <template #body="{ data }">
<div class="connect-list"> <div class="connect-list">
<ListItem v-for="item in data" :key="item.id" @update="handleRefresh"></ListItem> <ListItem
@edit="editConnect"
<div class="connect-item"> :data="item"
v-for="item in data"
:key="item.id"
@update="handleRefresh"
></ListItem>
<div class="connect-item" @click="createConnect">
<div class="connect-add-button"> <div class="connect-add-button">
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>
<span>新建连接</span> <span>新建连接</span>
...@@ -48,6 +74,8 @@ function handleRefresh() { ...@@ -48,6 +74,8 @@ function handleRefresh() {
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<!-- 新建链接 -->
<FormDialog :data="formData" v-model="formVisible" v-if="formVisible" @update="handleRefresh" />
</template> </template>
<style lang="scss"> <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"> <script setup lang="ts">
import type { EventProp } from '../types' import type { EventProp, ConnectionOptionProp } from '../types'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { createMetaEvent, updateMetaEvent } from '../api'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
interface Props { interface Props {
data?: EventProp data?: EventProp
option: ConnectionOptionProp[]
} }
const props = defineProps<Props>() const props = defineProps<Props>()
...@@ -21,17 +26,19 @@ const title = $computed(() => { ...@@ -21,17 +26,19 @@ const title = $computed(() => {
}) })
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ const form = reactive(
id: '', props.data || {
name: '', name: '',
type: '', english_name: '',
status: '' experiment_connection_id: '',
}) status: '0'
}
)
const rules = ref<FormRules>({ const rules = ref<FormRules>({
id: [{ required: true, message: '请输入事件ID' }], name: [{ required: true, message: '请输入' }],
name: [{ required: true, message: '请输入事件名称' }], english_name: [{ required: true, message: '请输入' }],
type: [{ required: true, message: '请选择属性字段类型' }] experiment_connection_id: [{ required: true, message: '请选择' }]
}) })
// 提交 // 提交
...@@ -43,32 +50,46 @@ function handleSubmit() { ...@@ -43,32 +50,46 @@ function handleSubmit() {
// 新建 // 新建
function handleCreate() { function handleCreate() {
createMetaEvent(form).then(res => {
ElMessage({ message: '创建成功', type: 'success' }) ElMessage({ message: '创建成功', type: 'success' })
emit('update') emit('update')
emit('update:modelValue', false) emit('update:modelValue', false)
})
} }
// 修改 // 修改
function handleUpdate() { function handleUpdate() {
updateMetaEvent(form).then(res => {
ElMessage({ message: '修改成功', type: 'success' }) ElMessage({ message: '修改成功', type: 'success' })
emit('update') emit('update')
emit('update:modelValue', false) emit('update:modelValue', false)
})
} }
</script> </script>
<template> <template>
<el-dialog :title="title" :close-on-click-modal="false" width="600px" @update:modelValue="$emit('update:modelValue')"> <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 ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="140px">
<el-form-item label="事件ID" prop="id"> <el-form-item label="事件ID" prop="id" v-if="isUpdate">
<el-input v-model="form.id" /> <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>
<el-form-item label="事件名称" prop="name"> <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>
<el-form-item label="所属连接" prop="type"> <el-form-item label="所属连接" prop="experiment_connection_id">
<el-select v-model="form.type" style="width: 100%"></el-select> <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>
<el-form-item label="状态" prop="status"> <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-item>
</el-form> </el-form>
<template #footer> <template #footer>
......
...@@ -8,18 +8,21 @@ defineProps<Props>() ...@@ -8,18 +8,21 @@ defineProps<Props>()
<template> <template>
<el-dialog title="查看事件属性" :close-on-click-modal="false" width="600px"> <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"> <el-form-item label="事件ID">
{{ data.id }} {{ data.id }}
</el-form-item> </el-form-item>
<el-form-item label="事件英文名称">
{{ data.english_name }}
</el-form-item>
<el-form-item label="事件名称"> <el-form-item label="事件名称">
{{ data.id }} {{ data.name }}
</el-form-item> </el-form-item>
<el-form-item label="所属连接"> <el-form-item label="所属连接">
{{ data.id }} {{ data.connection_name }}
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="状态">
{{ data.id }} {{ data.status_name }}
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
......
export interface EventProp { export interface EventProp {
id: string id: string
name: 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"> <script setup lang="ts">
import type { EventProp } from '../types' import type { EventProp, ConnectionOptionProp } from '../types'
import { Plus } from '@element-plus/icons-vue' 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 AppList from '@/components/base/AppList.vue'
import { getMetaEvent, getConnectionsList, deleteMetaEvent } from '../api'
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue')) const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue')) const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue'))
const FieldDialog = defineAsyncComponent(() => import('../components/FieldDialog.vue'))
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 所属链接选项
let experimentConnectionOptions = $ref<ConnectionOptionProp[]>()
getConnectionsList().then(res => {
experimentConnectionOptions = res.data
})
// 列表配置 // 列表配置
const listOptions = computed(() => { const listOptions = computed(() => {
return { return {
remote: {
httpRequest: getMetaEvent,
params: { name: '', status: '', experiment_connection_id: '' }
},
filters: [ filters: [
{ type: 'input', prop: 'name', placeholder: '请输入事件名称' }, { type: 'input', prop: 'name', placeholder: '请输入事件名称' },
{ {
type: 'select', type: 'select',
prop: 'type', prop: 'experiment_connection_id',
placeholder: '请选择事件所属连接' placeholder: '请选择事件所属连接',
options: experimentConnectionOptions,
labelKey: 'type_name',
valueKey: 'id'
},
{
type: 'select',
prop: 'status',
placeholder: '请选择生效状态',
options: [
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
} }
], ],
columns: [ columns: [
{ label: '序号', type: 'index', width: 60 }, { label: '序号', type: 'index', width: 60 },
{ label: '事件ID', prop: 'id' }, { label: '事件ID', prop: 'id' },
{ label: '事件英文名称', prop: 'english_name' },
{ label: '事件名称', prop: 'name' }, { label: '事件名称', prop: 'name' },
{ label: '所属连接', prop: 'name' }, { label: '所属连接', prop: 'connection_name' },
{ label: '属性字段数量', prop: 'name' }, { label: '属性字段数量', prop: 'attributes_count' },
{ label: '状态', prop: 'name' }, { label: '状态', prop: 'status_name' },
{ label: '更新人', prop: 'name' }, { label: '更新人', prop: 'updated_operator_name' },
{ label: '更新时间', prop: 'name' }, { label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 300 } { label: '操作', slots: 'table-x', width: 300 }
], ]
data: [{ id: 1 }, { id: 2 }]
} }
}) })
...@@ -63,13 +88,25 @@ function handleView(row: EventProp) { ...@@ -63,13 +88,25 @@ function handleView(row: EventProp) {
// 删除 // 删除
function handleRemove(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> </script>
<template> <template>
<AppCard> <AppCard>
<AppList v-bind="listOptions"> <AppList v-bind="listOptions" ref="appList">
<template #header-buttons> <template #header-buttons>
<el-space> <el-space>
<el-button type="primary" :icon="Plus" @click="handleAdd">新建</el-button> <el-button type="primary" :icon="Plus" @click="handleAdd">新建</el-button>
...@@ -79,12 +116,19 @@ function handleRemove(row: EventProp) { ...@@ -79,12 +116,19 @@ function handleRemove(row: EventProp) {
<el-button type="primary" plain @click="handleView(row)">查看</el-button> <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="handleUpdate(row)">编辑</el-button>
<el-button type="primary" plain @click="handleRemove(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> </template>
</AppList> </AppList>
</AppCard> </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" /> <ViewDialog v-model="viewVisible" :data="currentRow" v-if="viewVisible && currentRow" />
<FieldDialog v-model="fieldVisible" :data="currentRow" v-if="fieldVisible && currentRow"></FieldDialog>
</template> </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 @@ ...@@ -2,6 +2,10 @@
import type { UserProp } from '../types' import type { UserProp } from '../types'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { useMapStore } from '@/stores/map'
import { createMemberMeta, updateMemberMeta } from '../api'
const store = useMapStore()
interface Props { interface Props {
data?: UserProp data?: UserProp
...@@ -21,19 +25,22 @@ const title = $computed(() => { ...@@ -21,19 +25,22 @@ const title = $computed(() => {
}) })
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ const form = reactive(
id: '', props.data || {
name: '', name: '',
english_name: '',
type: '', type: '',
value: '', format: '',
status: '' status: '0'
}) }
)
const rules = ref<FormRules>({ const rules = ref<FormRules>({
id: [{ required: true, message: '请输入属性ID' }], name: [{ required: true, message: '请输入' }],
name: [{ required: true, message: '请输入属性名称' }], english_name: [{ required: true, message: '请输入' }],
type: [{ required: true, message: '请选择属性字段类型' }], type: [{ required: true, message: '请选择' }],
value: [{ required: true, message: '请输入属性ID' }] format: [{ required: true, message: '请输入' }],
status: [{ required: true, message: '请选择' }]
}) })
// 提交 // 提交
...@@ -45,35 +52,73 @@ function handleSubmit() { ...@@ -45,35 +52,73 @@ function handleSubmit() {
// 新建 // 新建
function handleCreate() { function handleCreate() {
createMemberMeta(form).then(res => {
ElMessage({ message: '创建成功', type: 'success' }) ElMessage({ message: '创建成功', type: 'success' })
emit('update') emit('update')
emit('update:modelValue', false) emit('update:modelValue', false)
})
} }
// 修改 // 修改
function handleUpdate() { function handleUpdate() {
updateMemberMeta(form).then(res => {
ElMessage({ message: '修改成功', type: 'success' }) ElMessage({ message: '修改成功', type: 'success' })
emit('update') emit('update')
emit('update:modelValue', false) emit('update:modelValue', false)
})
} }
// 属性字段类型
const experimentAttributeOptions = $ref(store.getMapValuesByKey('experiment_attribute_type'))
// 属性字段类型选择后->格式的placeholder改变
const formatPlaceholder = computed(() => {
return form.type === '1' ? '请输入字符串长度' : '请输入长度'
})
</script> </script>
<template> <template>
<el-dialog :title="title" :close-on-click-modal="false" width="600px" @update:modelValue="$emit('update:modelValue')"> <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 ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="122px">
<el-form-item label="属性ID" prop="id"> <el-form-item label="属性ID" v-if="isUpdate">
<el-input v-model="form.id" /> {{ 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>
<el-form-item label="属性名称" prop="name"> <el-form-item label="属性名称" prop="english_name">
<el-input v-model="form.name" /> <el-input v-model="form.english_name" placeholder="请输入" />
</el-form-item> </el-form-item>
<el-form-item label="属性字段类型" prop="type"> <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>
<el-form-item label="属性字段格式" prop="type"> <el-form-item label="属性字段格式" prop="format" v-if="form.type !== ''">
<el-input v-model="form.value" /> <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>
<el-form-item label="状态" prop="status"> <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-item>
</el-form> </el-form>
<template #footer> <template #footer>
......
...@@ -12,17 +12,20 @@ defineProps<Props>() ...@@ -12,17 +12,20 @@ defineProps<Props>()
<el-form-item label="属性ID"> <el-form-item label="属性ID">
{{ data.id }} {{ data.id }}
</el-form-item> </el-form-item>
<el-form-item label="属性英文名称">
{{ data.english_name }}
</el-form-item>
<el-form-item label="属性名称"> <el-form-item label="属性名称">
{{ data.id }} {{ data.name }}
</el-form-item> </el-form-item>
<el-form-item label="属性字段类型"> <el-form-item label="属性字段类型">
{{ data.id }} {{ data.type_name }}
</el-form-item> </el-form-item>
<el-form-item label="属性字段格式"> <el-form-item label="属性字段格式">
{{ data.id }} {{ data.format }}
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="状态">
{{ data.id }} {{ data.status_name }}
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
......
export interface UserProp { export interface UserProp {
id: string id: string
name: string name: string
english_name: string
type: string
format: string
status: string
type_name: string
status_name: string
} }
<script setup lang="ts"> <script setup lang="ts">
import type { UserProp } from '../types' import type { UserProp } from '../types'
import { Plus } from '@element-plus/icons-vue' 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 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 FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue')) const ViewDialog = defineAsyncComponent(() => import('../components/ViewDialog.vue'))
...@@ -11,25 +15,40 @@ const appList = $ref<InstanceType<typeof AppList> | null>(null) ...@@ -11,25 +15,40 @@ const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置 // 列表配置
const listOptions = computed(() => { const listOptions = computed(() => {
return { return {
remote: {
httpRequest: getMemberMeta,
params: { name: '', status: '', type: '' }
},
filters: [ filters: [
{ type: 'input', prop: 'name', placeholder: '请输入用户属性名称' }, { type: 'input', prop: 'name', placeholder: '请输入用户属性名称' },
{ {
type: 'select', type: 'select',
prop: 'experiment_id', prop: 'type',
placeholder: '请选择属性字段类型' placeholder: '请选择属性字段类型',
options: store.getMapValuesByKey('experiment_attribute_type')
},
{
type: 'select',
prop: 'status',
placeholder: '请选择生效状态',
options: [
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
} }
], ],
columns: [ columns: [
{ label: '序号', type: 'index', width: 60 }, { label: '序号', type: 'index', width: 60 },
{ label: '属性ID', prop: 'id' }, { label: '属性ID', prop: 'id' },
{ label: '属性名称', prop: 'name' }, { label: '属性名称', prop: 'name' },
{ label: '属性字段类型', prop: 'name' }, { label: '属性英文名称', prop: 'english_name' },
{ label: '状态', prop: 'name' }, { label: '属性字段类型', prop: 'type_name' },
{ label: '更新人', prop: 'name' }, { label: '属性字段格式', prop: 'format' },
{ label: '更新时间', prop: 'name' }, { label: '状态', prop: 'status_name' },
{ label: '更新人', prop: 'updated_operator_name' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 240 } { label: '操作', slots: 'table-x', width: 240 }
], ]
data: [{ id: 1 }, { id: 2 }]
} }
}) })
...@@ -62,7 +81,12 @@ function handleView(row: UserProp) { ...@@ -62,7 +81,12 @@ function handleView(row: UserProp) {
// 删除 // 删除
function handleRemove(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>
......
<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[] = [ ...@@ -5,8 +5,10 @@ const routes: RouteRecordRaw[] = [
{ {
path: '/user', path: '/user',
component: Layout, 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 } 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"> <script setup lang="ts">
import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue' import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.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) const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置 // 列表配置
...@@ -28,6 +32,15 @@ const listOptions = computed(() => { ...@@ -28,6 +32,15 @@ const listOptions = computed(() => {
function handleRefresh() { function handleRefresh() {
appList?.refetch() appList?.refetch()
} }
// 导入事件弹窗
const eventsVisible = $ref(false)
// 导入用户弹窗
const userVisible = $ref(false)
// 新建、更新、查看
const updateVisible = $ref(false)
</script> </script>
<template> <template>
...@@ -49,15 +62,14 @@ function handleRefresh() { ...@@ -49,15 +62,14 @@ function handleRefresh() {
<el-button type="primary" :icon="Upload">导入</el-button> <el-button type="primary" :icon="Upload">导入</el-button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item>用户数据</el-dropdown-item> <el-dropdown-item @click="userVisible = true">用户数据</el-dropdown-item>
<el-dropdown-item>用户事件数据</el-dropdown-item> <el-dropdown-item @click="eventsVisible = true">用户事件数据</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
<el-button type="danger" plain :icon="Delete">删除</el-button> <el-button type="danger" plain :icon="Delete">删除</el-button>
</el-space> </el-space>
</template> </template>
<template #table-x> <template #table-x>
<el-button type="primary" plain>画像</el-button> <el-button type="primary" plain>画像</el-button>
<el-button type="primary" plain>查看</el-button> <el-button type="primary" plain>查看</el-button>
...@@ -67,4 +79,10 @@ function handleRefresh() { ...@@ -67,4 +79,10 @@ function handleRefresh() {
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<!-- 导入事件弹窗 -->
<UploadEventsDialog v-model="eventsVisible"></UploadEventsDialog>
<!-- 导入用户弹窗 -->
<UploadUserDialog v-model="userVisible"></UploadUserDialog>
<!-- 新建、更新、查看 -->
<UpdateDialog v-model="updateVisible"></UpdateDialog>
</template> </template>
...@@ -26,11 +26,11 @@ export default defineConfig(({ mode }) => ({ ...@@ -26,11 +26,11 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/ezijing.com.pem')) cert: fs.readFileSync(path.join(__dirname, './https/ezijing.com.pem'))
}, },
proxy: { proxy: {
// '/api/lab': { '/api/experiment': {
// target: 'http://test-resource-api.ezijing.com:8001', target: 'http://localhost-resource-experiment.ezijing.com',
// changeOrigin: true, changeOrigin: true,
// rewrite: path => path.replace(/^\/api\/lab/, '') rewrite: path => path.replace(/^\/api\/experiment/, '')
// }, },
'/api': 'https://saas-lab.ezijing.com' '/api': 'https://saas-lab.ezijing.com'
} }
}, },
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论