index.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView('components/com-goods-detail', \Yii::$app->controller->module->viewPath);
  4. ?>
  5. <div id="app" v-cloak>
  6. <el-card shadow="never" style="border:0;min-width: 1200px;" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  7. <div slot="header">
  8. <span>选品库</span>
  9. <div style="float: right; margin: -5px 0">
  10. <el-button type="primary" size="small" :disabled="choose_list.length == 0 || btnLoading" v-loading="btnLoading" @click="onBatchWrite">
  11. {{btnLoading ? '导入中...' : '批量导入'}}
  12. </el-button>
  13. </div>
  14. </div>
  15. <div class="table-body">
  16. <el-form size="small" :inline="true" flex="dir:left cross:center">
  17. <div class="item-box">
  18. <el-input clearable size="small" style="width: 200px" v-model="search.goods_name" placeholder="请输入商品名称"></el-input>
  19. </div>
  20. <div class="item-box">
  21. <el-select v-model="search.cate_id" placeholder="请选择类目" clearable size="small">
  22. <el-option v-for="(item, index) in cats" :key="index" :label="item.cate_name" :value="item.third_cate_id"></el-option>
  23. </el-select>
  24. </div>
  25. <div class="item-box">
  26. <el-select v-model="search.imported" placeholder="是否已导入" clearable size="small">
  27. <el-option label="未导入" :value="0"></el-option>
  28. <el-option label="已导入" :value="1"></el-option>
  29. </el-select>
  30. </div>
  31. <div class="item-box" flex="dir:left cross:center">
  32. <el-button size="small" type="primary" style="padding: 9px 15px !important;" @click="searchs">搜索</el-button>
  33. </div>
  34. </el-form>
  35. <el-tabs v-model="activeName" @tab-click="handleClick" v-="loading">
  36. <el-table :data="list" stripe v-loading="loading" size="small" ref="multipleTable" style="margin-bottom: 15px;" @selection-change="handleSelectionChange">
  37. <el-table-column
  38. type="selection"
  39. width="55">
  40. </el-table-column>
  41. <el-table-column label="商品信息" align="left">
  42. <template slot-scope="scope">
  43. <div class="table-info-img-text">
  44. <el-image class="table-info-img circle" :src="scope.row.content.goods.default_image">
  45. <div slot="error" class="image-slot">
  46. <com-image src="/resources/img/common/default-avatar.png"></com-image>
  47. </div>
  48. </el-image>
  49. <div class="table-info-text">
  50. <div style="color:#000; text-align: left">{{scope.row.content.goods.goods_name}}</div>
  51. <div style="font-size: 12px; text-align: left">ID:{{scope.row.content.goods.goods_id}}</div>
  52. </div>
  53. </div>
  54. </template>
  55. </el-table-column>
  56. <el-table-column label="类目" align="center" width="120px">
  57. <template slot-scope="scope">
  58. <span v-if="scope.row.cateOne">{{scope.row.cateOne.cate_name}},</span>
  59. <span v-if="scope.row.cateTwo">{{scope.row.cateTwo.cate_name}}</span>
  60. </template>
  61. </el-table-column>
  62. <el-table-column label="库存" align="center" width="120px">
  63. <template slot-scope="scope">
  64. {{scope.row.content.goods.stock}}
  65. </template>
  66. </el-table-column>
  67. <el-table-column label="是否可售" align="center" width="120px">
  68. <template slot-scope="scope">
  69. <el-tag size="mini" :type="scope.row.content.goods.if_sale == 1 && scope.row.can_sale == 1 ? 'success' : 'danger'">
  70. {{scope.row.content.goods.if_sale == 1 && scope.row.can_sale == 1 ? '是' : '否'}}
  71. </el-tag>
  72. </template>
  73. </el-table-column>
  74. <el-table-column label="状态" align="center" width="120px">
  75. <template slot-scope="scope">
  76. <el-tag size="mini" :type="scope.row.status == 1 ? 'success' : 'danger'">
  77. {{scope.row.status == 1 ? '正常' : '禁用'}}
  78. </el-tag>
  79. </template>
  80. </el-table-column>
  81. <el-table-column label="供货价" align="center" width="120px">
  82. <template slot-scope="scope">
  83. {{scope.row.gonghuojia}}
  84. </template>
  85. </el-table-column>
  86. <el-table-column label="建议零售价" align="center" width="120px">
  87. <template slot-scope="scope">
  88. {{scope.row.retail_price}}
  89. </template>
  90. </el-table-column>
  91. <el-table-column label="商品价格" align="center" width="120px">
  92. <template slot-scope="scope">
  93. {{scope.row.price}}
  94. </template>
  95. </el-table-column>
  96. <el-table-column label="导入状态" align="center" width="120px">
  97. <template slot-scope="scope">
  98. <el-tag size="mini" :type="scope.row.goods_id > 0 ? 'success' : 'danger'">
  99. {{scope.row.goods_id > 0 ? scope.row.goods_id : '未导入'}}
  100. </el-tag>
  101. </template>
  102. </el-table-column>
  103. <el-table-column label="添加时间" width="160" align="center" width="150px">
  104. <template slot-scope="scope">
  105. <div>{{scope.row.created_at|dateTimeFormat('Y-m-d H:i:s')}}</div>
  106. </template>
  107. </el-table-column>
  108. <el-table-column label="导入时间" width="160" align="center" width="150px">
  109. <template slot-scope="scope">
  110. <div v-if="scope.row.goods_id > 0">{{scope.row.import_at|dateTimeFormat('Y-m-d H:i:s')}}</div>
  111. <div v-else>-</div>
  112. </template>
  113. </el-table-column>
  114. <el-table-column label="操作" align="center">
  115. <template slot-scope="scope">
  116. <!-- v-if="scope.row.edit_status == 3"-->
  117. <!-- 更新库存, 修改商品, 提交审核,上架,下架,删除,取消审核 -->
  118. <el-button size="mini" type="text" @click="onDetail(scope.row)">详情</el-button>
  119. <template v-if="scope.row.goods_id == 0">
  120. <el-popconfirm @confirm="writeGoods(scope.row, scope.$index)" title="您真的要导入当前商品吗?">
  121. <el-button type="text" slot="reference" style="color: #67C23A">导入</el-button>
  122. </el-popconfirm>
  123. </template>
  124. <el-popconfirm @confirm="removeGoods(scope.row, scope.$index)"
  125. title="您真的要删除当前商品吗?">
  126. <el-button type="text" slot="reference"
  127. style="color: #F56C6C">移除</el-button>
  128. </el-popconfirm>
  129. </template>
  130. </el-table-column>
  131. </el-table>
  132. </el-tabs>
  133. <!-- 分页器 -->
  134. <div flex="box:last cross:center">
  135. <div></div>
  136. <div>
  137. <el-pagination v-if="pagination" :page-size="pagination.defaultPageSize" style="display: inline-block;" background @current-change="pageChange" layout="prev, pager, next" :total="pagination.totalCount">
  138. </el-pagination>
  139. </div>
  140. </div>
  141. </div>
  142. <!-- 这个是复制用的容器,已隐藏 -->
  143. <textarea id="inputs" style="opacity: 0;width: 0;height: 0;">这是幕后黑手</textarea>
  144. <com-goods-detail :goods-id="goodsDetailId"></com-goods-detail>
  145. </el-card>
  146. </div>
  147. <script>
  148. const app = new Vue({
  149. el: '#app',
  150. data: {
  151. page: 1,
  152. time: [], //本地存时间,请求时不发送
  153. search: {
  154. goods_name: '',
  155. imported: '',
  156. cate_id: '',
  157. },
  158. loading: false,
  159. activeName: '-1',
  160. list: [], //列表数据
  161. pagination: null,
  162. wxList: [],
  163. goodsDialogVisible: false,
  164. btnLoading: false,
  165. cats: <?= $cats ?>,
  166. goodsDetailId: 0,
  167. rate: <?= $rate ?>,
  168. choose_list: [],
  169. },
  170. mounted() {
  171. // 获取列表首页数据
  172. this.loadData(this.page, this.search); //获取列表数据
  173. },
  174. methods: {
  175. onDetail(goods) {
  176. this.goodsDetailId = goods.third_goods_id
  177. },
  178. // 1.0 获取视频列表
  179. loadData(page, others) {
  180. this.loading = true;
  181. request({
  182. method: 'get',
  183. params: {
  184. r: 'qi-shang-tong/default/index',
  185. page: page,
  186. limit: 10,
  187. ...others, //其他搜索字段
  188. },
  189. }).then(e => {
  190. this.loading = false;
  191. if (e.data.code === 0) {
  192. this.edit_status_map = e.data.data.edit_status_map
  193. this._status_map = e.data.data.status_map
  194. this.list = e.data.data.list;
  195. this.shops = e.data.data.shop;
  196. this.pagination = e.data.data.pagination;
  197. } else {
  198. this.$message.error(e.data.msg);
  199. }
  200. }).catch(e => {});
  201. },
  202. pageChange(page) {
  203. this.page = page;
  204. this.loadData(this.page, this.search);
  205. },
  206. handleClick(tab, event) {
  207. this.page = 1;
  208. this.search.status = this.activeName;
  209. this.loadData(this.page, this.search)
  210. },
  211. handleSelectionChange(rows) {
  212. this.choose_list = []
  213. if (rows) {
  214. rows.forEach(row => {
  215. this.choose_list.push(row.id);
  216. });
  217. }
  218. },
  219. searchs() {
  220. this.page = 1;
  221. this.loadData(this.page, this.search);
  222. },
  223. writeGoods(item, index) {
  224. this.btnLoading = true
  225. request({
  226. method: 'post',
  227. params: {
  228. r: 'qi-shang-tong/goods/write',
  229. },
  230. data: {id: item.id}
  231. }).then(e => {
  232. this.btnLoading = false;
  233. if (e.data.code === 0) {
  234. // 数据重载
  235. this.loadData(this.page, this.search)
  236. this.$message.success(e.data.msg);
  237. } else {
  238. this.$message.error(e.data.msg);
  239. }
  240. }).catch(e => {
  241. this.btnLoading = false;
  242. });
  243. },
  244. onBatchWrite() {
  245. if (this.choose_list.length <= 0) {
  246. this.$message.success('请选择需要导入的商品');
  247. return
  248. }
  249. this.btnLoading = true
  250. request({
  251. method: 'post',
  252. params: {
  253. r: 'qi-shang-tong/goods/batch-write',
  254. },
  255. data: {id: this.choose_list}
  256. }).then(e => {
  257. this.btnLoading = false;
  258. if (e.data.code === 0) {
  259. // 数据重载
  260. this.$message.success(e.data.msg);
  261. } else {
  262. this.$message.error(e.data.msg);
  263. }
  264. }).catch(e => {
  265. this.btnLoading = false;
  266. });
  267. },
  268. removeGoods(item, index) {
  269. this.btnLoading = true
  270. request({
  271. method: 'post',
  272. params: {
  273. r: 'qi-shang-tong/goods/del',
  274. },
  275. data: {id: item.id}
  276. }).then(e => {
  277. this.btnLoading = false;
  278. if (e.data.code === 0) {
  279. this.list.splice(index, 1)
  280. this.$message.success(e.data.msg);
  281. } else {
  282. this.$message.error(e.data.msg);
  283. }
  284. }).catch(e => {
  285. this.btnLoading = false;
  286. });
  287. },
  288. onSubmit() {
  289. this.$refs['goodsForm'].validate((valid) => {
  290. if (valid) {
  291. this.btnLoading = true
  292. request({
  293. method: 'post',
  294. params: {
  295. r: 'qi-shang-tong/goods/create',
  296. },
  297. data: this.goodsForm
  298. }).then(e => {
  299. this.btnLoading = false;
  300. if (e.data.code === 0) {
  301. this.page = 1
  302. this.search = {
  303. keyword: '',
  304. audit_status: '',
  305. }
  306. this.loadData(this.page, this.search);
  307. this.onCloseGoodsDialogVisible()
  308. this.$message.success(e.data.msg);
  309. } else {
  310. this.$message.error(e.data.msg);
  311. }
  312. }).catch(e => {
  313. this.btnLoading = false;
  314. });
  315. } else {
  316. console.log(valid)
  317. }
  318. })
  319. },
  320. },
  321. });
  322. </script>
  323. <style>
  324. .set-el-button {
  325. padding: 0 !important;
  326. border: 0;
  327. margin: 0 5px;
  328. }
  329. .sort-input {
  330. width: 100%;
  331. background-color: #F3F5F6;
  332. height: 32px;
  333. }
  334. .sort-input span {
  335. height: 32px;
  336. width: 100%;
  337. line-height: 32px;
  338. display: inline-block;
  339. padding: 0 10px;
  340. font-size: 13px;
  341. }
  342. .sort-input .el-input__inner {
  343. height: 32px;
  344. line-height: 32px;
  345. background-color: #F3F5F6;
  346. float: left;
  347. padding: 0 10px;
  348. border: 0;
  349. }
  350. .table-body {
  351. padding: 20px;
  352. background-color: #fff;
  353. }
  354. .table-info .el-button {
  355. padding: 0 !important;
  356. border: 0;
  357. margin: 0 5px;
  358. }
  359. .input-item {
  360. margin: 0 0 20px;
  361. }
  362. .input-item-name {
  363. margin-right: 5px;
  364. }
  365. .input-search {
  366. margin-right: 30px;
  367. }
  368. .input-item .el-input-group__append {
  369. background-color: #fff;
  370. border-left: 0;
  371. width: 10%;
  372. padding: 0;
  373. }
  374. .input-item .el-input-group__append .el-button {
  375. padding: 0;
  376. }
  377. .input-item .el-input-group__append .el-button {
  378. margin: 0;
  379. }
  380. .data-pop-info {
  381. /* padding: 18px 15px 30px; */
  382. color: #333;
  383. }
  384. .data-pop-mode {
  385. background: #F8F8F8;
  386. border-radius: 4px;
  387. margin-bottom: 10px;
  388. }
  389. .data-pop-top {
  390. height: 90px;
  391. }
  392. .data-price {
  393. width: 200px;
  394. flex-direction: column;
  395. border-right: 1px solid #E5E5E5;
  396. }
  397. .data-info {
  398. flex: 1;
  399. padding: 22px 15px;
  400. font-size: 16px;
  401. }
  402. .data-info-name {
  403. display: inline-block;
  404. text-align: end;
  405. }
  406. .data-pop-detail {
  407. padding: 15px 18px;
  408. }
  409. .data-detail-mode {
  410. min-width: 33%;
  411. flex-shrink: 0;
  412. text-align: center;
  413. margin-top: 16px;
  414. line-height: 26px;
  415. font-size: 16px;
  416. }
  417. .share-pop-model {
  418. margin-top: 20px;
  419. }
  420. .share-name {
  421. width: 90px;
  422. display: inline-block;
  423. margin-right: 18px;
  424. text-align: end;
  425. }
  426. .flex-y-center {
  427. display: -webkit-box;
  428. display: -webkit-flex;
  429. display: flex;
  430. -webkit-box-align: center;
  431. -webkit-align-items: center;
  432. -ms-flex-align: center;
  433. -ms-grid-row-align: center;
  434. align-items: center;
  435. }
  436. </style>
  437. <style>
  438. .el-tabs__header {
  439. font-size: 16px;
  440. }
  441. .table-body {
  442. padding: 20px;
  443. background-color: #fff;
  444. }
  445. .table-body .el-button {
  446. padding: 0 !important;
  447. border: 0;
  448. margin: 0 5px;
  449. }
  450. .input-item {
  451. width: 250px;
  452. margin: 0 0 20px;
  453. display: inline-block;
  454. }
  455. .input-item .el-input__inner {
  456. border-right: 0;
  457. }
  458. .input-item .el-input__inner:hover {
  459. border: 1px solid #dcdfe6;
  460. border-right: 0;
  461. outline: 0;
  462. }
  463. .input-item .el-input__inner:focus {
  464. border: 1px solid #dcdfe6;
  465. border-right: 0;
  466. outline: 0;
  467. }
  468. .input-item .el-input-group__append {
  469. background-color: #fff;
  470. border-left: 0;
  471. width: 10%;
  472. padding: 0;
  473. }
  474. .input-item .el-input-group__append .el-button {
  475. padding: 0;
  476. }
  477. .input-item .el-input-group__append .el-button {
  478. margin: 0;
  479. }
  480. .batch {
  481. margin: 0 0 20px;
  482. display: inline-block;
  483. }
  484. .batch .el-button {
  485. padding: 9px 15px !important;
  486. }
  487. .item-box {
  488. margin-right: 20px;
  489. }
  490. .item-box .label {
  491. margin-right: 8px;
  492. }
  493. .item-box .symbol {
  494. margin: 0 6px;
  495. }
  496. .form-nickname {
  497. width: 180px;
  498. white-space: nowrap;
  499. overflow: hidden;
  500. text-overflow: ellipsis;
  501. }
  502. .index-video-url {
  503. width: 300px;
  504. }
  505. .index-video-url video {
  506. width: 100%;
  507. }
  508. .index-related-info {
  509. width: 500px;
  510. }
  511. .video-top {
  512. width: 100%;
  513. display: flex;
  514. align-items: flex-start;
  515. box-sizing: border-box;
  516. padding: 20px;
  517. /* opacity: .5; */
  518. background-color: #FFFFFF;
  519. }
  520. .video-top .top-right {
  521. line-height: 26px;
  522. }
  523. .video-top .top-right .top-title {
  524. font-size: 18px;
  525. white-space: nowrap;
  526. overflow: hidden;
  527. text-overflow: ellipsis;
  528. width: 360px;
  529. }
  530. .video-top .top-right .wrapper {
  531. display: flex;
  532. /* align-items: flex-start; */
  533. }
  534. .video-top .top-right .wrapper .to-copy {
  535. /* color: #03C5FF; */
  536. margin-left: 20px;
  537. }
  538. .video-top .top-right .detail-price {
  539. color: #BC0100;
  540. font-size: 18px;
  541. font-family: Microsoft YaHei;
  542. font-weight: bold;
  543. }
  544. /* .atooltip {
  545. background: #FFFFFF !important;
  546. border: none !important;
  547. } */
  548. .el-table th>.cell {
  549. color: #333;
  550. font-weight: bold;
  551. font-size: 14px;
  552. }
  553. .el-table__footer-wrapper,
  554. .el-table__header-wrapper {
  555. border-bottom: 1.4px solid #D6D6D6;
  556. }
  557. .price_col {
  558. color: #FF5D05;
  559. }
  560. </style>