MaterialList.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. <!-- by 7527189 2 0 -->
  2. <template>
  3. <a-row :gutter="24">
  4. <a-col :md="24">
  5. <a-card :bordered="false">
  6. <!-- 查询区域 -->
  7. <div class="table-page-search-wrapper">
  8. <!-- 搜索区域 -->
  9. <a-form layout="inline" @keyup.enter.native="searchQuery">
  10. <a-row :gutter="24">
  11. <a-col :md="6" :sm="24">
  12. <a-form-item label="类别" :labelCol="labelCol" :wrapperCol="wrapperCol">
  13. <a-tree-select
  14. style="width: 100%"
  15. :dropdownStyle="{ maxHeight: '200px', overflow: 'auto' }"
  16. allow-clear
  17. :treeData="categoryTree"
  18. v-model="queryParam.categoryId"
  19. placeholder="请选择类别"
  20. >
  21. </a-tree-select>
  22. </a-form-item>
  23. </a-col>
  24. <a-col :md="6" :sm="24">
  25. <a-form-item label="关键词" :labelCol="labelCol" :wrapperCol="wrapperCol">
  26. <a-input placeholder="请输入条码、名称、助记码等查询" v-model="queryParam.materialParam"></a-input>
  27. </a-form-item>
  28. </a-col>
  29. <a-col :md="6" :sm="24">
  30. <a-form-item label="规格" :labelCol="labelCol" :wrapperCol="wrapperCol">
  31. <a-input placeholder="请输入规格查询" v-model="queryParam.standard"></a-input>
  32. </a-form-item>
  33. </a-col>
  34. <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  35. <a-col :md="6" :sm="24">
  36. <a-button type="primary" @click="searchQuery">查询</a-button>
  37. <a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
  38. <a @click="handleToggleSearch" style="margin-left: 8px">
  39. {{ toggleSearchStatus ? '收起' : '展开' }}
  40. <a-icon :type="toggleSearchStatus ? 'up' : 'down'" />
  41. </a>
  42. </a-col>
  43. </span>
  44. </a-row>
  45. <template v-if="toggleSearchStatus">
  46. <a-row :gutter="24">
  47. <a-col :md="6" :sm="24">
  48. <a-form-item label="型号" :labelCol="labelCol" :wrapperCol="wrapperCol">
  49. <a-input placeholder="请输入型号查询" v-model="queryParam.model"></a-input>
  50. </a-form-item>
  51. </a-col>
  52. <a-col :md="6" :sm="24">
  53. <a-form-item label="颜色" :labelCol="labelCol" :wrapperCol="wrapperCol">
  54. <a-input placeholder="请输入颜色查询" v-model="queryParam.color"></a-input>
  55. </a-form-item>
  56. </a-col>
  57. <a-col :md="6" :sm="24">
  58. <a-form-item label="品牌" :labelCol="labelCol" :wrapperCol="wrapperCol">
  59. <a-input placeholder="请输入品牌查询" v-model="queryParam.brand"></a-input>
  60. </a-form-item>
  61. </a-col>
  62. <a-col :md="6" :sm="24">
  63. <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
  64. <a-select placeholder="请选择状态" v-model="queryParam.enabled">
  65. <a-select-option value="1">启用</a-select-option>
  66. <a-select-option value="0">禁用</a-select-option>
  67. </a-select>
  68. </a-form-item>
  69. </a-col>
  70. <a-col :md="6" :sm="24">
  71. <a-form-item label="序列号" :labelCol="labelCol" :wrapperCol="wrapperCol">
  72. <a-select placeholder="有无序列号" v-model="queryParam.enableSerialNumber">
  73. <a-select-option value="1">有</a-select-option>
  74. <a-select-option value="0">无</a-select-option>
  75. </a-select>
  76. </a-form-item>
  77. </a-col>
  78. <a-col :md="6" :sm="24">
  79. <a-form-item label="扩展信息" :labelCol="labelCol" :wrapperCol="wrapperCol">
  80. <a-input
  81. style="width: 100%"
  82. placeholder="请输入扩展信息查询"
  83. v-model="queryParam.materialOther"
  84. ></a-input>
  85. </a-form-item>
  86. </a-col>
  87. <a-col :md="6" :sm="24">
  88. <a-form-item label="基础重量" :labelCol="labelCol" :wrapperCol="wrapperCol">
  89. <a-input-number
  90. style="width: 100%"
  91. placeholder="请输入基础重量查询"
  92. v-model="queryParam.weight"
  93. ></a-input-number>
  94. </a-form-item>
  95. </a-col>
  96. <a-col :md="6" :sm="24">
  97. <a-form-item label="预警提示" :labelCol="labelCol" :wrapperCol="wrapperCol">
  98. <a-select v-model="queryParam.reminder" option-label-prop="title" placeholder="请选择预警提示">
  99. <a-select-option key="临期" value="临期" title="临期">临期</a-select-option>
  100. <a-select-option key="无动销" value="无动销" title="无动销">无动销</a-select-option>
  101. <a-select-option key="库存危险" value="库存危险" title="库存危险">库存危险</a-select-option>
  102. </a-select>
  103. </a-form-item>
  104. </a-col>
  105. <a-col :md="6" :sm="24">
  106. <a-form-item label="备注" :labelCol="labelCol" :wrapperCol="wrapperCol">
  107. <a-input placeholder="请输入备注查询" v-model="queryParam.remark"></a-input>
  108. </a-form-item>
  109. </a-col>
  110. </a-row>
  111. </template>
  112. </a-form>
  113. </div>
  114. <!-- 操作按钮区域 -->
  115. <div class="table-operator" style="margin-top: 5px">
  116. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="handleAdd" type="primary" icon="plus">新增</a-button>
  117. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchDel" icon="delete">删除</a-button>
  118. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchSetStatus(true)" icon="check-square"
  119. >启用</a-button
  120. >
  121. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchSetStatus(false)" icon="close-square"
  122. >禁用</a-button
  123. >
  124. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="handleImportXls()" icon="import">导入</a-button>
  125. <a-button v-if="btnEnableList.indexOf(3) > -1" @click="handleExportXls('商品信息')" icon="download"
  126. >导出</a-button
  127. >
  128. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchEdit()" icon="edit">批量编辑</a-button>
  129. <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchSetMaterialCurrentStock()" icon="stock"
  130. >修正库存</a-button
  131. >
  132. <!-- <a-button v-if="btnEnableList.indexOf(1) > -1" @click="batchSetMaterialCurrentUnitPrice()" icon="fund"
  133. >修正成本</a-button
  134. > -->
  135. <a-popover trigger="click" placement="right">
  136. <template slot="content">
  137. <a-checkbox-group @change="onColChange" v-model="settingDataIndex" :defaultValue="settingDataIndex">
  138. <a-row style="width: 500px">
  139. <template>
  140. <div v-for="(item, index) in defColumns" :key="index">
  141. <a-col :span="8">
  142. <a-checkbox :value="item.dataIndex">
  143. <j-ellipsis :value="item.title" :length="10"></j-ellipsis>
  144. </a-checkbox>
  145. </a-col>
  146. </div>
  147. </template>
  148. </a-row>
  149. <a-row style="padding-top: 10px">
  150. <a-col>
  151. 恢复默认列配置:<a-button @click="handleRestDefault" type="link" size="small">恢复默认</a-button>
  152. </a-col>
  153. </a-row>
  154. </a-checkbox-group>
  155. </template>
  156. <a-button icon="setting">列设置</a-button>
  157. </a-popover>
  158. </div>
  159. <!-- table区域-begin -->
  160. <div>
  161. <a-table
  162. ref="table"
  163. size="middle"
  164. bordered
  165. rowKey="id"
  166. :columns="columns"
  167. :dataSource="dataSource"
  168. :components="handleDrag(columns)"
  169. :pagination="ipagination"
  170. :scroll="scroll"
  171. :loading="loading"
  172. :rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange, columnWidth: '40px' }"
  173. @change="handleTableChange"
  174. >
  175. <span slot="action" slot-scope="text, record">
  176. <a @click="handleEdit(record)">编辑</a>
  177. <a-divider v-if="btnEnableList.indexOf(1) > -1" type="vertical" />
  178. <a-popconfirm
  179. v-if="btnEnableList.indexOf(1) > -1"
  180. title="确定删除吗?"
  181. @confirm="() => handleDelete(record.id)"
  182. >
  183. <a>删除</a>
  184. </a-popconfirm>
  185. </span>
  186. <template slot="customPic" slot-scope="text, record">
  187. <a-popover placement="right" trigger="click">
  188. <template slot="content">
  189. <img :src="getImgUrl(record.imgName, record.imgLarge)" width="500px" />
  190. </template>
  191. <div class="item-info" v-if="record.imgName">
  192. <img
  193. v-if="record.imgName"
  194. :src="getImgUrl(record.imgName, record.imgSmall)"
  195. class="item-img"
  196. title="查看大图"
  197. />
  198. </div>
  199. </a-popover>
  200. </template>
  201. <template slot="customName" slot-scope="text, record">
  202. {{ record.name }}
  203. <a-tag v-if="record.enableSerialNumber == 1" color="orange">序</a-tag>
  204. <a-tag v-if="record.enableBatchNumber == 1" color="orange">批</a-tag>
  205. </template>
  206. <template slot="customRenderInitialStock" slot-scope="text, record">
  207. <a-tooltip :title="record.bigUnitInitialStock">
  208. {{ text }}
  209. </a-tooltip>
  210. </template>
  211. <template slot="customRenderStock" slot-scope="text, record">
  212. <a-tooltip :title="record.bigUnitStock">
  213. {{ text }}
  214. </a-tooltip>
  215. </template>
  216. <template slot="reminder" slot-scope="text, record">
  217. <a-tag v-if="record.reminder&&record.reminder.includes('临期')" color="red" style="margin-right: 10px;">临期</a-tag>
  218. <a-tag v-if="record.reminder&&record.reminder.includes('无动销')" color="orange" style="margin-right: 10px;">无动销</a-tag>
  219. <a-tag v-if="record.reminder&&record.reminder.includes('库存危险')" color="blue">库存危险</a-tag>
  220. </template>
  221. <template slot="customRenderEnabled" slot-scope="enabled">
  222. <a-tag v-if="enabled" color="green">启用</a-tag>
  223. <a-tag v-if="!enabled" color="orange">禁用</a-tag>
  224. </template>
  225. </a-table>
  226. </div>
  227. <!-- table区域-end -->
  228. <!-- 表单区域 -->
  229. <material-modal ref="modalForm" @ok="modalFormOk"></material-modal>
  230. <import-file-modal ref="modalImportForm" @ok="modalFormOk"></import-file-modal>
  231. <batch-set-info-modal ref="batchSetInfoModalForm" @ok="modalFormOk"></batch-set-info-modal>
  232. </a-card>
  233. </a-col>
  234. </a-row>
  235. </template>
  236. <script>
  237. import MaterialModal from './modules/MaterialModal'
  238. import ImportFileModal from '@/components/tools/ImportFileModal'
  239. import BatchSetInfoModal from './modules/BatchSetInfoModal'
  240. import { queryMaterialCategoryTreeList } from '@/api/api'
  241. import { postAction, getFileAccessHttpUrl } from '@/api/manage'
  242. import { getMpListShort } from '@/utils/util'
  243. import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  244. import JEllipsis from '@/components/jeecg/JEllipsis'
  245. import JDate from '@/components/jeecg/JDate'
  246. import Vue from 'vue'
  247. export default {
  248. name: 'MaterialList',
  249. mixins: [JeecgListMixin],
  250. components: {
  251. MaterialModal,
  252. ImportFileModal,
  253. BatchSetInfoModal,
  254. JEllipsis,
  255. JDate,
  256. },
  257. data() {
  258. return {
  259. categoryTree: [],
  260. mPropertyListShort: '',
  261. model: {},
  262. labelCol: {
  263. span: 5,
  264. },
  265. wrapperCol: {
  266. span: 18,
  267. offset: 1,
  268. },
  269. // 查询条件
  270. queryParam: {
  271. categoryId: undefined,
  272. materialParam: '',
  273. standard: '',
  274. model: '',
  275. color: '',
  276. brand: '',
  277. materialOther: '',
  278. weight: '',
  279. enabled: undefined,
  280. enableSerialNumber: undefined,
  281. reminder: undefined,
  282. remark: '',
  283. mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
  284. },
  285. ipagination: {
  286. pageSizeOptions: ['10', '20', '30', '50', '100', '200'],
  287. },
  288. // 实际索引
  289. settingDataIndex: [],
  290. // 实际列
  291. columns: [],
  292. // 默认索引
  293. defDataIndex: [
  294. 'action',
  295. 'barCode',
  296. 'name',
  297. 'standard',
  298. 'model',
  299. 'color',
  300. 'categoryName',
  301. 'materialOther',
  302. 'unit',
  303. 'stock',
  304. 'defaultPurchaseDecimal',
  305. 'commodityDecimal',
  306. 'defaultWholesaleDecimal',
  307. 'lowDecimal',
  308. 'enabled',
  309. 'reminder'
  310. ],
  311. // 默认列
  312. defColumns: [
  313. {
  314. title: '操作',
  315. dataIndex: 'action',
  316. align: 'center',
  317. width: 100,
  318. scopedSlots: { customRender: 'action' },
  319. },
  320. { title: '图片', dataIndex: 'pic', width: 60, scopedSlots: { customRender: 'customPic' } },
  321. { title: '条码', dataIndex: 'barCode', width: 120 },
  322. { title: '名称', dataIndex: 'name', width: 160, scopedSlots: { customRender: 'customName' } },
  323. { title: '系统SKU', dataIndex: 'systemSku', width: 120 },
  324. { title: '规格', dataIndex: 'standard', width: 120 },
  325. { title: '型号', dataIndex: 'model', width: 120 },
  326. { title: '颜色', dataIndex: 'color', width: 70, ellipsis: true },
  327. { title: '品牌', dataIndex: 'brand', width: 100, ellipsis: true },
  328. { title: '助记码', dataIndex: 'mnemonic', width: 80, ellipsis: true },
  329. { title: '类别', dataIndex: 'categoryName', width: 100, ellipsis: true },
  330. { title: '扩展信息', dataIndex: 'materialOther', width: 100, ellipsis: true },
  331. {
  332. title: '单位',
  333. dataIndex: 'unit',
  334. width: 100,
  335. ellipsis: true,
  336. customRender: function (t, r, index) {
  337. if (r) {
  338. let name = t ? t : r.unitName
  339. if (r.sku) {
  340. return name + '[SKU]'
  341. } else {
  342. return name
  343. }
  344. }
  345. },
  346. },
  347. { title: '基础重量', dataIndex: 'weight', width: 80 },
  348. {
  349. title: '初始库存',
  350. dataIndex: 'initialStock',
  351. width: 80,
  352. scopedSlots: { customRender: 'customRenderInitialStock' },
  353. },
  354. { title: '默认采购价', dataIndex: 'defaultPurchaseDecimal', width: 100 },
  355. { title: '默认销售价', dataIndex: 'defaultWholesaleDecimal', width: 100 },
  356. { title: '库存', dataIndex: 'stock', width: 80, scopedSlots: { customRender: 'customRenderStock' } },
  357. { title: '预警提示', dataIndex: 'reminder', width: 100, scopedSlots: { customRender: 'reminder' }},
  358. { title: '备注', dataIndex: 'remark', width: 80 },
  359. {
  360. title: '状态',
  361. dataIndex: 'enabled',
  362. align: 'center',
  363. width: 60,
  364. scopedSlots: { customRender: 'customRenderEnabled' },
  365. },
  366. ],
  367. url: {
  368. list: '/material/list',
  369. delete: '/material/delete',
  370. deleteBatch: '/material/deleteBatch',
  371. importExcelUrl: '/material/importExcel',
  372. exportXlsUrl: '/material/exportExcel',
  373. batchSetStatusUrl: '/material/batchSetStatus',
  374. batchSetMaterialCurrentStockUrl: '/material/batchSetMaterialCurrentStock',
  375. batchSetMaterialCurrentUnitPriceUrl: '/material/batchSetMaterialCurrentUnitPrice',
  376. },
  377. }
  378. },
  379. created() {
  380. this.model = Object.assign({}, {})
  381. this.initColumnsSetting()
  382. this.loadTreeData()
  383. },
  384. computed: {
  385. importExcelUrl: function () {
  386. return `${window._CONFIG['domianURL']}${this.url.importExcelUrl}`
  387. },
  388. },
  389. methods: {
  390. //加载初始化列
  391. initColumnsSetting() {
  392. let columnsStr = Vue.ls.get('materialColumns')
  393. if (columnsStr && columnsStr.indexOf(',') > -1) {
  394. this.settingDataIndex = columnsStr.split(',')
  395. } else {
  396. this.settingDataIndex = this.defDataIndex
  397. }
  398. this.columns = this.defColumns.filter((item) => {
  399. return this.settingDataIndex.includes(item.dataIndex)
  400. })
  401. },
  402. //列设置更改事件
  403. onColChange(checkedValues) {
  404. this.columns = this.defColumns.filter((item) => {
  405. return checkedValues.includes(item.dataIndex)
  406. })
  407. let columnsStr = checkedValues.join()
  408. Vue.ls.set('materialColumns', columnsStr)
  409. },
  410. //恢复默认
  411. handleRestDefault() {
  412. Vue.ls.remove('materialColumns')
  413. this.initColumnsSetting()
  414. },
  415. loadTreeData() {
  416. let that = this
  417. let params = {}
  418. params.id = ''
  419. queryMaterialCategoryTreeList(params).then((res) => {
  420. if (res) {
  421. that.categoryTree = []
  422. for (let i = 0; i < res.length; i++) {
  423. let temp = res[i]
  424. that.categoryTree.push(temp)
  425. }
  426. }
  427. })
  428. },
  429. batchSetMaterialCurrentStock() {
  430. if (this.selectedRowKeys.length <= 0) {
  431. this.$message.warning('请选择一条记录!')
  432. } else {
  433. let ids = ''
  434. for (let a = 0; a < this.selectedRowKeys.length; a++) {
  435. ids += this.selectedRowKeys[a] + ','
  436. }
  437. let that = this
  438. this.$confirm({
  439. title: '确认操作',
  440. content: '是否操作选中数据?',
  441. onOk: function () {
  442. that.loading = true
  443. postAction(that.url.batchSetMaterialCurrentStockUrl, { ids: ids })
  444. .then((res) => {
  445. if (res.code === 200) {
  446. that.$message.info('修正库存成功!')
  447. that.loadData()
  448. that.onClearSelected()
  449. } else {
  450. that.$message.warning(res.data.message)
  451. }
  452. })
  453. .finally(() => {
  454. that.loading = false
  455. })
  456. },
  457. })
  458. }
  459. },
  460. batchSetMaterialCurrentUnitPrice() {
  461. if (this.selectedRowKeys.length <= 0) {
  462. this.$message.warning('请选择一条记录!')
  463. } else {
  464. let ids = ''
  465. for (let a = 0; a < this.selectedRowKeys.length; a++) {
  466. ids += this.selectedRowKeys[a] + ','
  467. }
  468. let that = this
  469. this.$confirm({
  470. title: '确认操作',
  471. content: '是否操作选中数据?',
  472. onOk: function () {
  473. that.loading = true
  474. postAction(that.url.batchSetMaterialCurrentUnitPriceUrl, { ids: ids })
  475. .then((res) => {
  476. if (res.code === 200) {
  477. that.$message.info('修正成本成功!')
  478. that.loadData()
  479. that.onClearSelected()
  480. } else {
  481. that.$message.warning(res.data.message)
  482. }
  483. })
  484. .finally(() => {
  485. that.loading = false
  486. })
  487. },
  488. })
  489. }
  490. },
  491. batchEdit() {
  492. if (this.selectedRowKeys.length <= 0) {
  493. this.$message.warning('请选择一条记录!')
  494. } else {
  495. let ids = ''
  496. for (let a = 0; a < this.selectedRowKeys.length; a++) {
  497. if (a === this.selectedRowKeys.length - 1) {
  498. ids += this.selectedRowKeys[a]
  499. } else {
  500. ids += this.selectedRowKeys[a] + ','
  501. }
  502. }
  503. this.$refs.batchSetInfoModalForm.edit(ids)
  504. this.$refs.batchSetInfoModalForm.title = '批量编辑'
  505. }
  506. },
  507. handleEdit: function (record) {
  508. this.$refs.modalForm.edit(record)
  509. this.$refs.modalForm.title = '编辑'
  510. this.$refs.modalForm.disableSubmit = false
  511. if (this.btnEnableList.indexOf(1) === -1) {
  512. this.$refs.modalForm.showOkFlag = false
  513. }
  514. },
  515. getImgUrl(imgName, type) {
  516. if (imgName && imgName.split(',')) {
  517. type = type ? type + '/' : ''
  518. return getFileAccessHttpUrl('systemConfig/static/' + type + imgName.split(',')[0])
  519. } else {
  520. return ''
  521. }
  522. },
  523. handleImportXls() {
  524. let importExcelUrl = this.url.importExcelUrl
  525. let templateUrl = '/doc/goods_template.xls'
  526. let templateName = '商品信息导入模版[下载]'
  527. this.$refs.modalImportForm.initModal(importExcelUrl, templateUrl, templateName, '商品信息导入模版')
  528. this.$refs.modalImportForm.title = '商品导入'
  529. },
  530. searchReset() {
  531. this.queryParam = {
  532. mpList: getMpListShort(Vue.ls.get('materialPropertyList')), //扩展属性
  533. }
  534. this.loadData(1)
  535. },
  536. },
  537. }
  538. </script>
  539. <style scoped>
  540. @import '~@assets/less/common.less';
  541. </style>
  542. <style>
  543. .item-info {
  544. float: left;
  545. width: 38px;
  546. height: 38px;
  547. margin-left: 6px;
  548. }
  549. .item-img {
  550. cursor: pointer;
  551. position: static;
  552. display: block;
  553. width: 100%;
  554. height: 100%;
  555. object-fit: cover;
  556. }
  557. </style>