diff --git a/Server/application/api/controller/UserController.php b/Server/application/api/controller/UserController.php index 209f1b0e..ab4ce133 100644 --- a/Server/application/api/controller/UserController.php +++ b/Server/application/api/controller/UserController.php @@ -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()]); } } diff --git a/Server/application/chukebao/controller/DataProcessing.php b/Server/application/chukebao/controller/DataProcessing.php index 72e617ea..863fee48 100644 --- a/Server/application/chukebao/controller/DataProcessing.php +++ b/Server/application/chukebao/controller/DataProcessing.php @@ -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); } diff --git a/Server/application/chukebao/controller/WechatFriendController.php b/Server/application/chukebao/controller/WechatFriendController.php index 931d8ce6..a37e31e6 100644 --- a/Server/application/chukebao/controller/WechatFriendController.php +++ b/Server/application/chukebao/controller/WechatFriendController.php @@ -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] : '未知状态'; } } \ No newline at end of file diff --git a/Server/application/common/controller/ExportController.php b/Server/application/common/controller/ExportController.php new file mode 100644 index 00000000..aea58f15 --- /dev/null +++ b/Server/application/common/controller/ExportController.php @@ -0,0 +1,166 @@ + 需要在请求结束时清理的临时文件 + */ + 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 = []; + } +} \ No newline at end of file diff --git a/Server/application/cunkebao/controller/BaseController.php b/Server/application/cunkebao/controller/BaseController.php index 26bd79db..f3875d54 100644 --- a/Server/application/cunkebao/controller/BaseController.php +++ b/Server/application/cunkebao/controller/BaseController.php @@ -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('密码修改失败');