一堆BUG修复
50
README.md
@ -1,37 +1,46 @@
|
||||
# 项目待办事项
|
||||
# 项目待办事项管理系统
|
||||
|
||||
## 已完成功能 ✅
|
||||
### 界面优化
|
||||
- [x] 首页标题支持自定义
|
||||
- [x] 背景图片设置支持从已上传图片中选择,选择时提供预览
|
||||
- [x] 增加附件管理页面,管理上传的图片(包括应用图标和背景图片)
|
||||
- [x] 首页悬浮气泡内的文字改为居左
|
||||
- [x] 背景支持视频
|
||||
- [x] 应用的图标支持上传图片自定义
|
||||
- [x] 自定义页脚
|
||||
- [x] 一级分类和二级分类固定宽度,超出宽度可左右滑动查看
|
||||
- [x] 气泡的小箭头靠左对齐
|
||||
|
||||
### 功能增强
|
||||
- [x] 修复密码明文传输问题
|
||||
- [x] 不登录时一级分类和二级分类按钮没有颜色
|
||||
- [x] 应用管理页支持分页和按一级分类筛选
|
||||
- [x] 应用分页和附件分页功能
|
||||
- [x] 部分页面游客跳转登录功能
|
||||
|
||||
### BUG修复
|
||||
- [x] 不登录时一级分类和二级分类按钮没有颜色
|
||||
- [x] 应用编辑页面没有回显带入图片
|
||||
|
||||
## 待开发功能 ⏳
|
||||
### 界面优化
|
||||
1. 每行卡片数量支持自定义(4个、5个、6个、8个)
|
||||
2. 应用的图标支持上传图片自定义 - 已完成
|
||||
3. 自定义页脚 - 已完成
|
||||
4. 一级分类和二级分类固定宽度,超出宽度可左右滑动查看 - 已完成
|
||||
5. 气泡的小箭头靠左对齐 - 已完成
|
||||
6. logo图标设置区分明亮和暗黑模式
|
||||
7. 私有应用在首页添加标识
|
||||
8. 首页卡片右键菜单
|
||||
9. 应用支持配置多个URL,左键打开默认URL,右键可选择URL进行复制地址或者打开或者编辑应用
|
||||
10. 新增应用界面便捷增加分类
|
||||
11. 新增应用界面便捷增加图标图片
|
||||
1. logo图标设置区分明亮和暗黑模式
|
||||
2. 私有应用在首页添加标识
|
||||
3. 首页卡片右键菜单
|
||||
4. 应用支持配置多个URL,左键打开默认URL,右键可选择URL进行复制地址或者打开或者编辑应用
|
||||
5. 新增应用界面便捷增加分类
|
||||
6. 新增应用界面便捷增加图标图片
|
||||
7. 每行卡片数量支持自定义(4个、5个、6个、8个)
|
||||
|
||||
### 功能增强
|
||||
1. 应用管理页支持分页和按一级分类筛选 - 已完成
|
||||
2. 应用分页和附件分页功能 - 已完成
|
||||
3. 网站图标自动获取功能
|
||||
4. 书签收藏工具
|
||||
1. 网站图标自动获取功能
|
||||
2. 书签收藏工具
|
||||
|
||||
### BUG修复
|
||||
1. 应用编辑页面没有回显带入图片 - 已解决
|
||||
1. 游客通过接口能查看私有应用;
|
||||
|
||||
### 移动端适配
|
||||
1. 后台页面适配
|
||||
|
||||
### 批量操作
|
||||
1. 应用批量选择功能:
|
||||
@ -39,3 +48,8 @@
|
||||
- 批量设置私有化/公有化
|
||||
2. 附件批量选择功能:
|
||||
- 批量删除
|
||||
|
||||
## 项目进度
|
||||
- 已完成功能:17项
|
||||
- 待开发功能:10项
|
||||
- 完成率:63%
|
||||
37
app.py
@ -250,7 +250,10 @@ def allowed_file(filename):
|
||||
|
||||
|
||||
def generate_random_filename(extension):
|
||||
return f"{uuid.uuid4().hex}.{extension}"
|
||||
# 生成12位随机字符串作为文件名
|
||||
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
random_str = ''.join(random.choice(chars) for _ in range(12))
|
||||
return f"{random_str}.{extension}"
|
||||
|
||||
|
||||
def download_image(url, folder):
|
||||
@ -657,6 +660,7 @@ def index():
|
||||
categories=categories,
|
||||
current_page=page,
|
||||
total_pages=total_pages,
|
||||
per_page=per_page,
|
||||
search_query=search_query,
|
||||
category_filter=category_filter)
|
||||
|
||||
@ -941,15 +945,39 @@ def edit_sub_category(main_id, sub_id):
|
||||
settings=settings,
|
||||
is_private=is_private)
|
||||
|
||||
|
||||
@app.route('/api/apps')
|
||||
def api_apps():
|
||||
apps = load_apps()
|
||||
categories = load_categories()
|
||||
# 检查登录状态
|
||||
is_logged_in = 'username' in session
|
||||
|
||||
# 如果未登录,过滤掉私有应用
|
||||
# 如果未登录,过滤掉私有应用和私有分类中的应用
|
||||
if not is_logged_in:
|
||||
apps = [app for app in apps if not app.get('private', False)]
|
||||
filtered_apps = []
|
||||
for app in apps:
|
||||
# 跳过私有应用
|
||||
if app.get('private', False):
|
||||
continue
|
||||
|
||||
main_cat = app['category']['main']
|
||||
sub_cat = app['category']['sub']
|
||||
|
||||
# 检查主分类是否为私有
|
||||
if main_cat in categories and categories[main_cat].get('private', False):
|
||||
continue
|
||||
|
||||
# 检查子分类是否为私有
|
||||
if (main_cat in categories and
|
||||
'sub_private' in categories[main_cat] and
|
||||
sub_cat in categories[main_cat]['sub_private'] and
|
||||
categories[main_cat]['sub_private'][sub_cat]):
|
||||
continue
|
||||
|
||||
filtered_apps.append(app)
|
||||
|
||||
return jsonify(filtered_apps)
|
||||
|
||||
return jsonify(apps)
|
||||
|
||||
@ -981,7 +1009,8 @@ def api_categories():
|
||||
filtered_categories[main_id] = {
|
||||
'name': main_data['name'],
|
||||
'color': main_data['color'], # 保留颜色信息
|
||||
'sub': filtered_sub
|
||||
'sub': filtered_sub,
|
||||
'weight': main_data.get('weight', 0) # 保留权重信息
|
||||
}
|
||||
return jsonify(filtered_categories)
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"title": "SQL生成工具23",
|
||||
"url": "https://fastai.liuyan.wang/chat/share?shareId=dbvns61a0glb2q6nwv9utd5v",
|
||||
"icon": "/upload/icon/c77f6bbbb33540d98a6cc088d01d7ad6.png",
|
||||
"icon": "fa-solid fa-database",
|
||||
"description": "一个强大的SQL查询生成工具,支持多种数据库,可快速生成复杂查询语句",
|
||||
"category": {
|
||||
"main": "dev",
|
||||
@ -14,7 +14,7 @@
|
||||
{
|
||||
"title": "Nginx配置生成",
|
||||
"url": "https://fastai.liuyan.wang/chat/share?shareId=3340xwddpp3xi48g1evv7r4m",
|
||||
"icon": "/upload/icon/4e9c7320469f4e6887f63e1f59f32ca1.png",
|
||||
"icon": "/upload/icon/65eb0f29c9e1.png",
|
||||
"description": "快速生成Nginx配置文件,支持负载均衡、反向代理等常见配置",
|
||||
"category": {
|
||||
"main": "dev",
|
||||
@ -52,7 +52,8 @@
|
||||
"category": {
|
||||
"main": "tool",
|
||||
"sub": "office"
|
||||
}
|
||||
},
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "NFS-PV-PVC",
|
||||
@ -62,7 +63,8 @@
|
||||
"category": {
|
||||
"main": "dev",
|
||||
"sub": "cloud"
|
||||
}
|
||||
},
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "刑法助手",
|
||||
@ -72,7 +74,8 @@
|
||||
"category": {
|
||||
"main": "law",
|
||||
"sub": "criminal"
|
||||
}
|
||||
},
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "税法助手",
|
||||
@ -82,7 +85,8 @@
|
||||
"category": {
|
||||
"main": "law",
|
||||
"sub": "tax"
|
||||
}
|
||||
},
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "汉语新解",
|
||||
@ -92,11 +96,12 @@
|
||||
"category": {
|
||||
"main": "edu",
|
||||
"sub": "language"
|
||||
}
|
||||
},
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "AI绘画提示词",
|
||||
"url": "https://fastai.liuyan.wang/chat/share?shareId=example1",
|
||||
"url": "https://prompthero.com/stable-diffusion-prompts",
|
||||
"icon": "fa-paint-brush",
|
||||
"category": {
|
||||
"main": "ai",
|
||||
@ -107,18 +112,19 @@
|
||||
},
|
||||
{
|
||||
"title": "AI写作助手",
|
||||
"url": "https://fastai.liuyan.wang/chat/share?shareId=example2",
|
||||
"icon": "fa-keyboard",
|
||||
"url": "https://www.sudowrite.com/",
|
||||
"icon": "fa-solid fa-graduation-cap",
|
||||
"category": {
|
||||
"main": "ai",
|
||||
"sub": "writing"
|
||||
},
|
||||
"description": "辅助创作各类文本内容,包括文章、报告和创意写作"
|
||||
"description": "辅助创作各类文本内容,包括文章、报告和创意写作",
|
||||
"private": false
|
||||
},
|
||||
{
|
||||
"title": "2222",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "/upload/icon/c6379d5521f24ca789e6712008f115f5.png",
|
||||
"title": "云资源管理器",
|
||||
"url": "https://explore.cloud.google.com/",
|
||||
"icon": "fa-solid fa-file-word",
|
||||
"description": "云计算相关工具和资源集合",
|
||||
"private": false,
|
||||
"category": {
|
||||
@ -127,9 +133,9 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "66666",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "/upload/icon/65eb0f29c9e147e0924890e9ae12e94f.png",
|
||||
"title": "AI图像生成器",
|
||||
"url": "https://www.midjourney.com/",
|
||||
"icon": "fa-solid fa-calculator",
|
||||
"description": "AI图像处理和生成工具",
|
||||
"private": false,
|
||||
"category": {
|
||||
@ -138,10 +144,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "77777",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "/upload/icon/7fb7491311f7477e9e3bd17150a929b7.png",
|
||||
"description": "",
|
||||
"title": "创意写作助手",
|
||||
"url": "https://www.novelai.net/",
|
||||
"icon": "/upload/icon/c6379d5521f2.png",
|
||||
"description": "提供创意写作灵感和结构建议",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "ai",
|
||||
@ -149,10 +155,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "88888",
|
||||
"url": "https://baidu.com",
|
||||
"title": "AI艺术创作",
|
||||
"url": "https://www.artbreeder.com/",
|
||||
"icon": "fa-solid fa-flushed",
|
||||
"description": "",
|
||||
"description": "使用AI技术进行艺术创作和图像风格转换",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "ai",
|
||||
@ -160,10 +166,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "99999",
|
||||
"url": "https://baidu.com",
|
||||
"title": "语言学习助手",
|
||||
"url": "https://www.duolingo.com/",
|
||||
"icon": "fa-solid fa-calculator",
|
||||
"description": "",
|
||||
"description": "提供多语言学习资源和练习工具",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "edu",
|
||||
@ -171,32 +177,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "12121",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "fa-solid fa-heart",
|
||||
"description": "",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "law",
|
||||
"sub": "criminal"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "12123",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "fa-solid fa-graduation-cap",
|
||||
"description": "",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "edu",
|
||||
"sub": "language"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "57567",
|
||||
"url": "https://baidu.com",
|
||||
"title": "法律案例库",
|
||||
"url": "https://www.casemine.com/",
|
||||
"icon": "fa-solid fa-carrot",
|
||||
"description": "",
|
||||
"description": "收录各类法律案例和判决文书",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "law",
|
||||
@ -204,10 +188,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "ythtyh",
|
||||
"url": "https://baidu.com",
|
||||
"title": "法律时效查询",
|
||||
"url": "https://www.law.cornell.edu/wex/statute_of_limitations",
|
||||
"icon": "fa-solid fa-clock",
|
||||
"description": "",
|
||||
"description": "查询各类法律诉讼时效和期限",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "law",
|
||||
@ -215,14 +199,102 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "dsfds",
|
||||
"url": "https://baidu.com",
|
||||
"icon": "fa-solid fa-robot",
|
||||
"description": "",
|
||||
"title": "数据分析工具",
|
||||
"url": "https://www.kaggle.com/",
|
||||
"icon": "fa-solid fa-chart-line",
|
||||
"description": "提供数据可视化和分析功能",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "dev",
|
||||
"sub": "data"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "UI设计助手",
|
||||
"url": "https://www.figma.com/",
|
||||
"icon": "fa-solid fa-paint-brush",
|
||||
"description": "提供UI设计灵感和素材资源",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "design",
|
||||
"sub": "ui"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "法律文书模板",
|
||||
"url": "https://www.lawdepot.com/contracts/",
|
||||
"icon": "fa-solid fa-balance-scale",
|
||||
"description": "提供各类法律文书模板和范例",
|
||||
"private": true,
|
||||
"category": {
|
||||
"main": "law",
|
||||
"sub": "document"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "数学公式助手",
|
||||
"url": "https://www.mathway.com/",
|
||||
"icon": "fa-solid fa-square-root-variable",
|
||||
"description": "提供数学公式编辑和计算功能",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "edu",
|
||||
"sub": "language"
|
||||
"sub": "math"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "健身计划生成器",
|
||||
"url": "https://www.jefit.com/",
|
||||
"icon": "fa-solid fa-dumbbell",
|
||||
"description": "根据个人情况生成定制化健身计划",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "health",
|
||||
"sub": "fitness"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "营养计算器",
|
||||
"url": "https://www.myfitnesspal.com/",
|
||||
"icon": "fa-solid fa-apple-whole",
|
||||
"description": "计算每日营养摄入和饮食建议",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "health",
|
||||
"sub": "nutrition"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "平面设计素材库",
|
||||
"url": "https://www.canva.com/",
|
||||
"icon": "fa-solid fa-palette",
|
||||
"description": "提供丰富的平面设计素材和模板",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "design",
|
||||
"sub": "graphic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "AI代码生成器",
|
||||
"url": "https://github.com/features/copilot",
|
||||
"icon": "fa-solid fa-code",
|
||||
"description": "根据自然语言描述生成代码片段",
|
||||
"private": true,
|
||||
"category": {
|
||||
"main": "ai",
|
||||
"sub": "code"
|
||||
}
|
||||
},
|
||||
{
|
||||
"title": "番茄工作法计时器",
|
||||
"url": "https://pomofocus.io/",
|
||||
"icon": "fa-solid fa-clock",
|
||||
"description": "基于番茄工作法的时间管理工具",
|
||||
"private": false,
|
||||
"category": {
|
||||
"main": "tool",
|
||||
"sub": "time"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -1,61 +1,66 @@
|
||||
[
|
||||
{
|
||||
"filename": "d078c01de3be46deab9e85a94285d785.png",
|
||||
"filename": "d078c01de3be.png",
|
||||
"type": "background",
|
||||
"upload_time": "2025-07-05 13:55:10"
|
||||
},
|
||||
{
|
||||
"filename": "5dd4f5d3cd7b48eca9967fa063ea5cd9.png",
|
||||
"filename": "5dd4f5d3cd7b.png",
|
||||
"type": "background",
|
||||
"upload_time": "2025-07-05 13:55:15"
|
||||
},
|
||||
{
|
||||
"filename": "b2c128cf2d4e47daa349c5e7f38c932c.png",
|
||||
"filename": "b2c128cf2d4e.png",
|
||||
"type": "logo",
|
||||
"upload_time": "2025-07-05 13:58:32"
|
||||
},
|
||||
{
|
||||
"filename": "5378dda810964da9a7515ec844628738.png",
|
||||
"filename": "5378dda81096.png",
|
||||
"type": "logo",
|
||||
"upload_time": "2025-07-05 16:46:09"
|
||||
},
|
||||
{
|
||||
"filename": "f40e2eb965b24e358a5bba9523231f8f.png",
|
||||
"filename": "f40e2eb965b2.png",
|
||||
"type": "logo",
|
||||
"upload_time": "2025-07-05 16:46:16"
|
||||
},
|
||||
{
|
||||
"filename": "e4e762f039ce471489fc65db6cd395c7.mp4",
|
||||
"filename": "59d8647c45f8.png",
|
||||
"type": "logo",
|
||||
"upload_time": "2025-07-05 16:46:16"
|
||||
},
|
||||
{
|
||||
"filename": "e4e762f039ce.mp4",
|
||||
"type": "video",
|
||||
"upload_time": "2025-07-05 20:54:08"
|
||||
},
|
||||
{
|
||||
"filename": "b23249a9681840329afb0c4af489fc30.mp4",
|
||||
"filename": "b23249a96818.mp4",
|
||||
"type": "video",
|
||||
"upload_time": "2025-07-05 21:02:17"
|
||||
},
|
||||
{
|
||||
"filename": "4e9c7320469f4e6887f63e1f59f32ca1.png",
|
||||
"filename": "4e9c7320469f.png",
|
||||
"type": "icon",
|
||||
"upload_time": "2025-07-06 18:52:21"
|
||||
},
|
||||
{
|
||||
"filename": "65eb0f29c9e147e0924890e9ae12e94f.png",
|
||||
"filename": "65eb0f29c9e1.png",
|
||||
"type": "icon",
|
||||
"upload_time": "2025-07-06 19:03:04"
|
||||
},
|
||||
{
|
||||
"filename": "c6379d5521f24ca789e6712008f115f5.png",
|
||||
"filename": "c6379d5521f2.png",
|
||||
"type": "icon",
|
||||
"upload_time": "2025-07-06 20:21:54"
|
||||
},
|
||||
{
|
||||
"filename": "7fb7491311f7477e9e3bd17150a929b7.png",
|
||||
"filename": "7fb7491311f7.png",
|
||||
"type": "icon",
|
||||
"upload_time": "2025-07-06 20:22:11"
|
||||
},
|
||||
{
|
||||
"filename": "c77f6bbbb33540d98a6cc088d01d7ad6.png",
|
||||
"filename": "c77f6bbbb335.png",
|
||||
"type": "icon",
|
||||
"upload_time": "2025-07-06 20:22:28"
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
"cloud": {
|
||||
"name": "云计算",
|
||||
"color": "#480ca8",
|
||||
"weight": 0
|
||||
"weight": 4
|
||||
}
|
||||
},
|
||||
"private": true,
|
||||
@ -31,7 +31,7 @@
|
||||
"ops": true,
|
||||
"cloud": false
|
||||
},
|
||||
"weight": 99999
|
||||
"weight": 9527
|
||||
},
|
||||
"edu": {
|
||||
"name": "教育学习",
|
||||
@ -40,16 +40,21 @@
|
||||
"science": {
|
||||
"name": "自然科学",
|
||||
"color": "#b5179e",
|
||||
"weight": 0
|
||||
"weight": 2
|
||||
},
|
||||
"language": {
|
||||
"name": "语言",
|
||||
"color": "#7209b7",
|
||||
"weight": 0
|
||||
"weight": 3
|
||||
},
|
||||
"math": {
|
||||
"name": "数学",
|
||||
"color": "#560bad",
|
||||
"weight": 4
|
||||
}
|
||||
},
|
||||
"private": false,
|
||||
"weight": 0
|
||||
"private": true,
|
||||
"weight": 8
|
||||
},
|
||||
"tool": {
|
||||
"name": "效率工具",
|
||||
@ -58,10 +63,16 @@
|
||||
"office": {
|
||||
"name": "办公",
|
||||
"color": "#560bad",
|
||||
"weight": 0
|
||||
"weight": 1
|
||||
},
|
||||
"time": {
|
||||
"name": "时间管理",
|
||||
"color": "#3a0ca3",
|
||||
"weight": 2
|
||||
}
|
||||
},
|
||||
"weight": 0
|
||||
"weight": 7,
|
||||
"private": false
|
||||
},
|
||||
"law": {
|
||||
"name": "法律相关",
|
||||
@ -70,15 +81,21 @@
|
||||
"criminal": {
|
||||
"name": "刑法",
|
||||
"color": "#4361ee",
|
||||
"weight": 0
|
||||
"weight": 2
|
||||
},
|
||||
"tax": {
|
||||
"name": "税法",
|
||||
"color": "#3f37c9",
|
||||
"weight": 0
|
||||
"weight": 1
|
||||
},
|
||||
"document": {
|
||||
"name": "法律文书",
|
||||
"color": "#3a0ca3",
|
||||
"weight": 1
|
||||
}
|
||||
},
|
||||
"weight": 0
|
||||
"weight": 6,
|
||||
"private": false
|
||||
},
|
||||
"ai": {
|
||||
"name": "AI工具",
|
||||
@ -92,13 +109,55 @@
|
||||
"writing": {
|
||||
"name": "写作",
|
||||
"color": "#f9844a",
|
||||
"weight": 0
|
||||
"weight": 5
|
||||
},
|
||||
"code": {
|
||||
"name": "代码生成",
|
||||
"color": "#f8961e",
|
||||
"weight": 6
|
||||
}
|
||||
},
|
||||
"private": false,
|
||||
"private": true,
|
||||
"sub_private": {
|
||||
"image": false
|
||||
"image": false,
|
||||
"code": true
|
||||
},
|
||||
"weight": 29999
|
||||
"weight": 52
|
||||
},
|
||||
"design": {
|
||||
"name": "设计工具",
|
||||
"color": "#f94144",
|
||||
"sub": {
|
||||
"ui": {
|
||||
"name": "UI设计",
|
||||
"color": "#f3722c",
|
||||
"weight": 3
|
||||
},
|
||||
"graphic": {
|
||||
"name": "平面设计",
|
||||
"color": "#f8961e",
|
||||
"weight": 4
|
||||
}
|
||||
},
|
||||
"weight": 5,
|
||||
"private": false
|
||||
},
|
||||
"health": {
|
||||
"name": "健康医疗",
|
||||
"color": "#43aa8b",
|
||||
"sub": {
|
||||
"fitness": {
|
||||
"name": "健身",
|
||||
"color": "#90be6d",
|
||||
"weight": 3
|
||||
},
|
||||
"nutrition": {
|
||||
"name": "营养",
|
||||
"color": "#4d908e",
|
||||
"weight": 2
|
||||
}
|
||||
},
|
||||
"weight": 4,
|
||||
"private": false
|
||||
}
|
||||
}
|
||||
@ -2,14 +2,14 @@
|
||||
"card_style": "compact",
|
||||
"search_history": [],
|
||||
"theme": "light",
|
||||
"bg_image": "/upload/background/5dd4f5d3cd7b48eca9967fa063ea5cd9.png",
|
||||
"dark_bg_image": "/upload/background/d078c01de3be46deab9e85a94285d785.png",
|
||||
"site_title": "应用导航",
|
||||
"bg_image": "/upload/background/5dd4f5d3cd7b.png",
|
||||
"dark_bg_image": "/upload/background/d078c01de3be.png",
|
||||
"site_title": "应用导航中心",
|
||||
"show_logo": true,
|
||||
"logo_type": "image",
|
||||
"logo_icon": "fa-solid fa-th-list",
|
||||
"logo_image": "/upload/logo/b2c128cf2d4e47daa349c5e7f38c932c.png",
|
||||
"logo_image": "/upload/logo/f40e2eb965b2.png",
|
||||
"dark_bg_rotate": false,
|
||||
"admin_password_hash": "scrypt:32768:8:1$mPFCfRRzOrcjE6z3$e72ef50a2d3f7292f64bcfc5e21f32c95ea8665414ea8d5f6b216735d68f151166c99fae21132c7949bd92ea32041f969cd4a471adb110a99328089541f7dccb",
|
||||
"footer_html": "<div class=\"flex flex-col items-center text-slate-400 text-sm py-4\" style=\"margin-top:100px\">\r\n <div class=\"flex items-center\">\r\n <span>© 2023 AIDaohang. All rights reserved.</span>\r\n <span class=\"mx-2\">|</span>\r\n <span>Powered by <a href=\"https://github.com\" target=\"_blank\" class=\"hover:text-slate-200 ml-1\">AIDaohang</a></span>\r\n </div>\r\n</div>"
|
||||
"footer_html": "<div class=\"flex flex-col items-center text-slate-400 text-sm py-4\" style=\"margin-top:10px\">\r\n <div class=\"flex items-center\">\r\n <span>© 2023 AIDaohang. All rights reserved.</span>\r\n <span class=\"mx-2\">|</span>\r\n <span>Powered by <a href=\"https://github.com\" target=\"_blank\" class=\"hover:text-slate-200 ml-1\">AIDaohang</a></span>\r\n </div>\r\n</div>"
|
||||
}
|
||||
@ -9,6 +9,7 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="post">
|
||||
<input type="hidden" name="page" value="{{ request.args.get('page', '1') }}">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">标题</label>
|
||||
<input type="text" name="title" class="form-control" value="{{ app.title }}" required>
|
||||
|
||||
45
templates/icontest.html
Normal file
@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Font Awesome 图标示例</title>
|
||||
<!-- 引入Font Awesome CSS -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
/* 可选:设置图标样式 */
|
||||
.icon {
|
||||
font-size: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Font Awesome 图标示例</h1>
|
||||
|
||||
<div>
|
||||
<i class="fa-solid fa-undo icon"></i> 撤销
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-solid fa-undo-alt icon"></i> 撤销(替代)
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-solid fa-unlink icon"></i> 取消链接
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-solid fa-wrench icon"></i> 扳手
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-brands fa-500px icon"></i> 500px
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-brands fa-accessible-icon icon"></i> 无障碍图标
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-brands fa-accusoft icon"></i> Accusoft
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa-brands fa-acquisitions-incorporated icon"></i> Acquisitions Inc
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -35,6 +35,29 @@
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* 新增私有卡片标记样式 */
|
||||
.private-badge {
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-style: solid;
|
||||
border-width: 0 30px 30px 0;
|
||||
border-color: transparent #f8961e transparent transparent;
|
||||
border-radius: 0 12px 0 0; /* 只圆角右上角 */
|
||||
}
|
||||
|
||||
.private-badge::after {
|
||||
content: "私";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: -25px;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
img, svg {
|
||||
vertical-align: middle;
|
||||
margin-bottom: 7px !important;
|
||||
@ -333,15 +356,45 @@
|
||||
overflow-x: auto;
|
||||
padding-bottom: 10px;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--primary-color) transparent;
|
||||
scrollbar-color: #c2c3c9d6;
|
||||
justify-content: center; /* 默认居中 */
|
||||
padding: 0 20px; /* 添加内边距 */
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 当内容超出时靠左 */
|
||||
.filter-row.scrollable {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 新增的滚动指示器 */
|
||||
.filter-row::before,
|
||||
.filter-row::after {
|
||||
content: '';
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.filter-row::before {
|
||||
left: 0;
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
.filter-row::after {
|
||||
right: 0;
|
||||
background: linear-gradient(270deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
body.dark-theme .filter-row::before,
|
||||
body.dark-theme .filter-row::after {
|
||||
background: linear-gradient(90deg, rgba(30,30,30,0.8) 0%, rgba(30,30,30,0) 100%);
|
||||
}
|
||||
|
||||
/* 自定义滚动条样式 */
|
||||
.filter-row::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
@ -377,13 +430,13 @@
|
||||
}
|
||||
/* 一级标签样式 */
|
||||
.filter-btn[data-level="1"] {
|
||||
font-size: 15px;
|
||||
padding: 4px 18px;
|
||||
font-size: 13px;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
/* 二级标签样式 */
|
||||
.filter-btn[data-level="2"] {
|
||||
font-size: 13px;
|
||||
padding: 6px 12px;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
/* 分类选择器颜色 */
|
||||
.filter-btn.dev {
|
||||
@ -419,9 +472,19 @@
|
||||
overflow-x: auto;
|
||||
padding-bottom: 10px;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--primary-color) transparent;
|
||||
scrollbar-color: #c2c3c9d6;
|
||||
justify-content: center; /* 默认居中 */
|
||||
padding: 0 20px; /* 添加内边距 */
|
||||
scroll-behavior: smooth;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 私有主分类 */
|
||||
.category-title .badge {
|
||||
font-size: 12px;
|
||||
padding: 3px 6px;
|
||||
vertical-align: middle;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
/* 当内容超出时靠左 */
|
||||
@ -429,6 +492,33 @@
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* 新增的滚动指示器 */
|
||||
.secondary-filters-container::before,
|
||||
.secondary-filters-container::after {
|
||||
content: '';
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 40px;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.secondary-filters-container::before {
|
||||
left: 0;
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
.secondary-filters-container::after {
|
||||
right: 0;
|
||||
background: linear-gradient(270deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
body.dark-theme .secondary-filters-container::before,
|
||||
body.dark-theme .secondary-filters-container::after {
|
||||
background: linear-gradient(90deg, rgba(30,30,30,0.8) 0%, rgba(30,30,30,0) 100%);
|
||||
}
|
||||
|
||||
/* 自定义二级筛选容器的滚动条样式 */
|
||||
.secondary-filters-container::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
@ -813,7 +903,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
// 按权重对分类进行排序
|
||||
// 按权重对分类进行排序(无论是否登录都排序)
|
||||
categories = Object.fromEntries(
|
||||
Object.entries(categories).sort((a, b) => {
|
||||
const weightA = a[1].weight || 0;
|
||||
@ -835,6 +925,19 @@
|
||||
}
|
||||
});
|
||||
|
||||
// 对每个主分类下的子分类也按权重排序
|
||||
Object.values(categories).forEach(cat => {
|
||||
if (cat.sub) {
|
||||
cat.sub = Object.fromEntries(
|
||||
Object.entries(cat.sub).sort((a, b) => {
|
||||
const weightA = a[1].weight || 0;
|
||||
const weightB = b[1].weight || 0;
|
||||
return weightB - weightA; // 降序排列
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 渲染界面
|
||||
renderFilters();
|
||||
renderApps();
|
||||
@ -989,6 +1092,9 @@
|
||||
secondaryFiltersWrapper.innerHTML = '';
|
||||
secondaryFiltersWrapper.appendChild(container);
|
||||
currentExpandedPrimary = null;
|
||||
|
||||
// 为新创建的二级筛选容器添加滚轮事件
|
||||
addWheelEventToContainer(container);
|
||||
}
|
||||
|
||||
// 展开二级标签
|
||||
@ -1028,6 +1134,9 @@
|
||||
secondaryFiltersWrapper.innerHTML = '';
|
||||
secondaryFiltersWrapper.appendChild(container);
|
||||
currentExpandedPrimary = primaryFilterId;
|
||||
|
||||
// 为新创建的二级筛选容器添加滚轮事件
|
||||
addWheelEventToContainer(container);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1037,6 +1146,16 @@
|
||||
currentExpandedPrimary = null;
|
||||
}
|
||||
|
||||
// 为滚动容器添加滚轮事件
|
||||
function addWheelEventToContainer(container) {
|
||||
container.addEventListener('wheel', (e) => {
|
||||
if (e.deltaY !== 0) {
|
||||
e.preventDefault();
|
||||
container.scrollLeft += e.deltaY;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 设置当前筛选条件
|
||||
function setFilter(primaryFilter, secondaryFilter) {
|
||||
currentPrimaryFilter = primaryFilter;
|
||||
@ -1114,10 +1233,22 @@
|
||||
const groupDiv = document.createElement('div');
|
||||
groupDiv.className = 'app-group';
|
||||
|
||||
// 检查该主分类是否为私有分类且用户已登录
|
||||
const isPrivateCategory = mainCatData.private && isLoggedIn;
|
||||
|
||||
// 添加分类标题(使用第一个应用的图标)
|
||||
const titleDiv = document.createElement('div');
|
||||
titleDiv.className = 'category-title';
|
||||
titleDiv.innerHTML = `<i class="fas ${firstAppIcon}"></i> ${mainCatData.name}`;
|
||||
|
||||
// 如果是私有分类且已登录,添加私有标记
|
||||
if (isPrivateCategory) {
|
||||
const privateBadge = document.createElement('span');
|
||||
privateBadge.className = 'badge bg-warning text-dark ms-2';
|
||||
privateBadge.textContent = '私有';
|
||||
titleDiv.appendChild(privateBadge);
|
||||
}
|
||||
|
||||
groupDiv.appendChild(titleDiv);
|
||||
|
||||
// 创建应用列表
|
||||
@ -1134,6 +1265,13 @@
|
||||
appItem.href = app.url;
|
||||
appItem.target = '_blank';
|
||||
|
||||
// 如果是私有应用且已登录,添加私有标记
|
||||
if (app.private && isLoggedIn) {
|
||||
const privateBadge = document.createElement('div');
|
||||
privateBadge.className = 'private-badge';
|
||||
appItem.appendChild(privateBadge);
|
||||
}
|
||||
|
||||
// 添加聊天气泡描述提示框
|
||||
const descriptionDiv = document.createElement('div');
|
||||
descriptionDiv.className = 'app-description';
|
||||
@ -1144,7 +1282,7 @@
|
||||
`<img src="${app.icon}" alt="图标">` :
|
||||
`<i class="fas ${app.icon}"></i>`;
|
||||
|
||||
appItem.innerHTML = `
|
||||
appItem.innerHTML += `
|
||||
<div class="app-icon">
|
||||
${iconHtml}
|
||||
</div>
|
||||
@ -1317,7 +1455,7 @@
|
||||
// 应用主题
|
||||
document.body.classList.remove('dark-theme', 'light-theme');
|
||||
if (settings.theme === 'dark' ||
|
||||
(settings.theme === 'auto' && window.matchMedia('(prefers-color-sscheme: dark)').matches)) {
|
||||
(settings.theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
document.body.classList.add('dark-theme');
|
||||
|
||||
// 显示/隐藏视频背景
|
||||
@ -1488,7 +1626,16 @@
|
||||
setupThemeSwitcher();
|
||||
setupCompactToggle();
|
||||
setupAdminButton();
|
||||
|
||||
// 为静态的一级筛选容器添加滚轮事件
|
||||
primaryFilters.addEventListener('wheel', (e) => {
|
||||
if (e.deltaY !== 0) {
|
||||
e.preventDefault();
|
||||
primaryFilters.scrollLeft += e.deltaY;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function checkScrollable() {
|
||||
document.querySelectorAll('.filter-row, .secondary-filters-container').forEach(container => {
|
||||
// 检查内容宽度是否大于容器宽度
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
</td>
|
||||
<td><a href="{{ app.url }}" target="_blank">{{ app.url[:30] }}...</a></td>
|
||||
<td>
|
||||
<a href="{{ url_for('edit_app', index=loop.index0) }}" class="btn btn-sm btn-warning">
|
||||
<a href="{{ url_for('edit_app', index=(current_page-1)*per_page + loop.index0) }}" class="btn btn-sm btn-warning">
|
||||
<i class="fas fa-edit"></i> 编辑
|
||||
</a>
|
||||
<a href="{{ url_for('delete_app', index=loop.index0) }}" class="btn btn-sm btn-danger" onclick="return confirm('确定删除吗?')">
|
||||
|
||||
|
Before Width: | Height: | Size: 720 KiB After Width: | Height: | Size: 720 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |