Explorar el Código

管理端功能增加

caojp hace 4 semanas
padre
commit
eadf53bc9c
Se han modificado 28 ficheros con 2331 adiciones y 91 borrados
  1. 30 0
      LiangZhiYUMao/utils/api.js
  2. 11 0
      marriageAdmin-vue/src/config/api.js
  3. 2 0
      marriageAdmin-vue/src/layouts/MainLayout.vue
  4. 44 5
      marriageAdmin-vue/src/router/index.js
  5. 11 1
      marriageAdmin-vue/src/utils/request.js
  6. 378 0
      marriageAdmin-vue/src/views/matchmaker/PointsOrderList.vue
  7. 405 0
      marriageAdmin-vue/src/views/matchmaker/ResourceList.vue
  8. 55 20
      service/Recommend/src/main/java/com/zhentao/controller/RecommendController.java
  9. 21 4
      service/Recommend/src/main/resources/mapper/RecommendMapper.xml
  10. 60 5
      service/admin/src/main/java/com/zhentao/controller/DashboardController.java
  11. 163 0
      service/admin/src/main/java/com/zhentao/controller/MyResourceController.java
  12. 215 0
      service/admin/src/main/java/com/zhentao/controller/PointsOrderController.java
  13. 257 0
      service/admin/src/main/java/com/zhentao/entity/MyResource.java
  14. 175 49
      service/admin/src/main/java/com/zhentao/entity/PointsOrder.java
  15. 120 0
      service/admin/src/main/java/com/zhentao/entity/SystemMessages.java
  16. 19 0
      service/admin/src/main/java/com/zhentao/mapper/MyResourceMapper.java
  17. 11 5
      service/admin/src/main/java/com/zhentao/mapper/PointsOrderMapper.java
  18. 18 0
      service/admin/src/main/java/com/zhentao/mapper/SystemMessagesMapper.java
  19. 14 0
      service/admin/src/main/java/com/zhentao/service/MyResourceService.java
  20. 13 0
      service/admin/src/main/java/com/zhentao/service/PointsOrderService.java
  21. 19 0
      service/admin/src/main/java/com/zhentao/service/SystemMessagesService.java
  22. 23 0
      service/admin/src/main/java/com/zhentao/service/impl/MyResourceServiceImpl.java
  23. 3 2
      service/admin/src/main/java/com/zhentao/service/impl/PointsMallServiceImpl.java
  24. 22 0
      service/admin/src/main/java/com/zhentao/service/impl/PointsOrderServiceImpl.java
  25. 142 0
      service/admin/src/main/java/com/zhentao/service/impl/SystemMessagesServiceImpl.java
  26. 43 0
      service/admin/src/main/resources/com/zhentao/mapper/MyResourceMapper.xml
  27. 34 0
      service/admin/src/main/resources/com/zhentao/mapper/PointsOrderMapper.xml
  28. 23 0
      service/admin/src/main/resources/com/zhentao/mapper/SystemMessagesMapper.xml

+ 30 - 0
LiangZhiYUMao/utils/api.js

@@ -32,6 +32,18 @@ const request = (options) => {
           // 根据后端约定的数据格式处理
           if (res.data.code === 200 || res.data.code === 0 || res.data.success) {
             resolve(res.data.data || res.data)
+          } else if (res.data.code === 403) {
+            // 业务层面的403错误,清除token并跳转登录
+            uni.removeStorageSync('token')
+            uni.removeStorageSync('userInfo')
+            uni.showToast({
+              title: res.data.message || res.data.msg || '拒绝访问,请重新登录',
+              icon: 'none'
+            })
+            uni.navigateTo({
+              url: '/pages/page3/page3'
+            })
+            reject(res.data)
           } else {
             uni.showToast({
               title: res.data.message || res.data.msg || '请求失败',
@@ -41,6 +53,24 @@ const request = (options) => {
           }
         } else if (res.statusCode === 401) {
           // 未授权,跳转登录
+          uni.removeStorageSync('token')
+          uni.removeStorageSync('userInfo')
+          uni.showToast({
+            title: '未授权,请重新登录',
+            icon: 'none'
+          })
+          uni.navigateTo({
+            url: '/pages/page3/page3'
+          })
+          reject(res)
+        } else if (res.statusCode === 403) {
+          // 拒绝访问,清除token并跳转登录
+          uni.removeStorageSync('token')
+          uni.removeStorageSync('userInfo')
+          uni.showToast({
+            title: '拒绝访问,请重新登录',
+            icon: 'none'
+          })
           uni.navigateTo({
             url: '/pages/page3/page3'
           })

+ 11 - 0
marriageAdmin-vue/src/config/api.js

@@ -54,6 +54,17 @@ export const API_ENDPOINTS = {
   SUCCESS_CASE_UPLOAD_APPROVE: '/admin/success-case-upload/approve',
   SUCCESS_CASE_UPLOAD_REJECT: '/admin/success-case-upload/reject',
   
+  // 积分订单管理
+  POINTS_ORDER_LIST: '/admin/points-order/list',
+  POINTS_ORDER_DETAIL: '/admin/points-order',
+  POINTS_ORDER_REVIEW: '/admin/points-order/review',
+  POINTS_ORDER_DELETE: '/admin/points-order',
+  
+  // 线索管理
+  MY_RESOURCE_LIST: '/admin/my-resource/list',
+  MY_RESOURCE_DETAIL: '/admin/my-resource',
+  MY_RESOURCE_AUDIT: '/admin/my-resource',
+  
   // 课程管理
   COURSE_LIST: '/api/course/list',
   COURSE_DETAIL: '/api/course/detail',

+ 2 - 0
marriageAdmin-vue/src/layouts/MainLayout.vue

@@ -59,6 +59,8 @@
           <el-menu-item index="/matchmaker/audit">红娘审核</el-menu-item>
           <el-menu-item index="/matchmaker/create">添加红娘</el-menu-item>
           <el-menu-item index="/matchmaker/points-product">积分商品</el-menu-item>
+          <el-menu-item index="/matchmaker/points-order">积分商城订单</el-menu-item>
+          <el-menu-item index="/matchmaker/resource">线索管理</el-menu-item>
           <el-menu-item index="/matchmaker/case-audit">案例审核</el-menu-item>
         </el-sub-menu>
         

+ 44 - 5
marriageAdmin-vue/src/router/index.js

@@ -3,6 +3,7 @@
  */
 import { createRouter, createWebHistory } from 'vue-router'
 import { useUserStore } from '@/stores/user'
+import { ElMessage } from 'element-plus'
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
@@ -16,7 +17,7 @@ const router = createRouter({
     {
       path: '/',
       component: () => import('@/layouts/MainLayout.vue'),
-      redirect: '/dashboard',
+      redirect: '/banner', // 默认跳转到轮播图,路由守卫会处理超级管理员的跳转
       meta: { requiresAuth: true },
       children: [
         {
@@ -121,6 +122,18 @@ const router = createRouter({
               name: 'CaseAudit',
               component: () => import('@/views/matchmaker/CaseAudit.vue'),
               meta: { title: '案例审核' }
+            },
+            {
+              path: 'points-order',
+              name: 'PointsOrder',
+              component: () => import('@/views/matchmaker/PointsOrderList.vue'),
+              meta: { title: '积分商城订单' }
+            },
+            {
+              path: 'resource',
+              name: 'ResourceList',
+              component: () => import('@/views/matchmaker/ResourceList.vue'),
+              meta: { title: '线索管理' }
             }
           ]
         },
@@ -250,17 +263,43 @@ router.beforeEach((to, from, next) => {
   // 设置页面标题
   document.title = to.meta.title ? `${to.meta.title} - 婚恋管理系统` : '婚恋管理系统'
   
-  // 检查是否需要认证
+    // 检查是否需要认证
   if (to.meta.requiresAuth !== false) {
     if (!userStore.token) {
       next('/login')
-    } else {
-      next()
+      return
+    }
+    
+    // 检查数据面板权限 - 仅超级管理员可访问
+    if (to.path === '/dashboard') {
+      if (!userStore.isSuperAdmin) {
+        // 非超级管理员重定向到轮播图管理页面
+        ElMessage.warning('只有超级管理员可以访问数据面板')
+        next('/banner')
+        return
+      }
+    }
+    
+    // 如果访问根路径,根据权限跳转
+    if (to.path === '/') {
+      if (userStore.isSuperAdmin) {
+        next('/dashboard')
+      } else {
+        next('/banner')
+      }
+      return
     }
+    
+    next()
   } else {
     // 如果已登录,访问登录页则跳转到首页
     if (to.path === '/login' && userStore.token) {
-      next('/')
+      // 根据是否是超级管理员跳转到不同页面
+      if (userStore.isSuperAdmin) {
+        next('/dashboard')
+      } else {
+        next('/banner')
+      }
     } else {
       next()
     }

+ 11 - 1
marriageAdmin-vue/src/utils/request.js

@@ -59,6 +59,13 @@ request.interceptors.response.use(
       localStorage.removeItem('admin_user')
       router.push('/login')
       return Promise.reject(new Error(res.msg || '未授权'))
+    } else if (res.code === 403) {
+      // 拒绝访问,清除token并跳转登录
+      showErrorMessage(res.msg || '拒绝访问,请重新登录')
+      localStorage.removeItem('admin_token')
+      localStorage.removeItem('admin_user')
+      router.push('/login')
+      return Promise.reject(new Error(res.msg || '拒绝访问'))
     } else {
       // 其他错误
       showErrorMessage(res.msg || '请求失败')
@@ -88,7 +95,10 @@ request.interceptors.response.use(
           router.push('/login')
           break
         case 403:
-          showErrorMessage('拒绝访问')
+          showErrorMessage('拒绝访问,请重新登录')
+          localStorage.removeItem('admin_token')
+          localStorage.removeItem('admin_user')
+          router.push('/login')
           break
         case 404:
           // 只对API请求显示404提示

+ 378 - 0
marriageAdmin-vue/src/views/matchmaker/PointsOrderList.vue

@@ -0,0 +1,378 @@
+<template>
+  <div class="points-order-list-container">
+    <h2 class="page-title">积分商城订单</h2>
+    
+    <!-- 工具栏 -->
+    <el-card shadow="never" class="toolbar-card">
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-space wrap>
+            <el-input 
+              v-model="filters.orderNo" 
+              placeholder="订单号" 
+              clearable 
+              style="width: 200px" 
+              @keyup.enter="loadList"
+            />
+            <el-input 
+              v-model="filters.productName" 
+              placeholder="产品名称" 
+              clearable 
+              style="width: 200px" 
+              @keyup.enter="loadList"
+            />
+            <el-select 
+              v-model="filters.review" 
+              placeholder="审核状态" 
+              clearable 
+              style="width: 150px" 
+              @change="loadList"
+            >
+              <el-option label="待审核" :value="0" />
+              <el-option label="审核通过" :value="1" />
+              <el-option label="审核未通过" :value="2" />
+            </el-select>
+            <el-select 
+              v-model="filters.status" 
+              placeholder="发货状态" 
+              clearable 
+              style="width: 150px" 
+              @change="loadList"
+            >
+              <el-option label="待发货" :value="0" />
+              <el-option label="已发货" :value="1" />
+              <el-option label="已完成" :value="2" />
+              <el-option label="已取消" :value="3" />
+            </el-select>
+            <el-button type="primary" icon="Search" @click="loadList">查询</el-button>
+            <el-button icon="Refresh" @click="resetFilters">重置</el-button>
+          </el-space>
+        </el-col>
+      </el-row>
+    </el-card>
+    
+    <!-- 列表 -->
+    <el-card shadow="never" class="table-card">
+      <el-table v-loading="loading" :data="list" stripe>
+        <template #empty>
+          <div class="custom-empty-state">
+            <el-icon class="empty-icon"><Document /></el-icon>
+            <div class="empty-text">暂无订单数据</div>
+          </div>
+        </template>
+        <el-table-column type="index" label="序号" width="60" />
+        <el-table-column prop="orderNo" label="订单号" width="180" />
+        <el-table-column prop="productName" label="产品名称" width="200" />
+        <el-table-column prop="productImage" label="产品图片" width="100">
+          <template #default="{ row }">
+            <el-image 
+              v-if="row.productImage" 
+              :src="row.productImage" 
+              style="width: 60px; height: 60px"
+              fit="cover"
+            />
+            <span v-else>-</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="pointsPrice" label="积分单价" width="100" align="center" />
+        <el-table-column prop="quantity" label="数量" width="80" align="center" />
+        <el-table-column prop="totalPoints" label="总积分" width="100" align="center" />
+        <el-table-column prop="receiverName" label="收件人" width="100" />
+        <el-table-column prop="receiverPhone" label="收件电话" width="130" />
+        <el-table-column prop="receiverAddress" label="收件地址" min-width="200" show-overflow-tooltip />
+        <el-table-column prop="review" label="审核状态" width="120" align="center">
+          <template #default="{ row }">
+            <el-tag :type="getReviewType(row.review)" size="small">
+              {{ getReviewText(row.review) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="发货状态" width="120" align="center">
+          <template #default="{ row }">
+            <el-tag :type="getStatusType(row.status)" size="small">
+              {{ getStatusText(row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="创建时间" width="180" />
+        <el-table-column label="操作" width="150" fixed="right">
+          <template #default="{ row }">
+            <el-button 
+              type="primary" 
+              size="small" 
+              link 
+              @click="handleReview(row)"
+              :disabled="row.review === 1 || row.review === 2"
+            >
+              审核
+            </el-button>
+            <el-button 
+              type="danger" 
+              size="small" 
+              link 
+              @click="handleDelete(row)"
+            >
+              删除
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="currentPage"
+          v-model:page-size="pageSize"
+          :total="total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="loadList"
+          @current-change="loadList"
+        />
+      </div>
+    </el-card>
+
+    <!-- 审核弹框 -->
+    <el-dialog 
+      v-model="reviewDialogVisible" 
+      title="订单审核" 
+      width="600px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="reviewForm" label-width="120px">
+        <el-form-item label="订单号">
+          <el-input v-model="reviewForm.orderNo" disabled />
+        </el-form-item>
+        <el-form-item label="收件人姓名">
+          <el-input v-model="reviewForm.receiverName" disabled />
+        </el-form-item>
+        <el-form-item label="收件人电话">
+          <el-input v-model="reviewForm.receiverPhone" disabled />
+        </el-form-item>
+        <el-form-item label="收件地址">
+          <el-input v-model="reviewForm.receiverAddress" type="textarea" :rows="2" disabled />
+        </el-form-item>
+        <el-form-item label="审核结果" required>
+          <el-radio-group v-model="reviewForm.review">
+            <el-radio :label="1">审核通过</el-radio>
+            <el-radio :label="2">审核不通过</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item 
+          v-if="reviewForm.review === 2" 
+          label="审核失败说明" 
+          required
+        >
+          <el-input 
+            v-model="reviewForm.reviewFail" 
+            type="textarea" 
+            :rows="4"
+            placeholder="请输入审核失败的原因"
+            maxlength="500"
+            show-word-limit
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="reviewDialogVisible = false">取消</el-button>
+        <el-button 
+          type="primary" 
+          @click="submitReview"
+          :loading="reviewLoading"
+        >
+          确定
+        </el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { Document } from '@element-plus/icons-vue'
+import request from '@/utils/request'
+import { API_ENDPOINTS } from '@/config/api'
+
+const loading = ref(false)
+const currentPage = ref(1)
+const pageSize = ref(10)
+const total = ref(0)
+const list = ref([])
+
+const filters = reactive({
+  orderNo: '',
+  productName: '',
+  review: null,
+  status: null
+})
+
+const reviewDialogVisible = ref(false)
+const reviewLoading = ref(false)
+const reviewForm = reactive({
+  id: null,
+  orderNo: '',
+  receiverName: '',
+  receiverPhone: '',
+  receiverAddress: '',
+  review: 1,
+  reviewFail: ''
+})
+
+const loadList = async () => {
+  loading.value = true
+  try {
+    const params = {
+      page: currentPage.value,
+      pageSize: pageSize.value
+    }
+    
+    if (filters.orderNo && filters.orderNo.trim()) {
+      params.orderNo = filters.orderNo.trim()
+    }
+    if (filters.productName && filters.productName.trim()) {
+      params.productName = filters.productName.trim()
+    }
+    if (filters.review !== null && filters.review !== undefined) {
+      params.review = filters.review
+    }
+    if (filters.status !== null && filters.status !== undefined) {
+      params.status = filters.status
+    }
+    
+    const response = await request.get(API_ENDPOINTS.POINTS_ORDER_LIST, { params })
+    
+    if (response.code === 200) {
+      const data = response.data || {}
+      list.value = data.list || data.records || []
+      total.value = data.total || 0
+    } else {
+      ElMessage.error(response.message || response.msg || '加载失败')
+      list.value = []
+      total.value = 0
+    }
+  } catch (error) {
+    console.error('加载失败:', error)
+    ElMessage.error('加载失败: ' + (error.message || '未知错误'))
+    list.value = []
+    total.value = 0
+  } finally {
+    loading.value = false
+  }
+}
+
+const resetFilters = () => {
+  filters.orderNo = ''
+  filters.productName = ''
+  filters.review = null
+  filters.status = null
+  currentPage.value = 1
+  loadList()
+}
+
+const getReviewText = (review) => {
+  const texts = { 0: '待审核', 1: '审核通过', 2: '审核未通过' }
+  return texts[review] || '未知'
+}
+
+const getReviewType = (review) => {
+  const types = { 0: 'warning', 1: 'success', 2: 'danger' }
+  return types[review] || ''
+}
+
+const getStatusText = (status) => {
+  const texts = { 0: '待发货', 1: '已发货', 2: '已完成', 3: '已取消' }
+  return texts[status] || '未知'
+}
+
+const getStatusType = (status) => {
+  const types = { 0: 'warning', 1: 'info', 2: 'success', 3: 'danger' }
+  return types[status] || ''
+}
+
+const handleReview = (row) => {
+  reviewForm.id = row.id
+  reviewForm.orderNo = row.orderNo || ''
+  reviewForm.receiverName = row.receiverName || ''
+  reviewForm.receiverPhone = row.receiverPhone || ''
+  reviewForm.receiverAddress = row.receiverAddress || ''
+  reviewForm.review = 1
+  reviewForm.reviewFail = ''
+  reviewDialogVisible.value = true
+}
+
+const submitReview = async () => {
+  if (!reviewForm.review) {
+    ElMessage.warning('请选择审核结果')
+    return
+  }
+  
+  if (reviewForm.review === 2 && !reviewForm.reviewFail?.trim()) {
+    ElMessage.warning('审核不通过时必须填写审核失败说明')
+    return
+  }
+  
+  reviewLoading.value = true
+  try {
+    const params = {
+      review: reviewForm.review
+    }
+    if (reviewForm.review === 2) {
+      params.reviewFail = reviewForm.reviewFail.trim()
+    }
+    
+    const response = await request.post(
+      `${API_ENDPOINTS.POINTS_ORDER_REVIEW}/${reviewForm.id}`,
+      null,
+      { params }
+    )
+    
+    if (response.code === 200) {
+      ElMessage.success('审核成功')
+      reviewDialogVisible.value = false
+      loadList()
+    } else {
+      ElMessage.error(response.message || response.msg || '审核失败')
+    }
+  } catch (error) {
+    console.error('审核失败:', error)
+    ElMessage.error(error.response?.data?.message || error.message || '审核失败')
+  } finally {
+    reviewLoading.value = false
+  }
+}
+
+const handleDelete = async (row) => {
+  try {
+    await ElMessageBox.confirm('确定要删除这个订单吗?删除后订单将不再显示。', '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning'
+    })
+    
+    const response = await request.delete(`${API_ENDPOINTS.POINTS_ORDER_DELETE}/${row.id}`)
+    
+    if (response.code === 200) {
+      ElMessage.success('删除成功')
+      loadList()
+    } else {
+      ElMessage.error(response.message || response.msg || '删除失败')
+    }
+  } catch (error) {
+    if (error !== 'cancel') {
+      console.error('删除失败:', error)
+      ElMessage.error(error.response?.data?.message || error.message || '删除失败')
+    }
+  }
+}
+
+onMounted(() => loadList())
+</script>
+
+<style scoped>
+@import '@/assets/list-common.css';
+
+.points-order-list-container {
+  padding: 0;
+}
+</style>
+

+ 405 - 0
marriageAdmin-vue/src/views/matchmaker/ResourceList.vue

@@ -0,0 +1,405 @@
+<template>
+  <div class="resource-list-container">
+    <h2 class="page-title">线索管理</h2>
+    
+    <!-- 工具栏 -->
+    <el-card shadow="never" class="toolbar-card">
+      <el-row :gutter="20">
+        <el-col :span="24">
+          <el-space wrap>
+            <el-input 
+              v-model="filters.name" 
+              placeholder="名称" 
+              clearable 
+              style="width: 200px" 
+              @keyup.enter="loadList"
+            />
+            <el-input 
+              v-model="filters.phone" 
+              placeholder="手机号" 
+              clearable 
+              style="width: 200px" 
+              @keyup.enter="loadList"
+            />
+            <el-select 
+              v-model="filters.status" 
+              placeholder="审核状态" 
+              clearable 
+              style="width: 150px" 
+              @change="loadList"
+            >
+              <el-option label="待审核" :value="0" />
+              <el-option label="审核通过" :value="1" />
+              <el-option label="审核失败" :value="2" />
+            </el-select>
+            <el-select 
+              v-model="filters.diploma" 
+              placeholder="学历" 
+              clearable 
+              style="width: 150px" 
+              @change="loadList"
+            >
+              <el-option label="高中" value="高中" />
+              <el-option label="专科" value="专科" />
+              <el-option label="本科" value="本科" />
+              <el-option label="硕士" value="硕士" />
+              <el-option label="博士" value="博士" />
+              <el-option label="无" value="无" />
+            </el-select>
+            <el-select 
+              v-model="filters.marrStatus" 
+              placeholder="婚姻状况" 
+              clearable 
+              style="width: 150px" 
+              @change="loadList"
+            >
+              <el-option label="未婚" :value="0" />
+              <el-option label="离异" :value="1" />
+              <el-option label="丧偶" :value="2" />
+            </el-select>
+            <el-button type="primary" icon="Search" @click="loadList">查询</el-button>
+            <el-button icon="Refresh" @click="resetFilters">重置</el-button>
+          </el-space>
+        </el-col>
+      </el-row>
+    </el-card>
+    
+    <!-- 列表 -->
+    <el-card shadow="never" class="table-card">
+      <el-table v-loading="loading" :data="list" stripe>
+        <template #empty>
+          <div class="custom-empty-state">
+            <el-icon class="empty-icon"><Document /></el-icon>
+            <div class="empty-text">暂无线索数据</div>
+          </div>
+        </template>
+        <el-table-column type="index" label="序号" width="60" />
+        <el-table-column prop="name" label="名称" width="120" />
+        <el-table-column prop="phone" label="手机号" width="130" />
+        <el-table-column prop="backupPhone" label="备用手机号" width="130" />
+        <el-table-column prop="age" label="年龄" width="80" align="center" />
+        <el-table-column prop="gender" label="性别" width="80" align="center">
+          <template #default="{ row }">
+            <span>{{ row.gender === 1 ? '男' : row.gender === 2 ? '女' : '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="height" label="身高(cm)" width="100" align="center" />
+        <el-table-column prop="diploma" label="学历" width="100" align="center" />
+        <el-table-column prop="marrStatus" label="婚姻状况" width="100" align="center">
+          <template #default="{ row }">
+            <span>{{ getMarrStatusText(row.marrStatus) }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="occupation" label="职业" width="120" show-overflow-tooltip />
+        <el-table-column prop="address" label="住址" min-width="150" show-overflow-tooltip />
+        <el-table-column prop="status" label="审核状态" width="120" align="center">
+          <template #default="{ row }">
+            <el-tag :type="getStatusType(row.status)" size="small">
+              {{ getStatusText(row.status) }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createTime" label="创建时间" width="180" />
+        <el-table-column label="操作" width="150" fixed="right">
+          <template #default="{ row }">
+            <el-button 
+              type="primary" 
+              size="small" 
+              link 
+              @click="handleDetail(row)"
+            >
+              详情
+            </el-button>
+            <el-button 
+              type="success" 
+              size="small" 
+              link 
+              @click="handleAudit(row)"
+            >
+              审核
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      
+      <div class="pagination-container">
+        <el-pagination
+          v-model:current-page="currentPage"
+          v-model:page-size="pageSize"
+          :total="total"
+          :page-sizes="[10, 20, 50, 100]"
+          layout="total, sizes, prev, pager, next, jumper"
+          @size-change="loadList"
+          @current-change="loadList"
+        />
+      </div>
+    </el-card>
+
+    <!-- 审核弹框 -->
+    <el-dialog 
+      v-model="auditDialogVisible" 
+      title="审核线索" 
+      width="500px"
+      :close-on-click-modal="false"
+    >
+      <div v-if="auditData" style="margin-bottom: 20px;">
+        <el-descriptions :column="1" border>
+          <el-descriptions-item label="名称">{{ auditData.name }}</el-descriptions-item>
+          <el-descriptions-item label="手机号">{{ auditData.phone }}</el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <el-form :model="auditForm" label-width="100px">
+        <el-form-item label="审核结果" required>
+          <el-radio-group v-model="auditForm.status">
+            <el-radio :label="1">审核通过</el-radio>
+            <el-radio :label="2">审核失败</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item 
+          label="失败原因" 
+          v-if="auditForm.status === 2"
+        >
+          <el-input 
+            v-model="auditForm.rejectReason" 
+            type="textarea" 
+            :rows="4"
+            placeholder="请输入审核失败原因"
+            maxlength="200"
+            show-word-limit
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="auditDialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="submitAudit" :loading="auditLoading">确定</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 详情弹框 -->
+    <el-dialog 
+      v-model="detailDialogVisible" 
+      title="线索详情" 
+      width="800px"
+      :close-on-click-modal="false"
+    >
+      <el-descriptions :column="2" border v-if="detailData">
+        <el-descriptions-item label="资源ID">{{ detailData.resourceId }}</el-descriptions-item>
+        <el-descriptions-item label="红娘ID">{{ detailData.matchmakerId }}</el-descriptions-item>
+        <el-descriptions-item label="名称">{{ detailData.name }}</el-descriptions-item>
+        <el-descriptions-item label="手机号">{{ detailData.phone }}</el-descriptions-item>
+        <el-descriptions-item label="备用手机号">{{ detailData.backupPhone || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="年龄">{{ detailData.age }}</el-descriptions-item>
+        <el-descriptions-item label="性别">
+          {{ detailData.gender === 1 ? '男' : detailData.gender === 2 ? '女' : '-' }}
+        </el-descriptions-item>
+        <el-descriptions-item label="身高">{{ detailData.height }}cm</el-descriptions-item>
+        <el-descriptions-item label="体重">{{ detailData.weight }}kg</el-descriptions-item>
+        <el-descriptions-item label="星座">{{ detailData.constellation || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="学历">{{ detailData.diploma || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="婚姻状况">{{ getMarrStatusText(detailData.marrStatus) }}</el-descriptions-item>
+        <el-descriptions-item label="收入">{{ detailData.income || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="职业">{{ detailData.occupation || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="住址">{{ detailData.address || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="户籍所在地">{{ detailData.domicile || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="购房">
+          {{ detailData.house === 1 ? '有' : detailData.house === 0 ? '无' : '-' }}
+        </el-descriptions-item>
+        <el-descriptions-item label="购车">
+          {{ detailData.car === 1 ? '有' : detailData.car === 0 ? '无' : '-' }}
+        </el-descriptions-item>
+        <el-descriptions-item label="审核状态">
+          <el-tag :type="getStatusType(detailData.status)" size="small">
+            {{ getStatusText(detailData.status) }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="审核失败原因" :span="2" v-if="detailData.rejectReason">
+          {{ detailData.rejectReason }}
+        </el-descriptions-item>
+        <el-descriptions-item label="择偶标准" :span="2">
+          {{ detailData.mateSelectionCriteria || '-' }}
+        </el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ detailData.createTime }}</el-descriptions-item>
+        <el-descriptions-item label="更新时间">{{ detailData.updateTime }}</el-descriptions-item>
+      </el-descriptions>
+      <template #footer>
+        <el-button @click="detailDialogVisible = false">关闭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+import { Document } from '@element-plus/icons-vue'
+import request from '@/utils/request'
+import { API_ENDPOINTS } from '@/config/api'
+
+const loading = ref(false)
+const currentPage = ref(1)
+const pageSize = ref(10)
+const total = ref(0)
+const list = ref([])
+
+const filters = reactive({
+  name: '',
+  phone: '',
+  status: null,
+  diploma: null,
+  marrStatus: null
+})
+
+const detailDialogVisible = ref(false)
+const detailData = ref(null)
+
+const auditDialogVisible = ref(false)
+const auditData = ref(null)
+const auditLoading = ref(false)
+const auditForm = reactive({
+  status: 1,
+  rejectReason: ''
+})
+
+const loadList = async () => {
+  loading.value = true
+  try {
+    const params = {
+      page: currentPage.value,
+      pageSize: pageSize.value
+    }
+    
+    if (filters.name && filters.name.trim()) {
+      params.name = filters.name.trim()
+    }
+    if (filters.phone && filters.phone.trim()) {
+      params.phone = filters.phone.trim()
+    }
+    if (filters.status !== null && filters.status !== undefined) {
+      params.status = filters.status
+    }
+    if (filters.diploma && filters.diploma.trim()) {
+      params.diploma = filters.diploma.trim()
+    }
+    if (filters.marrStatus !== null && filters.marrStatus !== undefined) {
+      params.marrStatus = filters.marrStatus
+    }
+    
+    const response = await request.get(API_ENDPOINTS.MY_RESOURCE_LIST, { params })
+    
+    if (response.code === 200) {
+      const data = response.data || {}
+      list.value = data.list || data.records || []
+      total.value = data.total || 0
+    } else {
+      ElMessage.error(response.message || response.msg || '加载失败')
+      list.value = []
+      total.value = 0
+    }
+  } catch (error) {
+    console.error('加载失败:', error)
+    ElMessage.error('加载失败: ' + (error.message || '未知错误'))
+    list.value = []
+    total.value = 0
+  } finally {
+    loading.value = false
+  }
+}
+
+const resetFilters = () => {
+  filters.name = ''
+  filters.phone = ''
+  filters.status = null
+  filters.diploma = null
+  filters.marrStatus = null
+  currentPage.value = 1
+  loadList()
+}
+
+const getStatusText = (status) => {
+  const texts = { 0: '待审核', 1: '审核通过', 2: '审核失败' }
+  return texts[status] || '未知'
+}
+
+const getStatusType = (status) => {
+  const types = { 0: 'warning', 1: 'success', 2: 'danger' }
+  return types[status] || ''
+}
+
+const getMarrStatusText = (marrStatus) => {
+  const texts = { 0: '未婚', 1: '离异', 2: '丧偶' }
+  return texts[marrStatus] || '-'
+}
+
+const handleDetail = async (row) => {
+  try {
+    const response = await request.get(`${API_ENDPOINTS.MY_RESOURCE_DETAIL}/${row.resourceId}`)
+    if (response.code === 200) {
+      detailData.value = response.data
+      detailDialogVisible.value = true
+    } else {
+      ElMessage.error(response.message || response.msg || '获取详情失败')
+    }
+  } catch (error) {
+    console.error('获取详情失败:', error)
+    ElMessage.error('获取详情失败: ' + (error.message || '未知错误'))
+  }
+}
+
+const handleAudit = (row) => {
+  auditData.value = row
+  auditForm.status = 1
+  auditForm.rejectReason = ''
+  auditDialogVisible.value = true
+}
+
+const submitAudit = async () => {
+  if (!auditData.value) {
+    return
+  }
+  
+  if (auditForm.status === 2 && !auditForm.rejectReason.trim()) {
+    ElMessage.warning('请填写审核失败原因')
+    return
+  }
+  
+  auditLoading.value = true
+  try {
+    const params = {
+      status: auditForm.status
+    }
+    if (auditForm.status === 2 && auditForm.rejectReason.trim()) {
+      params.rejectReason = auditForm.rejectReason.trim()
+    }
+    
+    const response = await request.put(
+      `${API_ENDPOINTS.MY_RESOURCE_AUDIT}/${auditData.value.resourceId}/audit`,
+      null,
+      { params }
+    )
+    
+    if (response.code === 200) {
+      ElMessage.success(response.message || response.msg || '审核成功')
+      auditDialogVisible.value = false
+      loadList()
+    } else {
+      ElMessage.error(response.message || response.msg || '审核失败')
+    }
+  } catch (error) {
+    console.error('审核失败:', error)
+    ElMessage.error('审核失败: ' + (error.message || '未知错误'))
+  } finally {
+    auditLoading.value = false
+  }
+}
+
+onMounted(() => loadList())
+</script>
+
+<style scoped>
+@import '@/assets/list-common.css';
+
+.resource-list-container {
+  padding: 0;
+}
+</style>
+

+ 55 - 20
service/Recommend/src/main/java/com/zhentao/controller/RecommendController.java

@@ -182,37 +182,72 @@ public class RecommendController {
 
     @GetMapping("/area/provinces")
     public Result<java.util.List<java.util.Map<String,Object>>> provinces() {
-        java.util.List<com.zhentao.pojo.Province> provinces = recommendService.getAllProvinces();
-        java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
-        for (com.zhentao.pojo.Province p : provinces) {
-            list.add(mapOf("id", p.getId(), "name", p.getName()));
+        try {
+            java.util.List<com.zhentao.pojo.Province> provinces = recommendService.getAllProvinces();
+            if (provinces == null) {
+                provinces = new java.util.ArrayList<>();
+            }
+            java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
+            for (com.zhentao.pojo.Province p : provinces) {
+                if (p != null) {
+                    list.add(mapOf("id", p.getId(), "name", p.getName()));
+                }
+            }
+            return Result.success(list);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("获取省份列表失败: " + e.getMessage());
         }
-        return Result.success(list);
     }
 
     @GetMapping("/area/cities")
     public Result<java.util.List<java.util.Map<String,Object>>> cities(@RequestParam(required = false) Integer provinceId) {
-        java.util.List<com.zhentao.pojo.City> cities;
-        if (provinceId != null) {
-            cities = recommendService.getCitiesByProvince(provinceId);
-        } else {
-            cities = recommendService.getAllCities();
-        }
-        java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
-        for (com.zhentao.pojo.City c : cities) {
-            list.add(mapOf("id", c.getId(), "name", c.getName()));
+        try {
+            java.util.List<com.zhentao.pojo.City> cities;
+            if (provinceId != null) {
+                cities = recommendService.getCitiesByProvince(provinceId);
+            } else {
+                cities = recommendService.getAllCities();
+            }
+            
+            if (cities == null) {
+                cities = new java.util.ArrayList<>();
+            }
+            
+            java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
+            for (com.zhentao.pojo.City c : cities) {
+                if (c != null) {
+                    list.add(mapOf("id", c.getId(), "name", c.getName()));
+                }
+            }
+            return Result.success(list);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("获取城市列表失败: " + e.getMessage());
         }
-        return Result.success(list);
     }
 
     @GetMapping("/area/areas")
     public Result<java.util.List<java.util.Map<String,Object>>> areas(@RequestParam Integer cityId) {
-        java.util.List<com.zhentao.pojo.Area> areas = recommendService.getAreasByCity(cityId);
-        java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
-        for (com.zhentao.pojo.Area a : areas) {
-            list.add(mapOf("id", a.getId(), "name", a.getName()));
+        try {
+            if (cityId == null) {
+                return Result.error("cityId参数不能为空");
+            }
+            java.util.List<com.zhentao.pojo.Area> areas = recommendService.getAreasByCity(cityId);
+            if (areas == null) {
+                areas = new java.util.ArrayList<>();
+            }
+            java.util.List<java.util.Map<String,Object>> list = new java.util.ArrayList<>();
+            for (com.zhentao.pojo.Area a : areas) {
+                if (a != null) {
+                    list.add(mapOf("id", a.getId(), "name", a.getName()));
+                }
+            }
+            return Result.success(list);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("获取区域列表失败: " + e.getMessage());
         }
-        return Result.success(list);
     }
 
     private java.util.Map<String,Object> mapOf(String k1, Object v1, String k2, Object v2) {

+ 21 - 4
service/Recommend/src/main/resources/mapper/RecommendMapper.xml

@@ -514,19 +514,36 @@
         LIMIT #{limit} OFFSET #{offset}
     </select>
 
-    <select id="selectAllProvinces" resultType="com.zhentao.pojo.Province">
+    <resultMap id="ProvinceResultMap" type="com.zhentao.pojo.Province">
+        <id property="id" column="id" jdbcType="INTEGER"/>
+        <result property="name" column="name" jdbcType="VARCHAR"/>
+    </resultMap>
+
+    <resultMap id="CityResultMap" type="com.zhentao.pojo.City">
+        <id property="id" column="id" jdbcType="INTEGER"/>
+        <result property="name" column="name" jdbcType="VARCHAR"/>
+        <result property="provinceId" column="province_id" jdbcType="INTEGER"/>
+    </resultMap>
+
+    <resultMap id="AreaResultMap" type="com.zhentao.pojo.Area">
+        <id property="id" column="id" jdbcType="INTEGER"/>
+        <result property="name" column="name" jdbcType="VARCHAR"/>
+        <result property="cityId" column="city_id" jdbcType="INTEGER"/>
+    </resultMap>
+
+    <select id="selectAllProvinces" resultMap="ProvinceResultMap">
         SELECT id, name FROM province ORDER BY id
     </select>
 
-    <select id="selectAllCities" resultType="com.zhentao.pojo.City">
+    <select id="selectAllCities" resultMap="CityResultMap">
         SELECT id, name, province_id FROM city ORDER BY id
     </select>
 
-    <select id="selectCitiesByProvince" resultType="com.zhentao.pojo.City">
+    <select id="selectCitiesByProvince" resultMap="CityResultMap">
         SELECT id, name, province_id FROM city WHERE province_id = #{provinceId} ORDER BY id
     </select>
 
-    <select id="selectAreasByCity" resultType="com.zhentao.pojo.Area">
+    <select id="selectAreasByCity" resultMap="AreaResultMap">
         SELECT id, name, city_id FROM area WHERE city_id = #{cityId} ORDER BY id
     </select>
 </mapper>

+ 60 - 5
service/admin/src/main/java/com/zhentao/controller/DashboardController.java

@@ -3,10 +3,14 @@ package com.zhentao.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.zhentao.common.Result;
 import com.zhentao.entity.Activity;
+import com.zhentao.entity.AdminUser;
 import com.zhentao.entity.Users;
 import com.zhentao.mapper.ActivityMapper;
 import com.zhentao.mapper.UsersMapper;
+import com.zhentao.service.AuthService;
+import com.zhentao.service.UserService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.web.bind.annotation.*;
 
@@ -18,6 +22,7 @@ import java.util.concurrent.TimeUnit;
 
 /**
  * 数据面板控制器
+ * 仅超级管理员可访问
  */
 @Slf4j
 @RestController
@@ -29,6 +34,12 @@ public class DashboardController {
     private final ActivityMapper activityMapper;
     private final RedisTemplate<String, Object> redisTemplate;
     
+    @Autowired
+    private AuthService authService;
+    
+    @Autowired
+    private UserService userService;
+    
     // Redis缓存键
     private static final String CACHE_KEY_STATS = "admin:dashboard:stats";
     private static final String CACHE_KEY_RECENT_ACTIVITIES = "admin:dashboard:recent_activities";
@@ -41,11 +52,30 @@ public class DashboardController {
         this.redisTemplate = redisTemplate;
     }
     
+    /**
+     * 检查当前用户是否是超级管理员
+     */
+    private boolean checkSuperAdmin(String token) {
+        if (token == null || token.isEmpty()) {
+            return false;
+        }
+        AdminUser user = authService.getUserByToken(token);
+        if (user == null) {
+            return false;
+        }
+        return userService.isSuperAdmin(user.getId());
+    }
+    
     /**
      * 获取统计数据(使用Redis缓存)
+     * 仅超级管理员可访问
      */
     @GetMapping("/stats")
-    public Result<Map<String, Object>> stats() {
+    public Result<Map<String, Object>> stats(@RequestHeader(value = "Authorization", required = false) String token) {
+        // 检查是否是超级管理员
+        if (!checkSuperAdmin(token)) {
+            return Result.error(403, "只有超级管理员可以访问数据面板");
+        }
         try {
             // 1. 先从Redis获取缓存
             Object cachedStats = redisTemplate.opsForValue().get(CACHE_KEY_STATS);
@@ -101,10 +131,16 @@ public class DashboardController {
     
     /**
      * 获取最近活动列表(使用Redis缓存)
+     * 仅超级管理员可访问
      */
     @GetMapping("/recent-activities")
     public Result<List<Activity>> getRecentActivities(
-            @RequestParam(defaultValue = "10") Integer limit) {
+            @RequestParam(defaultValue = "10") Integer limit,
+            @RequestHeader(value = "Authorization", required = false) String token) {
+        // 检查是否是超级管理员
+        if (!checkSuperAdmin(token)) {
+            return Result.error(403, "只有超级管理员可以访问数据面板");
+        }
         try {
             // 1. 先从Redis获取缓存
             String cacheKey = CACHE_KEY_RECENT_ACTIVITIES + ":" + limit;
@@ -143,9 +179,16 @@ public class DashboardController {
     
     /**
      * 获取用户增长趋势(真实数据)
+     * 仅超级管理员可访问
      */
     @GetMapping("/user-trend")
-    public Result<Map<String, Object>> getUserTrend(@RequestParam(defaultValue = "7") Integer days) {
+    public Result<Map<String, Object>> getUserTrend(
+            @RequestParam(defaultValue = "7") Integer days,
+            @RequestHeader(value = "Authorization", required = false) String token) {
+        // 检查是否是超级管理员
+        if (!checkSuperAdmin(token)) {
+            return Result.error(403, "只有超级管理员可以访问数据面板");
+        }
         try {
             Map<String, Object> result = new HashMap<>();
             List<String> dates = new ArrayList<>();
@@ -184,9 +227,16 @@ public class DashboardController {
     
     /**
      * 获取活动报名统计(真实数据)
+     * 仅超级管理员可访问
      */
     @GetMapping("/activity-stats")
-    public Result<Map<String, Object>> getActivityStats(@RequestParam(defaultValue = "7") Integer days) {
+    public Result<Map<String, Object>> getActivityStats(
+            @RequestParam(defaultValue = "7") Integer days,
+            @RequestHeader(value = "Authorization", required = false) String token) {
+        // 检查是否是超级管理员
+        if (!checkSuperAdmin(token)) {
+            return Result.error(403, "只有超级管理员可以访问数据面板");
+        }
         try {
             Map<String, Object> result = new HashMap<>();
             List<String> dates = new ArrayList<>();
@@ -225,9 +275,14 @@ public class DashboardController {
     
     /**
      * 清除缓存
+     * 仅超级管理员可访问
      */
     @DeleteMapping("/cache/clear")
-    public Result<String> clearCache() {
+    public Result<String> clearCache(@RequestHeader(value = "Authorization", required = false) String token) {
+        // 检查是否是超级管理员
+        if (!checkSuperAdmin(token)) {
+            return Result.error(403, "只有超级管理员可以访问数据面板");
+        }
         try {
             redisTemplate.delete(CACHE_KEY_STATS);
             redisTemplate.delete(CACHE_KEY_RECENT_ACTIVITIES + ":*");

+ 163 - 0
service/admin/src/main/java/com/zhentao/controller/MyResourceController.java

@@ -0,0 +1,163 @@
+package com.zhentao.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zhentao.common.Result;
+import com.zhentao.entity.MyResource;
+import com.zhentao.mapper.MyResourceMapper;
+import com.zhentao.service.MyResourceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 线索管理控制器
+ */
+@RestController
+@RequestMapping("/admin/my-resource")
+@CrossOrigin(origins = "*")
+public class MyResourceController {
+    
+    @Autowired
+    private MyResourceService myResourceService;
+    
+    /**
+     * 线索列表(分页查询)
+     * @param page 页码
+     * @param pageSize 每页数量
+     * @param name 名称(模糊查询)
+     * @param phone 手机号(模糊查询)
+     * @param status 审核状态(0-待审核,1-审核通过,2-审核失败)
+     * @param diploma 学历
+     * @param marrStatus 婚姻状况(0-未婚,1-离异,2-丧偶)
+     */
+    @GetMapping("/list")
+    public Result<Map<String, Object>> list(
+            @RequestParam(defaultValue = "1") Integer page,
+            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam(required = false) String name,
+            @RequestParam(required = false) String phone,
+            @RequestParam(required = false) Integer status,
+            @RequestParam(required = false) String diploma,
+            @RequestParam(required = false) Integer marrStatus) {
+        
+        try {
+            Page<MyResource> pageInfo = new Page<>(page, pageSize);
+            LambdaQueryWrapper<MyResource> queryWrapper = new LambdaQueryWrapper<>();
+            
+            // 只查询 isUser = 0 的数据
+            queryWrapper.eq(MyResource::getIsUser, 0);
+            
+            // 名称模糊查询
+            if (name != null && !name.trim().isEmpty()) {
+                queryWrapper.like(MyResource::getName, name.trim());
+            }
+            
+            // 手机号模糊查询
+            if (phone != null && !phone.trim().isEmpty()) {
+                queryWrapper.and(wrapper -> wrapper
+                    .like(MyResource::getPhone, phone.trim())
+                    .or()
+                    .like(MyResource::getBackupPhone, phone.trim())
+                );
+            }
+            
+            // 审核状态查询
+            if (status != null) {
+                queryWrapper.eq(MyResource::getStatus, status);
+            }
+            
+            // 学历查询
+            if (diploma != null && !diploma.trim().isEmpty()) {
+                queryWrapper.eq(MyResource::getDiploma, diploma.trim());
+            }
+            
+            // 婚姻状况查询
+            if (marrStatus != null) {
+                queryWrapper.eq(MyResource::getMarrStatus, marrStatus);
+            }
+            
+            // 按创建时间倒序
+            queryWrapper.orderByDesc(MyResource::getCreateTime);
+            
+            Page<MyResource> result = myResourceService.page(pageInfo, queryWrapper);
+            
+            Map<String, Object> data = new HashMap<>();
+            data.put("list", result.getRecords());
+            data.put("total", result.getTotal());
+            data.put("page", page);
+            data.put("pageSize", pageSize);
+            
+            return Result.success(data);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询失败:" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 获取线索详情
+     * @param id 线索ID
+     */
+    @GetMapping("/{id}")
+    public Result<MyResource> detail(@PathVariable Integer id) {
+        try {
+            MyResource resource = myResourceService.getById(id);
+            if (resource == null) {
+                return Result.error("线索不存在");
+            }
+            
+            if (resource.getIsUser() != null && resource.getIsUser() != 0) {
+                return Result.error("该线索不是待审核线索");
+            }
+            
+            return Result.success(resource);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询失败:" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 审核线索
+     * @param id 线索ID
+     * @param status 审核状态(1-审核通过,2-审核失败)
+     * @param rejectReason 审核失败原因(可选)
+     */
+    @PutMapping("/{id}/audit")
+    public Result<String> audit(
+            @PathVariable Integer id,
+            @RequestParam Integer status,
+            @RequestParam(required = false) String rejectReason) {
+        try {
+            MyResource resource = myResourceService.getById(id);
+            if (resource == null) {
+                return Result.error("线索不存在");
+            }
+            
+            if (status == null || (status != 1 && status != 2)) {
+                return Result.error("审核状态参数错误");
+            }
+            
+            resource.setStatus(status);
+            if (status == 2 && rejectReason != null && !rejectReason.trim().isEmpty()) {
+                resource.setRejectReason(rejectReason.trim());
+            } else if (status == 1) {
+                resource.setRejectReason(null);
+            }
+            
+            boolean success = myResourceService.updateById(resource);
+            if (success) {
+                return Result.success(status == 1 ? "审核通过成功" : "审核失败成功");
+            } else {
+                return Result.error("审核失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("审核失败:" + e.getMessage());
+        }
+    }
+}
+

+ 215 - 0
service/admin/src/main/java/com/zhentao/controller/PointsOrderController.java

@@ -0,0 +1,215 @@
+package com.zhentao.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zhentao.common.Result;
+import com.zhentao.entity.PointsOrder;
+import com.zhentao.mapper.PointsOrderMapper;
+import com.zhentao.service.PointsOrderService;
+import com.zhentao.service.SystemMessagesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 积分订单管理控制器
+ */
+@RestController
+@RequestMapping("/admin/points-order")
+@CrossOrigin(origins = "*")
+public class PointsOrderController {
+    
+    @Autowired
+    private PointsOrderService pointsOrderService;
+    
+    @Autowired
+    private PointsOrderMapper pointsOrderMapper;
+    
+    @Autowired
+    private SystemMessagesService systemMessagesService;
+    
+    /**
+     * 积分订单列表(分页查询)
+     * @param page 页码
+     * @param pageSize 每页数量
+     * @param orderNo 订单号(模糊查询)
+     * @param productName 产品名称(模糊查询)
+     * @param review 审核状态(0-待审核,1-审核通过,2-审核未通过)
+     * @param status 发货状态(0-待发货,1-已发货,2-已完成,3-已取消)
+     */
+    @GetMapping("/list")
+    public Result<Map<String, Object>> list(
+            @RequestParam(defaultValue = "1") Integer page,
+            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam(required = false) String orderNo,
+            @RequestParam(required = false) String productName,
+            @RequestParam(required = false) Integer review,
+            @RequestParam(required = false) Integer status) {
+        
+        try {
+            Page<PointsOrder> pageInfo = new Page<>(page, pageSize);
+            LambdaQueryWrapper<PointsOrder> queryWrapper = new LambdaQueryWrapper<>();
+            
+            // 只查询未删除的记录(is_del = 0)
+            queryWrapper.eq(PointsOrder::getIsDel, 0);
+            
+            // 订单号模糊查询
+            if (orderNo != null && !orderNo.trim().isEmpty()) {
+                queryWrapper.like(PointsOrder::getOrderNo, orderNo.trim());
+            }
+            
+            // 产品名称模糊查询
+            if (productName != null && !productName.trim().isEmpty()) {
+                queryWrapper.like(PointsOrder::getProductName, productName.trim());
+            }
+            
+            // 审核状态查询
+            if (review != null) {
+                queryWrapper.eq(PointsOrder::getReview, review);
+            }
+            
+            // 发货状态查询
+            if (status != null) {
+                queryWrapper.eq(PointsOrder::getStatus, status);
+            }
+            
+            // 按创建时间倒序
+            queryWrapper.orderByDesc(PointsOrder::getCreateTime);
+            
+            Page<PointsOrder> result = pointsOrderService.page(pageInfo, queryWrapper);
+            
+            Map<String, Object> data = new HashMap<>();
+            data.put("list", result.getRecords());
+            data.put("total", result.getTotal());
+            data.put("page", page);
+            data.put("pageSize", pageSize);
+            
+            return Result.success(data);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询失败:" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 审核订单
+     * @param id 订单ID
+     * @param review 审核结果(1-审核通过,2-审核未通过)
+     * @param reviewFail 审核失败说明(审核未通过时必填)
+     */
+    @PostMapping("/review/{id}")
+    public Result<String> review(
+            @PathVariable Long id,
+            @RequestParam Integer review,
+            @RequestParam(required = false) String reviewFail) {
+        
+        try {
+            PointsOrder order = pointsOrderService.getById(id);
+            if (order == null) {
+                return Result.error("订单不存在");
+            }
+            
+            if (order.getIsDel() != null && order.getIsDel() == 1) {
+                return Result.error("订单已删除");
+            }
+            
+            // 验证审核结果
+            if (review == null || (review != 1 && review != 2)) {
+                return Result.error("审核结果无效,必须为1(通过)或2(不通过)");
+            }
+            
+            // 如果审核不通过,必须提供失败说明
+            if (review == 2) {
+                if (reviewFail == null || reviewFail.trim().isEmpty()) {
+                    return Result.error("审核不通过时必须填写审核失败说明");
+                }
+                order.setReviewFail(reviewFail.trim());
+            } else {
+                // 审核通过时清空失败说明
+                order.setReviewFail(null);
+            }
+            
+            order.setReview(review);
+            order.setUpdateTime(new Date());
+            
+            boolean success = pointsOrderService.updateById(order);
+            if (success) {
+                System.out.println("订单审核更新成功,订单ID=" + id + ", 审核状态=" + review);
+                System.out.println("订单信息 - 订单号: " + order.getOrderNo() + ", 收件人电话: " + order.getReceiverPhone());
+                
+                // 创建系统消息
+                try {
+                    System.out.println("开始调用系统消息创建方法...");
+                    systemMessagesService.createPointsOrderReviewMessage(order);
+                    System.out.println("系统消息创建方法调用完成");
+                } catch (Exception e) {
+                    // 系统消息创建失败不影响审核结果,只记录日志
+                    System.err.println("创建系统消息失败:" + e.getMessage());
+                    e.printStackTrace();
+                }
+                
+                return Result.success(review == 1 ? "审核通过成功" : "审核不通过已记录");
+            } else {
+                return Result.error("审核失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("审核失败:" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 删除订单(逻辑删除)
+     * @param id 订单ID
+     */
+    @DeleteMapping("/{id}")
+    public Result<String> delete(@PathVariable Long id) {
+        try {
+            PointsOrder order = pointsOrderService.getById(id);
+            if (order == null) {
+                return Result.error("订单不存在");
+            }
+            
+            // 逻辑删除:设置is_del = 1
+            order.setIsDel(1);
+            order.setUpdateTime(new Date());
+            
+            boolean success = pointsOrderService.updateById(order);
+            if (success) {
+                return Result.success("删除成功");
+            } else {
+                return Result.error("删除失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("删除失败:" + e.getMessage());
+        }
+    }
+    
+    /**
+     * 获取订单详情
+     * @param id 订单ID
+     */
+    @GetMapping("/{id}")
+    public Result<PointsOrder> detail(@PathVariable Long id) {
+        try {
+            PointsOrder order = pointsOrderService.getById(id);
+            if (order == null) {
+                return Result.error("订单不存在");
+            }
+            
+            if (order.getIsDel() != null && order.getIsDel() == 1) {
+                return Result.error("订单已删除");
+            }
+            
+            return Result.success(order);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("查询失败:" + e.getMessage());
+        }
+    }
+}
+

+ 257 - 0
service/admin/src/main/java/com/zhentao/entity/MyResource.java

@@ -0,0 +1,257 @@
+package com.zhentao.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 红娘资源表
+
+ * @TableName my_resource
+ */
+@TableName(value ="my_resource")
+@Data
+public class MyResource {
+    /**
+     * 
+     */
+    @TableId(type = IdType.AUTO)
+    private Integer resourceId;
+
+    /**
+     * 用户id
+     */
+    private Integer userId;
+
+    /**
+     * 审核状态(0:待审核,1:审核通过,2:审核失败)
+     */
+    private Integer status;
+
+    /**
+     * 审核失败原因
+     */
+    private String rejectReason;
+
+    /**
+     * 奖励积分(用于后台开发人员计算红娘积分)
+     */
+    private Integer rewardPoints;
+
+    /**
+     * 红娘id
+     */
+    private Integer matchmakerId;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 年龄
+     */
+    private Integer age;
+
+    /**
+     * 性别(1:男,2:女)
+     */
+    private Integer gender;
+
+    /**
+     * 星座
+     */
+    private String constellation;
+
+    /**
+     * 身高
+     */
+    private Integer height;
+
+    /**
+     * 体重
+     */
+    private Integer weight;
+
+    /**
+     * 婚姻状况(0未婚,1离异,2丧偶)
+     */
+    private Integer marrStatus;
+
+    /**
+     * 学历('高中', '专科', '本科', '硕士', '博士', '无')
+     */
+    private String diploma;
+
+    /**
+     * 收入('1-5k', '5-10k', '10-20k', '20-50k', '50k+')
+     */
+    private String income;
+
+    /**
+     * 住址
+     */
+    private String address;
+
+    /**
+     * 户籍所在地
+     */
+    private String domicile;
+
+    /**
+     * 职业
+     */
+    private String occupation;
+
+    /**
+     * 购房(0:无,1:有)
+     */
+    private Integer house;
+
+    /**
+     * 择偶要求
+     */
+    private String mateSelectionCriteria;
+
+    /**
+     * 手机号
+     */
+    private String phone;
+
+    /**
+     * 备用手机号
+     */
+    private String backupPhone;
+
+    /**
+     * 购车(0:无,1:有)
+     */
+    private Integer car;
+
+    /**
+     * 
+     */
+    private Date createTime;
+
+    /**
+     * 
+     */
+    private Date updateTime;
+
+    /**
+     * 该资源是否已注册用户 0未注册 1已注册 默认0 未注册标签为待审核 已注册标签为已审核 2审核失败
+     */
+    private Integer isUser;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        MyResource other = (MyResource) that;
+        return (this.getResourceId() == null ? other.getResourceId() == null : this.getResourceId().equals(other.getResourceId()))
+            && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getRejectReason() == null ? other.getRejectReason() == null : this.getRejectReason().equals(other.getRejectReason()))
+            && (this.getRewardPoints() == null ? other.getRewardPoints() == null : this.getRewardPoints().equals(other.getRewardPoints()))
+            && (this.getMatchmakerId() == null ? other.getMatchmakerId() == null : this.getMatchmakerId().equals(other.getMatchmakerId()))
+            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
+            && (this.getAge() == null ? other.getAge() == null : this.getAge().equals(other.getAge()))
+            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
+            && (this.getConstellation() == null ? other.getConstellation() == null : this.getConstellation().equals(other.getConstellation()))
+            && (this.getHeight() == null ? other.getHeight() == null : this.getHeight().equals(other.getHeight()))
+            && (this.getWeight() == null ? other.getWeight() == null : this.getWeight().equals(other.getWeight()))
+            && (this.getMarrStatus() == null ? other.getMarrStatus() == null : this.getMarrStatus().equals(other.getMarrStatus()))
+            && (this.getDiploma() == null ? other.getDiploma() == null : this.getDiploma().equals(other.getDiploma()))
+            && (this.getIncome() == null ? other.getIncome() == null : this.getIncome().equals(other.getIncome()))
+            && (this.getAddress() == null ? other.getAddress() == null : this.getAddress().equals(other.getAddress()))
+            && (this.getDomicile() == null ? other.getDomicile() == null : this.getDomicile().equals(other.getDomicile()))
+            && (this.getOccupation() == null ? other.getOccupation() == null : this.getOccupation().equals(other.getOccupation()))
+            && (this.getHouse() == null ? other.getHouse() == null : this.getHouse().equals(other.getHouse()))
+            && (this.getMateSelectionCriteria() == null ? other.getMateSelectionCriteria() == null : this.getMateSelectionCriteria().equals(other.getMateSelectionCriteria()))
+            && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
+            && (this.getBackupPhone() == null ? other.getBackupPhone() == null : this.getBackupPhone().equals(other.getBackupPhone()))
+            && (this.getCar() == null ? other.getCar() == null : this.getCar().equals(other.getCar()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
+            && (this.getIsUser() == null ? other.getIsUser() == null : this.getIsUser().equals(other.getIsUser()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getResourceId() == null) ? 0 : getResourceId().hashCode());
+        result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getRejectReason() == null) ? 0 : getRejectReason().hashCode());
+        result = prime * result + ((getRewardPoints() == null) ? 0 : getRewardPoints().hashCode());
+        result = prime * result + ((getMatchmakerId() == null) ? 0 : getMatchmakerId().hashCode());
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getAge() == null) ? 0 : getAge().hashCode());
+        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
+        result = prime * result + ((getConstellation() == null) ? 0 : getConstellation().hashCode());
+        result = prime * result + ((getHeight() == null) ? 0 : getHeight().hashCode());
+        result = prime * result + ((getWeight() == null) ? 0 : getWeight().hashCode());
+        result = prime * result + ((getMarrStatus() == null) ? 0 : getMarrStatus().hashCode());
+        result = prime * result + ((getDiploma() == null) ? 0 : getDiploma().hashCode());
+        result = prime * result + ((getIncome() == null) ? 0 : getIncome().hashCode());
+        result = prime * result + ((getAddress() == null) ? 0 : getAddress().hashCode());
+        result = prime * result + ((getDomicile() == null) ? 0 : getDomicile().hashCode());
+        result = prime * result + ((getOccupation() == null) ? 0 : getOccupation().hashCode());
+        result = prime * result + ((getHouse() == null) ? 0 : getHouse().hashCode());
+        result = prime * result + ((getMateSelectionCriteria() == null) ? 0 : getMateSelectionCriteria().hashCode());
+        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
+        result = prime * result + ((getBackupPhone() == null) ? 0 : getBackupPhone().hashCode());
+        result = prime * result + ((getCar() == null) ? 0 : getCar().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        result = prime * result + ((getIsUser() == null) ? 0 : getIsUser().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", resourceId=").append(resourceId);
+        sb.append(", userId=").append(userId);
+        sb.append(", status=").append(status);
+        sb.append(", rejectReason=").append(rejectReason);
+        sb.append(", rewardPoints=").append(rewardPoints);
+        sb.append(", matchmakerId=").append(matchmakerId);
+        sb.append(", name=").append(name);
+        sb.append(", age=").append(age);
+        sb.append(", gender=").append(gender);
+        sb.append(", constellation=").append(constellation);
+        sb.append(", height=").append(height);
+        sb.append(", weight=").append(weight);
+        sb.append(", marrStatus=").append(marrStatus);
+        sb.append(", diploma=").append(diploma);
+        sb.append(", income=").append(income);
+        sb.append(", address=").append(address);
+        sb.append(", domicile=").append(domicile);
+        sb.append(", occupation=").append(occupation);
+        sb.append(", house=").append(house);
+        sb.append(", mateSelectionCriteria=").append(mateSelectionCriteria);
+        sb.append(", phone=").append(phone);
+        sb.append(", backupPhone=").append(backupPhone);
+        sb.append(", car=").append(car);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", isUser=").append(isUser);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 175 - 49
service/admin/src/main/java/com/zhentao/entity/PointsOrder.java

@@ -1,74 +1,200 @@
 package com.zhentao.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.Date;
 import lombok.Data;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
- * 积分兑换订单实体类
+ * 
+ * @TableName points_order 积分订单实体类
  */
+@TableName(value ="points_order")
 @Data
-@TableName("points_order")
-public class PointsOrder implements Serializable {
-    
-    private static final long serialVersionUID = 1L;
-    
-    @TableId(value = "id", type = IdType.AUTO)
+public class PointsOrder {
+    /**
+     * 
+     */
+    @TableId(type = IdType.AUTO)
     private Long id;
-    
-    /** 订单编号 */
+
+    /**
+     * 订单号
+     */
     private String orderNo;
-    
-    /** 红娘ID */
+
+    /**
+     * 红娘ID
+     */
     private Long makerId;
-    
-    /** 商品ID */
+
+    /**
+     * 产品ID
+     */
     private Long productId;
-    
-    /** 商品名称 */
+
+    /**
+     * 产品名称
+     */
     private String productName;
-    
-    /** 商品图片 */
+
+    /**
+     * 产品图片
+     */
     private String productImage;
-    
-    /** 兑换积分 */
+
+    /**
+     * 积分价格
+     */
     private Integer pointsPrice;
-    
-    /** 数量 */
+
+    /**
+     * 数量
+     */
     private Integer quantity;
-    
-    /** 总积分 */
+
+    /**
+     * 审核0-待审核,1-审核通过2,审核未通过
+     */
+    private Integer review;
+    /**
+     * 审核失败说明
+     */
+    private String reviewFail;
+
+    /**
+     * 总积分
+     */
     private Integer totalPoints;
-    
-    /** 状态: 0-待审核 1-审核通过 2-已完成 3-已拒绝 */
+
+    /**
+     * 0-待发货 1-已发货 2-已完成 3-已取消
+     */
     private Integer status;
-    
-    /** 收货人姓名 */
+
+    /**
+     * 收件人姓名
+     */
     private String receiverName;
-    
-    /** 收货人电话 */
+
+    /**
+     * 收件人电话
+     */
     private String receiverPhone;
-    
-    /** 收货地址 */
+
+    /**
+     * 收件人地址
+     */
     private String receiverAddress;
-    
-    /** 快递公司 */
+
+    /**
+     * 快递公司
+     */
     private String expressCompany;
-    
-    /** 快递单号 */
+
+    /**
+     * 快递单号
+     */
     private String expressNo;
-    
-    /** 备注 */
-    private String remark;
-    
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-    
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-}
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+    /**
+     * 是否删除 0-否,1-是
+     * */
+    private Integer isDel;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        PointsOrder other = (PointsOrder) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getOrderNo() == null ? other.getOrderNo() == null : this.getOrderNo().equals(other.getOrderNo()))
+            && (this.getMakerId() == null ? other.getMakerId() == null : this.getMakerId().equals(other.getMakerId()))
+            && (this.getProductId() == null ? other.getProductId() == null : this.getProductId().equals(other.getProductId()))
+            && (this.getProductName() == null ? other.getProductName() == null : this.getProductName().equals(other.getProductName()))
+            && (this.getProductImage() == null ? other.getProductImage() == null : this.getProductImage().equals(other.getProductImage()))
+            && (this.getPointsPrice() == null ? other.getPointsPrice() == null : this.getPointsPrice().equals(other.getPointsPrice()))
+            && (this.getQuantity() == null ? other.getQuantity() == null : this.getQuantity().equals(other.getQuantity()))
+            && (this.getReview() == null ? other.getReview() == null : this.getReview().equals(other.getReview()))
+            && (this.getTotalPoints() == null ? other.getTotalPoints() == null : this.getTotalPoints().equals(other.getTotalPoints()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getReceiverName() == null ? other.getReceiverName() == null : this.getReceiverName().equals(other.getReceiverName()))
+            && (this.getReceiverPhone() == null ? other.getReceiverPhone() == null : this.getReceiverPhone().equals(other.getReceiverPhone()))
+            && (this.getReceiverAddress() == null ? other.getReceiverAddress() == null : this.getReceiverAddress().equals(other.getReceiverAddress()))
+            && (this.getExpressCompany() == null ? other.getExpressCompany() == null : this.getExpressCompany().equals(other.getExpressCompany()))
+            && (this.getExpressNo() == null ? other.getExpressNo() == null : this.getExpressNo().equals(other.getExpressNo()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getOrderNo() == null) ? 0 : getOrderNo().hashCode());
+        result = prime * result + ((getMakerId() == null) ? 0 : getMakerId().hashCode());
+        result = prime * result + ((getProductId() == null) ? 0 : getProductId().hashCode());
+        result = prime * result + ((getProductName() == null) ? 0 : getProductName().hashCode());
+        result = prime * result + ((getProductImage() == null) ? 0 : getProductImage().hashCode());
+        result = prime * result + ((getPointsPrice() == null) ? 0 : getPointsPrice().hashCode());
+        result = prime * result + ((getQuantity() == null) ? 0 : getQuantity().hashCode());
+        result = prime * result + ((getReview() == null) ? 0 : getReview().hashCode());
+        result = prime * result + ((getTotalPoints() == null) ? 0 : getTotalPoints().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getReceiverName() == null) ? 0 : getReceiverName().hashCode());
+        result = prime * result + ((getReceiverPhone() == null) ? 0 : getReceiverPhone().hashCode());
+        result = prime * result + ((getReceiverAddress() == null) ? 0 : getReceiverAddress().hashCode());
+        result = prime * result + ((getExpressCompany() == null) ? 0 : getExpressCompany().hashCode());
+        result = prime * result + ((getExpressNo() == null) ? 0 : getExpressNo().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", orderNo=").append(orderNo);
+        sb.append(", makerId=").append(makerId);
+        sb.append(", productId=").append(productId);
+        sb.append(", productName=").append(productName);
+        sb.append(", productImage=").append(productImage);
+        sb.append(", pointsPrice=").append(pointsPrice);
+        sb.append(", quantity=").append(quantity);
+        sb.append(", review=").append(review);
+        sb.append(", totalPoints=").append(totalPoints);
+        sb.append(", status=").append(status);
+        sb.append(", receiverName=").append(receiverName);
+        sb.append(", receiverPhone=").append(receiverPhone);
+        sb.append(", receiverAddress=").append(receiverAddress);
+        sb.append(", expressCompany=").append(expressCompany);
+        sb.append(", expressNo=").append(expressNo);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 120 - 0
service/admin/src/main/java/com/zhentao/entity/SystemMessages.java

@@ -0,0 +1,120 @@
+package com.zhentao.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 系统消息
+ * @TableName system_messages
+ */
+@TableName(value ="system_messages")
+@Data
+public class SystemMessages {
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 接收用户ID
+     */
+    private Integer userId;
+
+    /**
+     * ban/unban/delete等
+     */
+    private String type;
+
+    /**
+     * 关联动态ID
+     */
+    private Integer relatedDynamicId;
+
+    /**
+     * 标题
+     */
+    private String title;
+
+    /**
+     * 正文内容
+     */
+    private String content;
+
+    /**
+     * 0未读 1已读
+     */
+    private Integer isRead;
+
+    /**
+     * 创建时间
+     */
+    private Date createdAt;
+
+    /**
+     * 已读时间
+     */
+    private Date readAt;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        SystemMessages other = (SystemMessages) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId()))
+            && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType()))
+            && (this.getRelatedDynamicId() == null ? other.getRelatedDynamicId() == null : this.getRelatedDynamicId().equals(other.getRelatedDynamicId()))
+            && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()))
+            && (this.getContent() == null ? other.getContent() == null : this.getContent().equals(other.getContent()))
+            && (this.getIsRead() == null ? other.getIsRead() == null : this.getIsRead().equals(other.getIsRead()))
+            && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt()))
+            && (this.getReadAt() == null ? other.getReadAt() == null : this.getReadAt().equals(other.getReadAt()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode());
+        result = prime * result + ((getType() == null) ? 0 : getType().hashCode());
+        result = prime * result + ((getRelatedDynamicId() == null) ? 0 : getRelatedDynamicId().hashCode());
+        result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
+        result = prime * result + ((getContent() == null) ? 0 : getContent().hashCode());
+        result = prime * result + ((getIsRead() == null) ? 0 : getIsRead().hashCode());
+        result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode());
+        result = prime * result + ((getReadAt() == null) ? 0 : getReadAt().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", userId=").append(userId);
+        sb.append(", type=").append(type);
+        sb.append(", relatedDynamicId=").append(relatedDynamicId);
+        sb.append(", title=").append(title);
+        sb.append(", content=").append(content);
+        sb.append(", isRead=").append(isRead);
+        sb.append(", createdAt=").append(createdAt);
+        sb.append(", readAt=").append(readAt);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 19 - 0
service/admin/src/main/java/com/zhentao/mapper/MyResourceMapper.java

@@ -0,0 +1,19 @@
+package com.zhentao.mapper;
+
+import com.zhentao.entity.MyResource;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 联想
+* @description 针对表【my_resource(红娘资源表
+)】的数据库操作Mapper
+* @createDate 2025-12-12 16:36:15
+* @Entity com.zhentao.entity.MyResource
+*/
+public interface MyResourceMapper extends BaseMapper<MyResource> {
+
+}
+
+
+
+

+ 11 - 5
service/admin/src/main/java/com/zhentao/mapper/PointsOrderMapper.java

@@ -1,12 +1,18 @@
 package com.zhentao.mapper;
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zhentao.entity.PointsOrder;
-import org.apache.ibatis.annotations.Mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
- * 积分兑换订单Mapper
- */
-@Mapper
+* @author 联想
+* @description 针对表【points_order】的数据库操作Mapper
+* @createDate 2025-12-12 14:07:01
+* @Entity com.zhentao.entity.PointsOrder
+*/
 public interface PointsOrderMapper extends BaseMapper<PointsOrder> {
+
 }
+
+
+
+

+ 18 - 0
service/admin/src/main/java/com/zhentao/mapper/SystemMessagesMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.mapper;
+
+import com.zhentao.entity.SystemMessages;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 联想
+* @description 针对表【system_messages(系统消息)】的数据库操作Mapper
+* @createDate 2025-12-12 14:54:02
+* @Entity com.zhentao.entity.SystemMessages
+*/
+public interface SystemMessagesMapper extends BaseMapper<SystemMessages> {
+
+}
+
+
+
+

+ 14 - 0
service/admin/src/main/java/com/zhentao/service/MyResourceService.java

@@ -0,0 +1,14 @@
+package com.zhentao.service;
+
+import com.zhentao.entity.MyResource;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 联想
+* @description 针对表【my_resource(红娘资源表
+)】的数据库操作Service
+* @createDate 2025-12-12 16:36:15
+*/
+public interface MyResourceService extends IService<MyResource> {
+
+}

+ 13 - 0
service/admin/src/main/java/com/zhentao/service/PointsOrderService.java

@@ -0,0 +1,13 @@
+package com.zhentao.service;
+
+import com.zhentao.entity.PointsOrder;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 联想
+* @description 针对表【points_order】的数据库操作Service
+* @createDate 2025-12-12 14:07:01
+*/
+public interface PointsOrderService extends IService<PointsOrder> {
+
+}

+ 19 - 0
service/admin/src/main/java/com/zhentao/service/SystemMessagesService.java

@@ -0,0 +1,19 @@
+package com.zhentao.service;
+
+import com.zhentao.entity.PointsOrder;
+import com.zhentao.entity.SystemMessages;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author 联想
+* @description 针对表【system_messages(系统消息)】的数据库操作Service
+* @createDate 2025-12-12 14:54:02
+*/
+public interface SystemMessagesService extends IService<SystemMessages> {
+    
+    /**
+     * 创建积分商城订单审核系统消息
+     * @param pointsOrder 积分订单
+     */
+    void createPointsOrderReviewMessage(PointsOrder pointsOrder);
+}

+ 23 - 0
service/admin/src/main/java/com/zhentao/service/impl/MyResourceServiceImpl.java

@@ -0,0 +1,23 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.entity.MyResource;
+import com.zhentao.service.MyResourceService;
+import com.zhentao.mapper.MyResourceMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 联想
+* @description 针对表【my_resource(红娘资源表
+)】的数据库操作Service实现
+* @createDate 2025-12-12 16:36:15
+*/
+@Service
+public class MyResourceServiceImpl extends ServiceImpl<MyResourceMapper, MyResource>
+    implements MyResourceService{
+
+}
+
+
+
+

+ 3 - 2
service/admin/src/main/java/com/zhentao/service/impl/PointsMallServiceImpl.java

@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 
@@ -173,8 +174,8 @@ public class PointsMallServiceImpl implements PointsMallService {
         order.setTotalPoints(totalPoints);
         order.setStatus(0); // 0-待审核
         order.setReceiverPhone(contactPhone); // 联系电话
-        order.setCreateTime(LocalDateTime.now());
-        order.setUpdateTime(LocalDateTime.now());
+        order.setCreateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
+        order.setUpdateTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
 
         pointsOrderMapper.insert(order);
 

+ 22 - 0
service/admin/src/main/java/com/zhentao/service/impl/PointsOrderServiceImpl.java

@@ -0,0 +1,22 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.entity.PointsOrder;
+import com.zhentao.service.PointsOrderService;
+import com.zhentao.mapper.PointsOrderMapper;
+import org.springframework.stereotype.Service;
+
+/**
+* @author 联想
+* @description 针对表【points_order】的数据库操作Service实现
+* @createDate 2025-12-12 14:07:01
+*/
+@Service
+public class PointsOrderServiceImpl extends ServiceImpl<PointsOrderMapper, PointsOrder>
+    implements PointsOrderService{
+
+}
+
+
+
+

+ 142 - 0
service/admin/src/main/java/com/zhentao/service/impl/SystemMessagesServiceImpl.java

@@ -0,0 +1,142 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.entity.PointsOrder;
+import com.zhentao.entity.SystemMessages;
+import com.zhentao.entity.Users;
+import com.zhentao.mapper.SystemMessagesMapper;
+import com.zhentao.mapper.UsersMapper;
+import com.zhentao.service.SystemMessagesService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+
+/**
+* @author 联想
+* @description 针对表【system_messages(系统消息)】的数据库操作Service实现
+* @createDate 2025-12-12 14:54:02
+*/
+@Service
+public class SystemMessagesServiceImpl extends ServiceImpl<SystemMessagesMapper, SystemMessages>
+    implements SystemMessagesService{
+
+    @Autowired
+    private UsersMapper usersMapper;
+    
+    @Autowired
+    private SystemMessagesMapper systemMessagesMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void createPointsOrderReviewMessage(PointsOrder pointsOrder) {
+        System.out.println("========== 开始创建积分订单审核系统消息 ==========");
+        System.out.println("订单信息: " + (pointsOrder != null ? pointsOrder.toString() : "null"));
+        
+        if (pointsOrder == null) {
+            System.err.println("错误:pointsOrder 为 null,无法创建系统消息");
+            return;
+        }
+        
+        if (pointsOrder.getReceiverPhone() == null || pointsOrder.getReceiverPhone().trim().isEmpty()) {
+            System.err.println("错误:订单收件人电话为空,订单ID=" + pointsOrder.getId() + ",订单号=" + pointsOrder.getOrderNo());
+            return;
+        }
+
+        System.out.println("收件人电话: " + pointsOrder.getReceiverPhone());
+        System.out.println("订单号: " + pointsOrder.getOrderNo());
+        System.out.println("审核状态: " + pointsOrder.getReview());
+        
+        // 检查订单号是否为空
+        if (pointsOrder.getOrderNo() == null || pointsOrder.getOrderNo().trim().isEmpty()) {
+            System.err.println("错误:订单号为空,订单ID=" + pointsOrder.getId() + ",无法创建系统消息");
+            return;
+        }
+
+        // 通过收件人电话查询用户ID
+        LambdaQueryWrapper<Users> userWrapper = new LambdaQueryWrapper<>();
+        userWrapper.eq(Users::getPhone, pointsOrder.getReceiverPhone());
+        Users user = usersMapper.selectOne(userWrapper);
+
+        if (user == null) {
+            System.err.println("错误:未找到手机号为 " + pointsOrder.getReceiverPhone() + " 的用户,无法创建系统消息");
+            return;
+        }
+        
+        if (user.getUserId() == null) {
+            System.err.println("错误:找到用户但 userId 为 null,手机号=" + pointsOrder.getReceiverPhone());
+            return;
+        }
+
+        System.out.println("找到用户: userId=" + user.getUserId() + ", phone=" + user.getPhone());
+
+        // 创建系统消息
+        SystemMessages message = new SystemMessages();
+        message.setUserId(user.getUserId());
+        message.setTitle("系统通知-积分商城货物通知");
+        message.setType("points_order_review"); // 设置消息类型为积分订单审核
+        
+        // 根据审核状态设置内容
+        if (pointsOrder.getReview() != null) {
+            if (pointsOrder.getReview() == 1) {
+                // 审核通过
+                String content = "订单号为\"" + pointsOrder.getOrderNo() + "\"的货物,经过管理人员审核成功,准备发送货物。";
+                message.setContent(content);
+                System.out.println("审核通过,消息内容: " + content);
+            } else if (pointsOrder.getReview() == 2) {
+                // 审核未通过
+                String reviewFailReason = pointsOrder.getReviewFail() != null ? pointsOrder.getReviewFail() : "未说明原因";
+                String content = "订单号为\"" + pointsOrder.getOrderNo() + "\"的货物,经过管理人员审核,表示未通过,具体原因是" + reviewFailReason;
+                message.setContent(content);
+                System.out.println("审核未通过,消息内容: " + content);
+            } else {
+                // 其他状态,不创建消息
+                System.out.println("审核状态为其他值(" + pointsOrder.getReview() + "),不创建消息");
+                return;
+            }
+        } else {
+            // 审核状态为空,不创建消息
+            System.err.println("错误:审核状态为 null,不创建消息");
+            return;
+        }
+
+        message.setIsRead(0); // 0-未读
+        message.setCreatedAt(new Date());
+        
+        System.out.println("准备保存系统消息: userId=" + message.getUserId() + ", title=" + message.getTitle() + ", content=" + message.getContent());
+        System.out.println("消息对象详情: " + message.toString());
+        
+        // 保存系统消息 - 使用 systemMessagesMapper.insert() 直接插入
+        try {
+            int insertResult = systemMessagesMapper.insert(message);
+            if (insertResult > 0) {
+                System.out.println("系统消息保存成功!插入行数=" + insertResult + ", 消息ID=" + (message.getId() != null ? message.getId() : "待生成"));
+                System.out.println("保存后的消息对象: " + message.toString());
+                
+                // 验证数据是否真的插入到数据库
+                if (message.getId() != null) {
+                    SystemMessages savedMessage = systemMessagesMapper.selectById(message.getId());
+                    if (savedMessage != null) {
+                        System.out.println("验证成功:从数据库查询到保存的消息,ID=" + savedMessage.getId());
+                    } else {
+                        System.err.println("警告:消息保存后无法从数据库查询到,可能存在事务问题");
+                    }
+                }
+            } else {
+                System.err.println("系统消息保存失败!insert() 方法返回 0,未插入任何数据");
+            }
+        } catch (Exception e) {
+            System.err.println("系统消息保存时发生异常:" + e.getMessage());
+            e.printStackTrace();
+            throw new RuntimeException("保存系统消息失败:" + e.getMessage(), e);
+        }
+        
+        System.out.println("========== 创建积分订单审核系统消息完成 ==========");
+    }
+}
+
+
+
+

+ 43 - 0
service/admin/src/main/resources/com/zhentao/mapper/MyResourceMapper.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.MyResourceMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.entity.MyResource">
+            <id property="resourceId" column="resource_id" />
+            <result property="userId" column="user_id" />
+            <result property="status" column="status" />
+            <result property="rejectReason" column="reject_reason" />
+            <result property="rewardPoints" column="reward_points" />
+            <result property="matchmakerId" column="matchmaker_id" />
+            <result property="name" column="name" />
+            <result property="age" column="age" />
+            <result property="gender" column="gender" />
+            <result property="constellation" column="constellation" />
+            <result property="height" column="height" />
+            <result property="weight" column="weight" />
+            <result property="marrStatus" column="marr_status" />
+            <result property="diploma" column="diploma" />
+            <result property="income" column="income" />
+            <result property="address" column="address" />
+            <result property="domicile" column="domicile" />
+            <result property="occupation" column="occupation" />
+            <result property="house" column="house" />
+            <result property="mateSelectionCriteria" column="mate_selection_criteria" />
+            <result property="phone" column="phone" />
+            <result property="backupPhone" column="backup_phone" />
+            <result property="car" column="car" />
+            <result property="createTime" column="create_time" />
+            <result property="updateTime" column="update_time" />
+            <result property="isUser" column="is_user" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        resource_id,user_id,status,reject_reason,reward_points,matchmaker_id,
+        name,age,gender,constellation,height,
+        weight,marr_status,diploma,income,address,
+        domicile,occupation,house,mate_selection_criteria,phone,
+        backup_phone,car,create_time,update_time,is_user
+    </sql>
+</mapper>

+ 34 - 0
service/admin/src/main/resources/com/zhentao/mapper/PointsOrderMapper.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.PointsOrderMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.entity.PointsOrder">
+            <id property="id" column="id" />
+            <result property="orderNo" column="order_no" />
+            <result property="makerId" column="maker_id" />
+            <result property="productId" column="product_id" />
+            <result property="productName" column="product_name" />
+            <result property="productImage" column="product_image" />
+            <result property="pointsPrice" column="points_price" />
+            <result property="quantity" column="quantity" />
+            <result property="review" column="review" />
+            <result property="totalPoints" column="total_points" />
+            <result property="status" column="status" />
+            <result property="receiverName" column="receiver_name" />
+            <result property="receiverPhone" column="receiver_phone" />
+            <result property="receiverAddress" column="receiver_address" />
+            <result property="expressCompany" column="express_company" />
+            <result property="expressNo" column="express_no" />
+            <result property="createTime" column="create_time" />
+            <result property="updateTime" column="update_time" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,order_no,maker_id,product_id,product_name,product_image,
+        points_price,quantity,review,total_points,status,
+        receiver_name,receiver_phone,receiver_address,express_company,express_no,
+        create_time,update_time
+    </sql>
+</mapper>

+ 23 - 0
service/admin/src/main/resources/com/zhentao/mapper/SystemMessagesMapper.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhentao.mapper.SystemMessagesMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.entity.SystemMessages">
+            <id property="id" column="id" />
+            <result property="userId" column="user_id" />
+            <result property="type" column="type" />
+            <result property="relatedDynamicId" column="related_dynamic_id" />
+            <result property="title" column="title" />
+            <result property="content" column="content" />
+            <result property="isRead" column="is_read" />
+            <result property="createdAt" column="created_at" />
+            <result property="readAt" column="read_at" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,user_id,type,related_dynamic_id,title,content,
+        is_read,created_at,read_at
+    </sql>
+</mapper>