index.php 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView('com-dialog-select');
  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" @click="onEdit(0)">添加商品</el-button>
  11. </div>
  12. </div>
  13. <div class="table-body">
  14. <el-form size="small" :inline="true" flex="dir:left cross:center">
  15. <div class="item-box">
  16. <el-select v-model="search.shop_id" placeholder="请选择所属店铺进行搜索" clearable size="small">
  17. <el-option v-for="(name, index) in shops" :key="index" :label="name" :value="index"></el-option>
  18. </el-select>
  19. </div>
  20. <div class="item-box">
  21. <el-select v-model="search.audit_status" placeholder="请选择审核状态搜索" clearable size="small">
  22. <el-option v-for="(name, index) in status_map" :key="index" :label="name" :value="index"></el-option>
  23. </el-select>
  24. </div>
  25. <div class="item-box">
  26. <el-input clearable size="small" style="width: 200px" v-model="search.keyword" placeholder="请输入商品名称"></el-input>
  27. </div>
  28. <div class="item-box" flex="dir:left cross:center">
  29. <el-button size="small" type="primary" style="padding: 9px 15px !important;" @click="searchs">搜索</el-button>
  30. </div>
  31. </el-form>
  32. <el-tabs v-model="activeName" @tab-click="handleClick" v-="loading">
  33. <el-table :data="list" stripe v-loading="loading" size="small" style="margin-bottom: 15px;" @selection-change="handleSelectionChange">
  34. <el-table-column label="店铺" align="center" width="150px">
  35. <template slot-scope="scope">
  36. {{scope.row.shop.name}}
  37. </template>
  38. </el-table-column>
  39. <el-table-column label="商品ID" prop="goods_id" align="center" width="120px"></el-table-column>
  40. <el-table-column label="商品信息" align="left">
  41. <template slot-scope="scope">
  42. <div class="table-info-img-text">
  43. <el-image class="table-info-img circle" :src="scope.row.goods.cover_pic">
  44. <div slot="error" class="image-slot">
  45. <com-image src="/resources/img/common/default-avatar.png"></com-image>
  46. </div>
  47. </el-image>
  48. <div class="table-info-text">
  49. <div style="color:#000; text-align: left">{{scope.row.goods.goods_name}}</div>
  50. <!-- <div style="font-size: 12px; text-align: left">{{scope.row.user.mobile}}</div>-->
  51. </div>
  52. </div>
  53. </template>
  54. </el-table-column>
  55. <el-table-column label="库存" prop="stock" align="center" width="120px"></el-table-column>
  56. <el-table-column label="审核状态" align="center" width="120px">
  57. <template slot-scope="scope">
  58. <el-tag size="mini" :type="audit_status_map[scope.row.audit_status].type">
  59. {{edit_status_map[scope.row.third_data.edit_product.edit_status]}}
  60. </el-tag>
  61. </template>
  62. </el-table-column>
  63. <el-table-column label="失败原因" align="center">
  64. <template slot-scope="scope">
  65. <span v-if="scope.row.audit_reason" style="color:red;">
  66. {{scope.row.audit_reason}}
  67. </span>
  68. <span v-else>
  69. -
  70. </span>
  71. </template>
  72. </el-table-column>
  73. <el-table-column label="商品状态" align="center" width="120px">
  74. <template slot-scope="scope">
  75. <template v-if="scope.row.third_data.product">
  76. <el-tag size="mini" type="default">
  77. {{_status_map[scope.row.third_data.product.status]}}
  78. </el-tag>
  79. </template>
  80. <template v-else>
  81. -
  82. </template>
  83. </template>
  84. </el-table-column>
  85. <el-table-column label="更新时间" width="160" align="center" width="150px">
  86. <template slot-scope="scope">
  87. <div>{{scope.row.updated_at|dateTimeFormat('Y-m-d H:i:s')}}</div>
  88. </template>
  89. </el-table-column>
  90. <el-table-column label="操作" align="center">
  91. <template slot-scope="scope">
  92. <!-- v-if="scope.row.edit_status == 3"-->
  93. <!-- 更新库存, 修改商品, 提交审核,上架,下架,删除,取消审核 -->
  94. <template v-if="scope.row.third_data.edit_product.status == 5">
  95. <el-popconfirm @confirm="onSale(scope.row, 0)" title="您真的要下架当前商品吗?">
  96. <el-button type="text" slot="reference" style="color: #F56C6C">下架</el-button>
  97. </el-popconfirm>
  98. <el-button size="mini" type="text" @click="onUpdateStock(scope.row)">设置库存</el-button>
  99. </template>
  100. <template v-if="scope.row.third_data.edit_product.edit_status == 1">
  101. <el-popconfirm @confirm="onSale(scope.row, 1)" title="您真的要将当前商品提交审核吗?">
  102. <el-button type="text" slot="reference" style="color: #F56C6C">提交审核</el-button>
  103. </el-popconfirm>
  104. </template>
  105. <template v-if="scope.row.third_data.edit_product.edit_status == 2">
  106. <el-popconfirm @confirm="onCancelAudit(scope.row)" title="您真的要将当前商品取消审核吗?">
  107. <el-button type="text" slot="reference" style="color: #F56C6C">取消审核</el-button>
  108. </el-popconfirm>
  109. </template>
  110. <el-button size="mini" type="text" @click="editGoods(scope.row)">编辑</el-button>
  111. <el-popconfirm @confirm="removeGoods(scope.row, scope.$index)"
  112. title="您真的要删除当前商品吗?">
  113. <el-button type="text" slot="reference"
  114. style="color: #F56C6C">删除</el-button>
  115. </el-popconfirm>
  116. </template>
  117. </el-table-column>
  118. </el-table>
  119. </el-tabs>
  120. <!-- 分页器 -->
  121. <div flex="box:last cross:center">
  122. <div></div>
  123. <div>
  124. <el-pagination v-if="pagination" :page-size="pagination.defaultPageSize" style="display: inline-block;" background @current-change="pageChange" layout="prev, pager, next" :total="pagination.totalCount">
  125. </el-pagination>
  126. </div>
  127. </div>
  128. </div>
  129. <!-- 这个是复制用的容器,已隐藏 -->
  130. <textarea id="inputs" style="opacity: 0;width: 0;height: 0;">这是幕后黑手</textarea>
  131. <!-- 添加商品 -->
  132. <el-dialog
  133. title="添加商品"
  134. :visible.sync="goodsDialogVisible"
  135. :close-on-click-modal="false"
  136. :close-on-press-escape="false"
  137. :before-close="onBeforeCloseGoodsDialogVisible"
  138. width="60%">
  139. <el-form size="small" ref="goodsForm" :model="goodsForm" label-position="top">
  140. <el-form-item label="请选择店铺" prop="shop_id" :rules="[{required: true, message: '请选择店铺'}]">
  141. <el-select v-model="goodsForm.shop_id" placeholder="请选择店铺" clearable size="small" @change="onChangeShop">
  142. <el-option v-for="(name, index) in shops" :key="index" :label="name" :value="index"></el-option>
  143. </el-select>
  144. </el-form-item>
  145. <el-form-item label="选择类目" prop="cat_id" :rules="[
  146. {required: true, message:'类目不能为空'}
  147. ]">
  148. <el-cascader-panel v-loading="catLoading" v-model="goodsForm.cats" :options="wxList" :props="{
  149. value: 'id',
  150. label: 'name'
  151. }" @change="onChangeWxCat($event, {}, goodsForm.shop_id)"></el-cascader-panel>
  152. <el-input v-model="goodsForm.cat_id" style="display: none"></el-input>
  153. </el-form-item>
  154. <el-form-item label="选择商品" prop="goods_id" :rules="[
  155. {required: true, message:'商品不能为空'}
  156. ]">
  157. <el-table border size="mini" :data="good ? [good] : []">
  158. <el-table-column prop="id" label="ID" width="80"></el-table-column>
  159. <el-table-column prop="cover_pic" label="商品图" width="180">
  160. <template slot-scope="scope">
  161. <com-image mode="aspectFill" :src="scope.row.cover_pic"></com-image>
  162. </template>
  163. </el-table-column>
  164. <el-table-column prop="name" label="商品名称">
  165. <template slot-scope="scope">
  166. <com-ellipsis :line="2">{{scope.row.goods_name}}</com-ellipsis>
  167. </template>
  168. </el-table-column>
  169. <el-table-column label="操作" width="120" align="center">
  170. <template slot="header" slot-scope="scope">
  171. <com-dialog-select :multiple="false" @selected="goodsSelect" title="选择商品">
  172. <el-button size="mini" type="primary">选择商品</el-button>
  173. </com-dialog-select>
  174. </template>
  175. <template slot-scope="scope">
  176. <el-popconfirm @confirm="onDeleteGoods(scope.row, scope.$index)" title="您真的要移除当前商品吗?">
  177. <el-button type="text" slot="reference" style="color: #F56C6C">删除</el-button>
  178. </el-popconfirm>
  179. </template>
  180. </el-table-column>
  181. </el-table>
  182. <el-input v-model="goodsForm.goods_id" style="display: none"></el-input>
  183. </el-form-item>
  184. <!--是否需要资质-->
  185. <div v-loading="catInfoLoading">
  186. <template v-if="catInfo && catInfo.attr && catInfo.attr.product_attr_list.length > 0">
  187. <h4>产品属性</h4>
  188. <el-form-item :prop="'attr.' + index + '.value'" :rules="item.is_required ? [{required: true, message: item.name + '不能为空'}] : []"
  189. :label="item.name" v-for="(item, index) in catInfo.attr.product_attr_list" :key="index">
  190. <el-input v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'string'" :placeholder="`请选输入${item.name}`"></el-input>
  191. <el-input type="number" v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'integer'" :placeholder="`请选输入${item.name}`"></el-input>
  192. <el-input type="number" v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'decimal4'" :placeholder="`请选输入${item.name}`"></el-input>
  193. <el-input type="number" v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'integer_unit'" :placeholder="`请选输入${item.name}`" class="input-with-select">
  194. <template slot="append">
  195. <el-select v-model="goodsForm.attr[index].ext.value" :placeholder="`请选输入${item.name}`" style="width: 100px">
  196. <el-option v-for="(val, key) in item.select_value.split(';')" :key="key" :label="val" :value="val"></el-option>
  197. </el-select>
  198. </template>
  199. </el-input>
  200. <el-input type="number" v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'decimal4_unit'" :placeholder="`请选输入${item.name}`">
  201. <template slot="append">
  202. <el-select v-model="goodsForm.attr[index].ext.value" :placeholder="`请选输入${item.name}`" style="width: 100px">
  203. <el-option v-for="(val, key) in item.select_value.split(';')" :key="key" :label="val" :value="val"></el-option>
  204. </el-select>
  205. </template>
  206. </el-input>
  207. <el-checkbox-group v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'select_many'">
  208. <el-checkbox v-for="(val, key) in item.value.split(';')" :key="key" :label="val"></el-checkbox>
  209. </el-checkbox-group>
  210. <el-select v-model="goodsForm.attr[index].value" v-if="item.type_v2 == 'select_one'" :placeholder="`请选选择${item.name}`">
  211. <el-option v-for="(val, key) in item.value.split(';')" :key="key" :label="val" :value="val"></el-option>
  212. </el-select>
  213. </el-form-item>
  214. </template>
  215. <template v-if="catInfo && catInfo.attr && catInfo.attr.sale_attr_list.length > 0">
  216. <h4>销售属性</h4>
  217. <el-form-item :prop="'sale_attr.' + index + '.value'" :rules="item.is_required ? [{required: true, message: item.name + '不能为空'}] : []"
  218. :label="item.name" v-for="(item, index) in catInfo.attr.sale_attr_list" :key="index">
  219. <el-input v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'string'" :placeholder="`请选输入${item.name}`"></el-input>
  220. <el-input type="number" v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'integer'" :placeholder="`请选输入${item.name}`"></el-input>
  221. <el-input type="number" v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'decimal4'" :placeholder="`请选输入${item.name}`"></el-input>
  222. <el-input type="number" v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'integer_unit'" :placeholder="`请选输入${item.name}`">
  223. <template #append>{{item.value}}</template>
  224. </el-input>
  225. <el-input type="number" v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'decimal4_unit'" :placeholder="`请选输入${item.name}`">
  226. <template #append>{{item.value}}</template>
  227. </el-input>
  228. <el-checkbox-group v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'select_many'">
  229. <el-checkbox v-for="(val, key) in item.value.split(';')" :key="key" :label="val"></el-checkbox>
  230. </el-checkbox-group>
  231. <el-select v-model="goodsForm.sale_attr[index].value" v-if="item.type_v2 == 'select_one'" :placeholder="`请选选择${item.name}`">
  232. <el-option v-for="(val, key) in item.value.split(';')" :key="key" :label="val" :value="val"></el-option>
  233. </el-select>
  234. </el-form-item>
  235. </template>
  236. </div>
  237. <div style="padding-top: 10px">
  238. <h4>商品资质</h4>
  239. <div flex="dir:left">
  240. <div class="card-coverimg" v-for="(item, index) in goodsForm.qualifications" :key="index">
  241. <el-image class="elImages" style="width: 80px; height: 80px;cursor: move;" :src="item"></el-image>
  242. <el-button @click="delCertificate(index)" class="icon-close" type="primary" size="mini" icon="el-icon-close" circle></el-button>
  243. </div>
  244. <com-attachment v-if="goodsForm.qualifications.length < 5" :multiple="true" :max="9" type="images" @selected="certificatePic">
  245. <div class="card-upload">
  246. <i class="el-icon-plus"></i>
  247. </div>
  248. </com-attachment>
  249. </div>
  250. <p>商品资质图片(最多5张)</p>
  251. </div>
  252. </el-form>
  253. <span slot="footer" class="dialog-footer">
  254. <el-button @click="onCloseGoodsDialogVisible">取 消</el-button>
  255. <el-button type="primary" @click="onSubmit" :disabled="btnLoading" v-loading="btnLoading">确 定</el-button>
  256. </span>
  257. </el-dialog>
  258. <el-dialog
  259. title="设置库存"
  260. :visible.sync="setStockDialogVisible"
  261. width="50%">
  262. <el-form size="small" ref="stockForm" :model="stockForm" label-position="top">
  263. <el-table size="mini" border :data="stockForm.skus">
  264. <el-table-column label="SKU名称" align="left" prop="name">
  265. <template slot-scope="scope">
  266. <div class="table-info-img-text">
  267. <el-image class="table-info-img" :src="scope.row.img">
  268. <div slot="error" class="image-slot">
  269. <com-image src="/resources/img/common/default-avatar.png"></com-image>
  270. </div>
  271. </el-image>
  272. <div class="table-info-text">
  273. <div style="color:#000; text-align: left">{{scope.row.name}}</div>
  274. </div>
  275. </div>
  276. </template>
  277. </el-table-column>
  278. <el-table-column label="销售价格" align="center" prop="sale_price" width="120px"></el-table-column>
  279. <el-table-column label="库存数量" align="center" width="200px">
  280. <template slot-scope="scope">
  281. <el-form-item label="" :prop="'skus.' + scope.$index + '.num'" :rules="[{required: true, message: '库存数量不能为空'}]">
  282. <el-input type="number" v-model="scope.row.num"></el-input>
  283. </el-form-item>
  284. </template>
  285. </el-table-column>
  286. </el-table>
  287. </el-form>
  288. <span slot="footer" class="dialog-footer">
  289. <el-button @click="setStockDialogVisible = false">取 消</el-button>
  290. <el-button type="primary" @click="onSubmitSetStock" :disabled="btnLoading" v-loading="btnLoading">确 定</el-button>
  291. </span>
  292. </el-dialog>
  293. </el-card>
  294. </div>
  295. <script>
  296. const app = new Vue({
  297. el: '#app',
  298. data: {
  299. page: 1,
  300. time: [], //本地存时间,请求时不发送
  301. search: {
  302. keyword: '',
  303. audit_status: '',
  304. },
  305. loading: false,
  306. activeName: '-1',
  307. list: [], //列表数据
  308. pagination: null,
  309. status_map: {
  310. 0: '全部',
  311. 2: '审核拒绝',
  312. 3: '审核通过'
  313. },
  314. audit_status_map: {
  315. 0: {
  316. title: '待提审',
  317. type: 'default'
  318. },
  319. 2: {
  320. title: '审核未通过',
  321. type: 'danger'
  322. },
  323. 3: {
  324. title: '审核通过',
  325. type: 'success'
  326. },
  327. },
  328. wxList: [],
  329. goodsDialogVisible: false,
  330. goodsForm: {
  331. cats: [],
  332. goods_id: 0,
  333. attr: [],
  334. sale_attr: [],
  335. seven_day_return: 0,
  336. qualifications: [],
  337. cat_id: 0,
  338. shop_id: '',
  339. product_id: ''
  340. },
  341. btnLoading: false,
  342. rules: {},
  343. good: null,
  344. catInfo: null,
  345. catInfoLoading: false,
  346. catLoading: false,
  347. shops: {},
  348. edit_status_map: {},
  349. _status_map: {},
  350. stockCurrentItem: null,
  351. setStockDialogVisible: false,
  352. stockForm: {
  353. skus: []
  354. }
  355. },
  356. mounted() {
  357. // 获取列表首页数据
  358. this.loadData(this.page, this.search); //获取列表数据
  359. },
  360. methods: {
  361. // 1.0 获取视频列表
  362. loadData(page, others) {
  363. this.loading = true;
  364. request({
  365. method: 'get',
  366. params: {
  367. r: 'wechat-video-shop/goods/index',
  368. page: page,
  369. limit: 10,
  370. ...others, //其他搜索字段
  371. },
  372. }).then(e => {
  373. this.loading = false;
  374. if (e.data.code === 0) {
  375. this.edit_status_map = e.data.data.edit_status_map
  376. this._status_map = e.data.data.status_map
  377. this.list = e.data.data.list;
  378. this.shops = e.data.data.shop;
  379. this.pagination = e.data.data.pagination;
  380. } else {
  381. this.$message.error(e.data.msg);
  382. }
  383. }).catch(e => {});
  384. },
  385. pageChange(page) {
  386. this.page = page;
  387. this.loadData(this.page, this.search);
  388. },
  389. handleClick(tab, event) {
  390. this.page = 1;
  391. this.search.status = this.activeName;
  392. this.loadData(this.page, this.search)
  393. },
  394. handleSelectionChange(val) {
  395. let self = this;
  396. self.choose_list = [];
  397. val.forEach(function(item) {
  398. self.choose_list.push(item.id);
  399. })
  400. },
  401. searchs() {
  402. this.page = 1;
  403. this.loadData(this.page, this.search);
  404. },
  405. onEdit(id) {
  406. this.goodsDialogVisible = true;
  407. },
  408. getWxCat(shop_id) {
  409. // 获取所有类目
  410. this.catLoading = true
  411. request({
  412. method: 'get',
  413. params: {
  414. r: 'wechat-video-shop/cate/list',
  415. shop_id: shop_id
  416. },
  417. }).then(e => {
  418. this.catLoading = false;
  419. if (e.data.code === 0) {
  420. this.wxList = e.data.data
  421. } else {
  422. this.$message.error(e.data.msg);
  423. }
  424. }).catch(e => {
  425. this.catLoading = false;
  426. });
  427. },
  428. onChangeWxCat(val, values, shop_id) {
  429. this.catInfoLoading = true
  430. if (values == null) values = {}
  431. request({
  432. method: 'get',
  433. params: {
  434. r: 'wechat-video-shop/cate/wx-info',
  435. id: val[2],
  436. shop_id: shop_id
  437. },
  438. }).then(e => {
  439. this.catInfoLoading = false;
  440. if (e.data.code === 0) {
  441. this.catInfo = e.data.data
  442. this.goodsForm.cat_id = val[2]
  443. this.goodsForm.seven_day_return = e.data.data.attr.seven_day_return ? 1 : (e.data.data.attr.seven_day_return ? e.data.data.attr.seven_day_return : 0)
  444. this.goodsForm.attr = []
  445. if (e.data.data.attr.product_attr_list && e.data.data.attr.product_attr_list.length) {
  446. for (let productAttrListKey in e.data.data.attr.product_attr_list) {
  447. let value = values[e.data.data.attr.product_attr_list[productAttrListKey].name] ? values[e.data.data.attr.product_attr_list[productAttrListKey].name] : ''
  448. switch (e.data.data.attr.product_attr_list[productAttrListKey].type_v2) {
  449. case 'integer_unit':
  450. case 'decimal4_unit':
  451. value = value !== "" ? value.split(" ")[0] : '';
  452. // 因为接口中这两种类型有单位需要拆分
  453. let unitValue = e.data.data.attr.product_attr_list[productAttrListKey].value;
  454. e.data.data.attr.product_attr_list[productAttrListKey].select_value = unitValue;
  455. e.data.data.attr.product_attr_list[productAttrListKey].value = unitValue.split(";")[0];
  456. break;
  457. case 'select_many':
  458. value = value !== "" ? value.split(";") : []
  459. break;
  460. }
  461. this.goodsForm.attr.push({
  462. name: e.data.data.attr.product_attr_list[productAttrListKey].name,
  463. value: value,
  464. ext: e.data.data.attr.product_attr_list[productAttrListKey]
  465. })
  466. }
  467. }
  468. if (e.data.data.attr.sale_attr_list && e.data.data.attr.sale_attr_list.length) {
  469. for (let productAttrListKey in e.data.data.attr.sale_attr_list) {
  470. let value = values[e.data.data.attr.product_attr_list[productAttrListKey].name] ? values[e.data.data.attr.product_attr_list[productAttrListKey].name] : ''
  471. switch (e.data.data.attr.product_attr_list[productAttrListKey].type_v2) {
  472. case 'integer_unit':
  473. case 'decimal4_unit':
  474. value = value !== "" ? value.split(" ")[0] : ''
  475. break;
  476. case 'select_many':
  477. value = value !== "" ? value.split(";") : []
  478. break;
  479. }
  480. this.goodsForm.sale_attr.push({
  481. name: e.data.data.attr.sale_attr_list[productAttrListKey].name,
  482. value: value,
  483. ext: e.data.data.attr.sale_attr_list[productAttrListKey]
  484. })
  485. }
  486. }
  487. } else {
  488. this.$message.error(e.data.msg);
  489. }
  490. }).catch(e => {
  491. this.catInfoLoading = false;
  492. });
  493. },
  494. onSubmit() {
  495. this.$refs['goodsForm'].validate((valid) => {
  496. if (valid) {
  497. this.btnLoading = true
  498. request({
  499. method: 'post',
  500. params: {
  501. r: 'wechat-video-shop/goods/create',
  502. },
  503. data: this.goodsForm
  504. }).then(e => {
  505. this.btnLoading = false;
  506. if (e.data.code === 0) {
  507. this.page = 1
  508. this.search = {
  509. keyword: '',
  510. audit_status: '',
  511. }
  512. this.loadData(this.page, this.search);
  513. this.onCloseGoodsDialogVisible()
  514. this.$message.success(e.data.msg);
  515. } else {
  516. this.$message.error(e.data.msg);
  517. }
  518. }).catch(e => {
  519. this.btnLoading = false;
  520. });
  521. } else {
  522. console.log(valid)
  523. }
  524. })
  525. },
  526. goodsSelect(goods) {
  527. if (goods) {
  528. this.good = goods
  529. this.goodsForm.goods_id = goods.id
  530. }
  531. },
  532. onDeleteGoods(item, index) {
  533. this.good = null
  534. this.goodsForm.goods_id = 0
  535. },
  536. certificatePic(e) { // 选择轮播图
  537. if (e.length) {
  538. e.forEach((item, index) => {
  539. if (this.goodsForm.qualifications.length >= 5) return;
  540. this.goodsForm.qualifications.push(item.url);
  541. })
  542. }
  543. },
  544. delCertificate(type, index) { // 删除图片
  545. this.goodsForm.qualifications.splice(index, 1)
  546. },
  547. onChangeShop(shop_id) {
  548. this.getWxCat(shop_id)
  549. },
  550. editGoods(item) {
  551. let content = JSON.parse(item.content)
  552. let cats = []
  553. for (let catsKey in content.cats) {
  554. cats.push(parseInt(content.cats[catsKey].cat_id))
  555. }
  556. let attr_values = {}
  557. if (content.attrs.length > 0) {
  558. for (let i in content.attrs) {
  559. attr_values[content.attrs[i].attr_key] = content.attrs[i].attr_value
  560. }
  561. }
  562. this.getWxCat(item.shop_id)
  563. this.goodsForm = {
  564. cats: cats,
  565. goods_id: item.goods_id,
  566. attr: [],
  567. sale_attr: [],
  568. seven_day_return: 0,
  569. qualifications: content.qualifications ? content.qualifications : [],
  570. cat_id: cats[2],
  571. shop_id: item.shop_id + '',
  572. product_id: item.product_id
  573. }
  574. this.good = item.goods
  575. this.onChangeWxCat(cats, attr_values, item.shop_id)
  576. this.goodsDialogVisible = true
  577. },
  578. removeGoods(item, index) {
  579. request({
  580. method: 'post',
  581. params: {
  582. r: 'wechat-video-shop/goods/delete',
  583. },
  584. data: {
  585. id: item.id
  586. }
  587. }).then(e => {
  588. this.btnLoading = false;
  589. if (e.data.code === 0) {
  590. this.list.splice(index, 1)
  591. this.$message.success(e.data.msg);
  592. } else {
  593. this.$message.error(e.data.msg);
  594. }
  595. }).catch(e => {
  596. this.btnLoading = false;
  597. });
  598. },
  599. onBeforeCloseGoodsDialogVisible() {
  600. this.onCloseGoodsDialogVisible()
  601. },
  602. onCloseGoodsDialogVisible() {
  603. try {
  604. this.goodsDialogVisible = false
  605. this.good = null
  606. this.catInfo = null
  607. this.wxList = []
  608. this.$set(this.goodsForm, 'cats', [])
  609. this.$set(this.goodsForm, 'goods_id', 0)
  610. this.$set(this.goodsForm, 'qualifications', [])
  611. this.$set(this.goodsForm, 'shop_id', '')
  612. this.$set(this.goodsForm, 'product_id', '')
  613. } catch (e) {
  614. }
  615. },
  616. onSale(item, type) {
  617. this.btnLoading = true;
  618. request({
  619. method: 'post',
  620. params: {
  621. r: 'wechat-video-shop/goods/on-sale',
  622. },
  623. data: {
  624. id: item.id,
  625. type: type,
  626. }
  627. }).then(e => {
  628. this.btnLoading = false;
  629. if (e.data.code === 0) {
  630. this.loadData(this.page, this.search);
  631. this.$message.success(e.data.msg);
  632. } else {
  633. this.$message.error(e.data.msg);
  634. }
  635. }).catch(e => {
  636. this.btnLoading = false;
  637. });
  638. },
  639. onCancelAudit(item) {
  640. this.btnLoading = true;
  641. request({
  642. method: 'post',
  643. params: {
  644. r: 'wechat-video-shop/goods/cancel-audit',
  645. },
  646. data: {
  647. id: item.id,
  648. }
  649. }).then(e => {
  650. this.btnLoading = false;
  651. if (e.data.code === 0) {
  652. this.loadData(this.page, this.search);
  653. this.$message.success(e.data.msg);
  654. } else {
  655. this.$message.error(e.data.msg);
  656. }
  657. }).catch(e => {
  658. this.btnLoading = false;
  659. });
  660. },
  661. onUpdateStock(item) {
  662. this.stockCurrentItem = item
  663. this.stockForm.skus = []
  664. for (let skusKey in this.stockCurrentItem.third_data.product.skus) {
  665. let name = ''
  666. for (let skuAttrsKey in this.stockCurrentItem.third_data.product.skus[skusKey].sku_attrs) {
  667. name += this.stockCurrentItem.third_data.product.skus[skusKey].sku_attrs[skuAttrsKey].attr_value + ','
  668. }
  669. this.stockForm.skus.push({
  670. sku_id: this.stockCurrentItem.third_data.product.skus[skusKey].sku_id,
  671. out_sku_id: this.stockCurrentItem.third_data.product.skus[skusKey].out_sku_id,
  672. status: this.stockCurrentItem.third_data.product.skus[skusKey].status,
  673. img: this.stockCurrentItem.third_data.product.skus[skusKey].thumb_img,
  674. stock_num: this.stockCurrentItem.third_data.product.skus[skusKey].stock_num,
  675. num: this.stockCurrentItem.third_data.product.skus[skusKey].stock_num,
  676. name: name.substr(0, name.length - 1),
  677. sale_price: parseFloat(this.stockCurrentItem.third_data.product.skus[skusKey].sale_price * 0.01).toFixed(2),
  678. })
  679. }
  680. this.setStockDialogVisible = true;
  681. },
  682. onSubmitSetStock() {
  683. this.$refs['stockForm'].validate((valid) => {
  684. if (valid) {
  685. this.btnLoading = true
  686. request({
  687. method: 'post',
  688. params: {
  689. r: 'wechat-video-shop/goods/set-stock',
  690. },
  691. data: {
  692. skus: JSON.stringify(this.stockForm.skus),
  693. id: this.stockCurrentItem.id
  694. }
  695. }).then(e => {
  696. this.btnLoading = false;
  697. if (e.data.code === 0) {
  698. this.setStockDialogVisible = false;
  699. this.$message.success(e.data.msg);
  700. } else {
  701. this.$message.error(e.data.msg);
  702. }
  703. }).catch(e => {
  704. this.btnLoading = false;
  705. });
  706. } else {
  707. console.log(valid)
  708. }
  709. })
  710. }
  711. },
  712. });
  713. </script>
  714. <style>
  715. .set-el-button {
  716. padding: 0 !important;
  717. border: 0;
  718. margin: 0 5px;
  719. }
  720. .sort-input {
  721. width: 100%;
  722. background-color: #F3F5F6;
  723. height: 32px;
  724. }
  725. .sort-input span {
  726. height: 32px;
  727. width: 100%;
  728. line-height: 32px;
  729. display: inline-block;
  730. padding: 0 10px;
  731. font-size: 13px;
  732. }
  733. .sort-input .el-input__inner {
  734. height: 32px;
  735. line-height: 32px;
  736. background-color: #F3F5F6;
  737. float: left;
  738. padding: 0 10px;
  739. border: 0;
  740. }
  741. .table-body {
  742. padding: 20px;
  743. background-color: #fff;
  744. }
  745. .table-info .el-button {
  746. padding: 0 !important;
  747. border: 0;
  748. margin: 0 5px;
  749. }
  750. .input-item {
  751. margin: 0 0 20px;
  752. }
  753. .input-item-name {
  754. margin-right: 5px;
  755. }
  756. .input-search {
  757. margin-right: 30px;
  758. }
  759. .input-item .el-input-group__append {
  760. background-color: #fff;
  761. border-left: 0;
  762. width: 10%;
  763. padding: 0;
  764. }
  765. .input-item .el-input-group__append .el-button {
  766. padding: 0;
  767. }
  768. .input-item .el-input-group__append .el-button {
  769. margin: 0;
  770. }
  771. .data-pop-info {
  772. /* padding: 18px 15px 30px; */
  773. color: #333;
  774. }
  775. .data-pop-mode {
  776. background: #F8F8F8;
  777. border-radius: 4px;
  778. margin-bottom: 10px;
  779. }
  780. .data-pop-top {
  781. height: 90px;
  782. }
  783. .data-price {
  784. width: 200px;
  785. flex-direction: column;
  786. border-right: 1px solid #E5E5E5;
  787. }
  788. .data-info {
  789. flex: 1;
  790. padding: 22px 15px;
  791. font-size: 16px;
  792. }
  793. .data-info-name {
  794. display: inline-block;
  795. text-align: end;
  796. }
  797. .data-pop-detail {
  798. padding: 15px 18px;
  799. }
  800. .data-detail-mode {
  801. min-width: 33%;
  802. flex-shrink: 0;
  803. text-align: center;
  804. margin-top: 16px;
  805. line-height: 26px;
  806. font-size: 16px;
  807. }
  808. .share-pop-model {
  809. margin-top: 20px;
  810. }
  811. .share-name {
  812. width: 90px;
  813. display: inline-block;
  814. margin-right: 18px;
  815. text-align: end;
  816. }
  817. .flex-y-center {
  818. display: -webkit-box;
  819. display: -webkit-flex;
  820. display: flex;
  821. -webkit-box-align: center;
  822. -webkit-align-items: center;
  823. -ms-flex-align: center;
  824. -ms-grid-row-align: center;
  825. align-items: center;
  826. }
  827. </style>
  828. <style>
  829. .el-tabs__header {
  830. font-size: 16px;
  831. }
  832. .table-body {
  833. padding: 20px;
  834. background-color: #fff;
  835. }
  836. .table-body .el-button {
  837. padding: 0 !important;
  838. border: 0;
  839. margin: 0 5px;
  840. }
  841. .input-item {
  842. width: 250px;
  843. margin: 0 0 20px;
  844. display: inline-block;
  845. }
  846. .input-item .el-input__inner {
  847. border-right: 0;
  848. }
  849. .input-item .el-input__inner:hover {
  850. border: 1px solid #dcdfe6;
  851. border-right: 0;
  852. outline: 0;
  853. }
  854. .input-item .el-input__inner:focus {
  855. border: 1px solid #dcdfe6;
  856. border-right: 0;
  857. outline: 0;
  858. }
  859. .input-item .el-input-group__append {
  860. background-color: #fff;
  861. border-left: 0;
  862. width: 10%;
  863. padding: 0;
  864. }
  865. .input-item .el-input-group__append .el-button {
  866. padding: 0;
  867. }
  868. .input-item .el-input-group__append .el-button {
  869. margin: 0;
  870. }
  871. .batch {
  872. margin: 0 0 20px;
  873. display: inline-block;
  874. }
  875. .batch .el-button {
  876. padding: 9px 15px !important;
  877. }
  878. .item-box {
  879. margin-right: 20px;
  880. }
  881. .item-box .label {
  882. margin-right: 8px;
  883. }
  884. .item-box .symbol {
  885. margin: 0 6px;
  886. }
  887. .form-nickname {
  888. width: 180px;
  889. white-space: nowrap;
  890. overflow: hidden;
  891. text-overflow: ellipsis;
  892. }
  893. .index-video-url {
  894. width: 300px;
  895. }
  896. .index-video-url video {
  897. width: 100%;
  898. }
  899. .index-related-info {
  900. width: 500px;
  901. }
  902. .video-top {
  903. width: 100%;
  904. display: flex;
  905. align-items: flex-start;
  906. box-sizing: border-box;
  907. padding: 20px;
  908. /* opacity: .5; */
  909. background-color: #FFFFFF;
  910. }
  911. .video-top .top-right {
  912. line-height: 26px;
  913. }
  914. .video-top .top-right .top-title {
  915. font-size: 18px;
  916. white-space: nowrap;
  917. overflow: hidden;
  918. text-overflow: ellipsis;
  919. width: 360px;
  920. }
  921. .video-top .top-right .wrapper {
  922. display: flex;
  923. /* align-items: flex-start; */
  924. }
  925. .video-top .top-right .wrapper .to-copy {
  926. /* color: #03C5FF; */
  927. margin-left: 20px;
  928. }
  929. .video-top .top-right .detail-price {
  930. color: #BC0100;
  931. font-size: 18px;
  932. font-family: Microsoft YaHei;
  933. font-weight: bold;
  934. }
  935. /* .atooltip {
  936. background: #FFFFFF !important;
  937. border: none !important;
  938. } */
  939. .el-table th>.cell {
  940. color: #333;
  941. font-weight: bold;
  942. font-size: 14px;
  943. }
  944. .el-table__footer-wrapper,
  945. .el-table__header-wrapper {
  946. border-bottom: 1.4px solid #D6D6D6;
  947. }
  948. .price_col {
  949. color: #FF5D05;
  950. }
  951. </style>