goodsList.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <template>
  2. <div class="app-container calendar-list-container">
  3. <!-- 查询和其他操作 -->
  4. <div class="filter-container">
  5. <el-input clearable class="filter-item" style="width: 200px;" placeholder="商品名称"
  6. v-model="listQuery.name"></el-input>
  7. <el-input clearable class="filter-item" style="width: 200px;" placeholder="商品编号"
  8. v-model="listQuery.seq"></el-input>
  9. <!-- <el-date-picker class="filter-item" v-model="listQuery.shelfTime" type="datetime" placeholder="商品上架时间">
  10. </el-date-picker> -->
  11. <el-select v-model="listQuery.status" clearable placeholder="状态" style="top: -4px;width: 200px;">
  12. <el-option :key="item.type" v-for="item in goodsStatusList" :label="item.name" :value="item.type">
  13. </el-option>
  14. </el-select>
  15. <el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">查找</el-button>
  16. <el-button class="filter-item" type="primary" @click="handleCreate" icon="el-icon-edit">添加</el-button>
  17. </div>
  18. <!-- 查询结果 -->
  19. <el-table size="small" :data="list" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit
  20. highlight-current-row>
  21. <el-table-column type="index" label="序号" header-align="center" align="center">
  22. </el-table-column>
  23. <el-table-column align="center" min-width="100px" label="商品名称" prop="name">
  24. </el-table-column>
  25. <el-table-column align="center" min-width="120px" label="商品编号" prop="seq">
  26. </el-table-column>
  27. <el-table-column align="center" min-width="80px" label="商品属性">
  28. <template slot-scope="props">
  29. <span v-if="props.row.productAttribute == 1">实物</span>
  30. <span v-if="props.row.productAttribute == 0">虚拟</span>
  31. </template>
  32. </el-table-column>
  33. <el-table-column align="center" min-width="80px" label="积分" prop="price">
  34. </el-table-column>
  35. <el-table-column align="center" min-width="100px" label="库存量" prop="actualStock">
  36. </el-table-column>
  37. <el-table-column align="center" min-width="100px" label="可兑换库存量" prop="stock">
  38. </el-table-column>
  39. <el-table-column align="center" min-width="80px" label="兑换方式">
  40. <template slot-scope="props">
  41. <span v-if="props.row.deliveryType == 1">快递</span>
  42. <span v-if="props.row.deliveryType == 0">无需快递</span>
  43. </template>
  44. </el-table-column>
  45. <el-table-column align="center" min-width="100px" label="商品所在地" prop="location">
  46. </el-table-column>
  47. <!-- <el-table-column align="center" min-width="150px" label="上架时间" prop="shelfTime">
  48. </el-table-column> -->
  49. <el-table-column align="center" min-width="80px" label="商品状态">
  50. <template slot-scope="props">
  51. <span v-if="props.row.status == 1">上架</span>
  52. <span v-if="props.row.status == 0">下架</span>
  53. </template>
  54. </el-table-column>
  55. <el-table-column align="center" min-width="80px" label="兑换记录">
  56. <template slot-scope="props">
  57. <span @click="handleView(props.row)" style="color:green;cursor: pointer;">查看</span>
  58. </template>
  59. </el-table-column>
  60. <el-table-column align="center" label="操作" width="240px" class-name="small-padding fixed-width">
  61. <template slot-scope="scope">
  62. <el-button type="primary" size="small" @click="handleUpdate(scope.row)">编辑</el-button>
  63. <el-button v-if="scope.row.status == 0" type="success" size="small"
  64. @click="changeGoodsState(scope.row.skuId, 1)">上架</el-button>
  65. <el-button v-if="scope.row.status == 1" type="warning" size="small"
  66. @click="changeGoodsState(scope.row.skuId, 0)">下架</el-button>
  67. <el-button type="danger" size="mini" @click="handleDelete(scope.row.skuId, -1)">删除</el-button>
  68. </template>
  69. </el-table-column>
  70. </el-table>
  71. <!-- 分页 -->
  72. <div class="pagination-container">
  73. <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
  74. :current-page="listQuery.page" :page-sizes="[10, 20, 30, 50]" :page-size="listQuery.limit"
  75. layout="total, sizes, prev, pager, next, jumper" :total="total">
  76. </el-pagination>
  77. </div>
  78. <!-- 员工积分记录列表 -->
  79. <el-dialog title="兑换记录" :visible.sync="dialogListVisible" width="70%" style="overflow: auto;">
  80. <div class="filter-container">
  81. <el-select filterable v-model="itemListQuery.deptId" clearable placeholder="部门" style="top: -4px;width: 200px;">
  82. <el-option :key="item.deptId" v-for="item in depTypeList" :label="item.deptName" :value="item.deptId">
  83. </el-option>
  84. </el-select>
  85. <el-input clearable class="filter-item" style="width: 200px;" placeholder="员工名称"
  86. v-model="itemListQuery.userName"></el-input>
  87. <el-button class="filter-item" type="primary" v-waves icon="el-icon-search"
  88. @click="itemHandleFilter">查找</el-button>
  89. <el-button class="filter-item" type="primary" @click="handleDownLoad" v-waves icon="el-icon-download">导出</el-button>
  90. </div>
  91. <!-- 查询结果 -->
  92. <el-table size="small" :data="itemList" v-loading="listLoading" element-loading-text="正在查询中。。。" border fit
  93. highlight-current-row>
  94. <el-table-column type="index" label="序号" header-align="center" align="center">
  95. </el-table-column>
  96. <el-table-column align="center" width="200px" label="部门" prop="deptName">
  97. </el-table-column>
  98. <el-table-column align="center" label="员工姓名" prop="purchaser">
  99. </el-table-column>
  100. <el-table-column align="center" label="兑换方式" prop="deliveryTypeName">
  101. </el-table-column>
  102. <el-table-column align="center" label="联系人" prop="contact">
  103. </el-table-column>
  104. <el-table-column align="center" width="120px" label="联系方式" prop="contactPhone">
  105. </el-table-column>
  106. <el-table-column align="center" width="200px" label="地址" prop="contactAddr">
  107. </el-table-column>
  108. <el-table-column align="center" width="200px" label="邮箱" prop="contactEmail">
  109. </el-table-column>
  110. <el-table-column align="center" width="150px" label="兑换时间" prop="createTime">
  111. </el-table-column>
  112. </el-table>
  113. <!-- 分页 -->
  114. <div class="pagination-container">
  115. <el-pagination background @size-change="itemHandleSizeChange" @current-change="itemHandleCurrentChange"
  116. :current-page="itemListQuery.page" :page-sizes="[10, 20, 30, 50]" :page-size="itemListQuery.limit"
  117. layout="total, sizes, prev, pager, next, jumper" :total="itemTotal">
  118. </el-pagination>
  119. </div>
  120. </el-dialog>
  121. <!-- 添加或修改对话框 -->
  122. <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible" width="70%">
  123. <el-form :rules="rules" ref="dataForm" :model="dataForm" status-icon label-position="left" label-width="100px" style='width:700px; margin-left:50px;'>
  124. <el-form-item label="商品名称" prop="name">
  125. <el-input v-model="dataForm.name"></el-input>
  126. </el-form-item>
  127. <el-form-item label="商品编号" prop="seq">
  128. <el-input placeholder="添加成功后自动生成" readonly v-model="dataForm.seq"></el-input>
  129. </el-form-item>
  130. <el-form-item label="商品属性" prop="productAttribute">
  131. <el-select v-model="dataForm.productAttribute" filterable placeholder="请选择" style="width: 350px"
  132. value-key="value" @change="changeProductAttribute">
  133. <el-option :key="item.type" v-for="item in productAttributeList" :label="item.name"
  134. :value="item.type">
  135. </el-option>
  136. </el-select>
  137. </el-form-item>
  138. <el-form-item label="兑换方式" prop="deliveryType">
  139. <el-select v-model="dataForm.deliveryType" filterable placeholder="请选择" style="width: 350px">
  140. <el-option :key="item.type" v-for="item in deliveryTypeList" :label="item.name" :value="item.type">
  141. </el-option>
  142. </el-select>
  143. </el-form-item>
  144. <el-form-item label="商品所在地" prop="location">
  145. <el-select v-model="dataForm.location" filterable placeholder="请选择" style="width: 350px">
  146. <el-option :key="item.index" v-for="item in locationList" :label="item" :value="item">
  147. </el-option>
  148. </el-select>
  149. </el-form-item>
  150. <!-- <el-form-item v-if="dataForm.deliveryType==0" label="商品所在地" prop="location">
  151. <el-select v-model="dataForm.location" filterable placeholder="请选择" style="width: 350px">
  152. <el-option :key="item.index" v-for="item in locationList" :label="item" :value="item">
  153. </el-option>
  154. </el-select>
  155. </el-form-item> -->
  156. <el-form-item style="width: 800px" label="商品图片" prop="imgUrl">
  157. <el-tooltip content="建议图片宽高比260*200" placement="top-start">
  158. <el-upload :limit="1" :action="fileImgUrl" list-type="picture-card" :file-list="dataForm.images"
  159. :on-success="handleGallerySucess" :on-exceed="handleExceed" :before-upload="uploadBannerImg"
  160. :on-remove="handleRemove">
  161. <i class="el-icon-plus"></i>
  162. </el-upload>
  163. </el-tooltip>
  164. </el-form-item>
  165. <el-form-item label="积分" prop="price">
  166. <el-input v-model="dataForm.price"></el-input>
  167. </el-form-item>
  168. <el-form-item label="库存量" prop="actualStock">
  169. <el-input-number :precision="0" :step="1" v-model="dataForm.actualStock"></el-input-number>
  170. </el-form-item>
  171. </el-form>
  172. <div slot="footer" class="dialog-footer">
  173. <el-button @click="dialogFormVisible = false">取消</el-button>
  174. <el-button v-if="dialogStatus == 'create'" type="primary" @click="createData">确定</el-button>
  175. <el-button v-else type="primary" @click="updateData">确定</el-button>
  176. </div>
  177. </el-dialog>
  178. </div>
  179. </template>
  180. <style>
  181. .demo-table-expand {
  182. font-size: 0;
  183. }
  184. .demo-table-expand label {
  185. width: 200px;
  186. color: #99a9bf;
  187. }
  188. .demo-table-expand .el-form-item {
  189. margin-right: 0;
  190. margin-bottom: 0;
  191. }
  192. </style>
  193. <script>
  194. import { createItem, updateItem, goodsList, goodsState, exchangeHistory } from "@/api/goodsManage";
  195. import { depTypeList } from "@/api/public";
  196. import waves from "@/directive/waves"; // 水波纹指令
  197. import Tinymce from '@/components/Tinymce'
  198. export default {
  199. name: 'goodsList',
  200. components: { Tinymce },
  201. directives: { waves },
  202. data() {
  203. return {
  204. locationList:['洛阳','北京','上海'],
  205. productAttributeList: [
  206. {
  207. type: 1,
  208. name: '实物'
  209. },
  210. {
  211. type: 0,
  212. name: '虚拟'
  213. },
  214. ],
  215. deliveryTypeList: [
  216. {
  217. type: 1,
  218. name: '快递'
  219. },
  220. {
  221. type: 0,
  222. name: '无需快递'
  223. },
  224. ],
  225. goodsStatusList: [
  226. {
  227. type: 1,
  228. name: '上架'
  229. },
  230. {
  231. type: 0,
  232. name: '下架'
  233. },
  234. ],
  235. depTypeList: [],
  236. list: [],
  237. itemList: [],
  238. total: 0,
  239. itemTotal: 0,
  240. listLoading: false,
  241. downloadLoading: false,
  242. listQuery: {
  243. page: 1,
  244. limit: 10,
  245. name: '',
  246. seq: '',
  247. status: '',
  248. },
  249. itemListQuery: {
  250. page: 1,
  251. limit: 10,
  252. skuId:'',
  253. deptId: '',
  254. userName: '',
  255. },
  256. dataForm: {
  257. name: undefined,
  258. seq: undefined,
  259. productAttribute: undefined,
  260. imgUrl: undefined,
  261. price: undefined,
  262. actualStock: undefined,
  263. deliveryType: undefined,
  264. location: undefined,
  265. images: [],
  266. },
  267. dialogFormVisible: false,
  268. dialogStatus: '',
  269. textMap: {
  270. update: "编辑",
  271. create: "创建",
  272. },
  273. rules: {
  274. name: [{ required: true, message: "请填写商品名称", trigger: "blur" }],
  275. imgUrl: [{ required: true, message: "请上传商品图片", trigger: "blur" }],
  276. productAttribute: [{ required: true, message: "请选择商品属性", trigger: "blur" }],
  277. price: [{ required: true, message: "请填写商品积分", trigger: "blur" }],
  278. actualStock: [{ required: true, message: "请设置库存量", trigger: "blur" }],
  279. deliveryType: [{ required: true, message: "请选择兑换方式", trigger: "blur" }],
  280. location: [{ required: true, message: "请选择商品所在地", trigger: "blur" }],
  281. },
  282. dialogListVisible: false,
  283. fileImgUrl: "https://xiaoyou.dgtis.com/admin/storage/create",
  284. }
  285. },
  286. created() {
  287. // this.getCompanyTypeList();
  288. this.getDepTypeList();
  289. this.getList();
  290. },
  291. methods: {
  292. handleDownLoad(){
  293. window.location.href = process.env.BASE_API + '/mall-sku/exportSkuLog?skuId=' + this.itemListQuery.skuId + '&deptId=' + this.itemListQuery.deptId + '&userName=' + this.itemListQuery.userName;
  294. },
  295. changeProductAttribute(val) {
  296. this.dataForm.deliveryType = '';
  297. this.dataForm.location = '';
  298. if (val == 1) {
  299. this.deliveryTypeList = [
  300. {
  301. type: 1,
  302. name: '快递'
  303. },
  304. {
  305. type: 0,
  306. name: '无需快递'
  307. },
  308. ]
  309. } else {
  310. this.deliveryTypeList = [
  311. {
  312. type: 0,
  313. name: '无需快递'
  314. },
  315. ]
  316. }
  317. },
  318. handleRemove(file, fileList) {
  319. console.log(file, fileList);
  320. let images = [];
  321. for (let i in fileList) {
  322. let response = fileList[i].response;
  323. let url = response.data.url;
  324. images.push(url);
  325. this.dataForm.imgUrl = images.join(",");
  326. }
  327. },
  328. uploadBannerImg(file) {
  329. const isJPGs = file.type === "image/jpeg";
  330. console.log(isJPGs);
  331. },
  332. handleExceed(files, fileList) {
  333. this.$message.warning(
  334. `当前限制选择 1 个文件,本次选择了 ${files.length} 个文件!,共选择了 ${files.length + fileList.length
  335. } 个文件`
  336. );
  337. },
  338. handleGallerySucess(res, file, fileList) {
  339. this.dataForm.imgUrl = ""; // 清空画廊图片数组
  340. let images = [];
  341. for (let i in fileList) {
  342. let response = fileList[i].response;
  343. if (response.errno && response.errno != "0") {
  344. this.$message.error("该图片上传失败,已被移除,请重新上传!");
  345. // 上传失败移除该 file 对象
  346. fileList.splice(i, 1);
  347. } else {
  348. let url = response.data.url;
  349. images.push(url);
  350. }
  351. }
  352. this.dataForm.imgUrl = images.join(",");
  353. },
  354. resetForm() {
  355. this.dataForm = {
  356. name: undefined,
  357. seq: undefined,
  358. productAttribute: undefined,
  359. imgUrl: undefined,
  360. price: undefined,
  361. actualStock: undefined,
  362. deliveryType: undefined,
  363. location: undefined,
  364. images: [],
  365. };
  366. },
  367. handleCreate() {
  368. this.resetForm();
  369. this.dialogFormVisible = true;
  370. this.dialogStatus = "create";
  371. this.$nextTick(() => {
  372. this.$refs["dataForm"].clearValidate();
  373. });
  374. },
  375. createData() {
  376. this.$refs["dataForm"].validate((valid) => {
  377. if (valid) {
  378. console.log(this.dataForm);
  379. createItem(this.dataForm)
  380. .then((response) => {
  381. this.getList();
  382. this.dialogFormVisible = false;
  383. this.$notify({
  384. title: "成功",
  385. message: "创建成功",
  386. type: "success",
  387. duration: 2000,
  388. });
  389. this.reload();
  390. })
  391. .catch(() => { });
  392. }
  393. });
  394. },
  395. handleUpdate(row) {
  396. this.dataForm = Object.assign({}, row);
  397. if (row.productAttribute == 1) {
  398. this.deliveryTypeList = [
  399. {
  400. type: 1,
  401. name: '快递'
  402. },
  403. {
  404. type: 0,
  405. name: '无需快递'
  406. },
  407. ]
  408. } else {
  409. this.deliveryTypeList = [
  410. {
  411. type: 0,
  412. name: '无需快递'
  413. },
  414. ]
  415. }
  416. if (this.dataForm.imgUrl) {
  417. let images = this.dataForm.imgUrl.split(",");
  418. this.dataForm.images = [];
  419. for (let i in images) {
  420. let url = images[i];
  421. let name = "image_" + i;
  422. this.dataForm.images.push({
  423. name: name,
  424. url: url,
  425. response: { error: "0", data: { url: url } },
  426. });
  427. }
  428. }
  429. this.dialogStatus = 'update'
  430. this.dialogFormVisible = true
  431. this.$nextTick(() => {
  432. this.$refs['dataForm'].clearValidate()
  433. })
  434. },
  435. updateData() {
  436. this.$refs['dataForm'].validate((valid) => {
  437. if (valid) {
  438. updateItem(this.dataForm).then(() => {
  439. this.dialogFormVisible = false
  440. this.$notify({
  441. title: '成功',
  442. message: '更新成功',
  443. type: 'success',
  444. duration: 2000
  445. })
  446. this.getList()
  447. })
  448. }
  449. })
  450. },
  451. changeGoodsState(id, index) {
  452. goodsState({ skuId: id, status: index }).then(response => {
  453. this.$notify({
  454. title: '成功',
  455. message: '商品状态修改成功',
  456. type: 'success',
  457. duration: 2000
  458. })
  459. this.getList()
  460. })
  461. },
  462. handleDelete(id, index) {
  463. this.$confirm('确认删除吗?', '提示', {
  464. confirmButtonText: '确定',
  465. cancelButtonText: '取消',
  466. type: 'warning'
  467. }).then(() => {
  468. goodsState({ skuId: id, status: index }).then(response => {
  469. this.$notify({
  470. title: '成功',
  471. message: '删除成功',
  472. type: 'success',
  473. duration: 2000
  474. })
  475. this.getList();
  476. })
  477. }).catch(() => {
  478. })
  479. },
  480. getDepTypeList() {
  481. depTypeList().then(response => {
  482. this.depTypeList = response.data.data;
  483. }).catch(() => {});
  484. },
  485. getList() {
  486. this.listLoading = true
  487. goodsList(this.listQuery).then(response => {
  488. this.list = response.data.data.items
  489. this.total = response.data.data.total
  490. this.listLoading = false
  491. }).catch(() => {})
  492. },
  493. getItemList() {
  494. this.listLoading = true
  495. exchangeHistory(this.itemListQuery).then(response => {
  496. this.itemList = response.data.data.items
  497. this.itemLotal = response.data.data.total
  498. this.listLoading = false
  499. }).catch(() => {})
  500. },
  501. handleFilter() {
  502. this.listQuery.page = 1
  503. this.getList()
  504. },
  505. handleSizeChange(val) {
  506. this.listQuery.limit = val
  507. this.getList()
  508. },
  509. handleCurrentChange(val) {
  510. this.listQuery.page = val
  511. this.getList()
  512. },
  513. itemHandleFilter() {
  514. this.itemListQuery.page = 1
  515. this.getItemList()
  516. },
  517. itemHandleSizeChange(val) {
  518. this.itemListQuery.limit = val
  519. this.getItemList()
  520. },
  521. itemHandleCurrentChange(val) {
  522. this.itemListQuery.page = val
  523. this.getItemList()
  524. },
  525. handleView(row) {
  526. this.itemListQuery.skuId = row.skuId;
  527. this.getItemList();
  528. this.dialogListVisible = true
  529. },
  530. }
  531. }
  532. </script>
  533. <style>
  534. .ad-avatar-uploader .el-upload {
  535. border: 1px dashed #d9d9d9;
  536. border-radius: 6px;
  537. cursor: pointer;
  538. position: relative;
  539. overflow: hidden;
  540. }
  541. .ad-avatar-uploader .el-upload:hover {
  542. border-color: #409EFF;
  543. }
  544. .ad-avatar-uploader-icon {
  545. font-size: 28px;
  546. color: #8c939d;
  547. width: 178px;
  548. height: 178px;
  549. line-height: 178px;
  550. text-align: center;
  551. }
  552. .ad-avatar {
  553. display: block;
  554. }
  555. </style>