index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. <template>
  2. <div class="app-container coupon-list">
  3. <el-form v-show="showSearch" :model="queryParams" ref="queryForm" :inline="true" size="small">
  4. <el-form-item label="商品名称" prop="title">
  5. <el-input
  6. v-model="queryParams.title"
  7. placeholder="请输入商品名称"
  8. clearable
  9. @clear="queryParams.pageNum = 1;getList()"
  10. @keyup.enter.native="queryParams.pageNum = 1;getList()"
  11. />
  12. </el-form-item>
  13. <el-form-item label="商品ID" prop="goodsId">
  14. <el-input
  15. v-model="queryParams.goodsId"
  16. placeholder="请输入商品ID"
  17. clearable
  18. @clear="queryParams.pageNum = 1;getList()"
  19. @keyup.enter.native="queryParams.pageNum = 1;getList()"
  20. />
  21. </el-form-item>
  22. <el-form-item label="商品类型" prop="type">
  23. <el-select v-model="queryParams.type" placeholder="请选择商品类型" clearable
  24. @change="queryParams.pageNum = 1;getList()">
  25. <el-option label="全部" value=""/>
  26. <el-option label="实物商品" value="1"/>
  27. <el-option label="卡密商品" value="2"/>
  28. <el-option label="采购商品" value="3"/>
  29. </el-select>
  30. </el-form-item>
  31. <el-form-item label="商品分类" prop="categoryIdList">
  32. <el-cascader
  33. v-model="queryParams.categoryIdList" collapse-tags clearable
  34. :options="goodsCategoryItemsList"
  35. :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', multiple: true, }"
  36. @change="queryParams.pageNum = 1;getList()"></el-cascader>
  37. </el-form-item>
  38. <el-form-item label="商品标签" prop="tagId">
  39. <el-select
  40. v-model="queryParams.tagId"
  41. placeholder="请选择商品标签"
  42. clearable
  43. @change="queryParams.pageNum = 1;getList()"
  44. >
  45. <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList" :key="index"/>
  46. </el-select>
  47. </el-form-item>
  48. <el-form-item label="上架状态" prop="status">
  49. <el-select v-model="queryParams.status" placeholder="请选择商品状态" clearable
  50. @change="queryParams.pageNum = 1;getList()">
  51. <el-option label="全部" value=""/>
  52. <el-option label="待上架" value="init"/>
  53. <el-option label="已上架" value="on"/>
  54. <el-option label="已下架" value="off"/>
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item label="是否支持兑换" prop="exchangeShow">
  58. <el-select v-model="queryParams.exchangeShow" placeholder="请选择是否支持兑换" clearable
  59. @change="queryParams.pageNum = 1;getList()">
  60. <el-option label="全部" value=""/>
  61. <el-option label="支持兑换" value="1"/>
  62. <el-option label="不支持兑换" value="0"/>
  63. <el-option label="盲票商品" value="2"/>
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item label="供应商" prop="supplierId">
  67. <el-select v-model="queryParams.supplierId" placeholder="请选择供应商" filterable clearable
  68. @clear="queryParams.pageNum = 1;getList()" @change="queryParams.pageNum = 1;getList()">
  69. <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index"/>
  70. </el-select>
  71. </el-form-item>
  72. <br>
  73. <el-form-item label="商品成本" prop="minCost">
  74. <el-input v-model="queryParams.minCost" placeholder="最低成本" clearable
  75. @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
  76. </el-form-item>
  77. <el-form-item label="-" prop="maxCost">
  78. <el-input v-model="queryParams.maxCost" placeholder="最高成本" clearable
  79. @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
  80. </el-form-item>
  81. <el-form-item label="价格" prop="minValue">
  82. <el-input v-model="queryParams.minValue" placeholder="最低价格" clearable
  83. @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
  84. </el-form-item>
  85. <el-form-item label="-" prop="maxValue">
  86. <el-input v-model="queryParams.maxValue" placeholder="最高价格" clearable
  87. @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
  88. </el-form-item>
  89. <el-form-item>
  90. <el-button type="primary" icon="el-icon-search" @click="queryParams.pageNum = 1;getList()">搜索</el-button>
  91. <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  92. </el-form-item>
  93. </el-form>
  94. <el-row :gutter="10" class="mb8">
  95. <el-col :span="1.5">
  96. <el-button v-hasPermi="['business:goods:add']" type="primary" icon="el-icon-plus" size="mini"
  97. @click="$router.push({ name: 'GoodsAdd' })">添加商品
  98. </el-button>
  99. <!-- <el-button v-hasPermi="['business:goods:on']" type="primary" plain size="mini">上架</el-button> -->
  100. <!-- <el-button v-hasPermi="['business:goods:off']" type="primary" plain size="mini">下架</el-button> -->
  101. <!-- <el-button v-hasPermi="['business:goods:remove']" type="danger" plain size="mini">删除</el-button> -->
  102. </el-col>
  103. <el-col :span="1.5">
  104. <el-button
  105. type="infor"
  106. plain
  107. icon="el-icon-download"
  108. size="mini"
  109. @click="handleOrderExport"
  110. v-hasPermi="['business:goods:export']"
  111. >导出商品
  112. </el-button>
  113. </el-col>
  114. <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  115. </el-row>
  116. <el-table v-loading="loading" :data="tableData" @sort-change="sortChannelId">
  117. <el-table-column label="商品ID" prop="goodsId" width="60"/>
  118. <el-table-column label="商品图片" prop="picUrl" align="center">
  119. <template slot-scope="{row}">
  120. <div v-if="row.picUrl">
  121. <el-image
  122. style="width: 100px; height: 100px"
  123. :src="IMG_URL + row.picUrl.split(',')[0]"
  124. :preview-src-list="row.picUrl.split(',').map(item => { return IMG_URL + item })"
  125. />
  126. </div>
  127. <span v-else>-</span>
  128. </template>
  129. </el-table-column>
  130. <el-table-column label="商品名称" prop="title"/>
  131. <el-table-column label="价格" prop="value" sortable="custom">
  132. <template slot-scope="{row}">
  133. ¥{{ $numberFormat(row.value) }}
  134. </template>
  135. </el-table-column>
  136. <el-table-column label="商品成本" prop="cost" sortable="custom" min-width="100px">
  137. <template slot-scope="{row}">
  138. ¥{{ $numberFormat(row.cost) }}
  139. </template>
  140. </el-table-column>
  141. <el-table-column label="是否支持兑换" prop="exchangeShow" min-width="100px">
  142. <template slot-scope="{row}">
  143. <span v-if="row.exchangeShow == '1'">支持</span>
  144. <span v-if="row.exchangeShow == '0'">不支持</span>
  145. <span v-if="row.exchangeShow == '2'">盲票商品</span>
  146. </template>
  147. </el-table-column>
  148. <el-table-column label="商品类型" prop="type" min-width="100px">
  149. <template slot-scope="{row}">
  150. <span v-if="row.type == '1'">实物商品</span>
  151. <span v-if="row.type == '2'">卡密商品</span>
  152. <span v-if="row.type == '3'">采购商品</span>
  153. </template>
  154. </el-table-column>
  155. <el-table-column label="盲豆兑换数量" prop="exchangePrice" sortable="custom" min-width="125"/>
  156. <el-table-column label="销量" prop="exchangedQty" sortable="custom"/>
  157. <el-table-column label="库存" prop="quantity" sortable="custom"/>
  158. <el-table-column label="状态" prop="status">
  159. <template slot-scope="{row}">
  160. <el-tag :type="JSON.parse(row.status).value === 'on' ? 'success' : 'info'">{{
  161. JSON.parse(row.status).desc
  162. }}
  163. </el-tag>
  164. </template>
  165. </el-table-column>
  166. <el-table-column label="排序" prop="sortWeight" sortable="custom" align="center" width="140px">
  167. <template slot-scope="{row, $index}">
  168. <el-input-number v-model="row.sortWeight" @change="handleSortChange($index,row.sortWeight)"
  169. controls-position="right" size="small"></el-input-number>
  170. </template>
  171. </el-table-column>
  172. <el-table-column fixed="right" align="center" label="操作" width="140">
  173. <template slot-scope="{row}">
  174. <el-button v-hasPermi="['business:goods:edit']" type="text" @click="toAssociation(row.goodsId)">查看关联盲票</el-button>
  175. <!-- <el-button v-hasPermi="['business:goods:query']" type="text">查看</el-button> -->
  176. <el-button v-hasPermi="['business:goods:edit']" type="text" @click="handleCamilo(row.goodsId)" v-if="row.type === 2">
  177. 查看卡密
  178. </el-button>
  179. <el-button v-hasPermi="['business:goods:edit']" type="text" @click="handleImport(row.goodsId)"
  180. v-if="row.type === 2">添加卡密
  181. </el-button>
  182. <el-button v-hasPermi="['business:goods:edit']" type="text"
  183. @click="$router.push({ name: 'GoodsEdit', query: { id: row.goodsId } })">编辑
  184. </el-button>
  185. <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'"
  186. v-hasPermi="['business:goods:on']" type="text" @click="setStatus(row, 'on')">上架
  187. </el-button>
  188. <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:goods:off']" type="text"
  189. @click="setStatus(row, 'off')">下架
  190. </el-button>
  191. <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:remove']" class="del"
  192. type="text" @click="del(row)">删除
  193. </el-button>
  194. </template>
  195. </el-table-column>
  196. </el-table>
  197. <pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
  198. @pagination="getList()"/>
  199. <!-- 查看卡密-->
  200. <camilo v-if="camiloShow" @cancel="cancel" :camiloShow="camiloShow" :camiloGoodsId="camiloGoodsId"></camilo>
  201. <!-- 导入卡密-->
  202. <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body :before-close="openSwitch">
  203. 1.请下载Excel模版,填写卡密
  204. <br><br>
  205. &emsp;&emsp;<a style="color: #1890FF;" @click="downloadExcel">下载Excel模版</a>
  206. <br><br>
  207. 2.上传填写好卡密的Excel
  208. <div style="padding-top: 20px; text-align: center">
  209. <el-upload
  210. ref="upload"
  211. :limit="1"
  212. :data="reqData"
  213. accept=".xlsx, .xls"
  214. :headers="upload.headers"
  215. :action="upload.url"
  216. :disabled="upload.isUploading"
  217. :on-progress="handleFileUploadProgress"
  218. :on-success="handleFileSuccess"
  219. :auto-upload="false"
  220. :http-request="reqUploadFile"
  221. :on-exceed="exceedMax"
  222. drag
  223. >
  224. <i class="el-icon-upload"></i>
  225. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  226. <div class="el-upload__tip text-center" slot="tip">
  227. <span>仅允许导入 xls xlsx 格式文件。</span>
  228. </div>
  229. </el-upload>
  230. </div>
  231. <div slot="footer" class="dialog-footer">
  232. <el-button @click="openSwitch()">取 消</el-button>
  233. <el-button type="primary" @click="submitFileForm">确 定</el-button>
  234. </div>
  235. </el-dialog>
  236. <!-- 查询关联盲票弹框-->
  237. <Association v-if="associationShow" @cancel="associationTicket" :associationShow="associationShow" :associationGoodsId="associationGoodsId"></Association>
  238. </div>
  239. </template>
  240. <script>
  241. import Camilo from '@/components/Camilo'
  242. import Association from '@/components/Association'
  243. import {publicFileGetUrl} from "@/api/common"
  244. import {
  245. getGoodsList,
  246. delGoods,
  247. setGoodsStatus,
  248. setTableData,
  249. salesiteGoodsExport,
  250. setCamiloShip, cradDownload
  251. } from '@/api/business/goods'
  252. import {goodsCategoryListTree} from '@/api/business/category'
  253. import {goodsTagItems} from '@/api/business/tag'
  254. import {accMul} from '@/utils/util'
  255. import {getSupplierList} from '@/api/business/supplier'
  256. import {randomStr20} from '@/utils/util'
  257. import {getToken, getSign} from "@/utils/auth";
  258. export default {
  259. name: 'List',
  260. components: {
  261. Camilo,
  262. Association
  263. },
  264. data() {
  265. return {
  266. IMG_URL: publicFileGetUrl,
  267. loading: false,
  268. showSearch: true,
  269. queryParams: {pageNum: 1, pageSize: 10, orderByColumn: '', isAsc: '',},
  270. tableData: [],
  271. total: 0,
  272. goodsCategoryItemsList: [],
  273. goodsTagItemsList: [],
  274. SupplierList: [],
  275. camiloShow: false,
  276. // 用户导入参数
  277. upload: {
  278. open: false,// 是否显示弹出层(用户导入)
  279. title: "",// 弹出层标题(用户导入)
  280. isUploading: false,// 是否禁用上传
  281. url: "",// 上传的地址
  282. headers: {},//请求头
  283. },
  284. reqData: {},
  285. camiloGoodsId: null,
  286. associationShow: false,
  287. associationGoodsId: '',
  288. }
  289. },
  290. created() {
  291. this.getList(true)
  292. this.getGoodsCategoryItems()
  293. this.getGoodsTagItems()
  294. this.getSupplierItems()
  295. },
  296. methods: {
  297. //获取供应商
  298. getSupplierItems() {
  299. getSupplierList('', {}).then(res => {
  300. this.SupplierList = res && res.rows
  301. })
  302. },
  303. //切换排序
  304. sortChannelId(row) {
  305. if (row) {
  306. let prop = row.prop == 'commRate' ? ('t1.' + row.prop) : row.prop;
  307. this.queryParams.orderByColumn = prop
  308. this.queryParams.isAsc = row.order == 'ascending' ? "asc" : "desc";
  309. this.getList()
  310. }
  311. },
  312. //步进器修改
  313. handleSortChange(index, sortWeight) {
  314. this.tableData[index].sortWeight = sortWeight
  315. let data = {
  316. goodsId: this.tableData[index].goodsId,
  317. sortWeight: this.tableData[index].sortWeight
  318. }
  319. setTableData(data)
  320. },
  321. //取消查看卡密
  322. cancel() {
  323. this.camiloShow = false
  324. },
  325. //下载excel模版表格
  326. downloadExcel() {
  327. cradDownload().then(response => {
  328. this.download(response.msg);
  329. })
  330. },
  331. //查看卡密
  332. handleCamilo(id){
  333. this.camiloGoodsId = id
  334. this.camiloShow = true
  335. },
  336. //查看关联盲票
  337. toAssociation(id) {
  338. this.associationShow = true
  339. this.associationGoodsId = id
  340. },
  341. //关闭关联盲票弹框
  342. associationTicket() {
  343. this.associationShow = false
  344. this.associationGoodsId = ''
  345. },
  346. //上传卡密按钮操作
  347. handleImport(id) {
  348. this.camiloGoodsId = id
  349. this.upload.title = "添加卡密";
  350. this.upload.open = true;
  351. this.getHttpHeader(id)
  352. },
  353. // 文件上传中处理
  354. handleFileUploadProgress(event, file, fileList) {
  355. this.upload.isUploading = true;
  356. },
  357. // 文件上传成功处理
  358. handleFileSuccess(response, file, fileList) {
  359. this.upload.open = false;
  360. this.upload.isUploading = false;
  361. this.getList();
  362. },
  363. // 超出限制时的提示
  364. exceedMax() {
  365. this.$message({
  366. message: '请移除已有文件后再进行上传',
  367. type: 'warning'
  368. })
  369. },
  370. openSwitch() {
  371. this.upload.open = false
  372. this.$refs.upload.clearFiles();
  373. },
  374. // 提交上传文件
  375. submitFileForm() {
  376. this.$refs.upload.submit();
  377. },
  378. //请求头
  379. getHttpHeader(id) {
  380. let timestamp = parseInt(new Date().getTime()),
  381. nonce = randomStr20();
  382. var sign = getSign(this.reqData || {}, timestamp)
  383. let url = process.env.VUE_APP_BASE_API + `/api/v1/mp/admin/goods/card/import/${id}` + '?sign=' + sign + '&nonce=' + nonce;
  384. this.upload.url = url
  385. var headers = {
  386. "Authorization": "Bearer " + getToken(),
  387. "x-zz-timestamp": timestamp
  388. }
  389. this.upload.headers = headers
  390. },
  391. // 自定义文件上传的实现
  392. reqUploadFile(param) {
  393. var data = this.reqData || {}
  394. var params = {
  395. file: param.file,
  396. ...data
  397. }
  398. this.vloading = this.$loading({
  399. lock: true,
  400. text: "正在导入卡密.....",
  401. background: "rgba(0, 0, 0, 0.7)",
  402. });
  403. setCamiloShip(params, this.headers, this.camiloGoodsId).then(response => {
  404. this.vloading.close();
  405. this.upload.open = false;
  406. this.upload.isUploading = false;
  407. this.$refs.upload.clearFiles();
  408. this.$message({
  409. message: '导入成功',
  410. type: 'success'
  411. })
  412. }).catch(() => {
  413. this.$refs.upload.clearFiles();
  414. this.vloading.close();
  415. })
  416. },
  417. getGoodsCategoryItems() {
  418. goodsCategoryListTree("", {}).then(res => {
  419. this.goodsCategoryItemsList = res && res.rows
  420. })
  421. },
  422. getGoodsTagItems() {
  423. goodsTagItems({}).then(res => {
  424. this.goodsTagItemsList = res && res.data
  425. })
  426. },
  427. getList(reset) {
  428. if (this.loading) {
  429. return
  430. }
  431. this.loading = true
  432. // if (reset) {
  433. // this.queryParams = { pageNum: 1, pageSize: 20, orderByColumn: '', isAsc: '', }
  434. // }
  435. if (this.queryParams.categoryIdList) {
  436. for (let i = 0; i < this.queryParams.categoryIdList.length; i++) {
  437. if (this.queryParams.categoryIdList[i][1]) {
  438. this.queryParams.categoryIdList[i] = this.queryParams.categoryIdList[i][1]
  439. }
  440. }
  441. }
  442. getGoodsList('pageNum=' + this.queryParams.pageNum + '&pageSize=' + this.queryParams.pageSize + '&orderByColumn=' + this.queryParams.orderByColumn + '&isAsc=' + this.queryParams.isAsc + '&', {
  443. title: this.queryParams.title,
  444. goodsId: this.queryParams.goodsId,
  445. type: this.queryParams.type ? Number(this.queryParams.type) : this.queryParams.type,
  446. categoryIdList: this.queryParams.categoryIdList,
  447. tagId: this.queryParams.tagId,
  448. status: this.queryParams.status,
  449. exchangeShow: this.queryParams.exchangeShow, supplierId: this.queryParams.supplierId,
  450. minCost: this.queryParams.minCost ? accMul(this.queryParams.minCost, 100) : this.queryParams.minCost,
  451. maxCost: this.queryParams.maxCost ? accMul(this.queryParams.maxCost, 100) : this.queryParams.maxCost,
  452. minValue: this.queryParams.minValue ? accMul(this.queryParams.minValue, 100) : this.queryParams.minValue,
  453. maxValue: this.queryParams.maxValue ? accMul(this.queryParams.maxValue, 100) : this.queryParams.maxValue
  454. }).then(res => {
  455. this.loading = false
  456. if (res.code === 0) {
  457. this.tableData = res.rows
  458. // this.tableData.map()
  459. this.total = res.total
  460. }
  461. }).catch(() => {
  462. this.loading = false
  463. })
  464. },
  465. // 重置
  466. resetQuery() {
  467. this.queryParams = {pageNum: 1, pageSize: 10, orderByColumn: '', isAsc: '',}
  468. this.getList();
  469. },
  470. setStatus(item, status) {
  471. this.$confirm(`确认${status === 'on' ? '上架' : '下架'}商品 “${item.title}” 吗?`, `${status === 'on' ? '上架' : '下架'}商品`, {
  472. confirmButtonText: '确定',
  473. cancelButtonText: '取消',
  474. type: 'warning'
  475. }).then(() => {
  476. setGoodsStatus({
  477. goodsId: item.goodsId,
  478. status
  479. }).then(res => {
  480. if (res.code === 0) {
  481. this.$message.success('操作已完成!')
  482. this.getList()
  483. }
  484. })
  485. })
  486. },
  487. // 导出商品
  488. handleOrderExport() {
  489. this.$confirm("是否确认导出商品?", "提示", {
  490. confirmButtonText: "确定",
  491. cancelButtonText: "取消",
  492. type: "warning",
  493. })
  494. .then(() => {
  495. this.vloading = this.$loading({
  496. lock: true,
  497. text: "正在导出商品.....",
  498. background: "rgba(0, 0, 0, 0.7)",
  499. });
  500. return salesiteGoodsExport(this.queryParams);
  501. })
  502. .then((response) => {
  503. this.vloading.close();
  504. this.download(response.msg);
  505. })
  506. .catch(() => {
  507. this.vloading.close();
  508. });
  509. },
  510. del(item) {
  511. this.$confirm(`确认删除商品 “${item.title}” 吗?`, '删除商品', {
  512. confirmButtonText: '确定',
  513. cancelButtonText: '取消',
  514. type: 'warning'
  515. }).then(() => {
  516. delGoods(item.goodsId).then(res => {
  517. if (res.code === 0) {
  518. this.$message.success('操作已完成!')
  519. this.getList()
  520. }
  521. })
  522. })
  523. }
  524. }
  525. }
  526. </script>