index.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView('com-dialog-select');
  4. ComponentHelper::loadComponentView('com-image');
  5. ?>
  6. <?php defined('YII_ENV') or exit('Access Denied'); ?>
  7. <style>
  8. .preview {
  9. background-color: #fff;
  10. border-radius: 30px;
  11. padding: 40px 12.5px;
  12. width: 400px;
  13. height: 740px;
  14. position: relative;
  15. }
  16. .preview-icon {
  17. position: absolute;
  18. height: 45%;
  19. top: 51%;
  20. left: 17%;
  21. right: 10%;
  22. }
  23. .el-tabs__nav-wrap .el-tabs__nav-scroll {
  24. height: 468px !important;
  25. background: #f3f3f3;
  26. }
  27. .is-left.is-active {
  28. background: #ffffff;
  29. color: #409EFF;
  30. }
  31. .el-tabs--card > .el-tabs__header .el-tabs__nav {
  32. border-left: none;
  33. border-top: none;
  34. }
  35. .setting-menu {
  36. background-color: #fff;
  37. margin-left: 1%;
  38. width: 100%;
  39. height: 100%;
  40. position: relative;
  41. overflow: visible;
  42. }
  43. .button-item {
  44. padding: 9px 25px;
  45. bottom: -50px;
  46. left: 0;
  47. }
  48. .el-form-item {
  49. margin-bottom: 2%;
  50. }
  51. .pond-left {
  52. height: 26.5%;
  53. padding: 4% 4% 7%;
  54. width: 31%;
  55. }
  56. </style>
  57. <div id="app" v-cloak>
  58. <el-card shadow="never" style="border:0" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  59. <div slot="header">
  60. <span>奖品列表</span>
  61. </div>
  62. <div style="display: flex;">
  63. <div class="preview" v-loading=loading>
  64. <com-image style="border:2px solid #F4F5F6" src="/resources/addons/sudoku/img/pond.png" width='375px'
  65. height='660px'></com-image>
  66. <div class="preview-icon">
  67. <el-col :span=8 v-for="(item,index) in prizeImg" class="pond-left">
  68. <el-image style="width:100%;height:100%;" :src="item" v-if="index != 4"
  69. fit="contain"></el-image>
  70. </el-col>
  71. </div>
  72. </div>
  73. <el-card shadow="never" class="setting-menu" body-style="padding:2%;padding-right: 0">
  74. <div slot="header">
  75. <span>奖品设置</span>
  76. </div>
  77. <div class="text item" v-loading=loading>
  78. <el-form :model="form" label-width="80px" :rules='FormRules' ref="form">
  79. <el-tabs type="card" style="border:1px solid #e2e2e2;height:650px" v-model="activeName"
  80. @tab-click="handleClick" tab-Position="left">
  81. <el-tab-pane :label="item.name" :name="item.id" v-for="item in prize" :key="item.id">
  82. <div style="margin-top:25px">
  83. <el-form-item label="奖品选择" prop="type">
  84. <el-radio v-model="form.type" label="5">谢谢参与</el-radio>
  85. <el-radio v-model="form.type" label="1">余额</el-radio>
  86. <el-radio v-model="form.type" label="2">优惠券</el-radio>
  87. <el-radio v-model="form.type" label="3">积分</el-radio>
  88. <el-radio v-model="form.type" label="4">赠品</el-radio>
  89. </el-form-item>
  90. <el-form-item prop="image_url">
  91. <com-attachment title="缩略图" @selected="singleSelected">
  92. <el-tooltip class="item"
  93. effect="dark"
  94. content="建议尺寸:150 * 80"
  95. placement="top">
  96. <el-button size="mini">选择图片</el-button>
  97. </el-tooltip>
  98. </com-attachment>
  99. <el-image
  100. style="width: 80px; height: 80px"
  101. :src="form.image_url"
  102. fit="contain"></el-image>
  103. </el-form-item>
  104. <el-form-item label="名称" prop="name" v-if="form.type != 5">
  105. <el-input style='max-width: 180px' size="small" placeholder="奖品别名" size="small" v-model="form.name"
  106. autocomplete="off"></el-input>
  107. </el-form-item>
  108. <el-form-item label="金额" prop="red_packet_amount" v-if="form.type == 1">
  109. <el-input style='max-width: 180px' size="small" type="number" v-model="form.red_packet_amount"
  110. autocomplete="off"></el-input>
  111. </el-form-item>
  112. <el-form-item label="优惠券" prop="coupon_id" v-if="form.type == 2">
  113. <el-select size="small" v-model="form.coupon_id" size="small" placeholder="请选择">
  114. <el-option v-for="item in coupon" :label="item.name" :value='item.id'>
  115. </el-option>
  116. </el-select>
  117. </el-form-item>
  118. <el-form-item label="积分数量" prop="score" v-if="form.type == 3">
  119. <el-input style='max-width: 180px' size="small" size="small" type="number" v-model="form.score"
  120. autocomplete="off"></el-input>
  121. </el-form-item>
  122. <el-form-item label="关联商品" v-if="form.type == 4" prop="goods_id">
  123. <el-radio-group v-model="form.goods_id">
  124. <com-dialog-select :multiple="true" @selected="goodsSelect" :params="{'sudoku_is_attr':0}" title="商品选择">
  125. <el-button type="text">选择商品</el-button>
  126. </com-dialog-select>
  127. </el-radio-group>
  128. </el-form-item>
  129. <el-form-item v-if="form.goods_id && form.type == 4">
  130. <template>
  131. <div style="color: #ff4544;">最多可关联1个商品</div>
  132. <div style="max-height: 300px;overflow-y: auto">
  133. <el-table :data="goods_list" :show-header="false" border>
  134. <el-table-column label="">
  135. <template slot-scope="scope">
  136. <div flex>
  137. <div style="padding-right: 10px;flex-grow: 0">
  138. <com-image mode="aspectFill" :src="scope.row.cover_pic"></com-image>
  139. </div>
  140. <div style="flex-grow: 1;">
  141. <com-ellipsis :line="2">{{scope.row.goods_name}}</com-ellipsis>
  142. <com-ellipsis :line="2" style="color: red;">¥{{scope.row.price}}</com-ellipsis>
  143. </div>
  144. <div style="flex-grow: 0;">
  145. <el-button @click="deleteGoods(scope.$index)" type="text" circle size="mini">
  146. 删除
  147. </el-button>
  148. </div>
  149. </div>
  150. </template>
  151. </el-table-column>
  152. </el-table>
  153. </div>
  154. </template>
  155. </el-form-item>
  156. <el-form-item label="库存" prop="stock" v-if="form.type != 5">
  157. <el-input style='max-width: 180px' size="small" type="number" v-model="form.stock"
  158. autocomplete="off"></el-input>
  159. </el-form-item>
  160. <el-form-item label="中奖概率" prop="probability">
  161. <el-input style='max-width: 180px' size="small" type="number" @input = "handleInput($event)" @change = "probability_sum($event)" v-model="form.probability"
  162. autocomplete="off"></el-input>
  163. <div class="tips-text" >(单位:%, 八个宫格概率总和需要小于100%)</div>
  164. </el-form-item>
  165. </div>
  166. </el-tab-pane>
  167. </el-tabs>
  168. </el-form>
  169. <el-button class="button-item" type="primary" size="small" @click="onSubmit">保存</el-button>
  170. </div>
  171. </el-card>
  172. </div>
  173. </el-card>
  174. </div>
  175. <script>
  176. const app = new Vue({
  177. el: '#app',
  178. data() {
  179. return {
  180. form: {
  181. attr_id:null,
  182. goods_id:null,
  183. prize_id:1,
  184. red_packet_amount:0,
  185. probability:0,
  186. type:1,
  187. score:null,
  188. },
  189. keyword: null,
  190. coupon: [],
  191. activeName: '0',
  192. prizeImg: [],
  193. loading: false,
  194. attr: true,
  195. leave: false,
  196. goods: [],
  197. goods_list:[],
  198. list:[],
  199. goodsName: null,
  200. timeout: null,
  201. btnLoading: false,
  202. api_url:"",
  203. prize: [
  204. {name: '奖品一', id: '0'},
  205. {name: '奖品二', id: '1'},
  206. {name: '奖品三', id: '2'},
  207. {name: '奖品四', id: '3'},
  208. {name: '奖品五', id: '4'},
  209. {name: '奖品六', id: '5'},
  210. {name: '奖品七', id: '6'},
  211. {name: '奖品八', id: '7'}
  212. ],
  213. FormRules: {
  214. red_packet_amount: [
  215. {required: true, message: '红包金额不能为空', trigger: 'blur'},
  216. {pattern: /^(?!0$)([1-9][0-9]{0,8}|0)(\.[0-9]{1,2})?$/,message:'红包金额必须在0.01~999999999以内'}
  217. ],
  218. score: [
  219. {required: true, message: '积分数量不能为空', trigger: 'blur'},
  220. {required: true, pattern: /^[1-9]\d{0,8}$/,message:'积分数量必须在1~999999999以内'}
  221. ],
  222. stock: [
  223. {required: true, message: '库存不能为空', trigger: 'blur'},
  224. ],
  225. coupon_id: [
  226. {required: true, message: '请选择优惠券', trigger: 'change'},
  227. ],
  228. type: [
  229. {required: true, message: '奖品类型不能为空', trigger: 'blur'},
  230. ],
  231. attr_id: [
  232. {required: true, message: '请输入规格', trigger: 'change'},
  233. ],
  234. goods_id: [
  235. {required: true, message: '请选择关联商品', trigger: 'change'},
  236. ],
  237. probability: [
  238. {required: true, message: '概率不能为空', trigger: 'blur'},
  239. {pattern: /^(0|[1-9]\d*)(.\d+)?$/, message: '请输入非负数'}
  240. ],
  241. },
  242. attr_list: [],
  243. };
  244. },
  245. methods: {
  246. //搜索
  247. querySearchAsync(queryString, callback) {
  248. var goods = [];
  249. request({
  250. params: {
  251. r: 'sudoku/default/index',
  252. keyword: queryString
  253. },
  254. }).then(e => {
  255. if (e.data.code == 0) {
  256. goods = e.data.data.list;
  257. for (let i of goods) {
  258. i.value = i.name
  259. }
  260. callback(goods);
  261. }
  262. }).catch(e => {
  263. this.loading = false;
  264. });
  265. },
  266. deleteGoods(index) {
  267. this.goods_list.splice(index, 1);
  268. this.goods_id = '';
  269. this.form.goods_id = '';
  270. },
  271. goodsSelect(param) {
  272. this.goods_list = [];
  273. for (let j in param) {
  274. let item = param[j];
  275. if (this.form.goods_id) {
  276. this.$message.error('只能关联1个商品');
  277. return;
  278. }
  279. this.form.goods_id = item.id;
  280. var goods_data = {
  281. id: item.id,
  282. goods_name: item.goods_name,
  283. price: item.price,
  284. cover_pic: item.cover_pic,
  285. };
  286. this.goods_list.push(goods_data);
  287. this.list[this.activeName].goods = goods_data;
  288. console.log(this.goods_list,999999999999);
  289. }
  290. },
  291. clerkClick(row) {
  292. this.form.attr_id = null;
  293. this.form.attr_list = row.attr;
  294. if(this.form.attr_list && this.form.attr_list.length){
  295. this.form.attr_id = this.form.attr_list[0].id;
  296. }
  297. this.form.goods_id = row.id
  298. },
  299. handleInput(event) { // 设置概率输入只能是正整数
  300. this.form.probability = event.replace(/[^0-9]\d*/g, '');
  301. },
  302. probability_sum(value){
  303. var sum = 0;
  304. var sum_probability = 0;
  305. for (var i = 0; i<8; i++){
  306. if(this.activeName==i) {
  307. sum = parseFloat(sum) + parseFloat(value);
  308. }else{
  309. sum_probability = parseFloat(sum_probability) + parseFloat(this.list[i].probability);
  310. sum = parseFloat(sum) + parseFloat(this.list[i].probability);
  311. }
  312. }
  313. $courrct = 100 - sum;
  314. $last_value = 100 - sum_probability;
  315. if($courrct <= 0){
  316. this.form.probability = $last_value;
  317. this.$message('概率总和最大只能100%,可输入最大值是'+this.form.probability);
  318. }
  319. },
  320. // 选择商品
  321. handleSelect(item) {
  322. let that = this;
  323. if (item == "") {
  324. that.$message.error('请输入商品名称');
  325. } else {
  326. that.form.attr = item;
  327. that.form.attr_list = item.attr_list;
  328. that.form.attr_id = item.attr_list[0].id;
  329. setTimeout(function () {
  330. that.attr = true;
  331. }, 500)
  332. }
  333. },
  334. // 隐藏规格
  335. hideAttr() {
  336. this.attr = false;
  337. },
  338. // 提交
  339. onSubmit() {
  340. this.$refs.form.validate((valid) => {
  341. if (valid) {
  342. this.btnLoading = true;
  343. this.list[this.activeName] = this.form;
  344. let para = Object.assign(this.list);
  345. request({
  346. params: {
  347. r: 'sudoku/default/index',
  348. },
  349. data: {
  350. list: para
  351. },
  352. method: 'post'
  353. }).then(e => {
  354. this.btnLoading = false;
  355. if (e.data.code === 0) {
  356. this.$alert(e.data.msg, {
  357. confirmButtonText: '确定',
  358. callback: action => {
  359. location.reload();
  360. }
  361. });
  362. } else {
  363. this.$alert(e.data.msg, {
  364. confirmButtonText: '确定',
  365. });
  366. }
  367. }).catch(e => {
  368. this.btnLoading = false;
  369. this.$alert(e.data.msg, {
  370. confirmButtonText: '确定',
  371. });
  372. });
  373. }
  374. });
  375. },
  376. // 展示图片
  377. singleSelected(list) {
  378. this.form.image_url = list.length ? list[0].url : null;
  379. this.imgFormat(list);
  380. console.log(list,this.prizeImg,"999***",this.list);
  381. },
  382. imgFormat(list) {
  383. this.prizeImg = [
  384. this.list[0].image_url,
  385. this.list[1].image_url,
  386. this.list[2].image_url,
  387. this.list[7].image_url,
  388. '',
  389. this.list[3].image_url,
  390. this.list[6].image_url,
  391. this.list[5].image_url,
  392. this.list[4].image_url,
  393. ];
  394. },
  395. // 表单验证没通过,不能切换
  396. toleave() {
  397. return this.$refs.form.validate().then(() => {
  398. this.$refs.form.validate()
  399. }).catch(() => {
  400. this.$message.error('填写完整后方能切换');
  401. reject();
  402. });
  403. },
  404. // 切换左侧列表
  405. handleClick() {
  406. let that = this;
  407. setTimeout(function () {
  408. that.goods_list = [];
  409. that.form = that.list[that.activeName];
  410. that.form.prize_id = parseInt(that.activeName)+1;
  411. if(that.form.goods) that.goods_list[0] = that.form.goods;
  412. console.log(that.form);
  413. that.loading = false;
  414. }, 500)
  415. },
  416. getList() {
  417. this.loading = true;
  418. request({
  419. params: {
  420. r: 'sudoku/default/index',
  421. },
  422. }).then(e => {
  423. if (e.data.code == 0) {
  424. this.loading = false;
  425. this.coupon = e.data.data.coupon;
  426. this.api_url = e.data.data.api_url;
  427. if(e.data.data.list[0]){
  428. this.list = e.data.data.list;
  429. this.form = e.data.data.list[0];
  430. if(this.form.goods) this.goods_list[0] = this.form.goods;
  431. if (this.list.length < 8) {
  432. let diff_len = 8 - this.list.length;
  433. for (let i = 0; i < diff_len; i++) {
  434. console.log(i, this.list.length, 8 - this.list.length)
  435. this.list.push({
  436. 'name':'',
  437. 'type':'',
  438. 'goods_id':'',
  439. 'score':'',
  440. 'red_packet_amount':'',
  441. 'image_url':this.api_url+'/resources/addons/sudoku/img/sudoku'+i+'.png',
  442. 'coupon_id':'',
  443. 'stock':'',
  444. 'probability':'',
  445. 'prize_id':i+1,
  446. })
  447. }
  448. }
  449. for (var i = 0; i<e.data.data.list.length ; i++) {
  450. this.list[i].type = this.list[i].type ? this.list[i].type.toString(): "5";
  451. }
  452. console.log('list',this.list);
  453. this.form.type = this.form.type.toString();
  454. this.form.coupon_id = this.form.coupon_id !='0' ? this.form.coupon_id:null;
  455. this.imgFormat(this.list);
  456. }else{
  457. this.list = [];
  458. for (var i = 0; i<8; i++){
  459. this.list[i] = {
  460. 'name':'',
  461. 'type':'',
  462. 'goods_id':'',
  463. 'score':'',
  464. 'red_packet_amount':'',
  465. 'image_url':this.api_url+'/resources/addons/sudoku/img/sudoku'+i+'.png',
  466. 'coupon_id':'',
  467. 'stock':'',
  468. 'probability':'',
  469. 'prize_id':i+1,
  470. };
  471. }
  472. this.form = this.list[0];
  473. this.imgFormat(this.list);
  474. console.log(this.api_url,6666666666666);
  475. }
  476. } else {
  477. this.$message.error(e.data.msg);
  478. }
  479. this.loading = false;
  480. }).catch(e => {
  481. this.loading = false;
  482. });
  483. },
  484. },
  485. mounted: function () {
  486. this.getList();
  487. },
  488. })
  489. </script>