index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. <template> 
  2. <div class="app-container">
  3. <el-card class="filter-container" shadow="never">
  4. <div>
  5. <i class="el-icon-search"></i>
  6. <span>筛选搜索</span>
  7. <el-button
  8. style="float: right"
  9. @click="handleSearchList()"
  10. type="primary"
  11. size="small">
  12. 查询结果
  13. </el-button>
  14. <el-button
  15. style="float: right;margin-right: 15px"
  16. @click="handleResetSearch()"
  17. size="small">
  18. 重置
  19. </el-button>
  20. </div>
  21. <div style="margin-top: 15px">
  22. <el-form :inline="true" :model="listQuery" size="small" label-width="140px">
  23. <el-form-item label="输入搜索:">
  24. <el-input style="width: 203px" v-model="listQuery.keyword" placeholder="商品名称"></el-input>
  25. </el-form-item>
  26. <el-form-item label="商品货号:">
  27. <el-input style="width: 203px" v-model="listQuery.productSn" placeholder="商品货号"></el-input>
  28. </el-form-item>
  29. <el-form-item label="商品分类:">
  30. <el-cascader
  31. clearable
  32. v-model="selectProductCateValue"
  33. :options="productCateOptions">
  34. </el-cascader>
  35. </el-form-item>
  36. <el-form-item label="商品品牌:">
  37. <el-select filterable v-model="listQuery.brandId" placeholder="请选择品牌" clearable>
  38. <el-option
  39. v-for="item in brandOptions"
  40. :key="item.value"
  41. :label="item.label"
  42. :value="item.value">
  43. </el-option>
  44. </el-select>
  45. </el-form-item>
  46. <el-form-item label="上架状态:">
  47. <el-select v-model="listQuery.publishStatus" placeholder="全部" clearable>
  48. <el-option
  49. v-for="item in publishStatusOptions"
  50. :key="item.value"
  51. :label="item.label"
  52. :value="item.value">
  53. </el-option>
  54. </el-select>
  55. </el-form-item>
  56. <el-form-item label="审核状态:">
  57. <el-select v-model="listQuery.verifyStatus" placeholder="全部" clearable>
  58. <el-option
  59. v-for="item in verifyStatusOptions"
  60. :key="item.value"
  61. :label="item.label"
  62. :value="item.value">
  63. </el-option>
  64. </el-select>
  65. </el-form-item>
  66. </el-form>
  67. </div>
  68. </el-card>
  69. <el-card class="operate-container" shadow="never">
  70. <i class="el-icon-tickets"></i>
  71. <span>数据列表</span>
  72. <el-button
  73. v-if="createproduct"
  74. class="btn-add"
  75. @click="handleAddProduct()"
  76. size="mini">
  77. 添加
  78. </el-button>
  79. </el-card>
  80. <div class="table-container">
  81. <el-table ref="productTable"
  82. :data="list"
  83. style="width: 100%"
  84. @selection-change="handleSelectionChange"
  85. v-loading="listLoading"
  86. border>
  87. <el-table-column type="selection" width="60" align="center"></el-table-column>
  88. <el-table-column label="编号" width="100" align="center">
  89. <template slot-scope="scope">{{scope.row.id}}</template>
  90. </el-table-column>
  91. <el-table-column label="商品图片" width="120" align="center">
  92. <template slot-scope="scope"><img style="height: 80px" :src="scope.row.pic+'?imageMogr2/quality/60'"></template>
  93. </el-table-column>
  94. <el-table-column label="商品名称" align="center">
  95. <template slot-scope="scope">
  96. <p>{{scope.row.name}}</p>
  97. <p>品牌:{{scope.row.brandName}}</p>
  98. </template>
  99. </el-table-column>
  100. <el-table-column label="价格/货号" width="120" align="center">
  101. <template slot-scope="scope">
  102. <p>价格:¥{{scope.row.price}}</p>
  103. <p>货号:{{scope.row.productSn}}</p>
  104. </template>
  105. </el-table-column>
  106. <el-table-column label="标签" width="140" align="center">
  107. <template slot-scope="scope">
  108. <p>上架:
  109. <el-switch
  110. @change="handlePublishStatusChange(scope.$index, scope.row)"
  111. :active-value="1"
  112. :inactive-value="0"
  113. v-model="scope.row.publishStatus">
  114. </el-switch>
  115. </p>
  116. <!-- <p>新品:
  117. <el-switch
  118. @change="handleNewStatusChange(scope.$index, scope.row)"
  119. :active-value="1"
  120. :inactive-value="0"
  121. v-model="scope.row.newStatus">
  122. </el-switch>
  123. </p>
  124. <p>推荐:
  125. <el-switch
  126. @change="handleRecommendStatusChange(scope.$index, scope.row)"
  127. :active-value="1"
  128. :inactive-value="0"
  129. v-model="scope.row.recommandStatus">
  130. </el-switch>
  131. </p> -->
  132. </template>
  133. </el-table-column>
  134. <el-table-column label="排序" width="100" align="center">
  135. <template slot-scope="scope">{{scope.row.sort}}</template>
  136. </el-table-column>
  137. <!-- <el-table-column label="SKU库存" width="100" align="center">
  138. <template slot-scope="scope">
  139. <el-button type="primary" icon="el-icon-edit" @click="handleShowSkuEditDialog(scope.$index, scope.row)" circle></el-button>
  140. </template>
  141. </el-table-column> -->
  142. <el-table-column label="销量" width="100" align="center">
  143. <template slot-scope="scope">{{scope.row.sale}}</template>
  144. </el-table-column>
  145. <el-table-column label="保质期" width="100" align="center">
  146. <template slot-scope="scope">{{scope.row.qualityGuaranteePeriod}}</template>
  147. </el-table-column>
  148. <el-table-column label="审核状态" width="100" align="center">
  149. <template slot-scope="scope">
  150. <p>{{scope.row.verifyStatus | verifyStatusFilter}}</p>
  151. <p>
  152. <!-- <el-button
  153. type="text"
  154. @click="handleShowVerifyDetail(scope.$index, scope.row)">审核详情
  155. </el-button> -->
  156. </p>
  157. </template>
  158. </el-table-column>
  159. <el-table-column label="操作" width="160" align="center">
  160. <template slot-scope="scope">
  161. <p>
  162. <!-- <el-button
  163. size="mini"
  164. @click="handleShowProduct(scope.$index, scope.row)">查看
  165. </el-button> -->
  166. <el-button
  167. v-if="updateproduct"
  168. size="mini"
  169. @click="handleUpdateProduct(scope.$index, scope.row)">编辑
  170. </el-button>
  171. </p>
  172. <p>
  173. <!-- <el-button
  174. size="mini"
  175. @click="handleShowLog(scope.$index, scope.row)">日志
  176. </el-button> -->
  177. <el-button size="mini" v-if="scope.row.verifyStatus==0&&verifyproduct" @click="handleVerify(scope.$index, scope.row)">
  178. 审核
  179. </el-button>
  180. <el-button
  181. v-if="delproduct"
  182. size="mini"
  183. type="danger"
  184. @click="handleDelete(scope.$index, scope.row)">删除
  185. </el-button>
  186. </p>
  187. </template>
  188. </el-table-column>
  189. </el-table>
  190. </div>
  191. <div class="batch-operate-container">
  192. <el-select
  193. size="small"
  194. v-model="operateType" placeholder="批量操作">
  195. <el-option
  196. v-for="item in operates"
  197. :key="item.value"
  198. :label="item.label"
  199. :value="item.value">
  200. </el-option>
  201. </el-select>
  202. <el-button
  203. style="margin-left: 20px"
  204. class="search-button"
  205. @click="handleBatchOperate()"
  206. type="primary"
  207. size="small">
  208. 确定
  209. </el-button>
  210. </div>
  211. <div class="pagination-container">
  212. <el-pagination
  213. background
  214. @size-change="handleSizeChange"
  215. @current-change="handleCurrentChange"
  216. layout="total, sizes,prev, pager, next,jumper"
  217. :page-size="listQuery.pageSize"
  218. :page-sizes="[5,10,15]"
  219. :current-page.sync="listQuery.pageNum"
  220. :total="total">
  221. </el-pagination>
  222. </div>
  223. <el-dialog
  224. title="编辑货品信息"
  225. :visible.sync="editSkuInfo.dialogVisible"
  226. width="40%">
  227. <span>商品货号:</span>
  228. <span>{{editSkuInfo.productSn}}</span>
  229. <el-input placeholder="按sku编号搜索" v-model="editSkuInfo.keyword" size="small" style="width: 50%;margin-left: 20px">
  230. <el-button slot="append" icon="el-icon-search" @click="handleSearchEditSku"></el-button>
  231. </el-input>
  232. <el-table style="width: 100%;margin-top: 20px"
  233. :data="editSkuInfo.stockList"
  234. border>
  235. <el-table-column
  236. label="SKU编号"
  237. align="center">
  238. <template slot-scope="scope">
  239. <el-input v-model="scope.row.skuCode"></el-input>
  240. </template>
  241. </el-table-column>
  242. <el-table-column
  243. v-for="(item,index) in editSkuInfo.productAttr"
  244. :label="item.name"
  245. :key="item.id"
  246. align="center">
  247. <template slot-scope="scope">
  248. {{getProductSkuSp(scope.row,index)}}
  249. </template>
  250. </el-table-column>
  251. <el-table-column
  252. label="销售价格"
  253. width="80"
  254. align="center">
  255. <template slot-scope="scope">
  256. <el-input v-model="scope.row.price"></el-input>
  257. </template>
  258. </el-table-column>
  259. <el-table-column
  260. label="商品库存"
  261. width="80"
  262. align="center">
  263. <template slot-scope="scope">
  264. <el-input v-model="scope.row.stock"></el-input>
  265. </template>
  266. </el-table-column>
  267. <el-table-column
  268. label="库存预警值"
  269. width="100"
  270. align="center">
  271. <template slot-scope="scope">
  272. <el-input v-model="scope.row.lowStock"></el-input>
  273. </template>
  274. </el-table-column>
  275. </el-table>
  276. <span slot="footer" class="dialog-footer">
  277. <el-button @click="editSkuInfo.dialogVisible = false">取 消</el-button>
  278. <el-button type="primary" @click="handleEditSkuConfirm">确 定</el-button>
  279. </span>
  280. </el-dialog>
  281. </div>
  282. </template>
  283. <script>
  284. import {
  285. fetchList,
  286. updateDeleteStatus,
  287. updateNewStatus,
  288. updateRecommendStatus,
  289. updatePublishStatus,
  290. updateVerifyStatus,
  291. } from '@/api/product'
  292. import {fetchList as fetchSkuStockList,update as updateSkuStockList} from '@/api/skuStock'
  293. import {fetchList as fetchProductAttrList} from '@/api/productAttr'
  294. import {fetchList as fetchBrandList} from '@/api/brand'
  295. import {fetchListWithChildren} from '@/api/productCate'
  296. import {verifyproduct,delproduct,updateproduct,createproduct} from '@/api/permissions'
  297. const defaultListQuery = {
  298. keyword: null,
  299. pageNum: 1,
  300. pageSize: 5,
  301. publishStatus: null,
  302. verifyStatus: null,
  303. productSn: null,
  304. productCategoryId: null,
  305. brandId: null
  306. };
  307. export default {
  308. name: "productList",
  309. data() {
  310. return {
  311. //按钮权限
  312. createproduct,
  313. updateproduct,
  314. delproduct,
  315. verifyproduct,
  316. editSkuInfo:{
  317. dialogVisible:false,
  318. productId:null,
  319. productSn:'',
  320. productAttributeCategoryId:null,
  321. stockList:[],
  322. productAttr:[],
  323. keyword:null,
  324. },
  325. operates: [
  326. {
  327. label: "商品上架",
  328. value: "publishOn"
  329. },
  330. {
  331. label: "商品下架",
  332. value: "publishOff"
  333. },
  334. {
  335. label: "设为推荐",
  336. value: "recommendOn"
  337. },
  338. {
  339. label: "取消推荐",
  340. value: "recommendOff"
  341. },
  342. {
  343. label: "设为新品",
  344. value: "newOn"
  345. },
  346. {
  347. label: "取消新品",
  348. value: "newOff"
  349. },
  350. {
  351. label: "转移到分类",
  352. value: "transferCategory"
  353. },
  354. {
  355. label: "移入回收站",
  356. value: "recycle"
  357. }
  358. ],
  359. operateType: null,
  360. listQuery: Object.assign({}, defaultListQuery),
  361. list: null,
  362. total: null,
  363. listLoading: true,
  364. selectProductCateValue: null,
  365. multipleSelection: [],
  366. productCateOptions: [],
  367. brandOptions: [],
  368. publishStatusOptions: [{
  369. value: 1,
  370. label: '上架'
  371. }, {
  372. value: 0,
  373. label: '下架'
  374. }],
  375. verifyStatusOptions: [{
  376. value: 1,
  377. label: '审核通过'
  378. }, {
  379. value: 0,
  380. label: '未审核'
  381. }],
  382. }
  383. },
  384. created() {
  385. this.getList();
  386. this.getBrandList();
  387. this.getProductCateList();
  388. },
  389. watch: {
  390. selectProductCateValue: function (newValue) {
  391. if (newValue != null && newValue.length == 2) {
  392. this.listQuery.productCategoryId = newValue[1];
  393. } else {
  394. this.listQuery.productCategoryId = null;
  395. }
  396. }
  397. },
  398. filters: {
  399. verifyStatusFilter(value) {
  400. if (value === 1) {
  401. return '审核通过';
  402. } else {
  403. return '未审核';
  404. }
  405. }
  406. },
  407. methods: {
  408. getProductSkuSp(row, index) {
  409. let spData = JSON.parse(row.spData);
  410. if(spData!=null&&index<spData.length){
  411. return spData[index].value;
  412. }else{
  413. return null;
  414. }
  415. },
  416. getList() {
  417. this.listLoading = true;
  418. fetchList(this.listQuery).then(response => {
  419. this.listLoading = false;
  420. this.list = response.data.list;
  421. this.total = response.data.total;
  422. });
  423. },
  424. getBrandList() {
  425. fetchBrandList({pageNum: 1, pageSize: 100}).then(response => {
  426. this.brandOptions = [];
  427. let brandList = response.data.list;
  428. for (let i = 0; i < brandList.length; i++) {
  429. this.brandOptions.push({label: brandList[i].name, value: brandList[i].id});
  430. }
  431. });
  432. },
  433. getProductCateList() {
  434. fetchListWithChildren().then(response => {
  435. let list = response.data;
  436. this.productCateOptions = [];
  437. for (let i = 0; i < list.length; i++) {
  438. let children = [];
  439. if (list[i].children != null && list[i].children.length > 0) {
  440. for (let j = 0; j < list[i].children.length; j++) {
  441. children.push({label: list[i].children[j].name, value: list[i].children[j].id});
  442. }
  443. }
  444. this.productCateOptions.push({label: list[i].name, value: list[i].id, children: children});
  445. }
  446. });
  447. },
  448. handleShowSkuEditDialog(index,row){
  449. this.editSkuInfo.dialogVisible=true;
  450. this.editSkuInfo.productId=row.id;
  451. this.editSkuInfo.productSn=row.productSn;
  452. this.editSkuInfo.productAttributeCategoryId = row.productAttributeCategoryId;
  453. this.editSkuInfo.keyword=null;
  454. fetchSkuStockList(row.id,{keyword:this.editSkuInfo.keyword}).then(response=>{
  455. this.editSkuInfo.stockList=response.data;
  456. });
  457. if(row.productAttributeCategoryId!=null){
  458. fetchProductAttrList(row.productAttributeCategoryId,{type:0}).then(response=>{
  459. this.editSkuInfo.productAttr=response.data.list;
  460. });
  461. }
  462. },
  463. handleSearchEditSku(){
  464. fetchSkuStockList(this.editSkuInfo.productId,{keyword:this.editSkuInfo.keyword}).then(response=>{
  465. this.editSkuInfo.stockList=response.data;
  466. });
  467. },
  468. handleEditSkuConfirm(){
  469. if(this.editSkuInfo.stockList==null||this.editSkuInfo.stockList.length<=0){
  470. this.$message({
  471. message: '暂无sku信息',
  472. type: 'warning',
  473. duration: 1000
  474. });
  475. return
  476. }
  477. this.$confirm('是否要进行修改', '提示', {
  478. confirmButtonText: '确定',
  479. cancelButtonText: '取消',
  480. type: 'warning'
  481. }).then(()=>{
  482. updateSkuStockList(this.editSkuInfo.productId,this.editSkuInfo.stockList).then(response=>{
  483. this.$message({
  484. message: '修改成功',
  485. type: 'success',
  486. duration: 1000
  487. });
  488. this.editSkuInfo.dialogVisible=false;
  489. });
  490. });
  491. },
  492. handleSearchList() {
  493. this.listQuery.pageNum = 1;
  494. this.getList();
  495. },
  496. handleAddProduct() {
  497. this.$router.push({path:'/pms/addProduct'});
  498. },
  499. handleBatchOperate() {
  500. if(this.operateType==null){
  501. this.$message({
  502. message: '请选择操作类型',
  503. type: 'warning',
  504. duration: 1000
  505. });
  506. return;
  507. }
  508. if(this.multipleSelection==null||this.multipleSelection.length<1){
  509. this.$message({
  510. message: '请选择要操作的商品',
  511. type: 'warning',
  512. duration: 1000
  513. });
  514. return;
  515. }
  516. this.$confirm('是否要进行该批量操作?', '提示', {
  517. confirmButtonText: '确定',
  518. cancelButtonText: '取消',
  519. type: 'warning'
  520. }).then(() => {
  521. let ids=[];
  522. for(let i=0;i<this.multipleSelection.length;i++){
  523. ids.push(this.multipleSelection[i].id);
  524. }
  525. switch (this.operateType) {
  526. case this.operates[0].value:
  527. this.updatePublishStatus(1,ids);
  528. break;
  529. case this.operates[1].value:
  530. this.updatePublishStatus(0,ids);
  531. break;
  532. case this.operates[2].value:
  533. this.updateRecommendStatus(1,ids);
  534. break;
  535. case this.operates[3].value:
  536. this.updateRecommendStatus(0,ids);
  537. break;
  538. case this.operates[4].value:
  539. this.updateNewStatus(1,ids);
  540. break;
  541. case this.operates[5].value:
  542. this.updateNewStatus(0,ids);
  543. break;
  544. case this.operates[6].value:
  545. break;
  546. case this.operates[7].value:
  547. this.updateDeleteStatus(1,ids);
  548. break;
  549. default:
  550. break;
  551. }
  552. this.getList();
  553. });
  554. },
  555. handleSizeChange(val) {
  556. this.listQuery.pageNum = 1;
  557. this.listQuery.pageSize = val;
  558. this.getList();
  559. },
  560. handleCurrentChange(val) {
  561. this.listQuery.pageNum = val;
  562. this.getList();
  563. },
  564. handleSelectionChange(val) {
  565. this.multipleSelection = val;
  566. },
  567. handlePublishStatusChange(index, row) {
  568. let ids = [];
  569. ids.push(row.id);
  570. this.updatePublishStatus(row.publishStatus, ids);
  571. },
  572. handleNewStatusChange(index, row) {
  573. let ids = [];
  574. ids.push(row.id);
  575. this.updateNewStatus(row.newStatus, ids);
  576. },
  577. handleRecommendStatusChange(index, row) {
  578. let ids = [];
  579. ids.push(row.id);
  580. this.updateRecommendStatus(row.recommandStatus, ids);
  581. },
  582. handleResetSearch() {
  583. this.selectProductCateValue = [];
  584. this.listQuery = Object.assign({}, defaultListQuery);
  585. },
  586. handleDelete(index, row){
  587. this.$confirm('是否要进行删除操作?', '提示', {
  588. confirmButtonText: '确定',
  589. cancelButtonText: '取消',
  590. type: 'warning'
  591. }).then(() => {
  592. let ids = [];
  593. ids.push(row.id);
  594. this.updateDeleteStatus(1,ids);
  595. });
  596. },
  597. handleUpdateProduct(index,row){
  598. this.$router.push({path:'/pms/updateProduct',query:{id:row.id}});
  599. },
  600. handleShowProduct(index,row){
  601. console.log("handleShowProduct",row);
  602. },
  603. handleShowVerifyDetail(index,row){
  604. console.log("handleShowVerifyDetail",row);
  605. },
  606. handleShowLog(index,row){
  607. console.log("handleShowLog",row);
  608. },
  609. updatePublishStatus(publishStatus, ids) {
  610. let params = new URLSearchParams();
  611. params.append('ids', ids);
  612. params.append('publishStatus', publishStatus);
  613. updatePublishStatus(params).then(response => {
  614. this.$message({
  615. message: '修改成功',
  616. type: 'success',
  617. duration: 1000
  618. });
  619. });
  620. },
  621. updateNewStatus(newStatus, ids) {
  622. let params = new URLSearchParams();
  623. params.append('ids', ids);
  624. params.append('newStatus', newStatus);
  625. updateNewStatus(params).then(response => {
  626. this.$message({
  627. message: '修改成功',
  628. type: 'success',
  629. duration: 1000
  630. });
  631. });
  632. },
  633. updateRecommendStatus(recommendStatus, ids) {
  634. let params = new URLSearchParams();
  635. params.append('ids', ids);
  636. params.append('recommendStatus', recommendStatus);
  637. updateRecommendStatus(params).then(response => {
  638. this.$message({
  639. message: '修改成功',
  640. type: 'success',
  641. duration: 1000
  642. });
  643. });
  644. },
  645. updateDeleteStatus(deleteStatus, ids) {
  646. let params = new URLSearchParams();
  647. params.append('ids', ids);
  648. params.append('deleteStatus', deleteStatus);
  649. updateDeleteStatus(params).then(response => {
  650. this.$message({
  651. message: '删除成功',
  652. type: 'success',
  653. duration: 1000
  654. });
  655. this.getList();
  656. });
  657. // location.reload();
  658. },
  659. handleVerify(index,row){
  660. this.$confirm('是否审核通过此产品?', '提示', {
  661. confirmButtonText: '确定',
  662. cancelButtonText: '取消',
  663. type: 'warning'
  664. }).then(() => {
  665. let id = row.id;
  666. updateVerifyStatus(id).then(res => {
  667. this.$message({
  668. message: res.message,
  669. type: 'success',
  670. duration: 1000
  671. });
  672. this.getList();
  673. });
  674. });
  675. // console.log(row)
  676. }
  677. }
  678. }
  679. </script>
  680. <style></style>