dusenyao 1 rok pred
rodič
commit
4cae3d2a20

+ 2 - 2
src/utils/validate.js

@@ -9,8 +9,8 @@ export function isExternal(path) {
 
 /**
  * @description 只允许输入两位小数
- * @param {String} value
- * @returns { Number }
+ * @param {string} value
+ * @returns {number}
  */
 export function twoDecimal(value) {
   if (!value) {

+ 1 - 1
src/views/book/courseware/preview/components/upload_control/UploadControlPreview.vue

@@ -10,7 +10,7 @@
 </template>
 
 <script>
-import UploadFile from './compontents/UploadView.vue';
+import UploadFile from './components/UploadView.vue';
 
 export default {
   name: 'UploadControlPreview',

+ 15 - 29
src/views/book/courseware/preview/components/upload_control/compontents/UploadView.vue → src/views/book/courseware/preview/components/upload_control/components/UploadView.vue

@@ -58,30 +58,21 @@ export default {
   computed: {
     url() {
       let userInfor = getToken();
-      let UserCode = '',
-        UserType = '',
-        SessionID = '';
+      let SessionID = '';
+      let UserCode = '';
+      let UserType = '';
       if (userInfor) {
         let user = JSON.parse(getToken());
         UserCode = user.user_code;
         UserType = user.user_type;
         SessionID = user.session_id;
       }
-      return (
-        process.env.VUE_APP_BASE_API +
-        '/GCLSFileServer/WebFileUpload?UserCode=' +
-        UserCode +
-        '&UserType=' +
-        UserType +
-        '&SessionID=' +
-        SessionID +
-        '&SecurityLevel=Mid'
-      );
+      return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload?UserCode=${UserCode}&UserType=${UserType}&SessionID=${SessionID}&SecurityLevel=Mid`;
     },
   },
   watch: {
     datafileList: {
-      handler: function (val, oldVal) {
+      handler(val, oldVal) {
         this.initUpload();
       },
       // 深度观察监听
@@ -95,7 +86,7 @@ export default {
   created() {
     this.currentfileList = this.fileList || [];
     // this.showList = this.fileList ? true : false;
-    if (this.type == 'upload_control_preview_chs' || this.type == 'upload_pdf_chs') {
+    if (this.type === 'upload_control_preview_chs' || this.type === 'upload_pdf_chs') {
       this.showList = true;
     } else {
       this.showList = false;
@@ -116,7 +107,7 @@ export default {
   methods: {
     handleChange(file, fileList) {},
     handleSuccess(response, file, fileList) {
-      if (response.status == 1) {
+      if (response.status === 1) {
         response.duration = response.file_info_list[0].media_duration ? response.file_info_list[0].media_duration : 10;
         this.$message.success('用户上传成功');
         this.changeFillId(fileList, response.duration, this.index);
@@ -128,21 +119,19 @@ export default {
       }
     },
     handlebeforeUplaod(file) {
-      if (file.type.indexOf('image/') != -1) {
+      if (file.type.indexOf('image/') !== -1) {
         if (file.size > 2 * 1024 * 1024) {
           this.$message.warning('上传图片大小不能超过2M');
-          return false; //必须返回false
+          return false; // 必须返回false
         }
-      } else if (file.type.indexOf('application/pdf') != -1) {
+      } else if (file.type.indexOf('application/pdf') !== -1) {
         if (file.size > 20 * 1024 * 1024) {
           this.$message.warning('上传pdf大小不能超过20M');
-          return false; //必须返回false
-        }
-      } else {
-        if (file.size > 500 * 1024 * 1024) {
-          this.$message.warning('上传文件大小不能超过500M');
-          return false; //必须返回false
+          return false; // 必须返回false
         }
+      } else if (file.size > 500 * 1024 * 1024) {
+        this.$message.warning('上传文件大小不能超过500M');
+        return false; // 必须返回false
       }
 
       this.loading = this.$loading({
@@ -159,9 +148,6 @@ export default {
     beforeRemove(file, fileList) {
       return this.$confirm(`确定移除 ${file.name}?`);
     },
-    beforeRemove(file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`);
-    },
     handlePreview(file) {},
     handleExceed(files, fileList) {
       this.$message.warning(
@@ -199,8 +185,8 @@ export default {
   }, // 如果页面有keep-alive缓存功能,这个函数会触发
 };
 </script>
+
 <style lang="scss" scoped>
-//@import url(); 引入公共css类;
 .uploadBtn {
   box-sizing: border-box;
   display: flex;

+ 1 - 1
src/views/book/courseware/preview/components/upload_preview/UploadPreviewPreview.vue

@@ -10,7 +10,7 @@
 </template>
 
 <script>
-import UploadFile from './compontents/UploadView.vue';
+import UploadFile from './components/UploadView.vue';
 
 export default {
   name: 'UploadControlPreview',

+ 15 - 29
src/views/book/courseware/preview/components/upload_preview/compontents/UploadView.vue → src/views/book/courseware/preview/components/upload_preview/components/UploadView.vue

@@ -58,30 +58,21 @@ export default {
   computed: {
     url() {
       let userInfor = getToken();
-      let UserCode = '',
-        UserType = '',
-        SessionID = '';
+      let SessionID = '';
+      let UserCode = '';
+      let UserType = '';
       if (userInfor) {
         let user = JSON.parse(getToken());
         UserCode = user.user_code;
         UserType = user.user_type;
         SessionID = user.session_id;
       }
-      return (
-        process.env.VUE_APP_BASE_API +
-        '/GCLSFileServer/WebFileUpload?UserCode=' +
-        UserCode +
-        '&UserType=' +
-        UserType +
-        '&SessionID=' +
-        SessionID +
-        '&SecurityLevel=Mid'
-      );
+      return `${process.env.VUE_APP_BASE_API}/GCLSFileServer/WebFileUpload?UserCode=${UserCode}&UserType=${UserType}&SessionID=${SessionID}&SecurityLevel=Mid`;
     },
   },
   watch: {
     datafileList: {
-      handler: function (val, oldVal) {
+      handler(val, oldVal) {
         this.initUpload();
       },
       // 深度观察监听
@@ -95,7 +86,7 @@ export default {
   created() {
     this.currentfileList = this.fileList || [];
     // this.showList = this.fileList ? true : false;
-    if (this.type == 'upload_control_preview_chs' || this.type == 'upload_pdf_chs') {
+    if (this.type === 'upload_control_preview_chs' || this.type === 'upload_pdf_chs') {
       this.showList = true;
     } else {
       this.showList = false;
@@ -116,7 +107,7 @@ export default {
   methods: {
     handleChange(file, fileList) {},
     handleSuccess(response, file, fileList) {
-      if (response.status == 1) {
+      if (response.status === 1) {
         response.duration = response.file_info_list[0].media_duration ? response.file_info_list[0].media_duration : 10;
         this.$message.success('用户上传成功');
         this.changeFillId(fileList, response.duration, this.index);
@@ -128,21 +119,19 @@ export default {
       }
     },
     handlebeforeUplaod(file) {
-      if (file.type.indexOf('image/') != -1) {
+      if (file.type.indexOf('image/') !== -1) {
         if (file.size > 2 * 1024 * 1024) {
           this.$message.warning('上传图片大小不能超过2M');
-          return false; //必须返回false
+          return false; // 必须返回false
         }
-      } else if (file.type.indexOf('application/pdf') != -1) {
+      } else if (file.type.indexOf('application/pdf') !== -1) {
         if (file.size > 20 * 1024 * 1024) {
           this.$message.warning('上传pdf大小不能超过20M');
-          return false; //必须返回false
-        }
-      } else {
-        if (file.size > 500 * 1024 * 1024) {
-          this.$message.warning('上传文件大小不能超过500M');
-          return false; //必须返回false
+          return false; // 必须返回false
         }
+      } else if (file.size > 500 * 1024 * 1024) {
+        this.$message.warning('上传文件大小不能超过500M');
+        return false; // 必须返回false
       }
 
       this.loading = this.$loading({
@@ -159,9 +148,6 @@ export default {
     beforeRemove(file, fileList) {
       return this.$confirm(`确定移除 ${file.name}?`);
     },
-    beforeRemove(file, fileList) {
-      return this.$confirm(`确定移除 ${file.name}?`);
-    },
     handlePreview(file) {},
     handleExceed(files, fileList) {
       this.$message.warning(
@@ -199,8 +185,8 @@ export default {
   }, // 如果页面有keep-alive缓存功能,这个函数会触发
 };
 </script>
+
 <style lang="scss" scoped>
-//@import url(); 引入公共css类;
 .uploadBtn {
   box-sizing: border-box;
   display: flex;

+ 42 - 37
src/views/book/create.vue

@@ -27,32 +27,33 @@
               <span>点击上传封面</span>
             </div>
           </el-upload>
-          <div class="tips">支持jpg、png格式图片,图片尺寸必须为 456 x 640px,大小不超过5mb。</div>
+          <div class="tips">支持jpg、png格式图片,大小不超过5mb。</div>
         </el-form-item>
         <el-form-item label="书籍名称" prop="name">
-          <el-input v-model="form.name" placeholder="请输入内容" />
+          <el-input v-model="form.name" placeholder="请输入内容" :maxlength="100" />
         </el-form-item>
         <el-form-item label="作者" prop="author">
-          <el-input v-model="form.author" placeholder="请输入内容" />
+          <el-input v-model="form.author" placeholder="请输入内容" :maxlength="20" />
         </el-form-item>
         <el-form-item label="现价" prop="price">
-          <el-input v-model="form.price" placeholder="请输入内容">
+          <el-input v-model="form.price" placeholder="请输入内容" @input="handlePrice($event, 'price')">
             <template slot="append">元</template>
           </el-input>
         </el-form-item>
         <el-form-item label="原价" prop="price_old">
-          <el-input v-model="form.price_old" placeholder="请输入内容">
+          <el-input v-model="form.price_old" placeholder="请输入内容" @input="handlePrice($event, 'price_old')">
             <template slot="append">元</template>
           </el-input>
         </el-form-item>
         <el-form-item label="标签" prop="label_name_list">
           <el-select
             v-model="form.label_name_list"
+            class="label-select"
             multiple
             filterable
             allow-create
             default-first-option
-            placeholder="请输入内容"
+            placeholder="请输入标签,回车确认"
           />
         </el-form-item>
         <el-form-item label="分类" prop="type_id">
@@ -82,6 +83,7 @@
 <script>
 import { fileUpload } from '@/api/app';
 import { GetBook, UpdateBook, AddBook, GetBookTypeList } from '@/api/book';
+import { twoDecimal } from '@/utils/validate';
 
 export default {
   name: 'CreateBookPage',
@@ -134,38 +136,25 @@ export default {
       });
     },
     beforeCoverUpload(file) {
-      return new Promise((resolve, reject) => {
-        // 图片尺寸必须为 456 x 640px
-        const img = new Image();
-        img.src = window.URL.createObjectURL(file);
-        let isCorrectSize = true; // 是否为正确尺寸
-        img.onload = () => {
-          const { width, height } = img;
-          if (width !== 456 || height !== 640) {
-            isCorrectSize = false;
-            this.$message.error('图片尺寸必须为 456 x 640px!');
-            reject();
-          }
-
-          const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
-          if (!isJPG) {
-            this.$message.error('上传封面图片只能是 JPG 或 PNG 格式!');
-            reject();
-          }
-
-          const isLt5M = file.size / 1024 / 1024 < 5;
-          if (!isLt5M) {
-            this.$message.error('上传封面图片大小不能超过 5MB!');
-            reject();
-          }
+      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
+      if (!isJPG) {
+        this.$message.error('上传封面图片只能是 JPG 或 PNG 格式!');
+        return false;
+      }
 
-          if (isCorrectSize && isJPG && isLt5M) {
-            resolve();
-          } else {
-            reject();
-          }
-        };
-      });
+      const isLt5M = file.size / 1024 / 1024 < 5;
+      if (!isLt5M) {
+        this.$message.error('上传封面图片大小不能超过 5MB!');
+        return false;
+      }
+    },
+    /**
+     * @description 处理价格输入
+     * @param {string | number} val 输入的值
+     * @param {price | price_old} type 输入的类型
+     */
+    handlePrice(val, type) {
+      this.form[type] = twoDecimal(val);
     },
     addBook() {
       this.$refs.form.validate((valid) => {
@@ -309,6 +298,12 @@ export default {
         }
       }
 
+      .label-select {
+        :deep .el-input__suffix {
+          display: none;
+        }
+      }
+
       .tips {
         margin-top: -4px;
         font-size: 12px;
@@ -322,3 +317,13 @@ export default {
   }
 }
 </style>
+
+<style lang="scss">
+.el-select-dropdown.el-popper.is-multiple {
+  display: none;
+
+  .el-select-dropdown__empty {
+    display: none;
+  }
+}
+</style>

+ 46 - 7
src/views/book/setting.vue

@@ -70,8 +70,8 @@
           <div class="catalogue-edit-top">
             <span class="title">编辑目录</span>
             <div class="operation">
-              <el-button class="cancel" @click="isEdit = false">取消</el-button>
-              <el-button type="primary" @click="isEdit = false">完成</el-button>
+              <el-button class="cancel" @click="cancel">取消</el-button>
+              <el-button type="primary" @click="complete">完成</el-button>
             </div>
           </div>
 
@@ -80,7 +80,9 @@
               <!-- 一级目录 -->
               <div v-if="item.id === curEditNodeId" :key="item.id" class="nodes-edit">
                 <el-input v-model="item.name" placeholder="请输入标题" />
-                <el-button type="primary" @click="confirmEditNode(item.id, '', 'false')">确定</el-button>
+                <el-button type="primary" class="confirm-edit" @click="confirmEditNode(item.id, '', 'false')">
+                  确定
+                </el-button>
                 <el-button @click="cancelEditNode(item.id)">取消</el-button>
               </div>
               <div v-else :key="item.id" class="nodes-item">
@@ -105,7 +107,11 @@
                 <template v-for="li in item.nodes">
                   <div v-if="li.id === curEditNodeId" :key="li.id" class="nodes-edit">
                     <el-input v-model="li.name" placeholder="请输入标题" />
-                    <el-button type="primary" @click="confirmEditNode(li.id, item.id, li.is_leaf_chapter)">
+                    <el-button
+                      type="primary"
+                      class="confirm-edit"
+                      @click="confirmEditNode(li.id, item.id, li.is_leaf_chapter)"
+                    >
                       确定
                     </el-button>
                     <el-button @click="cancelEditNode(li.id)">取消</el-button>
@@ -144,7 +150,11 @@
                     <template v-for="child in li.nodes">
                       <div v-if="child.id === curEditNodeId" :key="child.id" class="nodes-edit">
                         <el-input v-model="child.name" placeholder="请输入标题" />
-                        <el-button type="primary" @click="confirmEditNode(child.id, li.id, child.is_leaf_chapter)">
+                        <el-button
+                          type="primary"
+                          class="confirm-edit"
+                          @click="confirmEditNode(child.id, li.id, child.is_leaf_chapter)"
+                        >
                           确定
                         </el-button>
                         <el-button @click="cancelEditNode(child.id)">取消</el-button>
@@ -205,6 +215,7 @@ export default {
         description: '',
       },
       nodes: [],
+      loading: false,
     };
   },
   created() {
@@ -236,6 +247,7 @@ export default {
     getBookChapterStruct() {
       GetBookChapterStruct({ book_id: this.book_id, node_deep_mode: 0 }).then(({ nodes }) => {
         this.nodes = nodes ?? [];
+        this.loading = false;
       });
     },
     /**
@@ -253,6 +265,10 @@ export default {
       const name = nodes[position[position.length - 1]].name;
       if (name.length <= 0) {
         this.$message.error('请输入名称');
+        // 非编辑状态下删除临时节点
+        if (!this.isEdit) {
+          this.cancelEditNode(id);
+        }
         return;
       }
       if (nodes[position[position.length - 1]]?.temporary) {
@@ -262,11 +278,15 @@ export default {
       }
     },
     addChapterToBook(name, parent_id, is_leaf) {
+      if (this.loading) return;
+      this.loading = true;
       AddChapterToBook({ name, book_id: this.book_id, parent_id, is_leaf }).then(() => {
         this.getBookChapterStruct();
       });
     },
     updateChapter(id, name) {
+      if (this.loading) return;
+      this.loading = true;
       UpdateChapter({ id, name }).then(() => {
         this.getBookChapterStruct();
         this.curEditNodeId = '';
@@ -386,6 +406,22 @@ export default {
       }
       this.curEditNodeId = '';
     },
+    // 取消编辑
+    cancel() {
+      this.isEdit = false;
+      if (this.curEditNodeId) {
+        this.cancelEditNode(this.curEditNodeId);
+        this.getBookChapterStruct();
+      }
+    },
+    // 完成编辑
+    complete() {
+      this.isEdit = false;
+      // 如果有正在编辑的节点,先保存
+      if (this.curEditNodeId) {
+        document.querySelector('.confirm-edit').click();
+      }
+    },
   },
 };
 </script>
@@ -402,10 +438,13 @@ export default {
 }
 
 .setting {
-  height: 100%;
+  min-height: 100%;
   padding: 8px 24px;
 
   .breadcrumb {
+    position: sticky;
+    top: 8px;
+    z-index: 1;
     display: flex;
     align-items: center;
     font-size: 14px;
@@ -434,7 +473,7 @@ export default {
     display: flex;
     column-gap: 24px;
     justify-content: center;
-    height: calc(100% - 40px);
+    min-height: calc(100vh - 118px);
     margin-top: 16px;
 
     .basic-info {