Bläddra i källkod

积分规则配置

Xiao_123 1 år sedan
förälder
incheckning
4d73443a42

+ 79 - 0
src/api/menduner/system/integral/index.js

@@ -0,0 +1,79 @@
+import request from '@/config/axios'
+
+// 获取积分规则配置列表
+export const getPointRuleConfigPage = async (params) => {
+  return await request.get({ 
+    url: '/menduner/reward/point-rule-config/page',
+    params
+  })
+}
+
+// 获取积分配置详情
+export const getPointRuleConfigDetails = async (id) => {
+  return await request.get({ 
+    url: `/menduner/reward/point-rule-config/get?id=${id}`
+  })
+}
+
+// 删除积分规则配置
+export const deletePointRuleConfig = async (id) => {
+  return await request.delete({ 
+    url: `/menduner/reward/point-rule-config/delete?id=${id}`
+  })
+}
+
+// 创建积分规则配置
+export const savePointRuleConfig = async (data) => {
+  return await request.post({ 
+    url: '/menduner/reward/point-rule-config/create',
+    data
+  })
+}
+
+// 更新积分规则配置
+export const updatePointRuleConfig = async (data) => {
+  return await request.put({ 
+    url: '/menduner/reward/point-rule-config/update',
+    data
+  })
+}
+
+// 获取事件地址列表
+export const getEventTrackUrlList = async () => {
+  return await request.get({ 
+    url: '/menduner/reward/event-track/get/url/list'
+  })
+}
+
+// 获取操作运算符列表
+export const getOperationList = async () => {
+  return await request.get({ 
+    url: '/menduner/reward/common/get/operation'
+  })
+}
+
+// 获取事件指标列表
+export const getEventIndicatorList = async () => {
+  return await request.get({ 
+    url: '/menduner/reward/common/get/event-indicator'
+  })
+}
+
+// 导出积分规则配置表
+export const pointRuleConfigDownload = async (params) => {
+  return await request.download({ url: `/menduner/reward/point-rule-config/export-excel`, params })
+}
+
+// 关闭规则
+export const closeRoleConfig = async (ids) => {
+  return await request.post({ 
+    url: `/menduner/reward/point-rule-config/disable?ids=${ids}`
+  })
+}
+
+// 开启规则
+export const openRoleConfig = async (ids) => {
+  return await request.post({ 
+    url: `/menduner/reward/point-rule-config/enable?ids=${ids}`
+  })
+}

+ 4 - 2
src/store/modules/dict.ts

@@ -59,7 +59,8 @@ export const useDictStore = defineStore('dict', {
             value: dictData.value,
             label: dictData.label,
             colorType: dictData.colorType,
-            cssClass: dictData.cssClass
+            cssClass: dictData.cssClass,
+            remark: dictData.remark
           })
         })
         this.dictMap = dictDataMap
@@ -89,7 +90,8 @@ export const useDictStore = defineStore('dict', {
           value: dictData.value,
           label: dictData.label,
           colorType: dictData.colorType,
-          cssClass: dictData.cssClass
+          cssClass: dictData.cssClass,
+          remark: dictData.remark
         })
       })
       this.dictMap = dictDataMap

+ 3 - 0
src/utils/dict.ts

@@ -18,6 +18,7 @@ export interface DictDataType {
   value: string | number | boolean
   colorType: ElementPlusInfoType | ''
   cssClass: string
+  remark: string
 }
 
 export interface NumberDictDataType extends DictDataType {
@@ -224,4 +225,6 @@ export enum DICT_TYPE {
   MENDUNER_BUSINESS_STATUS = 'menduner_business_status', // 门墩儿 经营状态
   MENDUNER_FINANCING_STATUS = 'menduner_financing_status', // 门墩儿 融资状态
   MENDUNER_SCALE = 'menduner_scale', // 门墩儿 企业规模
+  MENDUNER_POINT_RULE_CONFIG_TYPE = 'menduner_point_rule_config_type',
+  MENDUNER_POINT_RULE_CONFIG_STATUS = 'menduner_point_rule_config_status'
 }

+ 22 - 0
src/views/menduner/reward/integral/check.js

@@ -0,0 +1,22 @@
+export function checkObjectValues(obj) {
+  // 遍历对象的每个属性
+  for (let key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      // 检查键的值是否存在且不为空
+      if (obj[key] === undefined || obj[key] === null || obj[key] === '') {
+        return false // 如果发现空值,返回false
+      }
+      // 如果当前属性是children且为数组,则递归检查children中的每个对象
+      if (key === 'children' && Array.isArray(obj[key])) {
+        for (let child of obj[key]) {
+          // 递归调用checkObjectValues函数
+          if (!checkObjectValues(child)) {
+            return false // 如果children中的对象有问题,返回false
+          }
+        }
+      }
+    }
+  }
+  // 如果没有发现任何问题,返回true
+  return true
+}

+ 239 - 0
src/views/menduner/reward/integral/condition.vue

@@ -0,0 +1,239 @@
+<template>
+  <div class="condition-box">
+    <div :class="{'parent': showParentBorder}">
+      <div v-for="(val, i) in list" :key="i" class="item">
+        <el-row :gutter="10" v-if="!val.children.length">
+          <el-col :span="6">
+            <el-select v-model="val.key" filterable placeholder="请选择事件指标">
+              <el-option v-for="item in eventIndicator" :key="item.value" :label="item.name" :value="item.value"/>
+            </el-select>
+          </el-col>
+          <el-col :span="6">
+            <el-select v-model="val.operation" filterable placeholder="请选择运算规则">
+              <el-option v-for="item in operator" :key="item.value" :label="item.remark" :value="item.operation"/>
+            </el-select>
+          </el-col>
+          <el-col :span="6">
+            <el-input v-model="val.value" clearable placeholder="请输入数值" />
+          </el-col>
+          <el-col :span="6">
+            <el-button text circle @click="handleDelete(i)">
+              <Icon icon="ep:close" />
+            </el-button>
+            <el-button v-if="list.length >= 2" @click="handleItemAdd(i)" text><Icon class="mr-5px" icon="ep:plus" />并且满足</el-button>
+          </el-col>
+        </el-row>
+        <template v-else>
+          <div class="parent">
+            <div v-for="(_val, index) in val.children" :key="index" class="item">
+              <el-row :gutter="10">
+                <el-col :span="6">
+                  <el-select v-model="_val.key" filterable placeholder="请选择事件指标">
+                    <el-option v-for="item in eventIndicator" :key="item.value" :label="item.name" :value="item.value"/>
+                  </el-select>
+                </el-col>
+                <el-col :span="6">
+                  <el-select v-model="_val.operation" filterable placeholder="请选择运算规则">
+                    <el-option v-for="item in operator" :key="item.value" :label="item.remark" :value="item.operation"/>
+                  </el-select>
+                </el-col>
+                <el-col :span="6">
+                  <el-input v-model="_val.value" clearable placeholder="请输入数值" />
+                </el-col>
+                <el-col :span="6">
+                  <el-button text circle @click="handleDelete(index, val.children, i)">
+                    <Icon icon="ep:close" />
+                  </el-button>
+                  <el-button v-if="index === 0" @click="handleItemAdd(index, val.children)" text><Icon class="mr-5px" icon="ep:plus" />并且满足</el-button>
+                </el-col>
+              </el-row>
+              <div class="relation">
+                <div :class="['relation-item', {'active': k.active}]" v-for="k in val.relationList" :key="k.value" @click="handleActive(k, val.relationList, val)">{{ k.text }}</div>
+              </div>
+            </div>
+          </div>
+        </template>
+      </div>
+      <div v-if="list.length >= 2" class="relation">
+        <div :class="['relation-item', {'active': k.active}]" v-for="k in relationList" :key="k.value" @click="handleActive(k)">{{ k.text }}</div>
+      </div>
+    </div>
+    <el-button text type="primary" @click="handleAdd"><Icon class="mr-5px" icon="ep:plus" />筛选条件</el-button>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'Condition'})
+import { cloneDeep } from 'lodash-es'
+import { checkObjectValues } from './check'
+import { getOperationList, getEventIndicatorList } from '@/api/menduner/system/integral'
+
+const emit = defineEmits(['submit'])
+const props = defineProps({
+  itemData: Object
+})
+
+const message = useMessage() // 消息弹窗
+const query = ref({
+  operation: 'AND',
+  type: 'RELATION',
+  children: []
+})
+
+const list = ref([
+  { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
+])
+
+const showParentBorder = computed(() => {
+  return (list.value && list.value.length === 1 && list.value[0].children.length) ? false : true
+})
+
+const relationList = ref([
+  { text: '且', active: true, value: 'AND' },
+  { text: '或', active: false, value: 'OR' }
+])
+
+
+// 获取运算符列表、事件指标列表
+const operator = ref([])
+const eventIndicator = ref([])
+const getData = async () => {
+  operator.value = await getOperationList()
+  eventIndicator.value = await getEventIndicatorList()
+}
+getData()
+
+// 添加筛选条件
+const handleAdd = () => {
+  list.value.push({ key: '', operation: '', type: 'EXPRESSION', value: '', children: [] })
+}
+
+// 删除筛选条件
+const handleDelete = (index, arr, parentIndex) => {
+  if (arr && arr.length) {
+    // 当children长度为2时变回一级
+    if (arr.length === 2) {
+      list.value[parentIndex] = { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
+      return
+    }
+    arr.splice(index, 1)
+    return
+  }
+  if (list.value.length === 1) return message.warning('最少保留一个触发条件')
+  list.value.splice(index, 1)
+}
+
+// 选择且或关系
+const handleActive = (k, arr, parentVal) => {
+  if (arr && arr.length) {
+    arr.forEach(e => e.active = false)
+    k.active = true
+    parentVal.operation = k.value
+    return
+  }
+  relationList.value.forEach(e => e.active = false)
+  k.active = true
+  query.value.operation = k.value
+}
+
+// 并且满足
+const handleItemAdd = (i, arr) => {
+  const obj = { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
+  const item = {
+    type: 'RELATION',
+    operation: 'AND',
+    relationList: cloneDeep(relationList.value),
+    children: [cloneDeep(obj), cloneDeep(obj)]
+  }
+  if (arr && arr.length) return arr.push(cloneDeep(obj))
+  list.value.splice(i, 1, item)
+}
+
+// 编辑回显
+watch(
+  () => props.itemData,
+  (newVal) => {
+    if (!newVal) return
+    const data = cloneDeep(newVal)
+    if (data.children && !data.children.length) {
+      list.value = [data]
+    } else {
+      list.value = data.children.map(e => {
+        if (e.type === 'RELATION') {
+          e.relationList = cloneDeep(relationList.value)
+          e.relationList.forEach(e => e.active = false)
+          const obj = e.relationList.find(j => j.value === e.operation)
+          if (obj) obj.active = true
+        }
+        return e
+      })
+      query.value = data
+      relationList.value.forEach(e => {
+        e.active = false
+        if (e.value === data.operation) e.active = true
+      })
+    }
+  },
+  { deep: true }
+)
+
+const result = {}
+const getQuery = () => {
+  // const check = list.value.every(e => checkObjectValues(e))
+  // if (!check) return message.warning('请将条件中的项填写完整')
+
+  if (list.value.length === 1) result.value = list.value[0]
+  else result.value = { ...query.value, children: list.value }
+  return result.value
+}
+
+defineExpose({
+  getQuery
+})
+</script>
+
+<style scoped lang="scss">
+.el-row {
+  width: 100%;
+}
+
+.condition-box {
+  padding: 20px;
+  margin-bottom: 20px;
+  // margin-left: 120px !important;
+  border: 1px solid #ccc;
+}
+
+.text-end {
+  text-align: end;
+}
+
+.parent {
+  position: relative;
+  padding-left: 50px;
+  border-left: 1px solid #ccc;
+
+  .relation {
+    position: absolute;
+    top: 50%;
+    left: -12px;
+    font-size: 14px;
+    color: #666;
+    background-color: #eee;
+    transform: translateY(-50%);
+
+    .relation-item {
+      padding: 3px;
+    }
+
+    .active {
+      color: #fff;
+      background-color: #409eff;
+    }
+  }
+}
+
+.item {
+  margin-bottom: 20px;
+}
+</style>

+ 197 - 0
src/views/menduner/reward/integral/index.vue

@@ -0,0 +1,197 @@
+<template>
+  <ContentWrap>
+    <el-form
+      ref="queryFormRef"
+      :inline="true"
+      :model="queryParams"
+      class="-mb-15px"
+      label-width="100px"
+    >
+      <el-form-item label="规则名称" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          class="!w-240px"
+          clearable
+          placeholder="请输入规则名称"
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          class="!w-240px"
+          clearable
+          placeholder="请选择状态"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_POINT_RULE_CONFIG_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery">
+          <Icon class="mr-5px" icon="ep:search" />
+          搜索
+        </el-button>
+        <el-button @click="resetQuery">
+          <Icon class="mr-5px" icon="ep:refresh" />
+          重置
+        </el-button>
+        <el-button
+          v-hasPermi="['system:integral:create']"
+          plain
+          type="primary"
+          @click="openForm('create')"
+        >
+          <Icon class="mr-5px" icon="ep:plus" />
+          新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['menduner:system:major:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <ContentWrap>
+    <el-table
+      v-loading="loading"
+      :data="items"
+      row-key="id"
+    >
+      <el-table-column :show-overflow-tooltip="true" label="规则名称" prop="title"/>
+      <el-table-column :show-overflow-tooltip="true" label="事件地址" prop="url"/>
+      <el-table-column label="规则类型" prop="type">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.MENDUNER_POINT_RULE_CONFIG_TYPE" :value="scope.row.type" />
+        </template>
+      </el-table-column>
+      <el-table-column label="积分处理" prop="operation">
+        <template #default="scope">
+          <span>{{ scope.row.operation === '+' ? '递增' : '递减' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="积分数量" prop="point"/>
+      <el-table-column :show-overflow-tooltip="true" label="创建时间" prop="createTime" :formatter="dateFormatter"/>
+      <el-table-column label="状态" prop="status" width="80">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.MENDUNER_POINT_RULE_CONFIG_STATUS" :value="scope.row.status" />
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="操作">
+        <template #default="scope">
+          <el-button v-if="scope.row.status === '1'" link type="success" @click="handleAction(scope.row.id, 1)">开启</el-button>
+          <el-button v-else link type="warning" @click="handleAction(scope.row.id, 0)">关闭</el-button>
+          <el-button v-hasPermi="['system:integral:update']" link type="primary" @click="openForm('update', scope.row.id)">修改</el-button>
+          <el-button v-hasPermi="['system:integral:delete']" link type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <SavePage ref="formRef" @success="getList" />
+</template>
+
+<script setup>
+defineOptions({ name: 'Integral' })
+import SavePage from './save.vue'
+import download from '@/utils/download'
+import { dateFormatter } from '@/utils/formatTime'
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import { getPointRuleConfigPage, deletePointRuleConfig, pointRuleConfigDownload, closeRoleConfig, openRoleConfig } from '@/api/menduner/system/integral'
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const total = ref(0)
+const queryFormRef = ref()
+const queryParams = reactive({
+  title: null,
+  status: null,
+  pageNo: 1,
+  pageSize: 10
+})
+const exportLoading = ref(false)
+const loading = ref(false)
+const items = ref([])
+
+const getList = async () => {
+  const { list, total: number } = await getPointRuleConfigPage(queryParams)
+  items.value = list
+  total.value = number
+}
+getList()
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type, id) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id) => {
+  try {
+    await message.delConfirm()
+    await deletePointRuleConfig(id)
+    message.success(t('common.delSuccess'))
+    getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await pointRuleConfigDownload(queryParams)
+    download.excel(data, '积分规则配置表.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+/** 开启、关闭按钮操作 */
+const handleAction = async (id, type) => {
+  try {
+    await message.delConfirm(`是否${type ? '开启' : '关闭'}所选中数据?`)
+    if (type) {
+      await openRoleConfig([id])
+    } else {
+      await closeRoleConfig([id])
+    }
+    message.success(t('common.updateSuccess'))
+    getList()
+  } catch {
+  } finally {
+  }
+}
+</script>

+ 188 - 0
src/views/menduner/reward/integral/save.vue

@@ -0,0 +1,188 @@
+<template>
+  <Dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="120px"
+      v-loading="formLoading"
+    >
+      <el-steps direction="vertical" :active="0" finish-status="success">
+        <el-step title="基本信息">
+          <template #description>
+            <div class="desc-text">请填写基本信息</div>
+            <el-form-item label="规则名称" prop="title">
+              <el-input v-model="formData.title" clearable placeholder="请输入规则名称" />
+            </el-form-item>
+            <el-form-item label="选择事件地址" prop="url">
+              <el-cascader 
+                v-model="formData.url"
+                placeholder="请输入要搜索的url地址"
+                :options="eventUrlList"
+                filterable
+                clearable
+                :props="{ label: 'operation', value: 'url' }"
+              />
+            </el-form-item>
+            <el-form-item label="规则类型" prop="type">
+              <el-radio-group v-model="formData.type">
+                <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_POINT_RULE_CONFIG_TYPE)" :key="dict.value" :value="dict.value">
+                  {{ dict.label }}
+                  <Tooltip :message="dict.remark"/>
+                </el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="状态" prop="status">
+              <el-radio-group v-model="formData.status">
+                <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.MENDUNER_POINT_RULE_CONFIG_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </template>
+        </el-step>
+        <el-step title="触发条件">
+          <template #description>
+            <div class="desc-text">请设置触发条件</div>
+            <ConditionPage ref="conditionRef" :itemData="formData.triggerRule" />
+          </template>
+        </el-step>
+        <el-step title="积分设置">
+          <template #description>
+            <div class="desc-text">请填写积分设置</div>
+            <el-form-item label="积分处理" prop="operation">
+              <el-radio-group v-model="formData.operation">
+                <el-radio :value="'+'">递增</el-radio>
+                <el-radio :value="'-'">递减</el-radio>
+              </el-radio-group>
+            </el-form-item>
+            <el-form-item label="积分数量" prop="point">
+              <el-input-number v-model="formData.point" :min="1" :max="1000"/>
+            </el-form-item>
+          </template>
+        </el-step>
+      </el-steps>
+    </el-form>
+    <template #footer>
+      <el-button type="primary" @click="submitForm" :disabled="formLoading">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script setup>
+defineOptions({ name: 'SaveForm'})
+import ConditionPage from './condition.vue'
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import { getEventTrackUrlList, savePointRuleConfig, getPointRuleConfigDetails, updatePointRuleConfig } from '@/api/menduner/system/integral'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+const dialogVisible = ref(false)
+const formLoading = ref(false)
+const dialogTitle = ref('')
+const formType = ref('')
+const formData = ref({
+  title: '',
+  url: '',
+  status: 0,
+  type: 0,
+  operation: '+',
+  point: 100
+})
+
+const formRules = reactive({
+  title: [{ required: true, message: '规则名称不能为空', trigger: 'blur' }],
+  url: [{ required: true, message: '事件地址不能为空', trigger: 'blur' }],
+  status: [{ required: true, message: '事件状态不能为空', trigger: 'blur' }],
+  type: [{ required: true, message: '规则类型不能为空', trigger: 'blur' }],
+  operation: [{ required: true, message: '积分处理不能为空', trigger: 'blur' }],
+  point: [{ required: true, message: '积分数量不能为空', trigger: 'blur' }],
+})
+const eventUrlList = ref([])
+const formRef = ref() // 表单 Ref
+const conditionRef = ref()
+
+// 获取事件地址列表
+const getEventUrlList = async () => {
+  const data = await getEventTrackUrlList()
+  eventUrlList.value = data.map(e => {
+    const children = e.children.map(k => {
+      return { operation: k.name, url: k.name, children: k.children }
+    })
+    return { operation: e.name, url: e.name, children }
+  })
+}
+
+/** 打开弹窗 */
+const open = async (type, id) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 获取事件地址列表
+  getEventUrlList()
+
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await getPointRuleConfigDetails(id)
+      formData.value.status = Number(formData.value.status)
+      formData.value.type = Number(formData.value.type)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+const emit = defineEmits(['success'])
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    title: '',
+    url: '',
+    status: 0,
+    type: 0,
+    operation: '+',
+    point: 100
+  }
+  formRef.value?.resetFields()
+}
+
+// 提交
+const submitForm = async () => {
+  await formRef.value.validate()
+  formLoading.value = true
+  const query = {
+    constraintRule: null
+  }
+  for (let i in formData.value) {
+    if (i === 'url') query[i] = Array.isArray(formData.value[i]) ? formData.value[i][formData.value[i].length - 1] : formData.value[i]
+    else query[i] = formData.value[i]
+  }
+  const data = conditionRef.value.getQuery()
+  if (!data) return
+  if (Object.keys(data).length) query.triggerRule = data
+
+  try {
+    if (formType.value === 'create') {
+      await savePointRuleConfig(query)
+      message.success(t('common.createSuccess'))
+    } else {
+      await updatePointRuleConfig(query)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.desc-text {
+  margin-bottom: 20px;
+  color: #a8abb2;
+}
+</style>