Product.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use \think\Request;
  5. use \think\Db;
  6. use think\Cache;
  7. use function fast\e;
  8. /**
  9. * 产品资料
  10. */
  11. class Product extends Api
  12. {
  13. protected $noNeedLogin = ['*'];
  14. protected $noNeedRight = ['*'];
  15. /**
  16. * 首页
  17. */
  18. public function index()
  19. {
  20. $this->success('产品_基本资料');
  21. }
  22. /**
  23. * 获取左侧菜单产品分类列表
  24. * 按 product_type 分组 → 分类下显示对应产品
  25. */
  26. public function ProductTypeMenu()
  27. {
  28. if (Request::instance()->isGet() == false) {
  29. $this->error('非法请求');
  30. }
  31. $params = Request::instance()->param();
  32. // 获取所有产品
  33. $productList = \db('产品_基本资料')->whereNull('mod_rq')
  34. ->column('id,product_code,product_name,product_type');
  35. $data = [];
  36. if ($productList) {
  37. foreach ($productList as $item) {
  38. $type = $item['product_type'] ?: '未分类';
  39. // 分类
  40. $data[$type]['name'] = $type;
  41. // 分类下的产品
  42. $data[$type]['list'][] = [
  43. 'id' => $item['id'],
  44. 'product_code' => $item['product_code'],
  45. 'product_name' => $item['product_name']
  46. ];
  47. }
  48. }
  49. // 转成索引数组返回
  50. $result = array_values($data);
  51. $this->success('获取成功', $result);
  52. }
  53. /**
  54. * 获取产品资料列表(产品→部件→工艺)
  55. */
  56. public function ProductList()
  57. {
  58. if (!Request::instance()->isGet()) {
  59. $this->error('非法请求');
  60. }
  61. $params = Request::instance()->param();
  62. $where = [];
  63. if (!empty($params['search'])) {
  64. $where['product_code|product_name|product_type'] = ['like', '%' . $params['search'] . '%'];
  65. }
  66. $limit = empty($params['limit']) ? 30 : $params['limit'];
  67. $pages = empty($params['page']) ? 1 : $params['page'];
  68. // 1. 查询产品主表
  69. $productList = db('产品_基本资料')
  70. ->whereNull('mod_rq')
  71. ->where($where)
  72. ->page($pages, $limit)
  73. ->order('id desc')
  74. ->select();
  75. if (empty($productList)) {
  76. $this->success('获取成功', ['list' => [], 'count' => 0]);
  77. }
  78. // 提取产品编号
  79. $productCodes = array_column($productList, 'product_code');
  80. // 2. 查询部件(按 product_code 关联,并按 part_sort 排序)
  81. $parts = db('产品_部件资料')
  82. ->whereNull('mod_rq')
  83. ->whereIn('product_code', $productCodes)
  84. ->order('part_sort asc') // 按部件排序号升序
  85. ->select();
  86. // 提取 (product_code + part_sort) 作为关联键
  87. $partKeys = [];
  88. foreach ($parts as $p) {
  89. $key = $p['product_code'] . '_' . $p['part_sort'];
  90. $partKeys[] = $key;
  91. }
  92. // 3. 查询工艺(按 product_code + part_sort 关联,并按 gy_sort 排序)
  93. $process = [];
  94. if (!empty($productCodes)) {
  95. $process = db('产品_工艺资料')
  96. ->whereNull('mod_rq')
  97. ->whereIn('product_code', $productCodes)
  98. ->order('part_sort asc, gy_sort asc') // 按部件排序+工序排序
  99. ->select();
  100. }
  101. // 部件按 product_code 分组
  102. $partGroup = [];
  103. foreach ($parts as $val) {
  104. $partGroup[$val['product_code']][] = $val;
  105. }
  106. // 工艺按 (product_code + part_sort) 分组
  107. $processGroup = [];
  108. foreach ($process as $val) {
  109. $key = $val['product_code'] . '_' . $val['part_sort'];
  110. $processGroup[$key][] = $val;
  111. }
  112. // 组装数据:产品 → 部件 → 工艺
  113. foreach ($productList as &$product) {
  114. $currentParts = $partGroup[$product['product_code']] ?? [];
  115. foreach ($currentParts as &$item) {
  116. // 用 product_code + part_sort 关联工艺
  117. $key = $product['product_code'] . '_' . $item['part_sort'];
  118. $item['processes'] = $processGroup[$key] ?? [];
  119. }
  120. $product['parts'] = $currentParts;
  121. }
  122. // 统计总数
  123. $count = db('产品_基本资料')
  124. ->whereNull('mod_rq')
  125. ->where($where)
  126. ->count();
  127. $this->success('获取成功', [
  128. 'list' => $productList,
  129. 'count' => $count
  130. ]);
  131. }
  132. /**
  133. * 新增产品资料
  134. */
  135. public function ProductAdd()
  136. {
  137. if (!Request::instance()->isPost()) {
  138. $this->error('非法请求');
  139. }
  140. $params = Request::instance()->param();
  141. // 自动生成产品编号:CP000001
  142. $lastCode = \db('产品_基本资料')->order('id desc')->value('product_code');
  143. if ($lastCode) {
  144. $num = intval(str_replace('CP', '', $lastCode)) + 1;
  145. } else {
  146. $num = 1;
  147. }
  148. $params['product_code'] = 'CP' . str_pad($num, 6, '0', STR_PAD_LEFT);
  149. $data = [];
  150. $data['product_code'] = $params['product_code'];
  151. $data['product_name'] = $params['product_name'];
  152. $data['product_type'] = $params['product_type'];
  153. $data['unit'] = $params['unit'];
  154. $data['sys_id'] = $params['sys_id'];
  155. $data['status'] = 1;
  156. $data['sys_rq'] = date('Y-m-d H:i:s');
  157. $result = \db('产品_基本资料')->insert($data);
  158. if ($result) {
  159. $this->success('新增成功');
  160. } else {
  161. $this->error('新增失败');
  162. }
  163. }
  164. /**
  165. * 修改产品资料
  166. */
  167. public function ProductEdit()
  168. {
  169. if (!Request::instance()->isPost()) {
  170. $this->error('非法请求');
  171. }
  172. $params = Request::instance()->param();
  173. if (empty($params['id'])) {
  174. $this->error('请选择数据');
  175. }
  176. // 禁止修改编号
  177. unset($params['product_code']);
  178. $data = [];
  179. $data['product_name'] = $params['product_name'];
  180. $data['product_type'] = $params['product_type'];
  181. $data['unit'] = $params['unit'];
  182. $data['sys_id'] = $params['sys_id'];
  183. $data['updatetime'] = date('Y-m-d H:i:s');
  184. $result = \db('产品_基本资料')
  185. ->where('id', $params['id'])
  186. ->update($data);
  187. if ($result !== false) {
  188. $this->success('修改成功');
  189. } else {
  190. $this->error('修改失败');
  191. }
  192. }
  193. /**
  194. * 删除产品资料
  195. */
  196. public function ProductDelete()
  197. {
  198. if (!Request::instance()->isPost()) {
  199. $this->error('非法请求');
  200. }
  201. $id = input('id');
  202. if (empty($id)) {
  203. $this->error('请选择需要删除的数据');
  204. }
  205. $ids = explode(',', $id);
  206. $result = \db('产品_基本资料')
  207. ->where('id', 'in', $ids)
  208. ->update(['mod_rq' => date('Y-m-d H:i:s')]);
  209. if ($result !== false) {
  210. $this->success('删除成功');
  211. } else {
  212. $this->error('删除失败');
  213. }
  214. }
  215. /**
  216. * 获取产品部件列表
  217. */
  218. public function ProductPartList()
  219. {
  220. if (Request::instance()->isGet() == false) {
  221. $this->error('非法请求');
  222. }
  223. $params = Request::instance()->param();
  224. $where = [];
  225. if (!empty($params['search'])) {
  226. $where['part_name'] = array('like', '%' . $params['search'] . '%');
  227. }
  228. if (!empty($params['product_code'])) {
  229. $where['product_code'] = array('like', '%' . $params['product_code'] . '%');
  230. }
  231. $limit = $params['limit'];
  232. if (empty($limit)) {
  233. $limit = 30;
  234. }
  235. $pages = $params['page'];
  236. if (empty($pages)) {
  237. $pages = 1;
  238. }
  239. $list = \db('产品_部件资料')->whereNull('mod_rq')->where($where)->page($pages)->limit($limit)->order('id desc')->select();
  240. $count = \db('产品_部件资料')->whereNull('mod_rq')->where($where)->page($pages)->limit($limit)->count();
  241. $this->success('获取成功', ['list' => $list, 'count' => $count]);
  242. }
  243. /**
  244. * 新增部件资料(支持批量)
  245. */
  246. public function PartAdd()
  247. {
  248. if (!Request::instance()->isPost()) {
  249. $this->error('非法请求');
  250. }
  251. $params = Request::instance()->param();
  252. // 必传校验
  253. if (empty($params['product_code']) || empty($params['part_list'])) {
  254. $this->error('产品编号/部件列表不能为空');
  255. }
  256. $productCode = $params['product_code'];
  257. $sysId = $params['sys_id'];
  258. $partList = $params['part_list'];
  259. // 组装批量数据
  260. $insertData = [];
  261. foreach ($partList as $item) {
  262. if (empty($item['part_name']) || empty($item['part_sort'])) {
  263. continue; // 跳过无效数据
  264. }
  265. $insertData[] = [
  266. 'product_code' => $productCode,
  267. 'part_sort' => $item['part_sort'],
  268. 'part_name' => $item['part_name'],
  269. 'sys_id' => $sysId,
  270. 'sys_rq' => date('Y-m-d H:i:s'),
  271. 'mod_rq' => null
  272. ];
  273. }
  274. if (empty($insertData)) {
  275. $this->error('无有效部件数据');
  276. }
  277. $res = db('产品_部件资料')->insertAll($insertData);
  278. return $res ? $this->success('新增成功') : $this->error('新增失败');
  279. }
  280. /**
  281. * 修改部件资料
  282. */
  283. public function PartEdit()
  284. {
  285. if (!Request::instance()->isPost()) {
  286. $this->error('非法请求');
  287. }
  288. $params = Request::instance()->param();
  289. // 必传校验
  290. if (empty($params['id']) || empty($params['part_name'])) {
  291. $this->error('ID/部件名称不能为空');
  292. }
  293. $data = [
  294. 'part_name' => $params['part_name'],
  295. 'sys_id' => $params['sys_id'],
  296. 'updatetime' => date('Y-m-d H:i:s')
  297. ];
  298. $res = db('产品_部件资料')
  299. ->where('id', $params['id'])
  300. ->whereNull('mod_rq')
  301. ->update($data);
  302. return $res !== false ? $this->success('修改成功') : $this->error('修改失败');
  303. }
  304. /**
  305. * 删除部件资料
  306. */
  307. public function PartDelete()
  308. {
  309. if (!Request::instance()->isPost()) {
  310. $this->error('非法请求');
  311. }
  312. $id = input('id');
  313. if (empty($id)) {
  314. $this->error('请选择需要删除的数据');
  315. }
  316. $ids = explode(',', $id);
  317. $result = \db('产品_部件资料')
  318. ->where('id', 'in', $ids)
  319. ->update(['mod_rq' => date('Y-m-d H:i:s')]);
  320. if ($result !== false) {
  321. $this->success('删除成功');
  322. } else {
  323. $this->error('删除失败');
  324. }
  325. }
  326. /**
  327. * 获取产品工艺列表
  328. */
  329. public function ProductGyList()
  330. {
  331. if (!Request::instance()->isGet()) {
  332. $this->error('非法请求');
  333. }
  334. $params = Request::instance()->param();
  335. $where = [];
  336. if (!empty($params['search'])) {
  337. $where['a.gy_name'] = ['like', '%' . $params['search'] . '%'];
  338. }
  339. if (!empty($params['product_code'])) {
  340. $where['a.product_code'] = $params['product_code'];
  341. }
  342. $limit = empty($params['limit']) ? 30 : $params['limit'];
  343. $pages = empty($params['page']) ? 1 : $params['page'];
  344. //获取产品_工艺数据
  345. $list = \db('产品_工艺资料')->alias('a')
  346. ->join('产品_部件资料 b', 'a.product_code = b.product_code AND a.part_sort = b.part_sort', 'LEFT')
  347. ->field('
  348. a.id,
  349. a.product_code,
  350. a.part_sort,
  351. a.gy_sort,
  352. a.gy_name,
  353. a.big_process,
  354. a.standard_hour,
  355. a.standard_score,
  356. a.difficulty_coef,
  357. a.sys_id,
  358. a.sys_rq,
  359. a.updatetime,
  360. b.part_name
  361. ')
  362. ->whereNull('a.mod_rq')
  363. ->whereNull('b.mod_rq')
  364. ->where($where)
  365. ->page($pages, $limit)
  366. ->order('a.part_sort asc, a.id asc')
  367. ->select();
  368. //统计总数量
  369. $count = \db('产品_工艺资料')->alias('a')
  370. ->join('产品_部件资料 b', 'a.product_code = b.product_code AND a.part_sort = b.part_sort', 'LEFT')
  371. ->whereNull('a.mod_rq')
  372. ->whereNull('b.mod_rq')
  373. ->where($where)
  374. ->count();
  375. $this->success('获取成功', [
  376. 'list' => $list,
  377. 'count' => $count
  378. ]);
  379. }
  380. /**
  381. * 新增工艺资料(批量)
  382. */
  383. public function ProcessAdd()
  384. {
  385. if (!Request::instance()->isPost()) {
  386. $this->error('非法请求');
  387. }
  388. $params = Request::instance()->param();
  389. $sys_id = $params['sys_id'];
  390. $process_list = $params['process_list'] ?? [];
  391. if (empty($process_list)) {
  392. $this->error('工艺数据不能为空');
  393. }
  394. $insertData = [];
  395. foreach ($process_list as $item) {
  396. // 必传校验
  397. if (empty($item['gy_name']) || empty($item['big_process'])) {
  398. continue;
  399. }
  400. $insertData[] = [
  401. 'product_code' => $item['product_code'],
  402. 'part_sort' => $item['part_sort'],
  403. 'part_name' => $item['part_name'],
  404. 'gy_sort' => $item['gy_sort'],
  405. 'gy_name' => $item['gy_name'],
  406. 'big_process' => $item['big_process'],
  407. 'standard_hour' => $item['standard_hour'] ?? 0,
  408. 'standard_score' => $item['standard_score'] ?? 0,
  409. 'difficulty_coef' => $item['difficulty_coef'] ?? 1,
  410. 'sys_id' => $sys_id,
  411. 'sys_rq' => date('Y-m-d H:i:s')
  412. ];
  413. }
  414. if (empty($insertData)) {
  415. $this->error('无有效工艺数据');
  416. }
  417. $result = db('产品_工艺资料')->insertAll($insertData);
  418. return $result ? $this->success('新增成功') : $this->error('新增失败');
  419. }
  420. /**
  421. * 修改工艺资料
  422. */
  423. public function ProcessEdit()
  424. {
  425. if (!Request::instance()->isPost()) {
  426. $this->error('非法请求');
  427. }
  428. $params = Request::instance()->param();
  429. //echo "<pre>";
  430. //print_r($params);
  431. //echo "<pre>";die;
  432. if (empty($params['id']) || empty($params['gy_name'])) {
  433. $this->error('ID/工序名称不能为空');
  434. }
  435. $data = [
  436. 'gy_name' => $params['gy_name'],
  437. 'big_process' => $params['big_process'],
  438. // 'part_sort' => $params['part_sort'],
  439. 'gy_sort' => $params['gy_sort'],
  440. 'standard_hour' => $params['standard_hour'] ?? 0,
  441. 'standard_score' => $params['standard_score'] ?? 0,
  442. 'difficulty_coef' => $params['difficulty_coef'] ?? 1,
  443. 'sys_id' => $params['sys_id'],
  444. 'updatetime' => date('Y-m-d H:i:s')
  445. ];
  446. $res = db('产品_工艺资料')
  447. ->where('id', $params['id'])
  448. ->whereNull('mod_rq')
  449. ->update($data);
  450. return $res !== false ? $this->success('修改成功') : $this->error('修改失败');
  451. }
  452. /**
  453. * 删除工艺资料
  454. */
  455. public function ProcessDelete()
  456. {
  457. if (!Request::instance()->isPost()) {
  458. $this->error('非法请求');
  459. }
  460. $id = input('id');
  461. if (empty($id)) {
  462. $this->error('请选择需要删除的数据');
  463. }
  464. $ids = explode(',', $id);
  465. $result = \db('产品_工艺资料')
  466. ->where('id', 'in', $ids)
  467. ->update(['mod_rq' => date('Y-m-d H:i:s')]);
  468. if ($result !== false) {
  469. $this->success('删除成功');
  470. } else {
  471. $this->error('删除失败');
  472. }
  473. }
  474. /**
  475. * 调整部件与工艺序号牌组
  476. */
  477. public function UpdataSort(){
  478. if (!Request::instance()->isPost()) {
  479. $this->error('非法请求');
  480. }
  481. $params = Request::instance()->param();
  482. $product_code = $params['product_code'];
  483. $sys_id = $params['sys_id'];
  484. if (empty($product_code)) {
  485. $this->error('产品编号不能为空');
  486. }
  487. // ======================
  488. // 更新 产品_部件资料
  489. // ======================
  490. if (!empty($params['part_list']) && is_array($params['part_list'])) {
  491. foreach ($params['part_list'] as $item) {
  492. $id = $item['id'] ?? 0;
  493. if ($id <= 0) continue;
  494. // 🔥 把要更新的内容放变量里
  495. $updateData = [
  496. 'part_sort' => $item['part_sort'],
  497. 'part_name' => $item['part_name'],
  498. 'sys_id' => $sys_id
  499. ];
  500. Db::name('产品_部件资料')
  501. ->where('id', $id)
  502. ->update($updateData);
  503. }
  504. }
  505. // ======================
  506. // 更新 产品_工艺资料
  507. // ======================
  508. if (!empty($params['process_list']) && is_array($params['process_list'])) {
  509. foreach ($params['process_list'] as $item) {
  510. $id = $item['id'] ?? 0;
  511. if ($id <= 0) continue;
  512. // 🔥 把要更新的内容放变量里
  513. $updateData = [
  514. 'gy_sort' => $item['gy_sort'],
  515. 'gy_name' => $item['gy_name'] ,
  516. 'big_process' => $item['big_process'],
  517. 'standard_hour' => $item['standard_hour'],
  518. 'standard_score' => $item['standard_score'],
  519. 'part_sort' => $item['part_sort'],
  520. 'part_name' => $item['part_name'],
  521. 'sys_id' => $sys_id
  522. ];
  523. Db::name('产品_工艺资料')
  524. ->where('id', $id)
  525. ->update($updateData);
  526. }
  527. }
  528. $this->success('排序更新成功');
  529. }
  530. /**
  531. * Excel 导入 部件 + 工艺
  532. */
  533. public function ProcessExcel(){
  534. if (!Request::instance()->isPost()) {
  535. $this->error('非法请求');
  536. }
  537. $params = Request::instance()->param();
  538. $file = request()->file('file');
  539. // 1. 先判断文件是否存在
  540. if (empty($file)) {
  541. $this->error('请上传Excel文件');
  542. }
  543. // 2. 必传参数校验
  544. $product_code = $params['product_code'];
  545. $sys_id = $params['sys_id'];
  546. if (empty($product_code)) {
  547. $this->error('请选择产品后,再进行提交');
  548. }
  549. // 3. 正确获取文件扩展名(解决 getExtension 为空的问题)
  550. $fileInfo = $file->getInfo();
  551. $fileName = $fileInfo['name'];
  552. $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
  553. if (!in_array($ext, ['xlsx', 'xls'])) {
  554. $this->error('只支持 xls / xlsx 格式');
  555. }
  556. $file_path = $file->getRealPath();
  557. $data = [];
  558. if ($ext == 'xlsx') {
  559. $data = $this->readXlsx($file_path);
  560. } elseif ($ext == 'xls') {
  561. $data = $this->readXls($file_path);
  562. }
  563. // 4. 解析数据
  564. $rows = array_slice($data, 1);
  565. $insert_data = [];
  566. foreach ($rows as $row) {
  567. $part_name = trim($row[0] ?? '');
  568. $gy_name = trim($row[1] ?? '');
  569. if (empty($part_name) || empty($gy_name)) continue;
  570. $insert_data[] = [
  571. 'part_name' => $part_name,
  572. 'gy_name' => $gy_name,
  573. 'big_process' => trim($row[2] ?? ''),
  574. 'standard_hour' => floatval($row[3] ?? 0),
  575. 'standard_score' => floatval($row[4] ?? 0),
  576. 'difficulty_coef' => floatval($row[5] ?? 1),
  577. ];
  578. }
  579. if (empty($insert_data)) {
  580. $this->error('Excel 无有效数据');
  581. }
  582. // 5. 处理部件
  583. $part_map = [];
  584. $part_sort = 1;
  585. foreach ($insert_data as $item) {
  586. $name = $item['part_name'];
  587. if (!isset($part_map[$name])) {
  588. $part_map[$name] = $part_sort++;
  589. }
  590. }
  591. $part_all = [];
  592. foreach ($part_map as $name => $sort) {
  593. $part_all[] = [
  594. 'product_code' => $product_code,
  595. 'part_sort' => $sort,
  596. 'part_name' => $name,
  597. 'sys_id' => $sys_id,
  598. 'sys_rq' => date('Y-m-d H:i:s'),
  599. 'mod_rq' => null
  600. ];
  601. }
  602. // 6. 处理工艺
  603. $gy_sort_map = [];
  604. $process_all = [];
  605. foreach ($insert_data as $item) {
  606. $part_sort = $part_map[$item['part_name']];
  607. $gy_sort_map[$part_sort] = isset($gy_sort_map[$part_sort]) ? $gy_sort_map[$part_sort] + 1 : 1;
  608. $process_all[] = [
  609. 'product_code' => $product_code,
  610. 'part_sort' => $part_sort,
  611. 'part_name' => $item['part_name'],
  612. 'gy_sort' => $gy_sort_map[$part_sort],
  613. 'gy_name' => $item['gy_name'],
  614. 'big_process' => $item['big_process'],
  615. 'standard_hour' => $item['standard_hour'],
  616. 'standard_score' => $item['standard_score'],
  617. 'difficulty_coef' => $item['difficulty_coef'],
  618. 'sys_id' => $sys_id,
  619. 'sys_rq' => date('Y-m-d H:i:s'),
  620. 'mod_rq' => null
  621. ];
  622. }
  623. echo "<pre>";
  624. print_r($part_all);
  625. echo "<pre>";die;
  626. // 7. 写入数据库(你可以按需注释)
  627. db('产品_部件资料')->where('product_code', $product_code)->update(['mod_rq' => date('Y-m-d H:i:s')]);
  628. db('产品_部件资料')->insertAll($part_all);
  629. db('产品_工艺资料')->where('product_code', $product_code)->update(['mod_rq' => date('Y-m-d H:i:s')]);
  630. db('产品_工艺资料')->insertAll($process_all);
  631. $this->success('导入成功', [
  632. '部件数量' => count($part_all),
  633. '工艺数量' => count($process_all)
  634. ]);
  635. }
  636. private function readXlsx($file)
  637. {
  638. if (!class_exists('ZipArchive')) {
  639. return [];
  640. }
  641. $zip = new \ZipArchive();
  642. if ($zip->open($file) !== true) {
  643. return [];
  644. }
  645. // 读取工作表内容和共享字符串
  646. $content = $zip->getFromName('xl/worksheets/sheet1.xml');
  647. $strings = $zip->getFromName('xl/sharedStrings.xml');
  648. $zip->close();
  649. // 解析共享字符串
  650. $str_map = [];
  651. if ($strings) {
  652. preg_match_all('/<si><t[^>]*>([^<]+)<\/t><\/si>/s', $strings, $matches);
  653. $str_map = $matches[1] ?? [];
  654. }
  655. $rows = [];
  656. // 解析每一行
  657. preg_match_all('/<row[^>]*>(.*?)<\/row>/s', $content, $row_matches);
  658. foreach ($row_matches[1] as $row_xml) {
  659. $cols = array_fill(0, 6, ''); // 固定6列,防止错位
  660. $cellIndex = 0;
  661. // 解析单元格
  662. preg_match_all('/<c r="[^"]+"(?: t="([^"]+)")?[^>]*>(.*?)<\/c>/s', $row_xml, $cell_matches);
  663. foreach ($cell_matches[0] as $i => $cell_xml) {
  664. if ($cellIndex >= 6) break; // 只取前6列
  665. $cell_type = $cell_matches[1][$i] ?? '';
  666. $cell_inner = $cell_matches[2][$i] ?? '';
  667. $value = '';
  668. // 读取单元格值
  669. if (preg_match('/<v>([^<]+)<\/v>/', $cell_inner, $v_match)) {
  670. $value = $v_match[1];
  671. } elseif (preg_match('/<t>([^<]+)<\/t>/', $cell_inner, $t_match)) {
  672. $value = $t_match[1];
  673. }
  674. // 处理共享字符串
  675. if ($cell_type === 's' && isset($str_map[$value])) {
  676. $value = $str_map[$value];
  677. }
  678. $cols[$cellIndex] = $value;
  679. $cellIndex++;
  680. }
  681. $rows[] = $cols;
  682. }
  683. return $rows;
  684. }
  685. private function readXls($file)
  686. {
  687. $data = file_get_contents($file);
  688. $rows = [];
  689. $len = strlen($data);
  690. $p = 0;
  691. while ($p < $len) {
  692. $id = ord($data[$p]);
  693. $size = unpack('v', substr($data, $p + 1, 2))[1];
  694. if ($id == 0x20) {
  695. $row = [];
  696. $sp = $p + 4;
  697. while ($sp < $p + $size) {
  698. $type = ord($data[$sp]);
  699. if ($type == 0x02) {
  700. $val = substr($data, $sp + 3, 1);
  701. $row[] = trim($val);
  702. $sp += 8;
  703. } else {
  704. $sp++;
  705. }
  706. }
  707. if (!empty($row)) $rows[] = $row;
  708. }
  709. $p += $size;
  710. }
  711. return $rows;
  712. }
  713. }