list.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <template>
  2. <div class="jg-page-wrap customerReportList-wrap">
  3. <a-card size="small" :bordered="false" class="table-page-search-wrapper">
  4. <div ref="tableSearch">
  5. <!-- 搜索条件 -->
  6. <a-form-model
  7. id="customerReportList-form"
  8. ref="ruleForm"
  9. class="form-model-con"
  10. layout="inline"
  11. :model="queryParam"
  12. :rules="rules"
  13. :labelCol="labelCol"
  14. :wrapperCol="wrapperCol"
  15. @keyup.enter.native="handleSearch" >
  16. <a-row :gutter="15">
  17. <a-col :md="6" :sm="24">
  18. <a-form-model-item label="查询时间" prop="time">
  19. <rangeDate ref="rangeDate" @change="dateChange" />
  20. </a-form-model-item>
  21. </a-col>
  22. <a-col :md="6" :sm="24">
  23. <a-form-item label="产品品牌">
  24. <ProductBrand id="salesDetailReportList-productBrandSn" placeholder="请选择产品品牌" v-model="queryParam.productBrandSn"></ProductBrand>
  25. </a-form-item>
  26. </a-col>
  27. <a-col :md="6" :sm="24">
  28. <a-form-model-item label="产品分类">
  29. <ProductType id="chainSalesReportList-productType" placeholder="请选择产品分类" @change="changeProductType" v-model="productType"></ProductType>
  30. </a-form-model-item>
  31. </a-col>
  32. <template v-if="advanced">
  33. <a-col :md="6" :sm="24">
  34. <a-form-model-item label="产品编码">
  35. <a-input id="salesDetailReportList-code" v-model.trim="queryParam.code" allowClear placeholder="请输入产品编码"/>
  36. </a-form-model-item>
  37. </a-col>
  38. <a-col :md="6" :sm="24">
  39. <a-form-model-item label="产品名称">
  40. <a-input id="salesDetailReportList-name" v-model.trim="queryParam.name" allowClear placeholder="请输入产品名称"/>
  41. </a-form-model-item>
  42. </a-col>
  43. </template>
  44. <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
  45. <a-button type="primary" @click="handleSearch" :disabled="disabled" id="customerReportList-refresh">查询</a-button>
  46. <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="customerReportList-reset">重置</a-button>
  47. <a-button
  48. type="primary"
  49. style="margin-left: 5px"
  50. @click="handleExport"
  51. :disabled="disabled"
  52. :loading="exportLoading"
  53. v-if="$hasPermissions('M_salesReturnReportExport')"
  54. class="button-warning"
  55. id="salesDetailReportList-export-btn">导出</a-button>
  56. <a @click="advanced=!advanced" style="margin-left: 8px">
  57. {{ advanced ? '收起' : '展开' }}
  58. <a-icon :type="advanced ? 'up' : 'down'"/>
  59. </a>
  60. </a-col>
  61. </a-row>
  62. </a-form-model>
  63. </div>
  64. </a-card>
  65. <a-card size="small" :bordered="false">
  66. <a-spin :spinning="spinning" tip="Loading...">
  67. <!-- 合计 -->
  68. <div class="table-operator">
  69. <div class="alert-message">
  70. 销售数量:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  71. 销售金额:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? toThousands(totalData.discountedAmount) : '--' }}</strong>;
  72. 销售折后金额:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? toThousands(totalData.discountedAmount) : '--' }}</strong>;
  73. 销售退货数量:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  74. 销售退货金额:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  75. 销售退货折后金额:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  76. 合计销售数量:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  77. 合计销售金额:<strong>{{ (totalData && (totalData.discountedAmount || totalData.discountedAmount==0)) ? totalData.discountedAmount : '--' }}</strong>;
  78. </div>
  79. <div>
  80. <span>显示:</span>
  81. <a-tree-select
  82. size="small"
  83. v-model="showCols"
  84. style="min-width: 200px"
  85. dropdownMatchSelectWidth
  86. :maxTagCount="3"
  87. :tree-data="colsArr"
  88. tree-checkable
  89. placeholder="请选择要显示的列(多选)"
  90. />
  91. </div>
  92. </div>
  93. <!-- 列表 -->
  94. <s-table
  95. class="sTable"
  96. ref="table"
  97. size="small"
  98. :rowKey="(record) => record.no"
  99. rowKeyName="no"
  100. :columns="columns"
  101. :data="loadData"
  102. :style="{ height: tableHeight+84+'px' }"
  103. :scroll="{ x: 1820}"
  104. :defaultLoadData="false"
  105. bordered>
  106. <!-- 销售数量 标题 -->
  107. <template slot="salesNumTit">
  108. <a-tooltip placement="top">
  109. <template slot="title">
  110. <span>销售单创建后开始计算销售数量</span>
  111. </template>
  112. <div>
  113. <span style="margin-right:5px;">销售数量</span>
  114. <a-icon type="question-circle" />
  115. </div>
  116. </a-tooltip>
  117. </template>
  118. <!-- 销售退货数量 标题 -->
  119. <template slot="salesReturnNum">
  120. <a-tooltip placement="top">
  121. <template slot="title">
  122. <span>销售退货单完结后开始计算销售数量</span>
  123. </template>
  124. <div>
  125. <span style="margin-right:5px;">销售退货数量</span>
  126. <a-icon type="question-circle" />
  127. </div>
  128. </a-tooltip>
  129. </template>
  130. <template slot="action" slot-scope="text, record">
  131. <a-button
  132. size="small"
  133. type="link"
  134. class="button-primary"
  135. @click="handleEexamine(record)"
  136. >加入购物车</a-button>
  137. </template>
  138. </s-table>
  139. </a-spin>
  140. </a-card>
  141. </div>
  142. </template>
  143. <script>
  144. import { commonMixin } from '@/utils/mixin'
  145. import { STable, VSelect } from '@/components'
  146. import rangeDate from '@/views/common/rangeDate.vue'
  147. import ProductBrand from '@/views/common/productBrand.js'
  148. import ProductType from '@/views/common/productType.js'
  149. import { reportBigCustomerList, reportBigCustomerCount } from '@/api/reportData'
  150. export default {
  151. mixins: [commonMixin],
  152. name: 'SalesRankingReport',
  153. components: { STable, VSelect, rangeDate, ProductType, ProductBrand },
  154. data () {
  155. return {
  156. spinning: false,
  157. labelCol: { span: 8 },
  158. wrapperCol: { span: 16 },
  159. advanced: true, // 高级搜索 展开/关闭
  160. tableHeight: 0,
  161. queryParam: { // 查询条件
  162. time: [],
  163. beginDate: '',
  164. endDate: '',
  165. productBrandSn: '',
  166. productTypeSn1: '', // 产品一级分类
  167. productTypeSn2: '', // 产品二级分类
  168. productTypeSn3: '', // 产品三级分类
  169. code: undefined,
  170. name: undefined
  171. },
  172. productType: [],
  173. rules: {
  174. 'time': [{ required: true, message: '请选择添加时间', trigger: 'change' }]
  175. },
  176. disabled: false, // 查询、重置按钮是否可操作
  177. exportLoading: false,
  178. // 加载数据方法 必须为 Promise 对象
  179. loadData: parameter => {
  180. this.disabled = true
  181. const params = Object.assign(parameter, this.queryParam)
  182. this.spinning = true
  183. delete params.time
  184. if (params.beginDate) {
  185. return reportBigCustomerList(params).then(res => {
  186. let data
  187. if (res.status == 200) {
  188. data = res.data
  189. // 总计
  190. this.getCount(params)
  191. const no = (data.pageNo - 1) * data.pageSize
  192. for (var i = 0; i < data.list.length; i++) {
  193. data.list[i].no = no + i + 1
  194. data.list[i].percentageUnit = data.list[i].percentage ? data.list[i].percentage + '%' : undefined
  195. }
  196. this.disabled = false
  197. }
  198. this.spinning = false
  199. return data
  200. })
  201. } else {
  202. const _this = this
  203. return new Promise(function (resolve, reject) {
  204. const data = {
  205. pageNo: 1,
  206. pageSize: 10,
  207. list: [],
  208. count: 0
  209. }
  210. _this.disabled = false
  211. _this.spinning = false
  212. _this.$message.info('请选择添加时间')
  213. resolve(data)
  214. })
  215. }
  216. },
  217. totalData: null, // 合计
  218. colsArr: [
  219. {
  220. title: '销售退货(明细)',
  221. value: 'totalCancelQty',
  222. key: 'totalCancelQty',
  223. disabled: false,
  224. checkedFlag: true
  225. }],
  226. showCols: ['totalCancelQty']
  227. }
  228. },
  229. computed: {
  230. columns () {
  231. const _this = this
  232. const arr = [
  233. { title: '序号', dataIndex: 'no', width: 60, align: 'center' },
  234. { title: '品牌', dataIndex: 'salesTargetName', width: 80, align: 'center', customRender: function (text) { return text || '--' } },
  235. { title: '分类', dataIndex: 'customerTypeName', width: 100, align: 'center', customRender: function (text) { return text || '--' } },
  236. { title: '产品编码', dataIndex: 'discountedAmount', width: 90, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  237. { title: '产品名称', dataIndex: 'discountedAmount', width: 150, align: 'left', customRender: function (text) { return text || '--' }, ellipsis: true },
  238. { title: '原厂编码', dataIndex: 'discountedAmount', width: 90, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  239. { title: '单位', dataIndex: 'discountedAmount', width: 70, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  240. { slots: { title: 'salesNumTit' }, dataIndex: 'discountedAmount', width: 100, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  241. { title: '销售金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  242. { title: '销售折扣金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  243. { title: '销售折后金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  244. { title: '销售成本金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  245. { slots: { title: 'salesReturnNum' }, dataIndex: 'discountedAmount', width: 110, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  246. { title: '销售退货金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  247. { title: '销售退货折扣金额', dataIndex: 'discountedAmount', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  248. { title: '销售退货折后金额', dataIndex: 'discountedAmount', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  249. { title: '销售退货成本金额', dataIndex: 'discountedAmount', width: 120, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  250. { title: '合计销售数量', dataIndex: 'discountedAmount', width: 100, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  251. { title: '合计销售金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  252. { title: '当前库存数量', dataIndex: 'discountedAmount', width: 100, align: 'center', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  253. { title: '当前库存金额', dataIndex: 'discountedAmount', width: 100, align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
  254. { title: '操作', scopedSlots: { customRender: 'action' }, width: 120, align: 'center', fixed: 'right' }
  255. ]
  256. // if (this.$hasPermissions('M_ShowAllCost')) {
  257. // arr.splice(4, 0, { title: '毛利', dataIndex: 'totalGrossProfit', width: '15%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } })
  258. // arr.splice(5, 0, { title: '毛利率', dataIndex: 'percentageUnit', width: '15%', align: 'right', customRender: function (text) { return text || '--' } })
  259. // }
  260. return arr
  261. }
  262. },
  263. methods: {
  264. areaChange (val) {
  265. this.queryParam.provinceSn = val[0] ? val[0] : ''
  266. this.queryParam.citySn = val[1] ? val[1] : ''
  267. this.queryParam.districtSn = val[2] ? val[2] : ''
  268. },
  269. // 合计
  270. getCount (params) {
  271. reportBigCustomerCount(params).then(res => {
  272. if (res.status == 200) {
  273. this.totalData = res.data
  274. } else {
  275. this.totalData = null
  276. }
  277. })
  278. },
  279. // 创建时间 change
  280. dateChange (date) {
  281. this.queryParam.time = date
  282. this.queryParam.beginDate = date[0] || ''
  283. this.queryParam.endDate = date[1] || ''
  284. },
  285. custSatelliteChange (v, row) {
  286. if (row && row.customerSn) {
  287. this.queryParam.customerSn = row.customerSn
  288. this.queryParam.customerName = row.customerName
  289. } else {
  290. this.queryParam.customerName = v
  291. this.queryParam.customerSn = undefined
  292. }
  293. },
  294. // 查询
  295. handleSearch () {
  296. this.$refs.ruleForm.validate(valid => {
  297. if (valid) {
  298. this.$refs.table.refresh(true)
  299. } else {
  300. this.$message.error('添加时间不能为空!')
  301. return false
  302. }
  303. })
  304. },
  305. // 重置
  306. resetSearchForm () {
  307. this.$refs.rangeDate.resetDate()
  308. this.queryParam.time = []
  309. this.queryParam.beginDate = ''
  310. this.queryParam.endDate = ''
  311. this.queryParam.productBrandSn = ''
  312. this.queryParam.productTypeSn1 = ''
  313. this.queryParam.productTypeSn2 = ''
  314. this.queryParam.productTypeSn3 = ''
  315. this.queryParam.code = undefined
  316. this.queryParam.name = undefined
  317. this.productType = []
  318. this.$refs.ruleForm.resetFields()
  319. this.totalData = null
  320. this.$refs.table.clearTable()
  321. },
  322. // 产品分类 change
  323. changeProductType (val, opt) {
  324. this.queryParam.productTypeSn1 = val[0] ? val[0] : ''
  325. this.queryParam.productTypeSn2 = val[1] ? val[1] : ''
  326. this.queryParam.productTypeSn3 = val[2] ? val[2] : ''
  327. },
  328. handleExport () {
  329. },
  330. setTableH () {
  331. const tableSearchH = this.$refs.tableSearch.offsetHeight
  332. this.tableHeight = window.innerHeight - tableSearchH - 255
  333. }
  334. },
  335. watch: {
  336. advanced (newValue, oldValue) {
  337. const _this = this
  338. this.$nextTick(() => { // 页面渲染完成后的回调
  339. _this.setTableH()
  340. })
  341. }
  342. },
  343. mounted () {
  344. if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
  345. this.resetSearchForm()
  346. this.$nextTick(() => { // 页面渲染完成后的回调
  347. this.setTableH()
  348. })
  349. }
  350. },
  351. activated () {
  352. // 如果是新页签打开,则重置当前页面
  353. if (this.$store.state.app.isNewTab) {
  354. this.resetSearchForm()
  355. this.$nextTick(() => { // 页面渲染完成后的回调
  356. this.setTableH()
  357. })
  358. }
  359. },
  360. beforeRouteEnter (to, from, next) {
  361. next(vm => {})
  362. }
  363. }
  364. </script>
  365. <style lang="less" scoped>
  366. .table-operator{
  367. display: flex;
  368. align-items: center;
  369. justify-content: space-between;
  370. }
  371. </style>