detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <template>
  2. <view class="db-page">
  3. <view class="db-header" :style="safeAreaStyle">
  4. <view class="db-header__nav">
  5. <view class="db-header__left">
  6. <text class="db-header__back" @click="goBack">←</text>
  7. <text class="db-header__title">{{ title }}</text>
  8. </view>
  9. <view /><!-- 胶囊占位 -->
  10. </view>
  11. </view>
  12. <view class="db-form-section">
  13. <view class="db-form-item">
  14. <view class="db-form-label">车牌号 <text class="req">*</text></view>
  15. <view v-if="isView" class="db-form-value">{{ form.vehicleNo || '--' }}</view>
  16. <view v-else class="db-form-value" @click="showVehicle = true">
  17. <text :class="{ ph: !form.vehicleNo }">{{ form.vehicleNo || '请选择车牌号' }}</text>
  18. <text>›</text>
  19. </view>
  20. </view>
  21. <view class="db-form-item">
  22. <view class="db-form-label">货物名称 <text class="req">*</text></view>
  23. <view v-if="isView" class="db-form-value">{{ cargoDisplay || '--' }}</view>
  24. <view v-else class="db-form-value" @click="showCargo = true">
  25. <text :class="{ ph: !cargoDisplay }">{{ cargoDisplay || '请选择货物名称' }}</text>
  26. <text>›</text>
  27. </view>
  28. </view>
  29. <view class="db-form-item">
  30. <view class="db-form-label">业务类型 <text class="req">*</text></view>
  31. <db-radio-group v-model="form.businessType" :disabled="isView" />
  32. </view>
  33. <view class="db-form-item">
  34. <view class="db-form-label">供货单位 <text class="req">*</text></view>
  35. <view v-if="isView" class="db-form-value">{{ form.supplier || '--' }}</view>
  36. <view v-else class="db-form-value" @click="pickSupplier = true">
  37. <text :class="{ ph: !form.supplier }">{{ form.supplier || '请选择供货单位' }}</text>
  38. <text>›</text>
  39. </view>
  40. </view>
  41. <view class="db-form-item">
  42. <view class="db-form-label">收货单位 <text class="req">*</text></view>
  43. <view v-if="isView" class="db-form-value">{{ form.consignee || '--' }}</view>
  44. <view v-else class="db-form-value" @click="pickConsignee = true">
  45. <text :class="{ ph: !form.consignee }">{{ form.consignee || '请选择收货单位' }}</text>
  46. <text>›</text>
  47. </view>
  48. </view>
  49. <view class="db-form-item">
  50. <view class="db-form-label">毛重(kg)</view>
  51. <view v-if="isView" class="db-form-value">{{ displayWeight(form.grossWeight) }}</view>
  52. <db-field
  53. v-else
  54. v-model="form.grossWeight"
  55. type="digit"
  56. placeholder="请输入毛重"
  57. @change="onGross"
  58. />
  59. </view>
  60. <view class="db-form-item">
  61. <view class="db-form-label">毛重时间</view>
  62. <view v-if="isView" class="db-form-value">{{ form.grossWeightTime || '--' }}</view>
  63. <view v-else class="db-form-value" @click="fillGrossTime">
  64. <text :class="{ ph: !form.grossWeightTime }">{{ form.grossWeightTime || '点此填当前时间' }}</text>
  65. </view>
  66. </view>
  67. <view class="db-form-item">
  68. <view class="db-form-label">皮重(kg)</view>
  69. <view v-if="isView" class="db-form-value">{{ displayWeight(form.tareWeight) }}</view>
  70. <db-field
  71. v-else
  72. v-model="form.tareWeight"
  73. type="digit"
  74. placeholder="请输入皮重"
  75. @change="onTare"
  76. />
  77. </view>
  78. <view class="db-form-item">
  79. <view class="db-form-label">皮重时间</view>
  80. <view v-if="isView" class="db-form-value">{{ form.tareWeightTime || '--' }}</view>
  81. <view v-else class="db-form-value" @click="fillTareTime">
  82. <text :class="{ ph: !form.tareWeightTime }">{{ form.tareWeightTime || '点此填当前时间' }}</text>
  83. </view>
  84. </view>
  85. <view class="db-form-item">
  86. <view class="db-form-label">扣杂(kg)</view>
  87. <view v-if="isView" class="db-form-value">{{ form.deduction || 0 }}</view>
  88. <db-field
  89. v-else
  90. v-model="form.deduction"
  91. type="digit"
  92. placeholder="请输入扣杂"
  93. @change="onDeduction"
  94. />
  95. </view>
  96. <view class="db-form-item">
  97. <view class="db-form-label">净重(kg)</view>
  98. <view class="db-form-value">
  99. <text :style="{ color: netInvalid ? '#ee0a24' : '#111827' }">
  100. {{ canShowNet ? netWeight : '--' }}
  101. </text>
  102. </view>
  103. <view v-if="netInvalid" style="color: #ee0a24; font-size: 12px; margin-top: 4px">净重必须大于0</view>
  104. </view>
  105. <view class="db-form-item">
  106. <view class="db-form-label">计划号</view>
  107. <view v-if="isView" class="db-form-value">{{ form.planNo || '--' }}</view>
  108. <db-field
  109. v-else
  110. v-model="form.planNo"
  111. placeholder="请输入计划号"
  112. />
  113. </view>
  114. <view class="db-form-item">
  115. <view class="db-form-label">备注</view>
  116. <view v-if="isView" class="db-form-value">{{ form.remarks || '--' }}</view>
  117. <db-field
  118. v-else
  119. v-model="form.remarks"
  120. type="textarea"
  121. autosize
  122. placeholder="请输入备注"
  123. />
  124. </view>
  125. </view>
  126. <view v-if="!isView" class="db-form-actions">
  127. <db-btn block type="primary" :loading="saving" :disabled="netInvalid" @click="save">保存</db-btn>
  128. <db-btn block plain style="margin-top:12px" @click="goBack">取消</db-btn>
  129. </view>
  130. <db-product-picker :show="showCargo" @update:show="(v) => (showCargo = v)" @select="onProduct" />
  131. <db-customer-picker :show="pickSupplier" @update:show="(v) => (pickSupplier = v)" @select="onSupplier" />
  132. <db-customer-picker :show="pickConsignee" @update:show="(v) => (pickConsignee = v)" @select="onConsignee" />
  133. <db-vehicle-picker :show="showVehicle" @update:show="(v) => (showVehicle = v)" @select="onVehicle" />
  134. </view>
  135. </template>
  136. <script setup>
  137. import { ref, reactive, computed } from 'vue'
  138. import { onLoad } from '@dcloudio/uni-app'
  139. import { PAGE_PATHS } from '@/config/api'
  140. import { getSafeAreaStyle } from '@/utils/safeArea'
  141. import { weighingApi } from '@/pages/db/api/db'
  142. import { nowYmdHms } from '@/pages/db/utils/dbDate'
  143. import DbField from '@/components/db-ui/db-field.vue'
  144. import DbBtn from '@/components/db-ui/db-btn.vue'
  145. import DbRadioGroup from '@/components/db-ui/db-radio-group.vue'
  146. import DbCustomerPicker from '@/components/db-customer-picker/db-customer-picker.vue'
  147. import DbProductPicker from '@/components/db-product-picker/db-product-picker.vue'
  148. import DbVehiclePicker from '@/components/db-vehicle-picker/db-vehicle-picker.vue'
  149. const safeAreaStyle = getSafeAreaStyle()
  150. const mode = ref('create')
  151. const id = ref('')
  152. const saving = ref(false)
  153. const showVehicle = ref(false)
  154. const showCargo = ref(false)
  155. const pickSupplier = ref(false)
  156. const pickConsignee = ref(false)
  157. const cargoDisplay = ref('')
  158. const form = reactive({
  159. vehicleNo: '',
  160. planNo: '',
  161. productId: '',
  162. businessType: '入库',
  163. supplier: '',
  164. consignee: '',
  165. grossWeight: '',
  166. grossWeightTime: '',
  167. tareWeight: '',
  168. tareWeightTime: '',
  169. deduction: 0,
  170. netWeight: 0,
  171. purchasePlanId: undefined,
  172. inboundOutboundId: undefined,
  173. remarks: ''
  174. })
  175. const isView = computed(() => mode.value === 'view')
  176. const isEdit = computed(() => mode.value === 'edit')
  177. const title = computed(() => (isEdit.value ? '编辑地磅单' : isView.value ? '查看地磅单' : '新增地磅单'))
  178. const netWeight = computed(() => {
  179. const g = Number(form.grossWeight) || 0
  180. const t = Number(form.tareWeight) || 0
  181. const d = Number(form.deduction) || 0
  182. return Math.max(0, g - t - d)
  183. })
  184. const canShowNet = computed(() => Number(form.grossWeight) > 0 && Number(form.tareWeight) > 0)
  185. const netInvalid = computed(() => canShowNet.value && netWeight.value <= 0)
  186. function calcNet() {
  187. form.netWeight = netWeight.value
  188. }
  189. function displayWeight(v) {
  190. return Number(v) > 0 ? v : '--'
  191. }
  192. function onGross(v) {
  193. form.grossWeight = v
  194. if (Number(v) > 0 && !form.grossWeightTime) form.grossWeightTime = nowYmdHms()
  195. if (!(Number(v) > 0)) form.grossWeightTime = ''
  196. calcNet()
  197. }
  198. function onTare(v) {
  199. form.tareWeight = v
  200. if (Number(v) > 0 && !form.tareWeightTime) form.tareWeightTime = nowYmdHms()
  201. if (!(Number(v) > 0)) form.tareWeightTime = ''
  202. calcNet()
  203. }
  204. function onDeduction(v) {
  205. form.deduction = Number(v) || 0
  206. calcNet()
  207. }
  208. function fillGrossTime() {
  209. form.grossWeightTime = nowYmdHms()
  210. }
  211. function fillTareTime() {
  212. form.tareWeightTime = nowYmdHms()
  213. }
  214. function goBack() {
  215. uni.navigateBack({ fail: () => uni.redirectTo({ url: PAGE_PATHS.dbWeighingList }) })
  216. }
  217. function onVehicle(plate) {
  218. form.vehicleNo = plate
  219. }
  220. function onProduct(item) {
  221. form.productId = item.id
  222. cargoDisplay.value = item.productName
  223. }
  224. function onSupplier(item) {
  225. form.supplier = item.customerName
  226. }
  227. function onConsignee(item) {
  228. form.consignee = item.customerName
  229. }
  230. async function loadDetail() {
  231. const data = await weighingApi.get(id.value)
  232. Object.assign(form, {
  233. vehicleNo: data.vehicleNo || '',
  234. planNo: data.planNo || '',
  235. productId: data.productId || '',
  236. businessType: data.businessType || '入库',
  237. supplier: data.supplier || '',
  238. consignee: data.consignee || '',
  239. grossWeight: Number(data.grossWeight) > 0 ? data.grossWeight : '',
  240. grossWeightTime: Number(data.grossWeight) > 0 ? data.grossWeightTime || '' : '',
  241. tareWeight: Number(data.tareWeight) > 0 ? data.tareWeight : '',
  242. tareWeightTime: Number(data.tareWeight) > 0 ? data.tareWeightTime || '' : '',
  243. deduction: data.deduction ?? 0,
  244. netWeight: data.netWeight ?? 0,
  245. purchasePlanId: data.purchasePlanId,
  246. inboundOutboundId: data.inboundOutboundId,
  247. remarks: data.remarks || ''
  248. })
  249. cargoDisplay.value = data.cargoName || ''
  250. }
  251. async function save() {
  252. if (!form.vehicleNo || !form.productId || !form.supplier || !form.consignee) {
  253. uni.showToast({ title: '请完善必填项', icon: 'none' })
  254. return
  255. }
  256. if (netInvalid.value) {
  257. uni.showToast({ title: '净重必须大于0', icon: 'none' })
  258. return
  259. }
  260. calcNet()
  261. saving.value = true
  262. try {
  263. const gross = Number(form.grossWeight) || 0
  264. const tare = Number(form.tareWeight) || 0
  265. const payload = {
  266. vehicleNo: form.vehicleNo,
  267. planNo: form.planNo || undefined,
  268. productId: form.productId,
  269. businessType: form.businessType,
  270. supplier: form.supplier,
  271. consignee: form.consignee,
  272. grossWeight: gross,
  273. grossWeightTime: gross > 0 ? form.grossWeightTime || nowYmdHms() : '',
  274. tareWeight: tare,
  275. tareWeightTime: tare > 0 ? form.tareWeightTime || nowYmdHms() : '',
  276. deduction: Number(form.deduction) || 0,
  277. netWeight: gross > 0 && tare > 0 ? form.netWeight : 0,
  278. purchasePlanId: form.purchasePlanId,
  279. inboundOutboundId: form.inboundOutboundId,
  280. remarks: form.remarks || undefined
  281. }
  282. if (id.value) await weighingApi.update(id.value, payload)
  283. else await weighingApi.create(payload)
  284. uni.showToast({ title: '保存成功', icon: 'success' })
  285. setTimeout(goBack, 500)
  286. } finally {
  287. saving.value = false
  288. }
  289. }
  290. onLoad(async (q) => {
  291. mode.value = q.mode || (q.id ? 'edit' : 'create')
  292. id.value = q.id || ''
  293. if (q.vehicleNo) form.vehicleNo = decodeURIComponent(q.vehicleNo)
  294. if (q.productId) form.productId = decodeURIComponent(q.productId)
  295. if (q.cargoName) cargoDisplay.value = decodeURIComponent(q.cargoName)
  296. if (q.businessType) form.businessType = decodeURIComponent(q.businessType)
  297. if (q.supplier) form.supplier = decodeURIComponent(q.supplier)
  298. if (q.consignee) form.consignee = decodeURIComponent(q.consignee)
  299. if (q.planNo) form.planNo = decodeURIComponent(q.planNo)
  300. if (q.inboundOutboundId) form.inboundOutboundId = decodeURIComponent(q.inboundOutboundId)
  301. if (q.purchasePlanId) form.purchasePlanId = decodeURIComponent(q.purchasePlanId)
  302. if (id.value) {
  303. try {
  304. await loadDetail()
  305. } catch (e) {
  306. // handled
  307. }
  308. }
  309. })
  310. </script>
  311. <style lang="scss">
  312. @import '@/styles/db-theme.scss';
  313. </style>