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

feat: 标签管理

上级 d850c524
import httpRequest from '@/utils/axios'
import type {
LabelTypeListRequest,
LabelTypeCreateRequest,
LabelTypeUpdateRequest,
LabelListRequest,
LabelCreateRequest,
LabelUpdateRequest
} from './types'
// 获取标签类型列表
export function getLabelTypeList(params?: LabelTypeListRequest) {
return httpRequest.get('/api/lab/v1/experiment/tag-type/list', { params })
}
// 创建标签类型
export function createLabelType(data: LabelTypeCreateRequest) {
return httpRequest.post('/api/lab/v1/experiment/tag-type/create', data)
}
// 更新标签类型
export function updateLabelType(data: LabelTypeUpdateRequest) {
return httpRequest.post('/api/lab/v1/experiment/tag-type/update', data)
}
// 更新标签类型
export function deleteLabelType(data: { id: string }) {
return httpRequest.post('/api/lab/v1/experiment/tag-type/delete', data)
}
// 获取标签列表
export function getLabelList(params?: LabelListRequest) {
return httpRequest.get('/api/lab/v1/experiment/tag/list', { params })
}
// 创建标签
export function createLabel(data: LabelCreateRequest) {
return httpRequest.post('/api/lab/v1/experiment/tag/create', data)
}
// 更新标签
export function updateLabel(data: LabelUpdateRequest) {
return httpRequest.post('/api/lab/v1/experiment/tag/update', data)
}
// 更新标签
export function deleteLabel(data: { id: string }) {
return httpRequest.post('/api/lab/v1/experiment/tag/delete', data)
}
// 获取标签数据信息
export function getLabelStatistics(params: { id: string }) {
return httpRequest.get('/api/lab//v1/experiment/tag/statistics', { params })
}
......@@ -3,11 +3,14 @@ import type { Label } from '../types'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { dateUnitList, weekList } from '@/utils/dictionary'
import { createLabel, updateLabel } from '../api'
import { useLabelType } from '../composables/useLabelType'
import { updateStatusRuleList } from '@/utils/dictionary'
import { pick } from 'lodash-es'
interface Props {
const props = defineProps<{
data?: Label
}
const props = defineProps<Props>()
}>()
const emit = defineEmits<{
(e: 'update'): void
......@@ -17,20 +20,33 @@ const emit = defineEmits<{
const isUpdate = $computed(() => !!props.data?.id)
const title = $computed(() => (isUpdate ? '修改标签' : '新建标签'))
const { typeList } = useLabelType()
const formRef = $ref<FormInstance>()
const form = reactive({
id: '',
name: '',
type: '',
update_rule: {
type: '1',
info: { unit: undefined, week: undefined, day: undefined }
},
status: ''
type_id: '',
update_status: '1',
update_rule: { type: 1, info: 1 },
status: '1'
})
watchEffect(() => {
if (props.data) {
let updateRule = { type: 1, info: 1 }
try {
updateRule = JSON.parse(props.data.update_rule)
} catch (error) {
console.log(error)
}
Object.assign(form, props.data, { update_rule: updateRule })
}
})
const rules = ref<FormRules>({
name: [{ required: true, message: '请输入标签名称' }],
type: [{ required: true, message: '请选择标签类型' }]
type_id: [{ required: true, message: '请选择标签类型' }],
update_status: [{ required: true, message: '请选择更新评率' }]
})
// 提交
......@@ -39,15 +55,34 @@ function handleSubmit() {
}
// 新建
function handleCreate() {
const params = pick({ ...form, update_rule: JSON.stringify(form.update_rule) }, [
'name',
'type_id',
'update_status',
'update_rule',
'status'
])
createLabel(params).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate() {
const params = pick({ ...form, update_rule: JSON.stringify(form.update_rule) }, [
'id',
'name',
'type_id',
'update_status',
'update_rule',
'status'
])
updateLabel(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
</script>
......@@ -57,32 +92,35 @@ function handleUpdate() {
<el-form-item label="标签名称" prop="name">
<el-input v-model="form.name" placeholder="请输入" />
</el-form-item>
<el-form-item label="标签类型" prop="type">
<el-select v-model="form.type" style="width: 100%"></el-select>
<el-form-item label="标签类型" prop="type_id">
<el-select v-model="form.type_id" style="width: 100%">
<el-option v-for="item in typeList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="更新频率" prop="update_rule.type">
<el-radio-group v-model="form.update_rule.type">
<el-radio label="1">自动更新</el-radio>
<el-radio label="2">手动更新</el-radio>
<el-form-item label="更新频率" prop="update_status">
<el-radio-group v-model="form.update_status">
<el-radio v-for="item in updateStatusRuleList" :key="item.value" :label="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
<div class="update-rule-wrap" v-if="form.update_rule.type === '1'">
<div class="update-rule-wrap" v-if="form.update_status === '1'">
<span></span>
<el-select v-model="form.update_rule.info.unit" placeholder=" " style="width: 60px">
<el-select v-model="form.update_rule.type" placeholder=" " style="width: 60px">
<el-option v-for="item in dateUnitList" :label="item.label" :value="item.value"></el-option>
</el-select>
<template v-if="form.update_rule.info.unit === 1">
<template v-if="form.update_rule.type === 1">
<span>的凌晨更新</span>
</template>
<template v-if="form.update_rule.info.unit === 2">
<template v-if="form.update_rule.type === 2">
<span></span>
<el-select v-model="form.update_rule.info.week" placeholder=" " style="width: 80px">
<el-select v-model="form.update_rule.info" placeholder=" " style="width: 80px">
<el-option v-for="item in weekList" :label="item.label" :value="item.value"></el-option>
</el-select>
<span>的凌晨更新</span>
</template>
<template v-if="form.update_rule.info.unit === 3">
<template v-if="form.update_rule.type === 3">
<span></span>
<el-select v-model="form.update_rule.info.day" placeholder=" " style="width: 60px">
<el-select v-model="form.update_rule.info" placeholder=" " style="width: 60px">
<el-option v-for="item in 6" :label="item" :value="item"></el-option>
</el-select>
<span>天的凌晨更新</span>
......@@ -90,7 +128,7 @@ function handleUpdate() {
</div>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-switch v-model="form.status" active-text="生效" inactive-text="失效" />
<el-switch v-model="form.status" active-text="生效" active-value="1" inactive-text="失效" inactive-value="0" />
</el-form-item>
</el-form>
<template #footer>
......
<script setup lang="ts">
import type { LabelType } from '../types'
import { Edit, Delete } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
import { deleteLabelType } from '../api'
import { useLabelType } from '../composables/useLabelType'
const LabelTypeFormDialog = defineAsyncComponent(() => import('../components/LabelTypeFormDialog.vue'))
const list = $ref<LabelType[]>([
{ id: '1', name: '基础标签', url: 'red' },
{ id: '2', name: '渠道标签', url: 'blue' }
])
const { labelCount, typeList, fetchTypeList } = useLabelType()
let formVisible = $ref(false)
let currentRow = $ref<LabelType>()
......@@ -25,7 +24,12 @@ function handleUpdate(row: LabelType) {
}
// 删除
function handleRemove(row: LabelType) {
ElMessageBox.confirm('确定要删除该类型吗?', '提示').then(() => {})
ElMessageBox.confirm('确定要删除该类型吗?', '提示').then(() => {
deleteLabelType({ id: row.id }).then(() => {
ElMessage({ message: '删除成功', type: 'success' })
fetchTypeList()
})
})
}
</script>
......@@ -33,10 +37,10 @@ function handleRemove(row: LabelType) {
<el-button type="primary" style="width: 100%" @click="handleAdd">添加标签类型</el-button>
<div class="label-type-total">
<h4>全部标签</h4>
<p>127个</p>
<p>{{ labelCount }}</p>
</div>
<ul>
<li class="label-type-item" v-for="item in list" :key="item.id">
<li class="label-type-item" v-for="item in typeList" :key="item.id">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" width="16" height="16" :fill="item.url">
<g>
<path
......@@ -46,12 +50,16 @@ function handleRemove(row: LabelType) {
<p>{{ item.name }}</p>
<div class="label-type-actions">
<el-icon class="label-type-item__edit" @click="handleUpdate(item)"><Edit /></el-icon>
<el-icon class="label-type-item__remove" @click="handleRemove"><Delete /></el-icon>
<el-icon class="label-type-item__remove" @click="handleRemove(item)"><Delete /></el-icon>
</div>
</li>
</ul>
<LabelTypeFormDialog v-model="formVisible" :data="currentRow" v-if="formVisible"></LabelTypeFormDialog>
<LabelTypeFormDialog
v-model="formVisible"
:data="currentRow"
@update="fetchTypeList"
v-if="formVisible"></LabelTypeFormDialog>
</template>
<style lang="scss">
......
......@@ -2,11 +2,11 @@
import type { LabelType } from '../types'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { createLabelType, updateLabelType } from '../api'
interface Props {
const props = defineProps<{
data?: LabelType
}
const props = defineProps<Props>()
}>()
const emit = defineEmits<{
(e: 'update'): void
......@@ -18,6 +18,11 @@ const title = $computed(() => (isUpdate ? '修改标签类型' : '新建标签
const formRef = $ref<FormInstance>()
const form = reactive({ id: '', name: '', url: '' })
watchEffect(() => {
if (props.data) Object.assign(form, props.data)
})
const rules = ref<FormRules>({
name: [{ required: true, message: '请输入标签类型名称' }],
url: [{ required: true, message: '请选择标签类型图标' }]
......@@ -55,15 +60,19 @@ function handleSubmit() {
}
// 新建
function handleCreate() {
createLabelType(form).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate() {
updateLabelType(form).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
</script>
......
<script setup lang="ts">
import type { Label } from '../types'
import { UserFilled } from '@element-plus/icons-vue'
import { useMapStore } from '@/stores/map'
import { getNameByValue, updateStatusRuleList } from '@/utils/dictionary'
import { getLabelStatistics } from '../api'
// import { ElMessage } from 'element-plus'
interface Props {
const props = defineProps<{
data: Label
}
const props = defineProps<Props>()
const emit = defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const statusList = useMapStore().getMapValuesByKey('system_status')
const detail = reactive({ count: 0, status: 1, updated_time: '-' })
function fetchInfo() {
getLabelStatistics({ id: props.data.id }).then(res => {
console.log(res)
Object.assign(detail, res.data.detail)
})
}
watchEffect(() => fetchInfo())
</script>
<template>
<el-dialog
title="查看标签信息"
:close-on-click-modal="false"
width="600px"
@update:modelValue="$emit('update:modelValue')">
<el-dialog title="查看标签信息" width="600px">
<el-form label-suffix=":" label-width="82px">
<el-row>
<el-col :span="12"><el-form-item label="标签名称">标签名称</el-form-item></el-col>
<el-col :span="12"
><el-form-item label="标签名称">{{ data.name }}</el-form-item></el-col
>
<el-col :span="12">
<el-form-item label="标签类型">标签类型</el-form-item>
<el-form-item label="标签类型">{{ data.tag_type.name }}</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12"><el-form-item label="更新频率">自动更新</el-form-item></el-col>
<el-col :span="12"><el-form-item label="状态">生效</el-form-item></el-col>
<el-col :span="12">
<el-form-item label="更新频率">{{ getNameByValue(data.update_status, updateStatusRuleList) }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-tag :type="data.status === '1' ? 'success' : 'danger'">
{{ getNameByValue(data.status, statusList) }}
</el-tag>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-card>
......@@ -38,12 +52,12 @@ const emit = defineEmits<{
<dt>符合标签人数</dt>
<dd class="label-box__count">
<el-icon><UserFilled></UserFilled></el-icon>
<span>199</span>
<span>{{ detail.count }}</span>
</dd>
</dl>
<dl>
<dt>最后更新时间</dt>
<dd>2022-10-12 13:24:23</dd>
<dd>{{ detail.updated_time }}</dd>
</dl>
<dl>
<dt>更新状态</dt>
......
import type { LabelType } from '../types'
import { getLabelTypeList } from '../api'
const labelCount = ref(0)
const typeList = ref<LabelType[]>([])
export function useLabelType() {
function fetchTypeList() {
getLabelTypeList().then(res => {
labelCount.value = res.data.tag_count
typeList.value = res.data.items
})
}
onMounted(() => {
if (!typeList.value?.length) fetchTypeList()
})
return { fetchTypeList, typeList, labelCount }
}
import type { Operator } from '@/types'
// 标签类型
export interface LabelType {
id: string
name: string
url: string
}
export type LabelTypeListRequest = Pick<LabelType, 'id' | 'name'> & { experiment_id?: string }
export type LabelTypeUpdateRequest = Pick<LabelType, 'id' | 'name' | 'url'> & { experiment_id?: string }
export type LabelTypeCreateRequest = Omit<LabelTypeUpdateRequest, 'id'>
// 标签
export interface Label {
id: string
name: string
status: 0 | 1
update_rule: LabelUpdateRule
type_id: string
status: string
update_status: '1' | '2'
update_rule: string
tag_type: LabelType
created_time: string
created_operator: Operator
updated_time: string
updated_operator: Operator
}
// 标签更新规则
export interface LabelUpdateRule {
type: 1 | 2 | 3
info: any
info: number
}
export type LabelListRequest = Pick<LabelType, 'id' | 'name'> & { experiment_id?: string }
export type LabelUpdateRequest = Pick<Label, 'id' | 'name' | 'type_id' | 'update_rule' | 'status'> & {
experiment_id?: string
}
export type LabelCreateRequest = Omit<LabelUpdateRequest, 'id'>
......@@ -3,34 +3,57 @@ import type { Label } from '../types'
import { Plus } from '@element-plus/icons-vue'
import AppList from '@/components/base/AppList.vue'
import LabelType from '../components/LabelType.vue'
import { ElMessageBox } from 'element-plus'
import { ElMessageBox, ElMessage } from 'element-plus'
import { getLabelList, deleteLabel } from '../api'
import { useMapStore } from '@/stores/map'
import { getNameByValue, updateStatusRuleList } from '@/utils/dictionary'
import { useLabelType } from '../composables/useLabelType'
const LabelFormDialog = defineAsyncComponent(() => import('../components/LabelFormDialog.vue'))
const LabelViewDialog = defineAsyncComponent(() => import('../components/LabelViewDialog.vue'))
const LabelRuleDialog = defineAsyncComponent(() => import('../components/LabelRuleDialog.vue'))
const statusList = useMapStore().getMapValuesByKey('system_status')
const { typeList } = useLabelType()
const appList = $ref<InstanceType<typeof AppList> | null>(null)
// 列表配置
const listOptions = computed(() => {
return {
remote: {
httpRequest: getLabelList,
params: { name: '', type_id: '', status: '', updated_operator: '' }
},
filters: [
{ type: 'input', prop: 'name', placeholder: '请输入标签名称' },
{ type: 'select', prop: 'type', placeholder: '请选择标签类型' },
{ type: 'select', prop: 'type', placeholder: '请选择标签状态' },
{ type: 'input', prop: 'name', placeholder: '更新人' }
{
type: 'select',
prop: 'type_id',
placeholder: '请选择标签类型',
options: typeList.value,
labelKey: 'name',
valueKey: 'id'
},
{ type: 'select', prop: 'status', placeholder: '请选择标签状态', options: statusList },
{ type: 'input', prop: 'updated_operator', placeholder: '更新人' }
],
columns: [
{ label: '序号', type: 'index', width: 60 },
{ label: '标签ID', prop: 'id' },
{ label: '标签名称', prop: 'name' },
{ label: '标签类型', prop: 'type' },
{ label: '更新频率', prop: 'update_rule.type' },
{ label: '状态', prop: 'status' },
{ label: '更新人', prop: 'updated_operator.name' },
{ label: '标签类型', prop: 'tag_type.name' },
{
label: '更新频率',
prop: 'update_status',
computed({ row }: { row: Label }) {
return getNameByValue(row.update_status, updateStatusRuleList)
}
},
{ label: '状态', prop: 'status', slots: 'table-status' },
{ label: '更新人', prop: 'updated_operator.real_name' },
{ label: '更新时间', prop: 'updated_time' },
{ label: '操作', slots: 'table-x', width: 320 }
],
data: [{ id: 1 }, { id: 2 }]
]
}
})
// 刷新
......@@ -53,7 +76,12 @@ function handleUpdate(row: Label) {
}
// 删除
function handleRemove(row: Label) {
ElMessageBox.confirm('确定要删除该标签吗?', '提示').then(() => {})
ElMessageBox.confirm('确定要删除该标签吗?', '提示').then(() => {
deleteLabel({ id: row.id }).then(() => {
ElMessage({ message: '删除成功', type: 'success' })
handleRefresh()
})
})
}
// 查看
let viewVisible = $ref(false)
......@@ -79,6 +107,11 @@ function handleRule(row: Label) {
<el-button type="primary" :icon="Plus" @click="handleAdd">新建</el-button>
</el-space>
</template>
<template #table-status="{ row }: { row: Label }">
<el-tag :type="row.status === '1' ? 'success' : 'danger'">
{{ getNameByValue(row.status, statusList) }}
</el-tag>
</template>
<template #table-x="{ row }">
<el-button type="primary" plain @click="handleRule(row)">规则</el-button>
......@@ -90,7 +123,11 @@ function handleRule(row: Label) {
</div>
</AppCard>
<!-- 新建/修改标签 -->
<LabelFormDialog v-model="formVisible" :data="currentRow" v-if="formVisible"></LabelFormDialog>
<LabelFormDialog
v-model="formVisible"
:data="currentRow"
@update="handleRefresh"
v-if="formVisible"></LabelFormDialog>
<!-- 查看标签 -->
<LabelViewDialog v-model="viewVisible" :data="currentRow" v-if="viewVisible && currentRow"></LabelViewDialog>
<!-- 规则 -->
......
......@@ -6,11 +6,11 @@ export function getTripTemplateList(params: TripTemplateListRequest) {
}
// 创建旅程模板
export function createTripTemplateList(data: TripTemplateCreateRequest) {
export function createTripTemplate(data: TripTemplateCreateRequest) {
return httpRequest.post('/api/lab/v1/experiment/itinerary/create', data)
}
// 更新旅程模板
export function updateTripTemplateList(data: TripTemplateUpdateRequest) {
export function updateTripTemplate(data: TripTemplateUpdateRequest) {
return httpRequest.post('/api/lab/v1/experiment/itinerary/update', data)
}
......@@ -2,7 +2,7 @@
import type { TripTemplate } from '../types'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus'
import { createTripTemplateList, updateTripTemplateList } from '../api'
import { createTripTemplate, updateTripTemplate } from '../api'
import { tripTemplateTypeList } from '@/utils/dictionary'
import { pick } from 'lodash-es'
......@@ -43,7 +43,7 @@ function handleSubmit() {
// 新建
function handleCreate() {
const params = pick(form, ['name', 'type', 'score', 'is_view_answer', 'status'])
createTripTemplateList(params).then(() => {
createTripTemplate(params).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
......@@ -52,7 +52,7 @@ function handleCreate() {
// 修改
function handleUpdate() {
const params = pick(form, ['id', 'name', 'type', 'score', 'is_view_answer', 'status'])
updateTripTemplateList(params).then(() => {
updateTripTemplate(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
......
......@@ -13,9 +13,10 @@ export interface TripTemplate {
updated_operator: Operator
}
export type TripTemplateListRequest = Pick<TripTemplate, 'name' | 'type' | 'status'> & { experiment_id: string }
export type TripTemplateListRequest = Pick<TripTemplate, 'name' | 'type' | 'status'> & { experiment_id?: string }
export type TripTemplateUpdateRequest = Pick<TripTemplate, 'id' | 'name' | 'type' | 'is_view_answer' | 'status'> & {
experiment_id?: string
score: number
}
......
......@@ -13,8 +13,11 @@ const httpRequest = axios.create({
// 请求拦截
httpRequest.interceptors.request.use(
function (config) {
if (config.params) config.params.experiment_id = '7028276368903241728'
if (config.data) config.data.experiment_id = '7028276368903241728'
if (config.method === 'get')
config.params = Object.assign({}, config.params, { experiment_id: '7028276368903241728' })
if (config.method === 'post') config.data = Object.assign({}, config.data, { experiment_id: '7028276368903241728' })
return config
},
function (error) {
......
......@@ -13,6 +13,12 @@ export const tripTemplateTypeList = [
{ label: '固定旅程', value: '2' }
]
// 更新方式
export const updateStatusRuleList = [
{ label: '自动更新', value: '1' },
{ label: '手动更新', value: '2' }
]
export const dateUnitList = [
{ label: '天', value: 1 },
{ label: '周', value: 2 },
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论