create.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. <!-- 课程创建/修改 -->
  2. <template>
  3. <div class="pjc">
  4. <el-page-header @back="$router.go(-1)" :content="title"></el-page-header>
  5. <h3>{{ title }}</h3>
  6. <el-form :model="courseDeail" label-width="110px">
  7. <el-form-item label="课程名称:">
  8. <el-input :maxlength="50" v-model.trim="courseDeail.name" style="width: 40%" placeholder="输入课程名称,最多50字符"></el-input>
  9. </el-form-item>
  10. <el-form-item label="预览图:">
  11. <div style="width: 68px" @click="showSelectImg(1)">
  12. <userImage
  13. v-if="courseDeail.thumb"
  14. width="68px"
  15. height="68px"
  16. radius="5px"
  17. :img_url="courseDeail.thumb"
  18. :user_name="courseDeail.name"
  19. style="cursor: pointer"
  20. ></userImage>
  21. <div v-else class="cursor">
  22. <div>+</div>
  23. </div>
  24. </div>
  25. </el-form-item>
  26. <el-form-item label="价格:">
  27. <el-input-number
  28. v-model="courseDeail.price"
  29. :min="0"
  30. :max="10000000"
  31. label="课程价格"
  32. ></el-input-number>
  33. </el-form-item>
  34. <el-form-item label="是否上架:">
  35. <el-switch
  36. v-model="courseDeail.enable"
  37. active-color="#13ce66"
  38. inactive-color="#999"
  39. >
  40. </el-switch>
  41. </el-form-item>
  42. <el-form-item label="课程介绍:">
  43. <div style="display: flex;">
  44. <div class="img_all">
  45. <template v-for="(item, index) in courseImages">
  46. <div class="imgout">
  47. <userImage
  48. width="68px"
  49. radius="5px"
  50. height="68px"
  51. :img_url="item"
  52. ></userImage>
  53. <div class="imgDelete" @click="imgsDelete(index)">
  54. <i class="el-icon-delete" style="color: #FFF;font-size: 18px;"></i>
  55. </div>
  56. </div>
  57. </template>
  58. </div>
  59. <div class="cursor" @click="showSelectImg(2)">
  60. <div>+</div>
  61. </div>
  62. </div>
  63. </el-form-item>
  64. <!-- <el-form-item label="课程介绍:">
  65. <uploadOss
  66. :headers="$xtoken"
  67. :action="$action"
  68. :limit="3"
  69. list_type="picture-card"
  70. :accept="$acceptImg"
  71. :multiple="true"
  72. ref="clearPicture"
  73. :show-file-list="true"
  74. :file-list="item.fileList"
  75. :on-success="handleFilesSuccess"
  76. :on-preview="onFilePreView"
  77. :before-upload="beforeUpload"
  78. :on-remove="onFileRemove"
  79. >
  80. <i class="el-icon-plus"></i>
  81. </uploadOss>
  82. </el-form-item> -->
  83. <el-form-item label="课程章节" size="normal">
  84. <div class="sectionout">
  85. <div
  86. class="sectionInner"
  87. v-for="(item, index) in courseDeail.sections"
  88. :key="index"
  89. >
  90. <div class="sectionName">
  91. <el-input v-model.trim="item.name" placeholder="请输入章节名..."></el-input>
  92. </div>
  93. <div class="sectionUrl">
  94. <el-input v-model.trim="item.link" placeholder="请输入章节链接..."></el-input>
  95. </div>
  96. <div class="del">
  97. <el-button
  98. type="text"
  99. size="mini"
  100. plain
  101. @click="sectionDel(index, item)"
  102. style="color: #f89881"
  103. >删除</el-button
  104. >
  105. </div>
  106. </div>
  107. <div class="addSection">
  108. <el-button plain @click="addSection">+</el-button>
  109. </div>
  110. </div>
  111. </el-form-item>
  112. <el-form-item style="display: flex; flex-direction: row-reverse">
  113. <el-button @click="$router.go(-1)">取消</el-button>
  114. <el-button @click="iffirm">{{ alterCreate }}</el-button>
  115. </el-form-item>
  116. </el-form>
  117. <el-dialog :visible.sync="dialogVisible">
  118. <img width="100%" :src="dialogImageUrl" alt="" />
  119. </el-dialog>
  120. <image-cropper
  121. v-loading="company_img_loading"
  122. field="file"
  123. :width="imgWidth"
  124. :height="imgHeight"
  125. :url="'https://integralsys.oss-cn-shenzhen.aliyuncs.com'"
  126. @close="company_img_show = false"
  127. @crop-upload-success="company_img_success"
  128. langType="zh"
  129. v-if="company_img_show"
  130. ></image-cropper>
  131. </div>
  132. </template>
  133. <script>
  134. import ImageCropper from "@/components/ImageCropper";
  135. import { validateURL } from "@/utils/validate";
  136. import {createCourse,updataCourse,getCourseDetail} from '../api'
  137. export default {
  138. name: "courseEdit",
  139. components: { ImageCropper },
  140. data() {
  141. return {
  142. curId: 0,
  143. title: "",
  144. company_img_show: false,
  145. company_img_loading: false,
  146. alterCreate: "保存",
  147. imgIndex: 1,
  148. imgWidth: 300,
  149. imgHeight: 300,
  150. // 个人信息
  151. courseDeail: {
  152. name: "",
  153. price: 0,
  154. thumb: "",
  155. enable: false,
  156. images: "",
  157. sections: [],
  158. },
  159. dialogVisible: false,
  160. dialogImageUrl: "",
  161. };
  162. },
  163. computed: {
  164. courseImages() {
  165. if (this.courseDeail.images) {
  166. return this.courseDeail.images.split(",");
  167. } else {
  168. return [];
  169. }
  170. },
  171. },
  172. methods: {
  173. //删除介绍图片
  174. imgsDelete(index){
  175. let list = this.courseDeail.images.split(",");
  176. list.splice(index,1)
  177. this.courseDeail.images = list.join(',')
  178. },
  179. //章节信息校验
  180. validateURL() {
  181. let result = false;
  182. result = this.courseDeail.sections.every((item) => {
  183. return item.link !== '' && item.name !== "";
  184. // return validateURL(item.link) && item.name !== "";
  185. });
  186. return result;
  187. },
  188. // 获取课程详情
  189. getCourseDetail() {
  190. getCourseDetail(this.curId).then((res) => {
  191. this.courseDeail = this.uploadToData(res);
  192. }).catch(err=>{
  193. console.error(err)
  194. });
  195. },
  196. //课程详情数据转换展示
  197. uploadToData(data) {
  198. data.enable = data.enable == 1 ? true : false;
  199. data.price = Number(data.price);
  200. data.images = data.images.join(",");
  201. return data;
  202. },
  203. //图片上传成功回调
  204. company_img_success(resData) {
  205. if (this.imgIndex == 1) {
  206. this.courseDeail.thumb = resData.url;
  207. } else {
  208. if (
  209. this.courseDeail.images.split(",").length == 1 &&
  210. this.courseDeail.images.split(",")[0] == ""
  211. ) {
  212. this.courseDeail.images = resData.url;
  213. } else {
  214. this.courseDeail.images = `${this.courseDeail.images},${resData.url}`;
  215. }
  216. }
  217. this.company_img_show = false;
  218. },
  219. //打开上传图片组件
  220. showSelectImg(type) {
  221. this.imgIndex = type;
  222. this.company_img_show = true;
  223. },
  224. //展示数据转换成上传数据
  225. toUpdata() {
  226. let data = JSON.parse(JSON.stringify(this.courseDeail));
  227. data.enable = data.enable ? 1 : 0;
  228. data.sections = JSON.stringify(data.sections);
  229. return data;
  230. },
  231. // 添加课程
  232. addSection() {
  233. let section = {
  234. name: "",
  235. link: "",
  236. };
  237. this.courseDeail.sections.push(section);
  238. },
  239. // 删除章节
  240. sectionDel(index, item) {
  241. this.$confirm("确定删除当前章节?", "提示", {
  242. confirmButtonText: "确定",
  243. cancelButtonText: "取消",
  244. type: "warning",
  245. })
  246. .then(() => {
  247. this.courseDeail.sections.splice(index, 1);
  248. })
  249. .catch((err) => {
  250. this.$message({
  251. type: "info",
  252. message: "已取消",
  253. });
  254. });
  255. },
  256. // 删除图片
  257. deleteImage(url, type) {
  258. this.$confirm("确定删除图片?", "提示", {
  259. confirmButtonText: "确定",
  260. cancelButtonText: "取消",
  261. type: "warning",
  262. })
  263. .then(() => {
  264. if (type) {
  265. let newList = this.courseDeail.images.filter((item) => {
  266. return item.url !== url;
  267. });
  268. this.courseDeail.images = newList;
  269. } else {
  270. this.courseDeail.thumb = [];
  271. }
  272. })
  273. .catch((err) => {
  274. this.$message({
  275. type: "info",
  276. message: "已取消",
  277. });
  278. });
  279. },
  280. //保存
  281. iffirm() {
  282. if (
  283. !this.courseDeail.name == "" &&
  284. !this.courseDeail.images == "" &&
  285. !this.courseDeail.thumb == "" &&
  286. !this.courseDeail.price !== 0 &&
  287. this.validateURL()
  288. ) {
  289. this.$confirm("确定保存当前页面信息?", "提示", {
  290. confirmButtonText: "确定",
  291. cancelButtonText: "取消",
  292. type: "info",
  293. })
  294. .then(() => {
  295. if (this.$route.params.id) {
  296. this.saveAlter();
  297. } else {
  298. this.saveCreate();
  299. }
  300. })
  301. .catch(() => {
  302. this.$message({
  303. type: "info",
  304. message: "已取消",
  305. });
  306. });
  307. } else if (!this.validateURL()) {
  308. this.$message({
  309. type: "warning",
  310. message: "章节列表未填写正确",
  311. });
  312. } else {
  313. this.$message({
  314. type: "warning",
  315. message: "用户信息未填写完整",
  316. });
  317. }
  318. },
  319. //修改保存
  320. saveAlter() {
  321. let data = this.toUpdata();
  322. updataCourse(this.curId,data).then(res=>{
  323. this.$message({
  324. message: "修改成功!",
  325. type: "success",
  326. showClose: true,
  327. duration: 2000,
  328. });
  329. this.$router.push("/course/courseManage");
  330. }).catch(err=>{
  331. console.error(err)
  332. })
  333. },
  334. //新建课程
  335. saveCreate() {
  336. let data = this.toUpdata();
  337. createCourse(data).then(res=>{
  338. this.$message({
  339. message: "新建成功!",
  340. type: "success",
  341. showClose: true,
  342. duration: 2000,
  343. });
  344. this.$router.push("/course/courseManage");
  345. }).catch(err=>{
  346. console.error(err)
  347. })
  348. },
  349. //判断新建/修改
  350. init() {
  351. if (this.$route.params.id == undefined) {
  352. this.title = "创建课程";
  353. this.courseDeail = {
  354. name: "",
  355. price: 0,
  356. thumb: "",
  357. enable: false,
  358. images: "",
  359. sections: [],
  360. };
  361. } else {
  362. this.curId = this.$route.params.id;
  363. this.title = "编辑课程";
  364. this.getCourseDetail();
  365. }
  366. },
  367. },
  368. created() {
  369. this.init();
  370. },
  371. };
  372. </script>
  373. <style scoped lang="scss">
  374. .pjc {
  375. width: 900px;
  376. height: auto;
  377. margin: 0 auto;
  378. margin-top: 10px;
  379. background-color: #fff;
  380. border-radius: 5px;
  381. padding: 30px 60px;
  382. h3 {
  383. color: #000;
  384. text-align: center;
  385. margin: 30px 0;
  386. }
  387. form {
  388. legend {
  389. font-size: 20px;
  390. color: #000;
  391. line-height: 30px;
  392. font-weight: bold;
  393. margin-bottom: 22px;
  394. }
  395. .el-form-item {
  396. .el-select {
  397. width: 380px;
  398. }
  399. }
  400. }
  401. }
  402. .sectionout {
  403. .sectionInner {
  404. display: flex;
  405. // justify-content: space-between;
  406. align-items: center;
  407. margin-bottom: 10px;
  408. .sectionName {
  409. width: 150px;
  410. margin-right: 20px;
  411. }
  412. .sectionUrl {
  413. width: 250px;
  414. margin-right: 20px;
  415. }
  416. .sectionDel {
  417. }
  418. }
  419. }
  420. .img_all {
  421. display: flex;
  422. flex-wrap: wrap;
  423. & > div {
  424. margin-right: 10px;
  425. margin-bottom: 10px;
  426. }
  427. .imgout{
  428. position: relative;
  429. .imgDelete{
  430. width: 100%;
  431. height: 100%;
  432. display: flex;
  433. align-items: center;
  434. justify-content: center;
  435. cursor: pointer;
  436. position: absolute;
  437. left:0;
  438. top:0;
  439. background-color: rgba(0,0,0,.3);
  440. opacity: 0;
  441. transition: opacity 0.3s ease;
  442. }
  443. &:hover{
  444. .imgDelete{
  445. opacity:1;
  446. }
  447. }
  448. }
  449. }
  450. .cursor {
  451. & > div {
  452. height: 68px;
  453. width: 68px;
  454. border: 2px dashed #f1f1f1;
  455. border-radius: 5px;
  456. font-size: 30px;
  457. display: flex;
  458. justify-content: center;
  459. align-items: center;
  460. }
  461. }
  462. </style>