PurchaseArea.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <el-form
  3. class="pd"
  4. ref="dataForm"
  5. v-loading="loading"
  6. :model="dataForm"
  7. :rules="dataFormRules"
  8. label-position="left"
  9. label-width="90px"
  10. >
  11. <el-form-item v-if="formDisabled" label="单据编号" prop="purchaseId">
  12. <el-input disabled :value="dataForm.purchaseId" />
  13. </el-form-item>
  14. <el-row :gutter="20">
  15. <el-col :span="8">
  16. <el-form-item label="网点" prop="websitId">
  17. <el-select v-model="dataForm.websitId" :disabled="formDisabled" placeholder="请选择网点" style="width: 100%">
  18. <el-option v-for="(item, index) in authShop" :key="index" :label="item.name" :value="item.websitId" />
  19. </el-select>
  20. </el-form-item>
  21. </el-col>
  22. <el-col :span="8">
  23. <el-form-item label="供应商" prop="venderId">
  24. <el-select
  25. v-model="dataForm.venderId"
  26. filterable
  27. :disabled="formDisabled"
  28. placeholder="请选择供应商"
  29. style="width: 100%"
  30. >
  31. <el-option
  32. v-for="(item, index) in venderList"
  33. :key="index"
  34. :label="item.venderName"
  35. :value="item.venderId"
  36. :disabled="item.status !== 'ON'"
  37. />
  38. </el-select>
  39. </el-form-item>
  40. </el-col>
  41. <el-col :span="8">
  42. <el-form-item label="采购日期" prop="purchaseTime">
  43. <el-date-picker
  44. v-model="dataForm.purchaseTime"
  45. type="date"
  46. placeholder="选择采购日期"
  47. value-format="yyyy-MM-dd HH:mm:ss"
  48. :disabled="inputParam.openType === 'view'"
  49. style="width: 100%"
  50. />
  51. </el-form-item>
  52. </el-col>
  53. </el-row>
  54. <el-form-item label="采购单图片" prop="image">
  55. <template v-if="inputParam.openType !== 'view'">
  56. <el-upload
  57. v-loading="imageLoading"
  58. element-loading-text="上传中"
  59. element-loading-spinner="el-icon-loading"
  60. element-loading-background="rgba(0, 0, 0, 0.8)"
  61. :disabled="imageLoading"
  62. class="avatar-uploader"
  63. :action="baseURL + 'common/upload'"
  64. :headers="myHeaders"
  65. :show-file-list="false"
  66. :on-success="uploadSuccess"
  67. :before-upload="beforeUpload"
  68. :on-error="uploadError"
  69. >
  70. <img v-if="dataForm.image" :src="$showImgUrl(dataForm.image)" class="avatar" alt="" />
  71. <i v-else class="el-icon-plus avatar-uploader-icon" />
  72. <div slot="tip" class="el-upload__tip" style="margin-top: 0; line-height: 20px">只支持上传jpg/png文件</div>
  73. </el-upload>
  74. </template>
  75. <template v-else>
  76. <el-image
  77. v-if="dataForm.image"
  78. style="width: 100px; height: 100px"
  79. :src="$showImgUrl(dataForm.image)"
  80. :preview-src-list="[$showImgUrl(dataForm.image)]"
  81. />
  82. </template>
  83. </el-form-item>
  84. <el-form-item v-if="dataForm.notes3" label="申请单备注">
  85. <el-input v-model="dataForm.notes3" disabled />
  86. </el-form-item>
  87. <el-form-item v-if="dataForm.notes2" label="供应商备注">
  88. <el-input v-model="dataForm.notes2" disabled />
  89. </el-form-item>
  90. <el-form-item label="备注" prop="notes">
  91. <el-input
  92. v-model="dataForm.notes"
  93. autocomplete="off"
  94. placeholder="备注"
  95. :disabled="inputParam.openType === 'view'"
  96. />
  97. </el-form-item>
  98. <el-row>
  99. <el-col>
  100. <el-divider>采购明细</el-divider>
  101. </el-col>
  102. <el-col>
  103. <el-table
  104. ref="goodsTable"
  105. :data="dataForm.items"
  106. max-height="500"
  107. size="mini"
  108. border
  109. header-cell-class-name="headerRowColor"
  110. show-summary
  111. :summary-method="getSummaries"
  112. class="detail-table"
  113. >
  114. <el-table-column prop="goodsId" label="辅材编号" min-width="140" />
  115. <el-table-column prop="goodsName" label="辅材名称" min-width="140" />
  116. <el-table-column prop="purchaseQty" label="订货数量" header-align="left" align="center" />
  117. <el-table-column prop="deliverQty" label="供应数量" header-align="left" align="center" />
  118. <el-table-column prop="estimateCost" label="预估进价" header-align="left" align="center" />
  119. <el-table-column prop="cost" label="进价" header-align="left" align="center">
  120. <template slot-scope="{ $index, row }">
  121. <label v-if="inputParam.openType === 'view'">{{ row.cost }}</label>
  122. <el-form-item
  123. v-else
  124. style="margin: 18px 0"
  125. label-width="0"
  126. size="mini"
  127. :prop="'items.' + $index + '.cost'"
  128. :rules="dataFormRules.cost"
  129. >
  130. <el-input v-model="row.cost" size="mini" @change="changeCostValue($index, row)" />
  131. </el-form-item>
  132. </template>
  133. </el-table-column>
  134. <el-table-column prop="recQty" label="验收数量" header-align="left" align="center" width="100">
  135. <template slot-scope="{ $index, row }">
  136. <label v-if="inputParam.openType === 'view'">{{ row.recQty + ' /' + row.goodsStockUnit }}</label>
  137. <el-form-item
  138. v-else
  139. style="margin: 18px 0"
  140. label-width="0"
  141. size="mini"
  142. :prop="'items.' + $index + '.recQty'"
  143. :rules="dataFormRules.recQty"
  144. >
  145. <el-input v-model="row.recQty" size="mini" @change="changeCostValue($index, row)">
  146. <template slot="suffix">{{ row.goodsStockUnit }}</template>
  147. </el-input>
  148. </el-form-item>
  149. </template>
  150. </el-table-column>
  151. <el-table-column prop="recGiftQty" label="赠品数量" header-align="left" align="center">
  152. <template slot-scope="{ $index, row }">
  153. <label v-if="inputParam.openType === 'view'">{{ row.recGiftQty + ' /' + row.goodsStockUnit }}</label>
  154. <el-form-item
  155. v-else
  156. style="margin: 18px 0"
  157. label-width="0"
  158. size="mini"
  159. :prop="'items.' + $index + '.recGiftQty'"
  160. :rules="dataFormRules.recGiftQty"
  161. >
  162. <el-input v-model="row.recGiftQty" size="mini">
  163. <template slot="suffix">{{ row.goodsStockUnit }}</template>
  164. </el-input>
  165. </el-form-item>
  166. </template>
  167. </el-table-column>
  168. <el-table-column prop="costValue" label="验收金额" header-align="left" align="center" />
  169. <el-table-column prop="inStockQty" label="入库数量" header-align="left" align="center" width="100">
  170. <template slot-scope="{ $index, row }">
  171. <label>{{ row.inStockQty }}</label>
  172. </template>
  173. </el-table-column>
  174. <el-table-column prop="inStockCost" label="入库进价" header-align="left" align="center" width="100">
  175. <template slot-scope="{ $index, row }">
  176. <label>{{ row.inStockCost + ' 元' }}</label>
  177. </template>
  178. </el-table-column>
  179. <el-table-column prop="goodsStockUnit" label="采购单位" />
  180. <el-table-column prop="goodsSpecification" label="规格" />
  181. </el-table>
  182. <el-row>
  183. <el-col :span="24"
  184. ><div>共 {{ goodsTotalCount }} 条记录</div></el-col
  185. >
  186. </el-row>
  187. </el-col>
  188. </el-row>
  189. <div style="text-align: right">
  190. <el-button @click="cancelForm">取 消</el-button>
  191. <el-button
  192. v-if="$restrict('edit') && dataForm.flag === 'SUBMIT' && dataForm.isRecheck === 'YES'"
  193. type="primary"
  194. :disabled="saveBtn"
  195. @click="submitForm('edit')"
  196. >保 存</el-button
  197. >
  198. <el-button
  199. v-if="$restrict('confirm') && dataForm.flag === 'SUBMIT' && dataForm.isRecheck === 'YES'"
  200. type="success"
  201. @click="confirmSheet(dataForm.purchaseId)"
  202. >审 核</el-button
  203. >
  204. </div>
  205. </el-form>
  206. </template>
  207. <script>
  208. import { computeVal } from '@/api/material-system/common'
  209. import { getToken } from '@/utils/auth'
  210. import { confirmPurchaseSheet, editPurchaseSheet, getPurchaseSheet } from '@/api/material-system/shop/purchase-sheet'
  211. import { listPageV2 } from '@/api/auxiliaryFittings/supplier'
  212. import { getWebsit } from '@/api/customerManagement.js'
  213. export default {
  214. name: 'PurchaseArea',
  215. props: {
  216. inputParam: {
  217. type: Object,
  218. default: function () {
  219. return {
  220. openType: 'add',
  221. purchaseId: ''
  222. }
  223. }
  224. }
  225. },
  226. data() {
  227. const validateCost = (rule, value, callback) => {
  228. this.saveBtn = true
  229. if (Number.isNaN(parseFloat(value))) {
  230. return callback(new Error('请输入数字值'))
  231. }
  232. if (parseFloat(value) < 0) {
  233. return callback(new Error('不能少于0'))
  234. }
  235. this.saveBtn = false
  236. callback()
  237. }
  238. const validateRecQty = (rule, value, callback) => {
  239. this.saveBtn = true
  240. if (Number.isNaN(parseFloat(value))) {
  241. return callback(new Error('请输入数字值'))
  242. }
  243. if (parseFloat(value) < 0) {
  244. return callback(new Error('不能少于0'))
  245. }
  246. this.saveBtn = false
  247. callback()
  248. }
  249. const validateRecGiftQty = (rule, value, callback) => {
  250. this.saveBtn = true
  251. if (Number.isNaN(parseFloat(value))) {
  252. return callback(new Error('请输入数字值'))
  253. }
  254. if (parseFloat(value) < 0) {
  255. return callback(new Error('不能少于0'))
  256. }
  257. this.saveBtn = false
  258. callback()
  259. }
  260. return {
  261. imageLoading: false,
  262. loading: true,
  263. baseURL: process.env.VUE_APP_BASE_API,
  264. myHeaders: { 'x-token': getToken() },
  265. dataForm: {
  266. purchaseId: '', // 单据ID
  267. websitId: '', // 网点ID
  268. websitName: '', // 网点名称
  269. venderId: '', // 供应商ID
  270. venderName: '', // 供应商名称
  271. purchaseTime: '', // 采购日期
  272. image: '',
  273. notes: '', // 备注
  274. flag: '',
  275. items: [] // 关系辅材列表
  276. },
  277. dataFormRules: {
  278. purchaseTime: [{ require: true, message: '请选择采购日期', trigger: 'blur' }],
  279. cost: [{ validator: validateCost, trigger: 'blur' }],
  280. recQty: [{ validator: validateRecQty, trigger: 'blur' }],
  281. recGiftQty: [{ validator: validateRecGiftQty, trigger: 'blur' }]
  282. },
  283. orgDataForm: {},
  284. goodsList: [], // 商品列表
  285. venderList: [], // 供应商列表
  286. innerVisible: false,
  287. searchGoods: '',
  288. saveBtn: false, // 保存按钮状态
  289. authShop: []
  290. }
  291. },
  292. computed: {
  293. formDisabled() {
  294. return this.inputParam.openType === 'view' || this.dataForm.purchaseId !== ''
  295. },
  296. goodsTotalCount: function () {
  297. return this.dataForm && this.dataForm.items ? this.dataForm.items.length : 0
  298. }
  299. },
  300. mounted() {
  301. this.getDetail()
  302. this.getVenderList()
  303. getWebsit({ type: 'C', status: true }).then(res => {
  304. this.authShop = res.data
  305. })
  306. },
  307. methods: {
  308. getDetail(id) {
  309. this.loading = true
  310. const openType = this.inputParam.openType
  311. const purchaseId = id || this.inputParam.purchaseId
  312. if (openType !== 'add') {
  313. getPurchaseSheet({ purchaseId }).then(res => {
  314. this.setDataForm(res.data)
  315. this.loading = false
  316. })
  317. } else {
  318. this.loading = false
  319. }
  320. },
  321. cancelForm() {
  322. this.$parent.backUpdPage()
  323. },
  324. submitForm(type) {
  325. if (this.dataForm.items && this.dataForm.items.length === 0) {
  326. this.$errorMsg('请添加商品后再保存!')
  327. return
  328. }
  329. this.$refs.dataForm.validate(valid => {
  330. if (!this.dataForm.image) {
  331. this.$errorMsg('请添加附件图片')
  332. return
  333. }
  334. if (valid) {
  335. if (type === 'edit') {
  336. editPurchaseSheet(this.dataForm).then(() => {
  337. this.getDetail(this.dataForm.purchaseId)
  338. this.$successMsg('保存成功')
  339. })
  340. }
  341. }
  342. })
  343. },
  344. setDataForm(data) {
  345. this.dataForm = {
  346. purchaseId: data.purchaseId, // 单据编号
  347. websitId: data.websitId, // 网点ID
  348. venderId: data.venderId, // 供应商Id
  349. purchaseTime: data.purchaseTime, // 采购日期
  350. flag: data.flag,
  351. image: data.image,
  352. notes: data.notes, // 备注
  353. items: data.items, // 关系商品列表
  354. isRecheck: data.isRecheck
  355. }
  356. Object.assign(this.orgDataForm, this.dataForm)
  357. },
  358. // 获取供应商列表
  359. getVenderList() {
  360. listPageV2({
  361. pageNum: 1,
  362. pageSize: -1,
  363. params: [
  364. { param: 'a.status', compare: '=', value: 'ON' },
  365. { param: 'a.vender_type', compare: 'like', value: '辅材' }
  366. ]
  367. }).then(res => {
  368. this.venderList = res.data.records
  369. })
  370. },
  371. // 预估进价或申请数量变动
  372. changeCostValue(index, row) {
  373. computeVal({
  374. frontVal: row.applyQty,
  375. afterVal: row.applyCost,
  376. operator: '*',
  377. scale: 2
  378. }).then(res => {
  379. this.dataForm.items[index].applyCostValue = res.data
  380. })
  381. },
  382. getSummaries(param) {
  383. const { columns, data } = param
  384. const sums = []
  385. columns.forEach((column, index) => {
  386. if (index === 0) {
  387. sums[index] = '合计'
  388. return
  389. }
  390. const values = data.map(item => Number(item[column.property]))
  391. if (column.property === 'applyCostValue') {
  392. let count = 0
  393. sums[index] = values.reduce((prev, curr) => {
  394. const suffix = (curr + '').split('.')
  395. if (suffix.length > 1) {
  396. count = suffix[1].length > count ? suffix[1].length : count
  397. }
  398. const value = Number(curr)
  399. if (!isNaN(value)) {
  400. return prev + curr
  401. } else {
  402. return prev
  403. }
  404. }, 0)
  405. sums[index] = parseFloat(sums[index]).toFixed(count)
  406. }
  407. })
  408. return sums
  409. },
  410. // 上传成功回调
  411. uploadSuccess(res) {
  412. this.imageLoading = false
  413. this.dataForm.image = res.data.url
  414. },
  415. // 上传前检查
  416. beforeUpload(file) {
  417. if (this.imageLoading) {
  418. this.$errorMsg('文件上传中,稍后再试!')
  419. return false
  420. }
  421. const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)
  422. const whiteList = ['jpg', 'jpeg', 'png']
  423. if (whiteList.indexOf(fileSuffix) === -1) {
  424. this.$errorMsg('只支持上传jpg/png文件!')
  425. return false
  426. }
  427. this.imageLoading = true
  428. },
  429. uploadError() {
  430. this.imageLoading = false
  431. },
  432. // 审核 采购入库单
  433. confirmSheet(purchaseId) {
  434. this.$confirm(
  435. `此操作将审核 ${purchaseId} 单据,<span style="color: #ff0000;">当前内容如果已修改将忽略保存</span>,是否继续?`,
  436. '提示',
  437. {
  438. confirmButtonText: '确定',
  439. cancelButtonText: '取消',
  440. type: 'warning',
  441. dangerouslyUseHTMLString: true
  442. }
  443. )
  444. .then(() => {
  445. this.loading = true
  446. confirmPurchaseSheet({ purchaseId: purchaseId }).then(
  447. () => {
  448. setTimeout(() => {
  449. this.inputParam.openType = 'view'
  450. this.getDetail(purchaseId)
  451. this.$successMsg('审核成功')
  452. this.loading = false
  453. }, 2000)
  454. },
  455. () => {
  456. this.loading = false
  457. }
  458. )
  459. })
  460. .catch(() => console.log('取消'))
  461. }
  462. }
  463. }
  464. </script>
  465. <style lang="scss" scoped>
  466. .detail-table {
  467. width: 100%;
  468. margin: 15px 0;
  469. ::v-deep .el-input__suffix-inner {
  470. color: red;
  471. }
  472. }
  473. .pd {
  474. padding: 20px 20px 0 20px;
  475. }
  476. </style>