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. 元
  473. </el-radio>
  474. <div v-if="coupon_data.length > 2" class="more_btn flex flex-y-center flex-x-center" @click="showMore('coupon')">
  475. <div style="margin-right: 2px;" v-if="is_coupon_more">收起</div>
  476. <div style="margin-right: 2px;" v-else>更多</div>
  477. <i class="el-icon-arrow-down more_icon" :class="{show_more_icon:is_coupon_more}" style="font-size: 18px;"></i>
  478. </div>
  479. </el-form-item>
  480. <el-form-item v-if="senior_setting" label="发起人是否免费开团" prop="is_initiator_free">
  481. <el-switch v-model="is_initiator_free" :active-value="1" :inactive-value="0">
  482. </el-switch>
  483. </el-form-item>
  484. <el-form-item v-if="senior_setting" label="拼团详情是否显示参团人员昵称" prop="is_show_participant_nickname">
  485. <el-switch v-model="is_show_participant_nickname" :active-value="1" :inactive-value="0">
  486. </el-switch>
  487. </el-form-item>
  488. <!-- 是否开启虚拟成团 -->
  489. <el-form-item v-if="senior_setting" label="是否开启虚拟成团" prop="status">
  490. <div>
  491. <el-switch v-model="is_virtual" :active-value="1" :inactive-value="0">
  492. </el-switch>
  493. </div>
  494. <div style="margin-bottom: 10px;">
  495. <el-tag type="warning">开启模拟成团后,满足条件的团,系统将会模拟“匿名买家”凑满该团,仅需对真实拼团买家发货。建议合理开启,以提高成团率。</el-tag>
  496. </div>
  497. <div v-if="is_virtual&&senior_setting">
  498. <el-radio class="huiyuanRadio" v-model="virtual_group_type" :label="1">虚拟立即成团</el-radio>
  499. <el-radio class="huiyuanRadio" v-model="virtual_group_type" :label="3">参团结束成团</el-radio>
  500. <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>
  501. <div v-if="virtual_group_type == 3">
  502. <el-radio-group v-model="virtual_group_sub_type">
  503. <el-radio :label="0">当拼团有效期结束后,自动成团</el-radio>
  504. <el-radio :label="1">当参团人数≥
  505. <el-input v-model="expired_auto_complete_min_num" style="width: 80px;"></el-input>
  506. 人,拼团有效期结束后,自动成团
  507. <el-tooltip effect="dark" content="若参团人数 < 所设置的人数,则拼团失败,发起人支付的金额原路返回。" placement="top" style="position: absolute;">
  508. <i class="el-icon-question"></i>
  509. </el-tooltip>
  510. </el-radio>
  511. </el-radio-group>
  512. </div>
  513. </div>
  514. <!-- 是否显示虚拟成团人的头像 -->
  515. <el-form-item v-if="is_virtual && virtual_group_type == 3 && senior_setting" label="是否显示虚拟成团人的头像" prop="is_show_virtual_avatar" label-width="200">
  516. <div>
  517. <el-switch v-model="is_show_virtual_avatar" :active-value="1" :inactive-value="0">
  518. </el-switch>
  519. </div>
  520. </el-form-item>
  521. </el-form-item>
  522. </template>
  523. </el-col>
  524. </el-row>
  525. </el-card>
  526. </el-tab-pane>
  527. <slot name="tab_pane"></slot>
  528. </el-tabs>
  529. </el-form>
  530. <div class="bottom-div" flex="cross:center" v-if="is_save_btn == 1" style="margin-top: 10px;">
  531. <el-button class="button-item" :loading="btnLoading" type="primary" size="small" @click="store('ruleForm')">保存
  532. </el-button>
  533. </div>
  534. </div>
  535. </el-card>
  536. </template>
  537. <script>
  538. Vue.component('group-com-goods', {
  539. template: '#abc',
  540. props: {
  541. // 规格库存
  542. is_attr: {
  543. type: Number,
  544. default: 1
  545. },
  546. //todo 仅显示售价(抽奖) 秒杀3显示
  547. is_price: {
  548. type: Number,
  549. default: 0
  550. },
  551. // 添加数据接口
  552. store_url: {
  553. type: String,
  554. default: 'group-buy/default/add'
  555. },
  556. // 请求数据地址--获取详情
  557. get_goods_detail_url: {
  558. type: String,
  559. default: 'group-buy/index/show'
  560. },
  561. // 保存之后返回地址
  562. referrer: {
  563. default: 'group-buy/default/index'
  564. },
  565. // 页面上数据
  566. form: Object,
  567. // 数据验证方式
  568. rule: Object,
  569. is_save_btn: {
  570. type: Number,
  571. default: 1
  572. }
  573. },
  574. data() {
  575. let ruleForm = {
  576. labels: [],
  577. attr: [],
  578. use_attr: 0,
  579. group_buy_price: '',
  580. select_attr_groups: [], // 已选择的规格
  581. goodsWarehouse_attrGroups: [], // 商品库商品所有的规格
  582. share_level_type: 0,
  583. };
  584. let rules = {
  585. };
  586. return {
  587. value1: '',
  588. goodsIndexUrl: 'group-buy/default/goods-list',
  589. title: '', //拼团活动名称
  590. formGoodsList: [], //选中的商品数组(最多只能选一个)
  591. moreAttrs: true, //默认选中多规格商品
  592. goods_stock: 0, //拼团商品总库存
  593. groupGoodsId: '', //拼团商品id
  594. valueDay: '', //添加拼团商品开始日期
  595. valueTime: '', //添加拼团具体时间
  596. groupStartDate: '', //拼团活动开始时刻
  597. groupEndDate: '', //拼团活动结束时间
  598. continuedHouse: '', //拼团小时数
  599. continuedMinute: '', //拼团分钟数
  600. continuedTime: '', //拼团活动持续时间
  601. group_size: 0, //成团所需人数
  602. senior_setting: 0, //默认不开启虚拟成团
  603. virtual_group_size: 0, //虚拟成团人数
  604. is_virtual: 0, //是否虚拟成团
  605. sendStatus: 0,
  606. give_score: 0, //团长送积分
  607. give_balance: 0, //团长送余额
  608. send_red_packet: 0, //送红包
  609. limit_buy_num:'',//限制购买数量 0=不限制
  610. goods_id: 0,
  611. cardLoading: false,
  612. btnLoading: false,
  613. activeName: 'first',
  614. ruleForm: ruleForm,
  615. attrGroups: [], //规格组
  616. dialogCoupon:false,
  617. couponLoading:false,
  618. couponKeyword: '',
  619. coupon_delete: [], //删除了的优惠券数据
  620. coupon_total: 0, //优惠券发放总数
  621. cou_tableData: [],
  622. coupon_data: [],
  623. dialog_total_count: 0,
  624. page: 1,
  625. level_arr: [],
  626. level_index: 0,
  627. level_id: '',
  628. coupon_test: [],
  629. loading:false,
  630. is_coupon_more: false,
  631. staging_arr: [],
  632. activeTime:'',
  633. purchase:2,// 1限购 2不限购
  634. memberLevel:[],//会员等级列表
  635. is_restrict_rule: 0, // 0 不限制参团规则 1限制参团规则
  636. restrict_rule_num: 0, // 限制参团次数
  637. cateList:[],//分类列表,
  638. cate_name: '',
  639. cate_id: 0,
  640. checkAll: true,
  641. checkAll_C: true,
  642. checkedCities: [],
  643. checkedCities_C: [],
  644. isIndeterminate: false,
  645. isIndeterminate_C: false,
  646. virtual_group_type:1,//虚拟成团类型 1=全部 2=成团人数大于
  647. gt_group_size:0,//拼团人数大于N,则虚拟成团
  648. isAll:1,//1指定全部会员购买 2指定等级购买
  649. isAll_C:1,//1指定全部会员购买 2指定等级购买
  650. is_initiator_free: 0, // 发起人免费开团
  651. virtual_group_sub_type: 0, // "参团结束开团" 出现的选项
  652. expired_auto_complete_min_num: 0, // 当参团人数≥ x 人,拼团有效期结束后,自动成团
  653. is_show_participant_nickname: 0, // 是否显示参团人员昵称
  654. is_show_virtual_avatar: 1, // 是否显示虚拟拼团头像
  655. };
  656. },
  657. created() {
  658. if (getQuery('id')) {
  659. this.getGoodsList(getQuery('id'));
  660. this.goods_id = getQuery('id');
  661. }
  662. this.getMemberLevel();
  663. this.getGroupCateList();
  664. },
  665. watch: {
  666. 'ruleForm.detail'(newVal, oldVal) {
  667. this.cForm.detail = newVal
  668. },
  669. 'attrGroups'(newVal, oldVal) {
  670. this.ruleForm.use_attr = newVal.length === 0 ? 0 : 1;
  671. },
  672. 'ruleForm.is_level'(newVal, oldVal) {
  673. if (newVal === 0) {
  674. this.ruleForm.is_level_alone = 0;
  675. }
  676. },
  677. },
  678. // 这里有用到计算属性
  679. computed: {
  680. cForm() {
  681. let form = {};
  682. let ruleForm = JSON.parse(JSON.stringify(this.ruleForm));
  683. if (this.form) {
  684. form = Object.assign(ruleForm, JSON.parse(JSON.stringify(this.form)));
  685. } else {
  686. form = ruleForm;
  687. }
  688. if (getQuery('id')) {
  689. form.id = getQuery('id')
  690. }
  691. return form;
  692. },
  693. cRule() {
  694. return this.rules;
  695. },
  696. },
  697. methods: {
  698. changeInput(){
  699. var pattern = /^[1-9][0-9]*$/ // 正整数的正则表达式
  700. // 不符合正整数时
  701. if (!pattern.test(this.goods_stock)) {
  702. // input 框绑定的内容为空
  703. this.goods_stock = ''
  704. }
  705. },
  706. changeInput2(){
  707. var pattern = /^[0-9][0-9]*$/ // 正整数的正则表达式
  708. // 不符合正整数时
  709. if (!pattern.test(this.continuedHouse)) {
  710. // input 框绑定的内容为空
  711. this.continuedHouse = ''
  712. }
  713. },
  714. changeInput3(){
  715. var pattern = /^[0-9][0-9]*$/ // 正整数的正则表达式
  716. // 不符合正整数时
  717. if (!pattern.test(this.continuedMinute)) {
  718. // input 框绑定的内容为空
  719. this.continuedMinute = ''
  720. }
  721. },
  722. handleCheckAllChange(val) {
  723. let arr = [];
  724. this.memberLevel.forEach((item)=>{
  725. arr.push(item.level)
  726. })
  727. this.checkedCities = val ? arr : [];
  728. this.isIndeterminate = false;
  729. },
  730. handleCheckAllChange_C(val) {
  731. let arr = [];
  732. this.memberLevel.forEach((item)=>{
  733. arr.push(item.level)
  734. })
  735. this.checkedCities_C = val ? arr : [];
  736. this.isIndeterminate_C = false;
  737. },
  738. handleCheckedCitiesChange(value) {
  739. let checkedCount = value.length;
  740. this.checkAll = checkedCount === this.memberLevel.length;
  741. this.isIndeterminate = checkedCount > 0 && checkedCount < this.memberLevel.length;
  742. },
  743. handleCheckedCitiesChange_C(value) {
  744. let checkedCount = value.length;
  745. this.checkAll_C = checkedCount === this.memberLevel.length;
  746. this.isIndeterminate_C = checkedCount > 0 && checkedCount < this.memberLevel.length;
  747. },
  748. // 会员等级列表
  749. getMemberLevel() {
  750. let self = this;
  751. request({
  752. params: {
  753. r: 'group-buy/default/user-level-list',
  754. page: 1,
  755. },
  756. method: 'get',
  757. }).then(e => {
  758. if (e.data.code === 0) {
  759. this.memberLevel = e.data.data.list;
  760. this.memberLevel.forEach((item)=>{
  761. this.checkedCities.push(item.level)
  762. this.checkedCities_C.push(item.level)
  763. })
  764. } else {
  765. self.$message.error(e.data.msg);
  766. }
  767. }).catch(e => {
  768. console.log(e);
  769. });
  770. },
  771. getGroupCateList() {
  772. let self = this;
  773. request({
  774. params: {
  775. r: 'group-buy/default/cate-list',
  776. page: 1,
  777. },
  778. method: 'get',
  779. }).then(e => {
  780. if (e.data.code === 0) {
  781. this.cateList = e.data.data.list;
  782. } else {
  783. self.$message.error(e.data.msg);
  784. }
  785. }).catch(e => {
  786. console.log(e);
  787. });
  788. },
  789. datetimeChange(){
  790. if(this.activeTime){
  791. this.start_at = this.activeTime[0];
  792. this.end_at = this.activeTime[1];
  793. }else{
  794. this.start_at = '';
  795. this.end_at = '';
  796. }
  797. },
  798. //拼团活动时间设置
  799. setActivityTime(params) {
  800. let begin = params[0];
  801. let end = params[1];
  802. self.groupStartDate = dateFormat('YYYY-mm-dd HH:MM:SS',begin);
  803. self.groupEndDate = dateFormat('YYYY-mm-dd HH:MM:SS',end);
  804. console.log(self.groupStartDate,self.groupEndDate)
  805. },
  806. // 0.0.1 删除选中商品
  807. delGoods() {
  808. this.formGoodsList = [];
  809. this.goods_warehouse = {};
  810. location.reload(); //刷新当前页
  811. },
  812. // 0.1 获取拼团开始时间 2020-08-07 00:00:00
  813. getGroupStartDate(valueDay, valueTime) {
  814. let self = this;
  815. self.groupStartDate = valueDay + ' ' + valueTime;
  816. },
  817. // 0.2 获取拼团持续分钟数 -''做乘法运算返回0
  818. getContinuedTime(continuedHouse, continuedMinute) {
  819. let self = this;
  820. self.continuedTime = continuedHouse * 60 + continuedMinute * 1;
  821. console.log(self.continuedTime);
  822. },
  823. store(formName) {
  824. self = this;
  825. let total_stock = 0
  826. this.$refs.commAttrs.cData.forEach(item => { total_stock += parseInt(item.stock) })
  827. if(total_stock==0){
  828. total_stock = this.goods_stock;
  829. }
  830. if (total_stock < this.group_size) {
  831. return self.$message.error("拼团商品总库存必须大于成团人数");
  832. }
  833. $res = this.validate();
  834. if($res === false) return false;
  835. if(this.senior_setting){//高级设置开启了
  836. // 判断是否开启了参团限制
  837. if (this.is_restrict_rule == 1 && this.restrict_rule_num <= 0) {
  838. return self.$message.error("请输入参团数量");
  839. }
  840. if(this.purchase == 1 && this.limit_buy_num <= 0){//限购 并且 没有填写限购数量
  841. return self.$message.error("请正确填写限购数量");
  842. }
  843. if(this.isAll == 2 && this.checkedCities.length == 0){//指定用户 没有勾选用户
  844. return self.$message.error("请勾选指定团长等级");
  845. }
  846. if(this.isAll_C == 2 && this.checkedCities_C.length == 0){//指定用户 没有勾选用户
  847. return self.$message.error("请勾选指定团员等级");
  848. }
  849. if(this.is_virtual && this.virtual_group_type == 2 && this.gt_group_size <=0 ){//开启虚拟成团
  850. return self.$message.error("请正确填写虚拟成团的参团人数");
  851. }
  852. if (this.is_virtual && this.virtual_group_type == 2 && this.gt_group_size > this.group_size) {
  853. return self.$message.error("虚拟成团参团人数不能大于拼团人数");
  854. }
  855. }else{
  856. //没有开启高级设置 把高级设置里面的参数设置为默认?
  857. this.purchase = 2; //不限购
  858. this.isAll = 1; //全部用户
  859. this.isAll_C = 1; //全部用户
  860. this.is_virtual = 0;//是否虚拟成团
  861. this.virtual_group_type = 1;
  862. this.sendStatus = 0
  863. }
  864. let commander_level_limit;
  865. let user_level_limit;
  866. if(this.isAll == 1){
  867. user_level_limit = 'all';
  868. }else if(this.isAll == 2){
  869. user_level_limit = this.checkedCities.join(',')
  870. }
  871. if(this.isAll_C == 1){
  872. commander_level_limit = 'all';
  873. }else if(this.isAll_C == 2){
  874. commander_level_limit = this.checkedCities_C.join(',')
  875. }
  876. let group_buy_goods = {
  877. "title": self.title,
  878. "cate_id": self.cate_id,
  879. "start_at": self.start_at, //开始时间
  880. "end_at": self.end_at, //结束时间
  881. "effective_time": self.continuedTime, //有效时间分钟数
  882. "group_size": self.group_size, //成团人数
  883. "virtual_group_size": self.virtual_group_size, //虚拟成团人数
  884. "is_virtual": self.is_virtual, //是否虚拟成团
  885. "goods_id": self.groupGoodsId, //商品id
  886. "goods_stock": self.goods_stock, //拼团商品总库存
  887. "limit_buy_num":self.purchase == 2?0:self.limit_buy_num,//购买数量限制 0=不限制
  888. 'commander_level_limit': commander_level_limit, //团长等级限制 或者全部用户all
  889. 'user_level_limit': user_level_limit, //团员等级限制 或者全部用户all
  890. "restrict_rule_num": self.is_restrict_rule === 0 ? 0 : self.restrict_rule_num, // 限制参团次数 0 不限制 1限制;
  891. "virtual_group_type":self.virtual_group_type,//虚拟成团类型 1=全部 2=成团人数大于
  892. "gt_group_size":self.gt_group_size,//拼团人数大于N,则虚拟成团,
  893. "is_initiator_free":self.is_initiator_free,// 发起人免费开团
  894. "is_show_participant_nickname":self.is_show_participant_nickname,// 是否显示参团人员昵称
  895. "is_show_virtual_avatar":self.is_show_virtual_avatar,// 是否显示虚拟人数头像
  896. };
  897. switch (self.sendStatus) {
  898. case 1:
  899. group_buy_goods['give_score'] = self.give_score;
  900. break;
  901. case 2:
  902. group_buy_goods['give_balance'] = self.give_balance
  903. break;
  904. case 3:
  905. group_buy_goods['send_red_packet'] = self.send_red_packet
  906. break;
  907. }
  908. if (group_buy_goods.virtual_group_type == 3) {
  909. group_buy_goods.virtual_group_sub_type = self.virtual_group_sub_type // "参团结束开团" 出现的选项
  910. group_buy_goods.expired_auto_complete_min_num = self.expired_auto_complete_min_num // 当参团人数≥ x 人,拼团有效期结束后,自动成团
  911. }
  912. // 如果是单规格商品
  913. request({
  914. params: {
  915. r: this.store_url
  916. },
  917. method: 'post',
  918. data: {
  919. form: self.cForm,
  920. group_buy_goods: group_buy_goods
  921. }
  922. }).then(e => {
  923. self.btnLoading = false;
  924. self.goods_stock = 0;
  925. if (e.data.code === 0) {
  926. //保存成功
  927. self.$message.success(e.data.msg);
  928. navigateTo({
  929. r: this.referrer,
  930. })
  931. } else {
  932. self.$message.error(e.data.msg);
  933. }
  934. }).catch(e => {
  935. console.log(e);
  936. });
  937. },
  938. validate(){
  939. let self = this;
  940. try {
  941. if (self.title === '') throw new Error('请输入拼团活动名称');
  942. //单规格拼团价赋值
  943. if (self.cForm.use_attr == 0) {
  944. if (!self.groupGoodsId) throw new Error('请选择拼团商品');
  945. self.cForm.attr[0].group_buy_price = self.cForm.group_buy_price;
  946. }
  947. if(self.cForm.group_buy_price <= 0){
  948. throw new Error('拼团价格不能为0');
  949. }
  950. self.cForm.attr.map(item => {
  951. if (item.price < 0 || item.price === '') throw new Error('规格价格不能为空');
  952. if (item.stock < 0 || item.stock === '') throw new Error('库存不能为空');
  953. if (!item.group_buy_price || item.group_buy_price <= 0 || item.group_buy_price === '') throw new Error('拼团价不能为0或者空');
  954. if ( parseFloat(item.group_buy_price) > parseFloat(item.price)) throw new Error('拼团价不能大于售价');/* self.moreAttrs && */
  955. })
  956. if (!self.groupGoodsId) throw new Error('请选择拼团商品');
  957. // if (!self.valueDay || !self.valueTime || (!self.continuedHouse && !self.continuedMinute) || !self.group_size) throw new Error('请设置拼团相关信息');
  958. if (!self.start_at || !self.end_at || (!self.continuedHouse && !self.continuedMinute) || !self.group_size) throw new Error('请设置拼团相关信息');
  959. if (parseInt(self.cForm.group_buy_price) > parseInt(self.cForm.price) && (!self.moreAttrs)) throw new Error('拼团价不能高于售价');
  960. // 获取拼团持续分钟数
  961. self.getContinuedTime(self.continuedHouse, self.continuedMinute);
  962. self.getGroupStartDate(self.valueDay, self.valueTime);
  963. let startTimeStr = new Date(self.groupStartDate).getTime(); //活动开始时间时间戳
  964. let endTimeStr = new Date(self.groupEndDate).getTime(); //活动开始时间时间戳
  965. // 获取当前时间戳
  966. let nowTime = new Date();
  967. let nowTimeStr = nowTime.getTime();
  968. if (self.cForm.use_attr == 0 && self.goods_stock == 0) throw new Error('总库存不能为0');
  969. if (startTimeStr < nowTimeStr) throw new Error('开团时间不能早于当前时间');
  970. if (self.continuedTime < 15) throw new Error('拼团有效时间不能低于15分钟');
  971. if (self.group_size < 2 || self.group_size > 100) throw new Error('拼团人数需为2-100人');
  972. if (self.cate_id == 0) throw new Error('请选择拼团分类');
  973. //if (self.is_virtual == 1 && self.virtual_group_size < 2) throw new Error('虚拟成团人数不能少于2人');
  974. return true;
  975. } catch (error) {
  976. self.$message.error(error.message);
  977. return false;
  978. }
  979. },
  980. // 设置获取到的拼团商品信息
  981. setGroupBuyGoodsData(groupBuyGoods) {
  982. let self = this;
  983. let timeArr = groupBuyGoods.start_at.trim().split(" ");
  984. self.valueDay = timeArr[0];
  985. self.valueTime = timeArr[1];
  986. // console.log(valueDay+'111'+valueTime);
  987. self.continuedHouse = parseInt(groupBuyGoods.vaild_time / 60);
  988. self.continuedMinute = groupBuyGoods.vaild_time % 60;
  989. self.group_size = groupBuyGoods.people;
  990. self.is_virtual = groupBuyGoods.is_virtual;
  991. self.virtual_group_size = groupBuyGoods.virtual_group_size;
  992. },
  993. // 获取详情数据
  994. getGoodsList(id, url = '') {
  995. let self = this;
  996. // 存一下商品的id
  997. self.groupGoodsId = id;
  998. self.cardLoading = true;
  999. request({
  1000. params: {
  1001. r: url ? url : this.get_goods_detail_url,
  1002. id: id,
  1003. },
  1004. method: 'get',
  1005. }).then(e => {
  1006. self.cardLoading = false;
  1007. if (e.data.code == 0) { //状态码判断是否请求成功
  1008. let detail = e.data.data.detail;
  1009. detail.attr.length > 1 ? self.moreAttrs = true : self.moreAttrs = false; //是否选中多规格商品
  1010. console.log('self.moreAttrs:'+self.moreAttrs);
  1011. if (self.formGoodsList.length > 0) {
  1012. this.goods_warehouse = {};
  1013. }
  1014. // 存一下商品的列表显示信息
  1015. let formGoods = {};
  1016. formGoods['goods_name'] = detail.goods_name;
  1017. formGoods['cover_pic'] = detail.cover_pic;
  1018. let formGoodsArr = [];
  1019. formGoodsArr.push(formGoods);
  1020. self.formGoodsList = formGoodsArr;
  1021. if (e.data.data.group_buy_goods) {
  1022. let groupBuyGoods = e.data.data.group_buy_goods;
  1023. self.setGroupBuyGoodsData(groupBuyGoods);
  1024. }
  1025. if (detail['use_attr'] === 0) { //单规格
  1026. detail['attr_groups'] = [];
  1027. }
  1028. if (this.form && this.form.extra) {
  1029. for (let i in this.form.extra) {
  1030. if (detail.use_attr == 1) {
  1031. for (let j in detail.attr) {
  1032. if (!detail.attr[j][i]) {
  1033. detail.attr[j][i] = 0;
  1034. }
  1035. }
  1036. }
  1037. Vue.set(self.ruleForm, i, 0);
  1038. }
  1039. }
  1040. if (detail.attr.length > 1) {
  1041. detail.attr.forEach(function(item, index) {
  1042. item.stock = 0;
  1043. });
  1044. }
  1045. self.ruleForm = Object.assign(self.ruleForm, detail);
  1046. // 初始化一下规格
  1047. self.attrGroups = e.data.data.detail.attr_groups;
  1048. self.ruleForm.group_buy_price = detail.attr[0].group_buy_price;
  1049. } else {
  1050. self.$message.error(e.data.msg);
  1051. }
  1052. }).catch(e => {
  1053. self.cardLoading = false;
  1054. console.log(e);
  1055. });
  1056. },
  1057. handleChange(value) {
  1058. this.cate_id = value;
  1059. },
  1060. // 选择商品(清空弹窗已有商品)
  1061. selectGoodsWarehouse(goods_warehouse) {
  1062. if(goods_warehouse.goods_stock <= 0){
  1063. this.$message.error('该商品的库存为0,请重新选择商品');
  1064. return
  1065. }
  1066. this.ruleForm.select_attr_groups = [];
  1067. this.getGoodsList(goods_warehouse.id, 'group-buy/default/goods-detail')
  1068. },
  1069. },
  1070. });
  1071. </script>