You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
8.5 KiB

6 months ago
  1. <template>
  2. <div class="pda-container">
  3. <!-- 头部栏 -->
  4. <div class="header-bar">
  5. <div class="header-left" @click="$router.back()">
  6. <i class="el-icon-arrow-left"></i>
  7. <span>委外发料</span>
  8. </div>
  9. <div class="header-right" @click="$router.push({ path: '/' })">
  10. 首页
  11. </div>
  12. </div>
  13. <!-- 搜索框 -->
  14. <div class="search-container">
  15. <el-input clearable
  16. v-model="searchCode"
  17. placeholder="请扫描委外订单或申请单号"
  18. prefix-icon="el-icon-search"
  19. @keyup.enter.native="handleSearch"
  20. ref="searchInput"
  21. />
  22. </div>
  23. <!-- 委外发料单列表 -->
  24. <div class="content-area">
  25. <div
  26. v-for="(item, index) in outsourcingList"
  27. :key="index"
  28. class="outsourcing-card"
  29. @click="goToPickingPage(item)"
  30. >
  31. <div class="card-title">
  32. <span class="title-label">委外订单号</span>
  33. <span class="title-value">{{ item.outsourcingNo }}</span>
  34. </div>
  35. <div class="card-details">
  36. <div class="detail-item">
  37. <div class="detail-label">申请单号</div>
  38. <div class="detail-value">{{ item.requestNo }}</div>
  39. </div>
  40. <div class="detail-item">
  41. <div class="detail-label">标签张数</div>
  42. <div class="detail-value">
  43. <span class="qualified">{{ item.pickedLabels }}</span><span class="total">{{ item.totalLabels }}</span>
  44. </div>
  45. </div>
  46. <div class="detail-item">
  47. <div class="detail-label">物料总数</div>
  48. <div class="detail-value">
  49. <span class="qualified">{{ item.requestQty }}</span><span class="total">{{ item.remainQty }}</span>
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <!-- 空状态 -->
  55. <div v-if="outsourcingList.length === 0 && !loading" class="empty-state">
  56. <i class="el-icon-box"></i>
  57. <p>暂无待发料委外订单</p>
  58. </div>
  59. <!-- 加载状态 -->
  60. <div v-if="loading" class="loading-state">
  61. <i class="el-icon-loading"></i>
  62. <p>加载中...</p>
  63. </div>
  64. </div>
  65. </div>
  66. </template>
  67. <script>
  68. import { getPoList } from '@/api/po/po.js'
  69. import moment from 'moment';
  70. export default {
  71. data() {
  72. return {
  73. searchCode: '',
  74. outsourcingList: [],
  75. loading: false
  76. };
  77. },
  78. methods: {
  79. formatDate(date) {
  80. return date ? moment(date).format('YYYY-MM-DD') : '';
  81. },
  82. // 处理搜索
  83. handleSearch() {
  84. if (this.searchCode.trim()) {
  85. this.searchOutsourcingList(this.searchCode.trim());
  86. } else {
  87. this.loadOutsourcingList();
  88. }
  89. },
  90. // 加载委外发料单列表
  91. loadOutsourcingList() {
  92. this.loading = true;
  93. const params = {
  94. site: this.$store.state.user.site,
  95. status: '待发料',
  96. type: 'outsourcing'
  97. }
  98. console.log('params', params);
  99. // 使用现有的 PO API 来获取委外订单数据
  100. getPoList(params).then(({ data }) => {
  101. this.loading = false;
  102. if (data && data.code === 0) {
  103. // 转换数据格式以适配委外发料
  104. this.outsourcingList = (data.rows || []).map(item => ({
  105. outsourcingNo: item.poNumber || item.notifyNo,
  106. requestNo: item.workOrderNo || item.relatedNo,
  107. pickedLabels: item.pickedLabels || 0,
  108. totalLabels: item.totalLabels || 0,
  109. requestQty: item.requestQty || item.qty,
  110. remainQty: item.remainQty || item.thisRecvQty
  111. }));
  112. } else {
  113. this.$message.error(data.msg || '获取数据失败');
  114. }
  115. }).catch(error => {
  116. this.loading = false;
  117. console.error('获取委外发料单列表失败:', error);
  118. this.$message.error('获取数据失败');
  119. });
  120. },
  121. // 搜索特定委外订单
  122. searchOutsourcingList(searchCode) {
  123. this.loading = true;
  124. const params = {
  125. poNumber: searchCode,
  126. site: this.$store.state.user.site,
  127. status: '待发料',
  128. type: 'outsourcing'
  129. };
  130. getPoList(params).then(({ data }) => {
  131. this.loading = false;
  132. if (data && data.code === 0) {
  133. if (data.rows.length === 0) {
  134. this.$message.warning('未找到匹配的委外订单');
  135. }
  136. // 转换数据格式
  137. this.outsourcingList = (data.rows || []).map(item => ({
  138. outsourcingNo: item.poNumber || item.notifyNo,
  139. requestNo: item.workOrderNo || item.relatedNo,
  140. pickedLabels: item.pickedLabels || 0,
  141. totalLabels: item.totalLabels || 0,
  142. requestQty: item.requestQty || item.qty,
  143. remainQty: item.remainQty || item.thisRecvQty
  144. }));
  145. } else {
  146. this.$message.error(data.msg || '查询失败');
  147. }
  148. }).catch(error => {
  149. this.loading = false;
  150. this.$message.error('查询失败');
  151. });
  152. },
  153. // 跳转到发料页面
  154. goToPickingPage(item) {
  155. this.$router.push({
  156. name: 'outsourcingPickingDetail',
  157. params: {
  158. outsourcingNo: item.outsourcingNo,
  159. }
  160. });
  161. }
  162. },
  163. mounted() {
  164. // 聚焦搜索框
  165. this.$nextTick(() => {
  166. if (this.$refs.searchInput) {
  167. this.$refs.searchInput.focus();
  168. }
  169. });
  170. // 加载数据
  171. this.loadOutsourcingList();
  172. }
  173. };
  174. </script>
  175. <style scoped>
  176. .pda-container {
  177. width: 100vw;
  178. height: 100vh;
  179. display: flex;
  180. flex-direction: column;
  181. background: #f5f5f5;
  182. }
  183. /* 头部栏 */
  184. .header-bar {
  185. display: flex;
  186. justify-content: space-between;
  187. align-items: center;
  188. padding: 8px 16px;
  189. background: #17B3A3;
  190. color: white;
  191. height: 40px;
  192. min-height: 40px;
  193. }
  194. .header-left {
  195. display: flex;
  196. align-items: center;
  197. cursor: pointer;
  198. font-size: 16px;
  199. font-weight: 500;
  200. }
  201. .header-left i {
  202. margin-right: 8px;
  203. font-size: 18px;
  204. }
  205. .header-right {
  206. cursor: pointer;
  207. font-size: 16px;
  208. font-weight: 500;
  209. }
  210. /* 搜索容器 */
  211. .search-container {
  212. padding: 12px 16px;
  213. background: white;
  214. }
  215. /* 内容区域 */
  216. .content-area {
  217. flex: 1;
  218. overflow-y: auto;
  219. padding: 12px 16px;
  220. }
  221. /* 委外卡片 */
  222. .outsourcing-card {
  223. background: white;
  224. border-radius: 8px;
  225. margin-bottom: 12px;
  226. padding: 16px;
  227. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  228. cursor: pointer;
  229. transition: all 0.2s ease;
  230. }
  231. .outsourcing-card:hover {
  232. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
  233. transform: translateY(-1px);
  234. }
  235. .outsourcing-card:active {
  236. transform: translateY(0);
  237. }
  238. /* 卡片标题 */
  239. .card-title {
  240. margin-bottom: 12px;
  241. }
  242. .title-label {
  243. font-size: 12px;
  244. color: #666;
  245. display: block;
  246. margin-bottom: 4px;
  247. }
  248. .title-value {
  249. font-size: 16px;
  250. font-weight: bold;
  251. color: #333;
  252. margin-left: 20px;
  253. }
  254. /* 卡片详情 */
  255. .card-details {
  256. display: flex;
  257. justify-content: space-between;
  258. align-items: flex-start;
  259. gap: 4px;
  260. }
  261. .detail-item {
  262. flex: 1;
  263. text-align: center;
  264. min-width: 60px;
  265. max-width: 60px;
  266. }
  267. .detail-label {
  268. font-size: 11px;
  269. color: #666;
  270. margin-bottom: 4px;
  271. line-height: 1.2;
  272. margin-left: -12px;
  273. }
  274. .detail-value {
  275. font-size: 13px;
  276. color: #333;
  277. line-height: 1.2;
  278. margin-left: -12px;
  279. }
  280. .detail-value .qualified {
  281. color: #17B3A3;
  282. font-weight: 500;
  283. }
  284. .detail-value .total {
  285. color: #333;
  286. font-weight: 500;
  287. }
  288. .detail-value .total::before {
  289. content: '/';
  290. color: #333;
  291. }
  292. /* 空状态 */
  293. .empty-state {
  294. display: flex;
  295. flex-direction: column;
  296. align-items: center;
  297. justify-content: center;
  298. padding: 60px 20px;
  299. color: #999;
  300. }
  301. .empty-state i {
  302. font-size: 48px;
  303. margin-bottom: 16px;
  304. }
  305. .empty-state p {
  306. font-size: 14px;
  307. margin: 0;
  308. }
  309. /* 加载状态 */
  310. .loading-state {
  311. display: flex;
  312. flex-direction: column;
  313. align-items: center;
  314. justify-content: center;
  315. padding: 60px 20px;
  316. color: #17B3A3;
  317. }
  318. .loading-state i {
  319. font-size: 24px;
  320. margin-bottom: 12px;
  321. animation: spin 1s linear infinite;
  322. }
  323. @keyframes spin {
  324. from { transform: rotate(0deg); }
  325. to { transform: rotate(360deg); }
  326. }
  327. .loading-state p {
  328. font-size: 14px;
  329. margin: 0;
  330. }
  331. /* 响应式设计 */
  332. @media (max-width: 360px) {
  333. .header-bar {
  334. padding: 8px 12px;
  335. }
  336. .search-container {
  337. padding: 8px 12px;
  338. }
  339. .content-area {
  340. padding: 8px 12px;
  341. }
  342. .outsourcing-card {
  343. padding: 12px;
  344. }
  345. .card-details {
  346. flex-wrap: wrap;
  347. gap: 6px;
  348. }
  349. .detail-item {
  350. flex: 0 0 48%;
  351. margin-bottom: 6px;
  352. min-width: 50px;
  353. }
  354. }
  355. </style>