Browse Source

1.添加关联图书检索

1 1 month ago
parent
commit
3a9e34b488

+ 33 - 0
imwork-assist/imwork-generator-service/src/main/java/top/imwork/assist/generator/config/DataSourceProperties.java

@@ -0,0 +1,33 @@
+package top.imwork.assist.generator.config;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: DataSourceProperties
+ * Author<作者姓名>:   silos
+ * CreateTime<创建时间>:   2025/11/9 20:22
+ * UpdateTime<修改时间>:   2025/11/9 20:22
+ * Description〈功能简述〉: 数据源属性类
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+public class DataSourceProperties {
+    private String url;
+    private String username;
+    private String password;
+    private String driverClassName;
+
+    // getter and setter
+    public String getUrl() { return url; }
+    public void setUrl(String url) { this.url = url; }
+
+    public String getUsername() { return username; }
+    public void setUsername(String username) { this.username = username; }
+
+    public String getPassword() { return password; }
+    public void setPassword(String password) { this.password = password; }
+
+    public String getDriverClassName() { return driverClassName; }
+    public void setDriverClassName(String driverClassName) {
+        this.driverClassName = driverClassName;
+    }
+}

+ 81 - 0
imwork-assist/imwork-generator-service/src/main/java/top/imwork/assist/generator/config/DynamicDataSourceManager.java

@@ -0,0 +1,81 @@
+package top.imwork.assist.generator.config;
+
+import com.zaxxer.hikari.HikariDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.jdbc.DataSourceBuilder;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: DynamicDataSourceManager
+ * Author<作者姓名>:   silos
+ * CreateTime<创建时间>:   2025/11/9 20:20
+ * UpdateTime<修改时间>:   2025/11/9 20:20
+ * Description〈功能简述〉: 数据源管理器
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+@Component
+public class DynamicDataSourceManager {
+
+    private final Map<String, DataSource> dataSourceMap = new ConcurrentHashMap<>();
+
+    @Autowired
+    private JdbcTemplate primaryJdbcTemplate;
+
+    /**
+     * 动态添加数据源
+     */
+    public void addDataSource(String key, DataSourceProperties properties) {
+        DataSource dataSource = createDataSource(properties);
+        dataSourceMap.put(key, dataSource);
+    }
+
+    /**
+     * 动态移除数据源
+     */
+    public void removeDataSource(String key) {
+        DataSource dataSource = dataSourceMap.remove(key);
+        if (dataSource != null) {
+            // 关闭数据源连接
+            if (dataSource instanceof HikariDataSource) {
+                ((HikariDataSource) dataSource).close();
+            }
+        }
+    }
+
+    /**
+     * 获取数据源
+     */
+    public DataSource getDataSource(String key) {
+        return dataSourceMap.get(key);
+    }
+
+    /**
+     * 创建数据源
+     */
+    private DataSource createDataSource(DataSourceProperties properties) {
+        return DataSourceBuilder.create()
+                .url(properties.getUrl())
+                .username(properties.getUsername())
+                .password(properties.getPassword())
+                .driverClassName(properties.getDriverClassName())
+                .build();
+    }
+
+    /**
+     * 获取特定数据源的 JdbcTemplate
+     */
+    public JdbcTemplate getJdbcTemplate(String dataSourceKey) {
+        DataSource dataSource = dataSourceMap.get(dataSourceKey);
+        if (dataSource == null) {
+            throw new IllegalArgumentException("数据源不存在: " + dataSourceKey);
+        }
+        return new JdbcTemplate(dataSource);
+    }
+}

+ 63 - 0
imwork-assist/imwork-generator-service/src/main/java/top/imwork/assist/generator/controller/DataSourceController.java

@@ -0,0 +1,63 @@
+package top.imwork.assist.generator.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.bind.annotation.*;
+import top.imwork.assist.generator.config.DataSourceProperties;
+import top.imwork.assist.generator.config.DynamicDataSourceManager;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: DataSourceController
+ * Author<作者姓名>:   silos
+ * CreateTime<创建时间>:   2025/11/9 20:24
+ * UpdateTime<修改时间>:   2025/11/9 20:24
+ * Description〈功能简述〉: 控制器示例
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+@RestController
+@RequestMapping("/api/datasource")
+public class DataSourceController {
+
+    @Autowired
+    private DynamicDataSourceManager dataSourceManager;
+
+    /**
+     * 添加动态数据源
+     */
+    @PostMapping("/add")
+    public ResponseEntity<String> addDataSource(@RequestBody DataSourceProperties properties) {
+        try {
+            String dataSourceKey = generateDataSourceKey(properties);
+            dataSourceManager.addDataSource(dataSourceKey, properties);
+            return ResponseEntity.ok("数据源添加成功: " + dataSourceKey);
+        } catch (Exception e) {
+            return ResponseEntity.badRequest().body("数据源添加失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 使用动态数据源查询
+     */
+    @PostMapping("/query")
+    public ResponseEntity<List<Map<String, Object>>> queryWithDataSource(
+            @RequestParam String dataSourceKey,
+            @RequestBody String sql) {
+        try {
+            JdbcTemplate jdbcTemplate = dataSourceManager.getJdbcTemplate(dataSourceKey);
+            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
+            return ResponseEntity.ok(result);
+        } catch (Exception e) {
+            return ResponseEntity.badRequest().body(null);
+        }
+    }
+
+    private String generateDataSourceKey(DataSourceProperties properties) {
+        return properties.getUrl().hashCode() + "_" + System.currentTimeMillis();
+    }
+}

+ 21 - 0
imwork-assist/imwork-generator-service/src/main/java/top/imwork/assist/generator/service/IGeneratorService.java

@@ -0,0 +1,21 @@
+package top.imwork.assist.generator.service;
+
+import top.imwork.commons.core.pojo.ResponseMsg;
+
+import java.util.Map;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: IGeneratorService
+ * Author<作者姓名>:   silos
+ * CreateTime<创建时间>:   2025/11/9 19:13
+ * UpdateTime<修改时间>:   2025/11/9 19:13
+ * Description〈功能简述〉: 生成接口
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+public interface IGeneratorService {
+    public ResponseMsg queryList(Map<String, Object> params);
+
+    public Map<String, String> queryTable(String tableName);
+}

+ 47 - 0
imwork-assist/imwork-generator-service/src/main/java/top/imwork/assist/generator/service/impl/GeneratorServiceImpl.java

@@ -0,0 +1,47 @@
+package top.imwork.assist.generator.service.impl;
+
+import com.mysql.cj.jdbc.MysqlDataSource;
+import org.springframework.stereotype.Service;
+import top.imwork.assist.generator.service.IGeneratorService;
+import top.imwork.commons.core.pojo.ResponseMsg;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Map;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: GeneratorServiceImpl
+ * Author<作者姓名>:   silos
+ * CreateTime<创建时间>:   2025/11/9 19:15
+ * UpdateTime<修改时间>:   2025/11/9 19:15
+ * Description〈功能简述〉:
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+@Service
+public class GeneratorServiceImpl implements IGeneratorService {
+    private DataSource getDataSource(){
+        MysqlDataSource dataSource = new MysqlDataSource();
+        dataSource.setURL("jdbc:mysql://mysql.imwork.top:63306/imwork_silos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC");
+        dataSource.setUser("root");
+        dataSource.setPassword("zh.3417.JXW");
+        return dataSource;
+    }
+
+    private Connection getConnection() throws SQLException {
+        Connection connection = getDataSource().getConnection();
+        return connection;
+    }
+    @Override
+    public ResponseMsg queryList(Map<String, Object> params) {
+
+        return null;
+    }
+
+    @Override
+    public Map<String, String> queryTable(String tableName) {
+        return Map.of();
+    }
+}

+ 202 - 0
imwork-windows/imwork-silos/src/main/resources/static/business/cms/base/pagination.css

@@ -0,0 +1,202 @@
+.dropdown-container {
+    position: relative;
+    width: 100%;
+}
+
+.dropdown-header {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 12px 16px;
+    border: 2px solid #e1e8ed;
+    border-radius: 8px;
+    cursor: pointer;
+    background: white;
+    transition: all 0.3s ease;
+}
+
+.dropdown-header:hover {
+    border-color: #3498db;
+}
+
+.dropdown-header.active {
+    border-color: #3498db;
+    box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.2);
+}
+
+.placeholder {
+    color: #95a5a6;
+}
+
+.selected-value {
+    color: #2c3e50;
+    font-weight: 500;
+}
+
+.dropdown-icon {
+    color: #7f8c8d;
+    transition: transform 0.3s ease;
+}
+
+.dropdown-icon.rotated {
+    transform: rotate(180deg);
+}
+
+.dropdown-list {
+    position: absolute;
+    top: 100%;
+    left: 0;
+    right: 0;
+    background: white;
+    border: 2px solid #e1e8ed;
+    border-top: none;
+    border-radius: 0 0 8px 8px;
+    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
+    max-height: 300px;
+    overflow: hidden;
+    display: none;
+    z-index: 1000;
+}
+
+.dropdown-list.active {
+    display: block;
+}
+
+.search-box {
+    padding: 12px 16px;
+    border-bottom: 1px solid #e1e8ed;
+}
+
+.search-input {
+    width: 100%;
+    padding: 8px 12px;
+    border: 1px solid #e1e8ed;
+    border-radius: 6px;
+    outline: none;
+    transition: border-color 0.3s;
+}
+
+.search-input:focus {
+    border-color: #3498db;
+}
+
+.options-container {
+    max-height: 180px;
+    overflow-y: auto;
+}
+
+.option-item {
+    padding: 12px 16px;
+    cursor: pointer;
+    border-bottom: 1px solid #f5f7fa;
+    transition: background 0.2s;
+}
+
+.option-item:hover {
+    background: #f8f9fa;
+}
+
+.option-item.selected {
+    background: #e1f5fe;
+    color: #0288d1;
+    font-weight: 500;
+}
+
+.pagination {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 12px 16px;
+    border-top: 1px solid #e1e8ed;
+    background: #f8f9fa;
+}
+
+.pagination-info {
+    font-size: 14px;
+    color: #7f8c8d;
+}
+
+.pagination-controls {
+    display: flex;
+    gap: 8px;
+}
+
+.pagination-btn {
+    background: white;
+    border: 1px solid #e1e8ed;
+    border-radius: 4px;
+    padding: 6px 10px;
+    cursor: pointer;
+    transition: all 0.2s;
+    font-size: 14px;
+}
+
+.pagination-btn:hover:not(:disabled) {
+    background: #3498db;
+    color: white;
+    border-color: #3498db;
+}
+
+.pagination-btn:disabled {
+    color: #bdc3c7;
+    cursor: not-allowed;
+}
+
+.clear-btn {
+    background: none;
+    border: none;
+    color: #e74c3c;
+    cursor: pointer;
+    font-size: 14px;
+    padding: 4px 8px;
+    border-radius: 4px;
+    transition: background 0.2s;
+}
+
+.clear-btn:hover {
+    background: rgba(231, 76, 60, 0.1);
+}
+
+.no-results {
+    padding: 20px;
+    text-align: center;
+    color: #95a5a6;
+}
+
+.selected-tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+    margin-top: 15px;
+}
+
+.selected-tag {
+    background: #e1f5fe;
+    color: #0288d1;
+    padding: 6px 12px;
+    border-radius: 20px;
+    font-size: 14px;
+    display: flex;
+    align-items: center;
+    gap: 6px;
+}
+
+.remove-tag {
+    background: none;
+    border: none;
+    cursor: pointer;
+    color: #0288d1;
+    font-size: 16px;
+    line-height: 1;
+}
+
+@media (max-width: 480px) {
+    .container {
+        padding: 20px;
+    }
+
+    .pagination {
+        flex-direction: column;
+        gap: 10px;
+    }
+}

+ 229 - 0
imwork-windows/imwork-silos/src/main/resources/static/business/cms/base/pagination.js

@@ -0,0 +1,229 @@
+document.addEventListener('DOMContentLoaded', function() {
+    // 模拟数据 - 实际应用中可能来自API
+    const allOptions = Array.from({length: 100}, (_, i) => ({
+        id: i + 1,
+        name: `选项 ${i + 1}`,
+        category: i % 5 === 0 ? '热门' : '常规'
+    }));
+
+    // 添加一些特殊选项
+    allOptions.push(
+        {id: 101, name: 'JavaScript', category: '技术'},
+        {id: 102, name: 'Python', category: '技术'},
+        {id: 103, name: 'Java', category: '技术'},
+        {id: 104, name: 'React', category: '前端'},
+        {id: 105, name: 'Vue', category: '前端'},
+        {id: 106, name: 'Angular', category: '前端'},
+        {id: 107, name: 'Node.js', category: '后端'},
+        {id: 108, name: 'Express', category: '后端'}
+    );
+
+    // DOM元素
+    const dropdownHeader = document.querySelector('.dropdown-header');
+    const dropdownList = document.querySelector('.dropdown-list');
+    const searchInput = document.querySelector('.search-input');
+    const optionsContainer = document.querySelector('.options-container');
+    const prevBtn = document.querySelector('.prev-btn');
+    const nextBtn = document.querySelector('.next-btn');
+    const currentPageEl = document.querySelector('.current-page');
+    const totalPagesEl = document.querySelector('.total-pages');
+    const selectedTagsContainer = document.querySelector('.selected-tags');
+    const selectedValueEl = document.querySelector('.selected-value');
+    const dropdownIcon = document.querySelector('.dropdown-icon');
+
+    // 状态变量
+    let currentPage = 1;
+    const itemsPerPage = 10;
+    let filteredOptions = [...allOptions];
+    let selectedOptions = [];
+
+    // 初始化
+    renderOptions();
+    updatePagination();
+
+    // 事件监听器
+    dropdownHeader.addEventListener('click', toggleDropdown);
+    searchInput.addEventListener('input', handleSearch);
+    prevBtn.addEventListener('click', goToPrevPage);
+    nextBtn.addEventListener('click', goToNextPage);
+
+    // 点击外部关闭下拉框
+    document.addEventListener('click', function(e) {
+        if (!dropdownHeader.contains(e.target) && !dropdownList.contains(e.target)) {
+            closeDropdown();
+        }
+    });
+
+    // 切换下拉框显示/隐藏
+    function toggleDropdown() {
+        if (dropdownList.classList.contains('active')) {
+            closeDropdown();
+        } else {
+            openDropdown();
+        }
+    }
+
+    function openDropdown() {
+        dropdownList.classList.add('active');
+        dropdownHeader.classList.add('active');
+        dropdownIcon.classList.add('rotated');
+        searchInput.focus();
+    }
+
+    function closeDropdown() {
+        dropdownList.classList.remove('active');
+        dropdownHeader.classList.remove('active');
+        dropdownIcon.classList.remove('rotated');
+    }
+
+    // 处理搜索
+    function handleSearch(e) {
+        const searchTerm = e.target.value.toLowerCase();
+
+        if (searchTerm.trim() === '') {
+            filteredOptions = [...allOptions];
+        } else {
+            filteredOptions = allOptions.filter(option =>
+                option.name.toLowerCase().includes(searchTerm) ||
+                option.category.toLowerCase().includes(searchTerm)
+            );
+        }
+
+        currentPage = 1;
+        renderOptions();
+        updatePagination();
+    }
+
+    // 渲染选项
+    function renderOptions() {
+        optionsContainer.innerHTML = '';
+
+        if (filteredOptions.length === 0) {
+            optionsContainer.innerHTML = '<div class="no-results">未找到匹配的选项</div>';
+            return;
+        }
+
+        const startIndex = (currentPage - 1) * itemsPerPage;
+        const endIndex = Math.min(startIndex + itemsPerPage, filteredOptions.length);
+        const currentOptions = filteredOptions.slice(startIndex, endIndex);
+
+        currentOptions.forEach(option => {
+            const isSelected = selectedOptions.some(selected => selected.id === option.id);
+
+            const optionElement = document.createElement('div');
+            optionElement.className = `option-item ${isSelected ? 'selected' : ''}`;
+            optionElement.innerHTML = `
+                        <div>${option.name}</div>
+                        <small style="color: #7f8c8d;">${option.category}</small>
+                    `;
+
+            optionElement.addEventListener('click', () => toggleOption(option));
+            optionsContainer.appendChild(optionElement);
+        });
+    }
+
+    // 切换选项选择状态
+    function toggleOption(option) {
+        const optionIndex = selectedOptions.findIndex(selected => selected.id === option.id);
+
+        if (optionIndex === -1) {
+            selectedOptions.push(option);
+        } else {
+            selectedOptions.splice(optionIndex, 1);
+        }
+
+        updateSelectedDisplay();
+        renderOptions();
+    }
+
+    // 更新选中项显示
+    function updateSelectedDisplay() {
+        if (selectedOptions.length === 0) {
+            selectedValueEl.textContent = '请选择选项';
+            selectedValueEl.className = 'placeholder';
+        } else if (selectedOptions.length === 1) {
+            selectedValueEl.textContent = selectedOptions[0].name;
+            selectedValueEl.className = 'selected-value';
+        } else {
+            selectedValueEl.textContent = `已选择 ${selectedOptions.length} 项`;
+            selectedValueEl.className = 'selected-value';
+        }
+
+        // 更新标签显示
+        selectedTagsContainer.innerHTML = '';
+
+        selectedOptions.forEach(option => {
+            const tagElement = document.createElement('div');
+            tagElement.className = 'selected-tag';
+            tagElement.innerHTML = `
+                        ${option.name}
+                        <button class="remove-tag" data-id="${option.id}">×</button>
+                    `;
+
+            selectedTagsContainer.appendChild(tagElement);
+        });
+
+        // 添加清除按钮
+        if (selectedOptions.length > 0) {
+            const clearBtn = document.createElement('button');
+            clearBtn.className = 'clear-btn';
+            clearBtn.textContent = '清除全部';
+            clearBtn.addEventListener('click', clearAllSelections);
+            selectedTagsContainer.appendChild(clearBtn);
+        }
+
+        // 添加移除标签事件监听
+        document.querySelectorAll('.remove-tag').forEach(btn => {
+            btn.addEventListener('click', function(e) {
+                e.stopPropagation();
+                const id = parseInt(this.getAttribute('data-id'));
+                removeOption(id);
+            });
+        });
+    }
+
+    // 移除单个选项
+    function removeOption(id) {
+        selectedOptions = selectedOptions.filter(option => option.id !== id);
+        updateSelectedDisplay();
+        renderOptions();
+    }
+
+    // 清除所有选项
+    function clearAllSelections() {
+        selectedOptions = [];
+        updateSelectedDisplay();
+        renderOptions();
+    }
+
+    // 更新分页
+    function updatePagination() {
+        const totalPages = Math.ceil(filteredOptions.length / itemsPerPage);
+
+        currentPageEl.textContent = currentPage;
+        totalPagesEl.textContent = totalPages;
+
+        prevBtn.disabled = currentPage === 1;
+        nextBtn.disabled = currentPage === totalPages || totalPages === 0;
+    }
+
+    // 上一页
+    function goToPrevPage() {
+        if (currentPage > 1) {
+            currentPage--;
+            renderOptions();
+            updatePagination();
+        }
+    }
+
+    // 下一页
+    function goToNextPage() {
+        const totalPages = Math.ceil(filteredOptions.length / itemsPerPage);
+
+        if (currentPage < totalPages) {
+            currentPage++;
+            renderOptions();
+            updatePagination();
+        }
+    }
+});

+ 1 - 1
imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/contents/edit.css

@@ -38,7 +38,7 @@ body {
 
 .container {
     width: 100%;
-    max-width: 1200px;
+    max-width: 1800px;
 }
 
 header {

+ 41 - 5
imwork-windows/imwork-silos/src/main/resources/templates/cms/books/contents/edit.html

@@ -10,6 +10,7 @@
     <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome4/css/font-awesome.css" th:href="@{/assets/lib/fonts/fontawesome4/css/font-awesome.css}"/>
     <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome6/css/all.min.css" th:href="@{/assets/lib/fonts/fontawesome6/css/all.min.css}"/>
     <link rel="stylesheet" href="../../../../static/business/cms/books/contents/edit.css" th:href="@{/business/cms/books/contents/edit.css}"/>
+    <link rel="stylesheet" href="../../../../static/business/cms/base/pagination.css" th:href="@{/business/cms/base/pagination.css}"/>
 
 </head>
 <body>
@@ -28,15 +29,46 @@
                 <h3 class="section-title">基本信息</h3>
                 <div class="form-row">
                     <div class="form-group">
-                        <label for="bookInfoId" class="required">关联图书</label>
+                        <label class="required">关联图书</label>
+                        <div class="dropdown-container">
+                            <div class="dropdown-header">
+                                <span class="selected-value">关联图书</span>
+                                <span class="dropdown-icon">▼</span>
+                            </div>
+
+                            <div class="dropdown-list">
+                                <div class="search-box">
+                                    <input type="text" class="search-input" placeholder="搜索选项...">
+                                </div>
+
+                                <div class="options-container">
+                                    <!-- 选项将通过JavaScript动态生成 -->
+                                </div>
+
+                                <div class="pagination">
+                                    <div class="pagination-info">第 <span class="current-page">1</span> 页,共 <span class="total-pages">1</span> 页</div>
+                                    <div class="pagination-controls">
+                                        <button class="pagination-btn prev-btn" disabled>上一页</button>
+                                        <button class="pagination-btn next-btn">下一页</button>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="selected-tags">
+                            <!-- 已选标签将通过JavaScript动态生成 -->
+                        </div>
+
+                        <!--<label for="bookInfoId" class="required">关联图书</label>
                         <select id="bookInfoId" name="bookId" required>
                             <option value="">请选择图书</option>
+                            <option value="9787111239505">java核心技术</option>
                             <option value="1">网页设计与开发实战</option>
                             <option value="2">JavaScript高级程序设计</option>
                             <option value="3">CSS权威指南</option>
                             <option value="4">HTML5与CSS3基础教程</option>
                         </select>
-                        <div class="error-message" id="bookIdError">请选择关联图书</div>
+                        <div class="error-message" id="bookIdError">请选择关联图书</div>-->
                     </div>
                     <div class="form-group">
                         <label for="chapterLevel" class="required">章节层级</label>
@@ -97,9 +129,12 @@
                         <label for="parentId">父级章节</label>
                         <select id="parentId" name="parentChapter">
                             <option value="">无(顶级章节)</option>
-                            <option value="1">第一章:HTML基础</option>
-                            <option value="2">第二章:CSS样式</option>
-                            <option value="3">第三章:JavaScript编程</option>
+                            <option value="14">第十四章:集合</option>
+                            <option value="15">第十五章:多线程</option>
+                            <option value="16">第十六章:反射</option>
+                            <option value="17">第十七章:jdbc</option>
+                            <option value="18">第二章:CSS样式</option>
+                            <option value="19">第三章:JavaScript编程</option>
                         </select>
                     </div>
                 </div>
@@ -152,5 +187,6 @@
 <script src="../../../../static/assets/lib/layui/layui.js" th:src="@{/assets/lib/layui/layui.js}"></script>
 <script src="../../../../static/assets/lib/jplus/tinymce/tinymce.min.js" th:src="@{/assets/lib/jplus/tinymce/tinymce.min.js}"></script>
 <script src="../../../../static/business/cms/books/contents/edit.js" th:src="@{/business/cms/books/contents/edit.js}"></script>
+<script src="../../../../static/business/cms/base/pagination.js" th:src="@{/business/cms/base/pagination.js}"></script>
 </body>
 </html>