discount.js 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) {
  2. // 代码更新说明:
  3. // 1. 添加了单规格商品的"折扣库存"列,多规格商品使用按钮方式设置
  4. // 2. 添加了折扣库存输入处理事件,并确保数据被正确保存
  5. // 3. 更新了updateDiscountData函数,确保折扣库存数据被正确提交
  6. var Controller = {
  7. index: function () {
  8. // 初始化表格参数配置
  9. Table.api.init({
  10. extend: {
  11. index_url: 'marketing/discount/index' + location.search,
  12. add_url: 'marketing/discount/add',
  13. edit_url: 'marketing/discount/edit',
  14. del_url: 'marketing/discount/del',
  15. multi_url: 'marketing/discount/multi',
  16. import_url: 'marketing/discount/import',
  17. table: 'shop_activity',
  18. }
  19. });
  20. var table = $("#table");
  21. // 初始化表格
  22. table.bootstrapTable({
  23. url: $.fn.bootstrapTable.defaults.extend.index_url,
  24. pk: 'id',
  25. sortName: 'id',
  26. fixedColumns: true,
  27. fixedRightNumber: 1,
  28. columns: [
  29. [
  30. {checkbox: true},
  31. {field: 'id', title: __('Id'), visible: false},
  32. {
  33. field: 'name',
  34. title: __('活动名称'),
  35. operate: 'LIKE',
  36. align: 'left',
  37. cellStyle: {css: {'max-width': '180px', 'overflow': 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap'}}
  38. },
  39. {
  40. field: 'image',
  41. title: __('活动主图'),
  42. operate: false,
  43. events: Table.api.events.image,
  44. formatter: Table.api.formatter.image,
  45. width: 80
  46. },
  47. {
  48. field: 'type',
  49. title: __('活动类型'),
  50. searchList: {"discount": "折扣活动"},
  51. formatter: Table.api.formatter.normal,
  52. width: 80
  53. },
  54. {
  55. field: 'goods_count',
  56. title: __('商品数量'),
  57. width: 80,
  58. align: 'center'
  59. },
  60. {
  61. field: 'start_time',
  62. title: __('开始时间'),
  63. operate: 'RANGE',
  64. addclass: 'datetimerange',
  65. formatter: Table.api.formatter.datetime,
  66. width: 150
  67. },
  68. {
  69. field: 'end_time',
  70. title: __('结束时间'),
  71. operate: 'RANGE',
  72. addclass: 'datetimerange',
  73. formatter: Table.api.formatter.datetime,
  74. width: 150
  75. },
  76. {
  77. field: 'activity_status',
  78. title: __('活动状态'),
  79. searchList: {
  80. 0: '未开始',
  81. 1: '进行中',
  82. 2: '已结束',
  83. 3: '手动停止'
  84. },
  85. formatter: function(value, row, index) {
  86. var statusMap = {
  87. 0: '<span class="label label-default">未开始</span>',
  88. 1: '<span class="label label-success">进行中</span>',
  89. 2: '<span class="label label-warning">已结束</span>',
  90. 3: '<span class="label label-danger">手动停止</span>'
  91. };
  92. return statusMap[value] || value;
  93. },
  94. width: 80,
  95. align: 'center'
  96. },
  97. {
  98. field: 'order_count',
  99. title: __('订单数'),
  100. width: 80,
  101. align: 'center'
  102. },
  103. {
  104. field: 'order_amount',
  105. title: __('成交金额'),
  106. width: 100,
  107. align: 'right',
  108. formatter: function(value, row, index) {
  109. return '¥' + value;
  110. }
  111. },
  112. {
  113. field: 'discount_amount',
  114. title: __('优惠金额'),
  115. width: 100,
  116. align: 'right',
  117. formatter: function(value, row, index) {
  118. return '¥' + value;
  119. }
  120. },
  121. {
  122. field: 'sale_quantity',
  123. title: __('销售数量'),
  124. width: 80,
  125. align: 'center'
  126. },
  127. {
  128. field: 'customer_count',
  129. title: __('成交人数'),
  130. width: 80,
  131. align: 'center'
  132. },
  133. {
  134. field: 'createtime',
  135. title: __('创建时间'),
  136. operate: 'RANGE',
  137. addclass: 'datetimerange',
  138. formatter: Table.api.formatter.datetime,
  139. visible: false
  140. },
  141. {
  142. field: 'updatetime',
  143. title: __('更新时间'),
  144. operate: 'RANGE',
  145. addclass: 'datetimerange',
  146. formatter: Table.api.formatter.datetime,
  147. visible: false
  148. },
  149. {
  150. field: 'operate',
  151. title: __('操作'),
  152. table: table,
  153. events: Table.api.events.operate,
  154. formatter: Table.api.formatter.operate,
  155. buttons: [
  156. {
  157. name: 'stop',
  158. text: __('停止活动'),
  159. icon: 'fa fa-stop',
  160. classname: 'btn btn-xs btn-warning btn-ajax',
  161. url: 'marketing/discount/stopActivity',
  162. confirm: '确认要停止此活动吗?停止后将无法恢复',
  163. visible: function(row) {
  164. return row.activity_status == 1; // 只有进行中的活动才显示停止按钮
  165. },
  166. success: function(data, ret) {
  167. Layer.msg(ret.msg);
  168. table.bootstrapTable('refresh');
  169. return false;
  170. },
  171. error: function(data, ret) {
  172. Layer.alert(ret.msg);
  173. return false;
  174. }
  175. }
  176. ]
  177. }
  178. ]
  179. ]
  180. });
  181. // 为表格绑定事件
  182. Table.api.bindevent(table);
  183. },
  184. recyclebin: function () {
  185. // 初始化表格参数配置
  186. Table.api.init({
  187. extend: {
  188. 'dragsort_url': ''
  189. }
  190. });
  191. var table = $("#table");
  192. // 初始化表格
  193. table.bootstrapTable({
  194. url: 'marketing/discount/recyclebin' + location.search,
  195. pk: 'id',
  196. sortName: 'id',
  197. columns: [
  198. [
  199. {checkbox: true},
  200. {field: 'id', title: __('Id')},
  201. {field: 'title', title: __('Title'), align: 'left'},
  202. {
  203. field: 'deletetime',
  204. title: __('Deletetime'),
  205. operate: 'RANGE',
  206. addclass: 'datetimerange',
  207. formatter: Table.api.formatter.datetime
  208. },
  209. {
  210. field: 'operate',
  211. width: '140px',
  212. title: __('Operate'),
  213. table: table,
  214. events: Table.api.events.operate,
  215. buttons: [
  216. {
  217. name: 'Restore',
  218. text: __('Restore'),
  219. classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
  220. icon: 'fa fa-rotate-left',
  221. url: 'marketing/discount/restore',
  222. refresh: true
  223. },
  224. {
  225. name: 'Destroy',
  226. text: __('Destroy'),
  227. classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
  228. icon: 'fa fa-times',
  229. url: 'marketing/discount/destroy',
  230. refresh: true
  231. }
  232. ],
  233. formatter: Table.api.formatter.operate
  234. }
  235. ]
  236. ]
  237. });
  238. // 为表格绑定事件
  239. Table.api.bindevent(table);
  240. },
  241. add: function () {
  242. Controller.api.bindevent();
  243. // 表单提交前处理
  244. $('#add-form').on('submit', function(e) {
  245. console.log('=== 表单提交验证开始 ===');
  246. // 验证是否选择了商品
  247. var goodsIds = $('#goods-ids').val();
  248. if (!goodsIds || goodsIds.trim() === '') {
  249. Layer.alert('请先选择参与活动的商品', {icon: 2});
  250. e.preventDefault();
  251. return false;
  252. }
  253. // 更新商品信息
  254. var goodsInfo = updateGoodsInfo();
  255. // 验证商品信息
  256. if (!goodsInfo || goodsInfo.length === 0) {
  257. Layer.alert('商品信息不能为空', {icon: 2});
  258. e.preventDefault();
  259. return false;
  260. }
  261. // 验证每个商品的折扣设置
  262. var hasError = false;
  263. var errorMsg = '';
  264. $.each(goodsInfo, function(index, item) {
  265. if (item.spec_type == 0) {
  266. // 单规格商品验证
  267. if (!item.discount || !item.discount_price || item.discount_stocks === undefined) {
  268. hasError = true;
  269. errorMsg = '商品"' + item.title + '"的折扣信息不完整';
  270. return false;
  271. }
  272. } else if (item.spec_type == 1) {
  273. // 多规格商品验证
  274. if (!item.spec || item.spec.length === 0) {
  275. hasError = true;
  276. errorMsg = '商品"' + item.title + '"请设置规格折扣';
  277. return false;
  278. }
  279. }
  280. });
  281. if (hasError) {
  282. Layer.alert(errorMsg, {icon: 2});
  283. e.preventDefault();
  284. return false;
  285. }
  286. console.log('=== 表单验证通过,准备提交 ===');
  287. console.log('提交的商品ID:', $('#goods-ids').val());
  288. console.log('提交的商品信息:', $('#goods-info').val());
  289. return true;
  290. });
  291. // 选择商品功能
  292. $('#select-goods').on('click', function() {
  293. Fast.api.open('shop/goods/select', '选择商品', {
  294. area: ['95%', '90%'],
  295. callback: function(data) {
  296. if (data && data.length > 0) {
  297. // 使用共享的商品渲染方法
  298. Controller.renderSelectedGoods(data, false);
  299. }
  300. }
  301. });
  302. });
  303. },
  304. edit: function () {
  305. Controller.api.bindevent();
  306. // 表单提交前处理
  307. $('#edit-form').on('submit', function(e) {
  308. console.log('=== 编辑表单提交验证开始 ===');
  309. // 验证是否选择了商品
  310. var goodsIds = $('#goods-ids').val();
  311. if (!goodsIds || goodsIds.trim() === '') {
  312. Layer.alert('请先选择参与活动的商品', {icon: 2});
  313. e.preventDefault();
  314. return false;
  315. }
  316. // 更新商品信息
  317. var goodsInfo = updateGoodsInfo();
  318. // 验证商品信息
  319. if (!goodsInfo || goodsInfo.length === 0) {
  320. Layer.alert('商品信息不能为空', {icon: 2});
  321. e.preventDefault();
  322. return false;
  323. }
  324. // 验证每个商品的折扣设置
  325. var hasError = false;
  326. var errorMsg = '';
  327. $.each(goodsInfo, function(index, item) {
  328. if (item.spec_type == 0) {
  329. // 单规格商品验证
  330. if (!item.discount || !item.discount_price || item.discount_stocks === undefined) {
  331. hasError = true;
  332. errorMsg = '商品"' + item.title + '"的折扣信息不完整';
  333. return false;
  334. }
  335. } else if (item.spec_type == 1) {
  336. // 多规格商品验证
  337. if (!item.spec || item.spec.length === 0) {
  338. hasError = true;
  339. errorMsg = '商品"' + item.title + '"请设置规格折扣';
  340. return false;
  341. }
  342. }
  343. });
  344. if (hasError) {
  345. Layer.alert(errorMsg, {icon: 2});
  346. e.preventDefault();
  347. return false;
  348. }
  349. console.log('=== 编辑表单验证通过,准备提交 ===');
  350. console.log('提交的商品ID:', $('#goods-ids').val());
  351. console.log('提交的商品信息:', $('#goods-info').val());
  352. return true;
  353. });
  354. // 初始化已选择的商品
  355. var goodsIds = $('#goods-ids').val();
  356. var goodsInfo = $('#goods-info').val() ? JSON.parse($('#goods-info').val()) : [];
  357. // 从goods_info构建折扣数据映射
  358. var discountData = {};
  359. if (goodsInfo && goodsInfo.length > 0) {
  360. $.each(goodsInfo, function(index, item) {
  361. if (item.goods_id) {
  362. discountData[item.goods_id] = {
  363. id: item.goods_id,
  364. sku_id: item.sku_id || 0,
  365. discount: item.discount || 9,
  366. discount_price: item.discount_price || '',
  367. stocks: item.discount_stocks || item.stock || 0
  368. };
  369. // 处理多规格商品
  370. if (item.spec && item.spec.length > 0) {
  371. var specs = {};
  372. var summary = {
  373. participate_count: 0,
  374. avg_discount: 0,
  375. total_stocks: 0
  376. };
  377. var totalDiscount = 0;
  378. $.each(item.spec, function(specIndex, spec) {
  379. specs[spec.sku_id] = {
  380. id: spec.sku_id,
  381. participate: true,
  382. discount: spec.discount,
  383. discount_price: spec.discount_price,
  384. stocks: spec.discount_stocks
  385. };
  386. summary.participate_count++;
  387. totalDiscount += parseFloat(spec.discount);
  388. summary.total_stocks += parseInt(spec.discount_stocks);
  389. });
  390. summary.avg_discount = summary.participate_count > 0 ?
  391. (totalDiscount / summary.participate_count).toFixed(1) : '0';
  392. discountData[item.goods_id].specs = specs;
  393. discountData[item.goods_id].summary = summary;
  394. }
  395. }
  396. });
  397. }
  398. console.log('编辑页面初始化:', {
  399. goodsIds: goodsIds,
  400. goodsInfo: goodsInfo,
  401. discountData: discountData
  402. });
  403. // 设置discount-data隐藏字段以便共享方法使用
  404. if (!$('#discount-data').length) {
  405. $('#goods-info').after('<input type="hidden" id="discount-data" value="">');
  406. }
  407. $('#discount-data').val(JSON.stringify(discountData));
  408. if(goodsIds) {
  409. console.log('开始加载商品数据,商品IDs:', goodsIds);
  410. // 检查是否有预设的goodsData(从服务器端传递)
  411. var goodsData = Controller.api.parseConfigJson('goodsData', []);
  412. if (goodsData && goodsData.length > 0) {
  413. console.log('使用服务器端预设的商品数据,数量:', goodsData.length);
  414. // 处理服务器端返回的活动折扣数据
  415. $.each(goodsData, function(index, goods) {
  416. // 处理SKU中的活动折扣数据
  417. if (goods.skus && goods.skus.length > 0) {
  418. $.each(goods.skus, function(skuIndex, sku) {
  419. // 如果SKU有活动折扣数据,构造discount_info
  420. if (sku.activity_discount !== undefined) {
  421. if (!goods.discount_info) {
  422. goods.discount_info = {
  423. goods_id: goods.id,
  424. spec_type: goods.spec_type
  425. };
  426. }
  427. if (goods.spec_type == 0) {
  428. // 单规格商品
  429. goods.discount_info.sku_id = sku.id;
  430. goods.discount_info.discount = sku.activity_discount;
  431. goods.discount_info.discount_price = sku.activity_discount_price;
  432. goods.discount_info.discount_stocks = sku.activity_stocks;
  433. } else if (goods.spec_type == 1) {
  434. // 多规格商品
  435. if (!goods.discount_info.spec) {
  436. goods.discount_info.spec = [];
  437. }
  438. goods.discount_info.spec.push({
  439. sku_id: sku.id,
  440. discount: sku.activity_discount,
  441. discount_price: sku.activity_discount_price,
  442. discount_stocks: sku.activity_stocks
  443. });
  444. }
  445. }
  446. });
  447. }
  448. // 处理多规格商品的已选择规格数据
  449. if (goods.spec_type == 1 && goods.selected_discount_data) {
  450. console.log('商品', goods.id, '已选择的规格折扣数据:', goods.selected_discount_data);
  451. // 如果没有discount_info,从selected_discount_data构建
  452. if (!goods.discount_info) {
  453. goods.discount_info = {
  454. goods_id: goods.id,
  455. spec_type: goods.spec_type,
  456. spec: goods.selected_discount_data.spec
  457. };
  458. }
  459. }
  460. });
  461. console.log('处理后的商品数据(包含活动折扣信息):', goodsData);
  462. // 使用共享的商品渲染方法,传入编辑模式标识
  463. Controller.renderSelectedGoods(goodsData, true);
  464. } else {
  465. // 如果没有预设数据,则通过AJAX加载
  466. console.log('没有预设数据,通过AJAX加载商品数据');
  467. $.ajax({
  468. url: Fast.api.fixurl('shop/goods/get_goods_by_ids'),
  469. type: 'POST',
  470. dataType: 'json',
  471. data: {ids: goodsIds},
  472. headers: {
  473. 'X-Requested-With': 'XMLHttpRequest'
  474. },
  475. success: function(ret, textStatus, jqXHR) {
  476. console.log('AJAX商品数据加载结果:', ret);
  477. // 根据实际返回的数据结构来处理
  478. var goodsData = [];
  479. // 情况1: 标准FastAdmin格式,数据在ret.data中
  480. if (ret && ret.code === 1 && ret.data && Array.isArray(ret.data)) {
  481. goodsData = ret.data;
  482. console.log('使用标准格式数据,数量:', goodsData.length);
  483. }
  484. // 情况2: 直接返回商品数组
  485. else if (Array.isArray(ret)) {
  486. goodsData = ret;
  487. console.log('使用直接数组数据,数量:', goodsData.length);
  488. }
  489. // 情况3: 如果ret.code不等于1,说明有错误
  490. else if (ret && ret.code !== undefined && ret.code !== 1) {
  491. console.error('接口返回错误:', ret.msg || '未知错误');
  492. Layer.msg(ret.msg || '加载商品数据失败', {icon: 2});
  493. return;
  494. }
  495. if(goodsData && goodsData.length > 0) {
  496. console.log('AJAX返回商品数据成功,商品数量:', goodsData.length);
  497. // 如果有goods_info数据,则合并折扣信息
  498. if (goodsInfo && goodsInfo.length > 0) {
  499. console.log('合并goods_info中的折扣数据');
  500. // 将goods_info中的折扣数据合并到接口返回的商品数据中
  501. $.each(goodsData, function(index, goods) {
  502. var matchedInfo = null;
  503. $.each(goodsInfo, function(infoIndex, info) {
  504. if (info.goods_id == goods.id) {
  505. matchedInfo = info;
  506. return false; // 跳出循环
  507. }
  508. });
  509. if (matchedInfo) {
  510. // 合并折扣信息到商品数据
  511. goods.discount_info = matchedInfo;
  512. console.log('商品', goods.id, '合并折扣信息:', matchedInfo);
  513. }
  514. });
  515. }
  516. // 使用共享的商品渲染方法,传入编辑模式标识
  517. Controller.renderSelectedGoods(goodsData, true);
  518. } else {
  519. console.warn('没有获取到商品数据或数据为空');
  520. }
  521. },
  522. error: function(jqXHR, textStatus, errorThrown) {
  523. console.error('加载商品数据失败:', {
  524. status: jqXHR.status,
  525. statusText: jqXHR.statusText,
  526. textStatus: textStatus,
  527. errorThrown: errorThrown
  528. });
  529. Layer.msg('加载商品数据失败', {icon: 2});
  530. }
  531. });
  532. }
  533. } else {
  534. console.log('没有商品IDs,跳过商品数据加载');
  535. }
  536. // 绑定选择商品按钮事件 - 使用共享方法
  537. $('#select-goods').off('click').on('click', function() {
  538. Fast.api.open('shop/goods/select', '选择商品', {
  539. area: ['95%', '90%'],
  540. callback: function(data) {
  541. if (data && data.length > 0) {
  542. Controller.renderSelectedGoods(data, true);
  543. }
  544. }
  545. });
  546. });
  547. },
  548. // 规格折扣设置页面
  549. spec_discount: function () {
  550. // 获取URL参数中的goods_id和spec_data
  551. var goodsId = Fast.api.query('goods_id');
  552. var specData = Fast.api.query('spec_data');
  553. // 设置批量折扣默认值,但不自动勾选
  554. $('#batch-participate').prop('checked', false);
  555. $('#batch-discount').val(9);
  556. // 更新批量价格信息
  557. Controller.api.updateBatchPriceInfo();
  558. // 如果有规格数据,则进行回显
  559. if (specData) {
  560. try {
  561. var data = JSON.parse(decodeURIComponent(specData));
  562. if (data && data.specs) {
  563. $.each(data.specs, function(id, item) {
  564. var $row = $('tr[data-id="' + id + '"]');
  565. if ($row.length > 0) {
  566. // 设置参与折扣
  567. if (item.participate) {
  568. // 勾选并确保输入框可编辑
  569. $row.find('.participate-checkbox').prop('checked', true);
  570. $row.find('.sku-stocks').prop('disabled', false);
  571. $row.find('.sku-discount').prop('disabled', false);
  572. // 设置折扣库存
  573. if (item.stocks !== undefined) {
  574. var maxStocks = parseInt($row.data('stocks')) || 0;
  575. var stocks = parseInt(item.stocks) || 0;
  576. // 确保回显的库存不超过现有库存
  577. if (stocks > maxStocks) {
  578. stocks = maxStocks;
  579. }
  580. $row.find('.sku-stocks').val(stocks);
  581. }
  582. // 设置折扣
  583. if (item.discount !== undefined) {
  584. $row.find('.sku-discount').val(item.discount);
  585. // 更新折后价显示
  586. var price = parseFloat($row.data('price')) || 0;
  587. var discount = parseFloat(item.discount) || 0;
  588. var discountPrice = (price * discount / 10).toFixed(2);
  589. $row.find('.discount-price').text('¥' + discountPrice);
  590. }
  591. } else {
  592. // 如果之前设置了不参与,则取消勾选
  593. $row.find('.participate-checkbox').prop('checked', false);
  594. $row.find('.sku-stocks').prop('disabled', true);
  595. $row.find('.sku-discount').prop('disabled', true);
  596. }
  597. }
  598. });
  599. // 检查已选规格数量,更新批量选择框状态
  600. var checkedCount = $('.participate-checkbox:checked').length;
  601. var totalCount = $('.participate-checkbox').length;
  602. if (checkedCount > 0 && checkedCount === totalCount) {
  603. // 如果所有规格都已选中,勾选批量选择框
  604. $('#batch-participate').prop('checked', true);
  605. } else if (checkedCount > 0) {
  606. // 部分选中,不勾选批量框但显示提示
  607. $('#batch-participate').prop('checked', false);
  608. } else {
  609. // 没有任何选中
  610. $('#batch-participate').prop('checked', false);
  611. }
  612. // 更新批量价格信息
  613. Controller.api.updateBatchPriceInfo();
  614. }
  615. } catch (e) {
  616. console.error('解析规格数据失败', e);
  617. }
  618. }
  619. // 参与折扣复选框事件,但勾选后可以直接编辑
  620. $('.participate-checkbox').off('change').on('change', function() {
  621. var checked = $(this).prop('checked');
  622. var $row = $(this).closest('tr');
  623. // 启用/禁用库存和折扣输入框
  624. var $stocksInput = $row.find('.sku-stocks');
  625. var $discountInput = $row.find('.sku-discount');
  626. $stocksInput.prop('disabled', !checked);
  627. $discountInput.prop('disabled', !checked);
  628. // 如果勾选,设置默认值
  629. if (checked) {
  630. // 获取库存默认值
  631. var stocks = $row.data('stocks') || 0;
  632. if (!$stocksInput.val()) {
  633. $stocksInput.val(stocks);
  634. } else if (parseInt($stocksInput.val()) > stocks) {
  635. // 如果当前值超过了最大库存,则调整为最大库存
  636. $stocksInput.val(stocks);
  637. }
  638. // 设置折扣默认值,如果未设置
  639. if (!$discountInput.val()) {
  640. $discountInput.val(9);
  641. }
  642. // 触发折扣输入框的input事件以更新折扣价格
  643. $discountInput.trigger('input');
  644. // 聚焦到折扣输入框方便用户直接修改
  645. setTimeout(function() {
  646. $discountInput.focus();
  647. }, 100);
  648. }
  649. });
  650. // 批量参与复选框事件
  651. $('#batch-participate').on('change', function() {
  652. var checked = $(this).prop('checked');
  653. // 同步所有规格的选中状态
  654. $('.participate-checkbox').prop('checked', checked).trigger('change');
  655. // 如果勾选了批量参与,则聚焦到批量折扣输入框
  656. if (checked) {
  657. setTimeout(function() {
  658. $('#batch-discount').focus();
  659. }, 100);
  660. }
  661. });
  662. // 批量折扣变化事件
  663. $('#batch-discount').on('input', function() {
  664. var discount = parseFloat($(this).val()) || 0;
  665. if (discount < 0.1) discount = 0.1;
  666. if (discount > 10) discount = 10;
  667. $(this).val(discount);
  668. // 更新批量价格信息
  669. Controller.api.updateBatchPriceInfo();
  670. });
  671. // 初始化批量价格信息
  672. Controller.api.updateBatchPriceInfo();
  673. // 应用批量设置按钮事件
  674. $('#apply-batch').on('click', function() {
  675. var discount = parseFloat($('#batch-discount').val()) || 9;
  676. // 如果没有选中规格,先勾选所有规格
  677. if ($('.participate-checkbox:checked').length === 0) {
  678. Layer.msg('请先勾选需要参与折扣的规格');
  679. return;
  680. }
  681. // 应用到所有已勾选的行
  682. $('.participate-checkbox:checked').each(function() {
  683. var $row = $(this).closest('tr');
  684. $row.find('.sku-discount').val(discount).trigger('input');
  685. });
  686. Layer.msg('批量设置折扣已应用');
  687. });
  688. // 折扣输入事件
  689. $('.sku-discount').off('input').on('input', function() {
  690. var discount = parseFloat($(this).val()) || 0;
  691. if(discount < 0.1) discount = 0.1;
  692. if(discount > 10) discount = 10;
  693. $(this).val(discount);
  694. var $row = $(this).closest('tr');
  695. var price = parseFloat($row.data('price')) || 0;
  696. var discountPrice = (price * discount / 10).toFixed(2);
  697. $row.find('.discount-price').text('¥' + discountPrice);
  698. });
  699. // 库存输入验证
  700. $('.sku-stocks').on('input', function() {
  701. var stocks = parseInt($(this).val()) || 0;
  702. var $row = $(this).closest('tr');
  703. var maxStocks = parseInt($row.data('stocks')) || 0;
  704. // 限制库存范围,不能超过现有库存
  705. if (stocks < 0) stocks = 0;
  706. if (stocks > maxStocks) stocks = maxStocks;
  707. $(this).val(stocks);
  708. });
  709. // 确认按钮事件
  710. $('.btn-confirm').on('click', function() {
  711. var specs = {};
  712. var hasParticipate = false;
  713. // 收集所有参与的规格数据
  714. $('.participate-checkbox:checked').each(function() {
  715. var $row = $(this).closest('tr');
  716. var id = $row.data('id');
  717. var price = parseFloat($row.data('price')) || 0;
  718. var discount = parseFloat($row.find('.sku-discount').val()) || 9;
  719. var stocks = parseInt($row.find('.sku-stocks').val()) || 0;
  720. var discountPrice = (price * discount / 10).toFixed(2);
  721. specs[id] = {
  722. id: id,
  723. participate: true,
  724. discount: discount,
  725. price: price,
  726. stocks: stocks,
  727. discount_price: discountPrice
  728. };
  729. hasParticipate = true;
  730. console.log('添加参与规格:', id, '折扣:', discount, '库存:', stocks);
  731. });
  732. // 验证是否有选择参与的规格
  733. if (!hasParticipate) {
  734. Layer.alert('请至少选择一个参与折扣的规格', {icon: 2});
  735. return;
  736. }
  737. // 计算平均折扣和参与规格数量
  738. var totalDiscount = 0;
  739. var count = 0;
  740. var totalStocks = 0;
  741. $.each(specs, function(id, item) {
  742. if (item.participate) {
  743. totalDiscount += parseFloat(item.discount);
  744. totalStocks += parseInt(item.stocks);
  745. count++;
  746. }
  747. });
  748. var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '-';
  749. // 添加汇总信息
  750. var summary = {
  751. participate_count: count,
  752. avg_discount: avgDiscount,
  753. total_stocks: totalStocks
  754. };
  755. var returnData = {
  756. goodsId: goodsId,
  757. specs: specs,
  758. summary: summary
  759. };
  760. console.log('多规格确认返回数据:', returnData);
  761. // 返回数据到add.html页面
  762. Fast.api.close(returnData);
  763. });
  764. },
  765. // 渲染已选择的商品表格 - 共享方法
  766. renderSelectedGoods: function(data, isEdit) {
  767. var defaultDiscount = 9;
  768. var existingDiscountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  769. // 如果是编辑模式且有现有数据,合并数据
  770. if (isEdit && Object.keys(existingDiscountData).length > 0) {
  771. console.log('编辑模式,使用现有折扣数据:', existingDiscountData);
  772. }
  773. console.log('renderSelectedGoods调用:', {
  774. dataLength: data ? data.length : 0,
  775. isEdit: isEdit,
  776. existingDataCount: Object.keys(existingDiscountData).length
  777. });
  778. // 收集商品ID
  779. var goodsIds = [];
  780. $.each(data, function(index, item) {
  781. goodsIds.push(item.id);
  782. });
  783. // 使用模板渲染表格
  784. var html = Template('goodsTableTpl', {
  785. list: data,
  786. discount: defaultDiscount
  787. });
  788. // 清空容器并显示表格
  789. $('#selected-goods-container').empty().append(html);
  790. // 初始化分页表格
  791. $('#selected-goods-table').bootstrapTable({
  792. data: data,
  793. pagination: true,
  794. pageSize: 5,
  795. pageList: [5, 10, 20],
  796. sortable: true,
  797. search: false,
  798. classes: 'table table-hover table-striped',
  799. onPostBody: function() {
  800. // 表格渲染完成后处理行属性
  801. $('#selected-goods-table tbody tr').each(function(index) {
  802. var rowData = data[index];
  803. if(rowData && rowData.id) {
  804. $(this).attr('data-id', rowData.id);
  805. console.log('设置行data-id属性:', rowData.id);
  806. }
  807. });
  808. },
  809. columns: [
  810. {
  811. field: 'goods',
  812. title: '商品',
  813. width: '30%',
  814. formatter: function(value, row) {
  815. return '<div class="goods-item">' +
  816. '<img src="' + Fast.api.cdnurl(row.image) + '" style="width:60px;height:60px;margin-right:10px;" class="pull-left img-thumbnail">' +
  817. '<div style="margin-left:70px;">' +
  818. '<h5 style="margin-top:0;font-weight:600;">' + row.title + '</h5>' +
  819. '<p class="text-muted">分类:' + (row.category ? row.category.name : '') + ' | 规格:' + (row.spec_type == 0 ? '单规格' : '多规格') + '</p>' +
  820. '</div>' +
  821. '</div>'
  822. }
  823. },
  824. {
  825. field: 'price',
  826. title: '价格',
  827. width: '10%',
  828. align: 'center',
  829. formatter: function(value, row) {
  830. return '<span class="text-danger">¥' + row.price + '</span>';
  831. }
  832. },
  833. {
  834. field: 'stocks',
  835. title: '现库存',
  836. width: '10%',
  837. align: 'center'
  838. },
  839. {
  840. field: 'discount_stocks',
  841. title: '折扣库存',
  842. width: '20%',
  843. align: 'center',
  844. formatter: function(value, row) {
  845. if(row.spec_type == 0) {
  846. // 从折扣数据中获取库存值,如果没有则使用商品库存
  847. var currentStocks = existingDiscountData[row.id] && existingDiscountData[row.id].stocks !== undefined ?
  848. existingDiscountData[row.id].stocks : parseInt(row.stocks);
  849. return '<input type="number" class="form-control discount-stocks-input" value="' + currentStocks + '" min="0" data-id="' + row.id + '" data-max-stocks="' + parseInt(row.stocks) + '" style="width:100%;">';
  850. } else {
  851. return '';
  852. }
  853. }
  854. },
  855. {
  856. field: 'discount',
  857. title: '折扣',
  858. width: '15%',
  859. align: 'center',
  860. formatter: function(value, row) {
  861. if(row.spec_type == 1) {
  862. // 检查是否有已保存的规格折扣数据
  863. var hasSpec = false;
  864. var specBtnText = '规格折扣设置';
  865. var summaryInfo = '';
  866. // 先检查合并的折扣信息
  867. if (row.discount_info && row.discount_info.spec && row.discount_info.spec.length > 0) {
  868. hasSpec = true;
  869. specBtnText = '规格折扣设置 <span class="label label-success">已设置</span>';
  870. // 计算汇总信息
  871. var totalDiscount = 0;
  872. var count = 0;
  873. var totalStocks = 0;
  874. $.each(row.discount_info.spec, function(index, spec) {
  875. totalDiscount += parseFloat(spec.discount || 0);
  876. totalStocks += parseInt(spec.discount_stocks || 0);
  877. count++;
  878. });
  879. var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '0';
  880. summaryInfo = '<div class="spec-discount-info text-muted" style="margin-top:5px;"><i class="fa fa-check-circle text-success"></i> 已设置' + count + '个规格,平均' + avgDiscount + '折,共' + totalStocks + '件</div>';
  881. }
  882. // 再检查existingDiscountData
  883. else if (existingDiscountData[row.id] && existingDiscountData[row.id].specs) {
  884. hasSpec = true;
  885. specBtnText = '规格折扣设置 <span class="label label-success">已设置</span>';
  886. if (existingDiscountData[row.id].summary) {
  887. var summary = existingDiscountData[row.id].summary;
  888. summaryInfo = '<div class="spec-discount-info text-muted" style="margin-top:5px;"><i class="fa fa-check-circle text-success"></i> 已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件</div>';
  889. }
  890. }
  891. var html = '<div class="text-center">' +
  892. '<a href="javascript:;" class="btn btn-info btn-sm btn-spec-discount" data-id="' + row.id + '">' + specBtnText + '</a>';
  893. // 根据是否已设置显示不同的提示语
  894. if (hasSpec) {
  895. html += '<div class="text-muted small" style="margin-top:8px;">点击可重新设置各规格折扣</div>';
  896. } else {
  897. html += '<div class="text-muted small" style="margin-top:8px;">请点击设置各规格折扣</div>';
  898. }
  899. html += summaryInfo + '</div>';
  900. return html;
  901. } else {
  902. var discount = (existingDiscountData[row.id] && existingDiscountData[row.id].discount) ? existingDiscountData[row.id].discount : defaultDiscount;
  903. return '<div class="input-group">' +
  904. '<input type="number" class="form-control discount-input" value="' + discount + '" min="0.1" max="10" step="0.1" data-price="' + row.price + '" data-id="' + row.id + '">' +
  905. '<span class="input-group-addon">折</span>' +
  906. '</div>';
  907. }
  908. }
  909. },
  910. {
  911. field: 'discount_price',
  912. title: '折后价',
  913. width: '20%',
  914. align: 'center',
  915. formatter: function(value, row) {
  916. if(row.spec_type == 0) {
  917. var discount = (existingDiscountData[row.id] && existingDiscountData[row.id].discount) ? existingDiscountData[row.id].discount : defaultDiscount;
  918. var discountPrice = (row.price * discount / 10).toFixed(2);
  919. return '<span class="discount-price text-success" id="discount-price-' + row.id + '">¥' + discountPrice + '</span>';
  920. } else {
  921. return '';
  922. }
  923. }
  924. },
  925. {
  926. field: 'operate',
  927. title: '操作',
  928. width: '15%',
  929. align: 'center',
  930. formatter: function(value, row) {
  931. return '<a href="javascript:;" class="btn btn-xs btn-danger remove-goods" data-id="' + row.id + '"><i class="fa fa-trash"></i> 删除</a>';
  932. },
  933. events: {
  934. 'click .remove-goods': function (e, value, row, index) {
  935. // 从表格中移除该行
  936. $('#selected-goods-table').bootstrapTable('remove', {
  937. field: 'id',
  938. values: [row.id]
  939. });
  940. // 更新隐藏字段
  941. var currentIds = $('#goods-ids').val().split(',');
  942. var newIds = [];
  943. $.each(currentIds, function(i, val) {
  944. if (val != row.id && val) {
  945. newIds.push(val);
  946. }
  947. });
  948. $('#goods-ids').val(newIds.join(','));
  949. // 移除折扣数据
  950. var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  951. if(discountData[row.id]) {
  952. delete discountData[row.id];
  953. $('#discount-data').val(JSON.stringify(discountData));
  954. }
  955. // 如果表格为空,则移除整个表格
  956. if(newIds.length === 0) {
  957. $('#selected-goods-container').empty();
  958. }
  959. updateGoodsInfo();
  960. }
  961. }
  962. }
  963. ]
  964. });
  965. // 更新隐藏字段
  966. $('#goods-ids').val(goodsIds.join(','));
  967. // 初始化折扣数据
  968. var discountData = existingDiscountData;
  969. $.each(data, function(index, item) {
  970. // 检查是否有合并的折扣信息
  971. var hasDiscountInfo = item.discount_info;
  972. // 检查是否有服务器端的已选择规格数据
  973. var hasSelectedData = item.selected_discount_data;
  974. if (item.spec_type == 0) {
  975. if (hasDiscountInfo) {
  976. // 使用合并的折扣信息
  977. discountData[item.id] = {
  978. id: item.id,
  979. sku_id: hasDiscountInfo.sku_id || 0,
  980. discount: hasDiscountInfo.discount || defaultDiscount,
  981. discount_price: hasDiscountInfo.discount_price || (item.price * defaultDiscount / 10).toFixed(2),
  982. stocks: hasDiscountInfo.discount_stocks || parseInt(item.stocks) || 0
  983. };
  984. console.log('使用已保存的单规格商品折扣信息:', item.id, discountData[item.id]);
  985. } else if (!discountData[item.id]) {
  986. // 单规格商品,只有在没有现有数据时才初始化
  987. var currentStocks = parseInt(item.stocks) || 0;
  988. var skuId = item.sku_id || 0;
  989. discountData[item.id] = {
  990. id: item.id,
  991. sku_id: skuId,
  992. discount: defaultDiscount,
  993. discount_price: (item.price * defaultDiscount / 10).toFixed(2),
  994. stocks: currentStocks
  995. };
  996. console.log('初始化单规格商品:', item.id, 'SKU ID:', skuId, '库存:', currentStocks);
  997. }
  998. } else if (item.spec_type == 1) {
  999. // 多规格商品处理
  1000. if (hasSelectedData) {
  1001. // 优先使用服务器端的已选择数据
  1002. var specs = {};
  1003. $.each(hasSelectedData.spec, function(specIndex, spec) {
  1004. specs[spec.sku_id] = {
  1005. id: spec.sku_id,
  1006. participate: true,
  1007. discount: spec.discount,
  1008. discount_price: spec.discount_price,
  1009. stocks: spec.discount_stocks
  1010. };
  1011. });
  1012. discountData[item.id] = {
  1013. id: item.id,
  1014. specs: specs,
  1015. summary: hasSelectedData.summary
  1016. };
  1017. console.log('使用服务器端已选择的多规格商品数据:', item.id, discountData[item.id]);
  1018. } else if (hasDiscountInfo && hasDiscountInfo.spec) {
  1019. // 使用合并的折扣信息
  1020. var specs = {};
  1021. var summary = {
  1022. participate_count: 0,
  1023. avg_discount: 0,
  1024. total_stocks: 0
  1025. };
  1026. var totalDiscount = 0;
  1027. $.each(hasDiscountInfo.spec, function(specIndex, spec) {
  1028. specs[spec.sku_id] = {
  1029. id: spec.sku_id,
  1030. participate: true,
  1031. discount: spec.discount,
  1032. discount_price: spec.discount_price,
  1033. stocks: spec.discount_stocks
  1034. };
  1035. summary.participate_count++;
  1036. totalDiscount += parseFloat(spec.discount);
  1037. summary.total_stocks += parseInt(spec.discount_stocks);
  1038. });
  1039. summary.avg_discount = summary.participate_count > 0 ?
  1040. (totalDiscount / summary.participate_count).toFixed(1) : '0';
  1041. discountData[item.id] = {
  1042. id: item.id,
  1043. specs: specs,
  1044. summary: summary
  1045. };
  1046. console.log('使用已保存的多规格商品折扣信息:', item.id, discountData[item.id]);
  1047. }
  1048. }
  1049. });
  1050. // 确保discount-data字段存在(兼容性)
  1051. if (!$('#discount-data').length) {
  1052. $('#goods-info').after('<input type="hidden" id="discount-data" value="">');
  1053. }
  1054. $('#discount-data').val(JSON.stringify(discountData));
  1055. // 延迟处理事件绑定和数据回显
  1056. setTimeout(function() {
  1057. // 处理多规格商品的数据回显
  1058. $('#selected-goods-table tbody tr').each(function() {
  1059. var $row = $(this);
  1060. var goodsId = $row.data('id');
  1061. console.log('检查商品行:', goodsId, '折扣数据:', discountData[goodsId]);
  1062. if (goodsId && discountData[goodsId]) {
  1063. // 检查是否是多规格商品且有规格数据
  1064. if (discountData[goodsId].specs || discountData[goodsId].spec) {
  1065. console.log('回显多规格商品数据:', goodsId, discountData[goodsId]);
  1066. // 设置多规格商品的数据属性
  1067. $row.attr('data-has-discount-setting', 'true');
  1068. $row.attr('data-discount-data', JSON.stringify(discountData[goodsId]));
  1069. // 更新按钮显示为"已设置"状态
  1070. var $btn = $row.find('.btn-spec-discount');
  1071. if ($btn.length > 0) {
  1072. $btn.html('规格折扣设置 <span class="label label-success">已设置</span>');
  1073. // 显示汇总信息
  1074. var summary = discountData[goodsId].summary;
  1075. if (summary) {
  1076. var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
  1077. // 检查是否已有汇总信息区域
  1078. var $infoArea = $row.find('.spec-discount-info');
  1079. if ($infoArea.length > 0) {
  1080. $infoArea.html(infoText);
  1081. } else {
  1082. $btn.parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
  1083. }
  1084. } else {
  1085. // 如果没有summary,计算一个
  1086. var specs = discountData[goodsId].specs || discountData[goodsId].spec || [];
  1087. if (Array.isArray(specs) && specs.length > 0) {
  1088. var totalDiscount = 0;
  1089. var totalStocks = 0;
  1090. var count = specs.length;
  1091. $.each(specs, function(i, spec) {
  1092. totalDiscount += parseFloat(spec.discount || 0);
  1093. totalStocks += parseInt(spec.discount_stocks || spec.stocks || 0);
  1094. });
  1095. var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '0';
  1096. var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + count + '个规格,平均' + avgDiscount + '折,共' + totalStocks + '件';
  1097. var $infoArea = $row.find('.spec-discount-info');
  1098. if ($infoArea.length > 0) {
  1099. $infoArea.html(infoText);
  1100. } else {
  1101. $btn.parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
  1102. }
  1103. }
  1104. }
  1105. }
  1106. }
  1107. }
  1108. });
  1109. // 绑定事件处理器
  1110. Controller.bindGoodsEvents();
  1111. // 同步更新商品详情信息
  1112. updateGoodsInfo();
  1113. }, 300);
  1114. },
  1115. // 绑定商品相关事件处理器
  1116. bindGoodsEvents: function() {
  1117. // 绑定折扣库存输入事件
  1118. $(document).off('input', '.discount-stocks-input').on('input', '.discount-stocks-input', function() {
  1119. var stocks = parseInt($(this).val()) || 0;
  1120. var goodsId = $(this).data('id');
  1121. var maxStocks = parseInt($(this).data('max-stocks')) || 0;
  1122. console.log('折扣库存输入事件:', goodsId, '输入值:', stocks, '最大值:', maxStocks);
  1123. // 限制输入范围,确保不超过现库存
  1124. if(stocks < 0) stocks = 0;
  1125. if(stocks > maxStocks) stocks = maxStocks;
  1126. $(this).val(stocks);
  1127. // 更新商品折扣数据
  1128. var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  1129. if(discountData[goodsId]) {
  1130. discountData[goodsId].stocks = stocks;
  1131. } else {
  1132. discountData[goodsId] = {
  1133. id: goodsId,
  1134. sku_id: 0,
  1135. stocks: stocks
  1136. };
  1137. }
  1138. $('#discount-data').val(JSON.stringify(discountData));
  1139. updateGoodsInfo();
  1140. });
  1141. // 绑定折扣输入事件
  1142. $(document).off('input', '.discount-input').on('input', '.discount-input', function() {
  1143. var discount = parseFloat($(this).val()) || 0;
  1144. if(discount < 0.1) discount = 0.1;
  1145. if(discount > 10) discount = 10;
  1146. var price = parseFloat($(this).data('price')) || 0;
  1147. var goodsId = $(this).data('id');
  1148. var discountPrice = (price * discount / 10).toFixed(2);
  1149. $('#discount-price-' + goodsId).text('¥' + discountPrice);
  1150. // 更新商品折扣数据
  1151. var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  1152. // 保留已有的数据结构
  1153. if (!discountData[goodsId]) {
  1154. discountData[goodsId] = {
  1155. id: goodsId,
  1156. sku_id: 0
  1157. };
  1158. }
  1159. discountData[goodsId].discount = discount;
  1160. discountData[goodsId].discount_price = discountPrice;
  1161. $('#discount-data').val(JSON.stringify(discountData));
  1162. updateGoodsInfo();
  1163. });
  1164. // 处理规格设置按钮点击事件
  1165. $(document).off('click', '.btn-spec-discount').on('click', '.btn-spec-discount', function() {
  1166. var goodsId = $(this).data('id');
  1167. var $row = $(this).closest('tr');
  1168. var hasDiscountSetting = $row.attr('data-has-discount-setting');
  1169. var specData = '';
  1170. console.log('点击规格折扣设置按钮:', goodsId, '当前设置状态:', hasDiscountSetting);
  1171. // 如果已经有设置,则传递已有的数据
  1172. if (hasDiscountSetting && $row.attr('data-discount-data')) {
  1173. specData = encodeURIComponent($row.attr('data-discount-data'));
  1174. console.log('已有折扣数据:', $row.attr('data-discount-data'));
  1175. }
  1176. Fast.api.open('marketing/discount/spec_discount?goods_id=' + goodsId + '&spec_data=' + specData, '规格折扣设置', {
  1177. area: ['90%', '90%'],
  1178. callback: function(data) {
  1179. if (data && data.goodsId && data.specs) {
  1180. console.log('规格折扣设置返回数据:', data);
  1181. // 保存数据到行属性
  1182. $row.attr('data-has-discount-setting', 'true');
  1183. $row.attr('data-discount-data', JSON.stringify(data));
  1184. // 更新按钮文字
  1185. $row.find('.btn-spec-discount').html('规格折扣设置 <span class="label label-success">已设置</span>');
  1186. // 计算并显示汇总信息
  1187. var totalDiscount = 0;
  1188. var count = 0;
  1189. var totalStocks = 0;
  1190. $.each(data.specs, function(id, item) {
  1191. if (item.participate) {
  1192. totalDiscount += parseFloat(item.discount);
  1193. totalStocks += parseInt(item.stocks);
  1194. count++;
  1195. }
  1196. });
  1197. var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '-';
  1198. var summary = {
  1199. participate_count: count,
  1200. avg_discount: avgDiscount,
  1201. total_stocks: totalStocks
  1202. };
  1203. var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
  1204. var $infoArea = $row.find('.spec-discount-info');
  1205. if ($infoArea.length > 0) {
  1206. $infoArea.html(infoText);
  1207. } else {
  1208. $row.find('.btn-spec-discount').parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
  1209. }
  1210. data.summary = summary;
  1211. // 将折扣数据保存到隐藏字段
  1212. var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  1213. discountData[goodsId] = data;
  1214. $('#discount-data').val(JSON.stringify(discountData));
  1215. updateGoodsInfo();
  1216. console.log('多规格商品设置后的折扣数据:', $('#discount-data').val());
  1217. }
  1218. }
  1219. });
  1220. });
  1221. },
  1222. api: {
  1223. // 解析Config中的JSON字符串的辅助函数
  1224. parseConfigJson: function(configKey, defaultValue) {
  1225. var configValue = Config[configKey] || defaultValue || {};
  1226. // 如果是字符串,尝试解析JSON
  1227. if (typeof configValue === 'string') {
  1228. try {
  1229. return JSON.parse(configValue);
  1230. } catch (e) {
  1231. return defaultValue || {};
  1232. }
  1233. }
  1234. return configValue;
  1235. },
  1236. bindevent: function () {
  1237. Form.api.bindevent($("form[role=form]"));
  1238. // 处理活动类型选择
  1239. $('select[name="row[type]"]').on('change', function() {
  1240. var type = $(this).val();
  1241. // 根据类型显示或隐藏内部类型选择
  1242. if (type == 'discount') {
  1243. // 折扣活动隐藏内部类型选择,默认为0
  1244. $('#inner-type-group').hide();
  1245. $('#c-inner-type').val(0);
  1246. // 折扣活动隐藏商品参与方式,强制为指定商品
  1247. $('.goods-join-type-group').hide();
  1248. $('input[name="row[goods_join_type]"][value="2"]').prop('checked', true);
  1249. } else {
  1250. // 其他活动类型显示相关选项
  1251. $('#inner-type-group').show();
  1252. $('.goods-join-type-group').show();
  1253. }
  1254. }).trigger('change'); // 页面加载时立即触发一次
  1255. // 活动名称字数限制处理
  1256. var nameInput = $("#c-name");
  1257. var countElement = $("#name-count");
  1258. // 初始化显示
  1259. countElement.text(nameInput.val().length + "/20");
  1260. // 监听输入事件
  1261. nameInput.on("input propertychange", function() {
  1262. var text = $(this).val();
  1263. var len = text.length;
  1264. // 更新显示的字数
  1265. countElement.text(len + "/20");
  1266. // 限制最多输入20个字符
  1267. if (len > 20) {
  1268. $(this).val(text.substring(0, 20));
  1269. countElement.text("20/20");
  1270. }
  1271. });
  1272. // 限购选项处理
  1273. $('input[name="row[purchase_limit_type]"]').on('change', function() {
  1274. var type = $(this).val();
  1275. // 禁用所有输入框
  1276. $('input[name="row[purchase_limit_total]"]').prop('disabled', true);
  1277. $('input[name="row[purchase_limit_daily]"]').prop('disabled', true);
  1278. // 根据选择启用对应输入框
  1279. if(type == '1') {
  1280. $('input[name="row[purchase_limit_total]"]').prop('disabled', false).focus();
  1281. } else if(type == '2') {
  1282. $('input[name="row[purchase_limit_daily]"]').prop('disabled', false).focus();
  1283. }
  1284. });
  1285. },
  1286. // 更新批量价格信息
  1287. updateBatchPriceInfo: function() {
  1288. var discount = parseFloat($('#batch-discount').val()) || 0;
  1289. var totalPrice = 0;
  1290. var totalCount = 0;
  1291. $('tr[data-price]').each(function() {
  1292. var price = parseFloat($(this).data('price')) || 0;
  1293. totalPrice += price;
  1294. totalCount++;
  1295. });
  1296. var avgPrice = totalCount > 0 ? totalPrice / totalCount : 0;
  1297. var discountPrice = (avgPrice * discount / 10).toFixed(2);
  1298. $('.batch-price-info').text('平均折后价:¥' + discountPrice);
  1299. }
  1300. }
  1301. };
  1302. // 更新商品详细信息到goods_info隐藏域
  1303. function updateGoodsInfo() {
  1304. console.log('=== 开始更新商品信息 ===');
  1305. // 获取表格中的所有商品数据
  1306. var goodsInfo = [];
  1307. var goodsIds = [];
  1308. var table = $('#selected-goods-table').bootstrapTable('getData');
  1309. if (!table || table.length === 0) {
  1310. console.log('表格为空,清空隐藏字段');
  1311. $('#goods-info').val('[]');
  1312. $('#goods-ids').val('');
  1313. return [];
  1314. }
  1315. console.log('表格商品数据:', table);
  1316. // 获取当前所有折扣数据
  1317. var discountData = $('#discount-data').val() ? JSON.parse($('#discount-data').val()) : {};
  1318. console.log('当前折扣数据:', discountData);
  1319. // 处理表格中的每个商品
  1320. $.each(table, function(index, item) {
  1321. var goodsId = item.id;
  1322. goodsIds.push(goodsId);
  1323. console.log('--- 处理商品:', goodsId, '规格类型:', item.spec_type);
  1324. // 基础商品信息
  1325. var goodsData = {
  1326. goods_id: goodsId,
  1327. title: item.title,
  1328. stock: parseInt(item.stocks) || 0,
  1329. spec_type: parseInt(item.spec_type) || 0
  1330. };
  1331. // 根据规格类型处理折扣信息
  1332. if (item.spec_type == 0) {
  1333. // 单规格商品处理
  1334. console.log('处理单规格商品:', goodsId);
  1335. // 从表格输入框获取当前值
  1336. var $row = $('#selected-goods-table tbody tr[data-id="' + goodsId + '"]');
  1337. var discount = parseFloat($row.find('.discount-input').val()) || 9;
  1338. var discountStocks = parseInt($row.find('.discount-stocks-input').val()) || 0;
  1339. var discountPrice = (item.price * discount / 10).toFixed(2);
  1340. // 获取SKU ID
  1341. var skuId = 0;
  1342. if (discountData[goodsId] && discountData[goodsId].sku_id) {
  1343. skuId = discountData[goodsId].sku_id;
  1344. } else if (item.sku_id) {
  1345. skuId = item.sku_id;
  1346. }
  1347. goodsData.sku_id = skuId;
  1348. goodsData.discount = discount;
  1349. goodsData.discount_price = discountPrice;
  1350. goodsData.discount_stocks = discountStocks;
  1351. console.log('单规格商品数据:', goodsData);
  1352. } else if (item.spec_type == 1) {
  1353. // 多规格商品处理
  1354. console.log('处理多规格商品:', goodsId);
  1355. var spec = [];
  1356. // 检查是否有规格折扣设置
  1357. if (discountData[goodsId] && discountData[goodsId].specs) {
  1358. var specData = discountData[goodsId].specs;
  1359. console.log('找到规格数据:', specData);
  1360. // 提取已选中参与折扣的规格
  1361. $.each(specData, function(skuId, specItem) {
  1362. if (specItem && specItem.participate === true) {
  1363. spec.push({
  1364. sku_id: skuId,
  1365. discount: parseFloat(specItem.discount) || 9,
  1366. discount_price: parseFloat(specItem.discount_price).toFixed(2) || "0.00",
  1367. discount_stocks: parseInt(specItem.stocks) || 0
  1368. });
  1369. console.log('添加规格:', skuId, specItem);
  1370. }
  1371. });
  1372. } else {
  1373. console.log('未找到多规格商品的规格设置数据');
  1374. }
  1375. goodsData.spec = spec;
  1376. console.log('多规格商品最终数据:', goodsData);
  1377. }
  1378. goodsInfo.push(goodsData);
  1379. });
  1380. // 更新隐藏字段
  1381. var goodsInfoJson = JSON.stringify(goodsInfo);
  1382. var goodsIdsStr = goodsIds.join(',');
  1383. $('#goods-info').val(goodsInfoJson);
  1384. $('#goods-ids').val(goodsIdsStr);
  1385. console.log('=== 更新完成 ===');
  1386. console.log('最终 goods_info:', goodsInfoJson);
  1387. console.log('最终 goods_ids:', goodsIdsStr);
  1388. return goodsInfo;
  1389. }
  1390. return Controller;
  1391. });