selectGoods.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. <template>
  2. <view class="content-box">
  3. <uni-nav-bar
  4. fixed="true"
  5. statusBar="true"
  6. left-icon="back"
  7. title="选择在制品"
  8. background-color="#157A2C"
  9. color="#fff"
  10. @clickLeft="back"
  11. ></uni-nav-bar>
  12. <view class="list_box">
  13. <u-list>
  14. <u-list-item v-for="item in goodsList" :key="item.id">
  15. <view class="goods-item" :class="{ selected: isSelected(item) }">
  16. <view class="goods-checkbox">
  17. <checkbox
  18. :checked="isSelected(item)"
  19. @click.stop="toggleSelect(item)"
  20. color="#157A2C"
  21. />
  22. </view>
  23. <view class="goods-content" @click="toggleSelect(item)">
  24. <view class="goods-header">
  25. <text class="goods-name">{{ item.categoryName }}</text>
  26. <view class="goods-actions">
  27. <text class="type-tag">{{
  28. getTypeName(item.rootCategoryLevelId)
  29. }}</text>
  30. </view>
  31. </view>
  32. <view class="goods-row">
  33. <text class="label">牌号:</text>
  34. <text class="value">{{ item.brandNum }}</text>
  35. </view>
  36. <view class="goods-row">
  37. <text class="label">批次号:</text>
  38. <text class="value">{{ item.batchNo }}</text>
  39. </view>
  40. <view class="goods-row">
  41. <text class="label">数量:</text>
  42. <text class="value"
  43. >{{ item.quantity }}{{ item.measuringUnit }}</text
  44. >
  45. </view>
  46. <view class="goods-row">
  47. <text class="label">重量:</text>
  48. <text class="value"
  49. >{{ item.weight }}{{ item.weightUnit }}</text
  50. >
  51. </view>
  52. <view class="goods-row">
  53. <text class="label">生产工单号:</text>
  54. <text class="value">{{ item.workOrderCode }}</text>
  55. </view>
  56. <view class="goods-row">
  57. <text class="label">规格:</text>
  58. <text class="value">{{ item.specification }}</text>
  59. </view>
  60. <view class="goods-row">
  61. <text class="label">型号:</text>
  62. <text class="value">{{ item.modelType }}</text>
  63. </view>
  64. <view class="goods-row">
  65. <text class="label">编码:</text>
  66. <text class="value">{{ item.categoryCode }}</text>
  67. </view>
  68. </view>
  69. </view>
  70. </u-list-item>
  71. <u-list-item v-if="goodsList.length === 0">
  72. <view class="empty-wrapper">
  73. <u-empty
  74. iconSize="150"
  75. textSize="32"
  76. text="暂无在制品数据"
  77. ></u-empty>
  78. </view>
  79. </u-list-item>
  80. </u-list>
  81. </view>
  82. <!-- 底部按钮 -->
  83. <view class="footer-btns">
  84. <view class="footer-left">
  85. <checkbox
  86. :checked="isAllSelected"
  87. @click="toggleSelectAll"
  88. color="#157A2C"
  89. />
  90. <text class="select-all-text">全选</text>
  91. </view>
  92. <view class="footer-right">
  93. <u-button class="btn-cancel" @click="handleCancel">取消</u-button>
  94. <u-button type="success" class="btn-confirm" @click="handleConfirm"
  95. >确定({{ selectedList.length }})</u-button
  96. >
  97. </view>
  98. </view>
  99. </view>
  100. </template>
  101. <script>
  102. import { pleaseEntrustAllGoodsDetail } from "@/api/entrust/index";
  103. export default {
  104. data() {
  105. return {
  106. id: "",
  107. goodsList: [],
  108. selectedList: [],
  109. existingGoods: [],
  110. };
  111. },
  112. computed: {
  113. isAllSelected() {
  114. return (
  115. this.goodsList.length > 0 &&
  116. this.selectedList.length === this.goodsList.length
  117. );
  118. },
  119. },
  120. onLoad(options) {
  121. this.id = options.id;
  122. if (options.existingIds) {
  123. try {
  124. this.existingGoods = JSON.parse(
  125. decodeURIComponent(options.existingIds),
  126. );
  127. } catch (e) {
  128. this.existingGoods = [];
  129. }
  130. }
  131. this.loadData();
  132. },
  133. methods: {
  134. async loadData() {
  135. try {
  136. const res = await pleaseEntrustAllGoodsDetail({ id: this.id });
  137. this.goodsList = res || [];
  138. // 预选已存在的在制品
  139. if (this.existingGoods.length > 0) {
  140. this.goodsList.forEach((item) => {
  141. if (this.existingGoods.some((exist) => exist.id === item.id)) {
  142. this.selectedList.push(item);
  143. }
  144. });
  145. }
  146. } catch (error) {
  147. uni.showToast({
  148. title: "加载失败",
  149. icon: "none",
  150. });
  151. }
  152. },
  153. getTypeName(type) {
  154. const typeMap = {
  155. 1: "物料",
  156. 2: "在制品",
  157. 3: "零部件",
  158. 4: "生产设备",
  159. 5: "模具",
  160. 6: "备品备件",
  161. 7: "周转车",
  162. 8: "舟皿",
  163. 9: "产品",
  164. 10: "消耗材料",
  165. 11: "干燥区",
  166. 12: "质检",
  167. 13: "包装材料",
  168. 14: "生产辅助设备",
  169. 15: "仪表计量设备",
  170. 16: "办公设备",
  171. 17: "客户",
  172. 18: "房屋、建筑物",
  173. 19: "供应商",
  174. 20: "工装夹具",
  175. 22: "工装夹具",
  176. 23: "半成品",
  177. 24: "会计科目",
  178. 25: "费用类型",
  179. 26: "周转盘",
  180. 27: "文档",
  181. 28: "废品",
  182. 99: "其他",
  183. };
  184. return typeMap[type] || "";
  185. },
  186. isSelected(item) {
  187. return this.selectedList.some((selected) => selected.id === item.id);
  188. },
  189. toggleSelect(item) {
  190. const index = this.selectedList.findIndex(
  191. (selected) => selected.id === item.id,
  192. );
  193. if (index > -1) {
  194. this.selectedList.splice(index, 1);
  195. } else {
  196. this.selectedList.push(item);
  197. }
  198. },
  199. toggleSelectAll() {
  200. if (this.isAllSelected) {
  201. this.selectedList = [];
  202. } else {
  203. this.selectedList = [...this.goodsList];
  204. }
  205. },
  206. handleCancel() {
  207. uni.navigateBack();
  208. },
  209. handleConfirm() {
  210. if (this.selectedList.length === 0) {
  211. uni.showToast({
  212. title: "请至少选择一条在制品数据",
  213. icon: "none",
  214. });
  215. return;
  216. }
  217. // 通过页面栈传递数据
  218. const pages = getCurrentPages();
  219. const prevPage = pages[pages.length - 2];
  220. if (prevPage && prevPage.$vm.receiveGoods) {
  221. prevPage.$vm.receiveGoods(this.selectedList);
  222. }
  223. uni.navigateBack();
  224. },
  225. },
  226. };
  227. </script>
  228. <style lang="scss" scoped>
  229. .content-box {
  230. height: 100vh;
  231. overflow: hidden;
  232. display: flex;
  233. flex-direction: column;
  234. background-color: $page-bg;
  235. }
  236. .list_box {
  237. flex: 1;
  238. overflow: hidden;
  239. padding: 16rpx 0;
  240. padding-bottom: 120rpx;
  241. .u-list {
  242. height: 100% !important;
  243. }
  244. }
  245. .goods-item {
  246. background-color: #fff;
  247. border-radius: 12rpx;
  248. padding: 24rpx;
  249. margin: 0 24rpx 20rpx;
  250. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
  251. border: 2rpx solid transparent;
  252. transition: all 0.3s;
  253. display: flex;
  254. gap: 16rpx;
  255. &.selected {
  256. border-color: $theme-color;
  257. background-color: rgba(21, 122, 44, 0.06);
  258. }
  259. .goods-checkbox {
  260. display: flex;
  261. align-items: flex-start;
  262. padding-top: 4rpx;
  263. }
  264. .goods-content {
  265. flex: 1;
  266. }
  267. .goods-header {
  268. display: flex;
  269. justify-content: space-between;
  270. align-items: center;
  271. margin-bottom: 20rpx;
  272. padding-bottom: 20rpx;
  273. border-bottom: 1rpx solid #f0f0f0;
  274. .goods-name {
  275. flex: 1;
  276. font-size: 32rpx;
  277. font-weight: bold;
  278. color: #333;
  279. }
  280. .goods-actions {
  281. display: flex;
  282. align-items: center;
  283. gap: 16rpx;
  284. .type-tag {
  285. display: inline-block;
  286. padding: 4rpx 16rpx;
  287. background-color: rgba(21, 122, 44, 0.1);
  288. color: $theme-color;
  289. border-radius: 4rpx;
  290. font-size: 24rpx;
  291. }
  292. .check-icon {
  293. width: 48rpx;
  294. height: 48rpx;
  295. line-height: 48rpx;
  296. text-align: center;
  297. background-color: $theme-color;
  298. color: #fff;
  299. border-radius: 50%;
  300. font-size: 32rpx;
  301. }
  302. }
  303. }
  304. .goods-row {
  305. display: flex;
  306. margin-bottom: 16rpx;
  307. font-size: 28rpx;
  308. .label {
  309. color: #999;
  310. min-width: 200rpx;
  311. }
  312. .value {
  313. flex: 1;
  314. color: #333;
  315. word-break: break-all;
  316. }
  317. }
  318. }
  319. .empty-wrapper {
  320. display: flex;
  321. align-items: center;
  322. justify-content: center;
  323. padding-top: 25vh;
  324. }
  325. .footer-btns {
  326. display: flex;
  327. justify-content: space-between;
  328. align-items: center;
  329. gap: 20rpx;
  330. padding: 20rpx 32rpx;
  331. background-color: #fff;
  332. box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.08);
  333. padding-bottom: constant(safe-area-inset-bottom);
  334. padding-bottom: env(safe-area-inset-bottom);
  335. position: fixed;
  336. bottom: 0;
  337. left: 0;
  338. right: 0;
  339. z-index: 100;
  340. .footer-left {
  341. display: flex;
  342. align-items: center;
  343. gap: 12rpx;
  344. .select-all-text {
  345. font-size: 28rpx;
  346. color: #333;
  347. }
  348. }
  349. .footer-right {
  350. display: flex;
  351. gap: 20rpx;
  352. }
  353. /deep/ .u-button {
  354. min-width: 160rpx;
  355. height: 80rpx;
  356. border-radius: 40rpx;
  357. font-size: 30rpx;
  358. }
  359. .btn-cancel {
  360. background-color: #fff;
  361. color: #666;
  362. border: 1rpx solid #e0e0e0;
  363. }
  364. }
  365. </style>