新增功能

This commit is contained in:
Your Name
2026-03-14 11:16:04 +08:00
parent eb283f008b
commit 4ddee40675
264 changed files with 5039 additions and 2813 deletions
+244
View File
@@ -0,0 +1,244 @@
<?php
namespace app\adminapi\logic;
use app\common\logic\BaseLogic;
use app\common\model\Fan;
use app\common\model\FanVisitRecord;
use think\facade\Db;
class FanLogic extends BaseLogic
{
/**
* @notes 添加粉丝
* @param array $params
* @return int|bool
*/
public static function add(array $params)
{
try {
if (!empty($params['phone'])) {
$exists = Fan::where('phone', $params['phone'])
->where('delete_time', null)
->find();
if ($exists) {
self::setError('该手机号已存在');
return false;
}
}
if (!empty($params['id_card'])) {
$exists = Fan::where('id_card', $params['id_card'])
->where('delete_time', null)
->find();
if ($exists) {
self::setError('该身份证号已存在');
return false;
}
}
$fan = Fan::create([
'name' => $params['name'],
'phone' => $params['phone'] ?? '',
'id_card' => $params['id_card'] ?? '',
'age' => $params['age'] ?? 0,
'gender' => $params['gender'] ?? 0,
'remark' => $params['remark'] ?? '',
'creator_id' => $params['creator_id'] ?? 0,
'creator_name' => $params['creator_name'] ?? '',
'status' => $params['status'] ?? 1,
]);
return $fan->id;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 编辑粉丝
* @param array $params
* @return bool
*/
public static function edit(array $params)
{
try {
if (!empty($params['phone'])) {
$exists = Fan::where('phone', $params['phone'])
->where('id', '<>', $params['id'])
->where('delete_time', null)
->find();
if ($exists) {
self::setError('该手机号已存在');
return false;
}
}
if (!empty($params['id_card'])) {
$exists = Fan::where('id_card', $params['id_card'])
->where('id', '<>', $params['id'])
->where('delete_time', null)
->find();
if ($exists) {
self::setError('该身份证号已存在');
return false;
}
}
Fan::update([
'id' => $params['id'],
'name' => $params['name'],
'phone' => $params['phone'] ?? '',
'id_card' => $params['id_card'] ?? '',
'age' => $params['age'] ?? 0,
'gender' => $params['gender'] ?? 0,
'remark' => $params['remark'] ?? '',
'status' => $params['status'] ?? 1,
]);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 删除粉丝
* @param array $params
* @return bool
*/
public static function delete(array $params)
{
try {
Fan::destroy($params['id']);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 粉丝详情
* @param array $params
* @return array
*/
public static function detail(array $params)
{
$fan = Fan::findOrEmpty($params['id']);
if ($fan->isEmpty()) {
return [];
}
$data = $fan->append(['gender_desc', 'status_desc'])->toArray();
return $data;
}
/**
* @notes 添加回访记录
* @param array $params
* @return int|bool
*/
public static function addVisitRecord(array $params)
{
try {
$fan = Fan::findOrEmpty($params['fan_id']);
if ($fan->isEmpty()) {
self::setError('粉丝不存在');
return false;
}
$record = FanVisitRecord::create([
'fan_id' => $params['fan_id'],
'visit_type' => $params['visit_type'] ?? 1,
'visit_time' => !empty($params['visit_time']) ? strtotime($params['visit_time']) : time(),
'content' => $params['content'] ?? '',
'result' => $params['result'] ?? '',
'next_visit_time' => !empty($params['next_visit_time']) ? strtotime($params['next_visit_time']) : null,
'operator_id' => $params['operator_id'] ?? 0,
'operator_name' => $params['operator_name'] ?? '',
]);
return $record->id;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 编辑回访记录
* @param array $params
* @return bool
*/
public static function editVisitRecord(array $params)
{
try {
FanVisitRecord::update([
'id' => $params['id'],
'visit_type' => $params['visit_type'] ?? 1,
'visit_time' => !empty($params['visit_time']) ? strtotime($params['visit_time']) : time(),
'content' => $params['content'] ?? '',
'result' => $params['result'] ?? '',
'next_visit_time' => !empty($params['next_visit_time']) ? strtotime($params['next_visit_time']) : null,
]);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 删除回访记录
* @param array $params
* @return bool
*/
public static function deleteVisitRecord(array $params)
{
try {
FanVisitRecord::destroy($params['id']);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 回访记录列表
* @param array $params
* @return array
*/
public static function visitRecordLists(array $params)
{
$where = [];
if (!empty($params['fan_id'])) {
$where[] = ['fan_id', '=', $params['fan_id']];
}
$pageNo = $params['page_no'] ?? 1;
$pageSize = $params['page_size'] ?? 15;
$count = FanVisitRecord::where($where)->count();
$lists = FanVisitRecord::where($where)
->append(['visit_type_desc'])
->order('id', 'desc')
->page($pageNo, $pageSize)
->select()
->toArray();
foreach ($lists as &$item) {
$item['visit_time_text'] = $item['visit_time'] ? date('Y-m-d H:i', $item['visit_time']) : '';
$item['next_visit_time_text'] = $item['next_visit_time'] ? date('Y-m-d H:i', $item['next_visit_time']) : '';
}
return [
'count' => $count,
'lists' => $lists,
'page_no' => $pageNo,
'page_size' => $pageSize,
];
}
}
+1 -1
View File
@@ -51,7 +51,7 @@ class LoginLogic extends BaseLogic
//设置token
$adminInfo = AdminTokenService::setToken($admin->id, $params['terminal'], $admin->multipoint_login);
//返回登录信息
$avatar = $admin->avatar ? $admin->avatar : Config::get('project.default_image.admin_avatar');
$avatar = FileService::getFileUrl($avatar);
@@ -16,7 +16,7 @@ namespace app\adminapi\logic\tcm;
use app\common\logic\BaseLogic;
use app\common\model\tcm\Diagnosis;
use app\common\model\DiagnosisViewRecord;
/**
* 中医辨房病因诊单逻辑
* Class DiagnosisLogic
@@ -278,7 +278,8 @@ class DiagnosisLogic extends BaseLogic
if (empty($diagnosis['local_hospital_visit_date']) && !empty($diagnosis['diagnosis_date'])) {
$diagnosis['local_hospital_visit_date'] = $diagnosis['diagnosis_date'];
}
$diagnosis['is_view'] =DiagnosisViewRecord::where(['diagnosis_id'=> $diagnosis['id'], 'user_id' =>$params['user_id']??0])->find() ? 1 : 0;
return $diagnosis;
}
@@ -986,6 +987,41 @@ class DiagnosisLogic extends BaseLogic
}
}
/**
* @notes 生成订单小程序码
*/
public static function generateOrderQrcode(array $params)
{
try {
$orderNo = $params['order_no'] ?? '';
if (empty($orderNo)) {
throw new \Exception('订单号不能为空');
}
$config = self::getMiniProgramConfig();
if (!$config) {
throw new \Exception('小程序配置未设置');
}
$page = 'pages/order/order';
$scene = "order_no={$orderNo}";
$qrcodeUrl = self::generateWxQrcode($config, $page, $scene);
if (!$qrcodeUrl) {
throw new \Exception('生成小程序码失败: ' . self::getError());
}
return [
'qrcode_url' => $qrcodeUrl,
'order_no' => $orderNo
];
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 获取小程序配置
* @return array|null
@@ -1207,19 +1243,19 @@ class DiagnosisLogic extends BaseLogic
$shareUserId = $params['share_user_id'] ?? 0;
// 获取诊单详情
$diagnosis = self::detail(['id' => $diagnosisId]);
$diagnosis = self::detail(['id' => $diagnosisId,'user_id' => $userId]);
if (!$diagnosis) {
throw new \Exception('诊单不存在');
}
// 记录查看行为
self::recordDiagnosisView([
'user_id' => $userId,
'diagnosis_id' => $diagnosisId,
'patient_id' => $diagnosis['patient_id'] ?? 0,
'share_user_id' => $shareUserId
]);
// self::recordDiagnosisView([
// 'user_id' => $userId,
// 'diagnosis_id' => $diagnosisId,
// 'patient_id' => $diagnosis['patient_id'] ?? 0,
// 'share_user_id' => $shareUserId
// ]);
return $diagnosis;
} catch (\Exception $e) {
@@ -1512,4 +1548,179 @@ class DiagnosisLogic extends BaseLogic
return false;
}
}
/**
* @notes 获取患者的企微信息(基于会话内容存档接口)
*/
public static function getWechatExternalContact(int $patientId)
{
try {
$diagnosis = \app\common\model\tcm\Diagnosis::where('patient_id', $patientId)
->field(['id', 'patient_name', 'phone', 'external_userid'])
->findOrEmpty();
if ($diagnosis->isEmpty()) {
$diagnosis = \app\common\model\tcm\Diagnosis::where('id', $patientId)
->field(['id', 'patient_name', 'phone', 'external_userid'])
->findOrEmpty();
}
if ($diagnosis->isEmpty()) {
self::setError('未找到患者信息');
return false;
}
$corpId = env('work_wechat.corp_id', '');
$msgauditSecret = env('work_wechat.msgaudit_secret', '');
$result = [
'patient_name' => $diagnosis->patient_name,
'phone' => $diagnosis->phone,
'external_userid' => $diagnosis->external_userid ?? '',
'msgaudit_enabled' => !empty($corpId) && !empty($msgauditSecret),
'permit_users' => [],
'msgaudit_agree' => [],
];
if (empty($corpId) || empty($msgauditSecret)) {
return $result;
}
$accessToken = self::getAccessToken($corpId, $msgauditSecret, 'msgaudit');
if (!$accessToken) {
return $result;
}
// 获取开启会话存档的成员列表
$permitUsers = self::fetchMsgAuditPermitUsers($accessToken);
$result['permit_users'] = $permitUsers;
// 如果有 external_userid,检查同意存档情况
if (!empty($diagnosis->external_userid) && !empty($permitUsers)) {
$agreeInfo = self::checkMsgAuditAgree($accessToken, $permitUsers, $diagnosis->external_userid);
$result['msgaudit_agree'] = $agreeInfo;
}
return $result;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
// ========== 通用 access_token 获取 ==========
private static function getAccessToken(string $corpId, string $secret, string $type = 'app')
{
$cacheKey = "work_wechat_{$type}_token_" . md5($corpId . $secret);
$cached = \think\facade\Cache::get($cacheKey);
if ($cached) return $cached;
$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpId}&corpsecret={$secret}";
$response = self::wechatHttpGet($url);
if (!$response || ($response['errcode'] ?? -1) != 0) {
\think\facade\Log::error("获取企微access_token失败[{$type}]: " . json_encode($response));
return false;
}
\think\facade\Cache::set($cacheKey, $response['access_token'], $response['expires_in'] - 200);
return $response['access_token'];
}
// ========== 会话内容存档 msgaudit 接口 ==========
/**
* @notes 获取会话内容存档开启成员列表
*/
public static function getMsgAuditPermitUsers()
{
try {
$corpId = env('work_wechat.corp_id', '');
$msgauditSecret = env('work_wechat.msgaudit_secret', '');
if (empty($corpId) || empty($msgauditSecret)) {
self::setError('会话内容存档Secret未配置(MSGAUDIT_SECRET');
return false;
}
$accessToken = self::getAccessToken($corpId, $msgauditSecret, 'msgaudit');
if (!$accessToken) {
self::setError('获取会话内容存档access_token失败');
return false;
}
$ids = self::fetchMsgAuditPermitUsers($accessToken);
return ['ids' => $ids];
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
private static function fetchMsgAuditPermitUsers(string $accessToken): array
{
$url = "https://qyapi.weixin.qq.com/cgi-bin/msgaudit/get_permit_user_list?access_token={$accessToken}";
$response = self::wechatHttpPost($url, '{}');
if (!$response || ($response['errcode'] ?? -1) != 0) {
return [];
}
return $response['ids'] ?? [];
}
/**
* @notes 检查单聊会话同意存档情况
*/
private static function checkMsgAuditAgree(string $accessToken, array $permitUserIds, string $externalUserId)
{
$infoList = [];
foreach ($permitUserIds as $userId) {
$infoList[] = [
'userid' => $userId,
'exteranalopenid' => $externalUserId,
];
}
$url = "https://qyapi.weixin.qq.com/cgi-bin/msgaudit/check_single_agree?access_token={$accessToken}";
$response = self::wechatHttpPost($url, json_encode(['info' => $infoList]));
if (!$response || ($response['errcode'] ?? -1) != 0) {
return [];
}
return $response['agreeinfo'] ?? [];
}
// ========== HTTP 工具方法 ==========
private static function wechatHttpGet(string $url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$result = curl_exec($ch);
curl_close($ch);
return $result ? json_decode($result, true) : null;
}
private static function wechatHttpPost(string $url, string $jsonBody)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonBody);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$result = curl_exec($ch);
curl_close($ch);
return $result ? json_decode($result, true) : null;
}
}