entryOperation.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <el-page-header @back="onCancel"
  5. :content="(pageType == 'create' ? '添加时间充值活动' : '查看时间充值活动')"></el-page-header>
  6. </h2>
  7. <div class="m-core">
  8. <el-form :model="form"
  9. :rules="rules"
  10. ref="form"
  11. label-width="120px"
  12. style="width: 100%">
  13. <el-form-item label="活动名称"
  14. prop="name">
  15. <el-input v-model.trim="form.name"
  16. placeholder="请输入活动名称"
  17. :disabled="pageType=='create'?false:true"></el-input>
  18. </el-form-item>
  19. <el-form-item label="适用范围"
  20. prop="suitableUser">
  21. <el-select v-model="form.suitableUser"
  22. :disabled="pageType=='create'?false:true"
  23. placeholder="请选择适用范围">
  24. <el-option label="全部"
  25. value="ALL"></el-option>
  26. <el-option label="新用户"
  27. value="NEW"></el-option>
  28. </el-select>
  29. </el-form-item>
  30. <el-form-item label="有效期"
  31. prop="date">
  32. <!-- <el-input v-model="form.memo"></el-input> -->
  33. <el-date-picker :disabled="pageType=='create'?false:true"
  34. v-model="form.date"
  35. type="datetimerange"
  36. :picker-options="{
  37. firstDayOfWeek:1
  38. }"
  39. :default-time="['00:00:00', '23:59:59']"
  40. align="right"
  41. unlink-panels
  42. value-format="yyyy-MM-dd HH:mm:ss"
  43. range-separator="至"
  44. start-placeholder="开始日期"
  45. end-placeholder="结束日期"></el-date-picker>
  46. </el-form-item>
  47. <!-- -->
  48. <el-form-item label="价格"
  49. prop="totalPrice">
  50. <el-input type="number"
  51. @mousewheel.native.prevent
  52. v-model.trim="form.totalPrice"
  53. placeholder="请输入价格"
  54. :disabled="pageType=='create'?false:true"></el-input>
  55. </el-form-item>
  56. <el-form-item label="折扣价"
  57. prop="discountPrice">
  58. <el-input type="number"
  59. @mousewheel.native.prevent
  60. v-model.trim="form.discountPrice"
  61. placeholder="请输入折价格"
  62. :disabled="pageType=='create'?false:true"></el-input>
  63. </el-form-item>
  64. <el-form-item label="购买分钟数"
  65. prop="purchaseMinutes">
  66. <el-input type="number"
  67. @mousewheel.native.prevent
  68. v-model.trim="form.purchaseMinutes"
  69. placeholder="请输入购买分钟"
  70. :disabled="pageType=='create'?false:true"></el-input>
  71. </el-form-item>
  72. <el-form-item label="赠送分钟数"
  73. prop="giveMinutes">
  74. <el-input type="number"
  75. @mousewheel.native.prevent
  76. v-model.trim="form.giveMinutes"
  77. placeholder="请输入赠送分钟"
  78. :disabled="pageType=='create'?false:true"></el-input>
  79. </el-form-item>
  80. <el-form-item label="活动图"
  81. prop="coverImg">
  82. <el-upload class="avatar-uploader"
  83. action="/api-web/uploadFile"
  84. :disabled="pageType=='create'?false:true"
  85. :headers="headers"
  86. :show-file-list="false"
  87. accept=".jpg, .jpeg, .png, .gif"
  88. :on-success="handleAvatarSuccess"
  89. :before-upload="beforeAvatarUpload">
  90. <img v-if="form.coverImg"
  91. :src="form.coverImg"
  92. class="avatar" />
  93. <i v-else
  94. class="el-icon-plus avatar-uploader-icon"></i>
  95. </el-upload>
  96. <p class="imageSize"
  97. v-if="imageSize">上传图片尺寸为:{{ imageSize }}</p>
  98. </el-form-item>
  99. <el-form-item label="活动详情"
  100. prop="detail">
  101. <!-- bidirectional data binding(双向数据绑定) -->
  102. <quill-editor class="ql-editor"
  103. :disabled="pageType=='create'?false:true"
  104. v-model="form.detail"
  105. ref="myQuillEditor"
  106. :options="editorOption"
  107. @change="onEditorChange($event)"></quill-editor>
  108. <el-upload class="ivu-upload"
  109. :show-upload-list="false"
  110. :headers="headers"
  111. :on-success="handleSuccess"
  112. accept=".jpg, .jpeg, .png, .gif"
  113. :max-size="2048"
  114. multiple
  115. action="/api-web/uploadFile">
  116. <Button icon="ios-cloud-upload-outline"></Button>
  117. </el-upload>
  118. </el-form-item>
  119. <el-form-item v-if="pageType == 'create'">
  120. <el-button @click="onSubmit('form')"
  121. type="primary">立即{{ pageType == "create" ? '创建' : '修改' }}</el-button>
  122. <el-button @click="onReSet('form')">重置</el-button>
  123. </el-form-item>
  124. </el-form>
  125. </div>
  126. </div>
  127. </template>
  128. <script>
  129. import { getActivitieQuery, getActivitieMerge } from "@/api/appTenant";
  130. import store from "@/store";
  131. import { getToken } from "@/utils/auth";
  132. import { vaildStudentUrl } from "@/utils/validate";
  133. import load from '@/utils/loading'
  134. // import E from 'wangeditor'
  135. // require styles
  136. import "quill/dist/quill.core.css";
  137. import "quill/dist/quill.snow.css";
  138. import "quill/dist/quill.bubble.css";
  139. import Quill from "quill";
  140. import { quillEditor } from "vue-quill-editor";
  141. // 工具栏配置
  142. const toolbarOptions = [
  143. ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
  144. ["blockquote", "code-block"], // 引用 代码块
  145. [{ header: 1 }, { header: 2 }], // 1、2 级标题
  146. [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
  147. [{ script: "sub" }, { script: "super" }], // 上标/下标
  148. [{ indent: "-1" }, { indent: "+1" }], // 缩进
  149. // [{'direction': 'rtl'}], // 文本方向
  150. [{ size: ["small", false, "large", "huge"] }], // 字体大小
  151. [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  152. [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  153. [{ font: [] }], // 字体种类
  154. [{ align: [] }], // 对齐方式
  155. ["clean"], // 清除文本格式
  156. // ["image", "video"] // 链接、图片、视频
  157. // ["link", "image", "video"] // 链接、图片、视频
  158. ];
  159. // 标题
  160. const titleConfig = {
  161. "ql-bold": "加粗",
  162. "ql-color": "颜色",
  163. "ql-font": "字体",
  164. "ql-code": "插入代码",
  165. "ql-italic": "斜体",
  166. // 'ql-link': '添加链接',
  167. "ql-background": "背景颜色",
  168. "ql-size": "字体大小",
  169. "ql-strike": "删除线",
  170. "ql-script": "上标/下标",
  171. "ql-underline": "下划线",
  172. "ql-blockquote": "引用",
  173. "ql-header": "标题",
  174. "ql-indent": "缩进",
  175. "ql-list": "列表",
  176. "ql-align": "文本对齐",
  177. "ql-direction": "文本方向",
  178. "ql-code-block": "代码块",
  179. "ql-formula": "公式",
  180. "ql-image": "图片",
  181. "ql-video": "视频",
  182. "ql-clean": "清除字体样式",
  183. "ql-upload": "文件"
  184. };
  185. let validPrice = (rule, value, callback) => {
  186. if (value == '' && typeof value == 'string' || value == null) {
  187. callback(new Error('请输入金额'))
  188. } else if (value < 0) {
  189. callback(new Error('输入金额必须大于或等于0'))
  190. } else if (value >= 100000) {
  191. callback(new Error('输入金额必须小于100000'))
  192. } else {
  193. callback()
  194. }
  195. }
  196. let validMinutes = (rule, value, callback) => {
  197. if (value == '' && typeof value == 'string' || value == null) {
  198. callback(new Error('请输入分钟数'))
  199. } else if (value < 0) {
  200. callback(new Error('输入分钟数必须大于或等于0'))
  201. } else if (value >= 100000) {
  202. callback(new Error('输入分钟数必须小于100000'))
  203. } else {
  204. callback()
  205. }
  206. }
  207. // 这里引入修改过的video模块并注册
  208. import Video from "../quill/video.js";
  209. Quill.register(Video, true);
  210. export default {
  211. name: "contentOperation",
  212. components: {
  213. quillEditor
  214. },
  215. data () {
  216. let that = this;
  217. return {
  218. categoryList: [],
  219. pageType: this.$route.query.type,
  220. headers: {
  221. Authorization: getToken()
  222. },
  223. content: null,
  224. editorIndex: 0, // 光标位置
  225. editorOption: {
  226. placeholder: "请输入内容",
  227. modules: {
  228. toolbar: {
  229. container: toolbarOptions,
  230. handlers: {
  231. image: function (value) {
  232. if (value) {
  233. // 调用iview图片上传
  234. document.querySelector(".ivu-upload .el-upload").click();
  235. } else {
  236. this.quill.format("image", false);
  237. }
  238. }
  239. }
  240. }
  241. }
  242. },
  243. form: {
  244. name: null,
  245. suitableUser: null,
  246. date: null,
  247. startDate: null,
  248. endDate: null,
  249. totalPrice: null,
  250. discountPrice: null,
  251. purchaseMinutes: null,
  252. giveMinutes: null,
  253. coverImg: null,
  254. detail: null
  255. },
  256. rules: {
  257. name: [
  258. { required: true, message: "请输入活动名称", trigger: "blur" },
  259. { min: 2, max: 30, message: "长度在 2 到 30 个字符", trigger: "blur" }
  260. ],
  261. suitableUser: [{ required: true, message: "请选择适用范围", trigger: "change" }],
  262. date: [{ required: true, message: '请选择有效期', trigger: 'change' }],
  263. totalPrice: [{ required: true, validator: validPrice, trigger: 'blur' }],
  264. discountPrice: [{ required: true, validator: validPrice, trigger: 'blur' }],
  265. purchaseMinutes: [{ required: true, validator: validMinutes, trigger: 'blur' }],
  266. giveMinutes: [{ required: true, validator: validMinutes, trigger: 'blur' }],
  267. coverImg: [
  268. { required: true, message: "请选择活动图", trigger: "blur" }
  269. ],
  270. detail: [{ required: true, message: "请编辑活动内容", trigger: "blur" }]
  271. },
  272. imageSize: null
  273. };
  274. },
  275. created () { },
  276. mounted () {
  277. this.init();
  278. },
  279. methods: {
  280. init () {
  281. this.getList();
  282. this.addQuillTitle();
  283. // this.form.type
  284. let tempTitle = {
  285. 1: "468px * 552px",
  286. 2: "456px * 288px",
  287. 3: "686px * 140px",
  288. 4: null
  289. };
  290. this.imageSize = tempTitle[this.form.type];
  291. },
  292. addQuillTitle () {
  293. const oToolBar = document.querySelector(".ql-toolbar"),
  294. aButton = oToolBar.querySelectorAll("button"),
  295. aSelect = oToolBar.querySelectorAll("select");
  296. aButton.forEach(function (item) {
  297. if (item.className === "ql-script") {
  298. item.value === "sub" ? (item.title = "下标") : (item.title = "上标");
  299. } else if (item.className === "ql-indent") {
  300. item.value === "+1"
  301. ? (item.title = "向右缩进")
  302. : (item.title = "向左缩进");
  303. } else {
  304. item.title = titleConfig[item.classList[0]];
  305. }
  306. });
  307. aSelect.forEach(function (item) {
  308. item.parentNode.title = titleConfig[item.classList[0]];
  309. });
  310. },
  311. onSubmit (formName) {
  312. this.$refs[formName].validate(valid => {
  313. if (valid) {
  314. if (this.pageType == "create") {
  315. let form = this.form
  316. let params = {
  317. name: form.name,
  318. suitableUser: form.suitableUser,
  319. startDate: form.date[0],
  320. endDate: form.date[1],
  321. totalPrice: form.totalPrice,
  322. discountPrice: form.discountPrice,
  323. purchaseMinutes: form.purchaseMinutes,
  324. giveMinutes: form.giveMinutes,
  325. coverImg: form.coverImg,
  326. detail: form.detail,
  327. delFlag: false
  328. }
  329. // return false
  330. getActivitieMerge(params).then(res => {
  331. this.messageTips("添加", res);
  332. });
  333. }
  334. } else {
  335. this.$nextTick(() => {
  336. let isError = document.getElementsByClassName('is-error')
  337. isError[0].scrollIntoView({
  338. block: 'center',
  339. behavior: 'smooth',
  340. })
  341. })
  342. return false;
  343. }
  344. });
  345. },
  346. messageTips (title, res) {
  347. if (res.code == 200) {
  348. this.$message.success(title + "成功");
  349. this.$store.dispatch('delVisitedViews', this.$route)
  350. this.$router.push({
  351. path: "/sysBasics/entryActivities"
  352. });
  353. } else {
  354. this.$message.error(res.msg);
  355. }
  356. },
  357. onCancel () {
  358. this.$store.dispatch('delVisitedViews', this.$route)
  359. this.$router.push({
  360. path: "/sysBasics/entryActivities"
  361. });
  362. },
  363. handleSuccess (res) {
  364. // 获取富文本组件实例
  365. let quill = this.editor;
  366. // 如果上传成功
  367. if (res.code) {
  368. // 获取光标所在位置
  369. let length = quill.getSelection().index;
  370. // 插入图片,res为服务器返回的图片链接地址
  371. quill.insertEmbed(length, "image", res.data.url);
  372. // 调整光标到最后
  373. quill.setSelection(length + 1);
  374. } else {
  375. // 提示信息,需引入Message
  376. this.$message.error("图片插入失败");
  377. }
  378. },
  379. onReSet (formName) {
  380. this.$refs[formName].resetFields();
  381. },
  382. getList () {
  383. if (this.pageType == "create") {
  384. return;
  385. } else {
  386. getActivitieQuery({ id: this.$route.query.id }).then(res => {
  387. if (res.code == 200) {
  388. let result = res.data;
  389. let form = this.form;
  390. this.form = {
  391. name: result.name,
  392. suitableUser: result.suitableUser,
  393. date: [result.startDate, result.endDate],
  394. startDate: result.startDate,
  395. endDate: result.endDate,
  396. totalPrice: result.totalPrice,
  397. discountPrice: result.discountPrice,
  398. purchaseMinutes: result.purchaseMinutes,
  399. giveMinutes: result.giveMinutes,
  400. coverImg: result.coverImg,
  401. detail: result.detail,
  402. };
  403. }
  404. });
  405. }
  406. },
  407. handleAvatarSuccess (res, file) {
  408. load.endLoading()
  409. this.form.coverImg = res.data.url;
  410. },
  411. beforeAvatarUpload (file) {
  412. const imageType = {
  413. "image/png": true,
  414. "image/jpeg": true,
  415. "image/gif": true
  416. };
  417. const isImage = imageType[file.type];
  418. const isLt2M = file.size / 1024 / 1024 < 2;
  419. if (!isImage) {
  420. this.$message.error("只能上传图片格式!");
  421. }
  422. if (!isLt2M) {
  423. this.$message.error("上传头像图片大小不能超过 2MB!");
  424. }
  425. if (isImage && isLt2M) { // 判断是否满足条件
  426. load.startLoading()
  427. }
  428. return isImage && isLt2M;
  429. },
  430. onEditorChange ({ quill, html, text }) {
  431. this.form.detail = html;
  432. }
  433. },
  434. computed: {
  435. editor () {
  436. return this.$refs.myQuillEditor.quill;
  437. }
  438. }
  439. };
  440. </script>
  441. <style lang="scss" scoped>
  442. .m-container {
  443. min-width: 100%;
  444. }
  445. .el-input {
  446. width: 400px;
  447. }
  448. ::v-deep .ql-editor {
  449. min-height: 300px;
  450. padding: 0;
  451. }
  452. ::v-deep .ql-container .ql-editor {
  453. max-height: 500px;
  454. }
  455. .el-row {
  456. margin-top: 40px;
  457. }
  458. .el-col {
  459. display: flex;
  460. align-items: center;
  461. margin-bottom: 20px;
  462. justify-content: flex-end;
  463. margin-right: 50%;
  464. }
  465. .el-input-group {
  466. width: 200px;
  467. margin: 0 20px;
  468. }
  469. ::v-deep .el-tree-node__content {
  470. height: 40px !important;
  471. }
  472. ::v-deep .avatar-uploader .el-upload {
  473. border: 1px dashed #d9d9d9;
  474. border-radius: 6px;
  475. cursor: pointer;
  476. position: relative;
  477. overflow: hidden;
  478. }
  479. .avatar-uploader .el-upload:hover {
  480. border-color: #409eff;
  481. }
  482. .avatar-uploader-icon {
  483. font-size: 28px;
  484. color: #8c939d;
  485. width: 240px;
  486. height: 120px;
  487. line-height: 120px;
  488. text-align: center;
  489. }
  490. ::v-deep .el-date-editor {
  491. width: 400px;
  492. }
  493. .avatar {
  494. width: 240px;
  495. height: 120px;
  496. display: block;
  497. }
  498. .ivu-upload {
  499. display: none;
  500. }
  501. </style>