Index.php 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use setasign\Fpdi\PdfReader\PdfReader;
  5. use think\Controller;
  6. use think\Db;
  7. use think\Request;
  8. /**
  9. * 达成大屏数据接口
  10. */
  11. class Index extends Controller{
  12. protected $noNeedLogin = ['*'];
  13. protected $noNeedRight = ['*'];
  14. /**首页*/
  15. public function index(){$this->success('成功');}
  16. public function OrderMes()
  17. {
  18. $endDate = '2025-11-01 00:00:00';
  19. // 查询工单基本信息
  20. $order = Db::name("工单_基本资料")
  21. ->where('落货日期', '<', $endDate)
  22. ->where('订单编号', 'DC2503287')
  23. // ->where('gd_statu', '同步中')
  24. ->whereNull('Mod_rq')
  25. ->select();
  26. $result = [];
  27. $processConfigs = [
  28. '2' => ['name' => '裁剪', 'needSerial' => false, 'needSnum' => false, 'sczl_jtbh' => 'CQ01'],
  29. '3' => ['name' => '车缝', 'needSerial' => true, 'needSnum' => false, 'sczl_jtbh' => 'CF01'],
  30. '4' => ['name' => '手工', 'needSerial' => true, 'needSnum' => true, 'sczl_jtbh' => 'HD01'],
  31. '5' => ['name' => '大烫', 'needSerial' => true, 'needSnum' => true, 'sczl_jtbh' => 'DT01'],
  32. '6' => ['name' => '总检', 'needSerial' => true, 'needSnum' => true, 'sczl_jtbh' => 'ZJ01'],
  33. '7' => ['name' => '包装', 'needSerial' => true, 'needSnum' => true, 'sczl_jtbh' => 'BZ01'],
  34. ];
  35. foreach ($order as $v) {
  36. // 批量查询印件资料
  37. $arr = Db::name("工单_印件资料")
  38. ->where('订单编号', $v['订单编号'])
  39. ->whereNull('Mod_rq')
  40. ->select();
  41. if (empty($arr)) {
  42. continue;
  43. }
  44. // 查询当前订单在产量计酬中已存在的工序
  45. $existingProcesses = Db::name('设备_产量计酬')
  46. ->where('订单编号', $v['订单编号'])
  47. ->field('DISTINCT 工序编号, 工序名称, sczl_jtbh')
  48. ->select();
  49. // 修改为处理所有预定义工序,无论是否已存在报工记录
  50. $processesToHandle = $processConfigs;
  51. // 如果已存在报工工序,更新工序名称和sczl_jtbh为实际值
  52. if (!empty($existingProcesses)) {
  53. foreach ($existingProcesses as $existingProcess) {
  54. $processCode = $existingProcess['工序编号'];
  55. if (isset($processesToHandle[$processCode])) {
  56. $processesToHandle[$processCode] = array_merge(
  57. $processesToHandle[$processCode],
  58. [
  59. 'name' => $existingProcess['工序名称'],
  60. 'sczl_jtbh' => $existingProcess['sczl_jtbh'] ?? $processesToHandle[$processCode]['sczl_jtbh']
  61. ]
  62. );
  63. }
  64. }
  65. }
  66. if (empty($processesToHandle)) {
  67. continue;
  68. }
  69. // 为每个工序处理数据
  70. foreach ($processesToHandle as $processCode => $processConfig) {
  71. $processName = $processConfig['name'];
  72. $needSerial = $processConfig['needSerial'];
  73. $needSnum = $processConfig['needSnum'];
  74. $sczl_jtbh = $processConfig['sczl_jtbh'];
  75. $operator = $processName . '01组长';
  76. $operators = $processName . '01组';
  77. $subOrderCounters = [];
  78. foreach ($arr as $printItem) {
  79. $subOrderNo = $printItem['子订单编号'];
  80. // 查询当前子订单编号在当前工序中已存在的尺码记录
  81. $existingRecords = Db::name('设备_产量计酬')
  82. ->where('子订单编号', $subOrderNo)
  83. ->where('工序编号', $processCode)
  84. ->where('工序名称', $processName)
  85. ->field('尺码,serial_num')
  86. ->select();
  87. // 将已存在的尺码记录转换为数组,方便检查
  88. $existingSizes = [];
  89. $maxSerialNum = 0;
  90. foreach ($existingRecords as $record) {
  91. $existingSizes[] = $record['尺码'];
  92. // 记录最大的serial_num
  93. if ($record['serial_num'] > $maxSerialNum) {
  94. $maxSerialNum = $record['serial_num'];
  95. }
  96. }
  97. // 初始化该子订单编号的计数器
  98. if (!isset($subOrderCounters[$subOrderNo])) {
  99. // 如果已存在记录,从最大serial_num+1开始,否则从1开始
  100. $subOrderCounters[$subOrderNo] = $maxSerialNum > 0 ? $maxSerialNum + 1 : 1;
  101. }
  102. // 提取尺码和数量信息
  103. for ($i = 1; $i <= 14; $i++) {
  104. $sizeField = "cm{$i}";
  105. $quantityField = "cmsl{$i}";
  106. // 检查尺码和数量是否有效
  107. $sizeValue = trim($printItem[$sizeField] ?? '');
  108. $quantityValue = $printItem[$quantityField] ?? 0;
  109. // 如果尺码不为空且数量大于0
  110. if (!empty($sizeValue) && $quantityValue > 0) {
  111. // 检查是否已存在相同的尺码记录
  112. if (in_array($sizeValue, $existingSizes)) {
  113. // 已存在,跳过插入
  114. continue;
  115. }
  116. // 构建基础数据
  117. $data = [
  118. '订单编号' => $printItem['订单编号'] ?? '',
  119. '子订单编号' => $subOrderNo ?? '',
  120. '款号' => $v['生产款号'] ?? '',
  121. '工序编号' => $processCode ?? '',
  122. '工序名称' => $processName ?? '',
  123. '尺码' => $sizeValue,
  124. '数量' => $quantityValue,
  125. 'sczl_jtbh' => $sczl_jtbh,
  126. 'sczl_rq' => '2025-11-04 00:00:00',
  127. 'sczl_bh' => $operators ?? '',
  128. '尾包' => 0,
  129. 'ci_num' => 0,
  130. 's_num' => '', // 默认值为空
  131. 'sys_id' => $operator,
  132. 'sys_rq' => date('Y-m-d H:i:s'),
  133. 'serial' => '', // 默认值为空
  134. 'serial_num' => 0, // 默认值为0
  135. ];
  136. // 根据工序配置更新字段
  137. if ($needSerial) {
  138. // 只有裁剪不需要serial,其他工序都需要
  139. $serial = str_pad($subOrderCounters[$subOrderNo], 3, '0', STR_PAD_LEFT);
  140. $data['serial'] = $serial;
  141. $data['serial_num'] = $subOrderCounters[$subOrderNo];
  142. }
  143. if ($needSnum) {
  144. $data['s_num'] = $quantityValue;
  145. }
  146. $result[] = $data;
  147. // 计数器加1(只有需要serial的工序才计数)
  148. if ($needSerial) {
  149. $subOrderCounters[$subOrderNo]++;
  150. }
  151. }
  152. }
  153. }
  154. }
  155. }
  156. // 检查是否有数据需要插入
  157. if (empty($result)) {
  158. return true; // 没有数据需要插入,返回成功
  159. }
  160. echo "<pre>";
  161. print_r($result);
  162. echo "<pre>";
  163. $sql = Db::name('设备_产量计酬')->fetchSql(true)->insertAll($result);
  164. $insertResult = \db()->query($sql);
  165. echo "成功插入 " . count($result) . " 条记录";
  166. }
  167. /**
  168. * 同步总检报工到入仓汇总表
  169. * 产量计酬中已存在报工,未入仓数据
  170. */
  171. public function GetCang()
  172. {
  173. $startDate = '2025-11-01 00:00:00';
  174. $endDate = date('Y-m-d H:i:s');
  175. // 查询未入仓的总检记录
  176. $res = Db::name('设备_产量计酬')->alias('c')
  177. ->join('工单_基本资料 j', 'c.订单编号 = j.订单编号', 'left')
  178. ->field([
  179. 'c.sys_id',
  180. 'c.sys_rq',
  181. 'c.订单编号',
  182. 'c.子订单编号',
  183. 'c.数量',
  184. 'c.尾包',
  185. 'c.尺码',
  186. 'j.客户编号'
  187. ])
  188. ->where('c.工序名称', '总检')
  189. ->whereBetween('c.sys_rq', [$startDate, $endDate])
  190. ->select();
  191. if (empty($res)) {
  192. $this->success('无数据需要插入');
  193. }
  194. // ▶ 查询成品入仓中已有的记录(用 sys_rq + cm + sl 去重)
  195. $existList = Db::name('成品入仓')
  196. ->field('sys_rq, cm, sl')
  197. ->whereBetween('sys_rq', [$startDate, $endDate])
  198. ->select();
  199. //转换为键值对,用于快速匹配
  200. $existKeys = [];
  201. foreach ($existList as $item) {
  202. $key = $item['sys_rq'] . '_' . $item['cm'] . '_' . $item['sl'];
  203. $existKeys[$key] = true;
  204. }
  205. // 构建待插入数据(过滤重复)
  206. $insertData = [];
  207. foreach ($res as $row) {
  208. $checkKey = $row['sys_rq'] . '_' . $row['尺码'] . '_' . $row['数量'];
  209. if (isset($existKeys[$checkKey])) {
  210. continue; // 已存在,跳过
  211. }
  212. $insertData[] = [
  213. 'sys_id' => $row['sys_id'],
  214. 'sys_rq' => $row['sys_rq'],
  215. 'order' => $row['订单编号'],
  216. 'order_id' => $row['子订单编号'],
  217. 'sl' => $row['数量'],
  218. 'cm' => $row['尺码'],
  219. 'wb' => $row['尾包'],
  220. 'customer' => $row['客户编号']
  221. ];
  222. }
  223. if (empty($insertData)) {
  224. $this->success('无新增记录需要插入');
  225. }
  226. $result = Db::name('成品入仓')->insertAll($insertData);
  227. if ($result) {
  228. $this->success("插入成功,共插入 {$result} 条记录");
  229. } else {
  230. $this->error('插入失败');
  231. }
  232. }
  233. /**第一屏*/
  234. //年度承接产量
  235. public function thisyear(){
  236. $date = date("Y");
  237. // 返回 JSON 格式数据
  238. return json([
  239. "status" => 0,
  240. "msg" => "",
  241. "data" => $date.'年度承接产量',
  242. ]);
  243. }
  244. public function lastyear(){
  245. $date = date("Y") - 1;
  246. // 返回 JSON 格式数据
  247. return json([
  248. "status" => 0,
  249. "msg" => "",
  250. "data" => $date.'年度承接产量',
  251. ]);
  252. }
  253. //获取近三年年份
  254. public function ymd_api(){
  255. $data = [
  256. ["name" => " ", "value" => strval(date('Y'))], // 将年份转换为字符串
  257. ["name" => " ", "value" => strval(date('Y') - 1)], // 将年份转换为字符串
  258. ["name" => " ", "value" => strval(date('Y') - 2)], // 将年份转换为字符串
  259. ];
  260. // 返回 JSON 格式数据
  261. return json([
  262. "status" => 0,
  263. "msg" => "",
  264. "data" => $data,
  265. ]);
  266. }
  267. /**
  268. *去年的年度承接产量【接口】
  269. *统计去年订单个数,订单数量,包装完工数量,完成率。
  270. */
  271. public function Lastcontractedoutput_api(){
  272. // 获取今年的年份
  273. $last_year = date("Y") -1;
  274. // 查询条件:Mod_rq为null且年份为今年的记录数量
  275. $count = \db('工单_基本资料')
  276. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  277. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  278. ->count();
  279. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  280. $sum = \db('工单_基本资料')
  281. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  282. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  283. ->whereNull('Mod_rq')
  284. ->select();
  285. $total_sum = 0;
  286. $s_num_total = 0;
  287. $ratio = 0;
  288. if (!empty($sum)) {
  289. foreach ($sum as $value) {
  290. $total_sum = $value['total_sum']; // 使用别名获取结果
  291. if ($total_sum) {
  292. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  293. $s_num_result = \db('设备_产量计酬')
  294. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  295. ->where('工序编号', 7)
  296. ->whereNull('mod_rq')
  297. ->where('sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  298. ->select();
  299. if (!empty($s_num_result)) {
  300. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  301. // 计算比例并四舍五入保留两位小数
  302. if ($total_sum != 0) { // 避免除数为0
  303. $ratio = round(($s_num_total / $total_sum) * 100) . '%';
  304. }
  305. }
  306. }
  307. }
  308. }
  309. // 构建返回数据
  310. // $data = [
  311. // ["name" => "总订单数", "value" => $count],
  312. // ["name" => "承接大货数", "value" => $total_sum],
  313. // ["name" => "完工数量", "value" => $s_num_total],
  314. // ["name" => "完成率", "value" => $ratio],
  315. // ];
  316. $data = [
  317. ["name" => " ", "value" => $count],
  318. ["name" => " ", "value" => $total_sum],
  319. ["name" => " ", "value" => $s_num_total],
  320. // ["name" => " ", "value" => $ratio],
  321. ];
  322. // 返回 JSON 格式数据
  323. return json([
  324. "status" => 0,
  325. "msg" => "",
  326. "data" => $data,
  327. ]);
  328. }
  329. /**
  330. *当年的年度承接产量【接口】
  331. *统计当年订单个数,订单数量,包装完工数量,完成率。
  332. */
  333. public function Annualcontractedoutput_api(){
  334. // 获取今年的年份
  335. $year = date("Y");
  336. // 查询条件:Mod_rq为null且年份为今年的记录数量
  337. $count = \db('工单_基本资料')
  338. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  339. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  340. ->count();
  341. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  342. $sum = \db('工单_基本资料')
  343. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  344. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  345. ->whereNull('Mod_rq')
  346. ->select();
  347. $total_sum = 0;
  348. $s_num_total = 0;
  349. $ratio = 0;
  350. if (!empty($sum)) {
  351. foreach ($sum as $value) {
  352. $total_sum = $value['total_sum']; // 使用别名获取结果
  353. if ($total_sum) {
  354. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  355. $s_num_result = \db('设备_产量计酬')
  356. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  357. ->where('工序编号', 7)
  358. ->whereNull('mod_rq')
  359. ->where('sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  360. ->select();
  361. if (!empty($s_num_result)) {
  362. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  363. // 计算比例并四舍五入保留两位小数
  364. if ($total_sum != 0) { // 避免除数为0
  365. $ratio = round(($s_num_total / $total_sum) * 100) . '%';
  366. }
  367. }
  368. }
  369. }
  370. }
  371. // 构建返回数据
  372. $data = [
  373. ["name" => " ", "value" => $count],
  374. ["name" => " ", "value" => $total_sum],
  375. ["name" => " ", "value" => $s_num_total],
  376. // ["name" => " ", "value" => $ratio],
  377. ];
  378. // 返回 JSON 格式数据
  379. return json([
  380. "status" => 0,
  381. "msg" => "",
  382. "data" => $data,
  383. ]);
  384. }
  385. public function dcompletion_api(){
  386. // 获取今年的年份
  387. $year = date("Y");
  388. // 查询条件:Mod_rq为null且年份为今年的记录数量
  389. $count = \db('工单_基本资料')
  390. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  391. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  392. ->count();
  393. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  394. $sum = \db('工单_基本资料')
  395. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  396. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  397. ->whereNull('Mod_rq')
  398. ->select();
  399. $total_sum = 0;
  400. $s_num_total = 0;
  401. $ratio = 0;
  402. if (!empty($sum)) {
  403. foreach ($sum as $value) {
  404. $total_sum = $value['total_sum']; // 使用别名获取结果
  405. if ($total_sum) {
  406. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  407. $s_num_result = \db('设备_产量计酬')
  408. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  409. ->where('工序编号', 7)
  410. ->whereNull('mod_rq')
  411. ->where('sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  412. ->select();
  413. if (!empty($s_num_result)) {
  414. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  415. // 计算比例并四舍五入取整数
  416. if ($total_sum != 0) { // 避免除数为0
  417. $ratio = ($s_num_total / $total_sum) * 100; // 四舍五入并取整数
  418. }
  419. }
  420. }
  421. }
  422. }
  423. // 返回 JSON 格式数据
  424. return json([
  425. "status" => 0,
  426. "hitSugarSelf" => true,
  427. "msg" => "",
  428. "data" => round($ratio), // 返回计算后的整数完成率
  429. ]);
  430. }
  431. public function qcompletion_api(){
  432. // 获取今年的年份
  433. $last_year = date("Y") - 1;
  434. // 查询条件:Mod_rq为null且年份为去年的记录数量
  435. $count = \db('工单_基本资料')
  436. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  437. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  438. ->count();
  439. // 查询条件:Mod_rq为null且年份为去年的订单数量字段的总和
  440. $sum = \db('工单_基本资料')
  441. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  442. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  443. ->whereNull('Mod_rq')
  444. ->select();
  445. $total_sum = 0;
  446. $s_num_total = 0;
  447. $ratio = 0;
  448. if (!empty($sum)) {
  449. foreach ($sum as $value) {
  450. $total_sum = $value['total_sum']; // 使用别名获取结果
  451. if ($total_sum) {
  452. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为去年的s_num总和
  453. $s_num_result = \db('设备_产量计酬')
  454. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  455. ->where('工序编号', 7)
  456. ->whereNull('mod_rq')
  457. ->where('sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  458. ->select();
  459. if (!empty($s_num_result)) {
  460. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  461. // 计算比例并四舍五入保留两位小数
  462. if ($total_sum != 0) { // 避免除数为0
  463. $ratio = round(($s_num_total / $total_sum) * 100, 2); // 计算并保留两位小数
  464. }
  465. }
  466. }
  467. }
  468. }
  469. // 返回 JSON 格式数据
  470. return json([
  471. "status" => 0,
  472. "hitSugarSelf" => true,
  473. "msg" => "",
  474. "data" => $ratio,
  475. ]);
  476. }
  477. /**
  478. * 年度订单个数【接口】
  479. * 统计近三年的订单条数
  480. */
  481. public function orderlist_api(){
  482. // 获取当前日期的年份
  483. $currentYear = date('Y');
  484. // 获取三年前的年份
  485. $threeYearsAgo = $currentYear - 2;
  486. // 构建查询的年份范围
  487. $years = [$threeYearsAgo, $threeYearsAgo + 1, $currentYear];
  488. // 查询订单的年份和数量
  489. $orderData = db('工单_基本资料')
  490. ->field('YEAR(Sys_rq) AS year, COUNT(*) AS order_count')
  491. ->whereNull('Mod_rq')
  492. ->where('YEAR(Sys_rq)', 'between', [$threeYearsAgo, $currentYear])
  493. ->group('YEAR(Sys_rq)')
  494. ->select();
  495. // 将查询结果按年份分组存储
  496. $orderCountByYear = [];
  497. foreach ($orderData as $data) {
  498. $orderCountByYear[$data['year']] = $data['order_count'];
  499. }
  500. // 对于没有订单的年份,默认值为0
  501. foreach ($years as $year) {
  502. if (!isset($orderCountByYear[$year])) {
  503. $orderCountByYear[$year] = 0; // 如果该年没有数据,则设置为0
  504. }
  505. }
  506. // 准备 API 格式的响应数据
  507. $response = [
  508. 'status' => 0,
  509. 'msg' => '',
  510. 'data' => [
  511. 'categories' => $years, // 输出年份数组
  512. 'series' => [
  513. [
  514. 'name' => '年度订单个数',
  515. 'data' => array_map(function($year) use ($orderCountByYear) {
  516. return $orderCountByYear[$year];
  517. }, $years), // 根据年份返回对应的订单数量
  518. ]
  519. ]
  520. ]
  521. ];
  522. return json($response);
  523. }
  524. /**
  525. * 年度计划数量【接口】
  526. * 统计近三年的订单总数量合计
  527. */
  528. public function ordersumlist_api(){
  529. // 获取当前日期的年份
  530. $currentYear = date('Y');
  531. // 获取三年前的年份
  532. $threeYearsAgo = $currentYear - 2;
  533. // 构建查询的年份范围
  534. $years = [$threeYearsAgo, $threeYearsAgo + 1, $currentYear];
  535. // 查询订单的年份和数量的合计
  536. $orderData = db('工单_基本资料')
  537. ->field('YEAR(Sys_rq) AS year, SUM(订单数量) AS total_quantity') // 这里改为求“数量”的合计
  538. ->whereNull('Mod_rq')
  539. ->where('YEAR(Sys_rq)', 'between', [$threeYearsAgo, $currentYear])
  540. ->group('YEAR(Sys_rq)')
  541. ->select();
  542. // 将查询结果按年份分组存储
  543. $orderSumByYear = [];
  544. foreach ($orderData as $data) {
  545. $orderSumByYear[$data['year']] = $data['total_quantity'];
  546. }
  547. // 对于没有订单的年份,默认值为0
  548. foreach ($years as $year) {
  549. if (!isset($orderSumByYear[$year])) {
  550. $orderSumByYear[$year] = 0; // 如果该年没有数据,则设置为0
  551. }
  552. }
  553. // 准备 API 格式的响应数据
  554. $response = [
  555. 'status' => 0,
  556. 'msg' => '',
  557. 'data' => [
  558. 'categories' => $years, // 输出年份数组
  559. 'series' => [
  560. [
  561. 'name' => '年度计划数量',
  562. 'data' => array_map(function($year) use ($orderSumByYear) {
  563. return $orderSumByYear[$year];
  564. }, $years), // 根据年份返回对应的订单数量合计
  565. ]
  566. ]
  567. ]
  568. ];
  569. return json($response);
  570. }
  571. /**
  572. * 年度完工数量【接口】
  573. * 统计每个月完成包装的数量
  574. */
  575. public function Annualcompletionrate_api() {
  576. // 获取当前年份和上一年份
  577. $currentYear = date('Y');
  578. $lastYear = $currentYear - 1;
  579. // 获取当前年份和去年的数据
  580. $orderData = db('设备_产量计酬')
  581. ->field("DATE_FORMAT(sys_rq, '%Y-%m') AS sys_rq, SUM(s_num) AS 数量")
  582. ->where('工序名称', '包装')
  583. ->where('mod_rq',null)
  584. ->group('DATE_FORMAT(sys_rq, "%Y-%m")') // 按年月分组
  585. ->select();
  586. // 手动过滤数据,只保留当前年和去年的数据
  587. $filteredData = array_filter($orderData, function ($data) use ($currentYear, $lastYear) {
  588. $year = explode('-', $data['sys_rq'])[0]; // 提取年份
  589. return $year == $currentYear || $year == $lastYear;
  590. });
  591. // 初始化月份和年份数组
  592. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  593. $responseData = [
  594. 'categories' => $months, // 月份数组
  595. 'series' => [
  596. ['name' => $lastYear . '年', 'data' => array_fill(0, 12, 0)], // 初始化为0
  597. ['name' => $currentYear . '年', 'data' => array_fill(0, 12, 0)] // 初始化为0
  598. ]
  599. ];
  600. // 将查询结果按年份和月份存储
  601. foreach ($filteredData as $data) {
  602. // 提取年和月
  603. $yearMonth = explode('-', $data['sys_rq']);
  604. $year = $yearMonth[0];
  605. $month = (int) $yearMonth[1] - 1; // 因为数组从0开始,所以要减去1
  606. // 根据年份更新对应的月份数据
  607. if ($year == $lastYear) {
  608. $responseData['series'][0]['data'][$month] = $data['数量'];
  609. } elseif ($year == $currentYear) {
  610. $responseData['series'][1]['data'][$month] = $data['数量'];
  611. }
  612. }
  613. // 构造最终的响应数据
  614. $response = [
  615. 'status' => 0,
  616. 'msg' => '',
  617. 'data' => $responseData
  618. ];
  619. return json($response);
  620. }
  621. /**
  622. * 年度完成率【接口】
  623. */
  624. public function Annualcompletionraterate_api() {
  625. // 获取当前年份和上一年
  626. $currentYear = date('Y');
  627. $lastYear = $currentYear - 1;
  628. // 初始化月份数组
  629. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  630. // 初始化返回数据
  631. $responseData = [
  632. 'categories' => $months, // 月份
  633. 'series' => [
  634. ['name' => $lastYear . '年完成率', 'data' => array_fill(0, 12, 0)], // 上一年完成率数据
  635. ['name' => $currentYear . '年完成率', 'data' => array_fill(0, 12, 0)], // 当前年完成率数据
  636. ]
  637. ];
  638. // 1. 获取工单基本资料表每月的订单数量(近两年)
  639. $orderData = db('工单_基本资料')
  640. ->field("DATE_FORMAT(出库日期, '%Y-%m') AS 订单日期, SUM(订单数量) AS 订单数量")
  641. ->where('Mod_rq', null) // 筛选 Mod_rq 为 null
  642. ->group('DATE_FORMAT(出库日期, "%Y-%m")') // 按年月分组
  643. ->select();
  644. // 2. 获取设备产量计酬表每月的包装数量(s_num)(近两年)
  645. $productionData = db('设备_产量计酬')
  646. ->field("DATE_FORMAT(sys_rq, '%Y-%m') AS 报工日期, SUM(s_num) AS 完工数量")
  647. ->where('工序名称', '包装') // 筛选工序名称为包装
  648. ->where('mod_rq', null) // 筛选 mod_rq 为 null
  649. ->group('DATE_FORMAT(sys_rq, "%Y-%m")') // 按年月分组
  650. ->select();
  651. // 将查询结果转换为数组,方便后续计算
  652. $orderDataMap = [];
  653. foreach ($orderData as $data) {
  654. $orderDataMap[$data['订单日期']] = $data['订单数量'];
  655. }
  656. $productionDataMap = [];
  657. foreach ($productionData as $data) {
  658. $productionDataMap[$data['报工日期']] = $data['完工数量'];
  659. }
  660. // 3. 计算每月的完成率并四舍五入
  661. foreach ($months as $month) {
  662. // 拼接当前月和上一年的年月
  663. $currentMonth = $currentYear . '-' . $month;
  664. $lastMonth = $lastYear . '-' . $month;
  665. // 获取当前月和上一年的订单数量和完工数量
  666. $totalOrdersCurrentYear = isset($orderDataMap[$currentMonth]) ? $orderDataMap[$currentMonth] : 0;
  667. $totalSNumCurrentYear = isset($productionDataMap[$currentMonth]) ? $productionDataMap[$currentMonth] : 0;
  668. $totalOrdersLastYear = isset($orderDataMap[$lastMonth]) ? $orderDataMap[$lastMonth] : 0;
  669. $totalSNumLastYear = isset($productionDataMap[$lastMonth]) ? $productionDataMap[$lastMonth] : 0;
  670. // 计算完成率,避免除以零,并四舍五入
  671. // $completionRateCurrentYear = $totalOrdersCurrentYear > 0 ? round(($totalSNumCurrentYear / $totalOrdersCurrentYear) * 100) : 0;
  672. // $completionRateLastYear = $totalOrdersLastYear > 0 ? round(($totalSNumLastYear / $totalOrdersLastYear) * 100) : 0;
  673. // 计算完成率,避免除以零,并限制最大值为 100%
  674. $completionRateCurrentYear = $totalOrdersCurrentYear > 0 ? min(round(($totalSNumCurrentYear / $totalOrdersCurrentYear) * 100), 100) : 0;
  675. $completionRateLastYear = $totalOrdersLastYear > 0 ? min(round(($totalSNumLastYear / $totalOrdersLastYear) * 100), 100) : 0;
  676. // 存储每个月的完成率
  677. $responseData['series'][0]['data'][$month - 1] = $completionRateLastYear;
  678. $responseData['series'][1]['data'][$month - 1] = $completionRateCurrentYear;
  679. }
  680. // 返回响应数据
  681. $response = [
  682. 'status' => 0,
  683. 'msg' => '',
  684. 'data' => $responseData
  685. ];
  686. return json($response);
  687. }
  688. /**
  689. * 年度客户订单数量汇总【接口】
  690. */
  691. public function getOrderSummaryKhStyle()
  692. {
  693. // 获取当前年份
  694. $last_year = date("Y");
  695. // 查询工单_基本资料表,按客户编号分组并计算订单数量的总和
  696. $result = \db('工单_基本资料')
  697. ->field('客户编号, SUM(订单数量) as 总订单数量') // 按客户编号分组并计算订单数量的总和
  698. ->where('Sys_rq', '>=', "$last_year-01-01 00:00:00") // 用 >= 和 <= 来代替 between,提高查询效率
  699. ->where('Sys_rq', '<=', "$last_year-12-31 23:59:59")
  700. ->whereNull('Mod_rq') // 确保 'Mod_rq' 为 null
  701. ->group('客户编号') // 按客户编号分组
  702. ->order('总订单数量 desc') // 按总订单数量降序排序
  703. ->cache(true, 60) // 添加缓存来减少数据库查询,60秒缓存一次
  704. ->select();
  705. // 如果没有数据,返回空结果
  706. if (empty($result)) {
  707. return json([
  708. 'status' => 0,
  709. 'msg' => '没有数据',
  710. 'data' => [
  711. 'columns' => [],
  712. 'rows' => []
  713. ]
  714. ]);
  715. }
  716. // 定义列格式
  717. $columns = [
  718. ['name' => '客户编号', 'id' => 'khbh', 'width' => '30', 'autoWrap' => "true", 'textAlign' => 'left'],
  719. ['name' => '总订单数量', 'id' => '总订单数量', 'width' => '30', 'autoWrap' => "true", 'textAlign' => 'left']
  720. ];
  721. // 格式化结果
  722. $rows = array_map(function ($item) {
  723. return [
  724. 'khbh' => $item['客户编号'],
  725. '总订单数量' => $item['总订单数量']
  726. ];
  727. }, $result);
  728. // 返回 JSON 格式的结果
  729. return json([
  730. 'status' => 0,
  731. 'msg' => '',
  732. 'data' => [
  733. 'columns' => $columns,
  734. 'rows' => $rows
  735. ]
  736. ]);
  737. }
  738. /**
  739. * 年度款式上下装数量汇总【接口】
  740. */
  741. public function jacket() {
  742. // 获取当前年份
  743. $last_year = date("Y");
  744. // 查询数据库,统计款式订单数量
  745. $row = \db('工单_基本资料')
  746. ->field('款式, COALESCE(SUM(订单数量), 0) as 总订单数量') // 避免 NULL 值
  747. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  748. ->whereNull('Mod_rq')
  749. ->group('款式') // 按款式分组
  750. ->order('总订单数量 desc') // 订单数量降序排列
  751. ->limit(20) // 取前 20 个热销款式
  752. ->select();
  753. // 定义表格列
  754. $result['columns'] = [
  755. ['name' => '分类', 'id' => 'fl', 'width' => '20', 'textAlign' => 'left'],
  756. ['name' => '款式', 'id' => 'ks', 'width' => '35', 'textAlign' => 'left'],
  757. ['name' => '总订单数量', 'id' => 'zds', 'width' => '25', 'textAlign' => 'left'],
  758. ];
  759. // 如果查询结果为空,返回空数据
  760. if (empty($row)) {
  761. return json([
  762. 'status' => 0,
  763. 'msg' => '没有数据',
  764. 'data' => $result
  765. ]);
  766. }
  767. // 分类关键词
  768. $upperKeywords = ['衣', '装', '夹', '衫', '甲', '外套']; // 上装
  769. $lowerKeywords = ['裤', '裙']; // 下装
  770. // 处理查询结果,添加分类信息
  771. foreach ($row as $k => $v) {
  772. $style = $v['款式'];
  773. $isUpper = $isLower = false; // 是否属于上装/下装
  774. // 判断款式分类
  775. if (preg_match('/(' . implode('|', $upperKeywords) . ')/u', $style)) {
  776. $isUpper = true;
  777. }
  778. if (preg_match('/(' . implode('|', $lowerKeywords) . ')/u', $style)) {
  779. $isLower = true;
  780. }
  781. // 归类
  782. if (strpos($style, '+') !== false) {
  783. $category = '套装';
  784. } elseif ($isUpper && $isLower) {
  785. $category = '全身';
  786. } elseif ($isUpper) {
  787. $category = '上装';
  788. } elseif ($isLower) {
  789. $category = '下装';
  790. } else {
  791. $category = '其他';
  792. }
  793. // 组装 `rows` 数据
  794. $result['rows'][$k]['ks'] = $style;
  795. $result['rows'][$k]['zds'] = $v['总订单数量'];
  796. $result['rows'][$k]['fl'] = $category;
  797. }
  798. $res['status'] = 0;
  799. $res['msg'] = '';
  800. $res['data'] = $result;
  801. return json($res);
  802. }
  803. /**第二屏*/
  804. /**
  805. * 每月各个小组生产报工走势【接口】
  806. * 统计每个工序小组的报工数据
  807. */
  808. public function Monthlyoutput_api() {
  809. $req = $this->request->param();
  810. if (isset($req['jtbh']) && !empty($req['jtbh'])){
  811. $jtbh = $req['jtbh'];
  812. } else {
  813. $this->error('参数错误');
  814. }
  815. $currentYear = date('Y'); // 当前年份
  816. $lastYear = $currentYear - 1; // 去年年份
  817. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  818. $wheres['sczl_jtbh'] = ['like', '%' . $jtbh . '%']; // 查询上个月的数据
  819. // 查询数据库,按年份、月份和 jtbh 分组,获取近两年的数据
  820. $queryResult = \db('设备_产量计酬')
  821. ->field('
  822. YEAR(sys_rq) as year,
  823. DATE_FORMAT(sys_rq, "%m") as month,
  824. SUM(
  825. CASE
  826. WHEN 工序名称 IN ("裁剪", "车缝") THEN 数量
  827. ELSE s_num
  828. END
  829. ) as 报工数量,
  830. 工序名称,
  831. sczl_jtbh as jtbh
  832. ')
  833. ->where($wheres)
  834. ->whereNull('mod_rq')
  835. ->where('sys_rq', 'between', ["$lastYear-01-01 00:00:00", "$currentYear-12-31 23:59:59"])
  836. ->group('YEAR(sys_rq), DATE_FORMAT(sys_rq, "%m"), sczl_jtbh')
  837. ->select();
  838. // 初始化结果数组,分开存储2024年和2025年的数据
  839. $result = [
  840. "categories" => $months, // 月份
  841. "series" => [
  842. ["name" => "{$lastYear}年", "data" => array_fill(0, 12, 0)], // 2024年数据,初始化为0
  843. ["name" => "{$currentYear}年", "data" => array_fill(0, 12, 0)] // 2025年数据,初始化为0
  844. ]
  845. ];
  846. // 按年份分组数据
  847. $dataByYear = [
  848. $lastYear => array_fill(0, 12, 0), // 2024年的每月数据,初始化为0
  849. $currentYear => array_fill(0, 12, 0) // 2025年的每月数据,初始化为0
  850. ];
  851. // 将查询结果填充到对应的年份和月份
  852. foreach ($queryResult as $row) {
  853. $year = $row['year'];
  854. $month = (int)$row['month'] - 1; // 月份从0开始
  855. $sNumTotal = $row['报工数量'];
  856. // 合并相同年份和月份的数据
  857. if (isset($dataByYear[$year])) {
  858. $dataByYear[$year][$month] += $sNumTotal; // 这里是累加相同年月的数据
  859. }
  860. }
  861. // 将数据填充到结果中的 series 中
  862. foreach ($dataByYear as $year => $monthData) {
  863. foreach ($result['series'] as &$series) {
  864. if ($series['name'] == "{$year}年") {
  865. $series['data'] = $monthData;
  866. break;
  867. }
  868. }
  869. }
  870. // 返回结果
  871. return json([
  872. "status" => 0,
  873. "msg" => "",
  874. "data" => $result,
  875. ]);
  876. }
  877. /**第三屏*/
  878. /**
  879. * 计划中
  880. * */
  881. public function plan_api(){
  882. // 获取今年的年份
  883. $last_year = date("Y");
  884. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  885. $data = \db('工单_基本资料')
  886. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  887. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  888. ->whereNull('Mod_rq')
  889. ->group('gd_statu') // 按订单状态分组
  890. ->select();
  891. // 如果查询结果为空,设置一个默认值
  892. if (empty($data)) {
  893. $formattedData[] = [
  894. 'name' => ' ',
  895. 'value' => 0
  896. ];
  897. } else {
  898. // 否则根据查询结果格式化数据
  899. $formattedData[] = [
  900. 'name' => ' ',
  901. 'value' => isset($data[0]['订单数量']) ? $data[0]['订单数量'] : 0
  902. ];
  903. }
  904. // 返回 JSON 格式数据
  905. return json([
  906. "status" => 0,
  907. "msg" => "",
  908. "data" => $formattedData,
  909. ]);
  910. }
  911. /**
  912. * 生产中
  913. * */
  914. public function Production_api(){
  915. // 获取今年的年份
  916. $last_year = date("Y");
  917. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  918. $data = \db('工单_基本资料')
  919. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  920. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  921. ->whereNull('Mod_rq')
  922. ->group('gd_statu') // 按订单状态分组
  923. ->select();
  924. // 如果查询结果为空,设置一个默认值
  925. if (empty($data)) {
  926. $formattedData[] = [
  927. 'name' => ' ',
  928. 'value' => 0
  929. ];
  930. } else {
  931. // 否则根据查询结果格式化数据
  932. $formattedData[] = [
  933. 'name' => ' ',
  934. 'value' => isset($data[1]['订单数量']) ? $data[1]['订单数量'] : 0
  935. ];
  936. }
  937. // 返回 JSON 格式数据
  938. return json([
  939. "status" => 0,
  940. "msg" => "",
  941. "data" => $formattedData,
  942. ]);
  943. }
  944. /**
  945. * 已完工
  946. * */
  947. public function Completed_api(){
  948. // 获取今年的年份
  949. $last_year = date("Y");
  950. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  951. $data = \db('工单_基本资料')
  952. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  953. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  954. ->whereNull('Mod_rq')
  955. ->group('gd_statu') // 按订单状态分组
  956. ->select();
  957. // 如果查询结果为空,设置一个默认值
  958. if (empty($data)) {
  959. $formattedData[] = [
  960. 'name' => ' ',
  961. 'value' => 0
  962. ];
  963. } else {
  964. // 否则根据查询结果格式化数据
  965. $formattedData[] = [
  966. 'name' => ' ',
  967. 'value' => isset($data[2]['订单数量']) ? $data[2]['订单数量'] : 0
  968. ];
  969. }
  970. // 返回 JSON 格式数据
  971. return json([
  972. "status" => 0,
  973. "msg" => "",
  974. "data" => $formattedData,
  975. ]);
  976. }
  977. /**
  978. * 统计当前小组正在生产某个工单
  979. * */
  980. public function group_api() {
  981. $last_year = date("Y");
  982. // 自定义小组排序规则
  983. $group_order = [
  984. '裁剪01组', '裁剪02组', '裁剪03组', '裁剪04组',
  985. '车缝01组', '车缝02组', '车缝03组', '车缝04组', '车缝05组', '车缝06组', '车缝07组', '车缝08组', '车缝09组', '车缝10组', '车缝11组', '车缝12组',
  986. '车缝13组', '车缝14组', '车缝15组',
  987. '大办组', '美英组', '小芬组',
  988. '手工01组', '手工02组',
  989. '总检01组', '总检02组',
  990. '大烫01组',
  991. '包装01组', '包装02组'
  992. ];
  993. // 查询条件:按小组和订单编号分组,取最新一条记录
  994. $data = \db('设备_产量计酬')->alias('c')
  995. ->join('工单_基本资料 j', 'j.订单编号 = c.订单编号', 'LEFT')
  996. ->field([
  997. 'c.订单编号',
  998. 'j.客户编号',
  999. 'c.款号',
  1000. 'c.尺码',
  1001. Db::raw('CASE
  1002. WHEN c.工序名称 IN ("裁剪", "车缝") THEN c.数量
  1003. ELSE c.s_num
  1004. END AS 数量'),
  1005. 'c.工序名称',
  1006. 'c.sczl_bh', // 小组名称
  1007. 'c.sys_rq' // 时间字段
  1008. ])
  1009. ->group('c.订单编号, c.sczl_bh') // 按订单编号和小组分组,确保每个订单编号只出现一次
  1010. ->order('c.sys_rq DESC') // 按时间倒序排序,确保取到最新的一条
  1011. ->where('c.sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"]) // 时间过滤
  1012. ->select();
  1013. // 格式化数据,按小组取最新的一条工单
  1014. $groupedData = [];
  1015. foreach ($data as $item) {
  1016. // 确保每个小组只有一条最新记录
  1017. $groupedData[$item['sczl_bh']][] = [
  1018. '订单编号' => $item['订单编号'],
  1019. '客户编号' => $item['客户编号'],
  1020. '款号' => $item['款号'],
  1021. '尺码' => $item['尺码'],
  1022. '数量' => $item['数量'],
  1023. '工序名称' => $item['工序名称'],
  1024. '小组' => $item['sczl_bh'],
  1025. '时间' => $item['sys_rq'], // 记录时间
  1026. ];
  1027. }
  1028. // 筛选每个小组的最新一条数据
  1029. $latestData = [];
  1030. foreach ($groupedData as $group => $groupItems) {
  1031. // 只取最新一条记录
  1032. $latestData[$group] = $groupItems[0]; // 因为数据是按时间降序排列的,所以取第一个就是最新的
  1033. }
  1034. // 对小组进行自定义排序
  1035. uasort($latestData, function($a, $b) use ($group_order) {
  1036. // 获取小组排序位置
  1037. $a_index = array_search($a['小组'], $group_order);
  1038. $b_index = array_search($b['小组'], $group_order);
  1039. // 根据位置排序
  1040. return $a_index - $b_index;
  1041. });
  1042. // 根据自定义列格式生成数据
  1043. $result['columns'] = [
  1044. // ['name' => '工序名称', 'id' => 'gxxm', 'width' => '10%', 'textAlign' => 'left'],
  1045. ['name' => '小组', 'id' => 'xz', 'width' => '10', 'autoWrap' => "true",'textAlign' => 'left'],
  1046. ['name' => '订单编号', 'id' => 'ddbh', 'width' => '14','autoWrap' => "true", 'textAlign' => 'left'],
  1047. ['name' => '客户编号', 'id' => 'khbh', 'width' => '10','autoWrap' => "true", 'textAlign' => 'left'],
  1048. ['name' => '款号', 'id' => 'kh', 'width' => '30', 'textAlign' => 'left'],
  1049. ['name' => '尺码', 'id' => 'cm', 'width' => '7','autoWrap' => "true", 'textAlign' => 'left'],
  1050. ['name' => '数量', 'id' => 'sl', 'width' => '7', 'autoWrap' => "true",'textAlign' => 'left'],
  1051. ['name' => '时间', 'id' => 'sj', 'width' => '20','autoWrap' => "true", 'textAlign' => 'left'],
  1052. ];
  1053. // 将最新的数据填充到表格行中
  1054. $rows = [];
  1055. foreach ($latestData as $v) {
  1056. $rows[] = [
  1057. 'ddbh' => $v['订单编号'],
  1058. 'khbh' => $v['客户编号'],
  1059. 'kh' => $v['款号'],
  1060. 'gxxm' => $v['工序名称'],
  1061. 'xz' => $v['小组'],
  1062. 'cm' => $v['尺码'],
  1063. 'sl' => $v['数量'],
  1064. 'sj' => $v['时间'],
  1065. ];
  1066. }
  1067. // 如果没有数据,返回空行
  1068. if (empty($rows)) {
  1069. $rows[] = [
  1070. 'ddbh' => '', 'khbh' => '', 'kh' => '', 'cm' => '', 'gxxm' => '', 'xz' => '', 'sl' => '', 'sj' => ''
  1071. ];
  1072. }
  1073. // 返回最终结果
  1074. $res['status'] = 0;
  1075. $res['msg'] = '查询成功';
  1076. $res['data'] = [
  1077. 'columns' => $result['columns'],
  1078. 'rows' => $rows
  1079. ];
  1080. return json($res);
  1081. }
  1082. /**
  1083. * 在产订单工序详情【缓存】
  1084. */
  1085. public function getJhzByRedis(){
  1086. //存缓存Redis
  1087. $redis = redis();
  1088. $redis_key = md5('getJhzByRedis');
  1089. // 定义固定工序名称
  1090. $processNames = ['裁剪', '车缝', '手工', '大烫', '总检', '包装'];
  1091. // $startTime = date('Y-m-d', strtotime('-180 days'));
  1092. $startTime = date('Y-m-01');
  1093. $endTime = date('Y-m-d');
  1094. $where['c.Sys_rq'] = ['between', [$startTime, $endTime]];
  1095. // $where['j.出库日期'] = ['<>', 'NULL'];
  1096. $where['c.mod_rq'] = null;
  1097. // 第一个查询:获取完工数量
  1098. $list = \db('工单_基本资料')->alias('j')
  1099. ->join('设备_产量计酬 c', 'j.订单编号 = c.订单编号', 'LEFT')
  1100. ->field('c.订单编号, j.工单入仓数量, j.客户编号, j.生产款号, j.款式, c.工序名称,
  1101. CASE
  1102. WHEN 工序名称 IN ("裁剪", "车缝") THEN SUM(数量)
  1103. ELSE SUM(s_num)
  1104. END as 完工数量,
  1105. j.gd_statu as 订单状态')
  1106. ->where($where)
  1107. ->group('c.订单编号, c.工序名称')
  1108. ->order('c.订单编号 desc')
  1109. ->having('完工数量 > 0')
  1110. ->select();
  1111. // 第二个查询:获取制单数
  1112. $yjwhere['y.Mod_rq'] = null;
  1113. $yjlist = \db('工单_基本资料')->alias('j')
  1114. ->join('工单_印件资料 y', 'j.订单编号 = y.订单编号', 'LEFT')
  1115. ->field('y.订单编号, SUM(y.zdtotal) as 制单数')
  1116. ->where($yjwhere)
  1117. ->group('y.订单编号')
  1118. ->order('y.订单编号 desc')
  1119. ->select();
  1120. // 将制单数结果转换为以订单编号为键的数组,方便后续合并
  1121. $yjlistIndexed = [];
  1122. foreach ($yjlist as $yj) {
  1123. $yjlistIndexed[$yj['订单编号']] = $yj['制单数'];
  1124. }
  1125. // 合并数据
  1126. $mergedData = [];
  1127. foreach ($list as $order) {
  1128. $orderId = $order['订单编号'];
  1129. // 初始化订单数据,如果还未存在
  1130. if (!isset($mergedData[$orderId])) {
  1131. // 获取制单数和已完工数量
  1132. $zdTotal = $yjlistIndexed[$orderId] ?? 0; // 制单数
  1133. $completedTotal = $order['工单入仓数量']; // 已完工数量
  1134. // 计算完成百分比
  1135. $completionPercentage = $zdTotal > 0 ? round(($completedTotal / $zdTotal) * 100, 2) . '%' : '0%';
  1136. // 初始化订单数据
  1137. $mergedData[$orderId] = [
  1138. '订单编号' => $orderId,
  1139. '客户编号' => $order['客户编号'],
  1140. '生产款号' => $order['生产款号'],
  1141. '款式' => $order['款式'],
  1142. '订单状态' => $order['订单状态'],
  1143. '已完工数量' => $completedTotal,
  1144. '制单数' => $zdTotal,
  1145. '完成百分比' => $completionPercentage, // 新增字段:完成百分比
  1146. ];
  1147. // 初始化所有工序的完工数量为空
  1148. foreach ($processNames as $process) {
  1149. $mergedData[$orderId][$process] = '';
  1150. }
  1151. }
  1152. // 更新对应的工序名称和完工数量
  1153. if (in_array($order['工序名称'], $processNames)) {
  1154. $mergedData[$orderId][$order['工序名称']] = $order['完工数量'];
  1155. }
  1156. }
  1157. foreach ($mergedData as $key => $order) {
  1158. // 判断裁剪是否为空
  1159. if (empty($order['裁剪'])) {
  1160. unset($mergedData[$key]); // 如果裁剪为空,删除该订单
  1161. }
  1162. }
  1163. // 转换合并后的数组格式
  1164. $result = array_values($mergedData);
  1165. $redis->set($redis_key, json_encode($result));
  1166. echo date("Y-m-d H:i:s").'----存进去了';
  1167. // return $result;
  1168. }
  1169. /**
  1170. * 在产订单工序详情【接口】
  1171. */
  1172. public function getJhzBy(){
  1173. $redis = redis();
  1174. $row = json_decode($redis->get(md5('getJhzByRedis')), true);
  1175. // 列定义
  1176. $result['columns'] = [
  1177. ['name' => '订单编号', 'id' => 'ddbh', 'width' => '7', 'textAlign' => 'left'],
  1178. ['name' => '客户编号', 'id' => 'khbh', 'width' => '6','autoWrap' => "true", 'textAlign' => 'left'],
  1179. ['name' => '生产款号', 'id' => 'sckh', 'width' => '12', 'textAlign' => 'left'],
  1180. ['name' => '款式', 'id' => 'ks', 'width' => '10', 'textAlign' => 'left'],
  1181. ['name' => '订单状态', 'id' => 'ddzt', 'width' => '6', 'textAlign' => 'left'],
  1182. ['name' => '制单总数', 'id' => 'zds', 'width' => '6', 'textAlign' => 'left'],
  1183. ['name' => '裁剪已完成', 'id' => 'cj', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1184. ['name' => '车缝已完成', 'id' => 'cf', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1185. ['name' => '手工已完成', 'id' => 'sg', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1186. ['name' => '大烫已完成', 'id' => 'dt', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1187. ['name' => '总检已完成', 'id' => 'zj', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1188. ['name' => '包装已完成', 'id' => 'bz', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1189. ['name' => '已完成数量', 'id' => 'ywgsl', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1190. ['name' => '完成百分比', 'id' => 'bfb', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  1191. ];
  1192. if ($row) {
  1193. foreach ($row as $k => $v) {
  1194. $result['rows'][$k]['ddbh'] = $v['订单编号'];
  1195. $result['rows'][$k]['khbh'] = $v['客户编号'];
  1196. $result['rows'][$k]['sckh'] = $v['生产款号'];
  1197. $result['rows'][$k]['ks'] = $v['款式'];
  1198. $result['rows'][$k]['ddzt'] = $v['订单状态'];
  1199. // 工序数量字段,根据之前的定义调整字段名
  1200. $result['rows'][$k]['cj'] = $v['裁剪'] ?? '';
  1201. $result['rows'][$k]['cf'] = $v['车缝'] ?? '';
  1202. $result['rows'][$k]['sg'] = $v['手工'] ?? '';
  1203. $result['rows'][$k]['dt'] = $v['大烫'] ?? '';
  1204. $result['rows'][$k]['zj'] = $v['总检'] ?? '';
  1205. $result['rows'][$k]['bz'] = $v['包装'] ?? '';
  1206. // 其他数量字段
  1207. $result['rows'][$k]['ywgsl'] = $v['已完工数量'] ?? ''; // 示例字段,需确保与数据一致
  1208. $result['rows'][$k]['zds'] = $v['制单数'] ?? ''; // 对应制单数
  1209. $result['rows'][$k]['bfb'] = $v['完成百分比'] ?? ''; // 对应制单数
  1210. }
  1211. } else {
  1212. // 如果没有数据,初始化空行
  1213. $result['rows'][0] = [
  1214. 'ddbh' => '', 'khbh' => '', 'sckh' => '', 'ks' => '', 'ddzt' => '',
  1215. 'cj' => '', 'cf' => '', 'sg' => '', 'dt' => '', 'zj' => '', 'bz' => '',
  1216. 'ywgsl' => '', 'zds' => ''
  1217. ];
  1218. }
  1219. // echo "<pre>";print_r($result);echo "<pre>";die;
  1220. $res['status'] = 0;
  1221. $res['msg'] = '';
  1222. $res['data'] = $result;
  1223. return json($res);
  1224. }
  1225. /**第四屏*/
  1226. /**
  1227. *当日班组报工产量【缓存】
  1228. * 建议缓存时间,5--10分钟自动更新一次
  1229. * 统计当天的各个小组报工完成数量
  1230. */
  1231. public function GroupProductionRedis() {
  1232. // 存缓存到 Redis
  1233. $redis = redis();
  1234. $redis_key = md5('GroupProductionRedis');
  1235. $today = date('Y-m-d'); // 获取今天的日期
  1236. $sevenDaysAgo = date('Y-m-d', strtotime('-6 days')); // 计算6天前的日期(包含今天共7天)
  1237. // 自定义需要显示的生产工序顺序
  1238. $customGroups = ['裁剪', '车缝', '手工', '大烫', '总检', '包装'];
  1239. // 获取所有设备资料,并按自定义工序顺序过滤
  1240. $Machine = db('设备_基本资料')
  1241. ->field('生产工序, 设备编组')
  1242. ->whereIn('生产工序', $customGroups)
  1243. ->select();
  1244. // 查询当天设备产量数据
  1245. $res = db('设备_产量计酬')->alias('c')
  1246. ->field([
  1247. 'c.sczl_bh',
  1248. // 使用 CASE 语句动态选择字段:裁剪和车缝使用数量,其他工序使用 s_num
  1249. Db::raw('CASE
  1250. WHEN c.工序名称 IN ("裁剪", "车缝") THEN c.数量
  1251. ELSE s_num
  1252. END AS 数量'),
  1253. 'c.工序名称',
  1254. 'c.sczl_jtbh',
  1255. 'c.sys_rq'
  1256. ])
  1257. ->where(function($query) {
  1258. // 过滤 mod_rq 为 NULL 或 空字符串的记录
  1259. $query->where('c.mod_rq', null)->whereOr('c.mod_rq', '');
  1260. })
  1261. ->where('c.sys_rq', '>=', $sevenDaysAgo . ' 00:00:00') // 从今天00:00开始
  1262. ->where('c.sys_rq', '<=', $today . ' 23:59:59') // 到今天23:59结束
  1263. ->select();
  1264. // 将合并后的数据存储到 Redis 中
  1265. $redis->set($redis_key, json_encode($res));
  1266. echo date("Y-m-d H:i:s") . ' 存进去了';
  1267. }
  1268. //当日报工数量
  1269. public function GroupMachineCFyi()
  1270. {
  1271. $redis = redis(); // 连接 Redis
  1272. $row = json_decode($redis->get(md5('GroupProductionRedis')), true); // 从 Redis 获取数据
  1273. // 获取请求参数中的组别代码
  1274. $req = $this->request->param();
  1275. if (isset($req['jtbh']) && !empty($req['jtbh'])) {
  1276. $arr = $req['jtbh'];
  1277. } else {
  1278. $this->error('参数错误'); // 如果没有传递有效的组别代码,返回错误
  1279. }
  1280. // 获取当前日期
  1281. $today = date('Y-m-d');
  1282. $toYear = date('Y'); // 当前年份
  1283. // 获取七天前的日期
  1284. $sevenDaysAgo = date('Y-m-d', strtotime('-6 days'));
  1285. // 初始化分类和数据系列
  1286. $categories = []; // 存储七天的日期
  1287. $dataSeries = []; // 存储不同工序的数量汇总
  1288. // 获取近七天的日期数组(只取日期部分)
  1289. for ($i = 6; $i >= 0; $i--) {
  1290. $categories[] = date('d', strtotime("-{$i} days")); // 只取日期部分
  1291. }
  1292. // 遍历 Redis 获取的数据,筛选出符合条件的数据
  1293. foreach ($row as $data) {
  1294. // 检查组别代码是否匹配
  1295. if ($data['sczl_jtbh'] === $arr) {
  1296. $date = date('Y-m-d', strtotime($data['sys_rq'])); // 获取数据的日期
  1297. if ($date >= $sevenDaysAgo && $date <= $today) {
  1298. // 计算该日期在七天日期数组中的索引
  1299. $dateIndex = array_search(date('d', strtotime($date)), $categories);
  1300. if ($dateIndex !== false) {
  1301. // 根据工序名称汇总
  1302. $processName = $data['工序名称'];
  1303. // 如果工序名称还没在 $dataSeries 中创建,先初始化
  1304. if (!isset($dataSeries[$processName])) {
  1305. $dataSeries[$processName] = array_fill(0, 7, 0); // 初始化该工序的数据
  1306. }
  1307. // 累加数量
  1308. $dataSeries[$processName][$dateIndex] += $data['数量']; // 使用工序名称作为键名
  1309. }
  1310. }
  1311. }
  1312. }
  1313. // 如果没有任何数据,确保工序数据为默认值
  1314. if (empty($dataSeries)) {
  1315. // 如果没有数据,初始化默认工序并设置数据为0
  1316. $dataSeries = [
  1317. '默认工序' => array_fill(0, 7, 0)
  1318. ];
  1319. }
  1320. // 构建返回的数据格式
  1321. $seriesData = [];
  1322. foreach ($dataSeries as $processName => $values) {
  1323. $seriesData[] = [
  1324. 'name' => $processName, // 工序名称作为名称
  1325. 'data' => $values // 当前工序的数量数据
  1326. ];
  1327. }
  1328. $list = [
  1329. 'categories' => $categories, // 七天的日期
  1330. 'series' => $seriesData // 不同工序的数据
  1331. ];
  1332. // 返回 JSON 格式的结果
  1333. $res = [
  1334. 'status' => 0,
  1335. 'msg' => '',
  1336. 'data' => $list
  1337. ];
  1338. return json($res); // 返回最终的 JSON 数据
  1339. }
  1340. /**第五屏*/
  1341. //质量问题分析
  1342. public function Get_rework(){
  1343. // 获取当前年份
  1344. $currentYear = date('Y');
  1345. // 查询问题分类统计排行
  1346. $problemStats = Db::name('设备_质量汇总')
  1347. ->field('问题分类, COUNT(*) as 问题次数, SUM(数量) as 问题数量')
  1348. ->where('状态', 'in', ['次片', '返工'])
  1349. ->where('YEAR(Sys_rq)', $currentYear)
  1350. ->group('问题分类')
  1351. ->order('问题数量 desc') // 按问题数量降序排序
  1352. ->limit(10) // 只取前10个问题分类
  1353. ->select();
  1354. // 计算问题总数量,用于计算百分比
  1355. $totalProblemData = Db::name('设备_质量汇总')
  1356. ->field('SUM(数量) as total_quantity')
  1357. ->where('状态', 'in', ['次片', '返工'])
  1358. ->where('YEAR(Sys_rq)', $currentYear)
  1359. ->find();
  1360. $totalProblemQuantity = $totalProblemData['total_quantity'] ?? 1; // 避免除零错误
  1361. // 格式化返回数据为要求的结构,包含百分比数据
  1362. $categories = [];
  1363. $seriesData = [];
  1364. foreach ($problemStats as $item) {
  1365. $categories[] = $item['问题分类'] ?? '未分类';
  1366. // 计算百分比占比(保留两位小数,返回数字类型)
  1367. $percentage = round(($item['问题数量'] / $totalProblemQuantity) * 100, 2);
  1368. $seriesData[] = $percentage;
  1369. }
  1370. $res['status'] = 0;
  1371. $res['msg'] = '';
  1372. $res['data'] = [
  1373. 'categories' => $categories,
  1374. 'series' => [
  1375. [
  1376. 'name' => '质量问题百分比',
  1377. 'data' => $seriesData
  1378. ]
  1379. ]
  1380. ];
  1381. return json($res);
  1382. }
  1383. //面料库存情况
  1384. public function Get_inventory(){
  1385. // 初始化结果数组
  1386. $result = [];
  1387. // 列定义
  1388. $result['columns'] = [
  1389. ['name' => '物料名称', 'id' => 'wuliao_name', 'width' => '15', 'textAlign' => 'left'],
  1390. ['name' => '库存数量', 'id' => 'stock_num', 'width' => '10', 'textAlign' => 'left'],
  1391. ];
  1392. // 查询数据
  1393. $allItems = Db::name('物料_库存')
  1394. ->field('物料名称,库存数量')
  1395. ->select();
  1396. // 按物料名称分组并累加库存数量
  1397. $groupedData = [];
  1398. foreach ($allItems as $item) {
  1399. $materialName = $item['物料名称'];
  1400. if (!isset($groupedData[$materialName])) {
  1401. $groupedData[$materialName] = 0;
  1402. }
  1403. $groupedData[$materialName] += floatval($item['库存数量']);
  1404. }
  1405. // 转换为数组格式并保留两位小数
  1406. $inventory = [];
  1407. foreach ($groupedData as $materialName => $stockNum) {
  1408. $inventory[] = [
  1409. '物料名称' => $materialName,
  1410. '库存数量' => round($stockNum, 2)
  1411. ];
  1412. }
  1413. // 按库存数量降序排序
  1414. usort($inventory, function($a, $b) {
  1415. return $b['库存数量'] - $a['库存数量'];
  1416. });
  1417. // 只取前20条
  1418. $inventory = array_slice($inventory, 0, 20);
  1419. // 格式化数据行
  1420. if (!empty($inventory)) {
  1421. foreach ($inventory as $k => $v) {
  1422. $result['rows'][$k]['wuliao_name'] = $v['物料名称'] ?? '';
  1423. $result['rows'][$k]['stock_num'] = $v['库存数量'] ?? '';
  1424. }
  1425. } else {
  1426. // 如果没有数据,初始化空行
  1427. $result['rows'][0] = [
  1428. 'wuliao_name' => '',
  1429. 'stock_num' => ''
  1430. ];
  1431. }
  1432. // 构建响应
  1433. $res['status'] = 0;
  1434. $res['msg'] = '';
  1435. $res['data'] = $result;
  1436. return json($res);
  1437. }
  1438. //获取每个工序中最新订单及完成百分比
  1439. public function Get_ReportingForWork()
  1440. {
  1441. $where = [];
  1442. $where['c.mod_rq'] = null;
  1443. // 首先获取所有记录,优先按时间降序排序,确保最新的记录在前面
  1444. $allOrders = Db::name('设备_产量计酬')
  1445. ->alias('c')
  1446. ->field('c.工序名称,
  1447. c.订单编号,
  1448. c.sczl_bh,
  1449. c.sys_rq,
  1450. j.订单数量,
  1451. j.客户编号,
  1452. j.生产款号,
  1453. j.款式
  1454. ')
  1455. ->join('工单_基本资料 j', 'c.订单编号 = j.订单编号', 'left')
  1456. ->where($where)
  1457. ->order('c.sys_rq desc, c.sczl_bh')
  1458. ->select();
  1459. // 只保留每个小组的第一条记录(最新的)
  1460. $teamLatestOrders = [];
  1461. $processedTeams = [];
  1462. foreach ($allOrders as $order) {
  1463. // 使用小组名称作为键,确保每个小组只保留一条最新记录
  1464. $teamName = $order['sczl_bh'];
  1465. if (!isset($processedTeams[$teamName])) {
  1466. $teamLatestOrders[] = $order;
  1467. $processedTeams[$teamName] = true;
  1468. }
  1469. }
  1470. // 获取每个小组在对应订单上的报工数量
  1471. $teamOrderQuantity = Db::name('设备_产量计酬')
  1472. ->alias('c')
  1473. ->field('c.sczl_bh,
  1474. c.订单编号,
  1475. SUM(CASE
  1476. WHEN c.工序名称 IN ("裁剪", "车缝") THEN c.数量
  1477. ELSE c.s_num
  1478. END) as 报工数量
  1479. ')
  1480. ->where($where)
  1481. ->group('c.sczl_bh, c.订单编号')
  1482. ->select();
  1483. // 将小组和订单的报工数量转为关联数组,方便查找
  1484. $teamOrderQuantityMap = [];
  1485. foreach ($teamOrderQuantity as $item) {
  1486. $key = $item['sczl_bh'] . '_' . $item['订单编号'];
  1487. $teamOrderQuantityMap[$key] = $item['报工数量'];
  1488. }
  1489. // 定义工序顺序
  1490. $processList = ['裁剪', '车缝', '手工', '大烫', '总检', '包装'];
  1491. // 按工序分组所有小组数据
  1492. $processTeams = [];
  1493. foreach ($teamLatestOrders as $item) {
  1494. $processName = $item['工序名称'];
  1495. if (!isset($processTeams[$processName])) {
  1496. $processTeams[$processName] = [];
  1497. }
  1498. $processTeams[$processName][] = $item;
  1499. }
  1500. // 初始化返回数据结构
  1501. $result = [];
  1502. // 定义列信息
  1503. $result['columns'] = [
  1504. ['name' => '客户编号', 'id' => '客户编号', 'width' => '12', 'textAlign' => 'left'],
  1505. ['name' => '订单编号', 'id' => '订单编号', 'width' => '15', 'textAlign' => 'left'],
  1506. ['name' => '生产款号', 'id' => '生产款号', 'width' => '12', 'textAlign' => 'left'],
  1507. ['name' => '款式', 'id' => '款式', 'width' => '15', 'textAlign' => 'left'],
  1508. ['name' => '工序名称', 'id' => '工序名称', 'width' => '10', 'textAlign' => 'left'],
  1509. ['name' => '小组', 'id' => '小组', 'width' => '10', 'textAlign' => 'left'],
  1510. // ['name' => '日期', 'id' => '日期', 'width' => '12', 'textAlign' => 'left'],
  1511. ['name' => '报工数量', 'id' => '报工数量', 'width' => '10', 'textAlign' => 'left'],
  1512. ['name' => '订单数量', 'id' => '订单数量', 'width' => '10', 'textAlign' => 'left'],
  1513. ['name' => '完成率', 'id' => '完成率', 'width' => '10', 'textAlign' => 'left']
  1514. ];
  1515. // 初始化行数据
  1516. $result['rows'] = [];
  1517. $k = 0;
  1518. // 先按照工序顺序处理
  1519. foreach ($processList as $process) {
  1520. // 检查该工序是否有数据
  1521. if (isset($processTeams[$process])) {
  1522. // 获取该工序的所有小组
  1523. $teams = $processTeams[$process];
  1524. // 按小组编号排序(提取数字部分进行排序)
  1525. usort($teams, function($a, $b) {
  1526. // 提取小组编号中的数字部分
  1527. preg_match('/(\d+)/', $a['sczl_bh'], $matchesA);
  1528. preg_match('/(\d+)/', $b['sczl_bh'], $matchesB);
  1529. $numA = isset($matchesA[1]) ? intval($matchesA[1]) : 0;
  1530. $numB = isset($matchesB[1]) ? intval($matchesB[1]) : 0;
  1531. return $numA - $numB; // 按数字升序排序
  1532. });
  1533. // 添加排序后的小组数据到结果
  1534. foreach ($teams as $item) {
  1535. $total_quantity = floatval($item['订单数量']);
  1536. // 获取该小组在当前订单上的报工数量
  1537. $key = $item['sczl_bh'] . '_' . $item['订单编号'];
  1538. $accumulated_quantity = intval($teamOrderQuantityMap[$key] ?? 0);
  1539. // 计算完成率
  1540. $completion_rate = $total_quantity > 0 ? round(($accumulated_quantity / $total_quantity) * 100, 2) : 0.0;
  1541. $result['rows'][$k]['客户编号'] = $item['客户编号'] ?? '';
  1542. $result['rows'][$k]['订单编号'] = $item['订单编号'] ?? '';
  1543. $result['rows'][$k]['生产款号'] = $item['生产款号'] ?? '';
  1544. $result['rows'][$k]['款式'] = $item['款式'] ?? '';
  1545. $result['rows'][$k]['工序名称'] = $item['工序名称'] ?? '';
  1546. $result['rows'][$k]['小组'] = $item['sczl_bh'] ?? '';
  1547. // $result['rows'][$k]['日期'] = date('Y-m-d', strtotime($item['sys_rq'])) ?? '';
  1548. $result['rows'][$k]['报工数量'] = $accumulated_quantity;
  1549. $result['rows'][$k]['订单数量'] = intval($total_quantity);
  1550. $result['rows'][$k]['完成率'] = strval($completion_rate) . '%';
  1551. $k++;
  1552. }
  1553. }
  1554. }
  1555. // 处理不在预定义顺序中的工序(如果有的话)
  1556. foreach ($processTeams as $process => $teams) {
  1557. // 检查该工序是否已经处理过(即在预定义顺序中)
  1558. if (!in_array($process, $processList)) {
  1559. // 按小组编号排序
  1560. usort($teams, function($a, $b) {
  1561. preg_match('/(\d+)/', $a['sczl_bh'], $matchesA);
  1562. preg_match('/(\d+)/', $b['sczl_bh'], $matchesB);
  1563. $numA = isset($matchesA[1]) ? intval($matchesA[1]) : 0;
  1564. $numB = isset($matchesB[1]) ? intval($matchesB[1]) : 0;
  1565. return $numA - $numB;
  1566. });
  1567. foreach ($teams as $item) {
  1568. $total_quantity = floatval($item['订单数量']);
  1569. // 获取该小组在当前订单上的报工数量
  1570. $key = $item['sczl_bh'] . '_' . $item['订单编号'];
  1571. $accumulated_quantity = intval($teamOrderQuantityMap[$key] ?? 0);
  1572. $completion_rate = $total_quantity > 0 ? round(($accumulated_quantity / $total_quantity) * 100, 2) : 0.0;
  1573. $result['rows'][$k]['客户编号'] = $item['客户编号'] ?? '';
  1574. $result['rows'][$k]['订单编号'] = $item['订单编号'] ?? '';
  1575. $result['rows'][$k]['生产款号'] = $item['生产款号'] ?? '';
  1576. $result['rows'][$k]['款式'] = $item['款式'] ?? '';
  1577. $result['rows'][$k]['工序名称'] = $item['工序名称'] ?? '';
  1578. $result['rows'][$k]['小组'] = $item['sczl_bh'] ?? '';
  1579. $result['rows'][$k]['日期'] = date('Y-m-d', strtotime($item['sys_rq'])) ?? '';
  1580. $result['rows'][$k]['报工数量'] = $accumulated_quantity;
  1581. $result['rows'][$k]['订单数量'] = intval($total_quantity);
  1582. $result['rows'][$k]['完成率'] = strval($completion_rate) . '%';
  1583. $k++;
  1584. }
  1585. }
  1586. }
  1587. // 构建响应
  1588. $res['status'] = 0;
  1589. $res['msg'] = '';
  1590. $res['data'] = $result;
  1591. return json($res);
  1592. }
  1593. //成品入仓列表数据
  1594. public function Get_Finished_Product(){
  1595. // 初始化返回数据结构
  1596. $result = [];
  1597. // 定义列信息
  1598. $result['columns'] = [
  1599. ['name' => '订单编号', 'id' => '订单编号', 'width' => '15', 'textAlign' => 'left'],
  1600. ['name' => '生产款号', 'id' => '生产款号', 'width' => '12', 'textAlign' => 'left'],
  1601. ['name' => '款式', 'id' => '款式', 'width' => '15', 'textAlign' => 'left'],
  1602. ['name' => '成品数量', 'id' => '成品数量', 'width' => '10', 'textAlign' => 'left'],
  1603. ['name' => '订单数量', 'id' => '订单数量', 'width' => '10', 'textAlign' => 'left'],
  1604. ['name' => '未入仓数量', 'id' => '未入仓数量', 'width' => '10', 'textAlign' => 'left'],
  1605. ['name' => '入仓率', 'id' => '入仓率', 'width' => '10', 'textAlign' => 'left']
  1606. ];
  1607. // 查询数据,对相同订单分组并求和成品数量
  1608. $list = Db::name('成品入仓')->alias('a')
  1609. ->field('a.order as 订单编号,
  1610. SUM(a.sl) as 成品数量,
  1611. j.生产款号,
  1612. j.款式,
  1613. j.订单数量
  1614. ')
  1615. ->join('工单_基本资料 j', 'a.order=j.订单编号', 'left')
  1616. ->group('a.order')
  1617. ->limit(30)
  1618. ->select();
  1619. // 格式化数据行
  1620. if (!empty($list)) {
  1621. foreach ($list as $k => $item) {
  1622. // 计算未入仓数量
  1623. $unfinishedQuantity = $item['订单数量'] - $item['成品数量'];
  1624. // 计算入仓率(成品数量 / 订单数量 * 100%),保留2位小数
  1625. $storageRate = $item['订单数量'] > 0 ? round(($item['成品数量'] / $item['订单数量']) * 100, 2) : 0;
  1626. $result['rows'][$k]['订单编号'] = $item['订单编号'] ?? '';
  1627. $result['rows'][$k]['生产款号'] = $item['生产款号'] ?? '';
  1628. $result['rows'][$k]['款式'] = $item['款式'] ?? '';
  1629. $result['rows'][$k]['成品数量'] = $item['成品数量'] ?? '';
  1630. $result['rows'][$k]['订单数量'] = $item['订单数量'] ?? '';
  1631. $result['rows'][$k]['未入仓数量'] = $unfinishedQuantity;
  1632. $result['rows'][$k]['入仓率'] = strval($storageRate) . '%';
  1633. }
  1634. } else {
  1635. // 如果没有数据,初始化空行
  1636. $result['rows'][0] = [
  1637. '订单编号' => '',
  1638. '生产款号' => '',
  1639. '款式' => '',
  1640. '成品数量' => '',
  1641. '订单数量' => '',
  1642. '未入仓数量' => '',
  1643. '入仓率' => ''
  1644. ];
  1645. }
  1646. // 构建响应
  1647. $res['status'] = 0;
  1648. $res['msg'] = '';
  1649. $res['data'] = $result;
  1650. return json($res);
  1651. }
  1652. //下面接口已写好-----暂时未用到
  1653. //板房车缝当日报工数量
  1654. public function GroupMachinebfCFyi()
  1655. {
  1656. $redis = redis();
  1657. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1658. // 初始化小组名称和数量
  1659. $categories = [];
  1660. $dataSeries = [];
  1661. // 遍历数据,找到所有工序名称为“车缝”的小组,且只包含“大办组”、“小芬组”、“美英组”
  1662. foreach ($row as $data) {
  1663. if ($data['工序名称'] === '车缝' && in_array($data['组别'], ['大办组', '小芬组', '美英组'])) {
  1664. $categories[] = $data['组别']; // 添加组别到分类中
  1665. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1666. }
  1667. }
  1668. // 构建输出数据格式
  1669. $list = [
  1670. 'categories' => $categories,
  1671. 'series' => [
  1672. [
  1673. 'name' => '完成',
  1674. 'data' => array_values($dataSeries) // 获取数量数组
  1675. ]
  1676. ]
  1677. ];
  1678. $res = [
  1679. 'status' => 0,
  1680. 'msg' => '',
  1681. 'data' => $list
  1682. ];
  1683. // 返回 JSON 格式的结果
  1684. return json($res);
  1685. }
  1686. //裁剪当日报工数量
  1687. public function GroupMachineCJyi()
  1688. {
  1689. $redis = redis();
  1690. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1691. // 初始化小组名称和数量
  1692. $categories = [];
  1693. $dataSeries = [];
  1694. // 遍历数据,找到所有工序名称为“车缝”的小组
  1695. foreach ($row as $data) {
  1696. if ($data['工序名称'] !== '车缝') {
  1697. $categories[] = $data['组别']; // 添加组别到分类中
  1698. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1699. }
  1700. }
  1701. // 构建输出数据格式
  1702. $list = [
  1703. 'categories' => $categories,
  1704. 'series' => [
  1705. [
  1706. 'name' => '完成',
  1707. 'data' => array_values($dataSeries) // 获取数量数组
  1708. ]
  1709. ]
  1710. ];
  1711. $res = [
  1712. 'status' => 0,
  1713. 'msg' => '',
  1714. 'data' => $list
  1715. ];
  1716. // 返回 JSON 格式的结果
  1717. return json($res);
  1718. }
  1719. //手工当日报工数量
  1720. public function GroupMachineSGyi()
  1721. {
  1722. $redis = redis();
  1723. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1724. // 初始化小组名称和数量
  1725. $categories = [];
  1726. $dataSeries = [];
  1727. // 遍历数据,找到所有工序名称为“车缝”的小组
  1728. foreach ($row as $data) {
  1729. if ($data['工序名称'] === '手工') {
  1730. $categories[] = $data['组别']; // 添加组别到分类中
  1731. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1732. }
  1733. }
  1734. // 构建输出数据格式
  1735. $list = [
  1736. 'categories' => $categories,
  1737. 'series' => [
  1738. [
  1739. 'name' => '完成',
  1740. 'data' => array_values($dataSeries) // 获取数量数组
  1741. ]
  1742. ]
  1743. ];
  1744. $res = [
  1745. 'status' => 0,
  1746. 'msg' => '',
  1747. 'data' => $list
  1748. ];
  1749. // 返回 JSON 格式的结果
  1750. return json($res);
  1751. }
  1752. //大烫当日报工数量
  1753. public function GroupMachineDTyi()
  1754. {
  1755. $redis = redis();
  1756. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1757. // 初始化小组名称和数量
  1758. $categories = [];
  1759. $dataSeries = [];
  1760. // 遍历数据,找到所有工序名称为“车缝”的小组
  1761. foreach ($row as $data) {
  1762. if ($data['工序名称'] === '大烫') {
  1763. $categories[] = $data['组别']; // 添加组别到分类中
  1764. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1765. }
  1766. }
  1767. // 构建输出数据格式
  1768. $list = [
  1769. 'categories' => $categories,
  1770. 'series' => [
  1771. [
  1772. 'name' => '完成',
  1773. 'data' => array_values($dataSeries) // 获取数量数组
  1774. ]
  1775. ]
  1776. ];
  1777. $res = [
  1778. 'status' => 0,
  1779. 'msg' => '',
  1780. 'data' => $list
  1781. ];
  1782. // 返回 JSON 格式的结果
  1783. return json($res);
  1784. }
  1785. //总检当日报工数量
  1786. public function GroupMachineZJyi()
  1787. {
  1788. $redis = redis();
  1789. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1790. // 初始化小组名称和数量
  1791. $categories = [];
  1792. $dataSeries = [];
  1793. // 遍历数据,找到所有工序名称为“车缝”的小组
  1794. foreach ($row as $data) {
  1795. if ($data['工序名称'] === '总检') {
  1796. $categories[] = $data['组别']; // 添加组别到分类中
  1797. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1798. }
  1799. }
  1800. // 构建输出数据格式
  1801. $list = [
  1802. 'categories' => $categories,
  1803. 'series' => [
  1804. [
  1805. 'name' => '完成',
  1806. 'data' => array_values($dataSeries) // 获取数量数组
  1807. ]
  1808. ]
  1809. ];
  1810. $res = [
  1811. 'status' => 0,
  1812. 'msg' => '',
  1813. 'data' => $list
  1814. ];
  1815. // 返回 JSON 格式的结果
  1816. return json($res);
  1817. }
  1818. //包装当日报工数量
  1819. public function GroupMachineBZyi()
  1820. {
  1821. $redis = redis();
  1822. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1823. // 初始化小组名称和数量
  1824. $categories = [];
  1825. $dataSeries = [];
  1826. // 遍历数据,找到所有工序名称为“车缝”的小组
  1827. foreach ($row as $data) {
  1828. if ($data['工序名称'] === '包装') {
  1829. $categories[] = $data['组别']; // 添加组别到分类中
  1830. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1831. }
  1832. }
  1833. // 构建输出数据格式
  1834. $list = [
  1835. 'categories' => $categories,
  1836. 'series' => [
  1837. [
  1838. 'name' => '完成',
  1839. 'data' => array_values($dataSeries) // 获取数量数组
  1840. ]
  1841. ]
  1842. ];
  1843. $res = [
  1844. 'status' => 0,
  1845. 'msg' => '',
  1846. 'data' => $list
  1847. ];
  1848. // 返回 JSON 格式的结果
  1849. return json($res);
  1850. }
  1851. //自动生成面料以及调用---》GPT
  1852. public function GtpAiOrder()
  1853. {
  1854. if (!$this->request->isGet()) {
  1855. $this->error('请求错误');
  1856. }
  1857. $order = $this->request->param('订单编号');
  1858. // 判断是否有指定的订单号
  1859. if (!empty($order)) {
  1860. // 查询单个订单的最大编号
  1861. $maxOrder = \db('工单_基本资料')
  1862. ->where('订单编号', 'like', "{$order}%")
  1863. ->order('订单编号', 'desc')
  1864. ->limit(1)
  1865. ->value('订单编号');
  1866. // 查询该订单的基本资料
  1867. $list = \db('工单_基本资料')
  1868. ->where('订单编号', 'like', "{$order}%")
  1869. ->order('订单编号', 'desc')
  1870. ->limit(1)
  1871. ->find();
  1872. // 如果面料数据为空,提示错误
  1873. if (empty($list['面料'])) {
  1874. $this->error('面料数据为空无法定义BOM');
  1875. }
  1876. // 处理订单编号
  1877. $numericPart = substr($maxOrder, 2);
  1878. $newNumericPart = str_pad((int)$numericPart + 1, strlen($numericPart), '0', STR_PAD_LEFT);
  1879. $param['订单编号'] = $order . $newNumericPart;
  1880. // 假设massage是从数据库获取的数据
  1881. $massage = empty($list['粘衬']) || $list['粘衬'] == '无' ? $list['面料'] : $list['面料'] . ',粘衬:' . $list['粘衬'];
  1882. $materialCategories = [];
  1883. $pattern = '/(\S+?):([^,]+)/'; // 匹配 类别:物料 格式
  1884. preg_match_all($pattern, $massage, $matches, PREG_SET_ORDER);
  1885. foreach ($matches as $match) {
  1886. $category = $match[1]; // 分类名称
  1887. $materials = explode('+', $match[2]); // 如果物料名称中有‘+’,则分开处理多个物料
  1888. // 将分类和对应的物料添加到数组中
  1889. foreach ($materials as $material) {
  1890. $materialCategories[$category][] = trim($material); // 去除物料两边的空格
  1891. }
  1892. }
  1893. $mianliao = $this->Gpt($massage);
  1894. $data = [];
  1895. foreach ($mianliao as $value) {
  1896. if (!empty($value) && $value !== '粘衬') { // 排除空值和粘衬
  1897. $category = '';
  1898. // 查找物料对应的分类
  1899. foreach ($materialCategories as $cat => $materials) {
  1900. if (in_array($value, $materials)) {
  1901. $category = $cat;
  1902. break;
  1903. }
  1904. }
  1905. // 如果找到分类,将数据存入BOM
  1906. $data[] = [
  1907. 'BOM_工单编号' => $list['订单编号'],
  1908. 'BOM_物料名称' => $value,
  1909. 'BOM_desc' => '',
  1910. '物料分类' => $category ? $category : '',
  1911. 'Sys_rq' => date('Y-m-d H:i:s'),
  1912. 'Sys_ID' => '超级管理员'
  1913. ];
  1914. }
  1915. }
  1916. foreach ($data as &$item) {
  1917. if (empty($item['物料分类'])) {
  1918. $item['物料分类'] = '';
  1919. }
  1920. // 去除所有非汉字字符
  1921. $item['物料分类'] = preg_replace('/[^\p{Han}]/u', '', $item['物料分类']);
  1922. }
  1923. //// 批量更新 BOM_desc,如果对应的 BOM_desc 没有填充就更新
  1924. // foreach ($data as $item) {
  1925. // if (!empty($item['物料分类'])) {
  1926. // \db('工单_bom资料')->insertAll($data);
  1927. //
  1928. //// \db('工单_面料资料')
  1929. //// ->where('BOM_工单编号', $item['BOM_工单编号'])
  1930. //// ->where('BOM_物料名称', $item['BOM_物料名称'])
  1931. //// ->update(['BOM_desc' => preg_replace('/[^\w\s]/u', '', $item['BOM_desc'])]);
  1932. //
  1933. // }
  1934. // }
  1935. // $this->success('成功',$order);
  1936. } else {
  1937. // 如果没有指定订单号,批量查询订单号并处理
  1938. $has_bom = \db('工单_bom资料')->alias('a')->field('a.BOM_工单编号')->group('a.BOM_工单编号')->select();
  1939. $all_orders = \db('工单_基本资料')->alias('a')->field('a.订单编号')->where('a.面料', '<>', '')->group('a.订单编号')->select();
  1940. // 提取有BOM资料的订单号
  1941. $has_bom_orders = array_column($has_bom, 'BOM_工单编号');
  1942. // 筛选出没有对应BOM资料的订单号
  1943. $no_bom_orders = array_filter($all_orders, function ($order) use ($has_bom_orders) {
  1944. return !in_array($order['订单编号'], $has_bom_orders);
  1945. });
  1946. // 遍历没有BOM资料的订单
  1947. foreach ($no_bom_orders as $orderData) {
  1948. // 获取该订单号的最大订单编号
  1949. $maxOrder = \db('工单_基本资料')
  1950. ->where('订单编号', 'like', "{$orderData['订单编号']}%")
  1951. ->order('订单编号', 'desc')
  1952. ->limit(1)
  1953. ->value('订单编号');
  1954. // 获取该订单号的具体数据
  1955. $list = \db('工单_基本资料')
  1956. ->where('订单编号', 'like', "{$orderData['订单编号']}%")
  1957. ->order('订单编号', 'desc')
  1958. ->limit(1)
  1959. ->find();
  1960. if (empty($list['面料'])) {
  1961. $this->error("订单 {$orderData['订单编号']} 面料数据为空,无法定义BOM");
  1962. }
  1963. // 处理订单编号
  1964. $numericPart = substr($maxOrder, 2);
  1965. $newNumericPart = str_pad((int)$numericPart + 1, strlen($numericPart), '0', STR_PAD_LEFT);
  1966. $param['订单编号'] = $order . $newNumericPart;
  1967. // 处理物料信息
  1968. $massage = empty($list['粘衬']) || $list['粘衬'] == '无' ? $list['面料'] : $list['面料'] . ',粘衬:' . $list['粘衬'];
  1969. $mianliao = $this->Gpt($massage);
  1970. // 插入物料数据
  1971. $data = [];
  1972. foreach ($mianliao as $key => $value) {
  1973. if (!empty($value) && $value !== '粘衬') { // 排除空值和粘衬
  1974. $data[] = [
  1975. 'BOM_工单编号' => $list['订单编号'],
  1976. 'BOM_物料名称' => $value,
  1977. 'BOM_desc' => '',
  1978. '物料分类' => '',
  1979. 'Sys_rq' => date('Y-m-d H:i:s'),
  1980. 'Sys_ID' => '超级管理员'
  1981. ];
  1982. }
  1983. }
  1984. // 批量插入BOM资料
  1985. if (!empty($data)) {
  1986. \db('工单_bom资料')->insertAll($data);
  1987. }
  1988. }
  1989. $this->success('成功');
  1990. }
  1991. }
  1992. //GPT
  1993. public function Gpt($massage)
  1994. {
  1995. // 设置 API 密钥
  1996. $apiKey = 'sk-e0JuPjMntkbgi1BoMjrqyyzMKzAxILkQzyGMSy3xiMupuoWY'; // 替换为您的 API 密钥
  1997. // 要发送给 GPT 的消息
  1998. $messages = [
  1999. [
  2000. 'role' => 'user',
  2001. 'content' => '你好,帮我按照:面料1、面料2、面料3……来整理归纳下面的面料信息,我只需要面料信息,不需要其他:'.$massage
  2002. ]
  2003. ];
  2004. // 创建请求数据
  2005. $data = [
  2006. 'model' => 'gpt-3.5-turbo', // 使用的模型
  2007. 'messages' => $messages,
  2008. 'max_tokens' => 100, // 设置最大 token 数
  2009. ];
  2010. // 初始化 cURL
  2011. $ch = curl_init('https://niubi.zeabur.app/v1/chat/completions');
  2012. // 设置 cURL 选项
  2013. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  2014. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  2015. 'Content-Type: application/json',
  2016. 'Authorization: Bearer ' . $apiKey,
  2017. ]);
  2018. curl_setopt($ch, CURLOPT_POST, true);
  2019. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  2020. curl_setopt($ch, CURLOPT_CAINFO, ROOT_PATH . '/public/uploads/cacert.pem');
  2021. // 执行请求
  2022. $response = curl_exec($ch);
  2023. // 检查错误
  2024. if (curl_errno($ch)) {
  2025. echo 'Error:' . curl_error($ch);
  2026. }
  2027. // 关闭 cURL
  2028. curl_close($ch);
  2029. // 解析和输出响应
  2030. $responseData = json_decode($response, true);
  2031. // 获取 GPT 的回复
  2032. if (isset($responseData['choices'][0]['message']['content'])) {
  2033. //获取返回内容
  2034. $gptReply = $responseData['choices'][0]['message']['content'];
  2035. // halt($gptReply);
  2036. //返回面料信息
  2037. $gptArray = explode('面料',$gptReply);
  2038. array_shift($gptArray);
  2039. foreach ($gptArray as $key=>$value){
  2040. $gptArray[$key] = preg_replace('/\s+/', '', substr($value,4));
  2041. }
  2042. return $gptArray;
  2043. } else {
  2044. echo "未能获取 GPT 的回复。";
  2045. }
  2046. }
  2047. }