| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084 |
- <?php
- namespace app\modules\client\controllers\v1;
- use app\models\Event;
- use app\models\EventForm;
- use app\models\EventFormDetail;
- use app\models\EventSetting;
- use app\models\EventSignLog;
- use app\models\EventSignStaff;
- use app\models\EventUser;
- use yii\data\Pagination;
- use app\modules\client\controllers\BaseController;
- use app\utils\QrCode;
- use app\utils\ShareQrcode;
- use app\utils\Alipay\alipaySdk\aop\request\AlipayOpenAppQrcodeCreateRequest;
- use Yii;
- /**
- * @file EventController
- * @editor Created by vscode
- * @author WPing丶
- * @date 2025/07/14
- * @time 09:20:05
- *
- * 备注:活动报名功能前端接口
- */
- class EventController extends BaseController
- {
- /**
- * 模块名:list
- * 代码描述:活动专区列表
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/14 09:45:13
- * @param int page
- * @param int limit
- */
- public function actionList()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $page = max(1, (int)get_params('page'));
- $limit = (int)get_params('limit', 10);
- $limit = ($limit <= 0) ? 10 : min($limit, 100);
- $now = time();
- // 活动分页列表
- $query = Event::find()
- ->where([
- 'is_delete' => 0,
- 'store_id' => $store_id,
- ])
- ->andWhere(['and', ['<=', 'start_time', $now], ['>', 'end_time', $now]])
- ->orderBy(['start_time' => SORT_DESC]);
- $count = (clone $query)->count(); // 避免污染
- $pagination = new Pagination([
- 'totalCount' => $count,
- 'pageSize' => $limit,
- 'page' => $page - 1,
- ]);
- $list = $query
- ->limit($pagination->limit)
- ->offset($pagination->offset)
- ->asArray()
- ->all();
- foreach ($list as &$item) {
- // 查询已报名人数
- $item['count'] = EventUser::find()
- ->where(['event_id' => $item['event_id'], 'is_delete' => 0])
- ->count();
- $event_user = EventUser::findOne(['user_id' => $user_id, 'is_delete' => 0, 'event_id' => $item['id']]);
- if (!$event_user) {
- $is_apply = -1;
- } else {
- $is_apply = $event_user->apply_status;
- }
- $item['is_apply'] = (int)$is_apply;
- }
- // 三种状态的统计
- $apply_num = $this->getUserEventCount($user_id, 0, 'start_time', '>', $now); // 申请中
- $underway_num = $this->getUserEventCount($user_id, 1, 'end_time', '>=', $now); // 进行中
- $finished_num = $this->getUserEventCount($user_id, 1, 'end_time', '<', $now); // 已结束
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'list' => $list,
- 'row_count' => (int)$count,
- 'page_count' => (int)$pagination->getPageCount(),
- 'apply_num' => (int)$apply_num,
- 'underway_num' => (int)$underway_num,
- 'finished_num' => (int)$finished_num,
- ],
- ]);
- }
- /**
- * 模块名:getUserEventCount
- * 代码描述:获取某用户某一状态的报名活动数量
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/14 10:49:38
- *
- * @param int $user_id 用户ID
- * @param int $apply_status 报名状态:0=申请中,1=已通过
- * @param string $time_field 时间字段名(start_time 或 end_time)
- * @param string $operator 比较操作符:>、>=、<
- * @param int $timestamp 当前时间
- * @return int
- */
- private function getUserEventCount($user_id, $apply_status, $time_field, $operator, $timestamp)
- {
- return EventUser::find()->alias('eu')
- ->select('eu.id') // 提高 count 性能
- ->leftJoin(['e' => Event::tableName()], 'e.id = eu.event_id')
- ->where([
- 'eu.user_id' => $user_id,
- 'eu.is_delete' => 0,
- 'e.is_delete' => 0,
- 'eu.apply_status' => $apply_status,
- ])
- ->andWhere([$operator, "e.{$time_field}", $timestamp])
- ->count();
- }
- /**
- * 模块名:event-apply-form
- * 代码描述:报名自定义表单
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/14 11:31:46
- * @param int id 活动ID
- */
- public function actionEventApplyForm()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $id = (int)get_params('id');
- if (!$id) {
- return $this->asJson(['code' => 1, 'msg' => '活动ID不能为空']);
- }
- // 查询活动是否存在
- $event = Event::find()
- ->where([
- 'id' => $id,
- 'store_id' => $store_id,
- 'is_delete' => 0
- ])
- ->asArray()
- ->one();
- if (!$event) {
- return $this->asJson(['code' => 1, 'msg' => '活动不存在']);
- }
- // 查询用户是否已报名
- $eventUser = EventUser::find()
- ->where([
- 'user_id' => $user_id,
- 'event_id' => $id,
- 'is_delete' => 0
- ])
- ->orderBy('id DESC') // 保证拿到最新一条
- ->asArray()
- ->one();
- // 情况 1:已报名,审核中或通过审核admin
- if ($eventUser && $eventUser['apply_status'] == 0) {
- return $this->asJson(['code' => 1, 'msg' => '您已提交报名,正在审核中', 'eventUser' => $eventUser]);
- }
- if ($eventUser && $eventUser['apply_status'] == 1) {
- return $this->asJson(['code' => 1, 'msg' => '您已提交报名,审核成功']);
- }
- // 查询所有表单结构,按 form_type 分组返回
- $forms = EventForm::find()
- ->where([
- 'event_id' => $id,
- 'is_delete' => 0
- ])
- ->orderBy('sort ASC')
- ->asArray()
- ->all();
- // 构造分组结构:1=企业,2=机构
- $form_group = [];
- foreach ($forms as $form) {
- $form_group[$form['form_type']][] = $form;
- }
- // 情况 2:首次报名(没有任何报名记录)
- if (!$eventUser) {
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- // 'event' => $event,
- 'form' => $form_group,
- ],
- 'setting' => $this->getSetting()
- ]);
- }
- // 情况 3:报名被拒绝 → 需要回填
- if ($eventUser['apply_status'] == 2) {
- // 回填数据查询
- $details = EventFormDetail::find()
- ->where([
- 'event_id' => $id,
- 'event_user_id' => $eventUser['id'],
- 'user_id' => $user_id,
- 'is_delete' => 0
- ])
- ->asArray()
- ->all();
- // 组装回填数据映射(按 form_type + key)
- $detail_map = [];
- foreach ($details as $item) {
- $detail_map[$item['form_type']][$item['key']] = $item['value'];
- }
- // 将回填数据合并到 form 结构中
- foreach ($form_group as $form_type => &$items) {
- foreach ($items as &$field) {
- $field['value'] = $detail_map[$form_type][$field['name']] ?? '';
- }
- }
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'form' => $form_group, // 每个字段中已附带 value
- 'event_user' => $eventUser,
- 'reason_refusal' => $eventUser['reason_refusal'],
- ],
- 'setting' => $this->getSetting()
- ]);
- }
- // 其他未定义情况,兜底处理
- return $this->asJson(['code' => 1, 'msg' => '无法处理的报名状态']);
- }
- /**
- * 模块名:event-apply-form-post
- * 代码描述: 提交活动报名表单
- * 作者:WPing丶
- * 请求方式: POST
- * 创建时间:2025/07/14 15:58:20
- * @param int id 活动ID
- * @param int form_type 表单类型(1=企业,2=机构)
- * @param array form_data 用户填写的表单(字段名为中文名称)
- * @param string company_code 统一社会信息代码
- * @param string company_name 公司名称
- * @param string company_address 公司地址
- * @param string real_name 姓名
- * @param string phone 电话
- * @param string identity_card 身份证
- */
- public function actionEventApplyFormPost()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $id = (int)post_params('id');
- $form_type = (int)post_params('form_type', 1);
- $form_data = post_params('form_data', []);
- $company_code = post_params('company_code');
- $company_name = post_params('company_name');
- $company_address = post_params('company_address');
- $real_name = post_params('real_name');
- $phone = post_params('phone');
- $identity_card = post_params('identity_card');
- if (!$id || !$form_type || empty($form_data || !$company_code || !$company_name || $company_address || $real_name || $phone || $identity_card)) {
- return $this->asJson(['code' => 1, 'msg' => '参数不完整']);
- }
- // 检查活动是否存在
- $event = Event::findOne([
- 'id' => $id,
- 'store_id' => $store_id,
- 'is_delete' => 0
- ]);
- if (!$event) {
- return $this->asJson(['code' => 1, 'msg' => '活动不存在']);
- }
- if ($event->end_time < time()) {
- return $this->asJson(['code' => 1, 'msg' => '活动报名已结束无法报名']);
- }
- // 检查是否已报名
- $exist = EventUser::findOne([
- 'event_id' => $id,
- 'user_id' => $user_id,
- 'is_delete' => 0,
- 'apply_status' => [0, 1]
- ]);
- if ($exist) {
- return $this->asJson(['code' => 1, 'msg' => '您已报名,请勿重复提交']);
- }
- $phone_exist = EventUser::findOne([
- 'event_id' => $id,
- 'phone' => $phone,
- 'is_delete' => 0,
- 'apply_status' => [0, 1]
- ]);
- if ($phone_exist) {
- return $this->asJson(['code' => 1, 'msg' => '此手机号已报名,请勿重复提交']);
- }
- // 检查限制人数 attendance = 0 不限制
- if ($event->attendance > 0) {
- $attendance = EventUser::find()
- ->where([
- 'event_id' => $id,
- 'is_delete' => 0,
- 'apply_status' => 1,
- 'company_code' => $company_code
- ])->count();
- if ($attendance >= $event->attendance) {
- return $this->asJson(['code' => 1, 'msg' => '【' . $company_name . '】报名已达到限制人数,请与活动主办方联系。']);
- }
- }
- // 开启事务
- $transaction = Yii::$app->db->beginTransaction();
- try {
- // 写入 event_user 表
- $eventUser = EventUser::findOne([
- 'event_id' => $id,
- 'user_id' => $user_id,
- 'is_delete' => 0,
- 'apply_status' => 2,
- 'store_id' => $store_id
- ]);
- if (!$eventUser) {
- $eventUser = new EventUser();
- $eventUser->store_id = $store_id;
- $eventUser->event_id = $id;
- $eventUser->user_id = $user_id;
- }
- $eventUser->company_code = $company_code;
- $eventUser->company_name = $company_name;
- $eventUser->company_address = $company_address;
- $eventUser->real_name = $real_name;
- $eventUser->phone = $phone;
- $eventUser->identity_card = $identity_card;
- $eventUser->apply_status = 0;
- $eventUser->created_at = time();
- $eventUser->updated_at = time();
- $eventUser->is_delete = 0;
- $eventUser->hotel = '{"title":"","data":[]}';
- $eventUser->restaurant = '{"title":"","data":[]}';
- $eventUser->itinerary = '{"title":"","data":[]}';
- $eventUser->form_type = $form_type;
- if (!$eventUser->save()) {
- throw new \Exception('保存报名主表失败');
- }
- // 查询字段定义
- $formList = EventForm::find()
- ->where([
- 'event_id' => $id,
- 'form_type' => $form_type,
- 'is_delete' => 0
- ])
- ->asArray()
- ->all();
- $formNameMap = []; // name => type
- foreach ($formList as $item) {
- $formNameMap[$item['name']] = $item['type'] ?? 'text';
- }
- // 写入表单明细
- EventFormDetail::updateAll(['is_delete' => 1], ['event_user_id' => $eventUser->id]);
- foreach ($form_data as $name => $value) {
- if (!isset($formNameMap[$name])) {
- continue;
- }
- $detail = new EventFormDetail();
- $detail->store_id = $store_id;
- $detail->event_user_id = $eventUser->id;
- $detail->event_id = $id;
- $detail->user_id = $user_id;
- $detail->form_type = $form_type;
- $detail->key = $name;
- $detail->value = $value;
- $detail->type = $formNameMap[$name];
- $detail->is_delete = 0;
- if (!$detail->save()) {
- throw new \Exception("保存表单字段【{$name}】失败");
- }
- }
- $transaction->commit();
- return $this->asJson(['code' => 0, 'msg' => '报名成功,等待审核']);
- } catch (\Exception $e) {
- $transaction->rollBack();
- return $this->asJson(['code' => 1, 'msg' => '报名失败:' . $e->getMessage()]);
- }
- }
- /**
- * 模块名:user-event-list
- * 代码描述: 我的报名
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/14 18:09:26
- * @param int page
- * @param int limit
- * @param string status 活动状态:all 全部 | audit 审核中 | underway 进行中 | done 已结束
- * @param string lng 经度
- * @param string lat 纬度
- */
- public function actionUserEventList()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $status = get_params('status', 'all'); // all | audit | underway | done
- $page = (int)get_params('page', 1);
- $limit = (int)get_params('limit', 10);
- $limit = ($limit <= 0) ? 10 : min($limit, 100);
- //用户当前的经纬度,如果未传经纬度,说明用户拒绝定位,则后续酒店、饭店、行程信息处理时距离返回空即可
- $lng = get_params('lng');
- $lat = get_params('lat');
- $query = EventUser::find()->alias('eu')
- ->leftJoin(['e' => Event::tableName()], 'e.id = eu.event_id')
- ->where([
- 'eu.user_id' => $user_id,
- 'eu.is_delete' => 0,
- 'e.is_delete' => 0,
- 'e.store_id' => $store_id,
- ]);
- // 状态筛选
- $now = time();
- if ($status === 'audit') {
- $query->andWhere(['eu.apply_status' => [0, 2]]);
- $query->andWhere(['>', 'e.start_time', $now]);
- } elseif ($status === 'underway') {
- $query->andWhere(['eu.apply_status' => 1]);
- $query->andWhere(['>=', 'e.end_time', $now]);
- } elseif ($status === 'done') {
- $query->andWhere(['eu.apply_status' => 1]);
- $query->andWhere(['<', 'e.end_time', $now]);
- }
- $count = $query->count();
- $pagination = new Pagination([
- 'totalCount' => $count,
- 'pageSize' => $limit,
- 'page' => $page - 1
- ]);
- $list = $query->select([
- 'eu.id',
- 'e.id AS event_id',
- 'e.name',
- 'e.start_time',
- 'e.end_time',
- 'e.cover_pic',
- 'eu.reason_refusal',
- 'eu.apply_status',
- 'eu.hotel',
- 'eu.restaurant',
- 'eu.itinerary',
- ])
- ->orderBy('e.start_time DESC')
- ->limit($pagination->limit)
- ->offset($pagination->offset)
- ->asArray()
- ->all();
- // 补充 status_text 和报名人数
- foreach ($list as &$item) {
- $apply_status = (int)$item['apply_status'];
- $start = (int)$item['start_time'];
- $end = (int)$item['end_time'];
- if ($apply_status === 0) {
- $item['status_text'] = '报名中·待审核';
- } elseif ($apply_status === 1 && $end >= $now) {
- $item['status_text'] = '进行中';
- } elseif ($apply_status === 1 && $end < $now) {
- $item['status_text'] = '已结束';
- } elseif ($apply_status === 2) {
- $item['status_text'] = '报名中·已驳回';
- } else {
- $item['status_text'] = '未知状态';
- }
- //酒店、饭店、行程数组处理
- //code...
- $has_location = $lat && $lng;
- // 计算距离(单位:米)
- $calcDistance = function ($lat1, $lng1, $lat2, $lng2) {
- $earthRadius = 6371000; // 米
- $lat1 = deg2rad($lat1);
- $lng1 = deg2rad($lng1);
- $lat2 = deg2rad($lat2);
- $lng2 = deg2rad($lng2);
- $dlat = $lat2 - $lat1;
- $dlng = $lng2 - $lng1;
- $a = sin($dlat / 2) ** 2 + cos($lat1) * cos($lat2) * sin($dlng / 2) ** 2;
- $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
- return round($earthRadius * $c, 2);
- };
- // 格式化距离显示
- $formatDistance = function ($distance) {
- if ($distance < 1000) {
- return (int)$distance . 'm';
- }
- return round($distance / 1000, 1) . 'km';
- };
- // 转换 json + 加入距离
- $parseJsonWithDistance = function ($json_str, $user_lat, $user_lng) use ($has_location, $calcDistance, $formatDistance) {
- $result = json_decode($json_str, true);
- if (!is_array($result) || !isset($result['data'])) {
- return null;
- }
- foreach ($result['data'] as &$item) {
- if (!$has_location || !isset($item['lat']) || !isset($item['lng'])) {
- $item['distance'] = null;
- continue;
- }
- $distance_val = $calcDistance((float)$user_lat, (float)$user_lng, (float)$item['lat'], (float)$item['lng']);
- $item['distance'] = $formatDistance($distance_val);
- }
- return $result;
- };
- // 应用处理
- $item['hotel'] = $parseJsonWithDistance($item['hotel'], $lat, $lng);
- $item['restaurant'] = $parseJsonWithDistance($item['restaurant'], $lat, $lng);
- $item['itinerary'] = $parseJsonWithDistance($item['itinerary'], $lat, $lng);
- // 查询已报名人数
- $item['count'] = EventUser::find()
- ->where(['event_id' => $item['event_id'], 'is_delete' => 0])
- ->count();
- }
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'list' => $list,
- 'row_count' => $count,
- 'page_count' => $pagination->pageCount
- ],
- 'setting' => $this->getSetting()
- ]);
- }
- /**
- * 模块名:get-event-user-qr
- * 代码描述:签到二维码
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/14 19:14:25
- * @param int id
- */
- public function actionGetEventUserQr()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $id = (int)get_params('id');
- if (!$id) {
- return $this->asJson(['code' => 1, 'msg' => '缺少参数:id']);
- }
- // 查询报名记录
- $eventUser = EventUser::find()
- ->where([
- 'id' => $id,
- 'user_id' => $user_id,
- 'store_id' => $store_id,
- 'is_delete' => 0,
- 'apply_status' => 1, // 只允许通过审核的用户查看二维码
- ])
- ->asArray()
- ->one();
- if (!$eventUser) {
- return $this->asJson(['code' => 1, 'msg' => '报名记录不存在或未审核通过']);
- }
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'real_name' => $eventUser['real_name'] ?? '',
- 'phone' => $eventUser['phone'] ?? '',
- 'identity_card' => $eventUser['identity_card'] ?? '',
- ]
- ]);
- }
- /**
- * 模块名:getSetting
- * 代码描述:获取设置项
- * 作者:WPing丶
- * 请求方式:private
- * 创建时间:2025/07/16 10:45:11
- */
- private function getSetting()
- {
- $store_id = get_store_id();
- $setting = EventSetting::findOne(['store_id' => $store_id, 'is_delete' => 0]);
- return [
- 'banner' => json_decode($setting->banner, true)
- ];
- }
- /**
- * 模块名:do-sign-by-staff
- * 代码描述:确认签到
- * 作者:WPing丶
- * 请求方式:POST
- * 创建时间:2025/07/16 11:28:38
- * @param int user_id
- * @param int event_id
- */
- public function actionDoSignByStaff()
- {
- $store_id = get_store_id();
- $staff_id = get_user_id(); // 当前登录用户(签到员)
- $user_id = (int)post_params('user_id'); // 被签到用户
- $event_id = (int)post_params('event_id');
- if (!$user_id || !$event_id) {
- return $this->asJson(['code' => 1, 'msg' => '参数错误']);
- }
- // 检查当前用户是否是有效的签到员
- $staff = EventSignStaff::findOne(['user_id' => $staff_id, 'is_delete' => 0]);
- if (!$staff) {
- return $this->asJson(['code' => 1, 'msg' => '无权限']);
- }
- // 查找报名记录
- $eventUser = EventUser::findOne([
- 'user_id' => $user_id,
- 'event_id' => $event_id,
- 'is_delete' => 0,
- 'apply_status' => 1
- ]);
- if (!$eventUser) {
- return $this->asJson(['code' => 1, 'msg' => '报名记录不存在或未通过审核']);
- }
- // 检查是否已签到
- if ($eventUser->sign_time > 0) {
- return $this->asJson(['code' => 1, 'msg' => '用户已签到']);
- }
- $transaction = Yii::$app->db->beginTransaction();
- try {
- $time = time();
- // 写入签到日志表
- $log = new EventSignLog();
- $log->store_id = $store_id;
- $log->is_delete = 0;
- $log->staff_id = $staff->id;
- $log->user_id = $user_id;
- $log->event_id = $event_id;
- $log->event_user_id = $eventUser->id;
- if (!$log->save()) {
- throw new \Exception('签到记录保存失败');
- }
- // 更新报名表中的签到时间
- $eventUser->sign_time = $time;
- if (!$eventUser->save()) {
- throw new \Exception('签到时间更新失败');
- }
- $transaction->commit();
- return $this->asJson(['code' => 0, 'msg' => '签到成功']);
- } catch (\Exception $e) {
- $transaction->rollBack();
- return $this->asJson(['code' => 1, 'msg' => '签到失败:' . $e->getMessage()]);
- }
- }
- /**
- * 模块名:my-sign-record
- * 代码描述:签到员记录
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/16 14:17:38
- * @param int page
- * @param int limit
- */
- public function actionMySignRecord()
- {
- $store_id = get_store_id();
- $staff_id = EventSignStaff::findOne(['user_id' => get_user_id(), 'is_delete' => 0])->id;
- $page = (int)get_params('page', 1);
- $limit = (int)get_params('limit', 10);
- if (!$staff_id) {
- return $this->asJson(['code' => 1, 'msg' => '当前用户不是签到员']);
- }
- $query = EventSignLog::find()->alias('l')
- ->leftJoin(['u' => EventUser::tableName()], 'u.id = l.event_user_id')
- ->leftJoin(['e' => Event::tableName()], 'e.id = l.event_id')
- ->where([
- 'l.store_id' => $store_id,
- 'l.is_delete' => 0,
- 'l.staff_id' => $staff_id
- ]);
- $count = $query->count();
- $pagination = new Pagination([
- 'totalCount' => $count,
- 'pageSize' => $limit,
- 'page' => $page - 1
- ]);
- $list = $query->select([
- 'u.sign_time',
- 'u.real_name',
- 'u.phone',
- 'e.name AS event_name'
- ])
- ->orderBy('l.created_at DESC')
- ->offset($pagination->offset)
- ->limit($pagination->limit)
- ->asArray()
- ->all();
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'list' => $list,
- 'row_count' => $count,
- 'page_count' => $pagination->pageCount,
- ]
- ]);
- }
- /**
- * 模块名: sign-preview
- * 代码描述: 签到员预览页
- * 请求方式: GET
- * @param int id event_user主键ID
- */
- public function actionSignPreview()
- {
- $store_id = get_store_id();
- $id = (int)get_params('id');
- if (!$id) {
- return $this->asJson(['code' => 1, 'msg' => '缺少报名记录ID']);
- }
- $staff_id = get_user_id(); // 当前登录用户(签到员)
- // 检查当前用户是否是有效的签到员
- $staff = EventSignStaff::findOne(['user_id' => $staff_id, 'is_delete' => 0]);
- if (!$staff) {
- return $this->asJson(['code' => 1, 'msg' => '无权限']);
- }
- // 联查 event_user 和 event 表(主表 event_user)
- $info = EventUser::find()
- ->alias('eu')
- ->leftJoin(['e' => Event::tableName()], 'e.id = eu.event_id')
- ->where([
- 'eu.id' => $id,
- 'eu.is_delete' => 0,
- 'eu.store_id' => $store_id,
- 'e.is_delete' => 0,
- ])
- ->select([
- 'eu.id',
- 'eu.real_name',
- 'eu.phone',
- 'eu.identity_card',
- 'eu.company_code',
- 'eu.company_name',
- 'eu.company_address',
- 'eu.event_id',
- 'e.name',
- 'e.address',
- 'e.start_time',
- 'e.end_time'
- ])
- ->asArray()
- ->one();
- if (!$info) {
- return $this->asJson(['code' => 1, 'msg' => '记录不存在,id=【' . $id . '】']);
- }
- // 查询自定义表单字段(event_form_detail)
- $formDetail = EventFormDetail::find()
- ->where([
- 'event_user_id' => $id,
- 'is_delete' => 0
- ])
- ->select(['key', 'value'])
- ->orderBy('id ASC')
- ->asArray()
- ->all();
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'info' => $info,
- 'form_detail' => $formDetail
- ]
- ]);
- }
- /**
- * 模块名:get-event-sign-qrcode
- * 代码描述:获取签到二维码
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/16 16:28:11
- * @param int event_id
- */
- public function actionGetEventSignQrcode()
- {
- $event_id = (int)get_params('event_id');
- $user_id = get_user_id();
- if (!$event_id) {
- return $this->asJson(['code' => 1, 'msg' => '参数缺失']);
- }
- // 查询报名记录
- $eventUser = EventUser::find()
- ->where([
- 'event_id' => $event_id,
- 'is_delete' => 0,
- 'user_id' => $user_id,
- 'apply_status' => 1, // 只允许通过审核的用户查看二维码
- ])
- ->asArray()
- ->one();
- if (!$eventUser) {
- return $this->asJson(['code' => 1, 'msg' => '报名记录不存在或未审核通过']);
- }
- $event_user_id = $eventUser['id'];
- $page = "eventPlanning/verifyCodeResult/verifyCodeResult";
- $scene = "event_user_id:{$event_user_id}";
- $file_name = [
- 'url_path' => ''
- ];
- if (is_wechat_platform()) {
- // 微信平台小程序码
- $file_name = ShareQrcode::wxQrcode($page, $scene);
- if ($file_name['code'] != 0) {
- return $this->asJson($file_name);
- }
- }
- if (is_alipay_platform()) {
- // 支付宝小程序码
- $request = new AlipayOpenAppQrcodeCreateRequest();
- $param = [
- 'url_param' => $page,
- 'query_param' => $scene,
- 'describe' => "签到预览页二维码"
- ];
- $aliConfigQr = $this->aliConfigQr($request, $param);
- if ($aliConfigQr->code === "10000") {
- $file_name['url_path'] = $aliConfigQr->qr_code_url_circle_blue;
- }
- }
- if (is_h5() || is_app_platform()) {
- $fileName = md5($page . $scene . get_store_id());
- $dir = \Yii::$app->runtimePath . '/image/wx_qrcode';
- if (!is_dir($dir)) {
- mkdir($dir, 0777, true);
- }
- $save_path = $dir . '/' . $fileName . '.jpg';
- $url = \Yii::$app->request->hostInfo . '/h5/#/' . $page . '?scene=' . urlencode($scene);
- QrCode::image($url, 600, false, 'L', 'JPEG', 0, ['255,255,255', '0,0,0'], 1, false, $save_path);
- $file_name['url_path'] = str_replace('http://', 'https://', \Yii::$app->request->hostInfo . '/runtime/image/wx_qrcode/' . $fileName . '.jpg');
- }
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => [
- 'qr_code' => $file_name['url_path'],
- 'real_name' => $eventUser['real_name'] ?? '',
- 'phone' => $eventUser['phone'] ?? '',
- 'identity_card' => $eventUser['identity_card'] ?? '',
- ]
- ]);
- }
- /**
- * 模块名:get-event-detail
- * 代码描述:获取报名详情
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/21 11:55:40
- * @param int event_user_id
- * @param int event_id
- * @param int lng 经度
- * @param int lat 纬度
- */
- public function actionGetEventDetail()
- {
- $event_user_id = (int)get_params('event_user_id');
- $event_id = (int)get_params('event_id');
- $user_id = get_user_id();
- //用户当前的经纬度,如果未传经纬度,说明用户拒绝定位,则后续酒店、饭店、行程信息处理时距离返回空即可
- $lng = get_params('lng');
- $lat = get_params('lat');
- $store_id = get_store_id();
- if (!$event_user_id && !$event_id) {
- return $this->asJson(['code' => 1, 'msg' => '参数缺失']);
- }
- // 查询报名记录
- $query = EventUser::find()
- ->where([
- 'store_id' => $store_id,
- 'is_delete' => 0,
- 'apply_status' => 1, // 只允许通过审核的用户查看二维码
- ]);
- if ($event_user_id) {
- $query->andWhere(['id' => $event_user_id]);
- } elseif ($event_id) {
- $query->andWhere(['event_id' => $event_id, 'user_id' => $user_id]);
- }
- $eventUser = $query
- ->asArray()
- ->one();
- if (!$eventUser) {
- return $this->asJson(['code' => 1, 'msg' => '报名记录不存在或未审核通过']);
- }
- $data = [];
- foreach ($eventUser as $k => $item) {
- if ($k == 'hotel' || $k == 'restaurant' || $k == 'itinerary') {
- /* begin 2025/07/24 16:00:21 WPing丶 */
- //酒店、饭店、行程数组处理
- //code...
- $has_location = $lat && $lng;
- // 计算距离(单位:米)
- $calcDistance = function ($lat1, $lng1, $lat2, $lng2) {
- $earthRadius = 6371000; // 米
- $lat1 = deg2rad($lat1);
- $lng1 = deg2rad($lng1);
- $lat2 = deg2rad($lat2);
- $lng2 = deg2rad($lng2);
- $dlat = $lat2 - $lat1;
- $dlng = $lng2 - $lng1;
- $a = sin($dlat / 2) ** 2 + cos($lat1) * cos($lat2) * sin($dlng / 2) ** 2;
- $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
- return round($earthRadius * $c, 2);
- };
- // 格式化距离显示
- $formatDistance = function ($distance) {
- if ($distance < 1000) {
- return (int)$distance . 'm';
- }
- return round($distance / 1000, 1) . 'km';
- };
- // 转换 json + 加入距离
- $parseJsonWithDistance = function ($json_str, $user_lat, $user_lng) use ($has_location, $calcDistance, $formatDistance) {
- $result = json_decode($json_str, true);
- if (!is_array($result) || !isset($result['data'])) {
- return null;
- }
- foreach ($result['data'] as &$item) {
- if (!$has_location || !isset($item['lat']) || !isset($item['lng'])) {
- $item['distance'] = null;
- continue;
- }
- $distance_val = $calcDistance((float)$user_lat, (float)$user_lng, (float)$item['lat'], (float)$item['lng']);
- $item['distance'] = $formatDistance($distance_val);
- }
- return $result;
- };
-
- // $arr = json_decode($item, true);
- // 应用处理
- $arr = $parseJsonWithDistance($item, $lat, $lng);
- /* end */
- if (count($arr['data']) == 0) {
- $data[$k] = [];
- } else {
- $data[$k] = $arr;
- }
- } else {
- $data[$k] = $item;
- }
- }
- $setting = EventSetting::findOne(['store_id' => $store_id, 'is_delete' => 0]);
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => $data,
- 'banner' => json_decode($setting->banner, true)
- ]);
- }
- /**
- * 模块名:event-msg-list
- * 代码描述:活动信息列表页
- * 作者:WPing丶
- * 请求方式:GET
- * 创建时间:2025/07/24 14:21:14
- * @param int event_id 活动ID
- * @param string type 信息类型:sign=签到;hotel=住宿信息;restaurant=用餐信息;itinerary=行程信息;
- */
- public function actionEventMsgList()
- {
- $user_id = get_user_id();
- $store_id = get_store_id();
- $event_id = get_params('event_id');
- $list = EventUser::find()->alias('eu')
- ->leftJoin(['e' => Event::tableName()], 'eu.event_id = e.id')
- ->where([
- 'eu.user_id' => $user_id,
- 'eu.store_id' => $store_id,
- 'eu.is_delete' => 0,
- 'e.is_delete' => 0,
- 'eu.apply_status' => 1,
- ])
- ->select('eu.id as event_user_id, e.name')
- ->asArray()
- ->all();
- return $this->asJson([
- 'code' => 0,
- 'msg' => 'success',
- 'data' => $list
- ]);
- }
- }
|