新增功能
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\controller;
|
||||
|
||||
use app\adminapi\controller\BaseAdminController;
|
||||
use app\adminapi\lists\FanLists;
|
||||
use app\adminapi\logic\FanLogic;
|
||||
use app\adminapi\validate\FanValidate;
|
||||
use app\adminapi\validate\FanVisitRecordValidate;
|
||||
|
||||
class FanController extends BaseAdminController
|
||||
{
|
||||
/**
|
||||
* @notes 粉丝列表
|
||||
*/
|
||||
public function lists()
|
||||
{
|
||||
return $this->dataLists(new FanLists());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 添加粉丝
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$params = (new FanValidate())->post()->goCheck('add');
|
||||
$params['creator_id'] = $this->adminId;
|
||||
$params['creator_name'] = $this->adminInfo['name'] ?? '';
|
||||
$result = FanLogic::add($params);
|
||||
if ($result) {
|
||||
return $this->success('添加成功', ['id' => $result], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 编辑粉丝
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$params = (new FanValidate())->post()->goCheck('edit');
|
||||
$result = FanLogic::edit($params);
|
||||
if ($result) {
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 删除粉丝
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$params = (new FanValidate())->post()->goCheck('id');
|
||||
$result = FanLogic::delete($params);
|
||||
if ($result) {
|
||||
return $this->success('删除成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 粉丝详情
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
$params = (new FanValidate())->goCheck('id');
|
||||
$result = FanLogic::detail($params);
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 回访记录列表
|
||||
*/
|
||||
public function visitRecordLists()
|
||||
{
|
||||
$params = $this->request->get();
|
||||
$result = FanLogic::visitRecordLists($params);
|
||||
return $this->success('', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 添加回访记录
|
||||
*/
|
||||
public function addVisitRecord()
|
||||
{
|
||||
$params = (new FanVisitRecordValidate())->post()->goCheck('add');
|
||||
$params['operator_id'] = $this->adminId;
|
||||
$params['operator_name'] = $this->adminInfo['name'] ?? '';
|
||||
$result = FanLogic::addVisitRecord($params);
|
||||
if ($result) {
|
||||
return $this->success('添加成功', ['id' => $result], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 编辑回访记录
|
||||
*/
|
||||
public function editVisitRecord()
|
||||
{
|
||||
$params = (new FanVisitRecordValidate())->post()->goCheck('edit');
|
||||
$result = FanLogic::editVisitRecord($params);
|
||||
if ($result) {
|
||||
return $this->success('编辑成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 删除回访记录
|
||||
*/
|
||||
public function deleteVisitRecord()
|
||||
{
|
||||
$params = (new FanVisitRecordValidate())->post()->goCheck('id');
|
||||
$result = FanLogic::deleteVisitRecord($params);
|
||||
if ($result) {
|
||||
return $this->success('删除成功', [], 1, 1);
|
||||
}
|
||||
return $this->fail(FanLogic::getError());
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ use app\adminapi\controller\BaseAdminController;
|
||||
use app\adminapi\lists\tcm\DiagnosisLists;
|
||||
use app\adminapi\logic\tcm\DiagnosisLogic;
|
||||
use app\adminapi\validate\tcm\DiagnosisValidate;
|
||||
use app\common\model\WechatChatRecord;
|
||||
|
||||
/**
|
||||
* 中医辨房病因诊单控制器
|
||||
@@ -97,6 +98,7 @@ class DiagnosisController extends BaseAdminController
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
|
||||
$params = (new DiagnosisValidate())->goCheck('id');
|
||||
$result = DiagnosisLogic::detail($params);
|
||||
return $this->data($result);
|
||||
@@ -324,6 +326,135 @@ class DiagnosisController extends BaseAdminController
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 生成订单小程序码
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function generateOrderQrcode()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
$params['share_user_id'] = $this->adminId;
|
||||
$result = DiagnosisLogic::generateOrderQrcode($params);
|
||||
if ($result === false) {
|
||||
return $this->fail(DiagnosisLogic::getError());
|
||||
}
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 获取企业微信聊天记录
|
||||
*/
|
||||
public function getWechatChatRecords()
|
||||
{
|
||||
$diagnosisId = $this->request->get('diagnosis_id', 0);
|
||||
$patientId = $this->request->get('patient_id', 0);
|
||||
$pageNo = $this->request->get('page_no', 1);
|
||||
$pageSize = $this->request->get('page_size', 20);
|
||||
|
||||
if (empty($diagnosisId) && empty($patientId)) {
|
||||
return $this->fail('诊单ID或患者ID不能都为空');
|
||||
}
|
||||
|
||||
$query = WechatChatRecord::order('chat_time', 'desc');
|
||||
if ($diagnosisId) {
|
||||
$query->where('diagnosis_id', $diagnosisId);
|
||||
}
|
||||
if ($patientId) {
|
||||
$query->where('patient_id', $patientId);
|
||||
}
|
||||
|
||||
$count = (clone $query)->count();
|
||||
$lists = $query->page($pageNo, $pageSize)->select()->toArray();
|
||||
|
||||
return $this->data([
|
||||
'lists' => $lists,
|
||||
'count' => $count,
|
||||
'page_no' => $pageNo,
|
||||
'page_size' => $pageSize
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 添加企业微信聊天记录(手动录入/同步写入)
|
||||
*/
|
||||
public function addWechatChatRecord()
|
||||
{
|
||||
$params = $this->request->post();
|
||||
|
||||
if (empty($params['diagnosis_id']) && empty($params['patient_id'])) {
|
||||
return $this->fail('诊单ID或患者ID不能都为空');
|
||||
}
|
||||
if (empty($params['content'])) {
|
||||
return $this->fail('内容不能为空');
|
||||
}
|
||||
|
||||
$adminInfo = $this->adminInfo;
|
||||
|
||||
$data = [
|
||||
'diagnosis_id' => $params['diagnosis_id'] ?? 0,
|
||||
'patient_id' => $params['patient_id'] ?? 0,
|
||||
'staff_userid' => $adminInfo['work_wechat_userid'] ?? ($params['staff_userid'] ?? ''),
|
||||
'staff_name' => $params['staff_name'] ?? ($adminInfo['name'] ?? ''),
|
||||
'external_userid' => $params['external_userid'] ?? '',
|
||||
'external_name' => $params['external_name'] ?? '',
|
||||
'msg_type' => $params['msg_type'] ?? 'note',
|
||||
'content' => $params['content'],
|
||||
'media_url' => $params['media_url'] ?? '',
|
||||
'chat_time' => $params['chat_time'] ?? time(),
|
||||
'direction' => $params['direction'] ?? 0,
|
||||
'create_time' => time(),
|
||||
];
|
||||
|
||||
$record = WechatChatRecord::create($data);
|
||||
|
||||
return $this->success('添加成功', ['id' => $record->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 删除企业微信聊天记录
|
||||
*/
|
||||
public function deleteWechatChatRecord()
|
||||
{
|
||||
$id = $this->request->post('id', 0);
|
||||
if (empty($id)) {
|
||||
return $this->fail('记录ID不能为空');
|
||||
}
|
||||
|
||||
WechatChatRecord::destroy($id);
|
||||
return $this->success('删除成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 同步企业微信外部联系人信息(查找该患者在企业微信中的跟进人)
|
||||
*/
|
||||
public function getWechatExternalContact()
|
||||
{
|
||||
$patientId = $this->request->get('patient_id', 0);
|
||||
if (empty($patientId)) {
|
||||
return $this->fail('患者ID不能为空');
|
||||
}
|
||||
|
||||
$result = DiagnosisLogic::getWechatExternalContact($patientId);
|
||||
if ($result === false) {
|
||||
return $this->fail(DiagnosisLogic::getError());
|
||||
}
|
||||
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 获取会话内容存档开启的成员列表
|
||||
*/
|
||||
public function getMsgAuditPermitUsers()
|
||||
{
|
||||
$result = DiagnosisLogic::getMsgAuditPermitUsers();
|
||||
if ($result === false) {
|
||||
return $this->fail(DiagnosisLogic::getError());
|
||||
}
|
||||
|
||||
return $this->data($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 搜索患者(用于创建订单等场景)
|
||||
* @return \think\response\Json
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\lists;
|
||||
|
||||
use app\adminapi\lists\BaseAdminDataLists;
|
||||
use app\common\model\Fan;
|
||||
use app\common\model\FanVisitRecord;
|
||||
use app\common\lists\ListsSearchInterface;
|
||||
|
||||
class FanLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
{
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
'%like%' => ['name', 'phone'],
|
||||
'=' => ['gender', 'status'],
|
||||
];
|
||||
}
|
||||
|
||||
public function lists(): array
|
||||
{
|
||||
$lists = Fan::where($this->searchWhere)
|
||||
->field(['id', 'name', 'phone', 'id_card', 'age', 'gender', 'remark', 'creator_id', 'creator_name', 'status', 'create_time', 'update_time'])
|
||||
->append(['gender_desc', 'status_desc'])
|
||||
->order(['id' => 'desc'])
|
||||
->limit($this->limitOffset, $this->limitLength)
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$fanIds = array_column($lists, 'id');
|
||||
if (!empty($fanIds)) {
|
||||
$visitCounts = FanVisitRecord::where('fan_id', 'in', $fanIds)
|
||||
->where('delete_time', null)
|
||||
->group('fan_id')
|
||||
->column('count(*) as cnt', 'fan_id');
|
||||
|
||||
foreach ($lists as &$item) {
|
||||
$item['visit_count'] = $visitCounts[$item['id']] ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $lists;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return Fan::where($this->searchWhere)->count();
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,7 @@ class DiagnosisLists extends BaseAdminDataLists implements ListsSearchInterface
|
||||
}
|
||||
|
||||
$lists = $query
|
||||
->with(['DiagnosisViewRecord'])
|
||||
->field(['id', 'patient_id', 'patient_name', 'id_card', 'phone', 'gender', 'age', 'diagnosis_date', 'diagnosis_type', 'syndrome_type', 'assistant_id', 'status', 'create_time', 'update_time'])
|
||||
->append(['gender_desc', 'status_desc', 'diagnosis_date_text'])
|
||||
->order(['id' => 'desc'])
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\validate;
|
||||
|
||||
use app\common\validate\BaseValidate;
|
||||
|
||||
class FanValidate extends BaseValidate
|
||||
{
|
||||
protected $rule = [
|
||||
'id' => 'require',
|
||||
'name' => 'require|length:1,50',
|
||||
'phone' => 'require|mobile',
|
||||
'id_card' => 'length:15,18',
|
||||
'age' => 'number|between:0,150',
|
||||
'gender' => 'in:0,1,2',
|
||||
'status' => 'in:0,1',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'id.require' => '参数缺失',
|
||||
'name.require' => '请输入姓名',
|
||||
'name.length' => '姓名长度须在1-50位字符',
|
||||
'phone.require' => '请输入手机号',
|
||||
'phone.mobile' => '手机号格式不正确',
|
||||
'id_card.length' => '身份证号长度不正确',
|
||||
'age.number' => '年龄必须为数字',
|
||||
'age.between' => '年龄范围0-150',
|
||||
'gender.in' => '性别参数错误',
|
||||
'status.in' => '状态参数错误',
|
||||
];
|
||||
|
||||
public function sceneAdd()
|
||||
{
|
||||
return $this->remove('id', true);
|
||||
}
|
||||
|
||||
public function sceneEdit()
|
||||
{
|
||||
return $this->only(['id', 'name', 'phone', 'id_card', 'age', 'gender', 'status']);
|
||||
}
|
||||
|
||||
public function sceneId()
|
||||
{
|
||||
return $this->only(['id']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace app\adminapi\validate;
|
||||
|
||||
use app\common\validate\BaseValidate;
|
||||
|
||||
class FanVisitRecordValidate extends BaseValidate
|
||||
{
|
||||
protected $rule = [
|
||||
'id' => 'require',
|
||||
'fan_id' => 'require',
|
||||
'visit_type' => 'require|in:1,2,3,4,5',
|
||||
'visit_time' => 'require',
|
||||
'content' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'id.require' => '参数缺失',
|
||||
'fan_id.require' => '请选择粉丝',
|
||||
'visit_type.require' => '请选择回访类型',
|
||||
'visit_type.in' => '回访类型参数错误',
|
||||
'visit_time.require' => '请选择回访时间',
|
||||
'content.require' => '请输入回访内容',
|
||||
];
|
||||
|
||||
public function sceneAdd()
|
||||
{
|
||||
return $this->remove('id', true);
|
||||
}
|
||||
|
||||
public function sceneEdit()
|
||||
{
|
||||
return $this->only(['id', 'visit_type', 'visit_time', 'content', 'result', 'next_visit_time']);
|
||||
}
|
||||
|
||||
public function sceneId()
|
||||
{
|
||||
return $this->only(['id']);
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,11 @@ class DiagnosisValidate extends BaseValidate
|
||||
->append('share_user_id', 'require');
|
||||
}
|
||||
|
||||
public function sceneGenerateOrderQrcode()
|
||||
{
|
||||
return $this->only([]);
|
||||
}
|
||||
|
||||
protected function checkDiagnosis($value)
|
||||
{
|
||||
$diagnosis = Diagnosis::findOrEmpty($value);
|
||||
|
||||
Reference in New Issue
Block a user