聊天消息记录状态 + 表格导出底层
This commit is contained in:
@@ -201,40 +201,38 @@ class UserController extends BaseController
|
||||
* 修改密码
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function modifyPwd()
|
||||
public function modifyPwd($data = [])
|
||||
{
|
||||
// 获取并验证参数
|
||||
$params = $this->validateModifyPwdParams();
|
||||
if (!is_array($params)) {
|
||||
return $params;
|
||||
|
||||
if (empty($data)) {
|
||||
return json_encode(['code' => 400,'msg' => '参数缺失']);
|
||||
}
|
||||
|
||||
$authorization = trim($this->request->header('authorization', $this->authorization));
|
||||
if (!isset($data['id']) || !isset($data['pwd'])) {
|
||||
return json_encode(['code' => 401,'msg' => '参数缺失']);
|
||||
}
|
||||
$authorization = $this->authorization;
|
||||
|
||||
if (empty($authorization)) {
|
||||
return errorJson('缺少授权信息');
|
||||
return json_encode(['code' => 400,'msg' => '缺少授权信息']);
|
||||
}
|
||||
|
||||
$headerData = ['client:' . self::CLIENT_TYPE];
|
||||
$header = setHeader($headerData, $authorization, 'plain');
|
||||
$headerData = ['client:system'];
|
||||
$header = setHeader($headerData, $authorization, 'json');
|
||||
$params = [
|
||||
'id' => $data['id'],
|
||||
'newPw' => $data['pwd'],
|
||||
];
|
||||
|
||||
try {
|
||||
$result = requestCurl($this->baseUrl . 'api/Account/self', $params, 'PUT', $header);
|
||||
$result = requestCurl($this->baseUrl . 'api/Account/modifypw', $params, 'PUT', $header,'json');
|
||||
$response = handleApiResponse($result);
|
||||
|
||||
if (empty($response)) {
|
||||
// 获取当前用户信息
|
||||
$currentUser = CompanyAccountModel::where('token', $authorization)->find();
|
||||
if ($currentUser) {
|
||||
recordUserLog($currentUser['id'], $currentUser['userName'], 'MODIFY_PASSWORD', '修改密码成功', [], 200, '修改成功');
|
||||
}
|
||||
return successJson(['message' => '修改成功']);
|
||||
return json_encode(['code' => 200,'msg' => '修改成功']);
|
||||
}
|
||||
|
||||
recordUserLog(0, '', 'MODIFY_PASSWORD', '修改密码失败', $params, 500, $response);
|
||||
return errorJson($response);
|
||||
return json_encode(['code' => 400,'msg' => $response]);
|
||||
} catch (\Exception $e) {
|
||||
recordUserLog(0, '', 'MODIFY_PASSWORD', '修改密码异常', $params, 500, $e->getMessage());
|
||||
return errorJson('修改密码失败:' . $e->getMessage());
|
||||
return json_encode(['code' => 400,'msg' => '修改密码失败:' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace app\chukebao\controller;
|
||||
|
||||
use library\ResponseHelper;
|
||||
use app\api\model\WechatFriendModel;
|
||||
use app\api\model\WechatMessageModel;
|
||||
use app\api\controller\MessageController;
|
||||
|
||||
|
||||
@@ -33,6 +34,7 @@ class DataProcessing extends BaseController
|
||||
'CmdAllotFriend', //转让好友 {labels、wechatAccountId、wechatFriendId}
|
||||
'CmdChatroomOperate', //修改群信息 {chatroomName(群名)、announce(公告)、extra(公告)、wechatAccountId、wechatChatroomId}
|
||||
'CmdNewMessage', //接收消息
|
||||
'CmdSendMessageResult', //更新消息状态
|
||||
];
|
||||
|
||||
if (empty($type) || empty($wechatAccountId)) {
|
||||
@@ -107,6 +109,44 @@ class DataProcessing extends BaseController
|
||||
$msg = '消息记录失败';
|
||||
$codee = 400;
|
||||
}
|
||||
break;
|
||||
case 'CmdSendMessageResult':
|
||||
$friendMessageId = $this->request->param('friendMessageId', 0);
|
||||
$chatroomMessageId = $this->request->param('chatroomMessageId', 0);
|
||||
$sendStatus = $this->request->param('sendStatus', null);
|
||||
$wechatTime = $this->request->param('wechatTime', 0);
|
||||
|
||||
if ($sendStatus === null) {
|
||||
return ResponseHelper::error('sendStatus不能为空');
|
||||
}
|
||||
|
||||
if (empty($friendMessageId) && empty($chatroomMessageId)) {
|
||||
return ResponseHelper::error('friendMessageId或chatroomMessageId至少提供一个');
|
||||
}
|
||||
|
||||
$messageId = $friendMessageId ?: $chatroomMessageId;
|
||||
$update = [
|
||||
'sendStatus' => (int)$sendStatus,
|
||||
];
|
||||
|
||||
if (!empty($wechatTime)) {
|
||||
$update['wechatTime'] = strlen((string)$wechatTime) > 10
|
||||
? intval($wechatTime / 1000)
|
||||
: (int)$wechatTime;
|
||||
}
|
||||
|
||||
$affected = WechatMessageModel::where('id', $messageId)->update($update);
|
||||
|
||||
if ($affected === false) {
|
||||
return ResponseHelper::error('更新消息状态失败');
|
||||
}
|
||||
|
||||
if ($affected === 0) {
|
||||
return ResponseHelper::error('消息不存在');
|
||||
}
|
||||
|
||||
$msg = '更新消息状态成功';
|
||||
break;
|
||||
}
|
||||
return ResponseHelper::success('',$msg,$codee);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class WechatFriendController extends BaseController
|
||||
$total = $query->count();
|
||||
$list = $query->page($page, $limit)->select();
|
||||
|
||||
// 提取所有好友ID
|
||||
// 提取所有好友ID
|
||||
$friendIds = array_column($list, 'id');
|
||||
|
||||
$aiTypeData = [];
|
||||
@@ -67,7 +67,7 @@ class WechatFriendController extends BaseController
|
||||
$friend = Db::table('s2_wechat_friend')
|
||||
->where(['id' => $friendId, 'isDeleted' => 0])
|
||||
->find();
|
||||
|
||||
|
||||
if (empty($friend)) {
|
||||
return ResponseHelper::error('好友不存在');
|
||||
}
|
||||
@@ -78,11 +78,11 @@ class WechatFriendController extends BaseController
|
||||
$friend['createTime'] = !empty($friend['createTime']) ? date('Y-m-d H:i:s', $friend['createTime']) : '';
|
||||
$friend['updateTime'] = !empty($friend['updateTime']) ? date('Y-m-d H:i:s', $friend['updateTime']) : '';
|
||||
$friend['passTime'] = !empty($friend['passTime']) ? date('Y-m-d H:i:s', $friend['passTime']) : '';
|
||||
|
||||
|
||||
// 获取AI类型设置
|
||||
$aiTypeSetting = FriendSettings::where('friendId', $friendId)->find();
|
||||
$friend['aiType'] = $aiTypeSetting ? $aiTypeSetting['type'] : 0;
|
||||
|
||||
|
||||
return ResponseHelper::success(['detail' => $friend]);
|
||||
}
|
||||
|
||||
@@ -183,87 +183,38 @@ class WechatFriendController extends BaseController
|
||||
if (empty($accountId)) {
|
||||
return ResponseHelper::error('请先登录');
|
||||
}
|
||||
|
||||
|
||||
// 直接使用operatorAccountId查询添加好友任务记录
|
||||
$query = Db::table('s2_friend_task')
|
||||
->where('operatorAccountId', $accountId)
|
||||
->order('createTime desc');
|
||||
|
||||
|
||||
// 如果指定了状态筛选
|
||||
if ($status !== '' && $status !== null) {
|
||||
$query->where('status', $status);
|
||||
}
|
||||
|
||||
|
||||
$total = $query->count();
|
||||
$tasks = $query->page($page, $limit)->select();
|
||||
|
||||
// 提取所有任务的phone和wechatId,用于查询好友信息(获取通过时间)
|
||||
$taskPhones = [];
|
||||
$taskWechatIds = [];
|
||||
foreach ($tasks as $task) {
|
||||
if (!empty($task['phone'])) {
|
||||
$taskPhones[] = $task['phone'];
|
||||
}
|
||||
if (!empty($task['wechatId'])) {
|
||||
$taskWechatIds[] = $task['wechatId'];
|
||||
}
|
||||
}
|
||||
|
||||
// 查询好友信息,获取通过时间
|
||||
$friendPassTimeMap = [];
|
||||
if (!empty($taskPhones) || !empty($taskWechatIds)) {
|
||||
// 分别通过phone和wechatId查询,确保都能匹配到
|
||||
$friendsByPhone = [];
|
||||
$friendsByWechatId = [];
|
||||
|
||||
if (!empty($taskPhones)) {
|
||||
$friendsByPhone = Db::table('s2_wechat_friend')
|
||||
->where('accountId', $accountId)
|
||||
->where('isDeleted', 0)
|
||||
->where('phone', 'in', $taskPhones)
|
||||
->field('phone,wechatId,passTime,nickname')
|
||||
->select();
|
||||
}
|
||||
|
||||
if (!empty($taskWechatIds)) {
|
||||
$friendsByWechatId = Db::table('s2_wechat_friend')
|
||||
->where('accountId', $accountId)
|
||||
->where('isDeleted', 0)
|
||||
->where('wechatId', 'in', $taskWechatIds)
|
||||
->field('phone,wechatId,passTime,nickname')
|
||||
->select();
|
||||
}
|
||||
|
||||
// 合并结果并构建映射表(优先使用phone作为key)
|
||||
$allFriends = array_merge($friendsByPhone, $friendsByWechatId);
|
||||
foreach ($allFriends as $friend) {
|
||||
// 使用phone作为key(如果存在)
|
||||
if (!empty($friend['phone'])) {
|
||||
$friendPassTimeMap[$friend['phone']] = [
|
||||
'passTime' => $friend['passTime'] ?? 0,
|
||||
'nickname' => $friend['nickname'] ?? '',
|
||||
];
|
||||
}
|
||||
// 同时使用wechatId作为key(如果存在且phone为空)
|
||||
if (!empty($friend['wechatId']) && empty($friend['phone'])) {
|
||||
$friendPassTimeMap[$friend['wechatId']] = [
|
||||
'passTime' => $friend['passTime'] ?? 0,
|
||||
'nickname' => $friend['nickname'] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 处理任务数据
|
||||
$list = [];
|
||||
foreach ($tasks as $task) {
|
||||
$taskKey = !empty($task['phone']) ? $task['phone'] : ($task['wechatId'] ?? '');
|
||||
$friendInfo = isset($friendPassTimeMap[$taskKey]) ? $friendPassTimeMap[$taskKey] : null;
|
||||
|
||||
// 提取所有任务的phone、wechatId,用于查询好友信息(获取通过时间)
|
||||
$friendInfo = Db::table('s2_wechat_friend')
|
||||
->where(['isDeleted' => 0, 'ownerWechatId' => $task['wechatId']])
|
||||
->where(function ($query) use ($task) {
|
||||
$query->whereLike('phone', '%'.$task['phone'].'%')->whereOr('alias', $task['phone'])->whereOr('wechatId', $task['phone']);
|
||||
})->field('phone,wechatId,alias,passTime,nickname')->find();
|
||||
|
||||
|
||||
|
||||
$item = [
|
||||
'taskId' => $task['id'] ?? 0,
|
||||
'phone' => $task['phone'] ?? '',
|
||||
'wechatId' => $task['wechatId'] ?? '',
|
||||
'alias' => $task['alias'] ?? '',
|
||||
// 添加者信息
|
||||
'adder' => [
|
||||
'avatar' => $task['wechatAvatar'] ?? '', // 添加者头像
|
||||
@@ -276,6 +227,7 @@ class WechatFriendController extends BaseController
|
||||
'status' => [
|
||||
'code' => $task['status'] ?? 0, // 状态码:0执行中,1执行成功,2执行失败
|
||||
'text' => $this->getTaskStatusText($task['status'] ?? 0), // 状态文本
|
||||
'extra' => ''
|
||||
],
|
||||
// 时间信息
|
||||
'time' => [
|
||||
@@ -299,10 +251,10 @@ class WechatFriendController extends BaseController
|
||||
'labels' => !empty($task['labels']) ? explode(',', $task['labels']) : [], // 标签
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
$list[] = $item;
|
||||
}
|
||||
|
||||
|
||||
return ResponseHelper::success(['list' => $list, 'total' => $total]);
|
||||
}
|
||||
|
||||
@@ -319,7 +271,7 @@ class WechatFriendController extends BaseController
|
||||
1 => '执行成功',
|
||||
2 => '执行失败',
|
||||
];
|
||||
|
||||
|
||||
return isset($statusMap[$status]) ? $statusMap[$status] : '未知状态';
|
||||
}
|
||||
}
|
||||
166
Server/application/common/controller/ExportController.php
Normal file
166
Server/application/common/controller/ExportController.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\controller;
|
||||
|
||||
use PHPExcel;
|
||||
use PHPExcel_IOFactory;
|
||||
use PHPExcel_Worksheet_Drawing;
|
||||
use think\Controller;
|
||||
use think\Exception;
|
||||
|
||||
/**
|
||||
* 通用导出控制器,提供 Excel 导出与图片插入能力
|
||||
*/
|
||||
class ExportController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var array<string> 需要在请求结束时清理的临时文件
|
||||
*/
|
||||
protected static $tempFiles = [];
|
||||
|
||||
/**
|
||||
* 导出 Excel(支持指定列插入图片)
|
||||
*
|
||||
* @param string $fileName 输出文件名(可不带扩展名)
|
||||
* @param array $headers 列定义,例如 ['name' => '姓名', 'phone' => '电话']
|
||||
* @param array $rows 数据行,需与 $headers 的 key 对应
|
||||
* @param array $imageColumns 需要渲染为图片的列 key 列表
|
||||
* @param string $sheetName 工作表名称
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function exportExcelWithImages(
|
||||
$fileName,
|
||||
array $headers,
|
||||
array $rows,
|
||||
array $imageColumns = [],
|
||||
$sheetName = 'Sheet1'
|
||||
) {
|
||||
if (empty($headers)) {
|
||||
throw new Exception('导出列定义不能为空');
|
||||
}
|
||||
if (empty($rows)) {
|
||||
throw new Exception('导出数据不能为空');
|
||||
}
|
||||
|
||||
$excel = new PHPExcel();
|
||||
$sheet = $excel->getActiveSheet();
|
||||
$sheet->setTitle($sheetName);
|
||||
|
||||
$columnKeys = array_keys($headers);
|
||||
|
||||
// 写入表头
|
||||
foreach ($columnKeys as $index => $key) {
|
||||
$columnLetter = self::columnLetter($index);
|
||||
$sheet->setCellValue($columnLetter . '1', $headers[$key]);
|
||||
$sheet->getColumnDimension($columnLetter)->setAutoSize(true);
|
||||
}
|
||||
|
||||
// 写入数据与图片
|
||||
foreach ($rows as $rowIndex => $rowData) {
|
||||
$excelRow = $rowIndex + 2; // 数据从第 2 行开始
|
||||
foreach ($columnKeys as $colIndex => $key) {
|
||||
$columnLetter = self::columnLetter($colIndex);
|
||||
$cell = $columnLetter . $excelRow;
|
||||
$value = isset($rowData[$key]) ? $rowData[$key] : '';
|
||||
|
||||
if (in_array($key, $imageColumns, true) && !empty($value)) {
|
||||
$imagePath = self::resolveImagePath($value);
|
||||
if ($imagePath) {
|
||||
$drawing = new PHPExcel_Worksheet_Drawing();
|
||||
$drawing->setPath($imagePath);
|
||||
$drawing->setCoordinates($cell);
|
||||
$drawing->setOffsetX(5);
|
||||
$drawing->setOffsetY(5);
|
||||
$drawing->setHeight(60);
|
||||
$drawing->setWorksheet($sheet);
|
||||
$sheet->getRowDimension($excelRow)->setRowHeight(60);
|
||||
} else {
|
||||
$sheet->setCellValue($cell, $value);
|
||||
}
|
||||
} else {
|
||||
$sheet->setCellValue($cell, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$safeName = preg_replace('/[^\w\-]/', '_', $fileName ?: 'export_' . date('Ymd_His'));
|
||||
if (stripos($safeName, '.xlsx') === false) {
|
||||
$safeName .= '.xlsx';
|
||||
}
|
||||
|
||||
if (ob_get_length()) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
header('Cache-Control: max-age=0');
|
||||
header('Content-Disposition: attachment;filename="' . $safeName . '"');
|
||||
|
||||
$writer = PHPExcel_IOFactory::createWriter($excel, 'Excel2007');
|
||||
$writer->save('php://output');
|
||||
|
||||
self::cleanupTempFiles();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据列序号生成 Excel 列字母
|
||||
*
|
||||
* @param int $index
|
||||
* @return string
|
||||
*/
|
||||
protected static function columnLetter($index)
|
||||
{
|
||||
$letters = '';
|
||||
do {
|
||||
$letters = chr($index % 26 + 65) . $letters;
|
||||
$index = intval($index / 26) - 1;
|
||||
} while ($index >= 0);
|
||||
|
||||
return $letters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将远程或本地图片路径转换为可用的本地文件路径
|
||||
*
|
||||
* @param string $path
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function resolveImagePath($path)
|
||||
{
|
||||
if (empty($path)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('/^https?:\/\//i', $path)) {
|
||||
$tempFile = tempnam(sys_get_temp_dir(), 'export_img_');
|
||||
$stream = @file_get_contents($path);
|
||||
if ($stream === false) {
|
||||
return null;
|
||||
}
|
||||
file_put_contents($tempFile, $stream);
|
||||
self::$tempFiles[] = $tempFile;
|
||||
return $tempFile;
|
||||
}
|
||||
|
||||
if (file_exists($path)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理所有临时文件
|
||||
*/
|
||||
protected static function cleanupTempFiles()
|
||||
{
|
||||
foreach (self::$tempFiles as $file) {
|
||||
if (file_exists($file)) {
|
||||
@unlink($file);
|
||||
}
|
||||
}
|
||||
self::$tempFiles = [];
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\cunkebao\controller;
|
||||
|
||||
use app\api\controller\AccountController;
|
||||
use app\api\controller\UserController;
|
||||
use app\common\service\ClassTableService;
|
||||
use library\ResponseHelper;
|
||||
use think\Controller;
|
||||
@@ -148,6 +149,12 @@ class BaseController extends Controller
|
||||
|
||||
$res = Db::name('users')->where(['id' => $userId, 'companyId' => $companyId])->update($data);
|
||||
if (!empty($res)) {
|
||||
if ($user['typeId'] == 1 && !empty($user['s2_accountId'])) {
|
||||
$UserController = new UserController();
|
||||
$UserController->modifyPwd(['id' => $user['s2_accountId'],'pwd' => $passWord]);
|
||||
}
|
||||
|
||||
|
||||
return ResponseHelper::success('密码修改成功');
|
||||
} else {
|
||||
return ResponseHelper::error('密码修改失败');
|
||||
|
||||
Reference in New Issue
Block a user