提交 90d00e72 authored 作者: lihuihui's avatar lihuihui

update

上级 fa868381
...@@ -202,7 +202,6 @@ ...@@ -202,7 +202,6 @@
"usePreferredDark": true, "usePreferredDark": true,
"usePreferredLanguages": true, "usePreferredLanguages": true,
"usePreferredReducedMotion": true, "usePreferredReducedMotion": true,
"usePrevious": true,
"useRafFn": true, "useRafFn": true,
"useRefHistory": true, "useRefHistory": true,
"useResizeObserver": true, "useResizeObserver": true,
......
...@@ -203,7 +203,6 @@ declare global { ...@@ -203,7 +203,6 @@ declare global {
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const useRafFn: typeof import('@vueuse/core')['useRafFn'] const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
......
...@@ -123,7 +123,7 @@ function handleUpdate() { ...@@ -123,7 +123,7 @@ function handleUpdate() {
v-model="scope.row.format" v-model="scope.row.format"
placeholder="请选择" placeholder="请选择"
> >
<el-option label="yyyy-mm-dd" value="yyyy-mm-dd"></el-option> <el-option v-if="scope.row.type !== '5'" label="yyyy-mm-dd" value="yyyy-mm-dd"></el-option>
<el-option <el-option
v-if="scope.row.type !== '4'" v-if="scope.row.type !== '4'"
label="yyyy-mm-dd hh:mm:ss" label="yyyy-mm-dd hh:mm:ss"
......
import httpRequest from '@/utils/axios'
// 人员列表
export function getMemberList(params: { name?: string; id?: string; mobile?: string; status?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/member/list', { params })
}
// 链接列表
export function getMemberConnectionsList() {
return httpRequest.get('/api/experiment/v1/experiment/member/connections')
}
// 用户属性
export function getMemberFieldsList() {
return httpRequest.get('/api/experiment/v1/experiment/member/member-fields')
}
// 新建用户
export function createMember(data: { name: string; status: string; experiment_connection_id: string; gender: string; mobile: string; fields: string }) {
return httpRequest.post('/api/experiment/v1/experiment/member/create', data)
}
// 删除用户
export function deleteMember(data: { ids: string; }) {
return httpRequest.post('/api/experiment/v1/experiment/member/delete', data)
}
// 新建用户
export function updateMember(data: { id?: string; name: string; status: string; experiment_connection_id: string; gender: string; mobile: string; fields: string }) {
return httpRequest.post('/api/experiment/v1/experiment/member/update', data)
}
// 单人员事件列表
export function getMemberEventList(params: { id: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/experiment/v1/experiment/member/member-events', { params })
}
// 事件列表
export function getEventList() {
return httpRequest.get('/api/experiment/v1/experiment/member/events')
}
// 新建事件
export function createEvent(data: { experiment_member_id: string; experiment_meta_event_id: string; fields: any }) {
return httpRequest.post('/api/experiment/v1/experiment/member/event-create', data)
}
// 更新事件
export function updateEvent(data: { id: string; fields: any }) {
return httpRequest.post('/api/experiment/v1/experiment/member/event-update', data)
}
// 删除事件
export function deleteEvent(data: { id: string }) {
return httpRequest.post('/api/experiment/v1/experiment/member/event-delete', data)
}
// 用户画像
export function getMemberImage(params: { id: string }) {
return httpRequest.get('/api/experiment/v1/experiment/member/member-image', { params })
}
// 导入事件
export function importEvent(data: { event_id: string; file: any }) {
return httpRequest.post('/api/experiment/v1/experiment/member/event-upload', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
// 导入用户
export function importMember(data: { groups_id?: string; connection_id: string; file: any }) {
return httpRequest.post('/api/experiment/v1/experiment/member/member-upload', data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
// 用户画像
export function getMemberGroups() {
return httpRequest.get('/api/experiment/v1/experiment/member/groups')
}
\ No newline at end of file
<script setup lang="ts">
withDefaults(defineProps<{ name: string; color?: string; w?: string; h?: string }>(), {
color: '#000000',
w: '30',
h: '30'
})
</script>
<template>
<div>
<svg
v-if="name === '1'"
t="1675654500635"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="10798"
:width="w"
:height="h"
>
<path
d="M664.250054 368.541681c10.015098 0 19.892049 0.732687 29.67281 1.795902-26.647917-122.810047-159.358451-214.077703-310.826188-214.077703-169.353083 0-308.085774 114.232694-308.085774 259.274068 0 83.708494 46.165436 152.460344 123.281791 205.78483l-30.80868 91.730191 107.688651-53.455469c38.558178 7.53665 69.459978 15.308661 107.924012 15.308661 9.66308 0 19.230993-0.470721 28.752858-1.225921-6.025227-20.36584-9.521864-41.723264-9.521864-63.862493C402.328693 476.632491 517.908058 368.541681 664.250054 368.541681zM498.62897 285.87389c23.200398 0 38.557154 15.120372 38.557154 38.061874 0 22.846334-15.356756 38.156018-38.557154 38.156018-23.107277 0-46.260603-15.309684-46.260603-38.156018C452.368366 300.994262 475.522716 285.87389 498.62897 285.87389zM283.016307 362.090758c-23.107277 0-46.402843-15.309684-46.402843-38.156018 0-22.941502 23.295566-38.061874 46.402843-38.061874 23.081695 0 38.46301 15.120372 38.46301 38.061874C321.479317 346.782098 306.098002 362.090758 283.016307 362.090758zM945.448458 606.151333c0-121.888048-123.258255-221.236753-261.683954-221.236753-146.57838 0-262.015505 99.348706-262.015505 221.236753 0 122.06508 115.437126 221.200938 262.015505 221.200938 30.66644 0 61.617359-7.609305 92.423993-15.262612l84.513836 45.786813-23.178909-76.17082C899.379213 735.776599 945.448458 674.90216 945.448458 606.151333zM598.803483 567.994292c-15.332197 0-30.807656-15.096836-30.807656-30.501688 0-15.190981 15.47546-30.477129 30.807656-30.477129 23.295566 0 38.558178 15.286148 38.558178 30.477129C637.361661 552.897456 622.099049 567.994292 598.803483 567.994292zM768.25071 567.994292c-15.213493 0-30.594809-15.096836-30.594809-30.501688 0-15.190981 15.381315-30.477129 30.594809-30.477129 23.107277 0 38.558178 15.286148 38.558178 30.477129C806.808888 552.897456 791.357987 567.994292 768.25071 567.994292z"
:fill="color"
p-id="10799"
></path>
</svg>
<svg
v-if="name === '2'"
t="1675654004777"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="8908"
:width="w"
:height="h"
>
<path
d="M903.282484 382.828702c-2.999866 10.899512-6.899691 21.499038-11.699476 31.698581h0.099995l-0.599973 1.299942c-34.098474 76.596571-123.194485 226.989839-123.194485 226.989839l-0.399982-0.999955-25.998836 47.597869h125.394386L627.294839 1024l54.397565-227.589812h-98.795578l34.298465-150.493263c-27.798756 6.999687-60.497292 16.699252-99.395551 29.798666 0 0-52.49765 32.298554-151.393222-62.197216 0 0-66.697014-61.597243-27.998747-77.096548 16.399266-6.499709 79.796428-14.799337 129.694194-21.999015 67.296987-9.59957 108.79513-14.699342 108.79513-14.699342s-207.690703 3.299852-256.988496-4.899781c-49.297793-8.099637-111.695-94.49577-125.0944-170.392372 0 0-20.599078-41.698133 44.198021-21.999016 64.897095 19.699118 333.385076 76.796562 333.385076 76.796563S223.312923 266.933891 200.113962 239.535117 131.717024 89.741823 137.616759 14.645184c0 0 2.599884-18.799158 20.899065-13.799382 0 0 258.188442 123.994449 434.680541 191.691419C769.688464 260.434182 923.081598 295.032633 903.282484 382.828702z"
:fill="color"
p-id="8909"
></path>
</svg>
<svg
v-if="name === '3'"
t="1675654843770"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="14477"
:width="w"
:height="h"
>
<path
d="M927.100379 675.459361c-1.321995-6.607974-9.439963-4.908981-14.915942-4.90898-32.096875 0-64.193749-2.265991-95.913626 0.377998-61.739759 5.09798-108.185577-26.243897-151.799407-62.683755-24.545904-20.39092-45.879821-44.558826-71.369721-64.00575-42.292835-32.474873-85.717665-62.305757-141.793446-64.759747-15.29294-0.566998-33.22987-1.321995-38.516849-21.524916a124.612513 124.612513 0 0 1-4.530983-28.697888c-0.754997-57.586775-4.530982-114.794552-4.153984-172.380326a397.890446 397.890446 0 0 0-20.012921-138.584459 195.037238 195.037238 0 0 0-49.089809-80.809684C298.563834 4.064984 254.571006-2.353991 207.748188 0.666997a41.631837 41.631837 0 0 0-33.04087 20.389921c-13.216948 17.181933 15.669939 47.768813-36.439858 47.390815-5.475979 0-33.796868-1.320995-41.537838 22.089913-5.285979 15.859938 82.697677 10.006961 100.256609 16.237937a11.913953 11.913953 0 0 0 5.09798-0.376999 94.591631 94.591631 0 0 0 67.780735 30.963879 29.132886 29.132886 0 0 1 28.509888 24.166906 411.692392 411.692392 0 0 1 11.705955 71.179722 447.471252 447.471252 0 0 1-10.19496 155.199394 302.524818 302.524818 0 0 1-33.985868 65.326745 268.70895 268.70895 0 0 0-36.439857 164.828356 191.97925 191.97925 0 0 0 47.201815 108.563576c21.901914 24.355905 52.110796 39.837844 72.124719 65.893742 26.621896 34.928864 52.487795 70.801723 81.186682 104.031594a155.879391 155.879391 0 0 1-1.509994 83.263675 29.887883 29.887883 0 0 1-26.244897 23.411908c-16.047937 1.321995-30.019883 11.139956-46.257819 13.216949 23.789907 2.264991 47.579814 1.320995 71.179721 2.45399 21.524916 1.132996 42.859833-11.705954 64.572748-0.943996a5.928977 5.928977 0 0 0 2.264991-0.754997c-4.530982-3.775985-8.306968-7.551971-12.837949-10.761958a54.319788 54.319788 0 0 1-22.656912-60.039766c2.45399-11.139956 3.586986-22.657911 5.09698-33.985867a419.150363 419.150363 0 0 0 142.549443 17.747931 200.135218 200.135218 0 0 1 7.173972 42.292834 31.359878 31.359878 0 0 1-22.655911 34.362866c-14.915942 4.908981-29.831883 10.005961-45.502822 15.103941a16.218937 16.218937 0 0 0 4.90998 2.076992c20.012922-0.188999 40.025844-0.754997 60.039766-0.565998a35.72186 35.72186 0 0 0 31.907875-12.64995c4.719982-6.608974 9.817962-6.419975 14.726943 0.565997a29.415885 29.415885 0 0 0 30.775879 9.629963 35.060863 35.060863 0 0 0-12.461951-16.615935 65.534744 65.534744 0 0 1-19.635923-27.565893c-3.963985-20.201921-8.117968-40.403842-12.271952-60.795762a92.363639 92.363639 0 0 0 56.830778-30.77488 357.070605 357.070605 0 0 0 59.473767-68.725731 127.500502 127.500502 0 0 1 44.369827-41.914837 228.248108 228.248108 0 0 0 68.347733-61.36176 69.593728 69.593728 0 0 1 42.669833-29.831883c4.531982-0.565998 13.782946 0 12.272953-7.92997zM239.090066 43.52483a9.892961 9.892961 0 0 1-9.062965-12.083953 9.779962 9.779962 0 0 1 9.251964-10.383959 10.081961 10.081961 0 0 1 10.38396 11.327955 10.34696 10.34696 0 0 1-10.572959 11.139957z"
:fill="color"
p-id="14478"
></path>
</svg>
<svg
v-if="name === '4'"
t="1675654964339"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="16272"
:width="w"
:height="h"
>
<path
d="M559.22 180.986667a21.333333 21.333333 0 0 1-19.14-11.893334L512 112.206667l-28.08 56.886666a21.333333 21.333333 0 0 1-38.26-18.88L492.866667 54.56a21.333333 21.333333 0 0 1 38.266666 0l47.206667 95.653333a21.333333 21.333333 0 0 1-19.12 30.773334zM784.233333 377.333333a21.333333 21.333333 0 0 0-18.04-24.18l-94.46-13.706666-42.246666-85.593334a21.333333 21.333333 0 1 0-38.26 18.88l47.206666 95.653334a21.333333 21.333333 0 0 0 16.06 11.666666l105.56 15.333334a21.3 21.3 0 0 0 24.18-18.053334z m137.333334 118.62l76.386666-74.453333a21.333333 21.333333 0 0 0-11.826666-36.386667l-105.553334-15.333333a21.333333 21.333333 0 1 0-6.14 42.22l62.786667 9.126667-45.433333 44.28a21.333333 21.333333 0 0 0 29.773333 30.593333z m-152.393334 266a21.333333 21.333333 0 0 0 17.42-24.666666l-16.14-94.073334L838.8 576.666667a21.333333 21.333333 0 1 0-29.78-30.553334L732.666667 620.546667a21.333333 21.333333 0 0 0-6.14 18.886666l18 105.126667a21.333333 21.333333 0 0 0 21 17.733333 21.066667 21.066667 0 0 0 3.64-0.293333z m46.5 215.28a21.333333 21.333333 0 0 0 8.486667-20.866666l-18-105.133334a21.333333 21.333333 0 1 0-42.046667 7.213334l10.72 62.526666-56.166666-29.493333a21.333333 21.333333 0 0 0-19.853334 37.766667l94.413334 49.633333a21.333333 21.333333 0 0 0 22.466666-1.62zM625.333333 866.506667a21.333333 21.333333 0 0 0-8.96-28.806667l-94.413333-49.64a21.333333 21.333333 0 0 0-19.853333 0l-94.413334 49.64a21.333333 21.333333 0 1 0 19.853334 37.766667L512 831.046667l84.486667 44.42a21.333333 21.333333 0 0 0 28.846666-8.96z m-394.533333 112.373333l94.413333-49.633333a21.333333 21.333333 0 0 0-19.88-37.766667l-56.153333 29.52 10.72-62.526667a21.333333 21.333333 0 1 0-42.046667-7.213333l-18.033333 105.133333a21.333333 21.333333 0 0 0 30.953333 22.486667z m48.666667-234.32l18.033333-105.126667a21.333333 21.333333 0 0 0-6.166667-18.886666L214.98 546.093333A21.333333 21.333333 0 0 0 185.2 576.666667l68.353333 66.626666L237.413333 737.333333a21.333333 21.333333 0 0 0 17.42 24.666667 21.066667 21.066667 0 0 0 3.633334 0.313333 21.333333 21.333333 0 0 0 21-17.753333zM132.606667 495.586667a21.333333 21.333333 0 0 0-0.386667-30.166667l-45.433333-44.28L149.573333 412a21.333333 21.333333 0 0 0-6.14-42.22l-105.553333 15.333333a21.333333 21.333333 0 0 0-11.826667 36.386667L102.433333 496a21.333333 21.333333 0 0 0 30.173334-0.386667z m131.333333-100.193334l105.56-15.333333a21.333333 21.333333 0 0 0 16.06-11.666667l47.213333-95.66a21.333333 21.333333 0 1 0-38.26-18.88L352.266667 339.446667l-94.453334 13.726666a21.333333 21.333333 0 1 0 6.133334 42.22z"
:fill="color"
p-id="16273"
></path>
</svg>
<svg
v-if="name === '5'"
t="1675655043899"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="17225"
:width="w"
:height="h"
>
<path
d="M832 192v640H192V192h640m32-64H160c-17.6 0-32 14.4-32 32v704c0 17.6 14.4 32 32 32h704c17.6 0 32-14.4 32-32V160c0-17.6-14.4-32-32-32zM768 640H576v64h192v-64zM512 512H256v192h256V512z m256 0H576v64h192v-64z m0-192H256v128h512V320z"
:fill="color"
p-id="17226"
></path>
</svg>
<svg
v-if="name === '6'"
t="1675650497733"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="8488"
:width="w"
:height="h"
>
<path
d="M937.4 423.9c-84 0-165.7-27.3-232.9-77.8v352.3c0 179.9-138.6 325.6-309.6 325.6S85.3 878.3 85.3 698.4c0-179.9 138.6-325.6 309.6-325.6 17.1 0 33.7 1.5 49.9 4.3v186.6c-15.5-6.1-32-9.2-48.6-9.2-76.3 0-138.2 65-138.2 145.3 0 80.2 61.9 145.3 138.2 145.3 76.2 0 138.1-65.1 138.1-145.3V0H707c0 134.5 103.7 243.5 231.6 243.5v180.3l-1.2 0.1"
:fill="color"
p-id="8489"
></path>
</svg>
<svg
v-if="name === '7'"
t="1675655112200"
class="icon"
viewBox="0 0 1138 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="18176"
:width="w"
:height="h"
>
<path
d="M914.432 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM656.384 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM522.24 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM359.424 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM778.24 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM778.24 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z"
:fill="color"
p-id="18177"
></path>
</svg>
<svg
v-if="name === '8'"
t="1675654563546"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="12785"
:width="w"
:height="h"
>
<path
d="M288 64l-128 0C106.88 64 64 106.88 64 160l0 512C64 725.12 106.88 768 160 768l128 0C341.12 768 384 810.88 384 864 384 881.92 398.08 896 416 896S448 881.92 448 864l0-640C448 135.68 376.32 64 288 64zM800 64l-128 0C583.68 64 512 135.68 512 224l0 640C512 881.92 526.08 896 544 896 561.92 896 576 881.92 576 864c0-53.12 42.88-96 96-96l128 0c53.12 0 96-42.88 96-96l0-512C896 106.88 853.12 64 800 64z"
:fill="color"
p-id="12786"
></path>
</svg>
<svg
v-if="name === '9'"
t="1675655183921"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="19990"
:width="w"
:height="h"
>
<path
d="M149.6 171.8h691.9c47.2 0 85.9 37.7 86.5 83.9L495.7 493 63.5 256c0.4-46.4 38.8-84.2 86.1-84.2z m-86.1 175l-0.4 419.6c0 46.7 38.9 84.9 86.5 84.9h691.9c47.6 0 86.5-38.2 86.5-84.9V346.6L505.9 572.8c-6.5 3.5-14.3 3.5-20.7 0l-421.7-226z"
:fill="color"
p-id="19991"
></path>
</svg>
<svg
v-if="name === '10'"
t="1675655232589"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="20965"
:width="w"
:height="h"
>
<path
d="M850.727 116.266H171.593c-72.728 0-108.108 35.866-108.108 107.608v430.43c0 71.746 33.193 105.653 104.108 105.653h104.112l-12.808 109.564a35.679 35.679 0 0 0 19.029 31.562 35.753 35.753 0 0 0 17.005 4.307c6.988 0 13.982-2.014 19.962-6.028L521.57 759.957h333.156c72.081 0 104.109-33.906 104.109-105.653v-430.43c0-71.742-36.033-107.608-108.108-107.608zM303.159 490.172c-28.658 0-51.949-23.3-51.949-51.873 0-28.57 23.292-51.968 51.949-51.968 28.655 0 51.95 23.304 51.95 51.968-0.005 28.668-23.392 51.873-51.95 51.873z m207.887 0c-28.809 0-52.214-23.3-52.214-51.873 0-28.57 23.41-51.968 52.214-51.968 28.806 0 52.211 23.304 52.211 51.968 0.001 28.668-23.507 51.873-52.21 51.873z m208.21 0c-28.81 0-52.133-23.3-52.133-51.873 0-28.57 23.323-51.968 52.132-51.968 28.797 0 52.207 23.304 52.207 51.968 0 28.668-23.405 51.873-52.207 51.873z m0 0"
:fill="color"
p-id="20966"
></path>
</svg>
<svg
v-if="name === '11'"
t="1675660021839"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="24527"
:width="w"
:height="h"
>
<path
d="M512 0C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z m-32 769V353c0-17.7 14.3-32 32-32s32 14.3 32 32v416c0 8.8-3.6 16.8-9.4 22.6-5.8 5.8-13.8 9.4-22.6 9.4-17.7 0-32-14.3-32-32z m64-543.5c0 8.8-3.6 16.8-9.4 22.6-5.8 5.8-13.8 9.4-22.6 9.4-17.7 0-32-14.3-32-32v-1c0-17.7 14.3-32 32-32s32 14.3 32 32v1z"
:fill="color"
p-id="24528"
></path>
</svg>
<svg
v-if="name === '12'"
t="1675659896272"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="21924"
:width="w"
:height="h"
>
<path
d="M911.275224 233.685939 825.637477 319.323686 704.59016 198.276368 790.227906 112.638622C816.453389 86.413139 859.427341 86.80945 886.152521 113.551861L910.379215 137.761325C937.104395 164.503736 937.500707 207.460456 911.275224 233.685939ZM293.012048 609.888941 414.059366 730.919028 232.479774 791.468533 293.012048 609.888941ZM801.393552 343.567611 438.28606 706.692334 317.238743 585.645016 680.363465 222.520293 801.393552 343.567611ZM179.666958 189.953826C151.166992 189.953826 127.974154 213.146665 127.974154 241.646631L127.974154 844.798277C127.974154 873.298243 151.166992 896.491082 179.666958 896.491082L782.818604 896.491082C811.31857 896.491082 834.511409 873.298243 834.511409 844.798277L834.511409 360.540082 868.973279 326.078212 868.973279 844.798277C868.973279 892.303964 830.324292 930.952951 782.818604 930.952951L179.666958 930.952951C132.161271 930.952951 93.512284 892.303964 93.512284 844.798277L93.512284 241.646631C93.512284 194.140944 132.161271 155.491957 179.666958 155.491957L698.387023 155.491957 663.925153 189.953826 179.666958 189.953826Z"
:fill="color"
p-id="21925"
></path>
</svg>
</div>
</template>
<style lang="scss"></style>
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage } from 'element-plus'
import { getMemberConnectionsList, getMemberFieldsList, createMember, updateMember } from '../api'
import type { ConnectionsProp, MemberFieldsProp, MemberProp } from '../types'
import { useMapStore } from '@/stores/map'
// interface Props { const store = useMapStore()
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{ const ruleFormRef = ref<FormInstance>()
onMounted(() => {
getConnectionsList()
getFieldsList()
})
// 链接列表(所属链接选项)
let connectionOptions = $ref<ConnectionsProp[]>()
const getConnectionsList = function () {
getMemberConnectionsList().then((res: { data: ConnectionsProp[] }) => {
connectionOptions = res.data
})
}
// 用户属性
let fieldsList = $ref<MemberFieldsProp[]>([])
const getFieldsList = function () {
getMemberFieldsList().then((res: { data: MemberFieldsProp[] }) => {
fieldsList = res.data.map(item => {
item.value = ''
if (props.data) {
item.value = JSON.parse(props.data?.fields)[item.id]
}
return item
})
})
}
interface Props {
data?: MemberProp
}
const props = defineProps<Props>()
const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const form = $ref(
const form = reactive({ props.data || {
id: '',
name: '', name: '',
type: '', status: '0',
value: '', experiment_connection_id: '',
status: '' gender: '',
}) mobile: ''
}
)
const rules = ref<FormRules>({ const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }] name: [{ required: true, message: '请输入' }],
status: [{ required: true, message: '请选择' }],
experiment_connection_id: [{ required: true, message: '请选择' }],
gender: [{ required: true, message: '请选择' }],
mobile: [{ required: true, message: '请输入' }]
}) })
// 提交
const submitForm = (formEl: FormInstance | undefined) => {
const fields = fieldsList.reduce((a: any, b: { id: string; value: string }) => {
a[b.id] = b.value
return a
}, {})
const params = { ...form, fields: fields }
if (!formEl) return
formEl.validate(valid => {
if (valid) {
if (props.data?.id) {
updateMember(params).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '更新成功', type: 'success' })
})
} else {
createMember(params).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '添加成功', type: 'success' })
})
}
} else {
console.log('error submit!')
return false
}
})
}
</script> </script>
<template> <template>
<el-dialog <el-dialog
class="connect-form" class="connect-form"
title="新建用户" :title="props.data ? (props.data?.isView ? '查看用户' : '编辑用户') : '新建用户'"
:close-on-click-modal="false" :close-on-click-modal="false"
width="800px" width="800px"
@update:modelValue="$emit('update:modelValue')" @update:modelValue="$emit('update:modelValue')"
> >
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="142px"> <el-form
<el-form-item label="所属实验" prop="type"> :disabled="props.data?.isView"
<el-select v-model="form.type" style="width: 100%"></el-select> ref="ruleFormRef"
style="width: 400px; margin: 0 auto; padding: 0 30px 30px 0"
:model="form"
:rules="rules"
label-suffix=":"
label-width="110px"
>
<el-form-item label="来源链接" prop="experiment_connection_id">
<el-select v-model="form.experiment_connection_id" style="width: 100%">
<el-option v-for="item in connectionOptions" :label="item?.type_name" :value="item?.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input v-model="form.name" style="width: 100%"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="来源链接"> <el-form-item label="状态" prop="status">
<el-select v-model="form.id" style="width: 100%"></el-select> <el-switch v-model="form.status" active-text="生效" active-value="1" inactive-text="失效" inactive-value="0" />
</el-form-item> </el-form-item>
<el-form-item label="姓名"> <el-form-item label="性别" prop="gender">
<el-input v-model="form.id" style="width: 100%"></el-input> <el-select v-model="form.gender" style="width: 100%">
<el-option
v-for="item in store.getMapValuesByKey('system_gender')"
:label="item?.label"
:value="item?.value"
></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="状态"> <el-form-item label="手机号码" prop="mobile">
<el-radio-group v-model="form.id" class="ml-4"> <el-input v-model="form.mobile" style="width: 100%"></el-input>
<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>
<el-form-item label="性别"> <el-form-item :label="item.name" v-for="item in fieldsList">
<el-input v-model="form.id" style="width: 100%"></el-input> <template v-if="item.type === '4' || item.type === '5'">
<el-date-picker
v-if="item.format === 'yyyy-mm-dd'"
v-model="item.value"
type="date"
placeholder="请选择"
style="width: 100%"
value-format="YYYY-MM-DD"
/>
<el-date-picker
value-format="YYYY-MM-DD HH:mm:ss"
v-else
v-model="item.value"
type="datetime"
placeholder="请选择"
style="width: 100%"
/>
</template>
<el-input v-else v-model="item.value" style="width: 100%" placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="手机号"> <el-form-item>
<el-input v-model="form.id" style="width: 100%"></el-input> <el-button type="primary" @click="submitForm(ruleFormRef)">提交</el-button>
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="btn-box"> <!-- <div class="btn-box">
<el-button type="primary">保存</el-button> <el-button type="primary">保存</el-button>
<el-button type="primary">关闭</el-button> <el-button type="primary">关闭</el-button>
</div> </div> -->
</el-dialog> </el-dialog>
</template> </template>
<style lang="scss"> <style lang="scss">
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { getEventList, createEvent, updateEvent } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import type { EventProp, MemberProp, AttributesProp } from '../types'
// interface Props { const route = useRoute()
// data?: UserProp
// }
// const props = defineProps<Props>()
defineEmits<{ interface Props {
info?: MemberProp
data?: AttributesProp
}
const props = defineProps<Props>()
const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ const form = $ref(
id: '', props.data || {
name: '', experiment_meta_event_id: ''
type: '', }
value: '', )
status: ''
})
const rules = ref<FormRules>({ const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }] experiment_meta_event_id: [{ required: true, message: '请选择' }]
})
let eventList = $ref<EventProp[]>()
onMounted(() => {
getEventList().then(res => {
eventList = res.data.map(
(item: any) =>
item.attributes.map((cItem: any) =>
props.data ? (cItem.value = JSON.parse(props.data.fields)[cItem.id]) : (cItem.value = '') && cItem
) && item
)
})
})
// 属性
const eventAttributes = computed(() => {
return eventList?.find(item => item.id === form.experiment_meta_event_id)?.attributes
}) })
// 提交
const submitForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
const attributes = eventAttributes.value?.reduce((a: any, b: any) => {
a[b.id] = b.value
return a
}, {})
console.log(eventList, '123attributes')
const [data] = eventAttributes.value || []
formEl.validate(valid => {
if (valid) {
if (props.data) {
const params = {
id: props.data?.id,
fields: attributes
}
updateEvent(params).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '更新成功', type: 'success' })
})
} else {
const params = {
experiment_member_id: route.query?.user_id as '',
experiment_meta_event_id: data.experiment_meta_event_id,
fields: attributes
}
createEvent(params).then(res => {
emit('update')
emit('update:modelValue', false)
ElMessage({ message: '创建成功', type: 'success' })
})
}
} else {
return false
}
})
}
</script> </script>
<template> <template>
...@@ -34,21 +93,49 @@ const rules = ref<FormRules>({ ...@@ -34,21 +93,49 @@ const rules = ref<FormRules>({
@update:modelValue="$emit('update:modelValue')" @update:modelValue="$emit('update:modelValue')"
> >
<div class="update-event_info"> <div class="update-event_info">
<span>姓名:王小二</span> <span>姓名:{{ props.info?.name }}</span>
<span>来源链接:抖音</span> <span>来源链接:{{ props.info?.connection_name }}</span>
</div> </div>
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="122px"> <el-form
<el-form-item label="请选择事件" prop="type"> :disabled="props.data?.isView"
<el-select v-model="form.type" style="width: 100%"></el-select> ref="formRef"
:model="form"
:rules="rules"
label-suffix=":"
label-width="122px"
>
<el-form-item label="请选择事件" prop="experiment_meta_event_id">
<el-select :disabled="!!props.data" v-model="form.experiment_meta_event_id" style="width: 100%">
<el-option v-for="item in eventList" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<!-- 属性字段 -->
<el-form-item :label="item.name" v-for="item in eventAttributes">
<template v-if="item.type === '4' || item.type === '5'">
<el-date-picker
v-if="item.format === 'yyyy-mm-dd'"
v-model="item.value"
type="date"
placeholder="请选择"
style="width: 100%"
value-format="YYYY-MM-DD"
/>
<el-date-picker
value-format="YYYY-MM-DD HH:mm:ss"
v-else
v-model="item.value"
type="datetime"
placeholder="请选择"
style="width: 100%"
/>
</template>
<el-input v-else v-model="item.value" style="width: 100%" placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="订单金额" prop="type"> <el-form-item>
<el-input v-model="form.type" style="width: 100%"></el-input> <el-button type="primary" @click="submitForm(formRef)">提交</el-button>
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="btn-box">
<el-button type="primary">关闭</el-button>
<el-button type="primary">保存</el-button>
</div>
</el-dialog> </el-dialog>
</template> </template>
<style lang="scss"> <style lang="scss">
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getEventList, importEvent } from '../api'
import type { EventProp } from '../types'
// interface Props { // interface Props {
// data?: UserProp // data?: UserProp
// } // }
// const props = defineProps<Props>() // const props = defineProps<Props>()
defineEmits<{ const route = useRoute()
const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ const form = reactive({
id: '', event_id: ''
name: '',
type: '',
value: '',
status: ''
}) })
const rules = ref<FormRules>({ const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }] event_id: [{ required: true, message: '请选择' }]
})
// 选择事件
let eventList = $ref<EventProp[]>()
onMounted(() => {
getEventList().then(res => {
eventList = res.data
})
})
const connectionName = computed(() => {
return eventList?.find((item: EventProp) => item.id === form.event_id)?.connection_name
}) })
// 下载数据模板
const downloadTemplate = function () {
if (form.event_id !== '')
window.open(
`/api/experiment/v1/experiment/member/event-download?event_id=${form.event_id}&experiment_id=${route.query.experiment_id}`
)
}
// 上传
const fetchFileUpload = (option: any) => {
return new Promise(() => {
importEvent({ event_id: form.event_id, file: option.file }).then(() => {
ElMessage.success('导入数据成功')
emit('update')
emit('update:modelValue', false)
// emit('update:isShowImportDialog', false)
// emit('create')
})
})
}
</script> </script>
<template> <template>
...@@ -35,24 +68,37 @@ const rules = ref<FormRules>({ ...@@ -35,24 +68,37 @@ const rules = ref<FormRules>({
@update:modelValue="$emit('update:modelValue')" @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="请选择事件" prop="type"> <el-form-item label="请选择事件" prop="event_id">
<el-select v-model="form.type" style="width: 100%"></el-select> <el-select v-model="form.event_id" style="width: 100%">
<span>事件所属链接:抖音</span> <el-option v-for="item in eventList" :label="item.name" :value="item.id"></el-option>
</el-select>
<span v-if="connectionName">事件所属链接:{{ connectionName }}</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="btn-box"> <div class="btn-box">
<el-button type="primary">下载事件数据模板</el-button> <el-button style="margin-right: 20px" type="primary" @click="downloadTemplate">下载事件数据模板</el-button>
<el-upload
class="upload-demo"
action="#"
multiple
ref="upload"
:auto-upload="true"
:limit="1"
:http-request="fetchFileUpload"
>
<el-button type="primary">上传事件数据</el-button> <el-button type="primary">上传事件数据</el-button>
</el-upload>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<el-button type="primary">关闭</el-button> <el-button type="primary" @click="$emit('update:modelValue', false)">关闭</el-button>
<!-- <el-button type="primary">上传事件数据</el-button> -->
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<style lang="scss"> <style lang="scss">
.btn-box { .btn-box {
display: flex;
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
justify-content: center;
} }
</style> </style>
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { getMemberConnectionsList, getMemberGroups, importMember } from '../api'
import type { ConnectionsProp } from '../types'
// interface Props { // interface Props {
// data?: UserProp // data?: UserProp
// } // }
// const props = defineProps<Props>() // const props = defineProps<Props>()
defineEmits<{ const route = useRoute()
const emit = defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void (e: 'update:modelValue', visible: boolean): void
}>() }>()
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ const form = reactive({
id: '', connection_id: '',
name: '', groups_id: ''
type: '',
value: '',
status: ''
}) })
const rules = ref<FormRules>({ const rules = ref<FormRules>({
type: [{ required: true, message: '请选择属性字段类型' }] connection_id: [{ required: true, message: '请选择' }]
})
// 链接列表
let connectionList = $ref<ConnectionsProp[]>()
// 群组列表
let groupList = $ref<{ name: string; id: string }[]>()
onMounted(() => {
getMemberConnectionsList().then(res => {
connectionList = res.data
})
getMemberGroups().then(res => {
groupList = res.data
})
}) })
// 下载数据模板
const downloadTemplate = function () {
window.open(`/api/experiment/v1/experiment/member/member-download?experiment_id=${route.query.experiment_id}`)
}
// 上传
const fetchFileUpload = (option: any) => {
return new Promise(() => {
const params = Object.assign(form, { file: option.file })
importMember(params).then(() => {
ElMessage.success('导入数据成功')
emit('update')
emit('update:modelValue', false)
// emit('update:isShowImportDialog', false)
// emit('create')
})
})
}
</script> </script>
<template> <template>
...@@ -35,16 +68,30 @@ const rules = ref<FormRules>({ ...@@ -35,16 +68,30 @@ const rules = ref<FormRules>({
@update:modelValue="$emit('update:modelValue')" @update:modelValue="$emit('update:modelValue')"
> >
<el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="142px"> <el-form ref="formRef" :model="form" :rules="rules" label-suffix=":" label-width="142px">
<el-form-item label="请选择所属链接" prop="type"> <el-form-item label="请选择所属链接" prop="connection_id">
<el-select v-model="form.type" style="width: 100%"></el-select> <el-select v-model="form.connection_id" style="width: 100%">
<el-option v-for="item in connectionList" :label="item.type_name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="请选择静态群组"> <el-form-item label="请选择静态群组">
<el-select v-model="form.id" style="width: 100%"></el-select> <el-select v-model="form.groups_id" style="width: 100%">
<el-option v-for="item in groupList" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="btn-box"> <div class="btn-box">
<el-button type="primary">下载用户数据模板</el-button> <el-button style="margin-right: 20px" type="primary" @click="downloadTemplate">下载用户数据模板</el-button>
<el-upload
class="upload-demo"
action="#"
multiple
ref="upload"
:auto-upload="true"
:limit="1"
:http-request="fetchFileUpload"
>
<el-button type="primary">上传用户数据</el-button> <el-button type="primary">上传用户数据</el-button>
</el-upload>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<el-button type="primary">关闭</el-button> <el-button type="primary">关闭</el-button>
...@@ -56,5 +103,7 @@ const rules = ref<FormRules>({ ...@@ -56,5 +103,7 @@ const rules = ref<FormRules>({
.btn-box { .btn-box {
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
display: flex;
justify-content: center;
} }
</style> </style>
...@@ -7,7 +7,8 @@ const routes: RouteRecordRaw[] = [ ...@@ -7,7 +7,8 @@ const routes: RouteRecordRaw[] = [
component: Layout, component: Layout,
children: [ children: [
{ path: '', component: () => import('./views/Index.vue') }, { path: '', component: () => import('./views/Index.vue') },
{ path: 'eventDetails', component: () => import('./views/EventDetails.vue') } { path: 'eventDetails', component: () => import('./views/EventDetails.vue') },
{ path: 'image', component: () => import('./views/Image.vue') }
] ]
} }
] ]
......
export interface ConnectionsProp {
id: string
type: string
type_name: string
}
export interface MemberFieldsProp {
id: string
name: string
english_name: string
type: string
type_name: string
format: string
value: string
isShow: boolean
}
export interface MemberProp {
id: string
name: string
status: string
experiment_connection_id: string
gender: string
mobile: string
fields: string
isView?: boolean
connection_name: string
status_name: string
}
export interface EventProp {
name: string
id: string
attributes: AttributesProp[]
connection_name: string
}
export interface AttributesProp {
name: string
id: string
type: string
format: string
value: string
experiment_meta_event_id: string
fields: string
connection_id: string
isView: boolean
}
export interface ImageProp {
tag: string[]
static_groups: string[]
dynamic_groups: string[]
events: {
list: {
updated_time: string
connection_type: string
connection_name: string
event_name: string
}[]
}
}
<script setup lang="ts"> <script setup lang="ts">
import { Plus, Download, Upload, Delete } from '@element-plus/icons-vue' import { ElMessageBox, ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue' import AppList from '@/components/base/AppList.vue'
import UpdateEventsDialog from '../components/UpdateEventsDialog.vue' import UpdateEventsDialog from '../components/UpdateEventsDialog.vue'
import { getMemberEventList, deleteEvent } from '../api'
import type { MemberProp, AttributesProp } from '../types'
const route = useRoute()
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
let userInfo = $ref<MemberProp>()
// 列表配置 // 列表配置
const listOptions = computed(() => { const listOptions = computed(() => {
return { return {
remote: {
httpRequest: getMemberEventList,
params: { id: route.query.user_id },
callback: (data: any) => {
userInfo = data
return data.events
}
},
columns: [ columns: [
{ label: '序号', type: 'index', width: 60 }, { label: '序号', type: 'index', width: 60 },
{ label: '事件名称', prop: 'id' }, { label: '事件名称', prop: 'event_name' },
{ label: '链接名称', prop: 'name' }, { label: '链接名称', prop: 'connection_name' },
{ label: '事件发生时间', prop: 'name' }, { label: '事件发生时间', prop: 'created_time' },
{ label: '操作', slots: 'table-x', width: 380 } { label: '操作', slots: 'table-x', width: 380 }
], ]
data: [{}, {}]
} }
}) })
...@@ -24,32 +38,69 @@ function handleRefresh() { ...@@ -24,32 +38,69 @@ function handleRefresh() {
} }
// 事件弹窗 // 事件弹窗
const eventsVisible = $ref(false) let eventsVisible = $ref(false)
// 编辑
let currentRow = $ref<AttributesProp>()
const handleEdit = function (row: AttributesProp) {
row.isView = false
currentRow = row
eventsVisible = true
}
// 删除
function handleRemove(row: AttributesProp) {
ElMessageBox.confirm('确定要删除该属性吗?', '提示').then(() => {
deleteEvent({ id: row.id }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
handleRefresh()
})
})
}
// 新建
const handleAdd = function () {
currentRow = undefined
eventsVisible = true
}
// 查看
const handleView = function (row: AttributesProp) {
row.isView = true
currentRow = row
eventsVisible = true
}
</script> </script>
<template> <template>
<AppCard title="用户事件数据"> <AppCard title="用户事件数据">
<div class="event-user_info"> <div class="event-user_info">
<span>姓名:王小二</span> <span>姓名:{{ userInfo?.name }}</span>
<span>id:11111</span> <span>id:{{ userInfo?.id }}</span>
<span>来源链接:抖音</span> <span>来源链接:{{ userInfo?.connection_name }}</span>
<span>状态:生效</span> <span>状态:{{ userInfo?.status_name }}</span>
</div> </div>
</AppCard> </AppCard>
<AppCard> <AppCard>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<template #header-buttons> <template #header-buttons>
<el-button type="primary" :icon="Plus" @click="eventsVisible = true">新建用户事件</el-button> <el-button type="primary" :icon="Plus" @click="handleAdd">新建用户事件</el-button>
</template> </template>
<template #table-x> <template #table-x="{ row }">
<el-button type="primary" plain>查看</el-button> <el-button type="primary" plain @click="handleView(row)">查看</el-button>
<el-button type="primary" plain>编辑</el-button> <el-button type="primary" plain @click="handleEdit(row)">编辑</el-button>
<el-button type="primary" plain>删除</el-button> <el-button type="primary" plain @click="handleRemove(row)">删除</el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<!-- 新建更新事件 --> <!-- 新建更新事件 -->
<UpdateEventsDialog v-model="eventsVisible"></UpdateEventsDialog> <UpdateEventsDialog
@update="handleRefresh()"
:data="currentRow"
v-if="eventsVisible"
:info="userInfo"
v-model="eventsVisible"
></UpdateEventsDialog>
</template> </template>
<style lang="scss"> <style lang="scss">
.event-user_info { .event-user_info {
......
<script setup lang="ts">
import { getMemberImage, getMemberFieldsList } from '../api'
import type { MemberFieldsProp, ImageProp } from '../types'
import Icon from '../components/Icon.vue'
const route = useRoute()
// 画像数据
let data = $ref<ImageProp>()
// 属性
let fieldsList = $ref<MemberFieldsProp[]>()
onMounted(() => {
// 画像
getMemberImage({ id: route.query.user_id as '' }).then(res => {
data = res.data
getFields(res.data)
})
// 属性
})
const getFields = function (data: { fields: any }) {
getMemberFieldsList().then(res => {
// fieldsList = res.data
fieldsList = res.data.map((item: MemberFieldsProp) => {
if (data.fields[item.id]) {
item.value = data.fields[item.id]
item.isShow = true
}
return item
})
})
}
// 获取上下午
const getDate = function (date: string) {
return parseInt(date.slice(date.indexOf(' '), date.indexOf(' ') + 3)) > 12 ? '下午' : '上午'
}
</script>
<template>
<div class="card-box">
<AppCard class="card" title="用户属性">
<div style="display: flex; justify-content: center; padding-right: 20px">
<el-form label-suffix=":" label-width="110px">
<template v-for="item in fieldsList">
<el-form-item v-if="item?.isShow" :label="item?.name"
><span>{{ item?.value }}</span></el-form-item
>
</template>
</el-form>
</div>
</AppCard>
<AppCard class="card" title="标签与群组">
<el-tabs class="demo-tabs">
<el-tab-pane label="用户标签">
<div class="scroll">
<el-tag class="ml-2" type="success" v-for="item in data?.tag">{{ item }}</el-tag>
</div>
</el-tab-pane>
</el-tabs>
<el-tabs class="demo-tabs">
<el-tab-pane label="静态分组">
<div class="scroll">
<el-tag class="ml-2" type="success" v-for="item in data?.static_groups">{{ item }}</el-tag>
</div>
</el-tab-pane>
</el-tabs>
<el-tabs class="demo-tabs">
<el-tab-pane label="动态分组">
<div class="scroll">
<el-tag class="ml-2" type="success" v-for="item in data?.dynamic_groups">{{ item }}</el-tag>
</div>
</el-tab-pane>
</el-tabs>
</AppCard>
<AppCard class="card" title="用户行为轨迹">
<div class="event-box" v-for="item in data?.events?.list">
<div class="date">{{ item.updated_time?.slice(0, item.updated_time.indexOf(' ')) }}</div>
<div class="event-content">
<div class="time">
{{ item.updated_time?.slice(item.updated_time.indexOf(' '), item.updated_time.length - 3) }}
{{ getDate(item.updated_time) }}
</div>
<Icon class="icon" :name="item.connection_type" w="30" h="30"></Icon>
<div class="event">
<span>"{{ item.connection_name }}"</span><span>"{{ item.event_name }}"</span>
</div>
</div>
</div>
<div class="event-box" v-for="item in data?.events?.list">
<div class="date">{{ item.updated_time?.slice(0, item.updated_time.indexOf(' ')) }}</div>
<div class="event-content">
<div class="time">
{{ item.updated_time?.slice(item.updated_time.indexOf(' '), item.updated_time.length - 3) }}
{{ getDate(item.updated_time) }}
</div>
<Icon class="icon" :name="item.connection_type" w="30" h="30"></Icon>
<div class="event">
<span>"{{ item.connection_name }}"</span><span>"{{ item.event_name }}"</span>
</div>
</div>
</div>
</AppCard>
</div>
</template>
<style lang="scss">
.ml-2 {
margin-right: 10px;
}
.card-box {
display: flex;
.card {
flex: 1;
margin-top: 0;
height: 90vh;
margin-right: 10px;
.demo-tabs {
height: 26vh;
}
}
}
.event-box {
border-bottom: 1px solid #ccc;
padding: 20px 0 5px;
.date {
font-size: 14px;
}
}
.event-content {
display: flex;
font-size: 12px;
align-items: center;
// margin-bottom: 20px;
flex-wrap: wrap;
.time {
color: #ccc;
}
.icon {
margin: 0 5px;
}
span {
color: #ba143e;
font-weight: bold;
}
}
</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 { getMemberList, deleteMember } from '../api'
import UploadUserDialog from '../components/UploadUserDialog.vue' import { ElMessage } from 'element-plus'
import UpdateDialog from '../components/UpdateDialog.vue' import type { MemberProp } from '../types'
// import { getMemberMetaDetail } from '../api'
const UpdateDialog = defineAsyncComponent(() => import('../components/UpdateDialog.vue'))
const UploadEventsDialog = defineAsyncComponent(() => import('../components/UploadEventsDialog.vue'))
const UploadUserDialog = defineAsyncComponent(() => import('../components/UploadUserDialog.vue'))
const router = useRouter()
const route = useRoute()
const appList = $ref<InstanceType<typeof AppList> | null>(null) const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置 // 列表配置
const listOptions = computed(() => { const listOptions = computed(() => {
return { return {
filters: [{ type: 'input', prop: 'name', placeholder: '请输入用户姓名' }], remote: {
httpRequest: getMemberList,
params: { name: '', id: '', mobile: '', status: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '请输入用户姓名' },
{ type: 'input', prop: 'id', placeholder: '请输入用户ID' },
{ type: 'input', prop: 'mobile', placeholder: '请输入用户手机号' },
{
type: 'select',
prop: 'status',
placeholder: '请选择生效状态',
options: [
{ label: '有效', value: '1' },
{ label: '失效', value: '0' }
]
}
],
columns: [ columns: [
{ type: 'selection' }, { type: 'selection' },
{ 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: 'gender_name' },
{ label: '手机号码', prop: 'name' }, { label: '手机号码', prop: 'mobile' },
{ label: '来源连接', prop: 'name' }, { label: '来源连接', prop: 'connection_name' },
{ 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: 380 } { label: '操作', slots: 'table-x', width: 380 }
], ]
data: [{}, {}]
} }
}) })
...@@ -40,21 +63,99 @@ const eventsVisible = $ref(false) ...@@ -40,21 +63,99 @@ const eventsVisible = $ref(false)
const userVisible = $ref(false) const userVisible = $ref(false)
// 新建、更新、查看 // 新建、更新、查看
const updateVisible = $ref(false) let updateVisible = $ref(false)
let multipleSelection = $ref<MemberProp[]>([])
function handleSelectionChange(selection: MemberProp[]) {
multipleSelection = selection
}
// 删除
const handleRemove = function (row: { id: string }) {
deleteMembers(row.id)
}
const handleRemoves = function () {
const ids = multipleSelection
.reduce((a: any, b: any) => {
a.push(b.id)
return a
}, [])
.toString()
deleteMembers(ids)
}
const deleteMembers = function (ids: string) {
deleteMember({ ids: ids }).then(res => {
ElMessage({ message: '删除成功', type: 'success' })
handleRefresh()
})
}
// 编辑
let currentRow = ref<MemberProp>()
const handleEdit = function (row: MemberProp) {
currentRow.value = row
row.isView = false
updateVisible = true
}
// 查看
const handleView = function (row: MemberProp) {
row.isView = true
currentRow.value = row
updateVisible = true
}
// 新建
const handleAdd = function () {
updateVisible = true
currentRow.value = undefined
}
// 事件详情页
const goPage = function (row: MemberProp) {
router.push({
path: '/user/eventDetails',
query: { user_id: row.id }
})
}
// 画像
const handleImage = function (row: MemberProp) {
router.push({
path: '/user/image',
query: { user_id: row.id }
})
}
// 导出用户
const downloadMember = function (isAll?: boolean) {
const ids = multipleSelection
.reduce((a: any, b: any) => {
a.push(b.id)
return a
}, [])
.toString()
if (isAll) {
window.open(`/api/experiment/v1/experiment/member/download?experiment_id=${route.query.experiment_id}`)
} else {
window.open(`/api/experiment/v1/experiment/member/download?experiment_id=${route.query.experiment_id}&ids=${ids}`)
}
}
</script> </script>
<template> <template>
<AppCard> <AppCard>
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList" @selection-change="handleSelectionChange">
<template #header-buttons> <template #header-buttons>
<el-space> <el-space>
<el-button type="primary" :icon="Plus">新建</el-button> <el-button type="primary" :icon="Plus" @click="handleAdd">新建</el-button>
<el-dropdown> <el-dropdown>
<el-button type="primary" :icon="Download">导出</el-button> <el-button type="primary" :icon="Download">导出</el-button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item>全部用户数据</el-dropdown-item> <el-dropdown-item @click="downloadMember(true)">全部用户数据</el-dropdown-item>
<el-dropdown-item>勾选用户数据</el-dropdown-item> <el-dropdown-item @click="downloadMember(false)">勾选用户数据</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
...@@ -67,22 +168,24 @@ const updateVisible = $ref(false) ...@@ -67,22 +168,24 @@ const updateVisible = $ref(false)
</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" :disabled="!multipleSelection.length" @click="handleRemoves()"
>删除</el-button
>
</el-space> </el-space>
</template> </template>
<template #table-x> <template #table-x="{ row }">
<el-button type="primary" plain>画像</el-button> <el-button type="primary" plain @click="handleImage(row)">画像</el-button>
<el-button type="primary" plain>查看</el-button> <el-button type="primary" plain @click="handleView(row)">查看</el-button>
<el-button type="primary" plain>编辑</el-button> <el-button type="primary" plain @click="handleEdit(row)">编辑</el-button>
<el-button type="primary" plain>删除</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="goPage(row)">事件</el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
<!-- 导入事件弹窗 --> <!-- 导入事件弹窗 -->
<UploadEventsDialog v-model="eventsVisible"></UploadEventsDialog> <UploadEventsDialog @update="handleRefresh" v-if="eventsVisible" v-model="eventsVisible"></UploadEventsDialog>
<!-- 导入用户弹窗 --> <!-- 导入用户弹窗 -->
<UploadUserDialog v-model="userVisible"></UploadUserDialog> <UploadUserDialog @update="handleRefresh" v-if="userVisible" v-model="userVisible"></UploadUserDialog>
<!-- 新建、更新、查看 --> <!-- 新建、更新、查看 -->
<UpdateDialog v-model="updateVisible"></UpdateDialog> <UpdateDialog v-if="updateVisible" :data="currentRow" v-model="updateVisible" @update="handleRefresh"></UpdateDialog>
</template> </template>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论