tianyun há 5 meses atrás
pai
commit
193083576b
1 ficheiros alterados com 489 adições e 67 exclusões
  1. 489 67
      tmp/tmp.html

+ 489 - 67
tmp/tmp.html

@@ -1,83 +1,505 @@
 <!DOCTYPE html>
-<html lang="en">
+<html lang="zh-CN">
 <head>
     <meta charset="UTF-8">
-    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
-    <title>可爱登录页面</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>简易链接管理器</title>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js"></script>
     <style>
-        .wrap {
+        body {
+            font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+            line-height: 1.6;
+            margin: 0;
+            padding: 20px;
+            color: #333;
+            background-color: #f9f9f9;
+        }
+        .container {
+            max-width: 1200px;
+            margin: 0 auto;
+        }
+        .header {
             display: flex;
             justify-content: space-between;
-            /*justify-content: center;*/
-            /*align-items: center;*/
-            /*height: 100vh;*/
+            align-items: center;
+            margin-bottom: 20px;
+        }
+        h1 {
+            color: #2c3e50;
+            margin: 0;
+        }
+        .toolbar {
+            display: flex;
+            gap: 10px;
+            margin-bottom: 20px;
+            flex-wrap: wrap;
+        }
+        .tag-list {
+            display: flex;
+            flex-wrap: wrap;
+            gap: 8px;
+            margin-bottom: 20px;
+        }
+        .tag {
+            background-color: #e0f2fe;
+            color: #0369a1;
+            padding: 5px 10px;
+            border-radius: 15px;
+            cursor: pointer;
+            transition: all 0.2s;
+            user-select: none;
+        }
+        .tag.active {
+            background-color: #0284c7;
+            color: white;
+        }
+        .tag:hover {
+            opacity: 0.8;
+        }
+        input, button, select {
+            padding: 8px 12px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            font-size: 14px;
+        }
+        input:focus, select:focus {
+            outline: none;
+            border-color: #0284c7;
+        }
+        button {
+            background-color: #0284c7;
+            color: white;
+            cursor: pointer;
+            border: none;
+        }
+        button:hover {
+            background-color: #0369a1;
+        }
+        table {
+            width: 100%;
+            border-collapse: collapse;
+            margin-top: 20px;
+            background-color: white;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+            border-radius: 8px;
+            overflow: hidden;
+        }
+        th, td {
+            padding: 12px 15px;
+            text-align: left;
+            border-bottom: 1px solid #eee;
+        }
+        th {
+            background-color: #f1f5f9;
+            font-weight: 600;
+            color: #334155;
+        }
+        tr:hover {
+            background-color: #f1f5f9;
+        }
+        .preview-img {
+            max-width: 100px;
+            max-height: 100px;
+            object-fit: contain;
+            cursor: pointer;
+        }
+        .modal {
+            display: none;
+            position: fixed;
+            top: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            background-color: rgba(0,0,0,0.8);
+            z-index: 1000;
+            justify-content: center;
+            align-items: center;
         }
-        .item{
-            width: 30vw;
+        .modal-content {
+            max-width: 90%;
+            max-height: 90%;
+        }
+        .modal-content img {
+            max-width: 100%;
+            max-height: 90vh;
+            object-fit: contain;
+        }
+        .close {
+            position: absolute;
+            top: 20px;
+            right: 30px;
+            color: white;
+            font-size: 30px;
+            cursor: pointer;
+        }
+        .export-import {
+            margin-top: 20px;
+            display: flex;
+            gap: 10px;
+        }
+        #importInput {
+            display: none;
         }
     </style>
 </head>
 <body>
-<div class="wrap">
-    <div class="item">123</div>
-    <div class="item">123</div>
-    <div class="item">123</div>
+<div class="container">
+    <div class="header">
+        <h1>简易链接管理器</h1>
+    </div>
+
+    <div class="toolbar">
+        <input type="text" id="searchInput" placeholder="搜索...">
+        <select id="sortSelect">
+            <option value="dateDesc">日期 (新→旧)</option>
+            <option value="dateAsc">日期 (旧→新)</option>
+            <option value="titleAsc">标题 (A→Z)</option>
+            <option value="titleDesc">标题 (Z→A)</option>
+        </select>
+        <button id="addNewBtn">添加新链接</button>
+    </div>
+
+    <div class="tag-list" id="tagList"></div>
+
+    <table id="dataTable">
+        <thead>
+        <tr>
+            <th>标题</th>
+            <th>链接</th>
+            <th>图片</th>
+            <th>标签</th>
+            <th>添加日期</th>
+            <th>操作</th>
+        </tr>
+        </thead>
+        <tbody id="tableBody"></tbody>
+    </table>
+
+    <div class="export-import">
+        <button id="exportBtn">导出数据</button>
+        <button id="importBtn">导入数据</button>
+        <input type="file" id="importInput" accept=".json">
+    </div>
+</div>
+
+<div id="imageModal" class="modal">
+    <span class="close">&times;</span>
+    <div class="modal-content">
+        <img id="modalImage" src="">
+    </div>
 </div>
 
-<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.16/vue.min.js"></script>
-<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
-<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.min.js"></script>
-<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
-</body>
 <script>
-  //   curl 'https://www.suoyoutongxue.cn/biz/video_lesson' \
-  // -H 'Referer: http://localhost:8080/' \
-  // -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' \
-  // -H 'Token: 4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572' \
-  // -H 'content-type: application/json;charset=UTF-8' \
-  // --data-raw '{"id":"970","token":"4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572"}'
-  // const data = {
-  //     id: "970",
-  //     token: "4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572"
-  // };
-  //
-  // const config = {
-  //     headers: {
-  //         'Referer': 'http://localhost:8080/',
-  //         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
-  //         'Token': '4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572',
-  //         'content-type': 'application/json;charset=UTF-8'
-  //     }
-  // };
-  //
-  // axios.post('https://www.suoyoutongxue.cn/biz/video_lesson', data, config)
-  //     .then(response => {
-  //         console.log(response.data);
-  //     })
-  //     .catch(error => {
-  //         console.error(error);
-  //     });
-  var myHeaders = new Headers();
-  myHeaders.append("Referer", "http://localhost:8080/");
-  myHeaders.append("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36");
-  myHeaders.append("Token", "4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572");
-  myHeaders.append("content-type", "application/json;charset=UTF-8");
-  myHeaders.append("Accept", "*/*");
-  myHeaders.append("Host", "www.suoyoutongxue.cn");
-  myHeaders.append("Connection", "keep-alive");
-
-  var raw = "{\"id\":\"970\",\"token\":\"4fefa7f2f623b3ab-e2dbfaadc863221a941069830427056a276b8882fed736822ec83102eeefa660aaa055c1003cf4ab0da572\"}";
-
-  var requestOptions = {
-      method: 'POST',
-      headers: myHeaders,
-      body: raw,
-      redirect: 'follow'
-  };
-
-  fetch("https://www.suoyoutongxue.cn/biz/video_lesson", requestOptions)
-      .then(response => response.text())
-      .then(result => console.log(result))
-      .catch(error => console.log('error', error));
+    // 初始数据存储
+    let data = JSON.parse(localStorage.getItem('linkData')) || [];
+    let allTags = new Set();
+    let activeTagFilters = new Set();
+
+    // 初始化应用
+    function init() {
+        renderTags();
+        renderTable();
+        setupEventListeners();
+    }
+
+    // 从数据中提取所有唯一标签
+    function extractAllTags() {
+        allTags = new Set();
+        data.forEach(item => {
+            if (item.tags && Array.isArray(item.tags)) {
+                item.tags.forEach(tag => allTags.add(tag));
+            }
+        });
+        return Array.from(allTags).sort();
+    }
+
+    // 渲染标签筛选器
+    function renderTags() {
+        const tags = extractAllTags();
+        const tagList = document.getElementById('tagList');
+        tagList.innerHTML = '';
+
+        tags.forEach(tag => {
+            const tagElement = document.createElement('span');
+            tagElement.className = `tag ${activeTagFilters.has(tag) ? 'active' : ''}`;
+            tagElement.textContent = tag;
+            tagElement.dataset.tag = tag;
+            tagList.appendChild(tagElement);
+        });
+    }
+
+    // 渲染数据表格
+    function renderTable() {
+        const tableBody = document.getElementById('tableBody');
+        tableBody.innerHTML = '';
+
+        const searchTerm = document.getElementById('searchInput').value.toLowerCase();
+        const sortMethod = document.getElementById('sortSelect').value;
+
+        // 筛选数据
+        let filteredData = data.filter(item => {
+            // 标签筛选
+            if (activeTagFilters.size > 0) {
+                if (!item.tags || !Array.isArray(item.tags)) return false;
+                const hasAllTags = Array.from(activeTagFilters).every(tag =>
+                    item.tags.includes(tag)
+                );
+                if (!hasAllTags) return false;
+            }
+
+            // 搜索筛选
+            if (searchTerm) {
+                const searchFields = [
+                    item.title,
+                    item.url,
+                    (item.tags || []).join(' ')
+                ].join(' ').toLowerCase();
+
+                return searchFields.includes(searchTerm);
+            }
+
+            return true;
+        });
+
+        // 排序数据
+        filteredData.sort((a, b) => {
+            switch (sortMethod) {
+                case 'dateDesc':
+                    return new Date(b.date) - new Date(a.date);
+                case 'dateAsc':
+                    return new Date(a.date) - new Date(b.date);
+                case 'titleAsc':
+                    return a.title.localeCompare(b.title);
+                case 'titleDesc':
+                    return b.title.localeCompare(a.title);
+                default:
+                    return new Date(b.date) - new Date(a.date);
+            }
+        });
+
+        // 渲染数据行
+        filteredData.forEach((item, index) => {
+            const row = document.createElement('tr');
+
+            // 标题列
+            const titleCell = document.createElement('td');
+            titleCell.textContent = item.title;
+            row.appendChild(titleCell);
+
+            // 链接列
+            const urlCell = document.createElement('td');
+            const urlLink = document.createElement('a');
+            urlLink.href = item.url;
+            urlLink.textContent = item.url.length > 30 ? item.url.substring(0, 30) + '...' : item.url;
+            urlLink.target = '_blank';
+            urlCell.appendChild(urlLink);
+            row.appendChild(urlCell);
+
+            // 图片列
+            const imageCell = document.createElement('td');
+            if (item.imageUrl) {
+                const img = document.createElement('img');
+                img.src = item.imageUrl;
+                img.alt = item.title;
+                img.className = 'preview-img';
+                img.dataset.fullImage = item.imageUrl;
+                imageCell.appendChild(img);
+            }
+            row.appendChild(imageCell);
+
+            // 标签列
+            const tagsCell = document.createElement('td');
+            if (item.tags && Array.isArray(item.tags)) {
+                item.tags.forEach(tag => {
+                    const tagSpan = document.createElement('span');
+                    tagSpan.className = 'tag';
+                    tagSpan.textContent = tag;
+                    tagsCell.appendChild(tagSpan);
+                });
+            }
+            row.appendChild(tagsCell);
+
+            // 日期列
+            const dateCell = document.createElement('td');
+            dateCell.textContent = new Date(item.date).toLocaleDateString();
+            row.appendChild(dateCell);
+
+            // 操作列
+            const actionsCell = document.createElement('td');
+            const editBtn = document.createElement('button');
+            editBtn.textContent = '编辑';
+            editBtn.dataset.index = index;
+            editBtn.style.marginRight = '5px';
+
+            const deleteBtn = document.createElement('button');
+            deleteBtn.textContent = '删除';
+            deleteBtn.dataset.index = index;
+            deleteBtn.style.backgroundColor = '#ef4444';
+
+            actionsCell.appendChild(editBtn);
+            actionsCell.appendChild(deleteBtn);
+            row.appendChild(actionsCell);
+
+            tableBody.appendChild(row);
+        });
+    }
+
+    // 设置事件监听器
+    function setupEventListeners() {
+        // 搜索框变化时更新表格
+        document.getElementById('searchInput').addEventListener('input', renderTable);
+
+        // 排序选择变化时更新表格
+        document.getElementById('sortSelect').addEventListener('change', renderTable);
+
+        // 标签点击事件
+        document.getElementById('tagList').addEventListener('click', event => {
+            if (event.target.classList.contains('tag')) {
+                const tag = event.target.dataset.tag;
+                if (activeTagFilters.has(tag)) {
+                    activeTagFilters.delete(tag);
+                } else {
+                    activeTagFilters.add(tag);
+                }
+                renderTags();
+                renderTable();
+            }
+        });
+
+        // 添加新链接按钮
+        document.getElementById('addNewBtn').addEventListener('click', () => {
+            const title = prompt('输入标题:');
+            if (!title) return;
+
+            const url = prompt('输入URL:');
+            if (!url) return;
+
+            const imageUrl = prompt('输入图片URL (可选):');
+
+            const tagsInput = prompt('输入标签 (用逗号分隔):');
+            const tags = tagsInput ? tagsInput.split(',').map(t => t.trim()).filter(t => t) : [];
+
+            const newItem = {
+                title,
+                url,
+                imageUrl,
+                tags,
+                date: new Date().toISOString()
+            };
+
+            data.push(newItem);
+            saveData();
+            renderTags();
+            renderTable();
+        });
+
+        // 表格行操作按钮
+        document.getElementById('tableBody').addEventListener('click', event => {
+            if (event.target.tagName === 'BUTTON') {
+                const index = parseInt(event.target.dataset.index);
+                const item = data[index];
+
+                if (event.target.textContent === '编辑') {
+                    // 编辑操作
+                    const title = prompt('编辑标题:', item.title);
+                    if (!title) return;
+
+                    const url = prompt('编辑URL:', item.url);
+                    if (!url) return;
+
+                    const imageUrl = prompt('编辑图片URL (可选):', item.imageUrl || '');
+
+                    const tagsInput = prompt('编辑标签 (用逗号分隔):', (item.tags || []).join(', '));
+                    const tags = tagsInput ? tagsInput.split(',').map(t => t.trim()).filter(t => t) : [];
+
+                    data[index] = {
+                        ...item,
+                        title,
+                        url,
+                        imageUrl,
+                        tags
+                    };
+
+                    saveData();
+                    renderTags();
+                    renderTable();
+                } else if (event.target.textContent === '删除') {
+                    // 删除操作
+                    if (confirm(`确定要删除 "${item.title}" 吗?`)) {
+                        data.splice(index, 1);
+                        saveData();
+                        renderTags();
+                        renderTable();
+                    }
+                }
+            } else if (event.target.classList.contains('preview-img')) {
+                // 图片预览
+                const modal = document.getElementById('imageModal');
+                const modalImg = document.getElementById('modalImage');
+                modal.style.display = 'flex';
+                modalImg.src = event.target.dataset.fullImage;
+            }
+        });
+
+        // 图片模态框关闭按钮
+        document.querySelector('.close').addEventListener('click', () => {
+            document.getElementById('imageModal').style.display = 'none';
+        });
+
+        // 导出数据
+        document.getElementById('exportBtn').addEventListener('click', () => {
+            const dataStr = JSON.stringify(data, null, 2);
+            const blob = new Blob([dataStr], {type: 'application/json'});
+            const url = URL.createObjectURL(blob);
+            const a = document.createElement('a');
+            a.href = url;
+            a.download = `bookmark-data-${new Date().toISOString().slice(0,10)}.json`;
+            document.body.appendChild(a);
+            a.click();
+            document.body.removeChild(a);
+        });
+
+        // 导入数据点击
+        document.getElementById('importBtn').addEventListener('click', () => {
+            document.getElementById('importInput').click();
+        });
+
+        // 导入数据处理
+        document.getElementById('importInput').addEventListener('change', event => {
+            const file = event.target.files[0];
+            if (!file) return;
+
+            const reader = new FileReader();
+            reader.onload = function(e) {
+                try {
+                    const importedData = JSON.parse(e.target.result);
+                    if (Array.isArray(importedData)) {
+                        if (confirm(`确定要导入 ${importedData.length} 条数据吗? 这将覆盖当前数据。`)) {
+                            data = importedData;
+                            saveData();
+                            renderTags();
+                            renderTable();
+                            alert('数据导入成功!');
+                        }
+                    } else {
+                        alert('导入的文件格式不正确。请提供有效的JSON数组。');
+                    }
+                } catch (err) {
+                    alert('导入失败: ' + err.message);
+                }
+                event.target.value = '';
+            };
+            reader.readAsText(file);
+        });
+    }
+
+    // 保存数据到localStorage
+    function saveData() {
+        localStorage.setItem('linkData', JSON.stringify(data));
+    }
+
+    // 初始化应用
+    init();
 </script>
+</body>
 </html>