Sin descripción

gen_waybill_vue.py 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. # -*- coding: utf-8 -*-
  2. """Regenerate waybill/index.vue with UTF-8 Chinese and region cascaders."""
  3. import os
  4. OUT = os.path.join(
  5. os.path.dirname(os.path.dirname(__file__)),
  6. "ruoyi-ui", "src", "views", "basic", "waybill", "index.vue"
  7. )
  8. # fmt: off
  9. VUE = r'''<template>
  10. <div class="app-container">
  11. <el-form ref="queryForm" :model="queryParams" :inline="true" size="small" v-show="showSearch" label-width="88px">
  12. <el-form-item label="\u8fd0\u5355\u53f7" prop="waybillNo">
  13. <el-input v-model="queryParams.waybillNo" placeholder="\u8bf7\u8f93\u5165\u8fd0\u5355\u53f7" clearable style="width: 180px" @keyup.enter.native="handleQuery" />
  14. </el-form-item>
  15. <el-form-item label="\u8fd0\u8f93\u7c7b\u578b" prop="transportType">
  16. <el-select v-model="queryParams.transportType" placeholder="\u8bf7\u9009\u62e9" clearable style="width: 140px">
  17. <el-option v-for="item in transportTypeOptions" :key="item" :label="item" :value="item" />
  18. </el-select>
  19. </el-form-item>
  20. <el-form-item label="\u53d1\u8d27\u4f01\u4e1a" prop="senderCompany">
  21. <el-input v-model="queryParams.senderCompany" placeholder="\u8bf7\u8f93\u5165\u53d1\u8d27\u4f01\u4e1a" clearable style="width: 160px" @keyup.enter.native="handleQuery" />
  22. </el-form-item>
  23. <el-form-item label="\u6536\u8d27\u4f01\u4e1a" prop="receiverCompany">
  24. <el-input v-model="queryParams.receiverCompany" placeholder="\u8bf7\u8f93\u5165\u6536\u8d27\u4f01\u4e1a" clearable style="width: 160px" @keyup.enter.native="handleQuery" />
  25. </el-form-item>
  26. <el-form-item label="\u5ba1\u6838\u72b6\u6001" prop="auditStatus">
  27. <el-select v-model="queryParams.auditStatus" placeholder="\u8bf7\u9009\u62e9" clearable style="width: 120px">
  28. <el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value" />
  29. </el-select>
  30. </el-form-item>
  31. <el-form-item>
  32. <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">\u641c\u7d22</el-button>
  33. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">\u91cd\u7f6e</el-button>
  34. </el-form-item>
  35. </el-form>
  36. <el-row :gutter="10" class="mb8">
  37. <el-col :span="1.5">
  38. <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['transport:waybill:add']">\u65b0\u589e</el-button>
  39. </el-col>
  40. <el-col :span="1.5">
  41. <el-button type="success" plain icon="el-icon-check" size="mini" :disabled="single" @click="handleApprove()" v-hasPermi="['transport:waybill:approve']">\u5ba1\u6838\u901a\u8fc7</el-button>
  42. </el-col>
  43. <el-col :span="1.5">
  44. <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete()" v-hasPermi="['transport:waybill:remove']">\u5220\u9664</el-button>
  45. </el-col>
  46. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
  47. </el-row>
  48. <el-table border stripe v-loading="loading" :data="waybillList" @selection-change="handleSelectionChange">
  49. <el-table-column type="selection" width="55" align="center" />
  50. <el-table-column label="\u8fd0\u5355\u53f7" prop="waybillNo" min-width="150" align="center" show-overflow-tooltip />
  51. <el-table-column label="\u8fd0\u8f93\u7c7b\u578b" prop="transportType" width="110" align="center" />
  52. <el-table-column label="\u5355\u636e\u65e5\u671f" prop="documentDate" width="110" align="center" />
  53. <el-table-column label="\u53d1\u8d27\u4f01\u4e1a" prop="senderCompany" min-width="140" align="center" show-overflow-tooltip />
  54. <el-table-column label="\u6536\u8d27\u4f01\u4e1a" prop="receiverCompany" min-width="140" align="center" show-overflow-tooltip />
  55. <el-table-column label="\u9884\u8ba1\u53d1\u8f66" prop="planDepartTime" width="160" align="center" />
  56. <el-table-column label="\u9884\u8ba1\u5230\u8fbe" prop="planArriveTime" width="160" align="center" />
  57. <el-table-column label="\u603b\u6570\u91cf" prop="totalQuantity" width="90" align="right" />
  58. <el-table-column label="\u603b\u91cd\u91cf(kg)" prop="totalWeight" width="100" align="right" />
  59. <el-table-column label="\u5ba1\u6838\u72b6\u6001" prop="auditStatus" width="100" align="center">
  60. <template slot-scope="scope">
  61. <el-tag :type="auditTagType(scope.row.auditStatus)" size="small">{{ auditStatusLabel(scope.row.auditStatus) }}</el-tag>
  62. </template>
  63. </el-table-column>
  64. <el-table-column label="\u64cd\u4f5c" align="center" width="220" class-name="small-padding fixed-width">
  65. <template slot-scope="scope">
  66. <el-button type="text" size="mini" icon="el-icon-view" @click="handleView(scope.row)" v-hasPermi="['transport:waybill:query']">\u67e5\u770b</el-button>
  67. <el-button type="text" size="mini" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['transport:waybill:edit']" v-if="canEdit(scope.row)">\u4fee\u6539</el-button>
  68. <el-button type="text" size="mini" icon="el-icon-check" @click="handleApprove(scope.row)" v-hasPermi="['transport:waybill:approve']" v-if="scope.row.auditStatus === 1">\u5ba1\u6838</el-button>
  69. <el-button type="text" size="mini" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['transport:waybill:remove']" v-if="canEdit(scope.row)">\u5220\u9664</el-button>
  70. </template>
  71. </el-table-column>
  72. </el-table>
  73. <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
  74. <el-dialog title="\u8fd0\u5355\u8be6\u60c5" :visible.sync="detailOpen" width="92%" top="3vh" append-to-body custom-class="waybill-detail-dialog" @closed="detailData = null">
  75. <waybill-detail v-if="detailData" :detail="detailData" />
  76. <div slot="footer">
  77. <el-button @click="detailOpen = false">\u5173 \u95ed</el-button>
  78. </div>
  79. </el-dialog>
  80. <el-dialog :title="title" :visible.sync="open" width="1280px" append-to-body :close-on-click-modal="false" @closed="onDialogClosed">
  81. <el-form ref="form" :model="form" :rules="rules" label-width="110px">
  82. <el-divider content-position="left">\u57fa\u7840\u4fe1\u606f</el-divider>
  83. <el-row :gutter="12">
  84. <el-col :span="6">
  85. <el-form-item label="\u8fd0\u5355\u53f7">
  86. <el-input v-model="form.waybillNo" readonly placeholder="\u4fdd\u5b58\u540e\u81ea\u52a8\u751f\u6210" />
  87. </el-form-item>
  88. </el-col>
  89. <el-col :span="6">
  90. <el-form-item label="\u8fd0\u8f93\u7c7b\u578b" prop="transportType">
  91. <el-select v-model="form.transportType" placeholder="\u8bf7\u9009\u62e9\u8fd0\u8f93\u7c7b\u578b" style="width: 100%">
  92. <el-option v-for="item in transportTypeOptions" :key="item" :label="item" :value="item" />
  93. </el-select>
  94. </el-form-item>
  95. </el-col>
  96. <el-col :span="6">
  97. <el-form-item label="\u5355\u636e\u65e5\u671f" prop="documentDate">
  98. <el-date-picker v-model="form.documentDate" type="date" value-format="yyyy-MM-dd" placeholder="\u8bf7\u9009\u62e9" style="width: 100%" />
  99. </el-form-item>
  100. </el-col>
  101. <el-col :span="6">
  102. <el-form-item label="\u5907\u6ce8">
  103. <el-input v-model="form.remark" placeholder="\u53ef\u9009\u586b\u5199" maxlength="500" />
  104. </el-form-item>
  105. </el-col>
  106. <el-col :span="6">
  107. <el-form-item label="\u9884\u8ba1\u53d1\u8f66" prop="planDepartTime">
  108. <el-date-picker v-model="form.planDepartTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="\u8bf7\u9009\u62e9" style="width: 100%" />
  109. </el-form-item>
  110. </el-col>
  111. <el-col :span="6">
  112. <el-form-item label="\u9884\u8ba1\u5230\u8fbe" prop="planArriveTime">
  113. <el-date-picker v-model="form.planArriveTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="\u8bf7\u9009\u62e9" style="width: 100%" />
  114. </el-form-item>
  115. </el-col>
  116. </el-row>
  117. <el-divider content-position="left">\u53d1\u8d27\u65b9</el-divider>
  118. <el-row :gutter="12">
  119. <el-col :span="8">
  120. <el-form-item label="\u53d1\u8d27\u4f01\u4e1a" prop="senderCompany">
  121. <el-input v-model="form.senderCompany" placeholder="\u8bf7\u8f93\u5165\u53d1\u8d27\u4f01\u4e1a" />
  122. </el-form-item>
  123. </el-col>
  124. <el-col :span="12">
  125. <el-form-item label="\u6240\u5728\u7701\u5e02\u53bf" prop="senderRegionArr">
  126. <el-cascader size="large" style="width: 100%" :options="regionOptions" v-model="form.senderRegionArr" clearable @change="handleSenderRegionChange" />
  127. </el-form-item>
  128. </el-col>
  129. <el-col :span="12">
  130. <el-form-item label="\u8be6\u7ec6\u5730\u5740" prop="senderAddressDetail">
  131. <el-input v-model="form.senderAddressDetail" placeholder="\u8bf7\u8f93\u5165\u8be6\u7ec6\u5730\u5740" />
  132. </el-form-item>
  133. </el-col>
  134. <el-col :span="6">
  135. <el-form-item label="\u8054\u7cfb\u4eba" prop="senderContact">
  136. <el-input v-model="form.senderContact" placeholder="\u8054\u7cfb\u4eba" />
  137. </el-form-item>
  138. </el-col>
  139. <el-col :span="6">
  140. <el-form-item label="\u8054\u7cfb\u7535\u8bdd" prop="senderPhone">
  141. <el-input v-model="form.senderPhone" placeholder="\u8054\u7cfb\u7535\u8bdd" />
  142. </el-form-item>
  143. </el-col>
  144. <el-col :span="12">
  145. <el-form-item label="\u88c5\u8d27\u65f6\u95f4\u8981\u6c42">
  146. <el-input v-model="form.loadTimeRequire" placeholder="\u5982\uff1a\u4e0a\u53488\u70b9\u524d\u5b8c\u6210\u88c5\u8d27" />
  147. </el-form-item>
  148. </el-col>
  149. </el-row>
  150. <el-divider content-position="left">\u6536\u8d27\u65b9</el-divider>
  151. <el-row :gutter="12">
  152. <el-col :span="8">
  153. <el-form-item label="\u6536\u8d27\u4f01\u4e1a" prop="receiverCompany">
  154. <el-input v-model="form.receiverCompany" placeholder="\u8bf7\u8f93\u5165\u6536\u8d27\u4f01\u4e1a" />
  155. </el-form-item>
  156. </el-col>
  157. <el-col :span="12">
  158. <el-form-item label="\u6240\u5728\u7701\u5e02\u53bf" prop="receiverRegionArr">
  159. <el-cascader size="large" style="width: 100%" :options="regionOptions" v-model="form.receiverRegionArr" clearable @change="handleReceiverRegionChange" />
  160. </el-form-item>
  161. </el-col>
  162. <el-col :span="12">
  163. <el-form-item label="\u8be6\u7ec6\u5730\u5740" prop="receiverAddressDetail">
  164. <el-input v-model="form.receiverAddressDetail" placeholder="\u8bf7\u8f93\u5165\u8be6\u7ec6\u5730\u5740" />
  165. </el-form-item>
  166. </el-col>
  167. <el-col :span="6">
  168. <el-form-item label="\u8054\u7cfb\u4eba" prop="receiverContact">
  169. <el-input v-model="form.receiverContact" placeholder="\u8054\u7cfb\u4eba" />
  170. </el-form-item>
  171. </el-col>
  172. <el-col :span="6">
  173. <el-form-item label="\u8054\u7cfb\u7535\u8bdd" prop="receiverPhone">
  174. <el-input v-model="form.receiverPhone" placeholder="\u8054\u7cfb\u7535\u8bdd" />
  175. </el-form-item>
  176. </el-col>
  177. <el-col :span="6">
  178. <el-form-item label="\u8ba1\u5212\u7b7e\u6536" prop="planSignTime">
  179. <el-date-picker v-model="form.planSignTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="\u8bf7\u9009\u62e9" style="width: 100%" />
  180. </el-form-item>
  181. </el-col>
  182. </el-row>
  183. <el-divider content-position="left">\u8d27\u7269\u660e\u7ec6</el-divider>
  184. <div class="mb8">
  185. <el-button type="primary" plain size="mini" icon="el-icon-plus" @click="addCargoRow">\u6dfb\u52a0\u8d27\u7269\u884c</el-button>
  186. </div>
  187. <el-table :data="form.cargoList" border size="small" show-summary :summary-method="cargoSummaryMethod">
  188. <el-table-column label="\u5e8f\u53f7" width="60" align="center">
  189. <template slot-scope="scope">{{ scope.$index + 1 }}</template>
  190. </el-table-column>
  191. <el-table-column label="\u8d27\u7269\u540d\u79f0" min-width="140">
  192. <template slot-scope="scope">
  193. <el-input v-model="scope.row.cargoName" placeholder="\u8d27\u7269\u540d\u79f0" />
  194. </template>
  195. </el-table-column>
  196. <el-table-column label="\u89c4\u683c\u578b\u53f7" min-width="120">
  197. <template slot-scope="scope">
  198. <el-input v-model="scope.row.specModel" placeholder="\u89c4\u683c\u578b\u53f7" />
  199. </template>
  200. </el-table-column>
  201. <el-table-column label="\u5355\u4f4d" width="90">
  202. <template slot-scope="scope">
  203. <el-input v-model="scope.row.unit" placeholder="\u5355\u4f4d" />
  204. </template>
  205. </el-table-column>
  206. <el-table-column label="\u6570\u91cf" width="120" align="right">
  207. <template slot-scope="scope">
  208. <el-input-number v-model="scope.row.quantity" :min="0" :precision="2" controls-position="right" style="width: 100%" @change="recalcCargoTotals" />
  209. </template>
  210. </el-table-column>
  211. <el-table-column label="\u91cd\u91cf(kg)" width="120" align="right">
  212. <template slot-scope="scope">
  213. <el-input-number v-model="scope.row.weightKg" :min="0" :precision="2" controls-position="right" style="width: 100%" @change="recalcCargoTotals" />
  214. </template>
  215. </el-table-column>
  216. <el-table-column label="\u4f53\u79ef(m\u00b3)" width="120" align="right">
  217. <template slot-scope="scope">
  218. <el-input-number v-model="scope.row.volumeM3" :min="0" :precision="3" controls-position="right" style="width: 100%" @change="recalcCargoTotals" />
  219. </template>
  220. </el-table-column>
  221. <el-table-column label="\u8d27\u503c(\u5143)" width="130" align="right">
  222. <template slot-scope="scope">
  223. <el-input-number v-model="scope.row.cargoValue" :min="0" :precision="2" controls-position="right" style="width: 100%" @change="recalcCargoTotals" />
  224. </template>
  225. </el-table-column>
  226. <el-table-column label="\u64cd\u4f5c" width="70" align="center">
  227. <template slot-scope="scope">
  228. <el-button type="text" size="mini" @click="removeCargoRow(scope.$index)">\u5220</el-button>
  229. </template>
  230. </el-table-column>
  231. </el-table>
  232. <el-divider content-position="left">\u8fd0\u8f93\u8981\u6c42</el-divider>
  233. <el-row :gutter="12">
  234. <el-col :span="6">
  235. <el-form-item label="\u6e29\u5ea6\u4e0a\u9650(\u2103)">
  236. <el-input-number v-model="form.tempMax" :precision="1" controls-position="right" style="width: 100%" />
  237. </el-form-item>
  238. </el-col>
  239. <el-col :span="6">
  240. <el-form-item label="\u6e29\u5ea6\u4e0b\u9650(\u2103)">
  241. <el-input-number v-model="form.tempMin" :precision="1" controls-position="right" style="width: 100%" />
  242. </el-form-item>
  243. </el-col>
  244. <el-col :span="6">
  245. <el-form-item label="\u6e7f\u5ea6\u8981\u6c42">
  246. <el-input v-model="form.humidityRequire" placeholder="\u5982\uff1a60%-70%" />
  247. </el-form-item>
  248. </el-col>
  249. <el-col :span="24">
  250. <el-form-item label="\u8fd0\u8f93\u7279\u6b8a\u8bf4\u660e">
  251. <el-input v-model="form.transportSpecialNote" type="textarea" :rows="2" placeholder="\u8bf7\u8f93\u5165\u8fd0\u8f93\u7279\u6b8a\u8bf4\u660e" />
  252. </el-form-item>
  253. </el-col>
  254. <el-col :span="24">
  255. <el-form-item label="\u8fd0\u8f93\u6807\u7b7e">
  256. <el-checkbox v-model="form.labelTempRecord" :true-label="1" :false-label="0">\u6e29\u5ea6\u8bb0\u5f55</el-checkbox>
  257. <el-checkbox v-model="form.labelFragile" :true-label="1" :false-label="0">\u6613\u788e\u54c1</el-checkbox>
  258. <el-checkbox v-model="form.labelShockproof" :true-label="1" :false-label="0">\u9632\u9707</el-checkbox>
  259. <el-checkbox v-model="form.labelMoistureproof" :true-label="1" :false-label="0">\u9632\u6f6e</el-checkbox>
  260. </el-form-item>
  261. </el-col>
  262. </el-row>
  263. <el-divider content-position="left">\u8d44\u6e90\u5206\u914d</el-divider>
  264. <el-row :gutter="12">
  265. <el-col :span="6">
  266. <el-form-item label="\u7269\u6d41\u7ebf\u8def" prop="lineNum">
  267. <el-select v-model="form.lineNum" placeholder="\u8bf7\u9009\u62e9\u7269\u6d41\u7ebf\u8def" filterable clearable style="width: 100%" @change="handleLineChange">
  268. <el-option v-for="line in lineList" :key="line.lineNum" :label="line.lineNum + ' - ' + line.lineName" :value="line.lineNum" />
  269. </el-select>
  270. </el-form-item>
  271. </el-col>
  272. <el-col :span="6">
  273. <el-form-item label="\u7ebf\u8def\u540d\u79f0">
  274. <el-input v-model="form.lineName" readonly />
  275. </el-form-item>
  276. </el-col>
  277. <el-col :span="6">
  278. <el-form-item label="\u8f66\u724c\u53f7">
  279. <el-input v-model="form.carNum" readonly />
  280. </el-form-item>
  281. </el-col>
  282. <el-col :span="6">
  283. <el-form-item label="\u8f66\u578b">
  284. <el-input v-model="form.carModel" readonly />
  285. </el-form-item>
  286. </el-col>
  287. <el-col :span="6">
  288. <el-form-item label="\u53f8\u673a\u59d3\u540d">
  289. <el-input v-model="form.driverName" readonly />
  290. </el-form-item>
  291. </el-col>
  292. <el-col :span="6">
  293. <el-form-item label="\u53f8\u673a\u7535\u8bdd">
  294. <el-input v-model="form.driverPhone" readonly />
  295. </el-form-item>
  296. </el-col>
  297. <el-col :span="6">
  298. <el-form-item label="\u9884\u4f30\u91cc\u7a0b(km)">
  299. <el-input v-model="form.estimateDistance" readonly />
  300. </el-form-item>
  301. </el-col>
  302. </el-row>
  303. </el-form>
  304. <div slot="footer" class="dialog-footer">
  305. <div class="submit-tip">\u63d0\u4ea4\u540e\u5c06\u8fdb\u5165\u5f85\u5ba1\u6838\u72b6\u6001\uff0c\u5ba1\u6838\u901a\u8fc7\u540e\u4e0d\u53ef\u4fee\u6539</div>
  306. <el-button type="primary" @click="submitForm">\u63d0 \u4ea4</el-button>
  307. <el-button @click="cancel">\u53d6 \u6d88</el-button>
  308. </div>
  309. </el-dialog>
  310. </div>
  311. </template>
  312. '''
  313. # fmt: on
  314. SCRIPT = r'''
  315. <script>
  316. import {
  317. listWaybill,
  318. getWaybill,
  319. addWaybill,
  320. updateWaybill,
  321. approveWaybill,
  322. delWaybill,
  323. previewWaybillNo
  324. } from "@/api/basic/waybill";
  325. import { getLogisticsList } from "@/api/baseInfo/logistics";
  326. import { getFindByKey } from "@/utils";
  327. import { regionData, CodeToText, TextToCode } from "element-plus-china-area";
  328. import WaybillDetail from "./components/WaybillDetail";
  329. export default {
  330. name: "TransportWaybill",
  331. components: { WaybillDetail },
  332. data() {
  333. return {
  334. loading: false,
  335. showSearch: true,
  336. total: 0,
  337. waybillList: [],
  338. ids: [],
  339. single: true,
  340. multiple: true,
  341. open: false,
  342. detailOpen: false,
  343. detailData: null,
  344. title: "",
  345. lineList: [],
  346. regionOptions: regionData,
  347. transportTypeOptions: ["\u51b7\u94fe\u8fd0\u8f93", "\u5e38\u6e29\u8fd0\u8f93", "\u6574\u8f66\u8fd0\u8f93", "\u96f6\u62c5\u8fd0\u8f93"],
  348. auditStatusOptions: [
  349. { value: 0, label: "\u8349\u7a3f" },
  350. { value: 1, label: "\u5f85\u5ba1\u6838" },
  351. { value: 2, label: "\u5df2\u901a\u8fc7" }
  352. ],
  353. queryParams: {
  354. pageNum: 1,
  355. pageSize: 10,
  356. waybillNo: undefined,
  357. transportType: undefined,
  358. senderCompany: undefined,
  359. receiverCompany: undefined,
  360. auditStatus: undefined
  361. },
  362. form: {},
  363. cargoTotals: { quantity: 0, weightKg: 0, volumeM3: 0, cargoValue: 0 },
  364. rules: {
  365. transportType: [{ required: true, message: "\u8bf7\u9009\u62e9\u8fd0\u8f93\u7c7b\u578b", trigger: "change" }],
  366. documentDate: [{ required: true, message: "\u8bf7\u9009\u62e9\u5355\u636e\u65e5\u671f", trigger: "change" }],
  367. planDepartTime: [{ required: true, message: "\u8bf7\u9009\u62e9\u9884\u8ba1\u53d1\u8f66\u65f6\u95f4", trigger: "change" }],
  368. planArriveTime: [{ required: true, message: "\u8bf7\u9009\u62e9\u9884\u8ba1\u5230\u8fbe\u65f6\u95f4", trigger: "change" }],
  369. senderCompany: [{ required: true, message: "\u53d1\u8d27\u4f01\u4e1a\u4e0d\u80fd\u4e3a\u7a7a", trigger: "blur" }],
  370. senderRegionArr: [{ required: true, message: "\u8bf7\u9009\u62e9\u53d1\u8d27\u7701\u5e02\u533a", trigger: "change" }],
  371. receiverCompany: [{ required: true, message: "\u6536\u8d27\u4f01\u4e1a\u4e0d\u80fd\u4e3a\u7a7a", trigger: "blur" }],
  372. receiverRegionArr: [{ required: true, message: "\u8bf7\u9009\u62e9\u6536\u8d27\u7701\u5e02\u533a", trigger: "change" }]
  373. }
  374. };
  375. },
  376. created() {
  377. this.getList();
  378. this.loadLineList();
  379. },
  380. methods: {
  381. auditStatusLabel(status) {
  382. const map = { 0: "\u8349\u7a3f", 1: "\u5f85\u5ba1\u6838", 2: "\u5df2\u901a\u8fc7" };
  383. return map[status] != null ? map[status] : "-";
  384. },
  385. auditTagType(status) {
  386. const map = { 0: "info", 1: "warning", 2: "success" };
  387. return map[status] || "info";
  388. },
  389. canEdit(row) {
  390. return row.auditStatus === 0 || row.auditStatus === 1;
  391. },
  392. loadLineList() {
  393. getLogisticsList({}).then((res) => {
  394. this.lineList = res.data || [];
  395. });
  396. },
  397. getList() {
  398. this.loading = true;
  399. listWaybill(this.queryParams).then((res) => {
  400. this.waybillList = res.rows || [];
  401. this.total = res.total || 0;
  402. this.loading = false;
  403. }).catch(() => { this.loading = false; });
  404. },
  405. buildEmptyCargoRow() {
  406. return { cargoName: "", specModel: "", unit: "", quantity: undefined, weightKg: undefined, volumeM3: undefined, cargoValue: undefined };
  407. },
  408. reset() {
  409. this.form = {
  410. id: undefined, waybillNo: "", transportType: undefined,
  411. documentDate: this.parseTime(new Date(), "{y}-{m}-{d}"),
  412. planDepartTime: undefined, planArriveTime: undefined, remark: "",
  413. senderCompany: "", senderRegionArr: [], senderProvince: "", senderCity: "", senderDistrict: "",
  414. senderAddressDetail: "", senderContact: "", senderPhone: "", loadTimeRequire: "",
  415. receiverCompany: "", receiverRegionArr: [], receiverProvince: "", receiverCity: "", receiverDistrict: "",
  416. receiverAddressDetail: "", receiverContact: "", receiverPhone: "", planSignTime: undefined,
  417. tempMax: undefined, tempMin: undefined, humidityRequire: "", transportSpecialNote: "",
  418. labelTempRecord: 0, labelFragile: 0, labelShockproof: 0, labelMoistureproof: 0,
  419. lineNum: undefined, lineName: "", carNum: "", carModel: "", driverName: "", driverPhone: "",
  420. estimateDistance: undefined, auditStatus: 1, cargoList: [this.buildEmptyCargoRow()]
  421. };
  422. this.recalcCargoTotals();
  423. this.resetForm("form");
  424. },
  425. fillForm(data) {
  426. this.form = Object.assign(this.resetFormData(), data || {});
  427. if (!this.form.cargoList || !this.form.cargoList.length) {
  428. this.form.cargoList = [this.buildEmptyCargoRow()];
  429. }
  430. this.$set(this.form, "senderRegionArr", this.textToRegionArr(this.form.senderProvince, this.form.senderCity, this.form.senderDistrict));
  431. this.$set(this.form, "receiverRegionArr", this.textToRegionArr(this.form.receiverProvince, this.form.receiverCity, this.form.receiverDistrict));
  432. this.recalcCargoTotals();
  433. },
  434. resetFormData() {
  435. return { cargoList: [this.buildEmptyCargoRow()], senderRegionArr: [], receiverRegionArr: [], labelTempRecord: 0, labelFragile: 0, labelShockproof: 0, labelMoistureproof: 0 };
  436. },
  437. getCodeToText(codeStr, codeArray) {
  438. if (codeStr == null && codeArray == null) return "";
  439. const arr = codeArray || (codeStr ? codeStr.split(",") : []);
  440. if (!arr.length) return "";
  441. let area = "";
  442. switch (arr.length) {
  443. case 1: area += CodeToText[arr[0]]; break;
  444. case 2: area += CodeToText[arr[0]] + "/" + CodeToText[arr[1]]; break;
  445. case 3: area += CodeToText[arr[0]] + "/" + CodeToText[arr[1]] + "/" + CodeToText[arr[2]]; break;
  446. default: break;
  447. }
  448. return area;
  449. },
  450. applyRegionText(prefix, codeArray) {
  451. const parts = (this.getCodeToText(null, codeArray) || "").split("/");
  452. this.form[prefix + "Province"] = parts[0] || "";
  453. this.form[prefix + "City"] = parts[1] || "";
  454. this.form[prefix + "District"] = parts[2] || "";
  455. },
  456. textToRegionArr(province, city, district) {
  457. const arr = [];
  458. if (!province) return arr;
  459. try {
  460. const provinceNode = TextToCode[province];
  461. if (!provinceNode || !provinceNode.code) return arr;
  462. arr.push(provinceNode.code);
  463. if (city && provinceNode[city] && provinceNode[city].code) {
  464. const cityNode = provinceNode[city];
  465. arr.push(cityNode.code);
  466. if (district && cityNode[district] && cityNode[district].code) {
  467. arr.push(cityNode[district].code);
  468. }
  469. }
  470. } catch (e) { return []; }
  471. return arr;
  472. },
  473. handleSenderRegionChange(value) {
  474. this.form.senderRegionArr = value || [];
  475. this.applyRegionText("sender", this.form.senderRegionArr);
  476. },
  477. handleReceiverRegionChange(value) {
  478. this.form.receiverRegionArr = value || [];
  479. this.applyRegionText("receiver", this.form.receiverRegionArr);
  480. },
  481. syncRegionFieldsBeforeSubmit() {
  482. this.applyRegionText("sender", this.form.senderRegionArr);
  483. this.applyRegionText("receiver", this.form.receiverRegionArr);
  484. },
  485. handleQuery() { this.queryParams.pageNum = 1; this.getList(); },
  486. resetQuery() { this.resetForm("queryForm"); this.handleQuery(); },
  487. handleSelectionChange(selection) {
  488. this.ids = selection.map((item) => item.id);
  489. this.single = selection.length !== 1;
  490. this.multiple = !selection.length;
  491. },
  492. handleAdd() {
  493. this.reset();
  494. previewWaybillNo().then((res) => { this.form.waybillNo = res.data || ""; });
  495. this.open = true;
  496. this.title = "\u65b0\u589e\u8fd0\u5355";
  497. },
  498. handleView(row) {
  499. const id = row.id || this.ids[0];
  500. getWaybill(id).then((res) => {
  501. this.detailData = res.data || {};
  502. this.detailOpen = true;
  503. });
  504. },
  505. handleUpdate(row) {
  506. const id = row.id || this.ids[0];
  507. getWaybill(id).then((res) => { this.fillForm(res.data); this.open = true; this.title = "\u4fee\u6539\u8fd0\u5355"; });
  508. },
  509. handleApprove(row) {
  510. const id = row && row.id ? row.id : this.ids[0];
  511. if (!id) { this.$modal.msgWarning("\u8bf7\u9009\u62e9\u8981\u5ba1\u6838\u7684\u8bb0\u5f55"); return; }
  512. const target = row || this.waybillList.find((item) => item.id === id);
  513. if (target && target.auditStatus !== 1) { this.$modal.msgWarning("\u4ec5\u5f85\u5ba1\u6838\u72b6\u6001\u53ef\u5ba1\u6838\u901a\u8fc7"); return; }
  514. this.$modal.confirm('\u786e\u8ba4\u5ba1\u6838\u901a\u8fc7\u8fd0\u5355"' + (target ? target.waybillNo : id) + '"\u5417\uff1f').then(() => approveWaybill(id)).then(() => {
  515. this.$modal.msgSuccess("\u5ba1\u6838\u6210\u529f");
  516. this.getList();
  517. }).catch(() => {});
  518. },
  519. handleLineChange(lineNum) {
  520. const item = getFindByKey(this.lineList, lineNum, "lineNum");
  521. if (!item) {
  522. this.form.lineName = ""; this.form.carNum = ""; this.form.carModel = "";
  523. this.form.driverName = ""; this.form.driverPhone = ""; this.form.estimateDistance = undefined;
  524. return;
  525. }
  526. this.form.lineName = item.lineName;
  527. this.form.carNum = item.carNum;
  528. this.form.carModel = item.carModel;
  529. this.form.driverName = item.driverName;
  530. this.form.driverPhone = item.phone;
  531. this.form.estimateDistance = item.totalMileage;
  532. },
  533. addCargoRow() { this.form.cargoList.push(this.buildEmptyCargoRow()); },
  534. removeCargoRow(index) {
  535. this.form.cargoList.splice(index, 1);
  536. if (!this.form.cargoList.length) this.form.cargoList.push(this.buildEmptyCargoRow());
  537. this.recalcCargoTotals();
  538. },
  539. sumField(list, field) {
  540. return (list || []).reduce((sum, row) => sum + Number(row[field] || 0), 0);
  541. },
  542. recalcCargoTotals() {
  543. const list = this.form.cargoList || [];
  544. this.cargoTotals = {
  545. quantity: this.sumField(list, "quantity"),
  546. weightKg: this.sumField(list, "weightKg"),
  547. volumeM3: this.sumField(list, "volumeM3"),
  548. cargoValue: this.sumField(list, "cargoValue")
  549. };
  550. this.form.totalQuantity = this.cargoTotals.quantity;
  551. this.form.totalWeight = this.cargoTotals.weightKg;
  552. this.form.totalVolume = this.cargoTotals.volumeM3;
  553. this.form.totalValue = this.cargoTotals.cargoValue;
  554. },
  555. cargoSummaryMethod({ columns }) {
  556. const sums = [];
  557. columns.forEach((column, index) => {
  558. if (index === 0) { sums[index] = "\u5408\u8ba1"; return; }
  559. if (column.label === "\u6570\u91cf") sums[index] = this.formatNum(this.cargoTotals.quantity, 2);
  560. else if (column.label === "\u91cd\u91cf(kg)") sums[index] = this.formatNum(this.cargoTotals.weightKg, 2);
  561. else if (column.label === "\u4f53\u79ef(m\u00b3)") sums[index] = this.formatNum(this.cargoTotals.volumeM3, 3);
  562. else if (column.label === "\u8d27\u503c(\u5143)") sums[index] = this.formatNum(this.cargoTotals.cargoValue, 2);
  563. else sums[index] = "";
  564. });
  565. return sums;
  566. },
  567. formatNum(val, precision) { return Number(val || 0).toFixed(precision); },
  568. validateCargoList() {
  569. const list = (this.form.cargoList || []).filter((row) => row.cargoName || row.unit || row.quantity);
  570. if (!list.length) { this.$modal.msgError("\u8bf7\u81f3\u5c11\u6dfb\u52a0\u4e00\u6761\u8d27\u7269\u660e\u7ec6"); return false; }
  571. for (let i = 0; i < list.length; i++) {
  572. const row = list[i];
  573. if (!row.cargoName) { this.$modal.msgError("\u7b2c" + (i + 1) + "\u884c\u8d27\u7269\u540d\u79f0\u4e0d\u80fd\u4e3a\u7a7a"); return false; }
  574. if (!row.unit) { this.$modal.msgError("\u7b2c" + (i + 1) + "\u884c\u5355\u4f4d\u4e0d\u80fd\u4e3a\u7a7a"); return false; }
  575. if (!row.quantity || Number(row.quantity) <= 0) { this.$modal.msgError("\u7b2c" + (i + 1) + "\u884c\u6570\u91cf\u5fc5\u987b\u5927\u4e8e0"); return false; }
  576. }
  577. this.form.cargoList = list;
  578. return true;
  579. },
  580. buildPayload() {
  581. this.syncRegionFieldsBeforeSubmit();
  582. this.recalcCargoTotals();
  583. return {
  584. ...this.form,
  585. auditStatus: this.form.auditStatus != null ? this.form.auditStatus : 1,
  586. cargoList: (this.form.cargoList || []).map((row, index) => ({
  587. id: row.id, cargoName: row.cargoName, specModel: row.specModel, unit: row.unit,
  588. quantity: row.quantity, weightKg: row.weightKg, volumeM3: row.volumeM3, cargoValue: row.cargoValue, sortOrder: index
  589. }))
  590. };
  591. },
  592. submitForm() {
  593. this.$refs.form.validate((valid) => {
  594. if (!valid) return;
  595. if (!this.validateCargoList()) return;
  596. const payload = this.buildPayload();
  597. const request = payload.id ? updateWaybill(payload) : addWaybill(payload);
  598. this.$modal.confirm("\u786e\u8ba4\u63d0\u4ea4\u8fd0\u5355\u5417\uff1f").then(() => request).then(() => {
  599. this.$modal.msgSuccess("\u63d0\u4ea4\u6210\u529f");
  600. this.open = false;
  601. this.getList();
  602. }).catch(() => {});
  603. });
  604. },
  605. cancel() { this.open = false; },
  606. onDialogClosed() { this.reset(); },
  607. handleDelete(row) {
  608. const ids = row && row.id ? row.id : this.ids.join(",");
  609. if (!ids) return;
  610. const nos = row && row.waybillNo ? row.waybillNo : ids;
  611. this.$modal.confirm('\u662f\u5426\u786e\u8ba4\u5220\u9664\u8fd0\u5355\u7f16\u53f7\u4e3a"' + nos + '"\u7684\u6570\u636e\u9879\uff1f').then(() => delWaybill(ids)).then(() => {
  612. this.$modal.msgSuccess("\u5220\u9664\u6210\u529f");
  613. this.getList();
  614. }).catch(() => {});
  615. }
  616. }
  617. };
  618. </script>
  619. <style scoped lang="scss">
  620. .submit-tip { float: left; line-height: 32px; font-size: 12px; color: #e6a23c; }
  621. .dialog-footer { overflow: hidden; }
  622. </style>
  623. <style lang="scss">
  624. .waybill-detail-dialog .el-dialog__body {
  625. padding: 12px 20px 8px;
  626. max-height: calc(100vh - 140px);
  627. overflow-y: auto;
  628. }
  629. </style>
  630. '''
  631. def main():
  632. content = VUE.encode("utf-8").decode("unicode_escape") + SCRIPT.encode("utf-8").decode("unicode_escape")
  633. os.makedirs(os.path.dirname(OUT), exist_ok=True)
  634. with open(OUT, "w", encoding="utf-8", newline="\n") as f:
  635. f.write(content)
  636. print("written", OUT, len(content))
  637. if __name__ == "__main__":
  638. main()