edit.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. <style>
  2. .header {
  3. padding: 18px 20px;
  4. background: #fff;
  5. margin-bottom: 10px;
  6. border-radius: 5px;
  7. border: 1px solid #EBEEF5;
  8. }
  9. .el-button--success {
  10. background-color: #67c23a;
  11. border-color: #67c23a;
  12. }
  13. .header .el-button {
  14. padding: 6px 26px;
  15. }
  16. .main {
  17. background: #ffffff;
  18. }
  19. .el-button--success:hover {
  20. background: #85ce61;
  21. border-color: #85ce61;
  22. }
  23. .coupon_type_list_expired {
  24. width: 100px;
  25. position: absolute;
  26. top: 50%;
  27. left: 50%;
  28. transform: translate(-50%, -50%);
  29. opacity: 0.2;
  30. zoom: 1.05;
  31. }
  32. .el-card {
  33. box-shadow: none !important;
  34. }
  35. .el-form-item {
  36. margin-bottom: 0;
  37. }
  38. .el-divider--horizontal {
  39. margin: 20px 0;
  40. }
  41. .sky .el-input__inner {
  42. height: 34px;
  43. }
  44. .line {
  45. background: #03C5FF;
  46. width: 5px;
  47. height: 20px;
  48. margin-right: 6px;
  49. }
  50. .rule_name .el-form-item__label {
  51. color: #333333;
  52. font-size: 14px;
  53. font-weight: 600;
  54. }
  55. .start {
  56. color: #EF1818;
  57. font-size: 14px;
  58. /*font-weight: 600;*/
  59. margin-right: 4px;
  60. }
  61. .type_text {
  62. font-size: 14px;
  63. font-weight: 600;
  64. color: #333;
  65. margin-right: 20px;
  66. }
  67. .detail_top {
  68. flex-wrap: wrap;
  69. }
  70. .detail_box {
  71. margin-top: 10px;
  72. }
  73. .coupon_box {
  74. /*width: 600px;*/
  75. margin-right: 50px;
  76. }
  77. .detail_top .coupon_box:last-child {
  78. margin-right: 0px;
  79. }
  80. .coupon_list_box {
  81. padding: 20px 20px 0 0;
  82. flex-wrap: wrap;
  83. box-sizing: border-box;
  84. overflow: hidden;
  85. /*height: 125px;*/
  86. }
  87. .coupon_list_box_active {
  88. height: auto;
  89. }
  90. .coupon_list_item {
  91. background: #F4F4F4;
  92. width: 275px;
  93. border-radius: 5px;
  94. position: relative;
  95. margin: 0 15px 15px 0;
  96. padding: 10px;
  97. }
  98. .add_coupon .el-button {
  99. padding: 6px 18px;
  100. margin: 20px 0;
  101. }
  102. .close_icon {
  103. font-size: 20px;
  104. font-weight: 700;
  105. position: absolute;
  106. right: 10px;
  107. top: 8px;
  108. cursor: pointer;
  109. }
  110. .coupon_list_title {
  111. font-size: 16px;
  112. margin-bottom: 10px;
  113. width: 220px;
  114. }
  115. .coupon_list_content {
  116. margin-bottom: 5px;
  117. font-size: 12px;
  118. }
  119. .more_btn {
  120. text-align: center;
  121. cursor: pointer;
  122. margin-top: 20px;
  123. }
  124. .more_icon {
  125. transform: rotate(0deg);
  126. transition: all 0.7s;
  127. }
  128. .show_more_icon {
  129. transform: rotate(180deg);
  130. }
  131. .show {
  132. height: auto;
  133. }
  134. .hide {
  135. height: 0;
  136. overflow: hidden;
  137. }
  138. .transform-hide {
  139. opacity: 0;
  140. -webkit-transform: translateY(-50%);
  141. transform: translateY(-50%);
  142. -webkit-transition: .3s;
  143. transition: .3s;
  144. }
  145. .transform-show {
  146. opacity: 1 !important;
  147. -webkit-transform: translateY(0) !important;
  148. transform: translateY(0) !important;
  149. }
  150. .is_divider {
  151. display: block;
  152. }
  153. @media screen and (min-width: 1540px) {
  154. .is_divider {
  155. display: none;
  156. }
  157. }
  158. .red_envelope_box {
  159. width: 600px;
  160. margin-right: 50px;
  161. }
  162. .red_envelope_box:last-child {
  163. margin-right: 0px;
  164. }
  165. .red_envelope_box .el-input {
  166. width: 150px;
  167. }
  168. .red_envelope_box .el-textarea {
  169. width: 250px;
  170. }
  171. .el-input {
  172. flex: 1;
  173. }
  174. .el-textarea {
  175. flex: 1;
  176. }
  177. .types_box {
  178. padding: 20px 20px 30px;
  179. }
  180. .label_title {
  181. font-weight: 600;
  182. margin-bottom: 8px;
  183. font-size: 16px;
  184. }
  185. .checkt_select {
  186. width: 140px;
  187. }
  188. .check_input {
  189. width: 200px;
  190. margin-left: 10px;
  191. }
  192. .check_btn_list .el-button {
  193. padding: 6px 14px;
  194. margin-bottom: 20px;
  195. }
  196. .el-dialog__footer {
  197. text-align: center;
  198. }
  199. .check_pagination {
  200. justify-content: flex-end;
  201. margin-top: 20px;
  202. }
  203. .level-box {
  204. margin-bottom: 20px;
  205. padding-left: 20px;
  206. overflow-y: auto;
  207. }
  208. .level-item {
  209. font-weight: 600;
  210. margin-right: 30px;
  211. cursor: pointer;
  212. }
  213. .level_item_active {
  214. color: #03C5FF;
  215. }
  216. /* 谷歌 */
  217. input::-webkit-outer-spin-button,
  218. input::-webkit-inner-spin-button {
  219. -webkit-appearance: none;
  220. appearance: none;
  221. margin: 0;
  222. }
  223. /* 火狐 */
  224. input {
  225. -moz-appearance: textfield;
  226. }
  227. /* 公共样式 */
  228. .flex {
  229. display: -webkit-box;
  230. display: -webkit-flex;
  231. /* #ifndef APP-NVUE */
  232. display: flex;
  233. /* #endif */
  234. }
  235. .flex-x-center {
  236. display: -webkit-box;
  237. display: -webkit-flex;
  238. /* #ifndef APP-NVUE */
  239. display: flex;
  240. /* #endif */
  241. -webkit-box-pack: center;
  242. -webkit-justify-content: center;
  243. -ms-flex-pack: center;
  244. justify-content: center;
  245. }
  246. .flex-x-between {
  247. display: -webkit-box;
  248. display: -webkit-flex;
  249. /* #ifndef APP-NVUE */
  250. display: flex;
  251. /* #endif */
  252. -webkit-box-pack: space-between;
  253. -webkit-justify-content: space-between;
  254. -ms-flex-pack: space-between;
  255. justify-content: space-between;
  256. }
  257. .flex-y-center {
  258. display: -webkit-box;
  259. display: -webkit-flex;
  260. /* #ifndef APP-NVUE */
  261. display: flex;
  262. /* #endif */
  263. -webkit-box-align: center;
  264. -webkit-align-items: center;
  265. -ms-flex-align: center;
  266. -ms-grid-row-align: center;
  267. align-items: center;
  268. }
  269. /* 溢出隐藏 */
  270. .over1 {
  271. text-overflow: -o-ellipsis-lastline;
  272. overflow: hidden;
  273. text-overflow: ellipsis;
  274. display: -webkit-box;
  275. -webkit-line-clamp: 1;
  276. -webkit-box-orient: vertical;
  277. }
  278. .over2 {
  279. text-overflow: -o-ellipsis-lastline;
  280. overflow: hidden;
  281. text-overflow: ellipsis;
  282. display: -webkit-box;
  283. -webkit-line-clamp: 2;
  284. -webkit-box-orient: vertical;
  285. }
  286. </style>
  287. <?php
  288. use common\helpers\ComponentHelper;
  289. use common\helpers\AddonHelper;
  290. if ($has_coupon) {
  291. ComponentHelper::loadComponentView('coupon-select', AddonHelper::getAddonRootPath('Coupon') . 'backend/views/components');
  292. }
  293. ComponentHelper::loadComponentView('com-dialog-select');
  294. ?>
  295. <div id="app">
  296. <div class="header flex flex-x-between flex-y-center">
  297. <div>发放规则</div>
  298. <div>
  299. <el-button type="primary" @click="submit('ruleForm')">保存</el-button>
  300. </div>
  301. </div>
  302. <el-card v-loading='loading'>
  303. <el-form ref="ruleForm" :rules="rules" label-position='center' :model="ruleForm" label-width="auto">
  304. <div class="flex flex-y-center">
  305. <div class="type_text flex flex-x-between flex-y-center">
  306. <div>{{ gift_type_name }}</div>
  307. </div>
  308. </div>
  309. <el-divider></el-divider>
  310. <div class="flex flex-y-center">
  311. <div class="line"></div>
  312. <div class="start">*</div>
  313. <div class="flex flex-x-between flex-y-center">
  314. <div>状态</div>
  315. </div>
  316. </div>
  317. <div style="padding: 20px 0;">
  318. <el-radio v-model="ruleForm.status" :label="1">启用</el-radio>
  319. <el-radio v-model="ruleForm.status" :label="0">禁用</el-radio>
  320. </div>
  321. <el-divider></el-divider>
  322. <div class="flex flex-y-center">
  323. <div class="line"></div>
  324. <div class="start">*</div>
  325. <div class="flex flex-x-between flex-y-center">
  326. <div>选择{{ level_name }}等级</div>
  327. </div>
  328. </div>
  329. <!-- 等级tabs -->
  330. <el-tabs v-model="activeName" style="margin-top: 20px;" type="card" @tab-click="handleClick">
  331. <el-tab-pane v-for="(name,level) in level_arr" :label="name" :key="name">
  332. <div class="detail_box">
  333. <div class="detail_top">
  334. <div class="flex flex-y-center" style="flex-wrap: wrap;" v-for="(title,type) in setting_type_arr">
  335. <!-- 优惠券特殊处理start -->
  336. <div class="coupon_box" v-if="type == 'coupon'">
  337. <div v-if="has_coupon">
  338. <div class="coupon_title flex flex-y-center">
  339. <div class="line"></div>
  340. <div style="margin-right: 6px;">{{ title }}</div>
  341. <el-tooltip class="item" effect="dark" content="所发优惠券不记入优惠券库存中" placement="right">
  342. <div class="el-icon-warning" style="margin-top: 2px;"></div>
  343. </el-tooltip>
  344. </div>
  345. <div class="add_coupon">
  346. <el-button type="primary" @click='handle("coupon_select",ruleForm.setting[type][level].arr, {gift_type:type,level_index:level})'>选择优惠券</el-button>
  347. </div>
  348. <div class="coupon_title flex flex-y-center">
  349. <div style="margin-right: 6px;">{{ title }}明细</div>
  350. </div>
  351. <div class="coupon_list_box flex-x-between flex" v-if="ruleForm.setting[type][level].arr" :class="{coupon_list_box_active:is_coupon_more}">
  352. <div class="coupon_list_item" v-for="(item,index) in ruleForm.setting[type][level].arr" :key='index'>
  353. <div class="coupon_list_title over1">{{item.name}}</div>
  354. <div class="coupon_list_content">优惠方式:{{item.discount_method}}</div>
  355. <div class="coupon_list_content">发放数量:{{item.num}}</div>
  356. <div class="el-icon-close close_icon" @click="handle('coupon_delete',ruleForm.setting[type][level].arr,index)"></div>
  357. <img v-if='item.status == 0' class='coupon_type_list_expired' src="/resources/img/common/gq.jpg">
  358. </div>
  359. </div>
  360. </div>
  361. </div>
  362. <!-- 优惠券特殊处理end -->
  363. <!-- 商品特殊处理start -->
  364. <div class="coupon_box" v-else-if="type == 'goods'">
  365. <div v-if="has_coupon">
  366. <div class="coupon_title flex flex-y-center">
  367. <div class="line"></div>
  368. <div style="margin-right: 6px;">{{ title }}</div>
  369. </div>
  370. <div class="add_coupon">
  371. <com-dialog-select v-model="bind_goods_id" :multiple="false" url="mall/goods/search"
  372. @selected="selectGoodsWarehouse">
  373. <el-button type="primary" @click='handle("goods_select", ruleForm.setting[type][level], {gift_type:type,level_index:level})'>选择商品</el-button>
  374. </com-dialog-select>
  375. </div>
  376. <div class="coupon_title flex flex-y-center">
  377. <div style="margin-right: 6px;">{{ title }}明细</div>
  378. </div>
  379. <div class="coupon_list_box flex-x-between flex" v-if="Object.keys(ruleForm.setting[type][level]).length !== 0">
  380. <div class="table-body">
  381. <template>
  382. <el-table
  383. :data="[ruleForm.setting[type][level]]"
  384. border
  385. style="width: 680px">
  386. <el-table-column
  387. label="商品"
  388. min-width="400">
  389. <template slot-scope="scope">
  390. <div flex="box:first">
  391. <div style="padding-right: 10px;">
  392. <com-image mode="aspectFill" :src="scope.row.cover_pic"></com-image>
  393. </div>
  394. <div>
  395. <div>
  396. {{scope.row.goods_name}}
  397. </div>
  398. <div>
  399. <span style="color:red;margin-right: 10px;">
  400. ¥{{scope.row.price}}
  401. </span>
  402. <span>
  403. 库存:{{scope.row.stock}}
  404. </span>
  405. </div>
  406. </div>
  407. </div>
  408. </template>
  409. </el-table-column>
  410. <el-table-column label="操作" min-width="150" align="center">
  411. <template slot-scope="scope">
  412. <el-button @click="delGoods(type, level)" type="text" size="small">删除</el-button>
  413. </template>
  414. </el-table-column>
  415. </el-table>
  416. </template>
  417. </div>
  418. </div>
  419. </div>
  420. </div>
  421. <!-- 商品特殊处理end -->
  422. <div class="red_envelope_box" v-else>
  423. <div class="coupon_title flex flex-y-center">
  424. <div class="line"></div>
  425. <div style="margin-right: 6px;">{{ title }}</div>
  426. </div>
  427. <div class="flex flex-y-center" v-if="ruleForm.setting[type]" >
  428. <div class="flex flex-y-center sky" style="margin-right: 20px;">
  429. <div style="width: 80px;">{{ title }}充值:</div>
  430. <el-input v-model="ruleForm.setting[type][level].prize" type="number" placeholder="请输入数值"></el-input>
  431. </div>
  432. <div class="flex flex-y-center">
  433. <div style="width: 80px;">备注说明:</div>
  434. <el-input type="textarea" placeholder="请输入内容" v-model="ruleForm.setting[type][level].remark" maxlength="30" show-word-limit>
  435. </div>
  436. </div>
  437. </div>
  438. <el-divider></el-divider>
  439. </div>
  440. </div>
  441. </div>
  442. </el-tab-pane>
  443. </el-tabs>
  444. </el-form>
  445. </el-card>
  446. <!-- 选择优惠券 -->
  447. <coupon-select v-if="has_coupon" :coupon-loading="couponLoading" :coupon_arr="coupon_arr" @submit="handleCoupon" @close="couponLoading = false"></coupon-select>
  448. </div>
  449. <script>
  450. new Vue({
  451. el: '#app',
  452. data() {
  453. var validatePass = (rule, value, callback) => {
  454. var reg = /^[\u4e00-\u9fa5\w]+$/;
  455. if (reg.test(value)) {
  456. callback();
  457. }else{
  458. callback(new Error('规则名不能含有特殊字符'));
  459. }
  460. };
  461. return {
  462. activeName: '',
  463. loading: false,
  464. is_coupon_more: false,
  465. couponLoading: false,
  466. level_arr: {},
  467. gift_type: '',
  468. goods_gift_type: '',
  469. level_name: '',
  470. level_index: 0,
  471. goods_level_index: 0,
  472. gift_type_name: '',
  473. setting_type_arr: {},
  474. coupon_arr: [],
  475. has_coupon: <?php echo $has_coupon ? 'true' : 'false'; ?>,
  476. ruleForm: {
  477. id: null,
  478. title: null,
  479. gift_type: null,
  480. status: 1,
  481. setting: {},
  482. },
  483. rules: {
  484. title: [
  485. {
  486. required: true,
  487. message: '请输入规则名称',
  488. trigger: 'blur',
  489. },
  490. {
  491. min: 1,
  492. max: 50,
  493. message: '长度在50个字符以内',
  494. trigger: 'blur'
  495. },
  496. {
  497. validator:validatePass,
  498. trigger: 'blur'
  499. },
  500. ],
  501. },
  502. formGoodsList:[],
  503. bind_goods_id: 0,
  504. }
  505. },
  506. mounted() {
  507. this.getDetail();
  508. },
  509. methods: {
  510. getDetail() {
  511. let self = this;
  512. self.loading = true;
  513. request({
  514. params: {
  515. r: 'upgrade-gift/default/edit',
  516. gift_type: getQuery('gift_type') ?? '',
  517. id: getQuery('id') ?? null,
  518. },
  519. method: 'get',
  520. }).then(e => {
  521. self.loading = false;
  522. if (e.data.code == 0) {
  523. let ruleForm_setting = e.data.data.detail.setting;// 配置数据
  524. self.level_arr = e.data.data.level_arr;// 等级
  525. self.setting_type_arr = e.data.data.setting_type_arr;// 赠送类型
  526. // 获取已有的数据
  527. let init_setting = {};
  528. if (ruleForm_setting) {
  529. for(let id in ruleForm_setting) {
  530. let item = ruleForm_setting[id];
  531. if(!init_setting[item.type]){ init_setting[item.type] = {}}// 空对象赋空值
  532. if (item.type == 'coupon') {
  533. if(!init_setting[item.type][item.level]){ init_setting[item.type][item.level] = {}}// 空对象赋空值
  534. if(!init_setting[item.type][item.level].arr){ init_setting[item.type][item.level].arr = []}// 空数组赋空值
  535. init_setting[item.type][item.level].arr.push({
  536. relevant_id: item.relevant_id,
  537. num: item.num,
  538. name: item.name,
  539. discount_method: item.discount_method,
  540. status: item.status,
  541. });
  542. } else if (item.type == 'goods') {
  543. init_setting[item.type][item.level] = item;
  544. } else {
  545. init_setting[item.type][item.level] = {
  546. prize: item.prize, remark: item.remark
  547. };
  548. }
  549. }
  550. }
  551. // 初始化ruleForm
  552. let setting = {};
  553. for(let type in self.setting_type_arr) {
  554. for(let level in self.level_arr) {
  555. if(!setting[type]){ setting[type] = {}}// 空对象赋空值
  556. if (init_setting[type] && init_setting[type][level]) {
  557. setting[type][level] = init_setting[type][level];
  558. } else {
  559. if (type == 'coupon') {
  560. setting[type][level] = {};// 空对象赋空值
  561. } else {
  562. setting[type][level] = {};// 空对象赋空值
  563. }
  564. }
  565. }
  566. }
  567. this.ruleForm.id = getQuery('id') ?? null;
  568. this.ruleForm.gift_type = e.data.data.detail.gift_type ?? getQuery('gift_type');
  569. this.ruleForm.setting = setting;
  570. this.level_name = e.data.data.level_name;
  571. this.gift_type_name = e.data.data.gift_type_name;
  572. this.ruleForm.status = e.data.data.detail.status ?? 1;
  573. } else {
  574. self.$message.error(e.data.msg);
  575. }
  576. })
  577. },
  578. submit(formName) {
  579. this.$refs[formName].validate((valid) => {
  580. if (valid) {
  581. console.log(this.ruleForm,'save');
  582. let self = this;
  583. self.loading = true;
  584. request({
  585. params: {
  586. r: 'upgrade-gift/default/edit',
  587. },
  588. method: 'post',
  589. data:this.ruleForm
  590. }).then(e => {
  591. self.loading = false;
  592. if (e.data.code == 0) {
  593. self.loading = false;
  594. self.$message.success(e.data.msg);
  595. navigateTo({
  596. r: 'upgrade-gift/default/index'
  597. })
  598. } else {
  599. self.$message.error(e.data.msg);
  600. }
  601. })
  602. } else {
  603. return false;
  604. }
  605. });
  606. },
  607. handleClick(tab, event){
  608. console.log(tab);
  609. },
  610. handleCoupon(data) {
  611. this.couponLoading = false;
  612. this.ruleForm.setting[this.gift_type][this.level_index].arr = data;
  613. },
  614. handle(type, data = null, data2 = null) {
  615. let id = data ? parseInt(data.id) : '';
  616. switch (type) {
  617. case 'edit':
  618. let params = {
  619. r: 'upgrade-gift/default/edit'
  620. };
  621. if (id) params = Object.assign(params, {
  622. id: id
  623. });
  624. navigateTo(params);
  625. break;
  626. case 'destroy':
  627. param = {id: data.id,type:type};
  628. this.$confirm('删除该条数据后不可以恢复, 是否继续?', '警告', {type: 'warning'}).then(() => {this.send(param,'upgrade-gift/default/handle')})
  629. break;
  630. case 'coupon_delete':
  631. data.splice(data2,1);
  632. console.log(this.ruleForm,'delete');
  633. break;
  634. case 'coupon_select':
  635. this.coupon_arr = data ?? [];
  636. this.gift_type = data2.gift_type;
  637. this.level_index = data2.level_index;
  638. this.couponLoading = true;
  639. break;
  640. case 'goods_select':
  641. this.goods_gift_type = data2.gift_type;
  642. this.goods_level_index = data2.level_index;
  643. break;
  644. }
  645. },
  646. send(params, url = '', callback) {
  647. let self = this;
  648. request({
  649. params: {
  650. r: url,
  651. },
  652. method: 'post',
  653. data: params
  654. }).then(e => {
  655. if (e.data.code == 0) {
  656. self.$message.success(e.data.msg);
  657. self.getList();
  658. } else {
  659. self.$message.error(e.data.msg);
  660. }
  661. if (callback) callback(e.data);
  662. }).catch(e => {
  663. console.log(e);
  664. });
  665. },
  666. selectGoodsWarehouse(v) {
  667. this.$set(this.ruleForm.setting[this.goods_gift_type], this.goods_level_index, {
  668. id: v.id,
  669. cover_pic: v.cover_pic,
  670. goods_name: v.goods_name,
  671. price: v.price,
  672. stock: v.stock,
  673. })
  674. },
  675. delGoods(type, level) {
  676. this.$set(this.ruleForm.setting[type], level, {})
  677. },
  678. }
  679. })
  680. </script>