seatonwan9
2025-08-15 c92b723d893bddd1cf9093e660806b226dc00921
提交源码
7个文件已修改
943 ■■■■ 已修改文件
src/api/pointsApi.ts 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/modules/pointsManage.ts 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/points.d.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pointsManage/personal/index.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pointsManage/ruleList/index.vue 252 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pointsManage/settings/index.vue 531 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/pointsManage/unit/index.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pointsApi.ts
@@ -5,7 +5,7 @@
const pointsApi = {
  // 积分规则设置相关接口
  // 获取积分规则配置
  getPointsRules(data?: object): ApiPromise {
  getPointsRules(data: object): ApiPromise {
    return createAxios({
      url: `${url}main/page`,
      data: data,
@@ -13,14 +13,14 @@
  },
  // 根据ID获取积分规则
  getPointsRuleById(data?: object): ApiPromise {
  getPointsRuleById(data: URLSearchParams): ApiPromise {
    return createAxios({
      url: `${url}rule/list`,
      method: 'post',
      data: data,
      headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
     data:data,
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }) as ApiPromise
  },
@@ -34,9 +34,9 @@
  // 个人积分相关接口
  // 获取个人积分统计
  getPersonalPointsStats(): ApiPromise {
  getPersonalPointsStats(userId: number): ApiPromise {
    return createAxios({
      url: `${url}personal/stats`,
      url: `${url}/total/user/` + userId,
      method: 'get',
    }) as ApiPromise
  },
@@ -44,7 +44,7 @@
  // 获取个人积分流水
  getPersonalPointsFlow(data: object): ApiPromise {
    return createAxios({
      url: `${url}personal/flow`,
      url: `${url}flow/personal/page`,
      data: data,
    }) as ApiPromise
  },
@@ -81,6 +81,14 @@
      data,
    }) as ApiPromise
  },
  // 获取积分流水数据类目列表
  getPointsFlowCategories(): ApiPromise {
    return createAxios({
      url: `${url}flow/categories`,
      method: 'get',
    }) as ApiPromise
  },
}
export default pointsApi
src/router/modules/pointsManage.ts
@@ -12,6 +12,15 @@
      },
    },
    {
      path: 'ruleDetail',
      name: 'pointsRuleDetail',
      component: () => import('@/views/pointsManage/ruleDetail/index.vue'),
      meta: {
        title: '积分规则详情',
        keepAlive: false,
      },
    },
    {
      path: 'settings',
      name: 'pointsSettings',
      component: () => import('@/views/pointsManage/settings/index.vue'),
src/types/points.d.ts
@@ -44,6 +44,7 @@
// 查询参数接口
export interface PointsQueryParams {
  userId?: string // 用户ID
  dateRange?: string // 日期范围
  dataCategory?: string // 数据类目
  dataType?: string // 数据类型
@@ -54,4 +55,6 @@
  day?: string // 日期
  pageNum?: number // 页码
  pageSize?: number // 每页大小
  flowStartTime?: string // 流水开始时间
  flowEndTime?: string // 流水结束时间
}
src/views/pointsManage/personal/index.vue
@@ -58,24 +58,25 @@
              <span class="filter-label">数据类目:</span>
              <el-select v-model="queryParams.dataCategory" placeholder="全部" clearable>
                <el-option label="全部" value="" />
                <el-option label="资源贡献" value="resource_contribution" />
                <el-option label="资源交易" value="resource_transaction" />
                <el-option label="资源传播" value="resource_dissemination" />
                <el-option label="用户参与" value="user_participation" />
                <el-option label="积分转换" value="points_conversion" />
                <el-option label="其他" value="other" />
                <el-option
                  v-for="category in categoryList"
                  :key="category"
                  :label="getCategoryLabel(category)"
                  :value="category"
                />
              </el-select>
            </div>
            <div class="filter-item">
              <span class="filter-label">时间:</span>
              <el-date-picker
                v-model="dateRange"
                type="daterange"
                type="datetimerange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                format="YYYY-MM-DD HH:mm:ss"
                  date-format="YYYY-MM-DD"
                  time-format="HH:mm:ss"
                @change="handleDateChange"
              />
            </div>
@@ -83,9 +84,8 @@
              <span class="filter-label">数据类型:</span>
              <el-select v-model="queryParams.dataType" placeholder="全部" clearable>
                <el-option label="全部" value="" />
                <el-option label="获取" value="earned" />
                <el-option label="消耗" value="consumed" />
                <el-option label="转换" value="converted" />
                <el-option label="获取" value="0" />
                <el-option label="消耗" value="1" />
              </el-select>
            </div>
          </div>
@@ -110,9 +110,9 @@
                <span>{{ getCategoryLabel(row.dataCategory) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="name" label="名称" min-width="300" show-overflow-tooltip />
            <el-table-column prop="flowTime" label="时间" width="180" align="center" />
            <el-table-column prop="points" label="积分" width="100" align="center">
            <el-table-column prop="name" label="名称"  show-overflow-tooltip />
            <el-table-column prop="flowTime" label="时间"  align="center" />
            <el-table-column prop="points" label="积分"  align="center">
              <template #default="{ row }">
                <span :class="row.points > 0 ? 'points-earned' : 'points-consumed'">
                  {{ row.points > 0 ? '+' : '' }}{{ row.points }}
@@ -144,7 +144,7 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { dayjs, ElMessage } from 'element-plus'
import { 
  ArrowLeft, 
  Refresh, 
@@ -160,18 +160,17 @@
// 积分统计
const stats = ref<PointsStats>({
  balance: 20000,
  totalEarned: 10000,
  totalConsumed: 200,
  balance: 0,
  totalEarned: 0,
  totalConsumed: 0,
  totalConverted: 0,
})
// 查询参数
const queryParams = reactive<PointsQueryParams>({
  userId: '1',
  dataCategory: '',
  dataType: '',
  startTime: '',
  endTime: '',
  pageNum: 1,
  pageSize: 10,
})
@@ -184,6 +183,9 @@
// 总数
const total = ref(0)
// 数据类目列表
const categoryList = ref<string[]>([])
// 格式化数字
const formatNumber = (num: number) => {
@@ -206,12 +208,25 @@
// 获取积分统计
const getPointsStats = async () => {
  try {
    const res = await pointsApi.getPersonalPointsStats()
    const userId = 1;
    const res = await pointsApi.getPersonalPointsStats(userId)
    if (res.code === 200 && res.data) {
      stats.value = res.data
    }
  } catch (error) {
    console.error('获取积分统计失败:', error)
  }
}
// 获取数据类目列表
const getCategoryList = async () => {
  try {
    const res = await pointsApi.getPointsFlowCategories()
    if (res.code === 200 && res.data) {
      categoryList.value = res.data
    }
  } catch (error) {
    console.error('获取数据类目失败:', error)
  }
}
@@ -238,8 +253,8 @@
const resetQuery = () => {
  queryParams.dataCategory = ''
  queryParams.dataType = ''
  queryParams.startTime = ''
  queryParams.endTime = ''
  queryParams.flowStartTime = ''
  queryParams.flowEndTime = ''
  dateRange.value = null
  queryParams.pageNum = 1
  queryData()
@@ -248,11 +263,11 @@
// 处理日期变化
const handleDateChange = (dates: [string, string] | null) => {
  if (dates) {
    queryParams.startTime = dates[0]
    queryParams.endTime = dates[1]
    queryParams.flowStartTime = dayjs(dates[0]).format('YYYY-MM-DD HH:mm:ss');
    queryParams.flowEndTime = dayjs(dates[1]).format('YYYY-MM-DD HH:mm:ss');
  } else {
    queryParams.startTime = ''
    queryParams.endTime = ''
    queryParams.flowStartTime = ''
    queryParams.flowEndTime = ''
  }
}
@@ -288,6 +303,7 @@
onMounted(() => {
  getPointsStats()
  getPointsFlow()
  getCategoryList()
})
</script>
src/views/pointsManage/ruleList/index.vue
@@ -1,81 +1,100 @@
<template>
  <div class="points-rule-list">
    <!-- 页面标题 -->
    <div class="page-title">积分规则管理</div>
    <!-- 列表页面 -->
    <div v-if="currentView === 'list'">
      <!-- 页面标题 -->
      <div class="page-title">积分规则管理</div>
    <!-- 规则列表卡片 -->
    <el-card shadow="never" class="rule-list-card">
      <!-- 筛选条件 -->
      <div class="filter-section">
        <div class="filter-row">
          <div class="filter-item">
            <span class="filter-label">生效时间:</span>
            <el-date-picker
                v-model="queryParams.dateRange"
                type="datetimerange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
      <!-- 规则列表卡片 -->
      <el-card shadow="never" class="rule-list-card">
        <!-- 筛选条件 -->
        <div class="filter-section">
          <div class="filter-row">
            <div class="filter-item">
              <span class="filter-label">生效时间:</span>
              <el-date-picker
                  v-model="queryParams.dateRange"
                  type="datetimerange"
                  range-separator="至"
                  start-placeholder="开始日期"
                  end-placeholder="结束日期"
                  format="YYYY-MM-DD HH:mm:ss"
                  date-format="YYYY-MM-DD"
                  time-format="HH:mm:ss"
                style="margin-left: 8px;"
                @change="handleDateChange"
              />
          </div>
        </div>
        <div class="filter-actions">
          <el-button type="primary" @click="queryData">
            <el-icon><Search /></el-icon>
            查询
          </el-button>
          <el-button @click="resetQuery">
            <el-icon><Refresh /></el-icon>
            重置
          </el-button>
        </div>
      </div>
                  style="margin-left: 8px;"
                  @change="handleDateChange"
                />
            </div>
      <!-- 规则表格 -->
      <div class="table-section">
        <el-table :data="ruleList" stripe style="width: 100%">
          <el-table-column prop="id" label="序号" width="80" align="center" />
          <el-table-column prop="pointsName" label="名称"  align="ceter">
            <template #default="{ row }">
                 {{ row.pointsName}}{{ row.updatedAt}}V{{ row.version }}
            </template>
          </el-table-column>
          <el-table-column prop="effectiveStart" label="开始生效时间"   align="center" />
          <el-table-column prop="modifierName" label="修改人"  align="center" />
          <el-table-column label="操作"  align="center" fixed="right">
            <template #default="{ row }">
              <el-button type="primary" size="small" @click="editRule(row)">查看</el-button>
              <el-button type="primary" size="small" @click="editRule(row)">编辑</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <div class="pagination-section">
          <div class="pagination-info">
            共{{ total }}条
          </div>
          <el-pagination
            v-model:current-page="queryParams.pageNum"
            v-model:page-size="queryParams.pageSize"
            :page-sizes="[10, 20, 50, 100]"
            :total="total"
            layout="sizes, prev, pager, next, jumper"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
          />
          <div class="filter-actions">
            <el-button type="primary" @click="queryData">
              <el-icon><Search /></el-icon>
              查询
            </el-button>
            <el-button @click="resetQuery">
              <el-icon><Refresh /></el-icon>
              重置
            </el-button>
          </div>
        </div>
      </div>
    </el-card>
        <!-- 规则表格 -->
        <div class="table-section">
          <el-table :data="ruleList" stripe style="width: 100%">
            <el-table-column type="index" label="序号" width="80" align="center" />
            <el-table-column prop="pointsName" label="名称"  align="ceter">
              <template #default="{ row }">
                   {{ row.pointsName}}{{ dayjs(row.updatedAt).format('YYYYMMDD')}}V{{ row.version }}
              </template>
            </el-table-column>
            <el-table-column prop="effectiveStart" label="开始生效时间"   align="center" />
            <el-table-column prop="modifierName" label="修改人"  align="center" />
            <el-table-column label="操作"  align="center" fixed="right">
              <template #default="{ row }">
                <el-button type="primary" size="small" @click="viewRule(row)">查看</el-button>
                <el-button type="primary" size="small" @click="editRule(row)">编辑</el-button>
              </template>
            </el-table-column>
          </el-table>
          <!-- 分页 -->
          <div class="pagination-section">
            <div class="pagination-info">
              共{{ total }}条
            </div>
            <el-pagination
              v-model:current-page="queryParams.pageNum"
              v-model:page-size="queryParams.pageSize"
              :page-sizes="[10, 20, 50, 100]"
              :total="total"
              layout="sizes, prev, pager, next, jumper"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
            />
          </div>
        </div>
      </el-card>
    </div>
    <!-- 编辑页面 -->
    <div v-if="currentView === 'edit'" class="edit-container">
      <SettingsComponent
        :ruleId="currentRuleId"
        @goBack="goBackToList"
        @saveSuccess="handleSaveSuccess"
      />
    </div>
    <!-- 查看详情页面 -->
    <div v-if="currentView === 'view'" class="view-container">
      <RuleDetailComponent
        :ruleId="currentRuleId"
        @goBack="goBackToList"
      />
    </div>
  </div>
</template>
@@ -85,14 +104,14 @@
import { Search, Refresh } from '@element-plus/icons-vue'
import pointsApi from '@/api/pointsApi'
import type { PointsRule, PointsQueryParams } from '@/types/points'
// 导入路由钩子
import { useRouter } from 'vue-router'
import SettingsComponent from '../settings/index.vue'
import RuleDetailComponent from '../ruleDetail/index.vue'
// 当前视图状态:'list' | 'edit' | 'view'
const currentView = ref<'list' | 'edit' | 'view'>('list')
// 查询参数
const queryParams = reactive<PointsQueryParams>({
 // ruleType: '',
 // category: '',
 // status: '',
  dateRange: '',
  pageNum: 1,
  pageSize: 10,
@@ -103,6 +122,9 @@
// 总数
const total = ref(0)
// 当前选中的规则ID
const currentRuleId = ref<string>('')
// 页面加载时获取数据
onMounted(() => {
@@ -144,65 +166,41 @@
  queryData()
}
// 获取规则类型标签
const getRuleTypeLabel = (type: string) => {
  const typeMap: Record<string, string> = {
    acquisition: '获取',
    consumption: '消耗',
    conversion: '转换',
  }
  return typeMap[type] || type
}
// 获取分类标签
const getCategoryLabel = (category: string) => {
  const categoryMap: Record<string, string> = {
    resource_contribution: '资源贡献',
    resource_transaction: '资源交易',
    resource_dissemination: '资源传播',
    user_participation: '用户参与',
    other: '其他',
  }
  return categoryMap[category] || category
}
// 处理状态变化
const handleStatusChange = async (row: PointsRule) => {
  try {
    await pointsApi.savePointsRules({
      id: row.id,
      status: row.status
    })
    ElMessage.success('状态更新成功')
  } catch (error) {
    ElMessage.error('状态更新失败')
    // 恢复原来的状态
    row.status = row.status === 1 ? 0 : 1
    console.error('更新规则状态失败:', error)
  }
}
// 处理日期变化
const handleDateChange = (dates: [string, string] | null) => {
  if (dates) {
    queryParams.effectiveStartTime = dates[0]
    queryParams.effectiveEndTime = dates[1]
    queryParams.effectiveStartTime = dayjs(dates[0]).format('YYYY-MM-DD HH:mm:ss');
    queryParams.effectiveEndTime = dayjs(dates[1]).format('YYYY-MM-DD HH:mm:ss');
  } else {
    queryParams.effectiveStartTime = ''
    queryParams.effectiveEndTime = ''
  }
}
// 创建路由实例
const router = useRouter()
// 编辑规则
const editRule = (row: PointsRule) => {
  // 跳转到规则设置界面,并传入规则id
  router.push({
    path: '/points/settings',
    query: { ruleId: row.id }
  })
  currentRuleId.value = row.id?.toString() || ''
  currentView.value = 'edit'
}
// 查看规则
const viewRule = (row: PointsRule) => {
  currentRuleId.value = row.id?.toString() || ''
  currentView.value = 'view'
}
// 返回列表页面
const goBackToList = () => {
  currentView.value = 'list'
  currentRuleId.value = ''
}
// 处理保存成功
const handleSaveSuccess = () => {
  ElMessage.success('保存成功')
  goBackToList()
  // 重新加载列表数据
  queryData()
}
</script>
@@ -265,5 +263,11 @@
      }
    }
  }
  .edit-container,
  .view-container {
    // 确保组件能够正确显示
    width: 100%;
  }
}
</style>
</style>
src/views/pointsManage/settings/index.vue
@@ -9,26 +9,26 @@
              <span class="section-title">积分获取规则</span>
            </div>
          </template>
          <!-- 资源贡献 -->
          <div class="rule-category" v-for="rule in rules.getPointsRuleList">
            <h4>{{ rule.category}}</h4>
            <div class="rule-subcategory">
              <!-- <h5>提报标杆</h5> -->
              <div class="rule-items">
              <div class="rule-item" v-for="pointRuleDetial in rule.pointsRules">
                <span class="rule-desc">{{ pointRuleDetial.ruleName }} : {{ pointRuleDetial.ruleDescription}} </span>
                <el-input
                  v-model="rules.benchmarkSubmission"
                <el-input
                  v-model="pointRuleDetial.pointsValue"
                  size="small"
                  style="width: 80px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
                <span class="unit" v-if="pointRuleDetial.isLimit === 1">,每日积分上限</span>
                <el-input
                  v-model="rules.productSubscribedDailyLimit"
                <el-input
                  v-model="pointRuleDetial.dailyLimit"
                  size="small"
                  style="width: 80px;"
                  placeholder="请输入"
@@ -42,8 +42,8 @@
              <div class="rule-items">
                <div class="rule-item">
                <span class="rule-desc">每提报1个知识,并审批完成,获</span>
                <el-input
                  v-model="rules.knowledgeSubmission"
                <el-input
                  v-model="rules.knowledgeSubmission"
                  size="small"
                  style="width: 80px;"
                  placeholder="请输入"
@@ -57,8 +57,8 @@
              <div class="rule-items">
              <div class="rule-item">
                <span class="rule-desc">每提报1个产品,并审批完成,获</span>
                <el-input
                  v-model="rules.productSubmission"
                <el-input
                  v-model="rules.productSubmission"
                  size="small"
                  style="width: 80px;"
                  placeholder="请输入"
@@ -67,7 +67,7 @@
              </div>
            </div>
            </div> -->
          </div>
          <!-- 资源交易 -->
@@ -78,8 +78,8 @@
              <div class="rule-items">
                <div class="rule-item">
                <span class="rule-desc">每接入1个产品,获</span>
                <el-input
                  v-model="rules.productAccess"
                <el-input
                  v-model="rules.productAccess"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
@@ -93,8 +93,8 @@
              <div class="rule-items">
              <div class="rule-item">
                <span class="rule-desc">每交易1个资源,获</span>
                <el-input
                  v-model="rules.resourceTransaction"
                <el-input
                  v-model="rules.resourceTransaction"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
@@ -117,228 +117,166 @@
              <span class="section-title">积分消耗规则</span>
            </div>
          </template>
          <!-- 资源传播 -->
          <div class="rule-category">
            <h4>资源传播</h4>
          <div class="rule-category" v-for="consumeRule in rules.consumePointsRuleList">
            <h4>{{ consumeRule.category }}</h4>
            <div class="rule-subcategory">
              <h5>数字资源</h5>
<!--              <h5>数字资源</h5>-->
            <div class="rule-items">
              <div class="rule-item">
                <span class="rule-desc">提报产品被取消收藏,扣除</span>
                <el-input
                  v-model="rules.productUnfavorited"
              <div class="rule-item" v-for="pointRuleDetials in consumeRule.pointsRules">
                <span class="rule-desc">{{ pointRuleDetials.ruleName }} : {{ pointRuleDetials.ruleDescription}}</span>
                <el-input
                  v-model="pointRuleDetials.pointsValue"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
              <div class="rule-item">
                <span class="rule-desc">提报产品被取消点赞,扣除</span>
                <el-input
                  v-model="rules.productUnliked"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
            </div>
            </div>
            <div class="rule-subcategory">
              <h5>产品订阅</h5>
            <div class="rule-items">
              <div class="rule-item">
                <span class="rule-desc">提报产品被取消订阅,扣除</span>
                <el-input
                  v-model="rules.productUnfavorited"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
              <div class="rule-item">
                <span class="rule-desc">提报产品被取消试用,扣除</span>
                <el-input
                  v-model="rules.productUnliked"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
            </div>
            </div>
            <div class="rule-subcategory">
              <h5>交流社区</h5>
            <div class="rule-items">
              <div class="rule-item">
                <span class="rule-desc">删除提问,扣除</span>
                <el-input
                  v-model="rules.productUnfavorited"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
              <div class="rule-item">
                <span class="rule-desc">删除评论,扣除</span>
                <el-input
                  v-model="rules.productUnliked"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
              </div>
              <div class="rule-item">
                <span class="rule-desc">评论被取消点赞,扣除</span>
                <el-input
                  v-model="rules.productUnliked"
                  size="small"
                  style="width: 60px;"
                  placeholder="请输入"
                />
                <span class="unit">积分</span>
                <span class="unit" v-if="pointRuleDetials.isLimit === 1">,每日积分上限</span>
                  <el-input
                          v-model="pointRuleDetials.dailyLimit"
                          size="small"
                          style="width: 80px;"
                          placeholder="请输入"
                          v-if="pointRuleDetials.isLimit === 1"
                  />
              </div>
            </div>
            </div>
          </div>
        </el-card>
        <!-- 积分转换规则 -->
        <el-card class="rule-section" shadow="never">
          <template #header>
            <div class="card-header">
              <span class="section-title">积分转换规则</span>
            </div>
          </template>
          <div class="rule-category">
            <h4>积分转换</h4>
            <div class="rule-subcategory">
              <h5>数字化标杆积分转换</h5>
              <div class="rule-items">
                <div class="rule-item">
                  <span class="rule-desc">数字化标杆个人</span>
                  <el-input
                    v-model="rules.benchmarkPersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化标杆单位</span>
                  <el-input
                    v-model="rules.benchmarkUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
                <div class="rule-item">
                  <span class="rule-desc">数字化标杆单位</span>
                  <el-input
                    v-model="rules.benchmarkUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化标杆个人</span>
                  <el-input
                    v-model="rules.benchmarkPersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
              </div>
            </div>
            <div class="rule-subcategory">
              <h5>数字化知识积分转换</h5>
              <div class="rule-items">
                <div class="rule-item">
                  <span class="rule-desc">数字化知识个人</span>
                  <el-input
                    v-model="rules.knowledgePersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化知识单位</span>
                  <el-input
                    v-model="rules.knowledgeUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
                <div class="rule-item">
                  <span class="rule-desc">数字化知识单位</span>
                  <el-input
                    v-model="rules.knowledgeUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化知识个人</span>
                  <el-input
                    v-model="rules.knowledgePersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
              </div>
            </div>
            <div class="rule-subcategory">
              <h5>数字化产品积分转换</h5>
              <div class="rule-items">
                <div class="rule-item">
                  <span class="rule-desc">数字化产品个人</span>
                  <el-input
                    v-model="rules.productPersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化产品单位</span>
                  <el-input
                    v-model="rules.productUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
                <div class="rule-item">
                  <span class="rule-desc">数字化产品单位</span>
                  <el-input
                    v-model="rules.productUnitToPersonal"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分兑换数字化产品个人</span>
                  <el-input
                    v-model="rules.productPersonalToUnit"
                    size="small"
                    style="width: 80px;"
                    placeholder="请输入"
                  />
                  <span class="unit">积分</span>
                </div>
              </div>
            </div>
          </div>
        </el-card>
<!--        <el-card class="rule-section" shadow="never">-->
<!--          <template #header>-->
<!--            <div class="card-header">-->
<!--              <span class="section-title">积分转换规则</span>-->
<!--            </div>-->
<!--          </template>-->
<!--          <div class="rule-category">-->
<!--            <h4>积分转换</h4>-->
<!--            <div class="rule-subcategory">-->
<!--              <h5>数字化标杆积分转换</h5>-->
<!--              <div class="rule-items">-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化标杆个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.benchmarkPersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化标杆单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.benchmarkUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化标杆单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.benchmarkUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化标杆个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.benchmarkPersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--              </div>-->
<!--            </div>-->
<!--            <div class="rule-subcategory">-->
<!--              <h5>数字化知识积分转换</h5>-->
<!--              <div class="rule-items">-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化知识个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.knowledgePersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化知识单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.knowledgeUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化知识单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.knowledgeUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化知识个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.knowledgePersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--              </div>-->
<!--            </div>-->
<!--            <div class="rule-subcategory">-->
<!--              <h5>数字化产品积分转换</h5>-->
<!--              <div class="rule-items">-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化产品个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.productPersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化产品单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.productUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--                <div class="rule-item">-->
<!--                  <span class="rule-desc">数字化产品单位</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.productUnitToPersonal"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分兑换数字化产品个人</span>-->
<!--                  <el-input-->
<!--                    v-model="rules.productPersonalToUnit"-->
<!--                    size="small"-->
<!--                    style="width: 80px;"-->
<!--                    placeholder="请输入"-->
<!--                  />-->
<!--                  <span class="unit">积分</span>-->
<!--                </div>-->
<!--              </div>-->
<!--            </div>-->
<!--          </div>-->
<!--        </el-card>-->
      </div>
    </div>
@@ -351,17 +289,27 @@
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowLeft } from '@element-plus/icons-vue'
import pointsApi from '../../../api/pointsApi'
import qs from 'qs'
// 获取路由实例
const route = useRoute()
// 获取路由参数中的规则id
const ruleId = route.query.ruleId as string
// 定义props
interface Props {
  ruleId?: string
}
const props = withDefaults(defineProps<Props>(), {
  ruleId: ''
})
// 定义emits
const emit = defineEmits<{
  goBack: []
  saveSuccess: []
}>()
interface PointRule {
  category: string,
@@ -375,81 +323,29 @@
  createdAt: string,
  ruleType: number,
  pointsWinner: number,
  isLimit: number
  isLimit: number,
  pointsValue: number,
  dailyLimit: number
}
// 积分规则配置
interface PointsRules {
  getPointsRuleList: PointRule[],
  consumePointsRuleList: PointRule[],
  benchmarkSubmission: number,
  productSubscribedDailyLimit: number,
  productAccess: number,
  resourceTransaction: number,
  productSubscribed: number,
  productTrialed: number,
  productTrialedDailyLimit: number,
  resourceLiked: number,
  resourceLikedDailyLimit: number,
  dailyFirstLogin: number,
  postQuestion: number,
  postQuestionDailyLimit: number,
  postComment: number,
  postCommentDailyLimit: number,
  commentLiked: number,
  commentLikedDailyLimit: number,
  monthlyTop1: number,
  monthlyTop2: number,
  monthlyTop3: number,
  productUnfavorited: number,
  productUnliked: number,
  benchmarkPersonalToUnit: number,
  benchmarkUnitToPersonal: number,
  knowledgePersonalToUnit: number,
  knowledgeUnitToPersonal: number,
  productPersonalToUnit: number,
  productUnitToPersonal: number
  consumePointsRuleList: PointRule[]
}
const rules = ref<PointsRules>({
  consumePointsRuleList: [],
  getPointsRuleList: [],
  benchmarkSubmission: 0,
  productSubscribedDailyLimit: 0,
  productAccess: 0,
  resourceTransaction: 0,
  productSubscribed: 0,
  productTrialed: 0,
  productTrialedDailyLimit: 0,
  resourceLiked: 0,
  resourceLikedDailyLimit: 0,
  dailyFirstLogin: 0,
  postQuestion: 0,
  postQuestionDailyLimit: 0,
  postComment: 0,
  postCommentDailyLimit: 0,
  commentLiked: 0,
  commentLikedDailyLimit: 0,
  monthlyTop1: 0,
  monthlyTop2: 0,
  monthlyTop3: 0,
  productUnfavorited: 0,
  productUnliked: 0,
  benchmarkPersonalToUnit: 0,
  benchmarkUnitToPersonal: 0,
  knowledgePersonalToUnit: 0,
  knowledgeUnitToPersonal: 0,
  productPersonalToUnit: 0,
  productUnitToPersonal: 0
  getPointsRuleList: []
})
// 获取积分规则配置
const getPointsRules = async () => {
  try {
    if (ruleId) {
    if (props.ruleId) {
      // 如果有ruleId参数,则获取特定规则
     const formData = new URLSearchParams();
     formData.append('ruleId', ruleId);
      const formData = new URLSearchParams();
      formData.append('ruleId', props.ruleId);
      const res = await pointsApi.getPointsRuleById(formData)
      if (res.code === 200 && res.data) {
@@ -457,13 +353,8 @@
        Object.assign(rules.value, res.data)
        console.log(rules.value)
      }
    } else {
      // 如果没有ruleId参数,则获取所有规则
      const res = await pointsApi.getPointsRules()
      if (res.code === 200 && res.data) {
        // 将后端数据映射到前端规则对象
        Object.assign(rules.value, res.data)
      }
    }else{
      ElMessage.error('对应规则设置不存在')
    }
  } catch (error) {
    console.error('获取积分规则失败:', error)
@@ -478,10 +369,16 @@
      cancelButtonText: '取消',
      type: 'warning',
    })
    const res = await pointsApi.savePointsRules(rules.value)
    let pointRuleDetials: PointRuleDetial[] = []
    rules.value.getPointsRuleList.forEach(k => {
        pointRuleDetials.push(...k.pointsRules)
    })
    rules.value.consumePointsRuleList.forEach(k =>  pointRuleDetials.push(...k.pointsRules))
    const res = await pointsApi.savePointsRules(pointRuleDetials)
    if (res.code === 200) {
      ElMessage.success('保存成功')
      // 发出保存成功事件
      emit('saveSuccess')
    } else {
      ElMessage.error(res.msg || '保存失败')
    }
@@ -501,7 +398,7 @@
      cancelButtonText: '取消',
      type: 'warning',
    })
    await getPointsRules()
    ElMessage.success('重置成功')
  } catch (error) {
@@ -514,11 +411,27 @@
// 返回上一页
const goBack = () => {
  history.back()
  // 如果是从组件调用,发出goBack事件
  if (props.ruleId) {
    emit('goBack')
  } else {
    // 否则使用原有的返回逻辑
    history.back()
  }
}
// 监听ruleId变化
watch(() => props.ruleId, (newRuleId) => {
  if (newRuleId) {
    getPointsRules()
  }
}, { immediate: true })
onMounted(() => {
  getPointsRules()
  // 只有在没有props.ruleId时才执行原有的逻辑
  if (!props.ruleId) {
    getPointsRules()
  }
})
</script>
@@ -548,7 +461,7 @@
        cursor: pointer;
        color: #409eff;
        font-size: 18px;
        &:hover {
          color: #66b1ff;
        }
@@ -573,7 +486,7 @@
    max-width: 1665px;
    margin: 0 auto;
    margin-bottom: 40px;
    @media (max-width: 768px) {
      flex-direction: column;
      gap: 16px;
@@ -585,7 +498,7 @@
    justify-content: center;
    gap: 20px;
    padding: 20px 0;
    .el-button {
      min-width: 120px;
      height: 40px;
@@ -596,7 +509,7 @@
  .left-column {
    flex: 1;
    max-width: 50%;
    @media (max-width: 768px) {
      max-width: 100%;
    }
@@ -608,7 +521,7 @@
    display: flex;
    flex-direction: column;
    gap: 20px;
    @media (max-width: 768px) {
      max-width: 100%;
      gap: 16px;
@@ -618,13 +531,13 @@
  .rule-section {
    border-radius: 8px;
    border: 1px solid #e4e7ed;
    .card-header {
      // background-color: #fafafa;
      // background-color: rgba(221, 230, 244, 1);
      // border-bottom: 1px solid #e4e7ed;
      .section-title {
        font-size: 16px;
        font-weight: 600;
@@ -697,11 +610,11 @@
      :deep(.el-input) {
        .el-input__wrapper {
          box-shadow: 0 0 0 1px #dcdfe6 inset;
          &:hover {
            box-shadow: 0 0 0 1px #c0c4cc inset;
          }
          &.is-focus {
            box-shadow: 0 0 0 1px #409eff inset;
          }
src/views/pointsManage/unit/index.vue
@@ -104,12 +104,12 @@
              <span class="filter-label">数据类目:</span>
              <el-select v-model="queryParams.dataCategory" placeholder="全部" clearable>
                <el-option label="全部" value="" />
                <el-option label="资源贡献" value="resource_contribution" />
                <el-option label="资源交易" value="resource_transaction" />
                <el-option label="资源传播" value="resource_dissemination" />
                <el-option label="用户参与" value="user_participation" />
                <el-option label="积分转换" value="points_conversion" />
                <el-option label="其他" value="other" />
                <el-option
                  v-for="category in categoryList"
                  :key="category"
                  :label="getCategoryLabel(category)"
                  :value="category"
                />
              </el-select>
            </div>
            <div class="filter-item">
@@ -234,7 +234,7 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { dayjs, ElMessage } from 'element-plus'
import { 
  Money, 
  Plus, 
@@ -257,8 +257,8 @@
const queryParams = reactive<PointsQueryParams>({
  dataCategory: '',
  dataType: '',
  startTime: '',
  endTime: '',
  flowStartTime: '',
  flowEndTime: '',
  year: new Date().getFullYear().toString(),
  month: '',
  day: '',
@@ -280,6 +280,9 @@
// 总数
const total = ref(0)
// 数据类目列表
const categoryList = ref<string[]>([])
// 获取积分详情
const earnedDetails = ref<UnitPointsDetail[]>([
@@ -327,6 +330,18 @@
  }
}
// 获取数据类目列表
const getCategoryList = async () => {
  try {
    const res = await pointsApi.getPointsFlowCategories()
    if (res.code === 200 && res.data) {
      categoryList.value = res.data
    }
  } catch (error) {
    console.error('获取数据类目失败:', error)
  }
}
// 获取单位积分流水
const getUnitPointsFlow = async () => {
  try {
@@ -351,8 +366,8 @@
const resetQuery = () => {
  queryParams.dataCategory = ''
  queryParams.dataType = ''
  queryParams.startTime = ''
  queryParams.endTime = ''
  queryParams.flowStartTime = ''
  queryParams.flowEndTime = ''
  queryParams.year = new Date().getFullYear().toString()
  queryParams.month = ''
  queryParams.day = ''
@@ -366,8 +381,8 @@
// 处理时间类型变化
const handleTimeTypeChange = (type: string | number | boolean | undefined) => {
  // 清空其他时间字段
  queryParams.startTime = ''
  queryParams.endTime = ''
  queryParams.flowStartTime = ''
  queryParams.flowEndTime = ''
  queryParams.month = ''
  queryParams.day = ''
  monthValue.value = ''
@@ -389,11 +404,11 @@
// 处理日期变化
const handleDateChange = (dates: [string, string] | null) => {
  if (dates) {
    queryParams.startTime = dates[0]
    queryParams.endTime = dates[1]
    queryParams.flowStartTime = dates[0]
    queryParams.flowEndTime = dates[1]
  } else {
    queryParams.startTime = ''
    queryParams.endTime = ''
    queryParams.flowStartTime = ''
    queryParams.flowEndTime = ''
  }
}
@@ -413,6 +428,7 @@
onMounted(() => {
  getUnitPointsStats()
  getUnitPointsFlow()
  getCategoryList()
})
</script>