baseInfo.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <template>
  2. <div>
  3. <el-alert
  4. title="基础信息"
  5. type="info"
  6. :closable="false"
  7. class="baseMsg"
  8. ></el-alert>
  9. <div class="m-core">
  10. <el-form
  11. :label-position="labelPosition"
  12. :model="baseForm"
  13. ref="vipform"
  14. label-width="140px"
  15. :rules="vipformRules"
  16. class="vipform"
  17. >
  18. <el-form-item label="活动名称" prop="name">
  19. <el-input
  20. style="width: 400px"
  21. v-model.trim="baseForm.name"
  22. :disabled="isDisabled || status != 'DRAFT'"
  23. ></el-input>
  24. </el-form-item>
  25. <!-- @visible-change="$forceUpdate()" -->
  26. <el-form-item label="适用分部" prop="organ">
  27. <select-all
  28. v-model.trim="baseForm.organ"
  29. style="width: 400px"
  30. multiple
  31. filterable
  32. @change="onOrganChange"
  33. clearable
  34. :disabled="isDisabled || status != 'DRAFT'"
  35. >
  36. <el-option
  37. v-for="(item, index) in selects.branchs"
  38. :key="index"
  39. :label="item.name"
  40. :value="item.id"
  41. ></el-option>
  42. </select-all>
  43. <!-- <el-button @click="onCheckAllBranch">适用所有分部</el-button> -->
  44. </el-form-item>
  45. <el-form-item label="活动描述" prop="description">
  46. <el-input
  47. type="textarea"
  48. v-model.trim="baseForm.description"
  49. style="width: 400px"
  50. :rows="5"
  51. placeholder="请输入活动说明"
  52. :disabled="isDisabled || status != 'DRAFT'"
  53. ></el-input>
  54. </el-form-item>
  55. <el-form-item label="活动类型" prop="activityType">
  56. <el-select
  57. v-model.trim="baseForm.activityType"
  58. placeholder="请选择活动类型"
  59. clearable
  60. style="width: 400px !important"
  61. @change="changeActivityType"
  62. :disabled="isDisabled || status != 'DRAFT'"
  63. >
  64. <el-option label="课程活动" :value="0"></el-option>
  65. <el-option label="会员活动" :value="1"></el-option>
  66. </el-select>
  67. </el-form-item>
  68. <el-form-item label="活动生效时间" prop="activeTime">
  69. <el-date-picker
  70. :disabled="isDisabled"
  71. v-model.trim="baseForm.activeTime"
  72. type="datetimerange"
  73. :default-time="['00:00:00', '23:59:59']"
  74. range-separator="至"
  75. value-format="yyyy-MM-dd HH:mm:ss"
  76. start-placeholder="开始日期"
  77. :picker-options="{
  78. firstDayOfWeek: 1,
  79. }"
  80. end-placeholder="结束日期"
  81. ></el-date-picker>
  82. <el-tooltip placement="top" popper-class="mTooltip">
  83. <div slot="content">
  84. 可通过该方案购买课程的时间范围,到达开始时间才可购买,到达结束时间后不可购买,不填则不限制且立即生效
  85. </div>
  86. <i
  87. class="el-icon-question micon el-tooltip"
  88. style="font-size: 18px; color: #f56c6c"
  89. ></i>
  90. </el-tooltip>
  91. </el-form-item>
  92. <el-form-item label="排课时间范围" prop="courseTime">
  93. <el-date-picker
  94. :disabled="isDisabled"
  95. v-model.trim="baseForm.courseTime"
  96. type="datetimerange"
  97. :default-time="['00:00:00', '23:59:59']"
  98. range-separator="至"
  99. value-format="yyyy-MM-dd HH:mm:ss"
  100. start-placeholder="开始日期"
  101. :picker-options="{
  102. firstDayOfWeek: 1,
  103. }"
  104. end-placeholder="结束日期"
  105. ></el-date-picker>
  106. <el-tooltip placement="top" popper-class="mTooltip">
  107. <div slot="content">
  108. 通过该方案购买的课程排课时间不可超过该时间范围,不填则不限制
  109. </div>
  110. <i
  111. class="el-icon-question micon el-tooltip"
  112. style="font-size: 18px; color: #f56c6c"
  113. ></i>
  114. </el-tooltip>
  115. </el-form-item>
  116. <el-form-item label="适用学员" prop="applyToStudentType">
  117. <el-row>
  118. <el-col style="width: 400px">
  119. <select-all
  120. v-model.trim="baseForm.applyToStudentType"
  121. style="width: 400px"
  122. multiple
  123. filterable
  124. clearable
  125. placeholder="请选择适用学员"
  126. @change="applyToStudentTypeChange"
  127. :disabled="isDisabled"
  128. >
  129. <el-option label="新学员" value="1"></el-option>
  130. <el-option label="老学员" value="0"></el-option>
  131. <el-option label="会员" value="2"></el-option>
  132. <el-option label="非会员" value="3"></el-option>
  133. </select-all>
  134. </el-col>
  135. <el-tooltip placement="top" popper-class="mTooltip">
  136. <div slot="content">
  137. 可通过该方案购买课程的学员群体,不填则不限制
  138. </div>
  139. <i
  140. class="el-icon-question micon el-tooltip"
  141. style="font-size: 18px; color: #f56c6c; margin-left: 3px"
  142. ></i>
  143. </el-tooltip>
  144. </el-row>
  145. </el-form-item>
  146. <el-form-item label="可购买次数" prop="studentMaxUsedTimes">
  147. <el-input
  148. style="width: 400px"
  149. type="number"
  150. v-model.trim="baseForm.studentMaxUsedTimes"
  151. :disabled="isDisabled"
  152. >
  153. <template slot="append">次</template>
  154. </el-input>
  155. <el-tooltip placement="top" popper-class="mTooltip">
  156. <div slot="content">
  157. 学员可通购买该活动方案的次数限制,不填则不限制
  158. </div>
  159. <i
  160. class="el-icon-question micon el-tooltip"
  161. style="font-size: 18px; color: #f56c6c"
  162. ></i>
  163. </el-tooltip>
  164. </el-form-item>
  165. <el-form-item label="是否充值课程余额" prop="isPayToBalance">
  166. <el-select
  167. v-model.trim="baseForm.isPayToBalance"
  168. placeholder="请选择是否充值课程余额"
  169. clearable
  170. style="width: 400px !important"
  171. :disabled="isDisabled || status != 'DRAFT'"
  172. >
  173. <el-option label="课程余额" :value="1"></el-option>
  174. <el-option label="资格限制" :value="0"></el-option>
  175. </el-select>
  176. <el-tooltip placement="top" popper-class="mTooltip">
  177. <div slot="content">
  178. 课程余额:学员缴费金额进入课程余额,排课时扣减课程余额;若课程余额不足则不可排课
  179. 资格限制:学员缴费金额不进入课程余额,学员购买后增加可排课次数,排课后扣减可排课次数
  180. 会员活动默认为资格限制,不可修改
  181. </div>
  182. <i
  183. class="el-icon-question micon el-tooltip"
  184. style="font-size: 18px; color: #f56c6c"
  185. ></i>
  186. </el-tooltip>
  187. </el-form-item>
  188. </el-form>
  189. </div>
  190. </div>
  191. </template>
  192. <script>
  193. import { vipGroupCategory, addVipActive } from "@/api/vipSeting";
  194. import { getEmployeeOrgan } from "@/api/buildTeam";
  195. import { vipResetTypeList } from "@/utils/searchArray";
  196. import cleanDeep from "clean-deep";
  197. export default {
  198. props: ["baseForm", "isDisabled", "status"],
  199. name: "vipNewActive",
  200. data() {
  201. return {
  202. vipResetTypeList,
  203. pageType: "",
  204. labelPosition: "right",
  205. vipformRules: {
  206. name: [
  207. { required: true, message: "请输入活动名称", trigger: "blur" },
  208. {
  209. min: 1,
  210. max: 25,
  211. message: "长度在 1 到 25 个字符",
  212. trigger: "blur",
  213. },
  214. ],
  215. desc: [
  216. { required: true, message: "请输入文字描述", trigger: "blur" },
  217. {
  218. min: 1,
  219. max: 200,
  220. message: "长度在 1 到 200 个字符",
  221. trigger: "blur",
  222. },
  223. ],
  224. activityType: [
  225. { required: true, message: "请选择活动类型", trigger: "blur" },
  226. ],
  227. // activeTime: [
  228. // { required: false, message: "请选择活动时间", trigger: "blur" },
  229. // ],
  230. courseTime: [
  231. { required: false, message: "请选择课程时间", trigger: "blur" },
  232. ],
  233. studentMaxUsedTimes: [
  234. { required: false, message: "请输入购买次数", trigger: "blur" },
  235. ],
  236. organ: [{ required: true, message: "请选择适用分部", trigger: "blur" }],
  237. stauts: [
  238. { required: true, message: "请选择活动形式", trigger: "blur" },
  239. ],
  240. applyToStudentType: [{ required: true, message: "请选择是否新生专享" }],
  241. isPayToBalance: [{ required: true, message: "请选择是否支付到余额" }],
  242. allowOnlineToOffline: [
  243. { required: true, message: "请选择课程调整方式" },
  244. ],
  245. },
  246. courseStatusList: [], // 获取所有课程形式
  247. activeType: "",
  248. online: true,
  249. unonline: true,
  250. onlineSalary: "TEACHER_DEFAULT",
  251. unonlineSalary: "TEACHER_DEFAULT",
  252. onlineprice: "",
  253. unonlineprice: "",
  254. salaryReadonlyFlag: false,
  255. paymentReadonlyFlag: false,
  256. attribute1: "",
  257. attribute2: "",
  258. courseNumForm: {
  259. minCourseNum: "",
  260. maxCourseNum: "",
  261. studentMaxUsedTimes: "",
  262. },
  263. giveClassPaySalaryFlag: true,
  264. organList: [],
  265. onlineClassJoinGradientRewards: false,
  266. offlineClassJoinGradientRewards: false,
  267. courseNumrules: {
  268. minCourseNum: [
  269. { required: true, message: "请输入最小课时数", trigger: "blur" },
  270. { validator: this.validateCom, trigger: "blur" },
  271. { validator: this.validateMin, trigger: "blur" },
  272. ],
  273. maxCourseNum: [
  274. { required: true, message: "请输入最大课时数", trigger: "blur" },
  275. { validator: this.validateCom, trigger: "blur" },
  276. { validator: this.validateMax, trigger: "blur" },
  277. ],
  278. },
  279. };
  280. },
  281. async mounted() {
  282. // 首先获取课程形式
  283. // vipGroupCategory().then(res => {
  284. // if (res.code == 200) {
  285. // this.courseStatusList = res.data;
  286. // }
  287. // });
  288. // // 适用分部
  289. // getEmployeeOrgan().then(res => {
  290. // if (res.code == 200) {
  291. // this.organList = res.data;
  292. // }
  293. // });
  294. // 获取类型
  295. await this.$store.dispatch("setVipGroupCategory");
  296. // 获取分部
  297. await this.$store.dispatch("setBranchs");
  298. // this.onReSet();
  299. // if (this.$route.query.rules) {
  300. // this.rules = this.$route.query.rules;
  301. // }
  302. // if (this.$route.query.searchForm) {
  303. // this.searchForm = this.$route.query.searchForm;
  304. // }
  305. this.pageType = this.$route.query.type;
  306. if (!this.$route.query.id) {
  307. this.$refs.vipform.resetFields();
  308. }
  309. //
  310. },
  311. methods: {
  312. resetForm() {
  313. this.$refs.form.resetFields();
  314. },
  315. handleMinChange() {
  316. this.$refs.form.validateField("maxCourseNum");
  317. },
  318. handleMaxChange() {
  319. this.$refs.form.validateField("minCourseNum");
  320. },
  321. validateCom(rule, value, callback) {
  322. const one = Number(value);
  323. if (Number.isInteger(one)) {
  324. if (one < MIN_NUMBER) {
  325. return callback(new Error("输入值必须大于0"));
  326. } else if (one > MAX_NUMBER) {
  327. return callback(new Error("输入值必须小于999"));
  328. }
  329. return callback();
  330. }
  331. return callback(new Error("输入值必须为正整数"));
  332. },
  333. validateMin(rule, value, callback) {
  334. const one = Number(value);
  335. const max = Number(this.courseNumForm.maxCourseNum);
  336. if (!max || one <= max) {
  337. return callback();
  338. }
  339. return callback(new Error("输入值不得大于最大课时数"));
  340. },
  341. validateMax(rule, value, callback) {
  342. const one = Number(value);
  343. const min = Number(this.courseNumForm.minCourseNum);
  344. if (!min || one >= min) {
  345. return callback();
  346. }
  347. return callback(new Error("输入值不得小于最小课时数"));
  348. },
  349. changeStauts(val) {
  350. console.log(val);
  351. },
  352. changeActivityType(val) {
  353. this.$emit("resetPayInfo");
  354. },
  355. submitFrom() {
  356. this.$refs.form.validate((isok) => {
  357. if (isok) {
  358. this.$refs["vipform"].validate((valid) => {
  359. if (valid) {
  360. // 验证通过
  361. let coursesStartTime = null,
  362. coursesEndTime = null,
  363. startTime = null,
  364. endTime = null;
  365. if (
  366. this.vipform.courseTime &&
  367. this.vipform.courseTime.length > 0
  368. ) {
  369. coursesStartTime = this.vipform.courseTime[0];
  370. coursesEndTime = this.vipform.courseTime[1];
  371. }
  372. if (
  373. this.vipform.activeTime &&
  374. this.vipform.activeTime.length > 0
  375. ) {
  376. startTime = this.vipform.activeTime[0];
  377. endTime = this.vipform.activeTime[1];
  378. }
  379. let organId = this.vipform.organ.join(",");
  380. let type = this.activeType;
  381. if (!type) {
  382. this.$message.error("请选择活动类型");
  383. return;
  384. }
  385. if (!this.online && !this.unonline) {
  386. this.$message.error("请选择活动适用范围");
  387. return;
  388. }
  389. if (type == "DISCOUNT") {
  390. if (!this.attribute1 || this.attribute1 < 0) {
  391. this.$message.error("折扣必须大于等于0");
  392. return;
  393. }
  394. } else if (type == "GIVE_CLASS") {
  395. if (!this.attribute1) {
  396. this.$message.error("请输入多少节开始赠");
  397. return;
  398. }
  399. if (!this.attribute2) {
  400. this.$message.error("请输入赠送课时数");
  401. return;
  402. }
  403. }
  404. let vipGroupCategoryIdList = this.vipform.stauts.join(",");
  405. let onlineSalarySettlement;
  406. let offlineSalarySettlement;
  407. if (this.online) {
  408. // 勾选线上
  409. if (this.onlineSalary == "RATIO_DISCOUNT") {
  410. if (this.onlineprice < 0 || this.onlineprice > 100) {
  411. this.$message.error("折扣比必须大于0且小于100");
  412. return;
  413. }
  414. } else if (this.onlineSalary == "TEACHER_DEFAULT") {
  415. this.onlineprice = 0;
  416. }
  417. onlineSalarySettlement = {
  418. salarySettlementType: this.onlineSalary,
  419. settlementValue: this.onlineprice,
  420. };
  421. } else {
  422. onlineSalarySettlement = null;
  423. }
  424. if (this.unonline) {
  425. // 勾选线下
  426. if (this.unonlineSalary == "RATIO_DISCOUNT") {
  427. if (this.unonlineprice < 0 || this.unonlineprice > 100) {
  428. this.$message.error("折扣比必须大于0且小于100");
  429. return;
  430. }
  431. } else if (this.unonlineSalary == "TEACHER_DEFAULT") {
  432. this.unonlineprice = 0;
  433. }
  434. offlineSalarySettlement = {
  435. salarySettlementType: this.unonlineSalary,
  436. settlementValue: this.unonlineprice,
  437. };
  438. } else {
  439. offlineSalarySettlement = null;
  440. }
  441. let salaryReadonlyFlag = this.salaryReadonlyFlag * 1;
  442. let paymentReadonlyFlag = this.paymentReadonlyFlag * 1;
  443. // let giveClassPaySalaryFlag = this.giveClassPaySalaryFlag * 1;
  444. let vipGroupSalarySettlement = {
  445. onlineSalarySettlement,
  446. offlineSalarySettlement,
  447. };
  448. if (type == "BASE_ACTIVITY") {
  449. this.courseNumForm.studentMaxUsedTimes = -1;
  450. this.courseNumForm.minCourseNum = -1;
  451. this.courseNumForm.maxCourseNum = -1;
  452. } else if (type == "GIVE_CLASS") {
  453. this.courseNumForm.minCourseNum = -1;
  454. this.courseNumForm.maxCourseNum = -1;
  455. }
  456. // 发请求创建活动
  457. addVipActive(
  458. cleanDeep({
  459. coursesStartTime,
  460. coursesEndTime,
  461. startTime,
  462. endTime,
  463. name: this.vipform.name,
  464. description: this.vipform.desc,
  465. applyToStudentType: this.vipform.applyToStudentType,
  466. allowOnlineToOffline: this.vipform.allowOnlineToOffline,
  467. organId,
  468. type,
  469. vipGroupCategoryIdList,
  470. vipGroupSalarySettlement,
  471. salaryReadonlyFlag,
  472. paymentReadonlyFlag,
  473. giveClassPaySalaryFlag: 1,
  474. attribute1: this.attribute1,
  475. attribute2: this.attribute2,
  476. minCourseNum: this.courseNumForm.minCourseNum,
  477. maxCourseNum: this.courseNumForm.maxCourseNum,
  478. studentMaxUsedTimes: this.courseNumForm.studentMaxUsedTimes
  479. ? this.courseNumForm.studentMaxUsedTimes
  480. : -1,
  481. offlineClassJoinGradientRewards:
  482. this.offlineClassJoinGradientRewards * 1,
  483. onlineClassJoinGradientRewards:
  484. this.onlineClassJoinGradientRewards * 1,
  485. })
  486. ).then((res) => {
  487. if (res.code == 200) {
  488. this.$message.success("恭喜你,活动创建成功");
  489. // this.onReSet();
  490. this.$store.dispatch("delVisitedViews", this.$route);
  491. this.$router.push({
  492. path: "/vipActiveManager/vipActiveList",
  493. });
  494. }
  495. });
  496. } else {
  497. this.$nextTick(() => {
  498. let isError = document.getElementsByClassName("is-error");
  499. isError[0].scrollIntoView({
  500. block: "center",
  501. behavior: "smooth",
  502. });
  503. });
  504. // this.$message.error("请填写必要参数");
  505. }
  506. });
  507. }
  508. });
  509. // 线上线下课 勾选就传不勾选就不传
  510. // addVipActive().then(res => { })
  511. },
  512. onOrganChange() {
  513. // this.$forceUpdate();
  514. this.$refs.vipform.validateField("organ");
  515. this.$forceUpdate();
  516. },
  517. applyToStudentTypeChange() {
  518. this.$refs.vipform.validateField("applyToStudentType");
  519. this.$forceUpdate();
  520. },
  521. onCheckAllBranch() {
  522. // 选择所有分部
  523. let vipform = this.vipform;
  524. vipform.organ = [];
  525. this.selects.branchs.forEach((item) => {
  526. vipform.organ.push(item.id);
  527. });
  528. this.$refs.vipform.validateField("organ");
  529. this.$forceUpdate();
  530. },
  531. onReSet() {
  532. this.vipform = {
  533. name: "",
  534. desc: "",
  535. activeTime: [],
  536. courseTime: [],
  537. };
  538. this.activeType = "";
  539. this.online = true;
  540. this.unonline = true;
  541. this.salaryReadonlyFlag = false;
  542. this.onlineSalary = "TEACHER_DEFAULT";
  543. this.unonlineSalary = "TEACHER_DEFAULT";
  544. this.onlineprice = "";
  545. this.unonlineprice = "";
  546. this.onlineClassJoinGradientRewards = false;
  547. this.offlineClassJoinGradientRewards = false;
  548. this.attribute1 = "";
  549. this.attribute2 = "";
  550. this.courseNumForm.maxCourseNum = "";
  551. this.courseNumForm.minCourseNum = "";
  552. // this.$refs.vipform.resetFields();
  553. },
  554. },
  555. };
  556. </script>
  557. <style lang="scss" scoped>
  558. .baseMsg {
  559. margin: 30px 0;
  560. }
  561. .m-core {
  562. font-size: 14px;
  563. width: 100%;
  564. display: flex;
  565. flex-direction: column;
  566. justify-content: center;
  567. // text-align: center;
  568. .activeRange {
  569. display: flex;
  570. flex-direction: row;
  571. justify-content: flex-start;
  572. .left {
  573. height: 72px;
  574. line-height: 72px;
  575. }
  576. .right {
  577. .chioseWrap {
  578. display: flex;
  579. flex-direction: row;
  580. justify-content: flex-start;
  581. height: 72px;
  582. line-height: 72px;
  583. align-items: center;
  584. .el-checkbox {
  585. margin-right: 20px;
  586. }
  587. .el-select {
  588. margin-right: 20px;
  589. }
  590. }
  591. }
  592. }
  593. .activeType {
  594. display: flex;
  595. flex-direction: row;
  596. justify-content: flex-start;
  597. .left {
  598. margin-right: 20px;
  599. p {
  600. height: 40px;
  601. line-height: 40px;
  602. }
  603. }
  604. .right {
  605. > div {
  606. display: flex;
  607. flex-direction: row;
  608. justify-content: flex-start;
  609. height: 40px;
  610. line-height: 40px;
  611. margin-bottom: 20px;
  612. .head {
  613. width: 120px;
  614. height: 40px;
  615. line-height: 40px;
  616. border: 1px solid #ccc;
  617. text-align: center;
  618. border-radius: 5px;
  619. cursor: pointer;
  620. margin-right: 10px;
  621. }
  622. > .head.active {
  623. background-color: #13817a;
  624. color: #fff;
  625. border: none;
  626. }
  627. .title {
  628. line-height: 40px;
  629. height: 40px;
  630. }
  631. }
  632. }
  633. }
  634. }
  635. </style>
  636. <style lang="scss">
  637. .m-core {
  638. // .vipform {
  639. // .el-select {
  640. // .el-input__inner {
  641. // }
  642. // }
  643. // }
  644. .activeType {
  645. .right {
  646. .el-input {
  647. width: 150px !important;
  648. }
  649. }
  650. }
  651. }
  652. </style>