Jelajahi Sumber

系统优化

dsy 3 bulan lalu
induk
melakukan
bff5ef628b

+ 1 - 1
.env

@@ -11,4 +11,4 @@ VUE_APP_BookWebSI = '/GCLSBookWebSI/ServiceInterface'
 VUE_APP_EepServer = '/EEPServer/SI'
 
 #version
-VUE_APP_VERSION = '2026.07.11'
+VUE_APP_VERSION = '2026.07.14'

+ 1 - 1
packages/package.json

@@ -1,6 +1,6 @@
 {
   "name": "eep-ui",
-  "version": "0.0.18",
+  "version": "0.0.21",
   "main": "eep/eep-ui.umd.js",
   "style": "eep/eep-ui.css",
   "exports": {

+ 13 - 8
src/api/app.js

@@ -62,15 +62,20 @@ export async function fileUpload(
   store?.commit(`app/${app.SET_UPLOAD_CONTROLLER}`, controller);
 
   try {
-    const res = await http.postForm('/FileServer/WebFileUpload', formData, {
-      params: {
-        SecurityLevel,
+    const res = await http.postForm(
+      '/FileServer/WebFileUpload',
+      formData,
+      {
+        params: {
+          SecurityLevel,
+        },
+        signal: controller.signal,
+        transformRequest: [(data) => data],
+        onUploadProgress,
+        timeout: 0,
       },
-      signal: controller.signal,
-      transformRequest: [(data) => data],
-      onUploadProgress,
-      timeout: 0,
-    });
+      true,
+    );
     store?.commit(`app/${app.SET_UPLOAD_INFO}`, { progress: 1 });
     return res;
   } finally {

+ 19 - 0
src/api/project.js

@@ -261,6 +261,15 @@ export function ShangjiaBook(data) {
 }
 
 /**
+ * @description 下架教材
+ * @param {object} data
+ * @param {string} data.project_id 项目ID
+ */
+export function XiajiaBook(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=project_manager-XiajiaBook`, data);
+}
+
+/**
  * @description 驳回上架教材申请
  * @param {object} data
  * @param {string} data.project_id 项目ID
@@ -401,3 +410,13 @@ export function GetColorList_RecentlyUsed(data) {
     data,
   );
 }
+
+/**
+ * @description 保存颜色(最近使用)
+ * @param {object} data
+ * @param {number} data.type 类型 1:背景色 2:文字颜色 3.主题色
+ * @param {string} data.color 颜色值 "FAF9DE"
+ */
+export function SaveColor_RecentlyUsed(data) {
+  return http.post(`${process.env.VUE_APP_EepServer}?MethodName=project_resource_manager-SaveColor_RecentlyUsed`, data);
+}

+ 7 - 1
src/components/ColorPicker.vue

@@ -4,11 +4,12 @@
     popper-class="color-picker has-history"
     v-bind="$attrs"
     v-on="$listeners"
+    @change="saveColorRecentlyUsed($event)"
   />
 </template>
 
 <script>
-import { GetColorList_Common, GetColorList_RecentlyUsed } from '@/api/project';
+import { GetColorList_Common, GetColorList_RecentlyUsed, SaveColor_RecentlyUsed } from '@/api/project';
 
 export default {
   name: 'ColorPicker',
@@ -49,6 +50,11 @@ export default {
         this.recentlyUsedList = color_list;
       });
     },
+    saveColorRecentlyUsed(color) {
+      SaveColor_RecentlyUsed({ type: this.type, color: color.replace('#', '') }).then(() => {
+        this.getColorList_RecentlyUsed();
+      });
+    },
   },
 };
 </script>

+ 4 - 0
src/components/CoursewareList.vue

@@ -254,10 +254,14 @@ export default {
       }
 
       .card-name {
+        width: 245px;
         margin-bottom: 12px;
+        overflow: hidden;
         font-size: 15px;
         font-weight: 600;
         color: #1f2937;
+        text-overflow: ellipsis;
+        white-space: nowrap;
       }
 
       .card-meta {

+ 42 - 27
src/views/book/courseware/create/components/CreateCanvas.vue

@@ -1246,16 +1246,15 @@ export default {
           this.calculateGridObject();
         }
       }
-      this.curType = '';
-      this.curParams = {};
-      this.enterCanvas = false;
+      this.resetMoveData();
     },
     /**
      * 处理组件移动
      * 组件拖拽移动后,先删除组件,再根据拖拽位置计算插入行、列、格子
      */
     async handleComponentMove() {
-      const component = this.findChildComponentByKey(`grid-${this.curParams.id}`);
+      const oldID = this.curParams?.id;
+      const component = this.findChildComponentByKey(`grid-${oldID}`);
       // 获取组件内容,保存后再插入到新的位置
       const requestData = component.getComponentRequestContent();
 
@@ -1276,7 +1275,9 @@ export default {
         grid,
         rowNum,
       };
-      this.deleteComponent(this.curParams.id);
+
+      // 根据 oldID 改变 data.row_list 中,将对应ID 改为新ID,并返回新ID,在删除时使用
+      const deleteID = this.replaceGridIdByOldId(oldID);
 
       await ContentSaveCoursewareComponentContent(requestData);
 
@@ -1285,38 +1286,49 @@ export default {
       }
 
       if (this.curRow >= -1 && this.curCol > -1 && this.curGrid <= -1) {
-        // 当拖拽组件和放置位置在同一列内,且行内组件数量为 1,将 curRow 减 1,才能正确插入
-        if ('col' in this.curParams) {
-          const { row, rowNum } = this.curParams;
-          if (row === this.curRow && rowNum === 1) {
-            this.curRow = Math.max(0, this.curRow - 1);
-            this.calculateRowInsertedObject();
-            return;
-          }
-        }
         this.calculateColObject();
       }
 
       if (this.curRow >= -1 && this.curCol > -1 && this.curGrid > -1) {
-        if ('col' in this.curParams) {
-          const { col, row, grid } = this.curParams;
+        this.calculateGridObject();
+      }
 
-          // 当拖拽组件和放置位置在同一列内,将 curGrid 减 1,对应上面的删除组件,才能正确插入
-          if (col === this.curCol && row === this.curRow && grid < this.curGrid) {
-            this.curGrid = Math.max(0, this.curGrid - 1);
-          }
+      this.$nextTick(() => {
+        this.deleteComponent(deleteID);
+      });
 
-          // 当拖拽组件和放置位置在同一列内,且行内组件数量为 1,将 curRow 减 1,才能正确插入
-          if (col === this.curCol && row === this.curRow && grid === this.curGrid) {
-            this.curRow = Math.max(0, this.curRow - 1);
-            this.calculateRowInsertedObject();
-            return;
+      this.resetMoveData();
+    },
+    /**
+     * 根据旧组件 id 将 row_list 中对应 grid 的 id 替换为新 id,并返回新 id
+     * @param {String} oldID 旧组件 id
+     * @returns {String} 新组件 id
+     */
+    replaceGridIdByOldId(oldID) {
+      if (!oldID) return oldID;
+
+      const allIds = this.data.row_list.flatMap((row) =>
+        row.col_list.flatMap((col) => col.grid_list.map((grid) => grid.id)),
+      );
+
+      let newID = `ID-${getRandomNumber(12, true)}`;
+      while (allIds.includes(newID)) {
+        newID = `ID-${getRandomNumber(12, true)}`;
+      }
+
+      for (const row of this.data.row_list) {
+        for (const col of row.col_list) {
+          const targetGrid = col.grid_list.find((grid) => grid.id === oldID);
+          if (targetGrid) {
+            targetGrid.id = newID;
+            return newID;
           }
         }
-
-        this.calculateGridObject();
       }
 
+      return oldID;
+    },
+    resetMoveData() {
       this.curType = '';
       this.curParams = {};
       this.enterCanvas = false;
@@ -1401,6 +1413,7 @@ export default {
         });
         grid[this.curGrid].width = `${w}fr`;
       }
+      this.resetMoveData();
     },
     /**
      * 计算列插入的对象
@@ -1438,6 +1451,7 @@ export default {
           },
         ],
       });
+      this.resetMoveData();
     },
     /**
      * 计算行插入的对象
@@ -1470,6 +1484,7 @@ export default {
           },
         ],
       });
+      this.resetMoveData();
     },
     /**
      * 获取拖拽元素和画布的边距差值

+ 1 - 1
src/views/book/courseware/create/components/question/fill/Fill.vue

@@ -9,7 +9,7 @@
           ref="richText"
           v-model="data.content"
           :is-fill="true"
-          toolbar="fontselect fontsizeselect forecolor backcolor | lineheight paragraphSpacing underline | bold italic strikethrough alignleft aligncenter alignright bullist numlist dotEmphasis"
+          toolbar="fontselect fontsizeselect forecolor backcolor | lineheight paragraphSpacing fullwidthspace underline | bold italic strikethrough alignleft aligncenter alignright bullist numlist dotEmphasis"
           :wordlimit-num="false"
           :font-size="data?.unified_attrib?.font_size"
           :font-family="data?.unified_attrib?.font"

+ 13 - 7
src/views/home/index.vue

@@ -33,7 +33,7 @@
         </div>
       </div>
 
-      <div class="list-section">
+      <div v-loading="loading" class="list-section">
         <el-table
           v-if="currentOverview === overviewList[0].key"
           :key="overviewList[0].key"
@@ -366,6 +366,7 @@ export default {
       cur_page: 1,
       projectList: [], // 项目列表
       toolModalVisible: false,
+      loading: false, // 列表加载状态
     };
   },
   created() {
@@ -387,12 +388,17 @@ export default {
         cur_page: this.cur_page,
         type: this.overviewList.find((item) => item.key === this.currentOverview)?.type,
       };
-      PageQueryMyProjectList({ ...params, ...data }).then(({ project_list, total_count, cur_page }) => {
-        this.projectList = project_list;
-        this.total = total_count;
-        this.page_capacity = data?.page_capacity || this.page_capacity;
-        this.cur_page = cur_page;
-      });
+      this.loading = true;
+      PageQueryMyProjectList({ ...params, ...data })
+        .then(({ project_list, total_count, cur_page }) => {
+          this.projectList = project_list;
+          this.total = total_count;
+          this.page_capacity = data?.page_capacity || this.page_capacity;
+          this.cur_page = cur_page;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
     },
     /**
      * @description 切换概览后重置页码并获取列表数据

+ 1 - 1
src/views/personal_workbench/courseware_check/index.vue

@@ -12,7 +12,7 @@
           <img v-if="item.cover_iamge_file_url.length > 0" :src="item.cover_iamge_file_url" alt="封面" />
         </div>
         <div class="card-right" @click="jumpToDetail(item.id)">
-          <div class="card-name">{{ item.name || '-' }}</div>
+          <div class="card-name" :title="item.name">{{ item.name || '-' }}</div>
           <div class="card-meta">
             <div class="meta-row">
               <span class="meta-label">项目组长:</span>

+ 1 - 1
src/views/personal_workbench/courseware_edit/index.vue

@@ -12,7 +12,7 @@
           <img v-if="item.cover_iamge_file_url.length > 0" :src="item.cover_iamge_file_url" alt="封面" />
         </div>
         <div class="card-right" @click="jumpToDetail(item.id)">
-          <div class="card-name">{{ item.name || '-' }}</div>
+          <div class="card-name" :title="item.name">{{ item.name || '-' }}</div>
           <div class="card-meta">
             <div class="meta-row">
               <span class="meta-label">项目组长:</span>

+ 1 - 1
src/views/personal_workbench/courseware_project/index.vue

@@ -12,7 +12,7 @@
           <img v-if="item.cover_iamge_file_url.length > 0" :src="item.cover_iamge_file_url" alt="封面" />
         </div>
         <div class="card-right" @click="jumpToDetail(item.id)">
-          <div class="card-name">{{ item.name || '-' }}</div>
+          <div class="card-name" :title="item.name">{{ item.name || '-' }}</div>
           <div class="card-meta">
             <div class="meta-row">
               <span class="meta-label">项目组长:</span>

+ 20 - 6
src/views/personal_workbench/project/ProductionEditorialManage.vue

@@ -324,10 +324,17 @@ export default {
       this.curSelectId = id;
     },
     chapterAddCoursewareToBook(data) {
-      ChapterAddCoursewareToBook(data).then(() => {
-        this.getBookChapterStructExpandList();
-        this.visible = false;
+      const loading = this.$loading({
+        text: '正在添加课件,请稍候...',
       });
+      ChapterAddCoursewareToBook(data)
+        .then(() => {
+          this.getBookChapterStructExpandList();
+          this.visible = false;
+        })
+        .finally(() => {
+          loading.close();
+        });
     },
     /**
      * 点击目录外部区域,取消选中
@@ -373,10 +380,17 @@ export default {
      * 添加章节
      */
     addChapterNode(data) {
-      ChapterAddChapterToBook(data).then(() => {
-        this.getBookChapterStructExpandList();
-        this.visible = false;
+      const loading = this.$loading({
+        text: '正在添加章节,请稍候...',
       });
+      ChapterAddChapterToBook(data)
+        .then(() => {
+          this.getBookChapterStructExpandList();
+          this.visible = false;
+        })
+        .finally(() => {
+          loading.close();
+        });
     },
     /**
      * 删除章节(二次确认)

+ 2 - 1
src/views/personal_workbench/project/components/AddChapter.vue

@@ -67,6 +67,8 @@ export default {
           this.$refs.form.clearValidate();
           this.$refs.name.focus();
         });
+      } else {
+        this.data.name = '';
       }
     },
   },
@@ -88,7 +90,6 @@ export default {
           chapter_id: this.curSelectId,
         });
       }
-      this.data.name = '';
     },
   },
 };

+ 6 - 1
src/views/project_manage/org/book/index.vue

@@ -12,11 +12,16 @@
         <el-table-column prop="sn" label="编号" width="140" header-align="center" />
         <el-table-column prop="name" label="名称" width="240" header-align="center" />
         <el-table-column prop="project_sn" label="项目编号" width="140" header-align="center" />
-        <el-table-column prop="project_name" label="项目名称" width="240" header-align="center" />
+        <el-table-column prop="project_name" label="教材名称" width="240" header-align="center" />
         <el-table-column prop="org_name" label="所属机构" width="120" header-align="center" />
         <el-table-column prop="content_count" label="教材页面数" width="100" header-align="center" />
         <el-table-column prop="shangjia_time" label="上架时间" width="180" header-align="center" />
         <el-table-column prop="version" label="版本号" width="90" header-align="center" align="center" />
+        <el-table-column prop="revise_count" label="修订版次" align="center" header-align="center">
+          <template slot-scope="{ row }">
+            {{ row.revise_count === 0 ? `首版` : `第${row.revise_count}次修订` }}
+          </template>
+        </el-table-column>
         <el-table-column label="已申请下架" align="center" header-align="center">
           <template slot-scope="{ row }">
             <span style="color: #f53f3f">

+ 64 - 4
src/views/project_manage/org/project/index.vue

@@ -2,6 +2,24 @@
   <div class="project org">
     <ProjectMenu cur-key="org/project" />
 
+    <div id="query-form">
+      <el-form inline>
+        <el-form-item prop="name" label="名称">
+          <el-input v-model="queryForm.name" clearable @change="pageQueryProjectList_OrgManager()" />
+        </el-form-item>
+        <el-form-item prop="status" label="状态">
+          <el-select v-model="queryForm.status" @change="pageQueryProjectList_OrgManager()">
+            <el-option label="全部" :value="-1" />
+            <el-option label="制作中" :value="0" />
+            <el-option label="审核中" :value="1" />
+            <el-option label="已终审" :value="2" />
+            <el-option label="已上架" :value="3" />
+            <el-option label="已下架" :value="4" />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+
     <div class="project-list">
       <el-table :data="list">
         <el-table-column label="序号" width="60" align="center" header-align="center" class-name="index-column">
@@ -16,8 +34,8 @@
         <el-table-column prop="leader_name_desc" label="项目组长" width="140" header-align="center" />
         <el-table-column prop="create_time" label="创建时间" width="180" header-align="center" />
         <el-table-column prop="content_count_SJ" label="教材页面数" width="100" header-align="center" />
-        <el-table-column prop="status_name" label="状态" width="120" header-align="center" />
-        <el-table-column prop="request_status_name" label="申请状态" header-align="center" />
+        <el-table-column prop="status_name" label="状态" align="center" width="120" header-align="center" />
+        <el-table-column prop="request_status_name" label="申请状态" align="center" header-align="center" />
 
         <el-table-column fixed="right" label="操作" width="350" align="center" header-align="center">
           <template slot-scope="{ row }">
@@ -36,6 +54,8 @@
               <span class="link" @click="projectAuditOperate(row.id, 'true', row.request_status)"> 审核通过 </span>
               <span class="link" @click="projectAuditOperate(row.id, 'false', row.request_status)">审核拒绝</span>
             </template>
+            <span v-if="isTrue(row.is_can_shangjia)" class="link" @click="shangjiaProject(row.id)">上架</span>
+            <span v-if="isTrue(row.is_can_xiajia)" class="link" @click="xiajiaProject(row.id)">下架</span>
           </template>
         </el-table-column>
       </el-table>
@@ -51,7 +71,7 @@ import ProjectMenu from '@/views/project_manage/common/ProjectMenu.vue';
 
 import { PageQueryProjectList_OrgManager } from '@/api/list';
 import { isTrue } from '@/utils/validate';
-import { ProjectAuditOperate } from '@/api/project';
+import { ProjectAuditOperate, ShangjiaBook, XiajiaBook } from '@/api/project';
 
 export default {
   name: 'OrgProjectPage',
@@ -65,6 +85,10 @@ export default {
       total: 0,
       cur_page_begin_index: 0,
       isTrue,
+      queryForm: {
+        name: '',
+        status: -1,
+      },
     };
   },
   methods: {
@@ -101,7 +125,13 @@ export default {
         .catch(() => {});
     },
     pageQueryProjectList_OrgManager(data) {
-      PageQueryProjectList_OrgManager({ ...data, status: -1 })
+      const _data = {
+        page_capacity: 10,
+        cur_page: 1,
+        ...data,
+        ...this.queryForm,
+      };
+      PageQueryProjectList_OrgManager(_data)
         .then(({ total_count, cur_page_begin_index, project_list }) => {
           this.total = total_count;
           this.cur_page_begin_index = cur_page_begin_index;
@@ -112,6 +142,36 @@ export default {
     previewProject(projectId) {
       this.$router.push({ path: `/project_manage/org/project/preview/${projectId}` });
     },
+    shangjiaProject(project_id) {
+      this.$confirm('确定要上架该教材吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      })
+        .then(() => {
+          ShangjiaBook({ project_id })
+            .then(() => {
+              this.$message.success('操作成功');
+              this.$refs.pagination.getList();
+            })
+            .catch(() => {});
+        })
+        .catch(() => {});
+    },
+    xiajiaProject(project_id) {
+      this.$confirm('确定要下架该教材吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+      })
+        .then(() => {
+          XiajiaBook({ project_id })
+            .then(() => {
+              this.$message.success('操作成功');
+              this.$refs.pagination.getList();
+            })
+            .catch(() => {});
+        })
+        .catch(() => {});
+    },
   },
 };
 </script>