dsy 2 месяцев назад
Родитель
Сommit
11ea7fec52

+ 1 - 1
.env

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

+ 18 - 0
src/common/data.js

@@ -21,3 +21,21 @@ export const unified_title = {
   italic: 'false', // 斜体
   indent: 0, // 缩进
 };
+
+// 状态颜色列表
+export const stateColorList = [
+  {
+    color: '#F59E0B',
+    bc: '#FEF3C7',
+  },
+  {
+    color: '#8B5CF6',
+    bc: '#EDE9FE',
+  },
+  {
+    color: '#3B82F6',
+    bc: '#DBEAFE',
+  },
+  { color: '#10B981', bc: '#D1FAE5' },
+  { color: '#FF4757', bc: '#FFE5E5' },
+];

+ 9 - 4
src/views/create_project/createProject.vue

@@ -40,6 +40,10 @@
             <label>出版单位</label>
             <el-input v-model="project.publisher" type="text" placeholder="请输入出版单位" maxlength="20" />
           </div>
+          <div class="project-item label-tworow">
+            <label>国标图书编号<br />(ISBN)</label>
+            <el-input v-model="project.isbn" type="text" placeholder="请输入国标图书编号(ISBN)" maxlength="20" />
+          </div>
           <div class="project-item label-input">
             <label>作品标签</label>
             <div class="label-input-content">
@@ -173,6 +177,7 @@ export default {
         language: '',
         topic: '',
         publisher: '',
+        isbn: '',
         content_intro: '',
         background: '',
         author_intro: '',
@@ -310,7 +315,7 @@ export default {
               align-items: center;
               justify-content: center;
               width: 418px;
-              height: 280px;
+              height: 330px;
               overflow: hidden;
               cursor: pointer;
               border: 1px dashed #d9d9d9;
@@ -323,9 +328,9 @@ export default {
 
             &-icon {
               width: 418px;
-              height: 280px;
+              height: 330px;
               font-size: 28px;
-              line-height: 280px;
+              line-height: 330px;
               color: #8c939d;
               text-align: center;
             }
@@ -333,7 +338,7 @@ export default {
             .avatar {
               display: block;
               max-width: 418px;
-              max-height: 280px;
+              max-height: 330px;
             }
           }
         }

+ 20 - 20
src/views/home/index.vue

@@ -210,16 +210,20 @@
           <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
           <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
           <el-table-column prop="version" label="版本" width="80" align="center" header-align="center" />
-          <el-table-column prop="member_name_desc" label="作者" width="220" align="center" header-align="center" />
+          <el-table-column prop="editor" label="作者" width="220" align="center" header-align="center" />
           <el-table-column prop="shangjia_date" label="上架日期" width="150" align="center" header-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}修订` }}
+              {{ row.revise_count === 0 ? `首版` : `第${row.revise_count}修订` }}
             </template>
           </el-table-column>
           <el-table-column fixed="right" label="操作" align="center" header-align="center">
             <template slot-scope="{ row }">
               <el-button type="text" @click="jumpDetail(row.id, 'launch')">进入</el-button>
+              <template v-if="row.pre_project_id">
+                <span class="line"></span>
+                <el-button type="text" @click="jumpDetail(row.pre_project_id, 'launch')">查看上一版本</el-button>
+              </template>
             </template>
           </el-table-column>
         </el-table>
@@ -250,10 +254,11 @@
 </template>
 
 <script>
+import PaginationPage from '@/components/PaginationPage.vue';
+
 import { GetMyProjectStatInfo } from '@/api/user';
 import { PageQueryMyProjectList } from '@/api/list';
-
-import PaginationPage from '@/components/PaginationPage.vue';
+import { stateColorList } from '@/common/data';
 
 export default {
   name: 'HomePage',
@@ -347,22 +352,7 @@ export default {
           type: 4,
         },
       ],
-      stateColorList: [
-        {
-          color: '#F59E0B',
-          bc: '#FEF3C7',
-        },
-        {
-          color: '#8B5CF6',
-          bc: '#EDE9FE',
-        },
-        {
-          color: '#3B82F6',
-          bc: '#DBEAFE',
-        },
-        { color: '#10B981', bc: '#D1FAE5' },
-        { color: '#FF4757', bc: '#FFE5E5' },
-      ],
+      stateColorList,
       // 项目统计信息
       stateInfo: {
         count_QB: 0, // 全部
@@ -621,6 +611,16 @@ export default {
     border: 1px solid #eef2f7;
     border-radius: 14px;
 
+    .line {
+      display: inline-block;
+      width: 1px;
+      height: 18px;
+      min-height: 18px;
+      margin: 0 8px;
+      vertical-align: middle;
+      background-color: #165dff;
+    }
+
     :deep(.el-table__header-wrapper th) {
       height: 48px;
       padding: 0;

+ 187 - 22
src/views/personal_workbench/courseware_detail/index.vue

@@ -3,7 +3,7 @@
   <div class="courseware-detail">
     <div class="page-header">
       <span v-if="normalizedType !== 'launch'" class="header-back" @click="goBack">
-        <SvgIcon icon-class="courseware-undo" size="16" />
+        <i class="el-icon-back"></i>
       </span>
     </div>
     <main class="courseware-detail__main">
@@ -28,24 +28,30 @@
               <span class="value">{{ project.editor || '-' }}</span>
             </div>
             <div class="info-item">
+              <span class="label">项目组长:</span>
+              <span class="value">{{ project.leader_name_desc || '-' }}</span>
+            </div>
+            <div class="info-item">
               <span class="label">出版单位:</span>
               <span class="value">{{ project.publisher || '-' }}</span>
             </div>
             <div class="info-item">
-              <span class="label">计划完成日期:</span>
+              <span class="label">计划出版日期:</span>
               <span class="value">{{ project.plan_publish_date || '-' }}</span>
             </div>
-            <div class="info-item">
-              <span class="label">适用年龄:</span>
-              <span class="value">{{ '-' }}</span>
-            </div>
-            <div class="info-item">
-              <span class="label">语言水平:</span>
-              <span class="value">{{ '-' }}</span>
+            <div class="info-item info-item--full">
+              <span class="label">ISBN:</span>
+              <span class="value">{{ project.isbn || '-' }}</span>
             </div>
-            <div class="info-item">
-              <span class="label">语种:</span>
-              <span class="value">{{ project.language || '-' }}</span>
+            <div class="info-item info-item--full">
+              <span class="label">标签:</span>
+              <span class="value">
+                <div class="label-list">
+                  <span v-for="(label, index) in project.label_list || []" :key="index" class="label-item">
+                    {{ label }}
+                  </span>
+                </div>
+              </span>
             </div>
           </div>
           <div class="book-intro">简介:{{ project.content_intro || '-' }}</div>
@@ -73,8 +79,17 @@
           </div>
         </div>
         <div v-if="normalizedType === 'manage'" class="apply-wrap">
-          <div v-if="project.status_name.length > 0" class="request-status">{{ project.status_name }}</div>
-          <div v-if="project.request_status_name.length > 0" class="request-status">
+          <div
+            v-if="project.status_name?.length > 0"
+            :style="{
+              color: stateColorList[project.status].color,
+              backgroundColor: stateColorList[project.status].bc,
+            }"
+            class="status"
+          >
+            {{ project.status_name }}
+          </div>
+          <div v-if="project.request_status_name?.length > 0" class="request-status">
             {{ project.request_status_name }}
           </div>
           <div style="flex: 1"></div>
@@ -82,10 +97,12 @@
             v-for="item in operateButtons"
             :key="item.type"
             type="button"
-            class="btn-apply"
+            :class="['btn-operate', item.customClass]"
+            :style="item.style"
             :disabled="operateLoadingType === item.type"
             @click="projectRequestOperate(item.type)"
           >
+            <SvgIcon :icon-class="item.icon" />
             {{ item.label }}
           </button>
         </div>
@@ -185,6 +202,7 @@
 <script>
 import BookUnifiedAttr from '@/views/personal_workbench/project/components/BookUnifiedAttr.vue';
 
+import { stateColorList } from '@/common/data';
 import { GetProjectInfo, ProjectRequestOperate } from '@/api/project';
 
 const TYPE_LIST = ['edit', 'manage', 'audit', 'launch'];
@@ -199,11 +217,36 @@ const PROGRESS_STEP_CONFIG = [
 
 // 操作按钮配置
 const OPERATE_BUTTON_CONFIG = [
-  { type: 1, label: '申请上架' },
-  { type: 2, label: '申请下架' },
-  { type: 3, label: '申请修订' },
-  { type: 4, label: '撤回重做' },
-  { type: 5, label: '申请改错' },
+  {
+    type: 1,
+    label: '申请上架',
+    icon: 'courseware-upload',
+    customClass: 'apply',
+  },
+  {
+    type: 2,
+    label: '申请下架',
+    icon: 'courseware-download',
+    customClass: 'shelve',
+  },
+  {
+    type: 3,
+    label: '申请修订',
+    icon: 'courseware-file-edit',
+    customClass: 'revise',
+  },
+  {
+    type: 4,
+    label: '撤回申请',
+    icon: 'courseware-undo',
+    customClass: 'revoke',
+  },
+  {
+    type: 5,
+    label: '申请改错',
+    icon: 'courseware-pencil',
+    customClass: 'error-correction',
+  },
 ];
 
 function isProgressFinished(value) {
@@ -220,6 +263,7 @@ export default {
       project: {},
       operateLoadingType: null,
       visibleAttr: false,
+      stateColorList,
     };
   },
   computed: {
@@ -246,7 +290,7 @@ export default {
     },
     currentStage() {
       const nextUnfinishedStep = this.progressSteps.find((step) => !step.finished);
-      return nextUnfinishedStep ? nextUnfinishedStep.index : this.progressSteps.length;
+      return nextUnfinishedStep ? nextUnfinishedStep.index : this.progressSteps?.length;
     },
     curCanOperateButtonList() {
       const list = this.project.cur_can_operate_button_list;
@@ -271,9 +315,10 @@ export default {
     getProjectInfo() {
       if (!this.projectId) return;
       GetProjectInfo({ id: this.projectId }).then(
-        ({ project_info = {}, progress_node_info = {}, member_list = [], leader_list = [] }) => {
+        ({ project_info = {}, progress_node_info = {}, book_info_PBE, member_list = [], leader_list = [] }) => {
           this.project = {
             ...project_info,
+            ...book_info_PBE,
             progress_node_info,
             leader_name_desc: leader_list.map((user) => user.name).join(',') || project_info.leader_name_desc,
             member_name_desc: member_list.map((user) => user.name).join(',') || project_info.member_name_desc,
@@ -425,6 +470,10 @@ export default {
       background: #fff;
       border-radius: 4px;
 
+      i {
+        font-size: 20px;
+      }
+
       &:hover {
         color: #2d3e8f;
       }
@@ -514,6 +563,10 @@ export default {
     .info-item {
       font-size: 13px;
 
+      &--full {
+        grid-column: 1 / -1;
+      }
+
       .label {
         display: inline-block;
         width: 95px;
@@ -526,6 +579,24 @@ export default {
       }
     }
 
+    .label-list {
+      display: inline-flex;
+      flex-wrap: wrap;
+      gap: 6px 12px;
+
+      .label-item {
+        display: inline-flex;
+        align-items: center;
+        padding: 3px 12px;
+        font-size: 12px;
+        font-weight: 500;
+        color: #2d3e8f;
+        background: #e8f8fd;
+        border: 1px solid rgba(77, 201, 246, 30%);
+        border-radius: 12px;
+      }
+    }
+
     .book-intro {
       margin-top: 14px;
       font-size: 13px;
@@ -651,6 +722,26 @@ export default {
       margin-top: 12px;
       border-top: $border;
 
+      .status {
+        padding: 4px 12px;
+        font-size: 13px;
+        color: #2563eb;
+        background: #dbeafe;
+        border-radius: 12px;
+
+        &::before {
+          position: relative;
+          top: -1px;
+          display: inline-block;
+          width: 6px;
+          height: 6px;
+          margin-right: 2px;
+          content: '';
+          background: currentColor;
+          border-radius: 50%;
+        }
+      }
+
       .request-status {
         padding: 4px 12px;
         font-size: 13px;
@@ -671,6 +762,80 @@ export default {
         }
       }
 
+      .btn-operate {
+        display: inline-flex;
+        gap: 5px;
+        align-items: center;
+        justify-content: center;
+        padding: 8px 18px;
+        font-size: 13px;
+        cursor: pointer;
+        background-color: #fff;
+        border: $border;
+        border-radius: 20px;
+        transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+
+        .svg-icon {
+          color: #000;
+        }
+
+        &.apply {
+          color: #2d3e8f;
+          border-color: #2d3e8f;
+
+          &:hover {
+            background-color: #e8f8fd;
+          }
+        }
+
+        &.revoke {
+          color: #f59e0b;
+          border-color: #fde68a;
+
+          &:hover {
+            color: #2d3e8f;
+            background-color: #fffbeb;
+            border-color: #f59e0b;
+          }
+        }
+
+        &.shelve {
+          color: #ef4444;
+          border-color: #fecaca;
+
+          &:hover {
+            background: #fef2f2;
+            border-color: #ef4444;
+          }
+        }
+
+        &.revise {
+          color: #10b981;
+          border-color: #a7f3d0;
+
+          &:hover {
+            background: #ecfdf5;
+            border-color: #10b981;
+          }
+        }
+
+        &.error-correction {
+          color: #64748b;
+          border-color: #e2e8f0;
+
+          &:hover {
+            color: #2d3e8f;
+            background: #e8f8fd;
+            border-color: #2d3e8f;
+          }
+        }
+
+        &:hover {
+          color: #2d3e8f;
+          box-shadow: 0 4px 12px rgba(45, 62, 143, 10%);
+        }
+      }
+
       .btn-apply {
         display: inline-flex;
         align-items: center;

+ 11 - 5
src/views/personal_workbench/project/ProjectInfoManage.vue

@@ -46,6 +46,7 @@
         <div class="label label-list">
           <span>语种</span>
           <span>出版单位</span>
+          <span style="line-height: 16px">国标图书编号<br />(ISBN)</span>
           <span>作品标签</span>
           <span>所属课题</span>
           <span>作者</span>
@@ -63,6 +64,11 @@
           </div>
 
           <div class="info-item">
+            <span>{{ project.isbn }}</span>
+            <span v-if="isManage" class="link" @click="showUpdateField('isbn', project.isbn)">更改</span>
+          </div>
+
+          <div class="info-item">
             <span>
               <span v-for="(label, index) in project.label_list" :key="index">
                 {{ label }}{{ index < project.label_list.length - 1 ? ',' : '' }}
@@ -279,8 +285,8 @@ export default {
   },
   methods: {
     getProjectInfo() {
-      GetProjectInfo({ id: this.id }).then(({ project_info, member_list, leader_list }) => {
-        this.project = project_info;
+      GetProjectInfo({ id: this.id }).then(({ project_info, book_info_PBE, member_list, leader_list }) => {
+        this.project = { ...project_info, ...book_info_PBE };
         this.project.leader_name_desc = leader_list.map((user) => user.name).join(',');
         this.project.member_name_desc = member_list.map((user) => user.name).join(',');
         this.getUserList_ID(project_info.leader_id_list, 'leader');
@@ -495,21 +501,21 @@ export default {
           align-items: center;
           justify-content: center;
           width: 373px;
-          height: 288px;
+          height: 338px;
           overflow: hidden;
 
           img {
             display: block;
             flex: none;
             max-width: 373px;
-            max-height: 288px;
+            max-height: 338px;
           }
         }
       }
     }
 
     .table-fourcolumn:first-child {
-      grid-template-rows: 40px 298px;
+      grid-template-rows: 40px 348px;
       grid-template-columns: 120px 1fr 120px 1fr;
     }
 

+ 5 - 1
src/views/personal_workbench/project/components/UpdateProjectField.vue

@@ -7,7 +7,9 @@
     @close="handleClose"
   >
     <template
-      v-if="['name', 'editor', 'category', 'language', 'topic', 'reader', 'publisher', 'version'].includes(field)"
+      v-if="
+        ['name', 'editor', 'category', 'language', 'topic', 'reader', 'publisher', 'version', 'isbn'].includes(field)
+      "
     >
       <el-input v-model="stringValue" type="text" />
     </template>
@@ -108,6 +110,7 @@ export default {
         word_count_YG: '预计字数',
         // 对象
         label_list: '作品标签',
+        isbn: '国标图书编号(ISBN)',
       },
       stringValue: this.value,
       arrayValue: [],
@@ -186,6 +189,7 @@ export default {
           'word_count_YG',
           'plan_publish_date',
           'version',
+          'isbn',
         ].includes(this.field)
       ) {
         this.$emit('updateProjectFieldValue', this.field, this.stringValue);