lsc 4 months ago
parent
commit
0494af3875

+ 20 - 0
src/App.vue

@@ -550,4 +550,24 @@ html::-webkit-scrollbar-thumb {
   color: #FF9400;
   font-weight: bold;
 }
+
+.count-node {
+  position: absolute;
+  top: 2px;
+  display: none;
+  height: 24px;
+  padding: 0 8px;
+  line-height: 22px;
+  margin-left: 6px;
+  background-color: #f4f4f5;
+  border: 1px solid #e9e9eb;
+  border-radius: 4px;
+  color: #909399;
+  font-size: 12px;
+  box-sizing: border-box;
+}
+
+.tagOption.selected{
+  color: #ef9e28 !important;
+}
 </style>

+ 131 - 0
src/components/common/ConfirmDialog.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="confirm_dialog">
+    <el-dialog
+      :visible.sync="dialogVisible"
+      width="400px"
+      :show-close="false"
+      :before-close="handleClose"
+      class="confirm_dialog_custom"
+    >
+      <div class="confirm_dialog_content">
+        <h3 class="confirm_dialog_title">{{ title }}</h3>
+        <p class="confirm_dialog_message">{{ message }}</p>
+      </div>
+      <div class="confirm_dialog_footer">
+        <el-button @click="handleCancel" class="cancel_btn">{{ cancelText }}</el-button>
+        <el-button type="primary" @click="handleConfirm" class="confirm_btn">{{ confirmText }}</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'ConfirmDialog',
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    title: {
+      type: String,
+      default: ''
+    },
+    message: {
+      type: String,
+      default: ''
+    },
+    confirmText: {
+      type: String,
+      default: '确认'
+    },
+    cancelText: {
+      type: String,
+      default: '取消'
+    }
+  },
+  data() {
+    return {
+      dialogVisible: this.visible
+    }
+  },
+  watch: {
+    visible: {
+      handler(newVal) {
+        this.dialogVisible = newVal;
+      },
+      immediate: true
+    }
+  },
+  methods: {
+    handleClose() {
+      this.dialogVisible = false;
+      this.$emit('update:visible', false);
+      this.$emit('cancel');
+    },
+    handleCancel() {
+      this.dialogVisible = false;
+      this.$emit('update:visible', false);
+      this.$emit('cancel');
+    },
+    handleConfirm() {
+      this.dialogVisible = false;
+      this.$emit('update:visible', false);
+      this.$emit('confirm');
+    }
+  }
+}
+</script>
+
+<style scoped>
+.confirm_dialog_custom >>> .el-dialog {
+  border-radius: 15px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+.confirm_dialog_custom >>> .el-dialog__header {
+  display: none;
+}
+
+.confirm_dialog_custom >>> .el-dialog__body {
+  padding: 20px;
+}
+
+.confirm_dialog_title {
+  font-size: 18px;
+  font-weight: bold;
+  margin-bottom: 16px;
+  color: #333;
+}
+
+.confirm_dialog_message {
+  font-size: 14px;
+  line-height: 1.5;
+  color: #666;
+  margin-bottom: 24px;
+}
+
+.confirm_dialog_footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 12px;
+}
+
+.cancel_btn {
+  border-radius: 10px;
+  border: 1px solid #DCDFE6;
+  background-color: #FFFFFF;
+  color: #606266;
+}
+
+.confirm_btn {
+  border-radius: 6px;
+  background-color: #FF9400;
+  border: none;
+  color: #FFFFFF;
+}
+
+.confirm_btn:hover {
+  background-color: #FFA500;
+}
+</style>

+ 124 - 62
src/components/pages/pptEasy/addCourse3.vue

@@ -1,5 +1,15 @@
 <template>
   <div class="pb_content" style="background: #F0F2F5;" v-loading.fullscreen.lock="uploadWorkLoading">
+    <confirm-dialog
+      :visible.sync="confirmVisible"
+      :title="confirmTitle"
+      :message="confirmMessage"
+      :confirm-text="confirmConfirmText"
+      :cancel-text="confirmCancelText"
+      @confirm="handleConfirm"
+      @cancel="handleCancel"
+    />
+
     <div class="pb_content_body" style="position: relative; margin: 0">
       <div class="right">
         <div style="width: 100%; height: 100%; overflow: auto" ref="stepBox">
@@ -743,19 +753,31 @@
         <div class="modal-body">
           <div class="form-item">
             <label class="form-label">{{ lang.ssSubjectCategory }}</label>
-            <el-select v-model="selectedSubject" :placeholder="lang.ssSelectSubj" class="custom-select" collapse-tags
+            <!-- <el-select v-model="selectedSubject" :placeholder="lang.ssSelectSubj" class="custom-select" collapse-tags
               multiple style="width: 100%">
               <el-option v-for="option in subjectOptions" :key="option.id" :label="option.name"
                 :value="option.id"></el-option>
-            </el-select>
+            </el-select> -->
+            <selectTag
+              v-model="selectedSubject"
+              :options="subjectOptions"
+              :placeholder=lang.ssSelectSubj
+              style="width: 100%;"
+            />
           </div>
           <div class="form-item">
             <label class="form-label">{{ lang.ssGradeType }}</label>
-            <el-select v-model="selectedGrade" :placeholder="lang.ssSelectGrade" class="custom-select" collapse-tags
+            <!-- <el-select v-model="selectedGrade" :placeholder="lang.ssSelectGrade" class="custom-select" collapse-tags
               multiple style="width: 100%">
               <el-option v-for="option in gradeOptions" :key="option.id" :label="option.name"
                 :value="option.id"></el-option>
-            </el-select>
+            </el-select> -->
+            <selectTag
+              v-model="selectedGrade"
+              :options="gradeOptions"
+              :placeholder=lang.ssSelectGrade
+              style="width: 100%;"
+            />
           </div>
         </div>
         <div class="modal-footer">
@@ -785,35 +807,58 @@
           <div class="form-box">
             <div class="form-box-left">
               <div class="form-row">
-                <div class="form-item required" style="flex: 2;">
+                <div class="form-item required">
                   <label class="form-label">{{ lang.ssSubjectCategory }}</label>
-                  <el-select v-model="selectedSubject" :placeholder="lang.ssSelectSubj" class="custom-select" collapse-tags multiple
-                    style="width: 100%">
-                    <el-option v-for="option in subjectOptions" :key="option.id" :label="option.name"
-                      :value="option.id"></el-option>
-                  </el-select>
+                  <selectTag
+                    v-model="selectedSubject"
+                    :options="subjectOptions"
+                    :placeholder=lang.ssSelectSubj
+                    style="width: 100%;"
+                  />
+                </div>
+                <div class="form-item required">
+                  <label class="form-label">{{ lang.ssClass }}{{ lang.ssLabel }}</label>
+                  <selectTag
+                    v-model="selectedGrade"
+                    :options="gradeOptions"
+                    :placeholder=lang.ssSelectGrade
+                    style="width: 100%;"
+                  />
                 </div>
               </div>
-
               <div class="form-row">
+                <div class="form-item required" style="flex: 2;">
+                  <label class="form-label">{{ lang.ssClass }}</label>
+                  <selectTag
+                    v-model="checkboxList2"
+                    :options="classOptions"
+                    :placeholder=lang.ssSelectClass
+                    style="width: 100%;"
+                  />
+                </div>
+              </div>
+
+              <!-- <div class="form-row">
                 <div class="form-item required">
                   <label class="form-label">{{ lang.ssGradeType }}</label>
-                  <el-select v-model="selectedGrade" :placeholder="lang.ssSelectGrade" class="custom-select" collapse-tags multiple
-                    style="width: 100%">
-                    <el-option v-for="option in gradeOptions" :key="option.id" :label="option.name"
-                      :value="option.id"></el-option>
-                  </el-select>
+                  <selectTag
+                    v-model="selectedGrade"
+                    :options="gradeOptions"
+                    :placeholder=lang.ssSelectGrade
+                    style="width: 100%;"
+                  />
                 </div>
 
                 <div class="form-item required">
                   <label class="form-label">{{ lang.ssClass }}</label>
-                  <el-select v-model="checkboxList2" :placeholder="lang.ssSelectClass" class="custom-select" collapse-tags multiple
-                    style="width: 100%">
-                    <el-option v-for="option in classOptions" :key="option.id" :label="option.name"
-                      :value="option.id"></el-option>
-                  </el-select>
+                  <selectTag
+                    v-model="checkboxList2"
+                    :options="classOptions"
+                    :placeholder=lang.ssSelectClass
+                    style="width: 100%;"
+                  />
                 </div>
-              </div>
+              </div> -->
 
               <div class="form-row">
                 <div class="form-item required">
@@ -921,6 +966,8 @@ import BilibiliSearchDialog from "./dialog/BilibiliSearchDialog2.vue";
 import { v4 as uuidv4 } from "uuid";
 import InteractiveToolDialog from "./dialog/InteractiveToolDialog.vue";
 import VideoUploadDialog from "./dialog/VideoUploadDialog2.vue";
+import ConfirmDialog from "../../common/ConfirmDialog";
+import selectTag from "./dialog/selectTag3.vue";
 
 var OpenCC = require("opencc-js");
 let converter = OpenCC.Converter({
@@ -973,7 +1020,9 @@ export default {
     InteractiveToolDialog,
     VideoUploadDialog,
     BilibiliSearchDialog,
-    appDialog
+    appDialog,
+    ConfirmDialog,
+    selectTag
   },
   data() {
     return {
@@ -989,6 +1038,12 @@ export default {
       dialogVisibleBasicInfo: false,
       dialogVisibleClass: false,
       dialogVisiblePublish: false,
+      confirmVisible: false,
+      confirmTitle: '',
+      confirmMessage: '',
+      confirmConfirmText: '',
+      confirmCancelText: '',
+      confirmCallback: null,
       loading: false,
       courseName: "",
       isTeacherSee: false,
@@ -1305,7 +1360,7 @@ export default {
       // 暂时使用模拟数据
       this.classOptions = this.grade2.map(item => ({
         id: item.id,
-        name: item.name
+        name: item.classname ? item.classname + '-' + item.name : item.name
       }));
     },
     // 确认发布
@@ -1614,45 +1669,47 @@ export default {
       // }
     },
     lastSteps() {
-      this.$confirm(this.lang.ssSaveEdit, this.lang.ssTip, {
-        confirmButtonText: this.lang.ssSave,
-        cancelButtonText: this.lang.ssNotSave,
-        distinguishCancelAndClose: true,
-        type: "warning"
-      })
-        .then(() => {
-          console.log("保存已编辑内容");
-          if (this.cid == "" || this.cid == undefined) {
-            if (this.courseName == "") {
-              this.$message.error(this.lang.ssFillCourseName2);
-              return;
-            } else {
-              this.addWork();
-            }
+      this.confirmTitle = this.lang.ssTip;
+      this.confirmMessage = this.lang.ssSaveEdit;
+      this.confirmConfirmText = this.lang.ssSave;
+      this.confirmCancelText = this.lang.ssNotSave;
+      this.confirmCallback = () => {
+        console.log("保存已编辑内容");
+        if (this.cid == "" || this.cid == undefined) {
+          if (this.courseName == "") {
+            this.$message.error(this.lang.ssFillCourseName2);
+            return;
           } else {
-            if (this.courseName == "") {
-              this.$message.error(this.lang.ssFillCourseName2);
-              return;
-            } else {
-              this.updateWork();
-            }
+            this.addWork();
           }
-        })
-        .catch(v => {
-          console.log(v);
-          if (v == "cancel") {
-            this.goTo(
-              "/course?userid=" +
-              this.userid +
-              "&oid=" +
-              this.oid +
-              "&org=" +
-              this.org +
-              "&role=" +
-              this.role
-            );
+        } else {
+          if (this.courseName == "") {
+            this.$message.error(this.lang.ssFillCourseName2);
+            return;
+          } else {
+            this.updateWork();
           }
-        });
+        }
+      };
+      this.confirmVisible = true;
+    },
+    handleConfirm() {
+      if (this.confirmCallback) {
+        this.confirmCallback();
+      }
+    },
+    handleCancel() {
+      console.log("不保存已编辑内容");
+      this.goTo(
+        "/course?userid=" +
+        this.userid +
+        "&oid=" +
+        this.oid +
+        "&org=" +
+        this.org +
+        "&role=" +
+        this.role
+      );
     },
     //获取ppt的数据
     async getPPtJson() {
@@ -4029,6 +4086,11 @@ export default {
   padding: 0 30px 0 15px;
 }
 
+.search_input >>> .el-input.is-active .el-input__inner, 
+.search_input >>> .el-input__inner:focus{
+  border-color: #f8932f;
+}
+
 .search_img {
   width: 20px;
   height: 20px;
@@ -4901,8 +4963,8 @@ export default {
 }
 
 .btn-cancel:hover {
-  border-color: #c6e2ff;
-  color: #409eff;
+  border-color: #ff9500;
+  color: #ff9500;
 }
 
 .publish-modal-footer .btn-cancel {

+ 2 - 2
src/components/pages/pptEasy/dialog/BilibiliSearchDialog2.vue

@@ -109,7 +109,7 @@
 				</div>
 
 				<!-- 分页控件 -->
-				<div class="pagination-box" v-if="data.length > 0">
+				<div class="pagination-box" v-if="false">
 					<el-button 
 						:disabled="currentPage === 1" 
 						@click="prevPage"
@@ -123,7 +123,7 @@
 					>{{ lang.ssNextPage }}→</el-button>
 				</div>
 			</div>
-			<div class="modal-footer">
+			<div class="modal-footer" v-show="false">
 				<el-button @click="handleClose" style="background-color: #fff;border-color: #DCDFE6;color: #606266;">{{ lang.ssClose }}</el-button>
 			</div>
 		</div>

+ 157 - 0
src/components/pages/pptEasy/dialog/selectTag3.vue

@@ -0,0 +1,157 @@
+<template>
+  <main>
+    <el-select
+      ref="select"
+      v-model="values"
+      multiple
+      style="width:100%"
+      :placeholder=lang.pleaseSelect3
+      @change="handleChange"
+      @remove-tag="removeTag"
+      class="tagS"
+    >
+      <el-option
+        class="tagOption"
+        v-for="item in options"
+        :key="item.id"
+        :disabled="disabled && item.id === Number(judgingCondition)"
+        :label="item.name"
+        :value="item.id"
+      />
+    </el-select>
+  </main>
+</template>
+<script>
+export default {
+  name: 'select-tags',
+  props: {
+    // 选项
+    options: {
+      type: Array,
+      default: () => []
+    },
+    // 选中的值
+    value: {
+      type: Array,
+      default: () => []
+    },
+    // 提示
+    placeholder: {
+      type: String,
+      default: ''
+    },
+    // 是否禁用
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    // 判断条件
+    judgingCondition: {
+      type: String | Number,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      observer: null,
+      hideDom: null
+    };
+  },
+  computed: {
+    /**
+     * @description 获取当前选中的值
+    */
+    values: {
+      get() {
+        return this.value;
+      },
+      set(val) {
+        this.$emit('input', val);
+      }
+    }
+  },
+  mounted() {
+    this.mutationObserver();
+  },
+  beforeDestroy() {
+    this.observer.disconnect();
+  },
+  methods: {
+    /**
+     * @description 监听tag变化
+     */
+    mutationObserver() {
+      const tagLIstDom = this.$refs.select.$el.querySelector('.el-select__tags');
+      const tagSpanDom = this.$refs.select.$el.querySelector('.el-select__tags > span');
+
+      // 创建隐藏的计数节点
+      this.hideDom = document.createElement('span');
+      this.hideDom.classList.add('count-node');
+      tagSpanDom.append(this.hideDom);
+
+      const config = { childList: true };
+
+      const callback = mutationsList => {
+        mutationsList.forEach(item => {
+          console.log(item);
+          
+          if (item.type === 'childList') {
+            const tagList = item.target.childNodes;
+            let tagWidth = 0;
+            let tagNum = 0;
+            let availableTagWidth = 0;
+
+            for (let i = 0; i < tagList.length; i++) {
+              const e = tagList[i];
+              if (tagWidth > tagLIstDom.offsetWidth) {
+                e.style.display = 'none';
+              } else {
+                e.style.display = 'inline-block';
+              }
+              tagWidth += e.offsetWidth + 5;
+
+              if (tagWidth > tagLIstDom.offsetWidth) {
+                e.style.display = 'none';
+              } else {
+                e.style.display = 'inline-block';
+              }
+
+              if (e.style.display !== 'none') {
+                tagNum++;
+                this.hideDom.style.display = 'none';
+                const margin = tagNum === 1 ? 0 : 7;
+                availableTagWidth += e.offsetWidth + margin;
+              } else {
+                this.hideDom.style.display = 'inline-block';
+                this.hideDom.style.left = `${availableTagWidth}px`;
+                this.hideDom.innerHTML = `+${tagList.length - tagNum}`;
+              }
+            }
+          }
+        });
+      };
+
+      this.observer = new MutationObserver(callback);
+      this.observer.observe(tagSpanDom, config);
+    },
+    /**
+     * @description 选择框改变
+     */
+    handleChange() {
+      this.$emit('change', this.value);
+    },
+    /**
+     *
+     * @param val 当前角色绑定的分校不允许删除
+     */
+    removeTag(val) {
+      this.$emit('remove-tag', val);
+    }
+  }
+};
+</script>
+<style scoped>
+.tagS >>> .el-input__inner:focus {
+  border-color: #ef9e28;
+}
+</style>