DistributionRecordLogic.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | saiadmin [ saiadmin快速开发框架 ]
  4. // +----------------------------------------------------------------------
  5. namespace plugin\saiadmin\app\logic\device;
  6. use plugin\saiadmin\basic\think\BaseLogic;
  7. use plugin\saiadmin\service\OpenSpoutWriter;
  8. use support\Response;
  9. use support\think\Db;
  10. /**
  11. * 设备铺货记录列表、搜索与导出。
  12. *
  13. * 业务语义迁移自旧项目 agentapi/merchant/bind_device_records:
  14. * action_type 1 为铺货,2 为解绑;查询范围按设备当前管理代理隔离。
  15. */
  16. class DistributionRecordLogic extends BaseLogic
  17. {
  18. private const TYPE_NAMES = [
  19. 1 => '充电底座',
  20. 100 => 'K霸宝',
  21. 101 => '充电宝',
  22. 102 => 'K霸宝 Blue',
  23. 103 => '密码线充',
  24. 104 => '蓝牙线充',
  25. 105 => '密码蓝牙线充',
  26. 107 => '车载充电器',
  27. ];
  28. public function indexList(array $where): array
  29. {
  30. $page = max(1, (int) request()->input('page', 1));
  31. $limit = min(100, max(1, (int) request()->input('limit', 20)));
  32. $result = $this->buildQuery($where)
  33. ->order('r.action_time', 'desc')
  34. ->order('r.id', 'desc')
  35. ->paginate([
  36. 'page' => $page,
  37. 'list_rows' => $limit,
  38. ])
  39. ->toArray();
  40. $result['data'] = array_map(fn (array $row) => $this->formatRecord($row), $result['data'] ?? []);
  41. return $result;
  42. }
  43. public function export(array $where): Response
  44. {
  45. $rows = $this->buildQuery($where)
  46. ->order('r.action_time', 'desc')
  47. ->order('r.id', 'desc')
  48. ->select()
  49. ->toArray();
  50. $data = [];
  51. foreach ($rows as $row) {
  52. $record = $this->formatRecord($row);
  53. $data[] = [
  54. 'id' => $record['id'],
  55. 'operator_name' => $this->excelSafe($record['operator_name']),
  56. 'operator_phone' => $this->excelSafe($record['operator_phone']),
  57. 'action_name' => $record['action_name'],
  58. 'action_time' => $record['action_time'],
  59. 'merchant' => $this->excelSafe($record['merchant']),
  60. 'merchant_phone' => $this->excelSafe($record['merchant_phone']),
  61. 'qr_code' => $this->excelSafe($record['qr_code']),
  62. 'device_sn' => $this->excelSafe($record['device_sn']),
  63. 'type_name' => $record['type_name'],
  64. ];
  65. }
  66. $fileName = '铺货记录_' . date('Ymd_His') . '.xlsx';
  67. $writer = new OpenSpoutWriter($fileName);
  68. $writer->setWidth([10, 20, 16, 12, 20, 24, 16, 22, 24, 18]);
  69. $writer->setHeader([
  70. '记录ID', '操作人', '操作人电话', '操作类型', '操作时间',
  71. '商户名称', '商户电话', '二维码/机器码', '设备SN码', '设备类型',
  72. ]);
  73. $writer->setData($data);
  74. return response()->download($writer->returnFile(), urlencode($fileName));
  75. }
  76. private function buildQuery(array $where)
  77. {
  78. $query = Db::table('sa_merchant_device_binding_record')->alias('r')
  79. ->leftJoin('sa_device d', 'd.id = r.device_id')
  80. ->leftJoin('sa_merchant m', 'm.id = r.merchant_id')
  81. ->leftJoin('sa_system_user u', 'u.id = r.operator_id')
  82. ->field(implode(',', [
  83. 'r.id', 'r.device_id', 'r.device_sn', 'r.depend_type', 'r.merchant_id',
  84. 'r.action_type', 'r.operator_id', 'r.action_time', 'r.create_time',
  85. 'd.goods_name', 'd.device_code', 'd.model', 'd.manage_agent_id',
  86. 'm.name AS merchant_name', 'm.phone AS merchant_phone',
  87. 'u.username AS operator_username', 'u.realname AS operator_realname',
  88. 'u.phone AS operator_phone',
  89. ]));
  90. $currentId = $this->currentAdminId();
  91. if ($currentId !== 1) {
  92. $query->where('d.manage_agent_id', $currentId);
  93. }
  94. $actionType = trim((string) ($where['action_type'] ?? ''));
  95. if (in_array($actionType, ['1', '2'], true)) {
  96. $query->where('r.action_type', (int) $actionType);
  97. }
  98. $merchant = trim((string) ($where['merchant'] ?? ''));
  99. if ($merchant !== '') {
  100. $query->whereLike('m.name', '%' . $merchant . '%');
  101. }
  102. $qrCode = trim((string) ($where['qr_code'] ?? ''));
  103. if ($qrCode !== '') {
  104. $query->whereLike('d.device_code', '%' . $qrCode . '%');
  105. }
  106. $deviceSn = trim((string) ($where['device_sn'] ?? ''));
  107. if ($deviceSn !== '') {
  108. $query->whereLike('r.device_sn', '%' . $deviceSn . '%');
  109. }
  110. if (($where['goods_type'] ?? '') !== '') {
  111. $query->where('r.depend_type', (int) $where['goods_type']);
  112. }
  113. return $query;
  114. }
  115. private function formatRecord(array $row): array
  116. {
  117. $type = (int) ($row['depend_type'] ?? 0);
  118. $actionType = (int) ($row['action_type'] ?? 0);
  119. $operatorId = (int) ($row['operator_id'] ?? 0);
  120. $operatorName = (string) (($row['operator_realname'] ?? '') ?: ($row['operator_username'] ?? ''));
  121. return [
  122. 'id' => (int) $row['id'],
  123. 'device_id' => (int) ($row['device_id'] ?? 0),
  124. 'device_sn' => (string) ($row['device_sn'] ?? ''),
  125. 'qr_code' => (string) (($row['device_code'] ?? '') ?: ($row['device_sn'] ?? '')),
  126. 'goods_name' => (string) ($row['goods_name'] ?? ''),
  127. 'goods_type' => $type,
  128. 'type_name' => self::TYPE_NAMES[$type] ?? '其他设备',
  129. 'action_type' => $actionType,
  130. 'action_name' => $actionType === 1 ? '铺货' : ($actionType === 2 ? '解绑' : '未知'),
  131. 'action_time' => (string) ($row['action_time'] ?? ''),
  132. 'merchant_id' => (int) ($row['merchant_id'] ?? 0),
  133. 'merchant' => (string) (($row['merchant_name'] ?? '') ?: '--'),
  134. 'merchant_phone' => (string) ($row['merchant_phone'] ?? ''),
  135. 'operator_id' => $operatorId,
  136. 'operator_name' => $operatorName !== '' ? $operatorName : '用户#' . $operatorId,
  137. 'operator_username' => (string) ($row['operator_username'] ?? ''),
  138. 'operator_phone' => (string) ($row['operator_phone'] ?? ''),
  139. ];
  140. }
  141. private function currentAdminId(): int
  142. {
  143. return (int) ($this->adminInfo['id'] ?? 0);
  144. }
  145. private function excelSafe(mixed $value): string
  146. {
  147. $value = (string) $value;
  148. return preg_match('/^[=+\-@]/u', $value) === 1 ? "'" . $value : $value;
  149. }
  150. }