goods.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
  2. var Controller = {
  3. index: function () {
  4. // 初始化表格参数配置
  5. Table.api.init({
  6. extend: {
  7. index_url: 'goods/index' + location.search,
  8. add_url: 'goods/add',
  9. edit_url: 'goods/edit',
  10. del_url: 'goods/del',
  11. multi_url: 'goods/multi',
  12. import_url: 'goods/import',
  13. bind_url: 'goods/bind_goods',
  14. statistics_url: 'goods/goods_statistics',
  15. amount_rank_url: 'goods/goods_buy_rank',
  16. order_amount_rank_url: 'goods/order_amount_rank',
  17. order_num_rank_url: 'goods/order_num_rank',
  18. copy_url: 'goods/copy',
  19. table: 'goods',
  20. }
  21. });
  22. let extend=$.fn.bootstrapTable.defaults.extend
  23. var table = $("#table");
  24. // 初始化表格
  25. table.bootstrapTable({
  26. url: $.fn.bootstrapTable.defaults.extend.index_url,
  27. pk: 'id',
  28. sortName: 'id',
  29. searchFormVisible:true,
  30. columns: [
  31. [
  32. {checkbox: true},
  33. {field: 'id', title: __('Id')},
  34. {field: 'name', title: __('Name'),formatter: Table.api.formatter.content,width:200,operate: 'like'},
  35. {field: 'category.name', title: __('分类'),formatter: Table.api.formatter.label,operate: "like"},
  36. {field: 'brand', title: __('Brand'),operate: 'like'},
  37. //{field: 'amount', title: __('售价'), operate:'BETWEEN'},
  38. //{field: 'amount_kill', title: __('Amount_kill'), operate:'BETWEEN'},
  39. {field: 'is_hot', title: __('Is_hot'),formatter:Table.api.formatter.label,searchList:{0:'否',1:'是'}},
  40. {field: 'is_kill', title: __('Is_kill'),formatter:Table.api.formatter.label,searchList:{0:'否',1:'是'}},
  41. {field: 'is_level_discount', title: __('参与会员折扣'),formatter:Table.api.formatter.label,searchList:{0:'否',1:'是'}},
  42. {field: 'status', title: __('状态'),formatter:Table.api.formatter.label,searchList:goodsStatus},
  43. {field: 'sku', title: __('库存预警'),operate: false,formatter(sku,goods){
  44. let a=[],
  45. stock=goods.is_kill?'num_stock':'num_stock_kill'
  46. /*sku.forEach(item=>{
  47. if(item.num_stock>0 && item.num_stock<=10){
  48. a.push(`<div class="bg-yellow" style="margin-top: 5px;">${item.name}库存:${item.num_stock}</div>`)
  49. }else if(item.num_stock===0){
  50. a.push(`<div class="bg-gray" style="margin-top: 5px;">${item.name}库存:${item.num_stock}</div>`)
  51. }else{
  52. a.push(`<div class="bg-green" style="margin-top: 5px;">${item.name}库存:${item.num_stock}</div>`)
  53. }
  54. })
  55. return a.join('')*/
  56. if(goods.num_stock===0){
  57. return `<a class="label label-danger"">是</a>`
  58. }else if(goods.num_stock<=10){
  59. return `<a class="label label-warning"">是</a>`
  60. }else{
  61. return `<a class="label label-success"">否</a>`
  62. }
  63. }},
  64. {field: 'num_sell', title: __('Num_sell')},
  65. {field: 'create_time', title: __('Create_time'),formatter: Table.api.formatter.datetime,addClass:'datetimerange'},
  66. //{field: 'update_time', title: __('Update_time'),formatter: Table.api.formatter.datetime,addClass:'datetimerange'},
  67. {field:'',title:'统计',table: table,events: Table.api.events.operate,formatter: Table.api.formatter.buttons,operate: false,
  68. buttons:[
  69. {
  70. name: 'detail',
  71. text: __('商品组合'),
  72. title: __('商品组合'),
  73. classname: 'btn btn-xs btn-primary btn-dialog btn-operation',
  74. icon: 'fa',
  75. url: extend.bind_url,
  76. callback: function (data) {
  77. },
  78. visible: function (row) {
  79. return table.data('operate-bind_goods');
  80. }
  81. },
  82. {
  83. name: 'detail',
  84. text: __('数据统计'),
  85. title: __('数据统计'),
  86. classname: 'btn btn-xs btn-info btn-dialog btn-operation btn-operation-mt10',
  87. icon: 'fa',
  88. url: extend.statistics_url,
  89. extend:`data-area='["800px","80%"]'`,
  90. callback: function (data) {
  91. },
  92. visible: function (row) {
  93. return table.data('operate-buy_rank');
  94. }
  95. },
  96. {
  97. name: 'detail',
  98. text: __('采购金额排名'),
  99. title: __('采购金额排名'),
  100. classname: 'btn btn-xs btn-info btn-dialog btn-operation btn-operation-mt10',
  101. icon: 'fa',
  102. url: extend.amount_rank_url,
  103. extend:`data-area='["800px","80%"]'`,
  104. callback: function (data) {
  105. },
  106. visible: function (row) {
  107. return table.data('operate-buy_rank');
  108. }
  109. },
  110. {
  111. name: 'detail',
  112. text: __('订单金额排名'),
  113. title: __('订单金额排名'),
  114. classname: 'btn btn-xs btn-info btn-dialog btn-operation btn-operation-mt10',
  115. icon: 'fa',
  116. url: extend.order_amount_rank_url,
  117. extend:`data-area='["800px","80%"]'`,
  118. callback: function (data) {
  119. },
  120. visible: function (row) {
  121. return table.data('operate-order_amount_rank');
  122. }
  123. },
  124. {
  125. name: 'detail',
  126. text: __('订单笔数排名'),
  127. title: __('订单笔数排名'),
  128. classname: 'btn btn-xs btn-info btn-dialog btn-operation btn-operation-mt10',
  129. icon: 'fa',
  130. url: extend.order_num_rank_url,
  131. extend:`data-area='["800px","80%"]'`,
  132. callback: function (data) {
  133. },
  134. visible: function (row) {
  135. return table.data('operate-order_num_rank');
  136. }
  137. },
  138. {
  139. name: 'detail',
  140. text: __('复制商品'),
  141. title: __('复制商品'),
  142. confirm: __('复制此商品?'),
  143. classname: 'btn btn-xs btn-danger btn-ajax btn-operation btn-operation-mt10',
  144. icon: 'fa',
  145. url: extend.copy_url,
  146. extend:`data-area='["800px","80%"]'`,
  147. success: function (data) {
  148. $('.btn-refresh').trigger('click')
  149. },
  150. visible: function (row) {
  151. return table.data('operate-copy');
  152. }
  153. },
  154. ]},
  155. {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate},
  156. ]
  157. ],
  158. onLoadSuccess(){
  159. setTimeout(()=>{
  160. $('.btn-editone').attr('data-area','["900px","100%"]')
  161. },100)
  162. }
  163. });
  164. $(document).on('click','.bindGoods',function (){
  165. let id=$(this).data('id')
  166. Fast.api.open(extend.bind_url+`/id/${id}`,'绑定商品')
  167. })
  168. // 为表格绑定事件
  169. Table.api.bindevent(table);
  170. },
  171. add: function () {
  172. this.editor()
  173. },
  174. edit: function () {
  175. this.editor(1)
  176. },
  177. goods_statistics(){
  178. //Controller.api.bindevent();
  179. Form.events.daterangepicker($('.form'))
  180. $('.doSearch').click(()=>{
  181. layer.load()
  182. })
  183. },
  184. goods_buy_rank(){
  185. Table.api.init()
  186. var table = $("#table");
  187. // 初始化表格
  188. table.bootstrapTable({
  189. url: location.href,
  190. pk: 'id',
  191. sortName: 'id',
  192. searchFormVisible:true,
  193. showExport:false,
  194. commonSearch:true,
  195. search:false,
  196. columns: [
  197. [
  198. {field: 'rank', title: __('排名'),operate:false,},
  199. {field: 'nickname', title: __('用户名'),operate:false,},
  200. {field: 'amount', title: __('金额'),operate:false,},
  201. {field: 'date', title: __('时间'),operate:'range',addClass:'datetimerange',visible:false},
  202. ]
  203. ]
  204. });
  205. Table.api.bindevent(table);
  206. },
  207. order_amount_rank(){
  208. Table.api.init()
  209. var table = $("#table");
  210. // 初始化表格
  211. table.bootstrapTable({
  212. url: location.href,
  213. pk: 'id',
  214. sortName: 'id',
  215. searchFormVisible:true,
  216. showExport:false,
  217. commonSearch:true,
  218. search:false,
  219. columns: [
  220. [
  221. {field: 'rank', title: __('排名'),operate: false,},
  222. {field: 'order_no', title: __('订单号'),operate: false,},
  223. {field: 'nickname', title: __('用户名'),operate: false,},
  224. {field: 'amount', title: __('金额'),operate: false,},
  225. {field: 'date', title: __('时间'),operate:'range',addClass:'datetimerange',visible:false},
  226. ]
  227. ]
  228. });
  229. Table.api.bindevent(table);
  230. },
  231. order_num_rank(){
  232. Table.api.init()
  233. var table = $("#table");
  234. // 初始化表格
  235. table.bootstrapTable({
  236. url: location.href,
  237. pk: 'id',
  238. sortName: 'id',
  239. searchFormVisible:true,
  240. showExport:false,
  241. commonSearch:true,
  242. search:false,
  243. columns: [
  244. [
  245. {field: 'rank', title: __('排名'),operate: false,},
  246. {field: 'nickname', title: __('用户名'),operate: false,},
  247. {field: 'num', title: __('笔数'),operate: false,},
  248. {field: 'date', title: __('时间'),operate:'range',addClass:'datetimerange',visible:false},
  249. ]
  250. ]
  251. });
  252. Table.api.bindevent(table);
  253. },
  254. editor(isEdit){
  255. let app=new Vue({
  256. el:'#app',
  257. data(){
  258. return {
  259. form:row||{
  260. is_hot:0,
  261. is_kill:0,
  262. is_level_discount:0,
  263. is_fix:0,
  264. status:1,
  265. is_ni:1,
  266. logo:[],
  267. video:null,
  268. size:[],
  269. sku:[],
  270. detail:{},
  271. service:[{name:null,value:null}],
  272. },
  273. category:category,
  274. status:status,
  275. logoLength:5,
  276. idx:1,
  277. isLoad:false,
  278. rules:{
  279. name:[{required:true,message:'此项必须'}],
  280. category_id:[{required:true,message:'此项必须'}],
  281. brand:[{required:true,message:'此项必须'}],
  282. describe:[{required:true,message:'此项必须'}],
  283. logo:[{required:true,message:'此项必须'},{type:'array',min:1,message: '请上传'}],
  284. size:[{required:true,message:'此项必须'}],
  285. sku:[{required:true,message:'此项必须'}],
  286. }
  287. }
  288. },
  289. mounted(){
  290. Controller.api.bindevent();
  291. },
  292. filters:{
  293. showName(key){
  294. }
  295. },
  296. methods:{
  297. addImg(type, index, multiple) {
  298. let that = this;
  299. let ext
  300. if(type==='image'){
  301. ext='image/*'
  302. }else if(type==='video'){
  303. ext='video/mp4'
  304. }
  305. parent.Fast.api.open(`general/attachment/select?mimetype=${ext}&multiple=` + multiple, "选择图片", {
  306. callback: function (data) {
  307. switch (type) {
  308. case "image":
  309. data.url.split(',').forEach(item=>{
  310. if(that.form.logo.length<that.logoLength) {
  311. that.form.logo.push(item)
  312. }
  313. })
  314. break;
  315. case "video":
  316. that.form.video=data.url
  317. break;
  318. }
  319. }
  320. });
  321. return false;
  322. },
  323. delImg(index) {
  324. this.form.logo.splice(index,1)
  325. },
  326. delVideo(){
  327. this.form.video=null
  328. },
  329. addMain(){
  330. let idx=this.form.size.length+1
  331. this.form.size.push({
  332. type:'',
  333. names:[],
  334. })
  335. /*this.$set(this.form.size,idx,{
  336. type:null,
  337. names:{},
  338. })*/
  339. },
  340. delMain(idx){
  341. this.$delete(this.form.size,idx)
  342. this.buildSku()
  343. },
  344. addName(spec){
  345. this.$prompt('请输入名称', '提示', {
  346. confirmButtonText: '确定',
  347. cancelButtonText: '取消',
  348. inputErrorMessage: '请输入',
  349. inputPattern:/\S+/
  350. }).then(({value})=>{
  351. for (let i=0;i<Object.values(this.form.size).length;i++){
  352. for (let a=0;a<Object.values(this.form.size[i].names).length;a++){
  353. if(this.form.size[i].names[a].name==value){
  354. this.$message.error('名称已存在')
  355. return false
  356. }
  357. }
  358. }
  359. spec.names.push({
  360. name:value,
  361. temp_id:Date.now().toString(),
  362. })
  363. this.buildSku()
  364. })
  365. },
  366. changeName(item,idx,item_idx){
  367. this.$prompt('请输入名称', '提示', {
  368. confirmButtonText: '确定',
  369. cancelButtonText: '取消',
  370. inputErrorMessage: '请输入',
  371. inputPattern:/\S+/,
  372. inputValue:item.name
  373. }).then(({value})=>{
  374. for (let i=0;i<Object.values(this.form.size).length;i++){
  375. for (let a=0;a<Object.values(this.form.size[i].names).length;a++){
  376. if(this.form.size[i].names[a].name==value && i!==idx && a!==item_idx){
  377. this.$message.error('名称已存在')
  378. return false
  379. }
  380. }
  381. }
  382. item.name=value
  383. this.buildSku()
  384. })
  385. },
  386. buildSku(){
  387. this.setTableList()
  388. },
  389. /**
  390. * 设置表格数据 该方法在新增规格、新增规格值、规格和规格值的文本改变都要调用
  391. */
  392. setTableList(){
  393. let newList=[];
  394. this.getRowList(null,0,newList,null)
  395. this.form.sku=newList;
  396. },
  397. /**
  398. * 获取行数据 specList规格集合 tableList表格集合
  399. * @param specValues 多规格值通过逗号拼接组成每一行唯一值
  400. * @param specIndex 规格索引
  401. * @param newList 新表格数据
  402. * @param temp_ids
  403. */
  404. getRowList(specValues,specIndex,newList,temp_ids){
  405. if(specIndex<this.form.size.length){
  406. this.form.size[specIndex].names.forEach((t)=>{
  407. let newValues=(specValues===null?t.name:(specValues+","+t.name))
  408. let new_temp_ids=(temp_ids===null?t.temp_id:(temp_ids+","+t.temp_id))
  409. //当前规格值,一直往下规格值循环完
  410. this.getRowList(newValues,specIndex+1,newList,new_temp_ids)
  411. })
  412. //当添加新规格(第二个规格的时候)没有规格值时,默认一个空值
  413. if(this.form.size[specIndex].names.length===0 && specValues!==null){
  414. let newValues=specValues+","
  415. let new_temp_ids=temp_ids+","
  416. this.getRowList(newValues,specIndex+1,newList,new_temp_ids)
  417. }
  418. }
  419. //当最后规格的规格值循环到最后后添加行数据
  420. else{
  421. //判断表格行数据是否已经存在,存在直接添加不创建新行
  422. let row = this.form.sku.find((r)=>{
  423. //return r.specValues.split(',').sort().toString()===specValues.split(',').sort().toString()
  424. let eq=r.temp_ids.split(',').sort().toString() === temp_ids.split(',').sort().toString()
  425. return eq
  426. });
  427. if(row){
  428. specValues.split(',').forEach((c,index)=>{
  429. row["sku-"+index]=c
  430. })
  431. row.specValues=specValues
  432. newList.push({...row})
  433. }
  434. else{
  435. //默认的字段
  436. row = {
  437. size:specIndex,
  438. specValues:specValues,
  439. temp_ids:temp_ids,
  440. num_stock:0,
  441. num_stock_kill:0,
  442. amount_cost:0,
  443. amount_ladder:[
  444. {
  445. min:null,
  446. max:null,
  447. amount:null,
  448. }
  449. ],
  450. amount_kill_ladder:[
  451. {
  452. min:null,
  453. max:null,
  454. amount:null,
  455. }
  456. ],
  457. detail:[
  458. {
  459. name:null,
  460. value:null,
  461. }
  462. ],
  463. is_down:0,
  464. num_max:0,
  465. }
  466. //通过规格值循环出规格值列数
  467. specValues.split(',').forEach((c,index)=>{
  468. row["sku-"+index]=c
  469. })
  470. newList.push(row);
  471. }
  472. }
  473. },
  474. nameChange(idx,name){
  475. //console.log(this.form.sku,this.sku)
  476. this.setTableList()
  477. },
  478. delSize(spec,idx){
  479. //this.$delete(spec.names,idx)
  480. spec.names.splice(idx,1)
  481. this.setTableList()
  482. },
  483. addLadder(ladder){
  484. ladder.push({min:null,max:null,amount:null})
  485. this.$forceUpdate()
  486. },
  487. delLadder(ladder,idx){
  488. if(ladder.length>1) {
  489. ladder.splice(idx, 1)
  490. }
  491. this.$forceUpdate()
  492. },
  493. addDetail(arr){
  494. arr.push({name:null,value:null})
  495. },
  496. delDetail(arr,idx){
  497. arr.splice(idx, 1)
  498. },
  499. addService(){
  500. this.form.service.push({name:null,value:null})
  501. },
  502. delService(idx){
  503. this.form.service.splice(idx, 1)
  504. },
  505. saveGoods(){
  506. this.form.content=$('#c-content').val()
  507. if(!this.form.content){
  508. layer.msg('请填写商品详情')
  509. return
  510. }
  511. let _this=this
  512. this.$refs.form.validate(v=>{
  513. if(!v){
  514. layer.msg('请填写商品信息')
  515. return
  516. }
  517. this.isLoad=true
  518. let form=JSON.stringify(this.form)
  519. $.ajax('',{
  520. type:'post',
  521. data:form,
  522. dataType:"json",
  523. headers:{
  524. 'content-type':'application/json'
  525. },
  526. success({code,msg}){
  527. if(code){
  528. parent.document.getElementsByClassName('btn-refresh')[0].click()
  529. Fast.api.close()
  530. }else{
  531. layer.alert(msg)
  532. }
  533. },
  534. error(){
  535. layer.alert('服务器错误')
  536. },
  537. complete(){
  538. _this.isLoad=false
  539. }
  540. })
  541. })
  542. },
  543. makeDown(sku){
  544. let val=sku.is_down?0:1
  545. this.$set(sku,'is_down',val)
  546. this.$message.success(`${val?'下架':'上架'}成功`)
  547. }
  548. }
  549. })
  550. },
  551. api: {
  552. bindevent: function () {
  553. Form.api.bindevent($("form[role=form]"));
  554. }
  555. },
  556. bind_goods(){
  557. Controller.api.bindevent();
  558. $('.skuItem input[type=radio]').change(function (){
  559. getGoods(goods.id,this.value)
  560. })
  561. let getGoods=(goods_id,sku_id)=>{
  562. let idx=layer.load()
  563. $.post('',{e:'get',sku_id,goods_id},function (res){
  564. if(res.data.length) {
  565. $('#c-name').val(res.data.join(','))
  566. }else{
  567. $('#c-name').selectPageClear()
  568. }
  569. $('#c-name').selectPageRefresh();
  570. layer.close(idx)
  571. })
  572. }
  573. $('.firstSku').trigger('click')
  574. }
  575. };
  576. return Controller;
  577. });