index.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView('component/com-add-cat', __DIR__);
  4. ComponentHelper::loadComponentView('com-export-dialog');
  5. ?>
  6. <style>
  7. </style>
  8. <div id="app" v-cloak>
  9. <el-card shadow="never" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  10. <div slot="header">
  11. <span>商品列表</span>
  12. </div>
  13. <div class="table-body">
  14. <el-tabs v-model="activeName" @tab-click="handleClick">
  15. <el-tab-pane v-for="item in tabs" :key="item.value" :label="item.name" :name="item.value">
  16. <el-form :inline="true" :model="search_data" size="small" class="demo-form-inline">
  17. <el-form-item>
  18. <el-button size="small" @click="$refs.cats.openDialog()">分类筛选</el-button>
  19. <el-button size="small" v-if="search_data.cats && search_data.cats.length > 0" type="danger" @click="clearCat">清除分类</el-button>
  20. </el-form-item>
  21. <el-form-item>
  22. <el-date-picker style="margin-top: 1px;" size="small" @change="changeTime" v-model="datetime" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']"></el-date-picker>
  23. </el-form-item>
  24. <el-form-item label="">
  25. <el-input size="small" placeholder="请输入商品名称" v-model="search_data.goods_name"></el-input>
  26. </el-form-item>
  27. <el-form-item label="">
  28. <el-input size="small" placeholder="请输入商品ID精准搜索" v-model="search_data.goods_id"></el-input>
  29. </el-form-item>
  30. <el-form-item label="">
  31. <el-input placeholder="请输入商户名称/手机号" v-model="search_data.keyword"></el-input>
  32. </el-form-item>
  33. <el-form-item>
  34. <el-button type="primary" @click="search">搜索</el-button>
  35. <el-button type="primary" @click="multipleOff">批量下架</el-button>
  36. <el-button type="danger" @click="clearSearch" v-if="show_clear_search_btn">清除条件</el-button>
  37. </el-form-item>
  38. </el-form>
  39. <el-table v-loading="listLoading" :data="list" stripe style="width: 100%" @sort-change="sortChange" @selection-change="handleSelectionChange">
  40. <!-- <el-table-column type="selection" align="center" width="60"></el-table-column> -->
  41. <el-table-column type="selection" align="center"> </el-table-column>
  42. <el-table-column label="ID" prop="id" align="center"></el-table-column>
  43. <!-- <el-table-column prop="sort" label="排序" width="150">
  44. <template slot-scope="scope">
  45. <div v-if="sort_id != scope.row.id">
  46. <el-tooltip class="item" effect="dark" content="排序" placement="top">
  47. <span>{{scope.row.sort}}</span>
  48. </el-tooltip>
  49. <el-button class="edit-sort" type="text" @click="edit(scope.row,'sort')">
  50. <img src="resources/img/mall/order/edit.png" alt="">
  51. </el-button>
  52. </div>
  53. <div style="display: flex;align-items: center" v-else>
  54. <el-input style="min-width: 70px" type="number" size="mini" class="change" v-model="sort" autocomplete="off"></el-input>
  55. <el-button class="change-quit" type="text" style="color: #F56C6C;padding: 0 5px" icon="el-icon-error" circle @click="cancelEdit('sort')"></el-button>
  56. <el-button class="change-success" type="text" style="margin-left: 0;color: #67C23A;padding: 0 5px" icon="el-icon-success" circle @click="handle('sort',scope.row)">
  57. </el-button>
  58. </div>
  59. </template>
  60. </el-table-column> -->
  61. <el-table-column label="分类" align="center">
  62. <template slot-scope="scope">
  63. <div class="goods-cat">
  64. <el-tag v-if="scope.row.cats && scope.row.cats.length > 0" size="mini">
  65. {{scope.row.cats[0].name}}
  66. </el-tag>
  67. <el-tooltip v-if="scope.row.cats && scope.row.cats.length > 1" placement="top">
  68. <div slot="content">
  69. <span v-for="item in scope.row.cats" :key="item.id">{{item.name}}&nbsp;</span>
  70. </div>
  71. <span>...</span>
  72. </el-tooltip>
  73. </div>
  74. </template>
  75. </el-table-column>
  76. <el-table-column label="商品名称" min-width="200" prop="goods_name" align="center">
  77. <template slot-scope="scope">
  78. <div flex="cross:center">
  79. <div style="margin-right: 10px;">
  80. <el-image style="width: 50px; height: 50px;border-radius: 5px;" :src="scope.row.cover_pic"></el-image>
  81. </div>
  82. <div v-if="goods_name_id != scope.row.id">
  83. <el-tooltip class="item" effect="dark" content="商品名称" placement="top">
  84. <span>{{scope.row.goods_name}}</span>
  85. </el-tooltip>
  86. <el-button class="edit-sort" type="text" @click="edit(scope.row,'goods_name')">
  87. <img src="resources/img/mall/order/edit.png" alt="">
  88. </el-button>
  89. </div>
  90. <div style="display: flex;align-items: center" v-else>
  91. <el-input style="min-width: 70px" size="mini" class="change" v-model="goods_name" autocomplete="off"></el-input>
  92. <el-button class="change-quit" type="text" style="color: #F56C6C;padding: 0 5px" icon="el-icon-error" circle @click="cancelEdit('goods_name')"></el-button>
  93. <el-button class="change-success" type="text" style="margin-left: 0;color: #67C23A;padding: 0 5px" icon="el-icon-success" circle @click="handle('goods_name',scope.row)">
  94. </el-button>
  95. </div>
  96. </div>
  97. </template>
  98. </el-table-column>
  99. <el-table-column label="售价" prop="price" align="center" sortable="false">
  100. <template slot-scope="scope">
  101. <div size="small">{{scope.row.price}}</div>
  102. </template>
  103. </el-table-column>
  104. <el-table-column label="库存" prop="stock" align="center" sortable="false">
  105. <template slot-scope="scope">
  106. <div size="small" style="color: red;" v-if="scope.row.stock<=scope.row.stock_warning">{{scope.row.stock}}</div>
  107. <div size="small" v-else>{{scope.row.stock}}</div>
  108. </template>
  109. </el-table-column>
  110. <el-table-column label="审核状态" prop="check_status" align="center">
  111. <template slot-scope="scope">
  112. <div size="small" v-if="scope.row.check_status == 1">已通过</div>
  113. <div size="small" v-if="scope.row.check_status == 2">不通过</div>
  114. <div size="small" v-if="scope.row.check_status == 0">审核中</div>
  115. </template>
  116. </el-table-column>
  117. <el-table-column label="商品状态" prop="is_on_sale" align="center">
  118. <template slot-scope="scope">
  119. <div size="small" v-if="scope.row.is_on_sale == 1">上架</div>
  120. <div size="small" v-if="scope.row.is_on_sale == 0">下架</div>
  121. </template>
  122. </el-table-column>
  123. <el-table-column label="创建时间" width="160" prop="created_at" align="center">
  124. <template slot-scope="scope">
  125. <div size="small">{{scope.row.created_at|dateTimeFormat('Y-m-d H:i:s')}}</div>
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="商户信息" width="180" prop="created_at" align="center">
  129. <template slot-scope="scope">
  130. <com-image style="float: left;margin-right: 10px;" mode="aspectFill" :src="scope.row.mch.logo_img"></com-image>
  131. <div>{{scope.row.mch.store_name}}</div>
  132. <div>{{scope.row.mch.shop_mobile}}</div>
  133. </template>
  134. </el-table-column>
  135. <el-table-column label="操作" min-width="300" align="center">
  136. <template slot-scope="scope">
  137. <template v-if="scope.row.addons_name">
  138. <el-tooltip class="item" effect="dark" content="该商品正在参与营销活动,暂不可操作" placement="left-start">
  139. <el-tag size="small" type="warning">{{scope.row.addons_name}}</el-tag>
  140. </el-tooltip>
  141. </template>
  142. <!-- <template v-else="group_buy_active_arr[scope.row.id]"> -->
  143. <!-- <template v-else>
  144. <el-button type="text" @click="handle('edit',scope.row)">编辑</el-button>
  145. <el-button type="text" @click="handle('destroy',scope.row)">删除</el-button>
  146. <el-button type="text" @click="handle('is_on_sale',scope.row)">
  147. <span size="small" v-if="scope.row.is_on_sale == 0">上架</span>
  148. <span size="small" v-if="scope.row.is_on_sale == 1">下架</span>
  149. </el-button>
  150. <el-button type="text" @click="handle('model',scope.row)">模式</el-button>
  151. </template> -->
  152. <template v-else>
  153. <el-button v-if="scope.row.check_status == 1" type="text" @click="handle('edit',scope.row)">编辑</el-button>
  154. <el-button v-if="scope.row.check_status == 1" type="text" @click="handle('destroy',scope.row)">删除</el-button>
  155. <el-button v-if="scope.row.check_status == 1" type="text" @click="handle('model',scope.row)">模式</el-button>
  156. <el-button v-if="scope.row.check_status == 0" type="text" @click="handle('audit',scope.row)">审核</el-button>
  157. </template>
  158. </template>
  159. </el-table-column>
  160. </el-table>
  161. <div style="text-align: right;margin: 20px 0;">
  162. <el-pagination @current-change="pagination" background layout="prev, pager, next" :page-count="pageCount"></el-pagination>
  163. </div>
  164. </el-tab-pane>
  165. </el-tabs>
  166. </div>
  167. </el-card>
  168. <!-- 分类筛选 -->
  169. <com-add-cat ref="cats" :new-cats="search_data.cats" @select="selectCat" :mch_id="mch_id"></com-add-cat>
  170. </div>
  171. <script>
  172. const app = new Vue({
  173. el: '#app',
  174. data() {
  175. return {
  176. goods_name: '',
  177. goods_id: '',
  178. tabs: [{
  179. name: '已通过',
  180. value: 'check_adopt'
  181. },
  182. {
  183. name: '待审核',
  184. value: 'check_waiting'
  185. },
  186. {
  187. name: '未通过',
  188. value: 'check_failed'
  189. },
  190. ],
  191. activeName: 'check_adopt',
  192. list: [],
  193. listLoading: false,
  194. page: 1,
  195. pageCount: 0,
  196. mch_id: 0, // 这个地方不知道要怎么获取
  197. searchCats: [],
  198. datetime: [],
  199. search_data: { // 筛选条件
  200. type: 'check_adopt',
  201. cats: [],
  202. start: null,
  203. end: null,
  204. goods_id: null,
  205. goods_name: null,
  206. keyword: '',
  207. },
  208. sort: 0,
  209. sort_id: 0,
  210. goods_name_id: 0,
  211. export_url: 'mall/goods/export-excel',
  212. export_list: {},
  213. group_buy_active_arr: {},
  214. selectedGoodIds: [],
  215. };
  216. },
  217. mounted: function() {
  218. this.getList();
  219. },
  220. computed: {
  221. show_clear_search_btn: function() {
  222. return !isEmpty(this.search_data.cats) || !isEmpty(this.search_data.start) ||
  223. !isEmpty(this.search_data.end) || !isEmpty(this.search_data.goods_id) ||
  224. !isEmpty(this.search_data.goods_name) || !isEmpty(this.search_data.keyword);
  225. }
  226. },
  227. methods: {
  228. selectCat(arr) {
  229. this.search_data.cats = [];
  230. arr.forEach(it => this.search_data.cats.push(it.id))
  231. this.getList()
  232. },
  233. clearCat() { // 清除分类
  234. this.search_data.cats = []
  235. this.getList()
  236. },
  237. changeTime(e) {
  238. // console.log(e)
  239. this.search_data.start = e[0]
  240. this.search_data.end = e[1]
  241. },
  242. handleClick(res) { //标签页切换
  243. if (this.search_data.status == this.activeName) return;
  244. this.search_data.type = this.activeName;
  245. this.getList();
  246. },
  247. sortChange(row) {
  248. if (row.prop) {
  249. this.search_data.sort_field = row.prop;
  250. this.search_data.sort_type = row.order == "descending" ? 'desc' : 'asc';
  251. } else {
  252. this.search_data.sort_prop = null;
  253. this.search_data.sort_type = null;
  254. }
  255. this.getList();
  256. },
  257. search() {
  258. this.page = 1;
  259. this.getList();
  260. },
  261. clearSearch() {
  262. this.search_data.cats = [];
  263. this.search_data.start = null;
  264. this.search_data.end = null;
  265. this.search_data.goods_id = null;
  266. this.search_data.goods_name = null;
  267. this.search_data.keyword = '';
  268. this.datetime = [];
  269. this.getList();
  270. },
  271. handle(type, data = null) {
  272. let id = data ? parseInt(data.id) : '';
  273. switch (type) {
  274. case 'edit':
  275. let params = {
  276. r: 'mch/store-goods/edit'
  277. };
  278. if (id) params = Object.assign(params, {
  279. id: id
  280. });
  281. navigateTo(params);
  282. break;
  283. case 'model': // 模式跳转
  284. param = {
  285. r: 'mch/store-goods/goods-model',
  286. is_mode: true,
  287. };
  288. if (id) param = Object.assign(param, {
  289. id: id
  290. });
  291. navigateTo(param);
  292. break;
  293. case 'destroy':
  294. param = {
  295. id: data.id,
  296. type
  297. };
  298. this.$confirm('删除该条数据后不可以恢复, 是否继续?', '警告', {
  299. type: 'warning'
  300. }).then(() => {
  301. this.send(param)
  302. })
  303. break;
  304. case 'sort':
  305. param = {
  306. id: id,
  307. sort: this.sort,
  308. type
  309. };
  310. this.send(param);
  311. break;
  312. case 'goods_name':
  313. param = {
  314. id: id,
  315. goods_name: this.goods_name,
  316. type
  317. };
  318. this.send(param);
  319. break;
  320. case 'is_on_sale':
  321. param = {
  322. id: id,
  323. is_on_sale: data.is_on_sale == 0 ? 1 : 0,
  324. type
  325. };
  326. operate_type = data.is_on_sale == 0 ? '上架' : '下架';
  327. this.$confirm('是否' + operate_type + '该商品?', '警告', {
  328. type: 'warning'
  329. }).then(() => {
  330. this.send(param)
  331. })
  332. break;
  333. case 'audit':
  334. param = {
  335. r: 'mch/store-goods/edit',
  336. is_audit: true,
  337. };
  338. if (id) param = Object.assign(param, {
  339. id: id
  340. });
  341. navigateTo(param);
  342. break;
  343. }
  344. this.cancelEdit(type);
  345. },
  346. send(params) {
  347. let self = this;
  348. request({
  349. params: {
  350. r: 'mch/store-goods/index',
  351. },
  352. method: 'post',
  353. data: params
  354. }).then(e => {
  355. if (e.data.code == 0) {
  356. self.$message.success(e.data.msg);
  357. self.getList();
  358. } else {
  359. self.$message.error(e.data.msg);
  360. }
  361. }).catch(e => {
  362. console.log(e);
  363. });
  364. },
  365. edit(row, type) {
  366. switch (type) {
  367. case 'sort':
  368. this.sort = row.sort;
  369. this.sort_id = row.id;
  370. break;
  371. case 'goods_name':
  372. this.goods_name_id = row.id;
  373. this.goods_name = row.goods_name;
  374. break;
  375. }
  376. },
  377. cancelEdit(type) {
  378. switch (type) {
  379. case 'sort':
  380. this.sort = 0;
  381. this.sort_id = 0;
  382. break;
  383. case 'goods_name':
  384. this.goods_name = '';
  385. this.goods_name_id = 0;
  386. break;
  387. }
  388. },
  389. searchClick() {
  390. this.page = 1;
  391. this.getList();
  392. },
  393. pagination(currentPage) {
  394. let self = this;
  395. self.page = currentPage;
  396. self.getList();
  397. },
  398. // 获取商品列表
  399. getList() {
  400. let self = this;
  401. let basic_params = {
  402. r: 'mch/store-goods/index',
  403. page: self.page,
  404. };
  405. params = Object.assign(basic_params, this.search_data);
  406. if (self.listLoading == false) {
  407. self.listLoading = true;
  408. request({
  409. params: params,
  410. method: 'get',
  411. }).then(e => {
  412. self.listLoading = false;
  413. if (e.data.code == 0) {
  414. self.list = e.data.data.list;
  415. self.group_buy_active_arr = e.data.data.group_buy_active_arr;
  416. self.pageCount = e.data.data.page_count;
  417. this.export_list = e.data.data.export_list;
  418. } else {
  419. self.$message.error(e.data.msg);
  420. }
  421. }).catch(e => {
  422. self.$message.error(e.data.msg);
  423. self.listLoading = false;
  424. });
  425. }
  426. },
  427. // 批量下架选中
  428. handleSelectionChange(val) {
  429. // console.log(val, 'handleSelectionChange ============= ');
  430. if (val.length) {
  431. this.selectedGoodIds = val.map((e) => {
  432. return e.id;
  433. });
  434. // console.log(this.selectedGoodIds, 'this.selectedGoodIds =============== ');
  435. } else {
  436. this.selectedGoodIds = [];
  437. }
  438. },
  439. // 批量下架商品
  440. multipleOff() {
  441. let self = this;
  442. if (!self.selectedGoodIds.length) {
  443. self.$message.error('请先选择要下架的商品');
  444. return false;
  445. }
  446. self.listLoading = true;
  447. self.$confirm('是否确认下架所选中商品', '警告', {
  448. confirmButtonText: '确定',
  449. cancelButtonText: '取消',
  450. type: 'warning'
  451. }).then(() => {
  452. request({
  453. params: {
  454. r: 'mch/store-goods/mutiple-off',
  455. },
  456. method: 'post',
  457. data: {
  458. good_ids: self.selectedGoodIds,
  459. }
  460. }).then(e => {
  461. self.listLoading = false;
  462. if (e.data.code == 0) {
  463. self.$message.success('操作成');
  464. self.getList();
  465. } else {
  466. self.$message.error(e.data.msg);
  467. return false;
  468. }
  469. }).catch(e => {
  470. self.listLoading = false;
  471. console.log(e);
  472. self.$message.error('网络错误');
  473. return false;
  474. });
  475. }).catch(() => {
  476. self.listLoading = false;
  477. console.log('已取消操作');
  478. return false;
  479. });
  480. },
  481. }
  482. });
  483. </script>