Index.php 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use think\Controller;
  5. use think\Db;
  6. use think\Request;
  7. /**
  8. * 达成大屏数据接口
  9. */
  10. class Index extends Controller{
  11. protected $noNeedLogin = ['*'];
  12. protected $noNeedRight = ['*'];
  13. /**首页*/
  14. public function index(){$this->success('成功');}
  15. /**第一屏*/
  16. //年度承接产量
  17. public function thisyear(){
  18. $date = date("Y");
  19. // 返回 JSON 格式数据
  20. return json([
  21. "status" => 0,
  22. "msg" => "",
  23. "data" => $date.'年度承接产量',
  24. ]);
  25. }
  26. public function lastyear(){
  27. $date = date("Y") - 1;
  28. // 返回 JSON 格式数据
  29. return json([
  30. "status" => 0,
  31. "msg" => "",
  32. "data" => $date.'年度承接产量',
  33. ]);
  34. }
  35. //获取近三年年份
  36. public function ymd_api(){
  37. $data = [
  38. ["name" => " ", "value" => strval(date('Y'))], // 将年份转换为字符串
  39. ["name" => " ", "value" => strval(date('Y') - 1)], // 将年份转换为字符串
  40. ["name" => " ", "value" => strval(date('Y') - 2)], // 将年份转换为字符串
  41. ];
  42. // 返回 JSON 格式数据
  43. return json([
  44. "status" => 0,
  45. "msg" => "",
  46. "data" => $data,
  47. ]);
  48. }
  49. /**
  50. *去年的年度承接产量【接口】
  51. *统计去年订单个数,订单数量,包装完工数量,完成率。
  52. */
  53. public function Lastcontractedoutput_api(){
  54. // 获取今年的年份
  55. $last_year = date("Y") -1;
  56. // 查询条件:Mod_rq为null且年份为今年的记录数量
  57. $count = \db('工单_基本资料')
  58. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  59. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  60. ->count();
  61. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  62. $sum = \db('工单_基本资料')
  63. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  64. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  65. ->whereNull('Mod_rq')
  66. ->select();
  67. $total_sum = 0;
  68. $s_num_total = 0;
  69. $ratio = 0;
  70. if (!empty($sum)) {
  71. foreach ($sum as $value) {
  72. $total_sum = $value['total_sum']; // 使用别名获取结果
  73. if ($total_sum) {
  74. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  75. $s_num_result = \db('设备_产量计酬')
  76. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  77. ->where('工序编号', 7)
  78. ->whereNull('mod_rq')
  79. ->where('sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  80. ->select();
  81. if (!empty($s_num_result)) {
  82. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  83. // 计算比例并四舍五入保留两位小数
  84. if ($total_sum != 0) { // 避免除数为0
  85. $ratio = round(($s_num_total / $total_sum) * 100) . '%';
  86. }
  87. }
  88. }
  89. }
  90. }
  91. // 构建返回数据
  92. // $data = [
  93. // ["name" => "总订单数", "value" => $count],
  94. // ["name" => "承接大货数", "value" => $total_sum],
  95. // ["name" => "完工数量", "value" => $s_num_total],
  96. // ["name" => "完成率", "value" => $ratio],
  97. // ];
  98. $data = [
  99. ["name" => " ", "value" => $count],
  100. ["name" => " ", "value" => $total_sum],
  101. ["name" => " ", "value" => $s_num_total],
  102. // ["name" => " ", "value" => $ratio],
  103. ];
  104. // 返回 JSON 格式数据
  105. return json([
  106. "status" => 0,
  107. "msg" => "",
  108. "data" => $data,
  109. ]);
  110. }
  111. /**
  112. *当年的年度承接产量【接口】
  113. *统计当年订单个数,订单数量,包装完工数量,完成率。
  114. */
  115. public function Annualcontractedoutput_api(){
  116. // 获取今年的年份
  117. $year = date("Y");
  118. // 查询条件:Mod_rq为null且年份为今年的记录数量
  119. $count = \db('工单_基本资料')
  120. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  121. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  122. ->count();
  123. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  124. $sum = \db('工单_基本资料')
  125. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  126. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  127. ->whereNull('Mod_rq')
  128. ->select();
  129. $total_sum = 0;
  130. $s_num_total = 0;
  131. $ratio = 0;
  132. if (!empty($sum)) {
  133. foreach ($sum as $value) {
  134. $total_sum = $value['total_sum']; // 使用别名获取结果
  135. if ($total_sum) {
  136. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  137. $s_num_result = \db('设备_产量计酬')
  138. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  139. ->where('工序编号', 7)
  140. ->whereNull('mod_rq')
  141. ->where('sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  142. ->select();
  143. if (!empty($s_num_result)) {
  144. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  145. // 计算比例并四舍五入保留两位小数
  146. if ($total_sum != 0) { // 避免除数为0
  147. $ratio = round(($s_num_total / $total_sum) * 100) . '%';
  148. }
  149. }
  150. }
  151. }
  152. }
  153. // 构建返回数据
  154. $data = [
  155. ["name" => " ", "value" => $count],
  156. ["name" => " ", "value" => $total_sum],
  157. ["name" => " ", "value" => $s_num_total],
  158. // ["name" => " ", "value" => $ratio],
  159. ];
  160. // 返回 JSON 格式数据
  161. return json([
  162. "status" => 0,
  163. "msg" => "",
  164. "data" => $data,
  165. ]);
  166. }
  167. public function dcompletion_api(){
  168. // 获取今年的年份
  169. $year = date("Y");
  170. // 查询条件:Mod_rq为null且年份为今年的记录数量
  171. $count = \db('工单_基本资料')
  172. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  173. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  174. ->count();
  175. // 查询条件:Mod_rq为null且年份为今年的订单数量字段的总和
  176. $sum = \db('工单_基本资料')
  177. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  178. ->where('Sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  179. ->whereNull('Mod_rq')
  180. ->select();
  181. $total_sum = 0;
  182. $s_num_total = 0;
  183. $ratio = 0;
  184. if (!empty($sum)) {
  185. foreach ($sum as $value) {
  186. $total_sum = $value['total_sum']; // 使用别名获取结果
  187. if ($total_sum) {
  188. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为今年的s_num总和
  189. $s_num_result = \db('设备_产量计酬')
  190. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  191. ->where('工序编号', 7)
  192. ->whereNull('mod_rq')
  193. ->where('sys_rq', 'between', ["$year-01-01 00:00:00", "$year-12-31 23:59:59"])
  194. ->select();
  195. if (!empty($s_num_result)) {
  196. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  197. // 计算比例并四舍五入取整数
  198. if ($total_sum != 0) { // 避免除数为0
  199. $ratio = ($s_num_total / $total_sum) * 100; // 四舍五入并取整数
  200. }
  201. }
  202. }
  203. }
  204. }
  205. // 返回 JSON 格式数据
  206. return json([
  207. "status" => 0,
  208. "hitSugarSelf" => true,
  209. "msg" => "",
  210. "data" => round($ratio), // 返回计算后的整数完成率
  211. ]);
  212. }
  213. public function qcompletion_api(){
  214. // 获取今年的年份
  215. $last_year = date("Y") - 1;
  216. // 查询条件:Mod_rq为null且年份为去年的记录数量
  217. $count = \db('工单_基本资料')
  218. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  219. ->whereNull('Mod_rq') // 修正:使用 whereNull 方法
  220. ->count();
  221. // 查询条件:Mod_rq为null且年份为去年的订单数量字段的总和
  222. $sum = \db('工单_基本资料')
  223. ->field("sum(`订单数量`) as total_sum") // 使用反引号包裹中文字段名,并设置别名
  224. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  225. ->whereNull('Mod_rq')
  226. ->select();
  227. $total_sum = 0;
  228. $s_num_total = 0;
  229. $ratio = 0;
  230. if (!empty($sum)) {
  231. foreach ($sum as $value) {
  232. $total_sum = $value['total_sum']; // 使用别名获取结果
  233. if ($total_sum) {
  234. // 查询设备_产量计酬表中工序编号为7且mod_rq为null且年份为去年的s_num总和
  235. $s_num_result = \db('设备_产量计酬')
  236. ->field("sum(`s_num`) as s_num_total") // 计算 s_num 的总和
  237. ->where('工序编号', 7)
  238. ->whereNull('mod_rq')
  239. ->where('sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  240. ->select();
  241. if (!empty($s_num_result)) {
  242. $s_num_total = $s_num_result[0]['s_num_total']; // 获取 s_num 的总和
  243. // 计算比例并四舍五入保留两位小数
  244. if ($total_sum != 0) { // 避免除数为0
  245. $ratio = round(($s_num_total / $total_sum) * 100, 2); // 计算并保留两位小数
  246. }
  247. }
  248. }
  249. }
  250. }
  251. // 返回 JSON 格式数据
  252. return json([
  253. "status" => 0,
  254. "hitSugarSelf" => true,
  255. "msg" => "",
  256. "data" => $ratio,
  257. ]);
  258. }
  259. /**
  260. * 年度订单个数【接口】
  261. * 统计近三年的订单条数
  262. */
  263. public function orderlist_api(){
  264. // 获取当前日期的年份
  265. $currentYear = date('Y');
  266. // 获取三年前的年份
  267. $threeYearsAgo = $currentYear - 2;
  268. // 构建查询的年份范围
  269. $years = [$threeYearsAgo, $threeYearsAgo + 1, $currentYear];
  270. // 查询订单的年份和数量
  271. $orderData = db('工单_基本资料')
  272. ->field('YEAR(Sys_rq) AS year, COUNT(*) AS order_count')
  273. ->whereNull('Mod_rq')
  274. ->where('YEAR(Sys_rq)', 'between', [$threeYearsAgo, $currentYear])
  275. ->group('YEAR(Sys_rq)')
  276. ->select();
  277. // 将查询结果按年份分组存储
  278. $orderCountByYear = [];
  279. foreach ($orderData as $data) {
  280. $orderCountByYear[$data['year']] = $data['order_count'];
  281. }
  282. // 对于没有订单的年份,默认值为0
  283. foreach ($years as $year) {
  284. if (!isset($orderCountByYear[$year])) {
  285. $orderCountByYear[$year] = 0; // 如果该年没有数据,则设置为0
  286. }
  287. }
  288. // 准备 API 格式的响应数据
  289. $response = [
  290. 'status' => 0,
  291. 'msg' => '',
  292. 'data' => [
  293. 'categories' => $years, // 输出年份数组
  294. 'series' => [
  295. [
  296. 'name' => '年度订单个数',
  297. 'data' => array_map(function($year) use ($orderCountByYear) {
  298. return $orderCountByYear[$year];
  299. }, $years), // 根据年份返回对应的订单数量
  300. ]
  301. ]
  302. ]
  303. ];
  304. return json($response);
  305. }
  306. /**
  307. * 年度计划数量【接口】
  308. * 统计近三年的订单总数量合计
  309. */
  310. public function ordersumlist_api(){
  311. // 获取当前日期的年份
  312. $currentYear = date('Y');
  313. // 获取三年前的年份
  314. $threeYearsAgo = $currentYear - 2;
  315. // 构建查询的年份范围
  316. $years = [$threeYearsAgo, $threeYearsAgo + 1, $currentYear];
  317. // 查询订单的年份和数量的合计
  318. $orderData = db('工单_基本资料')
  319. ->field('YEAR(Sys_rq) AS year, SUM(订单数量) AS total_quantity') // 这里改为求“数量”的合计
  320. ->whereNull('Mod_rq')
  321. ->where('YEAR(Sys_rq)', 'between', [$threeYearsAgo, $currentYear])
  322. ->group('YEAR(Sys_rq)')
  323. ->select();
  324. // 将查询结果按年份分组存储
  325. $orderSumByYear = [];
  326. foreach ($orderData as $data) {
  327. $orderSumByYear[$data['year']] = $data['total_quantity'];
  328. }
  329. // 对于没有订单的年份,默认值为0
  330. foreach ($years as $year) {
  331. if (!isset($orderSumByYear[$year])) {
  332. $orderSumByYear[$year] = 0; // 如果该年没有数据,则设置为0
  333. }
  334. }
  335. // 准备 API 格式的响应数据
  336. $response = [
  337. 'status' => 0,
  338. 'msg' => '',
  339. 'data' => [
  340. 'categories' => $years, // 输出年份数组
  341. 'series' => [
  342. [
  343. 'name' => '年度计划数量',
  344. 'data' => array_map(function($year) use ($orderSumByYear) {
  345. return $orderSumByYear[$year];
  346. }, $years), // 根据年份返回对应的订单数量合计
  347. ]
  348. ]
  349. ]
  350. ];
  351. return json($response);
  352. }
  353. /**
  354. * 年度完工数量【接口】
  355. * 统计每个月完成包装的数量
  356. */
  357. public function Annualcompletionrate_api() {
  358. // 获取当前年份和上一年份
  359. $currentYear = date('Y');
  360. $lastYear = $currentYear - 1;
  361. // 获取当前年份和去年的数据
  362. $orderData = db('设备_产量计酬')
  363. ->field("DATE_FORMAT(sys_rq, '%Y-%m') AS sys_rq, SUM(s_num) AS 数量")
  364. ->where('工序名称', '包装')
  365. ->where('mod_rq',null)
  366. ->group('DATE_FORMAT(sys_rq, "%Y-%m")') // 按年月分组
  367. ->select();
  368. // 手动过滤数据,只保留当前年和去年的数据
  369. $filteredData = array_filter($orderData, function ($data) use ($currentYear, $lastYear) {
  370. $year = explode('-', $data['sys_rq'])[0]; // 提取年份
  371. return $year == $currentYear || $year == $lastYear;
  372. });
  373. // 初始化月份和年份数组
  374. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  375. $responseData = [
  376. 'categories' => $months, // 月份数组
  377. 'series' => [
  378. ['name' => $lastYear . '年', 'data' => array_fill(0, 12, 0)], // 初始化为0
  379. ['name' => $currentYear . '年', 'data' => array_fill(0, 12, 0)] // 初始化为0
  380. ]
  381. ];
  382. // 将查询结果按年份和月份存储
  383. foreach ($filteredData as $data) {
  384. // 提取年和月
  385. $yearMonth = explode('-', $data['sys_rq']);
  386. $year = $yearMonth[0];
  387. $month = (int) $yearMonth[1] - 1; // 因为数组从0开始,所以要减去1
  388. // 根据年份更新对应的月份数据
  389. if ($year == $lastYear) {
  390. $responseData['series'][0]['data'][$month] = $data['数量'];
  391. } elseif ($year == $currentYear) {
  392. $responseData['series'][1]['data'][$month] = $data['数量'];
  393. }
  394. }
  395. // 构造最终的响应数据
  396. $response = [
  397. 'status' => 0,
  398. 'msg' => '',
  399. 'data' => $responseData
  400. ];
  401. return json($response);
  402. }
  403. /**
  404. * 年度完成率【接口】
  405. */
  406. public function Annualcompletionraterate_api() {
  407. // 获取当前年份和上一年
  408. $currentYear = date('Y');
  409. $lastYear = $currentYear - 1;
  410. // 初始化月份数组
  411. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  412. // 初始化返回数据
  413. $responseData = [
  414. 'categories' => $months, // 月份
  415. 'series' => [
  416. ['name' => $lastYear . '年完成率', 'data' => array_fill(0, 12, 0)], // 上一年完成率数据
  417. ['name' => $currentYear . '年完成率', 'data' => array_fill(0, 12, 0)], // 当前年完成率数据
  418. ]
  419. ];
  420. // 1. 获取工单基本资料表每月的订单数量(近两年)
  421. $orderData = db('工单_基本资料')
  422. ->field("DATE_FORMAT(出库日期, '%Y-%m') AS 订单日期, SUM(订单数量) AS 订单数量")
  423. ->where('Mod_rq', null) // 筛选 Mod_rq 为 null
  424. ->group('DATE_FORMAT(出库日期, "%Y-%m")') // 按年月分组
  425. ->select();
  426. // 2. 获取设备产量计酬表每月的包装数量(s_num)(近两年)
  427. $productionData = db('设备_产量计酬')
  428. ->field("DATE_FORMAT(sys_rq, '%Y-%m') AS 报工日期, SUM(s_num) AS 完工数量")
  429. ->where('工序名称', '包装') // 筛选工序名称为包装
  430. ->where('mod_rq', null) // 筛选 mod_rq 为 null
  431. ->group('DATE_FORMAT(sys_rq, "%Y-%m")') // 按年月分组
  432. ->select();
  433. // 将查询结果转换为数组,方便后续计算
  434. $orderDataMap = [];
  435. foreach ($orderData as $data) {
  436. $orderDataMap[$data['订单日期']] = $data['订单数量'];
  437. }
  438. $productionDataMap = [];
  439. foreach ($productionData as $data) {
  440. $productionDataMap[$data['报工日期']] = $data['完工数量'];
  441. }
  442. // 3. 计算每月的完成率并四舍五入
  443. foreach ($months as $month) {
  444. // 拼接当前月和上一年的年月
  445. $currentMonth = $currentYear . '-' . $month;
  446. $lastMonth = $lastYear . '-' . $month;
  447. // 获取当前月和上一年的订单数量和完工数量
  448. $totalOrdersCurrentYear = isset($orderDataMap[$currentMonth]) ? $orderDataMap[$currentMonth] : 0;
  449. $totalSNumCurrentYear = isset($productionDataMap[$currentMonth]) ? $productionDataMap[$currentMonth] : 0;
  450. $totalOrdersLastYear = isset($orderDataMap[$lastMonth]) ? $orderDataMap[$lastMonth] : 0;
  451. $totalSNumLastYear = isset($productionDataMap[$lastMonth]) ? $productionDataMap[$lastMonth] : 0;
  452. // 计算完成率,避免除以零,并四舍五入
  453. // $completionRateCurrentYear = $totalOrdersCurrentYear > 0 ? round(($totalSNumCurrentYear / $totalOrdersCurrentYear) * 100) : 0;
  454. // $completionRateLastYear = $totalOrdersLastYear > 0 ? round(($totalSNumLastYear / $totalOrdersLastYear) * 100) : 0;
  455. // 计算完成率,避免除以零,并限制最大值为 100%
  456. $completionRateCurrentYear = $totalOrdersCurrentYear > 0 ? min(round(($totalSNumCurrentYear / $totalOrdersCurrentYear) * 100), 100) : 0;
  457. $completionRateLastYear = $totalOrdersLastYear > 0 ? min(round(($totalSNumLastYear / $totalOrdersLastYear) * 100), 100) : 0;
  458. // 存储每个月的完成率
  459. $responseData['series'][0]['data'][$month - 1] = $completionRateLastYear;
  460. $responseData['series'][1]['data'][$month - 1] = $completionRateCurrentYear;
  461. }
  462. // 返回响应数据
  463. $response = [
  464. 'status' => 0,
  465. 'msg' => '',
  466. 'data' => $responseData
  467. ];
  468. return json($response);
  469. }
  470. /**
  471. * 年度客户订单数量汇总【接口】
  472. */
  473. public function getOrderSummaryKhStyle()
  474. {
  475. // 获取当前年份
  476. $last_year = date("Y");
  477. // 查询工单_基本资料表,按客户编号分组并计算订单数量的总和
  478. $result = \db('工单_基本资料')
  479. ->field('客户编号, SUM(订单数量) as 总订单数量') // 按客户编号分组并计算订单数量的总和
  480. ->where('Sys_rq', '>=', "$last_year-01-01 00:00:00") // 用 >= 和 <= 来代替 between,提高查询效率
  481. ->where('Sys_rq', '<=', "$last_year-12-31 23:59:59")
  482. ->whereNull('Mod_rq') // 确保 'Mod_rq' 为 null
  483. ->group('客户编号') // 按客户编号分组
  484. ->order('总订单数量 desc') // 按总订单数量降序排序
  485. ->cache(true, 60) // 添加缓存来减少数据库查询,60秒缓存一次
  486. ->select();
  487. // 如果没有数据,返回空结果
  488. if (empty($result)) {
  489. return json([
  490. 'status' => 0,
  491. 'msg' => '没有数据',
  492. 'data' => [
  493. 'columns' => [],
  494. 'rows' => []
  495. ]
  496. ]);
  497. }
  498. // 定义列格式
  499. $columns = [
  500. ['name' => '客户编号', 'id' => 'khbh', 'width' => '30', 'autoWrap' => "true", 'textAlign' => 'left'],
  501. ['name' => '总订单数量', 'id' => '总订单数量', 'width' => '30', 'autoWrap' => "true", 'textAlign' => 'left']
  502. ];
  503. // 格式化结果
  504. $rows = array_map(function ($item) {
  505. return [
  506. 'khbh' => $item['客户编号'],
  507. '总订单数量' => $item['总订单数量']
  508. ];
  509. }, $result);
  510. // 返回 JSON 格式的结果
  511. return json([
  512. 'status' => 0,
  513. 'msg' => '',
  514. 'data' => [
  515. 'columns' => $columns,
  516. 'rows' => $rows
  517. ]
  518. ]);
  519. }
  520. /**
  521. * 年度款式上下装数量汇总【接口】
  522. */
  523. public function jacket() {
  524. // 获取当前年份
  525. $last_year = date("Y");
  526. // 查询数据库,统计款式订单数量
  527. $row = \db('工单_基本资料')
  528. ->field('款式, COALESCE(SUM(订单数量), 0) as 总订单数量') // 避免 NULL 值
  529. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  530. ->whereNull('Mod_rq')
  531. ->group('款式') // 按款式分组
  532. ->order('总订单数量 desc') // 订单数量降序排列
  533. ->limit(20) // 取前 20 个热销款式
  534. ->select();
  535. // 定义表格列
  536. $result['columns'] = [
  537. ['name' => '分类', 'id' => 'fl', 'width' => '20', 'textAlign' => 'left'],
  538. ['name' => '款式', 'id' => 'ks', 'width' => '35', 'textAlign' => 'left'],
  539. ['name' => '总订单数量', 'id' => 'zds', 'width' => '25', 'textAlign' => 'left'],
  540. ];
  541. // 如果查询结果为空,返回空数据
  542. if (empty($row)) {
  543. return json([
  544. 'status' => 0,
  545. 'msg' => '没有数据',
  546. 'data' => $result
  547. ]);
  548. }
  549. // 分类关键词
  550. $upperKeywords = ['衣', '装', '夹', '衫', '甲', '外套']; // 上装
  551. $lowerKeywords = ['裤', '裙']; // 下装
  552. // 处理查询结果,添加分类信息
  553. foreach ($row as $k => $v) {
  554. $style = $v['款式'];
  555. $isUpper = $isLower = false; // 是否属于上装/下装
  556. // 判断款式分类
  557. if (preg_match('/(' . implode('|', $upperKeywords) . ')/u', $style)) {
  558. $isUpper = true;
  559. }
  560. if (preg_match('/(' . implode('|', $lowerKeywords) . ')/u', $style)) {
  561. $isLower = true;
  562. }
  563. // 归类
  564. if (strpos($style, '+') !== false) {
  565. $category = '套装';
  566. } elseif ($isUpper && $isLower) {
  567. $category = '全身';
  568. } elseif ($isUpper) {
  569. $category = '上装';
  570. } elseif ($isLower) {
  571. $category = '下装';
  572. } else {
  573. $category = '其他';
  574. }
  575. // 组装 `rows` 数据
  576. $result['rows'][$k]['ks'] = $style;
  577. $result['rows'][$k]['zds'] = $v['总订单数量'];
  578. $result['rows'][$k]['fl'] = $category;
  579. }
  580. $res['status'] = 0;
  581. $res['msg'] = '';
  582. $res['data'] = $result;
  583. return json($res);
  584. }
  585. /**第二屏*/
  586. /**
  587. * 每月各个小组生产报工走势【接口】
  588. * 统计每个工序小组的报工数据
  589. */
  590. public function Monthlyoutput_api() {
  591. $req = $this->request->param();
  592. if (isset($req['jtbh']) && !empty($req['jtbh'])){
  593. $jtbh = $req['jtbh'];
  594. } else {
  595. $this->error('参数错误');
  596. }
  597. $currentYear = date('Y'); // 当前年份
  598. $lastYear = $currentYear - 1; // 去年年份
  599. $months = ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
  600. $wheres['sczl_jtbh'] = ['like', '%' . $jtbh . '%']; // 查询上个月的数据
  601. // 查询数据库,按年份、月份和 jtbh 分组,获取近两年的数据
  602. $queryResult = \db('设备_产量计酬')
  603. ->field('
  604. YEAR(sys_rq) as year,
  605. DATE_FORMAT(sys_rq, "%m") as month,
  606. SUM(
  607. CASE
  608. WHEN 工序名称 IN ("裁剪", "车缝") THEN 数量
  609. ELSE s_num
  610. END
  611. ) as 报工数量,
  612. 工序名称,
  613. sczl_jtbh as jtbh
  614. ')
  615. ->where($wheres)
  616. ->whereNull('mod_rq')
  617. ->where('sys_rq', 'between', ["$lastYear-01-01 00:00:00", "$currentYear-12-31 23:59:59"])
  618. ->group('YEAR(sys_rq), DATE_FORMAT(sys_rq, "%m"), sczl_jtbh')
  619. ->select();
  620. // 初始化结果数组,分开存储2024年和2025年的数据
  621. $result = [
  622. "categories" => $months, // 月份
  623. "series" => [
  624. ["name" => "{$lastYear}年", "data" => array_fill(0, 12, 0)], // 2024年数据,初始化为0
  625. ["name" => "{$currentYear}年", "data" => array_fill(0, 12, 0)] // 2025年数据,初始化为0
  626. ]
  627. ];
  628. // 按年份分组数据
  629. $dataByYear = [
  630. $lastYear => array_fill(0, 12, 0), // 2024年的每月数据,初始化为0
  631. $currentYear => array_fill(0, 12, 0) // 2025年的每月数据,初始化为0
  632. ];
  633. // 将查询结果填充到对应的年份和月份
  634. foreach ($queryResult as $row) {
  635. $year = $row['year'];
  636. $month = (int)$row['month'] - 1; // 月份从0开始
  637. $sNumTotal = $row['报工数量'];
  638. // 合并相同年份和月份的数据
  639. if (isset($dataByYear[$year])) {
  640. $dataByYear[$year][$month] += $sNumTotal; // 这里是累加相同年月的数据
  641. }
  642. }
  643. // 将数据填充到结果中的 series 中
  644. foreach ($dataByYear as $year => $monthData) {
  645. foreach ($result['series'] as &$series) {
  646. if ($series['name'] == "{$year}年") {
  647. $series['data'] = $monthData;
  648. break;
  649. }
  650. }
  651. }
  652. // 返回结果
  653. return json([
  654. "status" => 0,
  655. "msg" => "",
  656. "data" => $result,
  657. ]);
  658. }
  659. /**第三屏*/
  660. /**
  661. * 计划中
  662. * */
  663. public function plan_api(){
  664. // 获取今年的年份
  665. $last_year = date("Y");
  666. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  667. $data = \db('工单_基本资料')
  668. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  669. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  670. ->whereNull('Mod_rq')
  671. ->group('gd_statu') // 按订单状态分组
  672. ->select();
  673. // 如果查询结果为空,设置一个默认值
  674. if (empty($data)) {
  675. $formattedData[] = [
  676. 'name' => ' ',
  677. 'value' => 0
  678. ];
  679. } else {
  680. // 否则根据查询结果格式化数据
  681. $formattedData[] = [
  682. 'name' => ' ',
  683. 'value' => isset($data[0]['订单数量']) ? $data[0]['订单数量'] : 0
  684. ];
  685. }
  686. // 返回 JSON 格式数据
  687. return json([
  688. "status" => 0,
  689. "msg" => "",
  690. "data" => $formattedData,
  691. ]);
  692. }
  693. /**
  694. * 生产中
  695. * */
  696. public function Production_api(){
  697. // 获取今年的年份
  698. $last_year = date("Y");
  699. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  700. $data = \db('工单_基本资料')
  701. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  702. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  703. ->whereNull('Mod_rq')
  704. ->group('gd_statu') // 按订单状态分组
  705. ->select();
  706. // 如果查询结果为空,设置一个默认值
  707. if (empty($data)) {
  708. $formattedData[] = [
  709. 'name' => ' ',
  710. 'value' => 0
  711. ];
  712. } else {
  713. // 否则根据查询结果格式化数据
  714. $formattedData[] = [
  715. 'name' => ' ',
  716. 'value' => isset($data[1]['订单数量']) ? $data[1]['订单数量'] : 0
  717. ];
  718. }
  719. // 返回 JSON 格式数据
  720. return json([
  721. "status" => 0,
  722. "msg" => "",
  723. "data" => $formattedData,
  724. ]);
  725. }
  726. /**
  727. * 已完工
  728. * */
  729. public function Completed_api(){
  730. // 获取今年的年份
  731. $last_year = date("Y");
  732. // 查询条件:Mod_rq为null且年份为今年的订单状态字段的数量
  733. $data = \db('工单_基本资料')
  734. ->field('gd_statu as 订单状态, COUNT(*) as 订单数量') // 统计每个订单状态的数量
  735. ->where('Sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"])
  736. ->whereNull('Mod_rq')
  737. ->group('gd_statu') // 按订单状态分组
  738. ->select();
  739. // 如果查询结果为空,设置一个默认值
  740. if (empty($data)) {
  741. $formattedData[] = [
  742. 'name' => ' ',
  743. 'value' => 0
  744. ];
  745. } else {
  746. // 否则根据查询结果格式化数据
  747. $formattedData[] = [
  748. 'name' => ' ',
  749. 'value' => isset($data[2]['订单数量']) ? $data[2]['订单数量'] : 0
  750. ];
  751. }
  752. // 返回 JSON 格式数据
  753. return json([
  754. "status" => 0,
  755. "msg" => "",
  756. "data" => $formattedData,
  757. ]);
  758. }
  759. /**
  760. * 统计当前小组正在生产某个工单
  761. * */
  762. public function group_api() {
  763. $last_year = date("Y");
  764. // 自定义小组排序规则
  765. $group_order = [
  766. '裁剪01组', '裁剪02组', '裁剪03组', '裁剪04组',
  767. '车缝01组', '车缝02组', '车缝03组', '车缝04组', '车缝05组', '车缝06组', '车缝07组', '车缝08组', '车缝09组', '车缝10组', '车缝11组', '车缝12组',
  768. '大办组', '美英组', '小芬组',
  769. '手工01组', '手工02组',
  770. '总检01组', '总检02组',
  771. '大烫01组',
  772. '包装01组', '包装02组'
  773. ];
  774. // 查询条件:按小组和订单编号分组,取最新一条记录
  775. $data = \db('设备_产量计酬')->alias('c')
  776. ->join('工单_基本资料 j', 'j.订单编号 = c.订单编号', 'LEFT')
  777. ->field([
  778. 'c.订单编号',
  779. 'j.客户编号',
  780. 'c.款号',
  781. 'c.尺码',
  782. Db::raw('CASE
  783. WHEN c.工序名称 IN ("裁剪", "车缝") THEN c.数量
  784. ELSE c.s_num
  785. END AS 数量'),
  786. 'c.工序名称',
  787. 'c.sczl_bh', // 小组名称
  788. 'c.sys_rq' // 时间字段
  789. ])
  790. ->group('c.订单编号, c.sczl_bh') // 按订单编号和小组分组,确保每个订单编号只出现一次
  791. ->order('c.sys_rq DESC') // 按时间倒序排序,确保取到最新的一条
  792. ->where('c.sys_rq', 'between', ["$last_year-01-01 00:00:00", "$last_year-12-31 23:59:59"]) // 时间过滤
  793. ->select();
  794. // 格式化数据,按小组取最新的一条工单
  795. $groupedData = [];
  796. foreach ($data as $item) {
  797. // 确保每个小组只有一条最新记录
  798. $groupedData[$item['sczl_bh']][] = [
  799. '订单编号' => $item['订单编号'],
  800. '客户编号' => $item['客户编号'],
  801. '款号' => $item['款号'],
  802. '尺码' => $item['尺码'],
  803. '数量' => $item['数量'],
  804. '工序名称' => $item['工序名称'],
  805. '小组' => $item['sczl_bh'],
  806. '时间' => $item['sys_rq'], // 记录时间
  807. ];
  808. }
  809. // 筛选每个小组的最新一条数据
  810. $latestData = [];
  811. foreach ($groupedData as $group => $groupItems) {
  812. // 只取最新一条记录
  813. $latestData[$group] = $groupItems[0]; // 因为数据是按时间降序排列的,所以取第一个就是最新的
  814. }
  815. // 对小组进行自定义排序
  816. uasort($latestData, function($a, $b) use ($group_order) {
  817. // 获取小组排序位置
  818. $a_index = array_search($a['小组'], $group_order);
  819. $b_index = array_search($b['小组'], $group_order);
  820. // 根据位置排序
  821. return $a_index - $b_index;
  822. });
  823. // 根据自定义列格式生成数据
  824. $result['columns'] = [
  825. // ['name' => '工序名称', 'id' => 'gxxm', 'width' => '10%', 'textAlign' => 'left'],
  826. ['name' => '小组', 'id' => 'xz', 'width' => '10', 'autoWrap' => "true",'textAlign' => 'left'],
  827. ['name' => '订单编号', 'id' => 'ddbh', 'width' => '14','autoWrap' => "true", 'textAlign' => 'left'],
  828. ['name' => '客户编号', 'id' => 'khbh', 'width' => '10','autoWrap' => "true", 'textAlign' => 'left'],
  829. ['name' => '款号', 'id' => 'kh', 'width' => '30', 'textAlign' => 'left'],
  830. ['name' => '尺码', 'id' => 'cm', 'width' => '7','autoWrap' => "true", 'textAlign' => 'left'],
  831. ['name' => '数量', 'id' => 'sl', 'width' => '7', 'autoWrap' => "true",'textAlign' => 'left'],
  832. ['name' => '时间', 'id' => 'sj', 'width' => '20','autoWrap' => "true", 'textAlign' => 'left'],
  833. ];
  834. // 将最新的数据填充到表格行中
  835. $rows = [];
  836. foreach ($latestData as $v) {
  837. $rows[] = [
  838. 'ddbh' => $v['订单编号'],
  839. 'khbh' => $v['客户编号'],
  840. 'kh' => $v['款号'],
  841. 'gxxm' => $v['工序名称'],
  842. 'xz' => $v['小组'],
  843. 'cm' => $v['尺码'],
  844. 'sl' => $v['数量'],
  845. 'sj' => $v['时间'],
  846. ];
  847. }
  848. // 如果没有数据,返回空行
  849. if (empty($rows)) {
  850. $rows[] = [
  851. 'ddbh' => '', 'khbh' => '', 'kh' => '', 'cm' => '', 'gxxm' => '', 'xz' => '', 'sl' => '', 'sj' => ''
  852. ];
  853. }
  854. // 返回最终结果
  855. $res['status'] = 0;
  856. $res['msg'] = '查询成功';
  857. $res['data'] = [
  858. 'columns' => $result['columns'],
  859. 'rows' => $rows
  860. ];
  861. return json($res);
  862. }
  863. /**
  864. * 在产订单工序详情【缓存】
  865. */
  866. public function getJhzByRedis(){
  867. //存缓存Redis
  868. $redis = redis();
  869. $redis_key = md5('getJhzByRedis');
  870. // 定义固定工序名称
  871. $processNames = ['裁剪', '车缝', '手工', '大烫', '总检', '包装'];
  872. // $startTime = date('Y-m-d', strtotime('-180 days'));
  873. $startTime = date('Y-m-01');
  874. $endTime = date('Y-m-d');
  875. $where['c.Sys_rq'] = ['between', [$startTime, $endTime]];
  876. $where['j.出库日期'] = ['<>', 'NULL'];
  877. $where['c.mod_rq'] = null;
  878. // 第一个查询:获取完工数量
  879. $list = \db('工单_基本资料')->alias('j')
  880. ->join('设备_产量计酬 c', 'j.订单编号 = c.订单编号', 'LEFT')
  881. ->field('c.订单编号, j.工单入仓数量, j.客户编号, j.生产款号, j.款式, c.工序名称,
  882. CASE
  883. WHEN 工序名称 IN ("裁剪", "车缝") THEN SUM(数量)
  884. ELSE SUM(s_num)
  885. END as 完工数量,
  886. j.gd_statu as 订单状态')
  887. ->where($where)
  888. ->group('c.订单编号, c.工序名称')
  889. ->order('c.订单编号 desc')
  890. ->having('完工数量 > 0')
  891. ->select();
  892. // 第二个查询:获取制单数
  893. $yjwhere['y.Mod_rq'] = null;
  894. $yjlist = \db('工单_基本资料')->alias('j')
  895. ->join('工单_印件资料 y', 'j.订单编号 = y.订单编号', 'LEFT')
  896. ->field('y.订单编号, SUM(y.zdtotal) as 制单数')
  897. ->where($yjwhere)
  898. ->group('y.订单编号')
  899. ->order('y.订单编号 desc')
  900. ->select();
  901. // 将制单数结果转换为以订单编号为键的数组,方便后续合并
  902. $yjlistIndexed = [];
  903. foreach ($yjlist as $yj) {
  904. $yjlistIndexed[$yj['订单编号']] = $yj['制单数'];
  905. }
  906. // 合并数据
  907. $mergedData = [];
  908. foreach ($list as $order) {
  909. $orderId = $order['订单编号'];
  910. // 初始化订单数据,如果还未存在
  911. if (!isset($mergedData[$orderId])) {
  912. // 获取制单数和已完工数量
  913. $zdTotal = $yjlistIndexed[$orderId] ?? 0; // 制单数
  914. $completedTotal = $order['工单入仓数量']; // 已完工数量
  915. // 计算完成百分比
  916. $completionPercentage = $zdTotal > 0 ? round(($completedTotal / $zdTotal) * 100, 2) . '%' : '0%';
  917. // 初始化订单数据
  918. $mergedData[$orderId] = [
  919. '订单编号' => $orderId,
  920. '客户编号' => $order['客户编号'],
  921. '生产款号' => $order['生产款号'],
  922. '款式' => $order['款式'],
  923. '订单状态' => $order['订单状态'],
  924. '已完工数量' => $completedTotal,
  925. '制单数' => $zdTotal,
  926. '完成百分比' => $completionPercentage, // 新增字段:完成百分比
  927. ];
  928. // 初始化所有工序的完工数量为空
  929. foreach ($processNames as $process) {
  930. $mergedData[$orderId][$process] = '';
  931. }
  932. }
  933. // 更新对应的工序名称和完工数量
  934. if (in_array($order['工序名称'], $processNames)) {
  935. $mergedData[$orderId][$order['工序名称']] = $order['完工数量'];
  936. }
  937. }
  938. foreach ($mergedData as $key => $order) {
  939. // 判断裁剪是否为空
  940. if (empty($order['裁剪'])) {
  941. unset($mergedData[$key]); // 如果裁剪为空,删除该订单
  942. }
  943. }
  944. // 转换合并后的数组格式
  945. $result = array_values($mergedData);
  946. $redis->set($redis_key, json_encode($result));
  947. echo date("Y-m-d H:i:s").'----存进去了';
  948. // return $result;
  949. }
  950. /**
  951. * 在产订单工序详情【接口】
  952. */
  953. public function getJhzBy(){
  954. $redis = redis();
  955. $row = json_decode($redis->get(md5('getJhzByRedis')), true);
  956. // 列定义
  957. $result['columns'] = [
  958. ['name' => '订单编号', 'id' => 'ddbh', 'width' => '7', 'textAlign' => 'left'],
  959. ['name' => '客户编号', 'id' => 'khbh', 'width' => '6','autoWrap' => "true", 'textAlign' => 'left'],
  960. ['name' => '生产款号', 'id' => 'sckh', 'width' => '12', 'textAlign' => 'left'],
  961. ['name' => '款式', 'id' => 'ks', 'width' => '10', 'textAlign' => 'left'],
  962. ['name' => '订单状态', 'id' => 'ddzt', 'width' => '6', 'textAlign' => 'left'],
  963. ['name' => '制单总数', 'id' => 'zds', 'width' => '6', 'textAlign' => 'left'],
  964. ['name' => '裁剪已完成', 'id' => 'cj', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  965. ['name' => '车缝已完成', 'id' => 'cf', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  966. ['name' => '手工已完成', 'id' => 'sg', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  967. ['name' => '大烫已完成', 'id' => 'dt', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  968. ['name' => '总检已完成', 'id' => 'zj', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  969. ['name' => '包装已完成', 'id' => 'bz', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  970. ['name' => '已完成数量', 'id' => 'ywgsl', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  971. ['name' => '完成百分比', 'id' => 'bfb', 'width' => '6','autoWrap'=>"true", 'textAlign' => 'left'],
  972. ];
  973. if ($row) {
  974. foreach ($row as $k => $v) {
  975. $result['rows'][$k]['ddbh'] = $v['订单编号'];
  976. $result['rows'][$k]['khbh'] = $v['客户编号'];
  977. $result['rows'][$k]['sckh'] = $v['生产款号'];
  978. $result['rows'][$k]['ks'] = $v['款式'];
  979. $result['rows'][$k]['ddzt'] = $v['订单状态'];
  980. // 工序数量字段,根据之前的定义调整字段名
  981. $result['rows'][$k]['cj'] = $v['裁剪'] ?? '';
  982. $result['rows'][$k]['cf'] = $v['车缝'] ?? '';
  983. $result['rows'][$k]['sg'] = $v['手工'] ?? '';
  984. $result['rows'][$k]['dt'] = $v['大烫'] ?? '';
  985. $result['rows'][$k]['zj'] = $v['总检'] ?? '';
  986. $result['rows'][$k]['bz'] = $v['包装'] ?? '';
  987. // 其他数量字段
  988. $result['rows'][$k]['ywgsl'] = $v['已完工数量'] ?? ''; // 示例字段,需确保与数据一致
  989. $result['rows'][$k]['zds'] = $v['制单数'] ?? ''; // 对应制单数
  990. $result['rows'][$k]['bfb'] = $v['完成百分比'] ?? ''; // 对应制单数
  991. }
  992. } else {
  993. // 如果没有数据,初始化空行
  994. $result['rows'][0] = [
  995. 'ddbh' => '', 'khbh' => '', 'sckh' => '', 'ks' => '', 'ddzt' => '',
  996. 'cj' => '', 'cf' => '', 'sg' => '', 'dt' => '', 'zj' => '', 'bz' => '',
  997. 'ywgsl' => '', 'zds' => ''
  998. ];
  999. }
  1000. // echo "<pre>";print_r($result);echo "<pre>";die;
  1001. $res['status'] = 0;
  1002. $res['msg'] = '';
  1003. $res['data'] = $result;
  1004. return json($res);
  1005. }
  1006. //下面接口已写好-----暂时未用到
  1007. /**
  1008. *当日班组报工产量【缓存】
  1009. * 建议缓存时间,5--10分钟自动更新一次
  1010. * 统计当天的各个小组报工完成数量
  1011. */
  1012. public function GroupProductionRedis() {
  1013. // 存缓存到 Redis
  1014. $redis = redis();
  1015. $redis_key = md5('GroupProductionRedis');
  1016. $today = date('Y-m-d'); // 获取今天的日期
  1017. $sevenDaysAgo = date('Y-m-d', strtotime('-6 days')); // 计算6天前的日期(包含今天共7天)
  1018. // 自定义需要显示的生产工序顺序
  1019. $customGroups = ['裁剪', '车缝', '手工', '大烫', '总检', '包装'];
  1020. // 获取所有设备资料,并按自定义工序顺序过滤
  1021. $Machine = db('设备_基本资料')
  1022. ->field('生产工序, 设备编组')
  1023. ->whereIn('生产工序', $customGroups)
  1024. ->select();
  1025. // 查询当天设备产量数据
  1026. $res = db('设备_产量计酬')->alias('c')
  1027. ->field([
  1028. 'c.sczl_bh',
  1029. // 使用 CASE 语句动态选择字段:裁剪和车缝使用数量,其他工序使用 s_num
  1030. Db::raw('CASE
  1031. WHEN c.工序名称 IN ("裁剪", "车缝") THEN c.数量
  1032. ELSE s_num
  1033. END AS 数量'),
  1034. 'c.工序名称',
  1035. 'c.sczl_jtbh',
  1036. 'c.sys_rq'
  1037. ])
  1038. ->where(function($query) {
  1039. // 过滤 mod_rq 为 NULL 或 空字符串的记录
  1040. $query->where('c.mod_rq', null)->whereOr('c.mod_rq', '');
  1041. })
  1042. ->where('c.sys_rq', '>=', $sevenDaysAgo . ' 00:00:00') // 从今天00:00开始
  1043. ->where('c.sys_rq', '<=', $today . ' 23:59:59') // 到今天23:59结束
  1044. ->select();
  1045. // 将合并后的数据存储到 Redis 中
  1046. $redis->set($redis_key, json_encode($res));
  1047. echo date("Y-m-d H:i:s") . ' 存进去了';
  1048. }
  1049. //车缝当日报工数量
  1050. public function GroupMachineCFyi()
  1051. {
  1052. $redis = redis(); // 连接 Redis
  1053. $row = json_decode($redis->get(md5('GroupProductionRedis')), true); // 从 Redis 获取数据
  1054. // 获取请求参数中的组别代码
  1055. $req = $this->request->param();
  1056. if (isset($req['jtbh']) && !empty($req['jtbh'])) {
  1057. $arr = $req['jtbh'];
  1058. } else {
  1059. $this->error('参数错误'); // 如果没有传递有效的组别代码,返回错误
  1060. }
  1061. // 获取当前日期
  1062. $today = date('Y-m-d');
  1063. $toYear = date('Y'); // 当前年份
  1064. // 获取七天前的日期
  1065. $sevenDaysAgo = date('Y-m-d', strtotime('-6 days'));
  1066. // 初始化分类和数据系列
  1067. $categories = []; // 存储七天的日期
  1068. $dataSeries = []; // 存储不同工序的数量汇总
  1069. // 获取近七天的日期数组(只取日期部分)
  1070. for ($i = 6; $i >= 0; $i--) {
  1071. $categories[] = date('d', strtotime("-{$i} days")); // 只取日期部分
  1072. }
  1073. // 遍历 Redis 获取的数据,筛选出符合条件的数据
  1074. foreach ($row as $data) {
  1075. // 检查组别代码是否匹配
  1076. if ($data['sczl_jtbh'] === $arr) {
  1077. $date = date('Y-m-d', strtotime($data['sys_rq'])); // 获取数据的日期
  1078. if ($date >= $sevenDaysAgo && $date <= $today) {
  1079. // 计算该日期在七天日期数组中的索引
  1080. $dateIndex = array_search(date('d', strtotime($date)), $categories);
  1081. if ($dateIndex !== false) {
  1082. // 根据工序名称汇总
  1083. $processName = $data['工序名称'];
  1084. // 如果工序名称还没在 $dataSeries 中创建,先初始化
  1085. if (!isset($dataSeries[$processName])) {
  1086. $dataSeries[$processName] = array_fill(0, 7, 0); // 初始化该工序的数据
  1087. }
  1088. // 累加数量
  1089. $dataSeries[$processName][$dateIndex] += $data['数量']; // 使用工序名称作为键名
  1090. }
  1091. }
  1092. }
  1093. }
  1094. // 如果没有任何数据,确保工序数据为默认值
  1095. if (empty($dataSeries)) {
  1096. // 如果没有数据,初始化默认工序并设置数据为0
  1097. $dataSeries = [
  1098. '默认工序' => array_fill(0, 7, 0)
  1099. ];
  1100. }
  1101. // 构建返回的数据格式
  1102. $seriesData = [];
  1103. foreach ($dataSeries as $processName => $values) {
  1104. $seriesData[] = [
  1105. 'name' => $processName, // 工序名称作为名称
  1106. 'data' => $values // 当前工序的数量数据
  1107. ];
  1108. }
  1109. $list = [
  1110. 'categories' => $categories, // 七天的日期
  1111. 'series' => $seriesData // 不同工序的数据
  1112. ];
  1113. // 返回 JSON 格式的结果
  1114. $res = [
  1115. 'status' => 0,
  1116. 'msg' => '',
  1117. 'data' => $list
  1118. ];
  1119. return json($res); // 返回最终的 JSON 数据
  1120. }
  1121. //板房车缝当日报工数量
  1122. public function GroupMachinebfCFyi()
  1123. {
  1124. $redis = redis();
  1125. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1126. // 初始化小组名称和数量
  1127. $categories = [];
  1128. $dataSeries = [];
  1129. // 遍历数据,找到所有工序名称为“车缝”的小组,且只包含“大办组”、“小芬组”、“美英组”
  1130. foreach ($row as $data) {
  1131. if ($data['工序名称'] === '车缝' && in_array($data['组别'], ['大办组', '小芬组', '美英组'])) {
  1132. $categories[] = $data['组别']; // 添加组别到分类中
  1133. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1134. }
  1135. }
  1136. // 构建输出数据格式
  1137. $list = [
  1138. 'categories' => $categories,
  1139. 'series' => [
  1140. [
  1141. 'name' => '完成',
  1142. 'data' => array_values($dataSeries) // 获取数量数组
  1143. ]
  1144. ]
  1145. ];
  1146. $res = [
  1147. 'status' => 0,
  1148. 'msg' => '',
  1149. 'data' => $list
  1150. ];
  1151. // 返回 JSON 格式的结果
  1152. return json($res);
  1153. }
  1154. //裁剪当日报工数量
  1155. public function GroupMachineCJyi()
  1156. {
  1157. $redis = redis();
  1158. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1159. // 初始化小组名称和数量
  1160. $categories = [];
  1161. $dataSeries = [];
  1162. // 遍历数据,找到所有工序名称为“车缝”的小组
  1163. foreach ($row as $data) {
  1164. if ($data['工序名称'] !== '车缝') {
  1165. $categories[] = $data['组别']; // 添加组别到分类中
  1166. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1167. }
  1168. }
  1169. // 构建输出数据格式
  1170. $list = [
  1171. 'categories' => $categories,
  1172. 'series' => [
  1173. [
  1174. 'name' => '完成',
  1175. 'data' => array_values($dataSeries) // 获取数量数组
  1176. ]
  1177. ]
  1178. ];
  1179. $res = [
  1180. 'status' => 0,
  1181. 'msg' => '',
  1182. 'data' => $list
  1183. ];
  1184. // 返回 JSON 格式的结果
  1185. return json($res);
  1186. }
  1187. //手工当日报工数量
  1188. public function GroupMachineSGyi()
  1189. {
  1190. $redis = redis();
  1191. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1192. // 初始化小组名称和数量
  1193. $categories = [];
  1194. $dataSeries = [];
  1195. // 遍历数据,找到所有工序名称为“车缝”的小组
  1196. foreach ($row as $data) {
  1197. if ($data['工序名称'] === '手工') {
  1198. $categories[] = $data['组别']; // 添加组别到分类中
  1199. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1200. }
  1201. }
  1202. // 构建输出数据格式
  1203. $list = [
  1204. 'categories' => $categories,
  1205. 'series' => [
  1206. [
  1207. 'name' => '完成',
  1208. 'data' => array_values($dataSeries) // 获取数量数组
  1209. ]
  1210. ]
  1211. ];
  1212. $res = [
  1213. 'status' => 0,
  1214. 'msg' => '',
  1215. 'data' => $list
  1216. ];
  1217. // 返回 JSON 格式的结果
  1218. return json($res);
  1219. }
  1220. //大烫当日报工数量
  1221. public function GroupMachineDTyi()
  1222. {
  1223. $redis = redis();
  1224. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1225. // 初始化小组名称和数量
  1226. $categories = [];
  1227. $dataSeries = [];
  1228. // 遍历数据,找到所有工序名称为“车缝”的小组
  1229. foreach ($row as $data) {
  1230. if ($data['工序名称'] === '大烫') {
  1231. $categories[] = $data['组别']; // 添加组别到分类中
  1232. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1233. }
  1234. }
  1235. // 构建输出数据格式
  1236. $list = [
  1237. 'categories' => $categories,
  1238. 'series' => [
  1239. [
  1240. 'name' => '完成',
  1241. 'data' => array_values($dataSeries) // 获取数量数组
  1242. ]
  1243. ]
  1244. ];
  1245. $res = [
  1246. 'status' => 0,
  1247. 'msg' => '',
  1248. 'data' => $list
  1249. ];
  1250. // 返回 JSON 格式的结果
  1251. return json($res);
  1252. }
  1253. //总检当日报工数量
  1254. public function GroupMachineZJyi()
  1255. {
  1256. $redis = redis();
  1257. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1258. // 初始化小组名称和数量
  1259. $categories = [];
  1260. $dataSeries = [];
  1261. // 遍历数据,找到所有工序名称为“车缝”的小组
  1262. foreach ($row as $data) {
  1263. if ($data['工序名称'] === '总检') {
  1264. $categories[] = $data['组别']; // 添加组别到分类中
  1265. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1266. }
  1267. }
  1268. // 构建输出数据格式
  1269. $list = [
  1270. 'categories' => $categories,
  1271. 'series' => [
  1272. [
  1273. 'name' => '完成',
  1274. 'data' => array_values($dataSeries) // 获取数量数组
  1275. ]
  1276. ]
  1277. ];
  1278. $res = [
  1279. 'status' => 0,
  1280. 'msg' => '',
  1281. 'data' => $list
  1282. ];
  1283. // 返回 JSON 格式的结果
  1284. return json($res);
  1285. }
  1286. //包装当日报工数量
  1287. public function GroupMachineBZyi()
  1288. {
  1289. $redis = redis();
  1290. $row = json_decode($redis->get(md5('GroupProductionRedis')), true);
  1291. // 初始化小组名称和数量
  1292. $categories = [];
  1293. $dataSeries = [];
  1294. // 遍历数据,找到所有工序名称为“车缝”的小组
  1295. foreach ($row as $data) {
  1296. if ($data['工序名称'] === '包装') {
  1297. $categories[] = $data['组别']; // 添加组别到分类中
  1298. $dataSeries[$data['组别']] = $data['数量']; // 更新小组数量
  1299. }
  1300. }
  1301. // 构建输出数据格式
  1302. $list = [
  1303. 'categories' => $categories,
  1304. 'series' => [
  1305. [
  1306. 'name' => '完成',
  1307. 'data' => array_values($dataSeries) // 获取数量数组
  1308. ]
  1309. ]
  1310. ];
  1311. $res = [
  1312. 'status' => 0,
  1313. 'msg' => '',
  1314. 'data' => $list
  1315. ];
  1316. // 返回 JSON 格式的结果
  1317. return json($res);
  1318. }
  1319. //自动生成面料以及调用---》GPT
  1320. public function GtpAiOrder()
  1321. {
  1322. $order = Request::instance()->get('订单编号');
  1323. // 判断是否有指定的订单号
  1324. if (!empty($order)) {
  1325. // 查询单个订单的最大编号
  1326. $maxOrder = \db('工单_基本资料')
  1327. ->where('订单编号', 'like', "{$order}%")
  1328. ->order('订单编号', 'desc')
  1329. ->limit(1)
  1330. ->value('订单编号');
  1331. // 查询该订单的基本资料
  1332. $list = \db('工单_基本资料')
  1333. ->where('订单编号', 'like', "{$order}%")
  1334. ->order('订单编号', 'desc')
  1335. ->limit(1)
  1336. ->find();
  1337. // 如果面料数据为空,提示错误
  1338. if (empty($list['面料'])) {
  1339. $this->error('面料数据为空无法定义BOM');
  1340. }
  1341. // 处理订单编号
  1342. $numericPart = substr($maxOrder, 2);
  1343. $newNumericPart = str_pad((int)$numericPart + 1, strlen($numericPart), '0', STR_PAD_LEFT);
  1344. $param['订单编号'] = $order . $newNumericPart;
  1345. // 处理物料信息
  1346. $massage = empty($list['粘衬']) || $list['粘衬'] == '无' ? $list['面料'] : $list['面料'] . ',粘衬:' . $list['粘衬'];
  1347. $mianliao = $this->Gpt($massage);
  1348. // 插入物料数据
  1349. $data = [];
  1350. foreach ($mianliao as $key => $value) {
  1351. if (!empty($value) && $value !== '粘衬') { // 排除空值和粘衬
  1352. $data[] = [
  1353. 'BOM_工单编号' => $list['订单编号'],
  1354. 'BOM_物料名称' => $value,
  1355. 'Sys_rq' => date('Y-m-d H:i:s'),
  1356. 'Sys_ID' => '超级管理员'
  1357. ];
  1358. }
  1359. }
  1360. // 批量插入BOM资料
  1361. if (!empty($data)) {
  1362. \db('工单_bom资料')->insertAll($data);
  1363. }
  1364. $this->success('成功', $order);
  1365. } else {
  1366. // 如果没有指定订单号,批量查询订单号并处理
  1367. $has_bom = \db('工单_bom资料')->alias('a')->field('a.BOM_工单编号')->group('a.BOM_工单编号')->select();
  1368. $all_orders = \db('工单_基本资料')->alias('a')->field('a.订单编号')->where('a.面料', '<>', '')->group('a.订单编号')->select();
  1369. // 提取有BOM资料的订单号
  1370. $has_bom_orders = array_column($has_bom, 'BOM_工单编号');
  1371. // 筛选出没有对应BOM资料的订单号
  1372. $no_bom_orders = array_filter($all_orders, function ($order) use ($has_bom_orders) {
  1373. return !in_array($order['订单编号'], $has_bom_orders);
  1374. });
  1375. // 统计成功更新的订单编号
  1376. $successOrders = [];
  1377. // 每次处理五个订单号
  1378. $batchSize = 5;
  1379. $totalOrders = count($no_bom_orders);
  1380. $batches = array_chunk($no_bom_orders, $batchSize); // 将订单分批
  1381. foreach ($batches as $batch) {
  1382. foreach ($batch as $orderData) {
  1383. // 获取该订单号的最大订单编号
  1384. $maxOrder = \db('工单_基本资料')
  1385. ->where('订单编号', 'like', "{$orderData['订单编号']}%")
  1386. ->order('订单编号', 'desc')
  1387. ->limit(1)
  1388. ->value('订单编号');
  1389. // 获取该订单号的具体数据
  1390. $list = \db('工单_基本资料')
  1391. ->where('订单编号', 'like', "{$orderData['订单编号']}%")
  1392. ->order('订单编号', 'desc')
  1393. ->limit(1)
  1394. ->find();
  1395. if (empty($list['面料'])) {
  1396. $this->error("订单 {$orderData['订单编号']} 面料数据为空,无法定义BOM");
  1397. }
  1398. // 处理订单编号
  1399. $numericPart = substr($maxOrder, 2);
  1400. $newNumericPart = str_pad((int)$numericPart + 1, strlen($numericPart), '0', STR_PAD_LEFT);
  1401. $param['订单编号'] = $order . $newNumericPart;
  1402. // 处理物料信息
  1403. $massage = empty($list['粘衬']) || $list['粘衬'] == '无' ? $list['面料'] : $list['面料'] . ',粘衬:' . $list['粘衬'];
  1404. $mianliao = $this->Gpt($massage);
  1405. // 插入物料数据
  1406. $data = [];
  1407. foreach ($mianliao as $key => $value) {
  1408. if (!empty($value) && $value !== '粘衬') { // 排除空值和粘衬
  1409. $data[] = [
  1410. 'BOM_工单编号' => $list['订单编号'],
  1411. 'BOM_物料名称' => $value,
  1412. 'Sys_rq' => date('Y-m-d H:i:s'),
  1413. 'Sys_ID' => '超级管理员'
  1414. ];
  1415. }
  1416. }
  1417. // 批量插入BOM资料
  1418. if (!empty($data)) {
  1419. \db('工单_bom资料')->insertAll($data);
  1420. // 记录成功的订单编号
  1421. $successOrders[] = $orderData['订单编号'];
  1422. }
  1423. }
  1424. }
  1425. // 打印成功更新的订单编号
  1426. $this->success('成功更新的订单编号:' . implode(', ', $successOrders));
  1427. }
  1428. }
  1429. //GPT
  1430. public function Gpt($massage)
  1431. {
  1432. // 设置 API 密钥
  1433. $apiKey = 'sk-e0JuPjMntkbgi1BoMjrqyyzMKzAxILkQzyGMSy3xiMupuoWY'; // 替换为您的 API 密钥
  1434. // 要发送给 GPT 的消息
  1435. $messages = [
  1436. [
  1437. 'role' => 'user',
  1438. 'content' => '你好,帮我按照:面料1、面料2、面料3……来整理归纳下面的面料信息,我只需要面料信息,不需要其他:'.$massage
  1439. ]
  1440. ];
  1441. // 创建请求数据
  1442. $data = [
  1443. 'model' => 'gpt-3.5-turbo', // 使用的模型
  1444. 'messages' => $messages,
  1445. 'max_tokens' => 100, // 设置最大 token 数
  1446. ];
  1447. // 初始化 cURL
  1448. $ch = curl_init('https://niubi.zeabur.app/v1/chat/completions');
  1449. // 设置 cURL 选项
  1450. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  1451. curl_setopt($ch, CURLOPT_HTTPHEADER, [
  1452. 'Content-Type: application/json',
  1453. 'Authorization: Bearer ' . $apiKey,
  1454. ]);
  1455. curl_setopt($ch, CURLOPT_POST, true);
  1456. curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  1457. curl_setopt($ch, CURLOPT_CAINFO, ROOT_PATH . '/public/uploads/cacert.pem');
  1458. // 执行请求
  1459. $response = curl_exec($ch);
  1460. // 检查错误
  1461. if (curl_errno($ch)) {
  1462. echo 'Error:' . curl_error($ch);
  1463. }
  1464. // 关闭 cURL
  1465. curl_close($ch);
  1466. // 解析和输出响应
  1467. $responseData = json_decode($response, true);
  1468. // 获取 GPT 的回复
  1469. if (isset($responseData['choices'][0]['message']['content'])) {
  1470. //获取返回内容
  1471. $gptReply = $responseData['choices'][0]['message']['content'];
  1472. // halt($gptReply);
  1473. //返回面料信息
  1474. $gptArray = explode('面料',$gptReply);
  1475. array_shift($gptArray);
  1476. foreach ($gptArray as $key=>$value){
  1477. $gptArray[$key] = preg_replace('/\s+/', '', substr($value,4));
  1478. }
  1479. return $gptArray;
  1480. } else {
  1481. echo "未能获取 GPT 的回复。";
  1482. }
  1483. }
  1484. }