Răsfoiți Sursa

Add 添加活动签到模块

Yue 2 ani în urmă
părinte
comite
4d6433fa34

+ 17 - 15
SERVER/YanZhongXYH/script/sql/XYHSQL.sql

@@ -67,21 +67,21 @@ create table am_alumnus_ex
 -- ----------------------------
 -- 3、学习经历信息
 -- ----------------------------
-drop table if exists am_study;
-create table am_study
-(
-    study_id      bigint(20)  not null comment '校友id',
-    am_id         bigint(20)  not null comment '校友id',
-    study         varchar(30) not null comment '专业名称',
-    enrol_year    char(4)     not null comment '入学年份',
-    graduate_year char(4)     not null comment '毕业年份',
-    create_by     varchar(64) default '' comment '创建者',
-    create_time   datetime comment '创建时间',
-    update_by     varchar(64) default '' comment '更新者',
-    update_time   datetime comment '更新时间',
-    primary key (study_id)
-) engine = innodb
-  auto_increment = 100 comment = '学习经历信息';
+# drop table if exists am_study;
+# create table am_study
+# (
+#     study_id      bigint(20)  not null comment '校友id',
+#     am_id         bigint(20)  not null comment '校友id',
+#     study         varchar(30) not null comment '专业名称',
+#     enrol_year    char(4)     not null comment '入学年份',
+#     graduate_year char(4)     not null comment '毕业年份',
+#     create_by     varchar(64) default '' comment '创建者',
+#     create_time   datetime comment '创建时间',
+#     update_by     varchar(64) default '' comment '更新者',
+#     update_time   datetime comment '更新时间',
+#     primary key (study_id)
+# ) engine = innodb
+#   auto_increment = 100 comment = '学习经历信息';
 
 -- ----------------------------
 -- 4、好友信息
@@ -201,6 +201,8 @@ create table am_activity_apply
     cost_status     char(4)        default '0' comment '费用状态(0未支付 1已支付)',
     cost_audit_user varchar(64) comment '费用审核人',
     cost_time       datetime       default null comment '费用确认时间',
+    is_attend       char(1)        default '0' comment '是否参加(0未参加 1已参加)',
+    attend_time     datetime comment '参加时间',
     del_flag        char(1)        default '0' comment '删除标志(0代表存在 1代表删除)',
     create_by       varchar(64)    default '' comment '创建者',
     create_time     datetime comment '创建时间',

+ 11 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/controller/AmActivityController.java

@@ -280,4 +280,15 @@ public class AmActivityController extends BaseController {
         BigDecimal costVal = new BigDecimal(cost);
         return toAjax(amActivityApplyService.updateAuditCost(costVal, applyId, getUserId()));
     }
+
+    /**
+     * 确认参加活动
+     */
+    @SaCheckPermission(PermissionName.AmActivityActivityCost)
+    @Log(title = "确认参加活动", businessType = BusinessType.UPDATE)
+    @PostMapping("/attend/{activityId}")
+    public R<Void> attend(@PathVariable String activityId) {
+
+        return toAjax(amActivityApplyService.updateAttend(activityId, getAmId()));
+    }
 }

+ 12 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/domain/AmActivityApply.java

@@ -64,6 +64,7 @@ public class AmActivityApply extends BaseEntity {
      * 费用状态(0未支付 1已支付)
      */
     private String costStatus;
+
     /**
      * 费用审核人
      */
@@ -72,6 +73,17 @@ public class AmActivityApply extends BaseEntity {
      * 费用确认时间
      */
     private Date costTime;
+
+    /**
+     * 是否参加(0未参加 1已参加)
+     */
+    private String isAttend;
+
+    /**
+     * 参加时间
+     */
+    private Date attendTime;
+
     /**
      * 备注
      */

+ 10 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/domain/bo/AmActivityApplyBo.java

@@ -82,6 +82,16 @@ public class AmActivityApplyBo extends BaseEntity {
      */
     private Date costTime;
 
+    /**
+     * 是否参加(0未参加 1已参加)
+     */
+    private String isAttend;
+
+    /**
+     * 参加时间
+     */
+    private Date attendTime;
+
     /**
      * 备注
      */

+ 14 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/domain/vo/AmActivityApplyVo.java

@@ -38,6 +38,7 @@ public class AmActivityApplyVo implements Serializable {
      */
     @ExcelProperty(value = "活动id")
     private String activityId;
+
     /**
      * 姓名
      */
@@ -91,6 +92,19 @@ public class AmActivityApplyVo implements Serializable {
     @ExcelProperty(value = "费用确认时间")
     private Date costTime;
 
+    /**
+     * 是否参加(0未参加 1已参加)
+     */
+    @ExcelProperty(value = "是否参加", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0=未参加,1=参加")
+    private String isAttend;
+
+    /**
+     * 参加时间
+     */
+    @ExcelProperty(value = "参加确认时间")
+    private Date attendTime;
+
     @ExcelProperty(value = "报名时间")
     private Date createTime;
 

+ 2 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/service/IAmActivityApplyService.java

@@ -57,4 +57,6 @@ public interface IAmActivityApplyService {
     TableDataInfo<AmActivityApplyVo> queryApplyPage(AmActivityApplyBo bo, PageQuery pageQuery);
 
     R<AmActivityApplyVo> queryMyApplyInfo(Long amId, String activityId);
+
+    Boolean updateAttend(String activityId, Long amId);
 }

+ 16 - 0
SERVER/YanZhongXYH/xyh-system/src/main/java/cn/xyh/amActivity/service/impl/AmActivityApplyServiceImpl.java

@@ -10,7 +10,9 @@ import cn.xyh.common.core.domain.PageQuery;
 import cn.xyh.common.core.domain.R;
 import cn.xyh.common.core.page.TableDataInfo;
 import cn.xyh.common.exception.ServiceException;
+import cn.xyh.common.utils.DateUtils;
 import cn.xyh.common.utils.StringUtils;
+import cn.xyh.system.utils.AuditStatusEnum;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -84,6 +86,20 @@ public class AmActivityApplyServiceImpl implements IAmActivityApplyService {
         return R.ok(vo);
     }
 
+    @Override
+    public Boolean updateAttend(String activityId, Long amId) {
+        AmActivityApply amActivityApply = baseMapper.selectOne(new LambdaQueryWrapper<AmActivityApply>()
+                .eq(AmActivityApply::getAmId, amId)
+                .eq(AmActivityApply::getActivityId, activityId)
+                .eq(AmActivityApply::getAuditStatus, AuditStatusEnum.PASS.getValue()));
+        if (amActivityApply == null) {
+            throw new ServiceException("活动不存在或未通过审核");
+        }
+        amActivityApply.setIsAttend("1");
+        amActivityApply.setAttendTime(DateUtils.getNowDate());
+        return baseMapper.updateById(amActivityApply) > 0;
+    }
+
     private LambdaQueryWrapper<AmActivityApply> buildQueryWrapper(AmActivityApplyBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<AmActivityApply> lqw = Wrappers.lambdaQuery();

+ 5 - 0
UI/XYH.APP/package-lock.json

@@ -6483,6 +6483,11 @@
         "picocolors": "^1.0.0"
       }
     },
+    "uqrcodejs": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmmirror.com/uqrcodejs/-/uqrcodejs-4.0.7.tgz",
+      "integrity": "sha512-84+aZmD2godCVI+93lxE3YUAPNY8zAJvNA7xRS7R7U+q57KzMDepBSfNCwoRUhWOfR6eHFoAOcHRPwsP6ka1cA=="
+    },
     "uri-js": {
       "version": "4.4.1",
       "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",

+ 1 - 0
UI/XYH.APP/package.json

@@ -58,6 +58,7 @@
     "pinia": "2.0.23",
     "unplugin-auto-import": "^0.15.3",
     "unplugin-vue-components": "^0.24.1",
+    "uqrcodejs": "^4.0.7",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-vue-setup-extend": "^0.4.0",
     "vue": "^3.2.45",

+ 11 - 0
UI/XYH.APP/src/api/amActivity/_activity.ts

@@ -117,6 +117,16 @@ class activityApi {
       loading: false,
     })
   }
+
+  // 确认参加
+  attendActivity = (activityId: string) => {
+    return Rs.post({
+      url: `/amActivity/activity/attend/${activityId}`,
+      loading: true,
+      successAlert: false,
+    })
+  }
+
   // 查询我参与的活动信息
   myApply = (activityId: string) => {
     return Rs.get({
@@ -124,6 +134,7 @@ class activityApi {
       loading: false,
     })
   }
+
   // 查询我创建活动信息列表
   myCreateActivity = (query: any) => {
     return Rs.get({

+ 2 - 0
UI/XYH.APP/src/components/vber/picker-m/vb-picker-m.vue

@@ -10,6 +10,7 @@ const props = withDefaults(
     getChildColumns?: (v1: Array<any>, v2: string | number) => Array<any>
     isConfirm?: boolean
     isCancel?: boolean
+    disabled?: boolean
     label?: string
     popupTitle?: string | false
     placeholder?: string
@@ -244,6 +245,7 @@ onLoad(init)
       @clear="bindClear"
       :inputBorder="false"
       :placeholder="_placeholder"
+      :disabled="disabled"
     />
   </view>
   <view class="vb-popup" v-if="show">

+ 2 - 0
UI/XYH.APP/src/components/vber/picker/vb-picker.vue

@@ -7,6 +7,7 @@ const props = withDefaults(
     formatter?: (v: any) => Array<any>
     isConfirm?: boolean
     isCancel?: boolean
+    disabled?: boolean
     label?: string
     popupTitle?: string | false
     placeholder?: string
@@ -179,6 +180,7 @@ onLoad(init)
       @clear="bindClear"
       :inputBorder="false"
       :placeholder="_placeholder"
+      :disabled="disabled"
     />
   </view>
   <view ref="popupRef" class="vb-popup" v-if="show">

+ 126 - 0
UI/XYH.APP/src/pages-sub/activity/attend.vue

@@ -0,0 +1,126 @@
+<template>
+  <view v-if="ready" class="page-cpntainer">
+    <view v-if="error" class="h-100px d-fc text-danger font-bold fs-20">
+      {{ error }}
+    </view>
+    <vb-cell-group inset>
+      <vb-cell title="活动名称" :value="activity.title" />
+      <vb-cell title="活动时间" :value="activity.activityDate" />
+      <vb-cell title="活动地点" :value="address" />
+      <vb-cell v-if="name" title="姓名" :value="name" />
+      <vb-cell v-if="apply && activity.needCost == 1" title="是否付费" :value="cost" />
+    </vb-cell-group>
+    <vb-cell-group inset v-if="showBtn">
+      <vb-button @click="onAttend">确认参加活动</vb-button>
+    </vb-cell-group>
+    <!-- <view v-else-if="ready" class="flex-column fs-18">
+      <view class="d-fcv">
+        <view class=" font-bold ">活动名称:</view>
+        <view class="text-">{{ activity.title }}</view>
+      </view>
+    </view>-->
+  </view>
+</template>
+
+<script lang="ts" setup>
+import dayjs from "dayjs"
+import apis from "@/api"
+import route from "@/route"
+const params = route.getRouteParams("activityAttend")
+
+const activityId = ref(params.id)
+const activity = ref<any>({})
+const apply = ref<any>()
+const ready = ref(false)
+
+const error = computed(() => {
+  if (activity.value.isClose == "1") {
+    return "活动已结束"
+  }
+  if (dayjs(new Date()).isBefore(dayjs(activity.value.activityDate))) {
+    return "活动还未开始报名"
+  }
+  if (activity.value.auditStatus != "1") {
+    return "活动状态异常"
+  }
+  if (!apply.value) {
+    return "您未报名参加活动"
+  }
+  if (apply.value.isAttend == "1") {
+    return "您已经签到成功"
+  }
+  if (apply.value.auditStatus != 1) {
+    return "您的报名未被审核通过"
+  }
+  return false
+})
+
+const address = computed(() => {
+  if (activity.value.area == "线上活动") {
+    return activity.value.area
+  } else {
+    return activity.value.address
+  }
+})
+
+const name = computed(() => {
+  return apply.value?.name
+})
+
+const cost = computed(() => {
+  return apply.value?.costStatus == 1 ? apply.value?.cost : "未付费"
+})
+
+const showBtn = computed(() => {
+  if (error.value || !apply.value) {
+    return false
+  }
+  if (apply.value.auditStatus != 1) {
+    return false
+  }
+  if (activity.value.needCost == "1" && apply.value.costStatus == 0) {
+    return false
+  }
+  if (apply.value.isAttend == 1) {
+    return false
+  }
+  return true
+})
+
+function onAttend() {
+  message.confirm("确认参加活动?").then((res: any) => {
+    if (res.confirm) {
+      apis.amActivity.activityApi.attendActivity(activityId.value).then((res: any) => {
+        message.msgSuccess("报名成功")
+        setTimeout(() => {
+          route.back()
+        }, 1500)
+      })
+    }
+  })
+}
+
+function loadData() {
+  // 加载活动信息
+  if (activityId.value) {
+    apis.amActivity.activityApi.getActivity(activityId.value).then((res) => {
+      if (res) {
+        activity.value = res
+        ready.value = true
+      }
+    })
+    apis.amActivity.activityApi.myApply(activityId.value).then((res) => {
+      if (res) {
+        apply.value = res
+      }
+    })
+  }
+}
+
+function init() {
+  loadData()
+}
+onMounted(init)
+</script>
+
+<style scoped></style>

+ 7 - 0
UI/XYH.APP/src/pages.json

@@ -3,6 +3,7 @@
     "autoscan": true,
     "custom": {
       "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
+      "^u-(.*)": "@components/u-$1/u-$1.vue",
       "^qiun-(.*)": "@/components/uCharts/qiun-$1/qiun-$1.vue",
       "^vb-(.*)": "@/components/vber/$1/vb-$1.vue"
     }
@@ -187,6 +188,12 @@
           "style": {
             "navigationBarTitleText": "我的活动"
           }
+        },
+        {
+          "path": "attend",
+          "style": {
+            "navigationBarTitleText": "活动签到"
+          }
         }
       ]
     },

+ 23 - 3
UI/XYH.APP/src/pages/mine/index.vue

@@ -24,9 +24,29 @@ function onActivityScan() {
   uni.scanCode({
     scanType: ["barCode", "qrCode"],
     success: function (res: any) {
-      console.log("条码类型:" + res.scanType)
-      console.log("条码内容:" + res.result)
-      if (res.result.startsWith("activity")) {
+      // console.log("条码类型:" + res.scanType)
+      // console.log("条码内容:" + res.result)
+      const arr = res.result.split("@")
+      if (arr.length == 2) {
+        const type = arr[0].toUpperCase()
+        switch (type) {
+          //activityDetail
+          case "AD":
+            route.navigate("activityDetail", { id: arr[1] })
+            break
+          //activityAttend
+          case "AA":
+            route.navigate("activityAttend", { id: arr[1] })
+            break
+          //helpDetail
+          case "HD":
+            route.navigate("helpDetail", { id: arr[1] })
+            break
+          //newsDetail
+          case "ND":
+            route.navigate("newsDetail", { id: arr[1] })
+            break
+        }
       }
     },
   })

+ 1 - 0
UI/XYH.APP/src/route/_pages.ts

@@ -37,6 +37,7 @@ const activitySub = {
   activityApply: "/pages-sub/activity/apply",
   activityApplyList: "/pages-sub/activity/applyList",
   activityApplyAudit: "/pages-sub/activity/applyAudit",
+  activityAttend: "/pages-sub/activity/attend",
 }
 const friendSub = {
   friendApply: "/pages-sub/friend/apply",