group-com-goods.php 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. <?php
  2. use common\helpers\ComponentHelper;
  3. ComponentHelper::loadComponentView('goods/com-attr', __DIR__);
  4. ComponentHelper::loadComponentView('com-attr-select' );
  5. ComponentHelper::loadComponentView('com-select-goods');
  6. ComponentHelper::loadComponentView('com-dialog-select');
  7. ?>
  8. <style>
  9. .type_text {
  10. font-size: 16px;
  11. font-weight: 600;
  12. color: #333;
  13. margin-right: 20px;
  14. }
  15. .detail_top {
  16. flex-wrap: wrap;
  17. }
  18. .detail_box {
  19. margin-top: 10px;
  20. }
  21. .coupon_box {
  22. width: 600px;
  23. margin-right: 50px;
  24. }
  25. .detail_top .coupon_box:last-child {
  26. margin-right: 0px;
  27. }
  28. .coupon_list_box {
  29. padding: 20px 20px 0 0;
  30. flex-wrap: wrap;
  31. box-sizing: border-box;
  32. overflow: hidden;
  33. height: 125px;
  34. }
  35. .coupon_list_box_active {
  36. height: auto;
  37. }
  38. .coupon_list_item {
  39. background: #F4F4F4;
  40. width: 275px;
  41. border-radius: 5px;
  42. position: relative;
  43. margin-bottom: 15px;
  44. padding: 10px;
  45. }
  46. .add_coupon .el-button {
  47. padding: 6px 18px;
  48. margin: 20px 0;
  49. }
  50. .close_icon {
  51. font-size: 20px;
  52. font-weight: 700;
  53. position: absolute;
  54. right: 10px;
  55. top: 8px;
  56. cursor: pointer;
  57. }
  58. .coupon_list_title {
  59. font-size: 16px;
  60. margin-bottom: 5px;
  61. width: 180px;
  62. }
  63. .coupon_list_content {
  64. margin-bottom: 2px;
  65. font-size: 12px;
  66. }
  67. .more_btn {
  68. text-align: center;
  69. cursor: pointer;
  70. margin-top: 20px;
  71. }
  72. .more_icon {
  73. transform: rotate(0deg);
  74. transition: all 0.7s;
  75. }
  76. .show_more_icon {
  77. transform: rotate(180deg);
  78. }
  79. .show {
  80. height: auto;
  81. }
  82. .hide {
  83. height: 0;
  84. overflow: hidden;
  85. }
  86. .transform-hide {
  87. opacity: 0;
  88. -webkit-transform: translateY(-50%);
  89. transform: translateY(-50%);
  90. -webkit-transition: .3s;
  91. transition: .3s;
  92. }
  93. .transform-show {
  94. opacity: 1 !important;
  95. -webkit-transform: translateY(0) !important;
  96. transform: translateY(0) !important;
  97. }
  98. .is_divider {
  99. display: block;
  100. }
  101. @media screen and (min-width: 1540px) {
  102. .is_divider {
  103. display: none;
  104. }
  105. }
  106. .red_envelope_box {
  107. width: 600px;
  108. margin-right: 50px;
  109. }
  110. .red_envelope_box:last-child {
  111. margin-right: 0px;
  112. }
  113. .red_envelope_box .el-input {
  114. width: 150px;
  115. }
  116. .red_envelope_box .el-textarea {
  117. width: 250px;
  118. }
  119. .el-input {
  120. flex: 1;
  121. }
  122. .el-textarea {
  123. flex: 1;
  124. }
  125. .types_box {
  126. padding: 20px 20px 30px;
  127. }
  128. .label_title {
  129. font-weight: 600;
  130. margin-bottom: 8px;
  131. font-size: 16px;
  132. }
  133. .checkt_select {
  134. width: 140px;
  135. }
  136. .check_input {
  137. width: 200px;
  138. margin-left: 10px;
  139. }
  140. .check_btn_list .el-button {
  141. padding: 6px 14px;
  142. margin-bottom: 20px;
  143. }
  144. .el-dialog__footer {
  145. text-align: center;
  146. }
  147. .check_pagination {
  148. justify-content: flex-end;
  149. margin-top: 20px;
  150. }
  151. /* 谷歌 */
  152. input::-webkit-outer-spin-button,
  153. input::-webkit-inner-spin-button {
  154. -webkit-appearance: none;
  155. appearance: none;
  156. margin: 0;
  157. }
  158. /* 火狐 */
  159. input {
  160. -moz-appearance: textfield;
  161. }
  162. /* 公共样式 */
  163. .flex {
  164. display: -webkit-box;
  165. display: -webkit-flex;
  166. /* #ifndef APP-NVUE */
  167. display: flex;
  168. /* #endif */
  169. }
  170. .flex-x-center {
  171. display: -webkit-box;
  172. display: -webkit-flex;
  173. /* #ifndef APP-NVUE */
  174. display: flex;
  175. /* #endif */
  176. -webkit-box-pack: center;
  177. -webkit-justify-content: center;
  178. -ms-flex-pack: center;
  179. justify-content: center;
  180. }
  181. .flex-x-between {
  182. display: -webkit-box;
  183. display: -webkit-flex;
  184. /* #ifndef APP-NVUE */
  185. display: flex;
  186. /* #endif */
  187. -webkit-box-pack: space-between;
  188. -webkit-justify-content: space-between;
  189. -ms-flex-pack: space-between;
  190. justify-content: space-between;
  191. }
  192. .flex-y-center {
  193. display: -webkit-box;
  194. display: -webkit-flex;
  195. /* #ifndef APP-NVUE */
  196. display: flex;
  197. /* #endif */
  198. -webkit-box-align: center;
  199. -webkit-align-items: center;
  200. -ms-flex-align: center;
  201. -ms-grid-row-align: center;
  202. align-items: center;
  203. }
  204. /* 溢出隐藏 */
  205. .over1 {
  206. text-overflow: -o-ellipsis-lastline;
  207. overflow: hidden;
  208. text-overflow: ellipsis;
  209. display: -webkit-box;
  210. -webkit-line-clamp: 1;
  211. -webkit-box-orient: vertical;
  212. }
  213. .over2 {
  214. text-overflow: -o-ellipsis-lastline;
  215. overflow: hidden;
  216. text-overflow: ellipsis;
  217. display: -webkit-box;
  218. -webkit-line-clamp: 2;
  219. -webkit-box-orient: vertical;
  220. }
  221. .huiyuanRadio{
  222. margin-bottom: 10px;
  223. }
  224. </style>
  225. <template id="abc">
  226. <el-card shadow="never" style="border:0" body-style="background-color: #f3f3f3;padding: 10px 0 0;" class="com-goods" v-loading="cardLoading">
  227. <div>
  228. <el-form :model="cForm" :rules="cRule" ref="ruleForm" label-width="140px" size="small" class="demo-ruleForm">
  229. <el-tabs v-model="activeName">
  230. <el-tab-pane label="基础设置" name="first">
  231. <!-- 选择分类 -->
  232. <slot name="before_cats"></slot>
  233. <!-- 基本信息 -->
  234. <slot name="before_info"></slot>
  235. <el-card shadow="never" class="mt-24" style="margin-bottom: 20px;">
  236. <div slot="header">
  237. <span>基本信息</span>
  238. </div>
  239. <el-row>
  240. <el-col :xl="12" :lg="16">
  241. <template>
  242. <el-form-item label="拼团活动名称">
  243. <el-input class="width-200" v-model="title"></el-input>
  244. </el-form-item>
  245. <el-form-item label="拼团分类" prop="parent_title">
  246. <el-select v-model="cate_name" placeholder="请选择" @change="handleChange">
  247. <el-option v-for="item,k in cateList" :key="item.id" :label="item.name" :value="item.id">
  248. </el-option>
  249. </el-select>
  250. </el-form-item>
  251. <el-form-item label="商品信息获取" width="120">
  252. <label slot="label">
  253. 商品信息获取
  254. <el-tooltip class="item" effect="dark" content="只能从商城中获取商品信息,且基本信息与商城商品保持一致" placement="top">
  255. <i class="el-icon-info"></i>
  256. </el-tooltip>
  257. </label>
  258. <div>
  259. <el-row type="flex">
  260. <com-dialog-select :multiple="false" :url="goodsIndexUrl"
  261. @selected="selectGoodsWarehouse" ref="comDialogSelect"
  262. :show-mch-source="true" :extra-search-fields="['goods_source']">
  263. <el-button>选择商品</el-button>
  264. </com-dialog-select>
  265. </el-row>
  266. </div>
  267. </el-form-item>
  268. <el-form-item v-if="formGoodsList.length>0" label="拼团商品">
  269. <div class="table-body" style="padding-left: 0;padding-top: 0;">
  270. <template>
  271. <el-table :data="formGoodsList" border style="width: 100%">
  272. <el-table-column fixed type="index" label="编号" show-overflow-tooltip width="50">
  273. </el-table-column>
  274. <el-table-column prop="goods_name,cover_pic" label="商品名称" >
  275. <template slot-scope="scope">
  276. <div flex="box:first">
  277. <div style="padding-right: 10px;">
  278. <com-image mode="aspectFill" :src="scope.row.cover_pic"></com-image>
  279. </div>
  280. <div flex="cross:top cross:center">
  281. {{scope.row.goods_name}}
  282. </div>
  283. </div>
  284. </template>
  285. </el-table-column>
  286. <el-table-column fixed="right" label="操作" width="100">
  287. <template slot-scope="scope">
  288. <el-button @click="delGoods(scope.$index)" type="primary" size="mini">删除</el-button>
  289. </template>
  290. </el-table-column>
  291. </el-table>
  292. </template>
  293. </div>
  294. </el-form-item>
  295. <el-form-item label="规格" v-if="is_attr == 0">
  296. <el-row type="flex">
  297. <com-ellipsis :line="1">
  298. <template v-for="item in ruleForm.select_attr_groups">
  299. <span style="margin: 0 5px;">
  300. {{item.attr_group_name}}:{{item.attr_name}}
  301. </span>
  302. </template>
  303. </com-ellipsis>
  304. </el-row>
  305. </el-form-item>
  306. </template>
  307. </el-col>
  308. </el-row>
  309. </el-card>
  310. <!-- 价格库存 -->
  311. <slot name="before_attr"></slot>
  312. <el-card shadow="never" class="mt-24" style="margin-bottom: 20px;">
  313. <div slot="header">
  314. <span>价格库存</span>
  315. </div>
  316. <el-row>
  317. <el-col :xl="12" :lg="16">
  318. <template v-if="is_attr == 1">
  319. <el-form-item prop="goods_num" v-if="ruleForm.use_attr==0">
  320. <label slot="label">
  321. <span>拼团商品总库存</span>
  322. <el-tooltip class="item" effect="dark" content="拼团商品总库存与普通商品总库存相互独立" placement="top">
  323. <i class="el-icon-info"></i>
  324. </el-tooltip>
  325. </label>
  326. <el-input type="number" min="0" :max="999999" @input="changeInput" v-model="goods_stock"><!--oninput="this.value = this.value.replace(/[^0-9\.]/, '');" :disabled="moreAttrs" -->
  327. </el-input>
  328. </el-form-item>
  329. <el-form-item prop="goods_num" v-show="ruleForm.use_attr==1">
  330. <label slot="label">
  331. <span>商品规格</span>
  332. <el-tooltip class="item" effect="dark" content="如有颜色、尺码等多种规格,请添加商品规格" placement="top">
  333. <i class="el-icon-info"></i>
  334. </el-tooltip>
  335. </label>
  336. <div v-show="ruleForm.use_attr" style="width:130%;margin-top: 24px;">
  337. <com-attr ref="commAttrs" v-model="ruleForm.attr" :attr-groups="attrGroups" :extra="cForm.extra ? cForm.extra : {}"></com-attr>
  338. </div>
  339. </el-form-item>
  340. <el-form-item label="售价" prop="price" v-if="is_price !=3">
  341. <el-input :disabled="true" type="number" oninput="this.value = this.value.replace(/[^0-9\.]/, '');" min="0" v-model="ruleForm.price">
  342. <template slot="append">元</template>
  343. </el-input>
  344. </el-form-item>
  345. <el-form-item label="拼团价" prop="group_buy_price" v-if="ruleForm.use_attr==0">
  346. <el-input oninput="value = toNumber(value, 2)" min="0" :max="ruleForm.price" v-model="ruleForm.group_buy_price">
  347. <template slot="append">元</template>
  348. </el-input>
  349. </el-form-item>
  350. </template>
  351. </el-col>
  352. </el-row>
  353. </el-card>
  354. <el-card shadow="never" class="mt-24" style="margin-bottom: 20px;">
  355. <div slot="header">
  356. <span>拼团信息</span>
  357. </div>
  358. <el-row>
  359. <el-col :xl="12" :lg="16">
  360. <template v-if="is_attr == 1">
  361. <el-form-item label="拼团活动时间">
  362. <el-date-picker
  363. size="small"
  364. v-model="activeTime"
  365. @change="datetimeChange"
  366. type="datetimerange"
  367. range-separator="至"
  368. start-placeholder="开始日期"
  369. end-placeholder="结束日期"
  370. value-format="yyyy-MM-dd HH:mm:ss"
  371. align="center">
  372. </el-date-picker>
  373. </el-form-item>
  374. <el-form-item label="拼团有效时间" prop="goods_num">
  375. <el-input style="width:220px;" type="number" min="0" v-model="continuedHouse" @input="changeInput2"><!-- oninput="this.value = this.value.replace(/[^0-9\.]/, '');" -->
  376. <template slot="append">小时</template>
  377. </el-input>
  378. <el-input style="width:220px;margin-left: 20px;" type="number" min="0" max="59" v-model="continuedMinute" @input="changeInput3"><!-- oninput="this.value = this.value.replace(/[^0-9\.]/, '');" -->
  379. <template slot="append">分钟</template>
  380. </el-input>
  381. </el-form-item>
  382. <!-- 加入校验规则rules显示* -->
  383. <el-form-item label="成团人数" prop="goods_num">
  384. <el-input type="number" placeholder="请输入2-999999人" oninput="this.value = this.value.replace(/[^0-9]/, '');" min="0" v-model="group_size">
  385. <template slot="append">人</template>
  386. </el-input>
  387. </el-form-item>
  388. <!-- 高级设置 -->
  389. <el-form-item label="高级设置" prop="status">
  390. <el-switch v-model="senior_setting" :active-value="1" :inactive-value="0">
  391. </el-switch>
  392. </el-form-item>
  393. <el-form-item label="限购规则" v-if="senior_setting">
  394. <div>
  395. <el-radio v-model="purchase" border :label="2">不限购</el-radio>
  396. <el-radio v-model="purchase" border :label="1">限购</el-radio>
  397. </div>
  398. <div style="margin-top: 15px;width: 350px;" v-if="purchase == 1">
  399. <el-input placeholder="请输入数量" type="number" v-model="limit_buy_num" oninput="this.value = this.value.replace(/[^0-9]/, '');">
  400. <template slot="prepend">每单限购</template>
  401. <template slot="append">件/人</template>
  402. </el-input>
  403. </div>
  404. </el-form-item>
  405. <el-form-item label="限制参团规则" v-if="senior_setting" required>
  406. <label slot="label">
  407. 限制参团规则
  408. <el-tooltip class="item" effect="dark" content="只有拼团中和拼团成功才计算参团次数,拼团失败不计入参团次数" placement="top">
  409. <i class="el-icon-info"></i>
  410. </el-tooltip>
  411. </label>
  412. <div>
  413. <el-radio-group v-model="is_restrict_rule">
  414. <el-radio :label="0" border>不限制</el-radio>
  415. <el-radio :label="1" border>限制</el-radio>
  416. </el-radio-group>
  417. </div>
  418. <div style="margin-top: 15px;width: 350px;" v-if="is_restrict_rule == 1">
  419. <el-input placeholder="限制参团" type="number" v-model="restrict_rule_num" oninput="this.value = this.value.replace(/[^0-9]/, '');">
  420. <template slot="prepend">限制参团</template>
  421. <template slot="append">次/人</template>
  422. </el-input>
  423. </div>
  424. </el-form-item>
  425. <el-form-item label="团长权重限制" v-if="senior_setting">
  426. <div>
  427. <div>
  428. <el-radio class="huiyuanRadio" v-model="isAll_C" border :label="1">全部用户</el-radio>
  429. <el-radio class="huiyuanRadio" v-model="isAll_C" border :label="2">指定用户权重</el-radio>
  430. </div>
  431. <div style="display: flex;" v-if="isAll_C == 2">
  432. <div style="margin-right: 20px;">
  433. <el-checkbox :indeterminate="isIndeterminate_C" v-model="checkAll_C" @change="handleCheckAllChange_C">全选</el-checkbox>
  434. </div>
  435. <div>
  436. <el-checkbox-group v-model="checkedCities_C" @change="handleCheckedCitiesChange_C">
  437. <el-checkbox v-for="(item,index) in memberLevel" :label="item.level" :value="item.level" :key="index" >{{item.name}}</el-checkbox>
  438. </el-checkbox-group>
  439. </div>
  440. </div>
  441. </div>
  442. </el-form-item>
  443. <el-form-item label="团员等级限制" v-if="senior_setting">
  444. <div>
  445. <div>
  446. <el-radio class="huiyuanRadio" v-model="isAll" border :label="1">全部用户</el-radio>
  447. <el-radio class="huiyuanRadio" v-model="isAll" border :label="2">指定用户等级</el-radio>
  448. </div>
  449. <div style="display: flex;" v-if="isAll == 2">
  450. <div style="margin-right: 20px;">
  451. <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
  452. </div>
  453. <div>
  454. <el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
  455. <el-checkbox v-for="(item,index) in memberLevel" :label="item.level" :value="item.level" :key="index" >{{item.name}}</el-checkbox>
  456. </el-checkbox-group>
  457. </div>
  458. </div>
  459. </div>
  460. </el-form-item>
  461. <el-form-item v-if="senior_setting" label="团长福利" prop="goods_num">
  462. <el-radio style="display: block;" v-model="sendStatus" :label="1">
  463. 团长送积分
  464. <el-input type="number" style="width:200px;margin-left:10px;margin-bottom: 10px;" oninput="this.value = this.value.replace(/[^0-9\.]/, '');" min="0" :disabled="sendStatus==1?false:true" v-model="give_score">
  465. </el-input>
  466. 积分
  467. </el-radio>
  468. <el-radio style="display: block;" v-model="sendStatus" :label="2">
  469. 团长送余额
  470. <el-input type="number" style="width:200px;margin-left:10px;margin-bottom: 10px;" oninput="this.value = this.value.replace(/[^0-9\.]/, '');" min="0" :disabled="sendStatus==2?false:true" v-model="give_balance">
  471. </el-input>
  472. </el-radio>
  473. <div v-if="coupon_data.length > 2" class="more_btn flex flex-y-center flex-x-center" @click="showMore('coupon')">
  474. <div style="margin-right: 2px;" v-if="is_coupon_more">收起</div>
  475. <div style="margin-right: 2px;" v-else>更多</div>
  476. <i class="el-icon-arrow-down more_icon" :class="{show_more_icon:is_coupon_more}" style="font-size: 18px;"></i>
  477. </div>
  478. </el-form-item>
  479. <el-form-item v-if="senior_setting" label="发起人是否免费开团" prop="is_initiator_free">
  480. <el-switch v-model="is_initiator_free" :active-value="1" :inactive-value="0">
  481. </el-switch>
  482. </el-form-item>
  483. <el-form-item v-if="senior_setting" label="拼团详情是否显示参团人员昵称" prop="is_show_participant_nickname">
  484. <el-switch v-model="is_show_participant_nickname" :active-value="1" :inactive-value="0">
  485. </el-switch>
  486. </el-form-item>
  487. <!-- 是否开启虚拟成团 -->
  488. <el-form-item v-if="senior_setting" label="是否开启虚拟成团" prop="status">
  489. <div>
  490. <el-switch v-model="is_virtual" :active-value="1" :inactive-value="0">
  491. </el-switch>
  492. </div>
  493. <div style="margin-bottom: 10px;">
  494. <el-tag type="warning">开启模拟成团后,满足条件的团,系统将会模拟“匿名买家”凑满该团,仅需对真实拼团买家发货。建议合理开启,以提高成团率。</el-tag>
  495. </div>
  496. <div v-if="is_virtual&&senior_setting">
  497. <el-radio class="huiyuanRadio" v-model="virtual_group_type" :label="1">虚拟立即成团</el-radio>
  498. <el-radio class="huiyuanRadio" v-model="virtual_group_type" :label="3">参团结束成团</el-radio>
  499. <el-radio class="huiyuanRadio" v-model="virtual_group_type" :label="2">参团人数≥ <el-input :disabled="virtual_group_type == 1 || virtual_group_type == 3" style="width: 150px;" type="number" placeholder="请输入数量" v-model="gt_group_size"></el-input> 的团</el-radio>
  500. <div v-if="virtual_group_type == 3">
  501. <el-radio-group v-model="virtual_group_sub_type">
  502. <el-radio :label="0">当拼团有效期结束后,自动成团</el-radio>
  503. <el-radio :label="1">当参团人数≥
  504. <el-input v-model="expired_auto_complete_min_num" style="width: 80px;"></el-input>
  505. 人,拼团有效期结束后,自动成团
  506. <el-tooltip effect="dark" content="若参团人数 < 所设置的人数,则拼团失败,发起人支付的金额原路返回。" placement="top" style="position: absolute;">
  507. <i class="el-icon-question"></i>
  508. </el-tooltip>
  509. </el-radio>
  510. </el-radio-group>
  511. </div>
  512. </div>
  513. <!-- 是否显示虚拟成团人的头像 -->
  514. <el-form-item v-if="is_virtual && virtual_group_type == 3 && senior_setting" label="是否显示虚拟成团人的头像" prop="is_show_virtual_avatar" label-width="200">
  515. <div>
  516. <el-switch v-model="is_show_virtual_avatar" :active-value="1" :inactive-value="0">
  517. </el-switch>
  518. </div>
  519. </el-form-item>
  520. </el-form-item>
  521. </template>
  522. </el-col>
  523. </el-row>
  524. </el-card>
  525. </el-tab-pane>
  526. <slot name="tab_pane"></slot>
  527. </el-tabs>
  528. </el-form>
  529. <div class="bottom-div" flex="cross:center" v-if="is_save_btn == 1" style="margin-top: 10px;">
  530. <el-button class="button-item" :loading="btnLoading" type="primary" size="small" @click="store('ruleForm')">保存
  531. </el-button>
  532. </div>
  533. </div>
  534. </el-card>
  535. </template>
  536. <script>
  537. Vue.component('group-com-goods', {
  538. template: '#abc',
  539. props: {
  540. // 规格库存
  541. is_attr: {
  542. type: Number,
  543. default: 1
  544. },
  545. //todo 仅显示售价(抽奖) 秒杀3显示
  546. is_price: {
  547. type: Number,
  548. default: 0
  549. },
  550. // 添加数据接口
  551. store_url: {
  552. type: String,
  553. default: 'group-buy/default/add'
  554. },
  555. // 请求数据地址--获取详情
  556. get_goods_detail_url: {
  557. type: String,
  558. default: 'group-buy/index/show'
  559. },
  560. // 保存之后返回地址
  561. referrer: {
  562. default: 'group-buy/default/index'
  563. },
  564. // 页面上数据
  565. form: Object,
  566. // 数据验证方式
  567. rule: Object,
  568. is_save_btn: {
  569. type: Number,
  570. default: 1
  571. }
  572. },
  573. data() {
  574. let ruleForm = {
  575. labels: [],
  576. attr: [],
  577. use_attr: 0,
  578. group_buy_price: '',
  579. select_attr_groups: [], // 已选择的规格
  580. goodsWarehouse_attrGroups: [], // 商品库商品所有的规格
  581. share_level_type: 0,
  582. };
  583. let rules = {
  584. };
  585. return {
  586. value1: '',
  587. goodsIndexUrl: 'group-buy/default/goods-list',
  588. title: '', //拼团活动名称
  589. formGoodsList: [], //选中的商品数组(最多只能选一个)
  590. moreAttrs: true, //默认选中多规格商品
  591. goods_stock: 0, //拼团商品总库存
  592. groupGoodsId: '', //拼团商品id
  593. valueDay: '', //添加拼团商品开始日期
  594. valueTime: '', //添加拼团具体时间
  595. groupStartDate: '', //拼团活动开始时刻
  596. groupEndDate: '', //拼团活动结束时间
  597. continuedHouse: '', //拼团小时数
  598. continuedMinute: '', //拼团分钟数
  599. continuedTime: '', //拼团活动持续时间
  600. group_size: 0, //成团所需人数
  601. senior_setting: 0, //默认不开启虚拟成团
  602. virtual_group_size: 0, //虚拟成团人数
  603. is_virtual: 0, //是否虚拟成团
  604. sendStatus: 0,
  605. give_score: 0, //团长送积分
  606. give_balance: 0, //团长送余额
  607. send_red_packet: 0, //送红包
  608. limit_buy_num:'',//限制购买数量 0=不限制
  609. goods_id: 0,
  610. cardLoading: false,
  611. btnLoading: false,
  612. activeName: 'first',
  613. ruleForm: ruleForm,
  614. attrGroups: [], //规格组
  615. dialogCoupon:false,
  616. couponLoading:false,
  617. couponKeyword: '',
  618. coupon_delete: [], //删除了的优惠券数据
  619. coupon_total: 0, //优惠券发放总数
  620. cou_tableData: [],
  621. coupon_data: [],
  622. dialog_total_count: 0,
  623. page: 1,
  624. level_arr: [],
  625. level_index: 0,
  626. level_id: '',
  627. coupon_test: [],
  628. loading:false,
  629. is_coupon_more: false,
  630. staging_arr: [],
  631. activeTime:'',
  632. purchase:2,// 1限购 2不限购
  633. memberLevel:[],//会员等级列表
  634. is_restrict_rule: 0, // 0 不限制参团规则 1限制参团规则
  635. restrict_rule_num: 0, // 限制参团次数
  636. cateList:[],//分类列表,
  637. cate_name: '',
  638. cate_id: 0,
  639. checkAll: true,
  640. checkAll_C: true,
  641. checkedCities: [],
  642. checkedCities_C: [],
  643. isIndeterminate: false,
  644. isIndeterminate_C: false,
  645. virtual_group_type:1,//虚拟成团类型 1=全部 2=成团人数大于
  646. gt_group_size:0,//拼团人数大于N,则虚拟成团
  647. isAll:1,//1指定全部会员购买 2指定等级购买
  648. isAll_C:1,//1指定全部会员购买 2指定等级购买
  649. is_initiator_free: 0, // 发起人免费开团
  650. virtual_group_sub_type: 0, // "参团结束开团" 出现的选项
  651. expired_auto_complete_min_num: 0, // 当参团人数≥ x 人,拼团有效期结束后,自动成团
  652. is_show_participant_nickname: 0, // 是否显示参团人员昵称
  653. is_show_virtual_avatar: 1, // 是否显示虚拟拼团头像
  654. };
  655. },
  656. created() {
  657. if (getQuery('id')) {
  658. this.getGoodsList(getQuery('id'));
  659. this.goods_id = getQuery('id');
  660. }
  661. this.getMemberLevel();
  662. this.getGroupCateList();
  663. },
  664. watch: {
  665. 'ruleForm.detail'(newVal, oldVal) {
  666. this.cForm.detail = newVal
  667. },
  668. 'attrGroups'(newVal, oldVal) {
  669. this.ruleForm.use_attr = newVal.length === 0 ? 0 : 1;
  670. },
  671. 'ruleForm.is_level'(newVal, oldVal) {
  672. if (newVal === 0) {
  673. this.ruleForm.is_level_alone = 0;
  674. }
  675. },
  676. },
  677. // 这里有用到计算属性
  678. computed: {
  679. cForm() {
  680. let form = {};
  681. let ruleForm = JSON.parse(JSON.stringify(this.ruleForm));
  682. if (this.form) {
  683. form = Object.assign(ruleForm, JSON.parse(JSON.stringify(this.form)));
  684. } else {
  685. form = ruleForm;
  686. }
  687. if (getQuery('id')) {
  688. form.id = getQuery('id')
  689. }
  690. return form;
  691. },
  692. cRule() {
  693. return this.rules;
  694. },
  695. },
  696. methods: {
  697. changeInput(){
  698. var pattern = /^[1-9][0-9]*$/ // 正整数的正则表达式
  699. // 不符合正整数时
  700. if (!pattern.test(this.goods_stock)) {
  701. // input 框绑定的内容为空
  702. this.goods_stock = ''
  703. }
  704. },
  705. changeInput2(){
  706. var pattern = /^[0-9][0-9]*$/ // 正整数的正则表达式
  707. // 不符合正整数时
  708. if (!pattern.test(this.continuedHouse)) {
  709. // input 框绑定的内容为空
  710. this.continuedHouse = ''
  711. }
  712. },
  713. changeInput3(){
  714. var pattern = /^[0-9][0-9]*$/ // 正整数的正则表达式
  715. // 不符合正整数时
  716. if (!pattern.test(this.continuedMinute)) {
  717. // input 框绑定的内容为空
  718. this.continuedMinute = ''
  719. }
  720. },
  721. handleCheckAllChange(val) {
  722. let arr = [];
  723. this.memberLevel.forEach((item)=>{
  724. arr.push(item.level)
  725. })
  726. this.checkedCities = val ? arr : [];
  727. this.isIndeterminate = false;
  728. },
  729. handleCheckAllChange_C(val) {
  730. let arr = [];
  731. this.memberLevel.forEach((item)=>{
  732. arr.push(item.level)
  733. })
  734. this.checkedCities_C = val ? arr : [];
  735. this.isIndeterminate_C = false;
  736. },
  737. handleCheckedCitiesChange(value) {
  738. let checkedCount = value.length;
  739. this.checkAll = checkedCount === this.memberLevel.length;
  740. this.isIndeterminate = checkedCount > 0 && checkedCount < this.memberLevel.length;
  741. },
  742. handleCheckedCitiesChange_C(value) {
  743. let checkedCount = value.length;
  744. this.checkAll_C = checkedCount === this.memberLevel.length;
  745. this.isIndeterminate_C = checkedCount > 0 && checkedCount < this.memberLevel.length;
  746. },
  747. // 会员等级列表
  748. getMemberLevel() {
  749. let self = this;
  750. request({
  751. params: {
  752. r: 'group-buy/default/user-level-list',
  753. page: 1,
  754. },
  755. method: 'get',
  756. }).then(e => {
  757. if (e.data.code === 0) {
  758. this.memberLevel = e.data.data.list;
  759. this.memberLevel.forEach((item)=>{
  760. this.checkedCities.push(item.level)
  761. this.checkedCities_C.push(item.level)
  762. })
  763. } else {
  764. self.$message.error(e.data.msg);
  765. }
  766. }).catch(e => {
  767. console.log(e);
  768. });
  769. },
  770. getGroupCateList() {
  771. let self = this;
  772. request({
  773. params: {
  774. r: 'group-buy/default/cate-list',
  775. page: 1,
  776. },
  777. method: 'get',
  778. }).then(e => {
  779. if (e.data.code === 0) {
  780. this.cateList = e.data.data.list;
  781. } else {
  782. self.$message.error(e.data.msg);
  783. }
  784. }).catch(e => {
  785. console.log(e);
  786. });
  787. },
  788. datetimeChange(){
  789. if(this.activeTime){
  790. this.start_at = this.activeTime[0];
  791. this.end_at = this.activeTime[1];
  792. }else{
  793. this.start_at = '';
  794. this.end_at = '';
  795. }
  796. },
  797. //拼团活动时间设置
  798. setActivityTime(params) {
  799. let begin = params[0];
  800. let end = params[1];
  801. self.groupStartDate = dateFormat('YYYY-mm-dd HH:MM:SS',begin);
  802. self.groupEndDate = dateFormat('YYYY-mm-dd HH:MM:SS',end);
  803. console.log(self.groupStartDate,self.groupEndDate)
  804. },
  805. // 0.0.1 删除选中商品
  806. delGoods() {
  807. this.formGoodsList = [];
  808. this.goods_warehouse = {};
  809. location.reload(); //刷新当前页
  810. },
  811. // 0.1 获取拼团开始时间 2020-08-07 00:00:00
  812. getGroupStartDate(valueDay, valueTime) {
  813. let self = this;
  814. self.groupStartDate = valueDay + ' ' + valueTime;
  815. },
  816. // 0.2 获取拼团持续分钟数 -''做乘法运算返回0
  817. getContinuedTime(continuedHouse, continuedMinute) {
  818. let self = this;
  819. self.continuedTime = continuedHouse * 60 + continuedMinute * 1;
  820. console.log(self.continuedTime);
  821. },
  822. store(formName) {
  823. self = this;
  824. let total_stock = 0
  825. this.$refs.commAttrs.cData.forEach(item => { total_stock += parseInt(item.stock) })
  826. if(total_stock==0){
  827. total_stock = this.goods_stock;
  828. }
  829. if (total_stock < this.group_size) {
  830. return self.$message.error("拼团商品总库存必须大于成团人数");
  831. }
  832. $res = this.validate();
  833. if($res === false) return false;
  834. if(this.senior_setting){//高级设置开启了
  835. // 判断是否开启了参团限制
  836. if (this.is_restrict_rule == 1 && this.restrict_rule_num <= 0) {
  837. return self.$message.error("请输入参团数量");
  838. }
  839. if(this.purchase == 1 && this.limit_buy_num <= 0){//限购 并且 没有填写限购数量
  840. return self.$message.error("请正确填写限购数量");
  841. }
  842. if(this.isAll == 2 && this.checkedCities.length == 0){//指定用户 没有勾选用户
  843. return self.$message.error("请勾选指定团长等级");
  844. }
  845. if(this.isAll_C == 2 && this.checkedCities_C.length == 0){//指定用户 没有勾选用户
  846. return self.$message.error("请勾选指定团员等级");
  847. }
  848. if(this.is_virtual && this.virtual_group_type == 2 && this.gt_group_size <=0 ){//开启虚拟成团
  849. return self.$message.error("请正确填写虚拟成团的参团人数");
  850. }
  851. if (this.is_virtual && this.virtual_group_type == 2 && this.gt_group_size > this.group_size) {
  852. return self.$message.error("虚拟成团参团人数不能大于拼团人数");
  853. }
  854. }else{
  855. //没有开启高级设置 把高级设置里面的参数设置为默认?
  856. this.purchase = 2; //不限购
  857. this.isAll = 1; //全部用户
  858. this.isAll_C = 1; //全部用户
  859. this.is_virtual = 0;//是否虚拟成团
  860. this.virtual_group_type = 1;
  861. this.sendStatus = 0
  862. }
  863. let commander_level_limit;
  864. let user_level_limit;
  865. if(this.isAll == 1){
  866. user_level_limit = 'all';
  867. }else if(this.isAll == 2){
  868. user_level_limit = this.checkedCities.join(',')
  869. }
  870. if(this.isAll_C == 1){
  871. commander_level_limit = 'all';
  872. }else if(this.isAll_C == 2){
  873. commander_level_limit = this.checkedCities_C.join(',')
  874. }
  875. let group_buy_goods = {
  876. "title": self.title,
  877. "cate_id": self.cate_id,
  878. "start_at": self.start_at, //开始时间
  879. "end_at": self.end_at, //结束时间
  880. "effective_time": self.continuedTime, //有效时间分钟数
  881. "group_size": self.group_size, //成团人数
  882. "virtual_group_size": self.virtual_group_size, //虚拟成团人数
  883. "is_virtual": self.is_virtual, //是否虚拟成团
  884. "goods_id": self.groupGoodsId, //商品id
  885. "goods_stock": self.goods_stock, //拼团商品总库存
  886. "limit_buy_num":self.purchase == 2?0:self.limit_buy_num,//购买数量限制 0=不限制
  887. 'commander_level_limit': commander_level_limit, //团长等级限制 或者全部用户all
  888. 'user_level_limit': user_level_limit, //团员等级限制 或者全部用户all
  889. "restrict_rule_num": self.is_restrict_rule === 0 ? 0 : self.restrict_rule_num, // 限制参团次数 0 不限制 1限制;
  890. "virtual_group_type":self.virtual_group_type,//虚拟成团类型 1=全部 2=成团人数大于
  891. "gt_group_size":self.gt_group_size,//拼团人数大于N,则虚拟成团,
  892. "is_initiator_free":self.is_initiator_free,// 发起人免费开团
  893. "is_show_participant_nickname":self.is_show_participant_nickname,// 是否显示参团人员昵称
  894. "is_show_virtual_avatar":self.is_show_virtual_avatar,// 是否显示虚拟人数头像
  895. };
  896. switch (self.sendStatus) {
  897. case 1:
  898. group_buy_goods['give_score'] = self.give_score;
  899. break;
  900. case 2:
  901. group_buy_goods['give_balance'] = self.give_balance
  902. break;
  903. case 3:
  904. group_buy_goods['send_red_packet'] = self.send_red_packet
  905. break;
  906. }
  907. if (group_buy_goods.virtual_group_type == 3) {
  908. group_buy_goods.virtual_group_sub_type = self.virtual_group_sub_type // "参团结束开团" 出现的选项
  909. group_buy_goods.expired_auto_complete_min_num = self.expired_auto_complete_min_num // 当参团人数≥ x 人,拼团有效期结束后,自动成团
  910. }
  911. // 如果是单规格商品
  912. request({
  913. params: {
  914. r: this.store_url
  915. },
  916. method: 'post',
  917. data: {
  918. form: self.cForm,
  919. group_buy_goods: group_buy_goods
  920. }
  921. }).then(e => {
  922. self.btnLoading = false;
  923. self.goods_stock = 0;
  924. if (e.data.code === 0) {
  925. //保存成功
  926. self.$message.success(e.data.msg);
  927. navigateTo({
  928. r: this.referrer,
  929. })
  930. } else {
  931. self.$message.error(e.data.msg);
  932. }
  933. }).catch(e => {
  934. console.log(e);
  935. });
  936. },
  937. validate(){
  938. let self = this;
  939. try {
  940. if (self.title === '') throw new Error('请输入拼团活动名称');
  941. //单规格拼团价赋值
  942. if (self.cForm.use_attr == 0) {
  943. if (!self.groupGoodsId) throw new Error('请选择拼团商品');
  944. self.cForm.attr[0].group_buy_price = self.cForm.group_buy_price;
  945. }
  946. if(self.cForm.group_buy_price <= 0){
  947. throw new Error('拼团价格不能为0');
  948. }
  949. self.cForm.attr.map(item => {
  950. if (item.price < 0 || item.price === '') throw new Error('规格价格不能为空');
  951. if (item.stock < 0 || item.stock === '') throw new Error('库存不能为空');
  952. if (!item.group_buy_price || item.group_buy_price <= 0 || item.group_buy_price === '') throw new Error('拼团价不能为0或者空');
  953. if ( parseFloat(item.group_buy_price) > parseFloat(item.price)) throw new Error('拼团价不能大于售价');/* self.moreAttrs && */
  954. })
  955. if (!self.groupGoodsId) throw new Error('请选择拼团商品');
  956. // if (!self.valueDay || !self.valueTime || (!self.continuedHouse && !self.continuedMinute) || !self.group_size) throw new Error('请设置拼团相关信息');
  957. if (!self.start_at || !self.end_at || (!self.continuedHouse && !self.continuedMinute) || !self.group_size) throw new Error('请设置拼团相关信息');
  958. if (parseInt(self.cForm.group_buy_price) > parseInt(self.cForm.price) && (!self.moreAttrs)) throw new Error('拼团价不能高于售价');
  959. // 获取拼团持续分钟数
  960. self.getContinuedTime(self.continuedHouse, self.continuedMinute);
  961. self.getGroupStartDate(self.valueDay, self.valueTime);
  962. let startTimeStr = new Date(self.groupStartDate).getTime(); //活动开始时间时间戳
  963. let endTimeStr = new Date(self.groupEndDate).getTime(); //活动开始时间时间戳
  964. // 获取当前时间戳
  965. let nowTime = new Date();
  966. let nowTimeStr = nowTime.getTime();
  967. if (self.cForm.use_attr == 0 && self.goods_stock == 0) throw new Error('总库存不能为0');
  968. if (startTimeStr < nowTimeStr) throw new Error('开团时间不能早于当前时间');
  969. if (self.continuedTime < 15) throw new Error('拼团有效时间不能低于15分钟');
  970. if (self.group_size < 2 || self.group_size > 100) throw new Error('拼团人数需为2-100人');
  971. if (self.cate_id == 0) throw new Error('请选择拼团分类');
  972. //if (self.is_virtual == 1 && self.virtual_group_size < 2) throw new Error('虚拟成团人数不能少于2人');
  973. return true;
  974. } catch (error) {
  975. self.$message.error(error.message);
  976. return false;
  977. }
  978. },
  979. // 设置获取到的拼团商品信息
  980. setGroupBuyGoodsData(groupBuyGoods) {
  981. let self = this;
  982. let timeArr = groupBuyGoods.start_at.trim().split(" ");
  983. self.valueDay = timeArr[0];
  984. self.valueTime = timeArr[1];
  985. // console.log(valueDay+'111'+valueTime);
  986. self.continuedHouse = parseInt(groupBuyGoods.vaild_time / 60);
  987. self.continuedMinute = groupBuyGoods.vaild_time % 60;
  988. self.group_size = groupBuyGoods.people;
  989. self.is_virtual = groupBuyGoods.is_virtual;
  990. self.virtual_group_size = groupBuyGoods.virtual_group_size;
  991. },
  992. // 获取详情数据
  993. getGoodsList(id, url = '') {
  994. let self = this;
  995. // 存一下商品的id
  996. self.groupGoodsId = id;
  997. self.cardLoading = true;
  998. request({
  999. params: {
  1000. r: url ? url : this.get_goods_detail_url,
  1001. id: id,
  1002. },
  1003. method: 'get',
  1004. }).then(e => {
  1005. self.cardLoading = false;
  1006. if (e.data.code == 0) { //状态码判断是否请求成功
  1007. let detail = e.data.data.detail;
  1008. detail.attr.length > 1 ? self.moreAttrs = true : self.moreAttrs = false; //是否选中多规格商品
  1009. console.log('self.moreAttrs:'+self.moreAttrs);
  1010. if (self.formGoodsList.length > 0) {
  1011. this.goods_warehouse = {};
  1012. }
  1013. // 存一下商品的列表显示信息
  1014. let formGoods = {};
  1015. formGoods['goods_name'] = detail.goods_name;
  1016. formGoods['cover_pic'] = detail.cover_pic;
  1017. let formGoodsArr = [];
  1018. formGoodsArr.push(formGoods);
  1019. self.formGoodsList = formGoodsArr;
  1020. if (e.data.data.group_buy_goods) {
  1021. let groupBuyGoods = e.data.data.group_buy_goods;
  1022. self.setGroupBuyGoodsData(groupBuyGoods);
  1023. }
  1024. if (detail['use_attr'] === 0) { //单规格
  1025. detail['attr_groups'] = [];
  1026. }
  1027. if (this.form && this.form.extra) {
  1028. for (let i in this.form.extra) {
  1029. if (detail.use_attr == 1) {
  1030. for (let j in detail.attr) {
  1031. if (!detail.attr[j][i]) {
  1032. detail.attr[j][i] = 0;
  1033. }
  1034. }
  1035. }
  1036. Vue.set(self.ruleForm, i, 0);
  1037. }
  1038. }
  1039. if (detail.attr.length > 1) {
  1040. detail.attr.forEach(function(item, index) {
  1041. item.stock = 0;
  1042. });
  1043. }
  1044. self.ruleForm = Object.assign(self.ruleForm, detail);
  1045. // 初始化一下规格
  1046. self.attrGroups = e.data.data.detail.attr_groups;
  1047. self.ruleForm.group_buy_price = detail.attr[0].group_buy_price;
  1048. } else {
  1049. self.$message.error(e.data.msg);
  1050. }
  1051. }).catch(e => {
  1052. self.cardLoading = false;
  1053. console.log(e);
  1054. });
  1055. },
  1056. handleChange(value) {
  1057. this.cate_id = value;
  1058. },
  1059. // 选择商品(清空弹窗已有商品)
  1060. selectGoodsWarehouse(goods_warehouse) {
  1061. if(goods_warehouse.goods_stock <= 0){
  1062. this.$message.error('该商品的库存为0,请重新选择商品');
  1063. return
  1064. }
  1065. this.ruleForm.select_attr_groups = [];
  1066. this.getGoodsList(goods_warehouse.id, 'group-buy/default/goods-detail')
  1067. },
  1068. },
  1069. });
  1070. </script>