最近在整理个人收藏的二次元角色图库时,发现很多朋友对如何高效地管理、展示和分享自己喜爱的角色图片感到头疼。手动整理费时费力,分享起来也不方便。本文将以人气角色“枫”(《猫娘乐园》)为例,手把手带你从零开始,用 Python 和 Flask 框架搭建一个轻量级的个人向“每日美少女”图站。整个过程不仅会涵盖 Web 开发的核心流程,还会融入图片处理、前端展示等实用技巧,适合有一定 Python 基础,想通过实战项目巩固技能的开发者。学完后,你将拥有一个完全由自己掌控的、可自定义的在线角色图库。
1. 项目背景与核心概念
1.1 什么是“每日美少女”图站?
“每日美少女”图站本质上是一个个人化的图片内容管理与展示系统。它不同于大型图库或社交平台,核心目标是为收藏者提供一个私有的、可按自己喜好(如角色、作品、标签)分类和展示图片的空间。以《猫娘乐园》的“枫”为例,你可以将所有关于她的官方立绘、同人作品、表情包等集中管理,并设置每日随机展示或按特定规则轮播。
这个项目解决了几个实际问题:
- 资料分散:图片可能散落在电脑文件夹、手机相册、不同网站收藏夹,难以统一查看。
- 分享不便:向同好分享特定角色的全套图片时,需要多次发送文件或链接。
- 缺乏仪式感:通过一个专属网页每日打开欣赏自己喜欢的角色,能增加收藏的乐趣和仪式感。
1.2 技术栈选型:为什么用 Flask?
对于个人或小型的图片展示项目,我们追求的是快速开发、易于部署、足够轻量。Flask 作为一个微框架,完美契合这些需求:
- 轻量灵活:核心简单,没有强制的项目结构,可以根据需求自由添加组件。
- 易于上手:对于已经掌握 Python 基础语法的开发者,学习曲线平缓。
- 生态丰富:有大量扩展(Flask-Extensions)可以处理路由、数据库、表单、文件上传等常见需求。 本项目将使用以下核心库:
- Flask: Web 框架本体。
- Pillow (PIL): Python 图像处理库,用于获取图片尺寸、生成缩略图。
- SQLite: 轻量级数据库,无需单独安装服务器,适合个人项目。
- Jinja2: Flask 默认的模板引擎,用于动态生成 HTML。
2. 环境准备与项目初始化
2.1 开发环境说明
- 操作系统:Windows 10/11, macOS, 或 Linux (如 Ubuntu) 均可。本文示例在 Windows 11 下完成。
- Python 版本:3.8 或以上。请确保你的 Python 环境已正确安装。
- 包管理工具:使用
pip进行 Python 包管理。 - 代码编辑器:推荐 VS Code、PyCharm 或任何你熟悉的文本编辑器。
2.2 创建项目目录与虚拟环境
为了避免污染全局 Python 环境,首先为项目创建一个独立的虚拟环境。
# 1. 创建项目文件夹并进入 mkdir daily-moe-gallery cd daily-moe-gallery # 2. 创建虚拟环境 (Windows) python -m venv venv # 激活虚拟环境 (Windows) venv\Scripts\activate # 如果是 macOS/Linux # python3 -m venv venv # source venv/bin/activate # 激活后,命令行提示符前会出现 (venv) 标识2.3 安装依赖包
在激活的虚拟环境中,使用pip安装项目所需的库。
pip install flask pillowFlask是 web 框架,Pillow是图像处理库。SQLite 是 Python 标准库的一部分,无需单独安装。
2.4 初始化项目结构
一个清晰的项目结构有助于后期维护。创建如下文件和文件夹:
daily-moe-gallery/ │ ├── app.py # Flask 应用主入口 ├── config.py # 配置文件 ├── requirements.txt # 项目依赖列表 │ ├── static/ # 静态资源文件夹 │ ├── css/ │ │ └── style.css # 样式表 │ └── images/ # **用户上传的图片将存放在这里** │ ├── templates/ # Jinja2 模板文件夹 │ ├── base.html # 基础模板 │ ├── index.html # 首页模板 │ └── upload.html # 上传页面模板 │ └── database.py # 数据库操作模块接下来,我们创建requirements.txt文件来记录依赖。
# 在项目根目录执行 pip freeze > requirements.txt此时requirements.txt内容应包含Flask和Pillow等。
3. 核心功能设计与数据库建模
3.1 功能模块拆解
我们的“每日美少女”图站需要实现以下核心功能:
- 图片管理:上传、删除、查看图片。
- 信息记录:为每张图片记录角色名、来源作品、标签、上传时间等元数据。
- 内容展示:首页随机展示一张图片(“每日”),并提供按角色、标签浏览的图库页面。
- 后台管理:一个简单的页面用于上传和删除图片(为简化,暂不设复杂权限)。
3.2 数据库表设计
我们使用 SQLite 数据库。在database.py中,我们将定义并初始化数据库。
首先,思考需要存储哪些信息。一张图片(Image)的核心属性包括:
id: 主键,唯一标识。filename: 存储在服务器上的文件名。title: 图片标题(如“枫-夏日泳装”)。character: 角色名(如“枫”)。source: 来源作品(如“猫娘乐园/Nekopara”)。tags: 标签,用逗号分隔的字符串存储(如“泳装, 夏日, 官方”)。upload_time: 上传时间。width&height: 图片原始尺寸,用于前端展示时保持比例。
database.py 代码:
# database.py import sqlite3 from datetime import datetime def get_db_connection(): """创建并返回一个数据库连接。""" conn = sqlite3.connect('gallery.db') # 设置返回字典格式的行,方便操作 conn.row_factory = sqlite3.Row return conn def init_db(): """初始化数据库,创建表(如果不存在)。""" conn = get_db_connection() cursor = conn.cursor() # 创建 images 表 cursor.execute(''' CREATE TABLE IF NOT EXISTS images ( id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT NOT NULL UNIQUE, title TEXT, character TEXT, source TEXT, tags TEXT, upload_time TIMESTAMP NOT NULL, width INTEGER, height INTEGER ) ''') conn.commit() conn.close() print("数据库初始化完成!") if __name__ == '__main__': # 直接运行此文件来初始化数据库 init_db()运行python database.py来创建数据库文件gallery.db和images表。
4. Flask 应用骨架与配置
4.1 基础配置 (config.py)
我们将一些配置项单独放在config.py中,便于管理。
config.py 代码:
# config.py import os # 获取项目根目录的绝对路径 basedir = os.path.abspath(os.path.dirname(__file__)) class Config: # 密钥,用于会话安全等,务必在生产环境中更改! SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key-change-in-production' # 数据库路径 DATABASE = os.path.join(basedir, 'gallery.db') # 上传配置 UPLOAD_FOLDER = os.path.join(basedir, 'static', 'images') # 上传目录 ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'webp'} # 允许的图片格式 MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 最大上传大小 16MB # 创建上传目录(如果不存在) os.makedirs(Config.UPLOAD_FOLDER, exist_ok=True)4.2 创建 Flask 应用 (app.py)
这是应用的核心文件,我们将在这里定义路由和主要逻辑。
app.py 基础结构:
# app.py from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory from werkzeug.utils import secure_filename from PIL import Image import os from datetime import datetime from database import get_db_connection, init_db from config import Config # 初始化 Flask 应用 app = Flask(__name__) app.config.from_object(Config) # 确保数据库和上传目录存在 with app.app_context(): init_db() def allowed_file(filename): """检查文件扩展名是否合法。""" return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS'] # 首页路由 - 随机展示一张图片 @app.route('/') def index(): conn = get_db_connection() # 随机选择一张图片 daily_image = conn.execute('SELECT * FROM images ORDER BY RANDOM() LIMIT 1').fetchone() conn.close() return render_template('index.html', image=daily_image) if __name__ == '__main__': app.run(debug=True)现在,基础骨架已经搭建完成。运行python app.py,访问http://127.0.0.1:5000,你会看到一个空白页(因为还没有模板和图片)。接下来我们实现核心功能。
5. 核心功能实现:图片上传与管理
5.1 图片上传页面与逻辑
我们需要一个页面让用户填写图片信息并上传文件。
首先,创建上传页面的模板templates/upload.html。
templates/upload.html:
<!-- templates/upload.html --> {% extends "base.html" %} {% block title %}上传新图片 - 每日美少女图库{% endblock %} {% block content %} <h2>上传新的美少女图片</h2> <form method="post" enctype="multipart/form-data"> <div> <label for="file">选择图片文件:</label> <input type="file" id="file" name="file" accept="image/*" required> <small>支持格式:{{ config.ALLOWED_EXTENSIONS | join(', ') }},最大 {{ config.MAX_CONTENT_LENGTH // (1024*1024) }}MB</small> </div> <div> <label for="title">图片标题:</label> <input type="text" id="title" name="title" placeholder="例如:枫-夏日泳装"> </div> <div> <label for="character">角色名:</label> <input type="text" id="character" name="character" placeholder="例如:枫" required> </div> <div> <label for="source">来源作品:</label> <input type="text" id="source" name="source" placeholder="例如:猫娘乐园"> </div> <div> <label for="tags">标签(用逗号分隔):</label> <input type="text" id="tags" name="tags" placeholder="例如:泳装, 官方, 夏日"> </div> <button type="submit">上传图片</button> </form> {% endblock %}然后,在app.py中添加处理上传的路由。
app.py 新增上传路由:
# app.py (续) @app.route('/upload', methods=['GET', 'POST']) def upload_file(): if request.method == 'POST': # 检查是否有文件部分 if 'file' not in request.files: flash('没有选择文件') return redirect(request.url) file = request.files['file'] # 如果用户没有选择文件,浏览器也可能提交一个空文件 if file.filename == '': flash('没有选择文件') return redirect(request.url) if file and allowed_file(file.filename): # 安全化文件名,防止路径遍历攻击 filename = secure_filename(file.filename) # 为避免重名,添加时间戳 from datetime import datetime timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') name, ext = os.path.splitext(filename) unique_filename = f"{name}_{timestamp}{ext}" filepath = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename) # 保存文件 file.save(filepath) # 使用 Pillow 获取图片尺寸 try: with Image.open(filepath) as img: width, height = img.size except Exception as e: width, height = None, None print(f"无法读取图片尺寸: {e}") # 获取表单其他数据 title = request.form.get('title', '').strip() character = request.form.get('character', '').strip() source = request.form.get('source', '').strip() tags = request.form.get('tags', '').strip() # 将信息存入数据库 conn = get_db_connection() conn.execute(''' INSERT INTO images (filename, title, character, source, tags, upload_time, width, height) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ''', (unique_filename, title, character, source, tags, datetime.now(), width, height)) conn.commit() conn.close() flash(f'图片 {unique_filename} 上传成功!') return redirect(url_for('index')) else: flash('文件类型不允许或文件过大') return redirect(request.url) # GET 请求,显示上传表单 return render_template('upload.html')5.2 首页展示“每日美少女”
现在完善首页模板,展示随机选出的图片及其信息。
templates/index.html:
<!-- templates/index.html --> {% extends "base.html" %} {% block title %}每日美少女 - 枫(猫娘乐园){% endblock %} {% block content %} <div class="daily-featured"> <h2>今日的美少女</h2> {% if image %} <div class="image-card"> <img src="{{ url_for('static', filename='images/' + image.filename) }}" alt="{{ image.title or image.character }}" style="max-width: 100%; height: auto;"> <div class="image-info"> <h3>{{ image.title if image.title else image.character }}</h3> <p><strong>角色:</strong>{{ image.character }}</p> {% if image.source %}<p><strong>来源:</strong>{{ image.source }}</p>{% endif %} {% if image.tags %}<p><strong>标签:</strong>{{ image.tags }}</p>{% endif %} <p><small>上传于:{{ image.upload_time[:10] }}</small></p> <!-- 刷新按钮,获取新的随机图片 --> <a href="{{ url_for('index') }}">换一张</a> </div> </div> {% else %} <p>图库还是空的哦,快去 <a href="{{ url_for('upload_file') }}">上传第一张图片</a> 吧!</p> {% endif %} </div> <div class="quick-actions"> <a href="{{ url_for('upload_file') }}" class="btn">上传新图片</a> <a href="{{ url_for('gallery') }}" class="btn">浏览完整图库</a> </div> {% endblock %}5.3 创建基础模板 (base.html)
基础模板包含导航栏、页脚和消息闪现块。
templates/base.html:
<!-- templates/base.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}每日美少女图库{% endblock %}</title> <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}"> </head> <body> <header> <nav> <h1><a href="{{ url_for('index') }}">每日美少女图库</a></h1> <ul> <li><a href="{{ url_for('index') }}">今日推荐</a></li> <li><a href="{{ url_for('gallery') }}">图库浏览</a></li> <li><a href="{{ url_for('upload_file') }}">上传图片</a></li> </ul> </nav> </header> <main> <!-- 闪现消息,用于显示上传成功/失败等提示 --> {% with messages = get_flashed_messages() %} {% if messages %} <div class="flash-messages"> {% for message in messages %} <div class="flash">{{ message }}</div> {% endfor %} </div> {% endif %} {% endwith %} {% block content %}{% endblock %} </main> <footer> <p>© 2023 个人向美少女图库 | 基于 Flask 构建 | 示例角色:枫 (Nekopara)</p> </footer> </body> </html>5.4 添加基础样式 (static/css/style.css)
为了让页面看起来更舒适,添加一些基础 CSS。
static/css/style.css:
/* static/css/style.css */ * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333; background-color: #f9f9f9; max-width: 1200px; margin: 0 auto; padding: 20px; } header nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 0; border-bottom: 2px solid #eee; margin-bottom: 2rem; } header nav h1 a { color: #e75480; /* 一个可爱的粉色 */ text-decoration: none; font-size: 1.8rem; } header nav ul { display: flex; list-style: none; } header nav ul li { margin-left: 1.5rem; } header nav ul li a { text-decoration: none; color: #555; font-weight: 500; padding: 0.5rem 1rem; border-radius: 4px; transition: background-color 0.3s; } header nav ul li a:hover { background-color: #f0f0f0; } .daily-featured { background: white; padding: 2rem; border-radius: 10px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); margin-bottom: 2rem; } .image-card { display: flex; flex-wrap: wrap; gap: 2rem; align-items: flex-start; } .image-card img { flex: 1; min-width: 300px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } .image-info { flex: 1; min-width: 300px; } .image-info h3 { color: #e75480; margin-bottom: 1rem; } .image-info p { margin-bottom: 0.5rem; } .quick-actions { display: flex; gap: 1rem; margin-top: 2rem; } .btn { display: inline-block; background-color: #e75480; color: white; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: bold; transition: background-color 0.3s; } .btn:hover { background-color: #d44672; } form div { margin-bottom: 1.5rem; } form label { display: block; margin-bottom: 0.5rem; font-weight: bold; } form input[type="text"], form input[type="file"] { width: 100%; padding: 0.75rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } form button[type="submit"] { @extend .btn; border: none; cursor: pointer; font-size: 1rem; } .flash-messages { margin-bottom: 1.5rem; } .flash { padding: 1rem; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px; } footer { margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid #eee; text-align: center; color: #888; font-size: 0.9rem; }6. 扩展功能:图库浏览与简单管理
6.1 图库浏览页面
我们需要一个页面来展示所有图片,并支持简单的筛选(如按角色)。
首先,在app.py中添加图库路由。
app.py 新增图库路由:
# app.py (续) @app.route('/gallery') def gallery(): character_filter = request.args.get('character', '') conn = get_db_connection() if character_filter: # 按角色筛选 images = conn.execute( 'SELECT * FROM images WHERE character LIKE ? ORDER BY upload_time DESC', (f'%{character_filter}%',) ).fetchall() else: # 显示所有图片 images = conn.execute('SELECT * FROM images ORDER BY upload_time DESC').fetchall() conn.close() return render_template('gallery.html', images=images, character_filter=character_filter)然后,创建图库模板templates/gallery.html。
templates/gallery.html:
<!-- templates/gallery.html --> {% extends "base.html" %} {% block title %}图库浏览 - 每日美少女图库{% endblock %} {% block content %} <h2>图库浏览</h2> <!-- 简单的筛选表单 --> <form method="get" action="{{ url_for('gallery') }}" class="filter-form"> <label for="character">按角色筛选:</label> <input type="text" id="character" name="character" placeholder="输入角色名,如:枫" value="{{ character_filter }}"> <button type="submit">筛选</button> {% if character_filter %} <a href="{{ url_for('gallery') }}">清除筛选</a> {% endif %} </form> {% if images %} <div class="gallery-grid"> {% for image in images %} <div class="gallery-item"> <a href="{{ url_for('static', filename='images/' + image.filename) }}" target="_blank"> <img src="{{ url_for('static', filename='images/' + image.filename) }}" alt="{{ image.title or image.character }}" loading="lazy"> </a> <div class="item-info"> <p><strong>{{ image.title if image.title else image.character }}</strong></p> <p>角色:{{ image.character }}</p> {% if image.tags %}<p>标签:{{ image.tags }}</p>{% endif %} </div> </div> {% endfor %} </div> {% else %} <p>没有找到符合条件的图片。{% if character_filter %}尝试更换筛选条件或<a href="{{ url_for('upload_file') }}">上传图片</a>。{% endif %}</p> {% endif %} {% endblock %}6.2 添加图库样式
在static/css/style.css末尾添加图库样式。
static/css/style.css (追加):
/* 图库样式 */ .filter-form { margin-bottom: 2rem; padding: 1rem; background: #f5f5f5; border-radius: 6px; } .gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1.5rem; } .gallery-item { background: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.08); transition: transform 0.3s, box-shadow 0.3s; } .gallery-item:hover { transform: translateY(-5px); box-shadow: 0 6px 16px rgba(0,0,0,0.12); } .gallery-item img { width: 100%; height: 200px; object-fit: cover; display: block; } .item-info { padding: 1rem; } .item-info p { margin-bottom: 0.3rem; font-size: 0.9rem; }7. 运行与测试
7.1 启动应用
确保你在项目根目录,并且虚拟环境已激活,然后运行:
python app.py你应该看到类似输出:
* Serving Flask app 'app' * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. * Running on http://127.0.0.1:50007.2 功能测试流程
- 访问
http://127.0.0.1:5000,首页会提示图库为空。 - 点击导航栏的“上传图片”或首页的链接,进入上传页面。
- 选择一张“枫”的图片,填写角色名“枫”,来源“猫娘乐园”,标签“猫娘, 女仆, 可爱”等,点击上传。
- 上传成功后,会闪现消息并跳回首页,此时首页会随机展示你刚上传的图片。
- 点击“换一张”可以刷新,看到同一张(因为目前只有一张)。
- 多上传几张不同角色的图片(如“巧克力”、“香草”)。
- 访问
http://127.0.0.1:5000/gallery,查看所有图片的网格展示。 - 在图库页面使用筛选功能,输入“枫”,只显示该角色的图片。
8. 常见问题与排查思路
在开发和使用过程中,你可能会遇到以下问题:
| 问题现象 | 可能原因 | 解决思路 |
|---|---|---|
运行python app.py报ModuleNotFoundError | 依赖未安装或虚拟环境未激活。 | 1. 确认命令行前有(venv)。2. 在项目根目录执行pip install -r requirements.txt。 |
| 上传图片时提示“文件类型不允许” | 文件扩展名不在ALLOWED_EXTENSIONS中,或文件名没有扩展名。 | 1. 检查文件是否为png, jpg, jpeg, gif, webp。2. 确保文件名包含点号,如maple.jpg。 |
| 上传图片后,首页或图库不显示 | 图片未成功保存,或数据库记录未插入。 | 1. 检查static/images/目录下是否有文件。2. 查看 Flask 运行终端的错误输出。3. 使用 SQLite 浏览器查看gallery.db中images表是否有数据。 |
| 图片显示为破损图标 | HTML 中图片路径错误,或文件确实不存在。 | 1. 浏览器右键检查图片 URL 是否正确指向static/images/xxx.jpg。2. 确认文件是否在正确的目录。 |
| 筛选功能不生效 | SQL 查询语句或模板逻辑有误。 | 1. 检查app.py中/gallery路由的查询逻辑。2. 在模板中打印character_filter变量值。 |
| 样式 (CSS) 没有加载 | Flask 未正确配置静态文件夹,或浏览器缓存。 | 1. 确认static/css/style.css文件存在。2. 浏览器按 Ctrl+F5 强制刷新。3. 检查base.html中link标签的href属性。 |
9. 生产环境部署与安全强化建议
当前项目运行在 Flask 自带的开发服务器上,仅适用于本地测试。若要对外提供服务,必须进行安全加固和正式部署。
9.1 安全加固措施
- 更改密钥:在
config.py中,将SECRET_KEY设置为一个长且复杂的随机字符串,可以通过os.urandom(24)生成,并设置为环境变量。# config.py (生产环境) SECRET_KEY = os.environ.get('SECRET_KEY') # 必须设置 - 关闭调试模式:在运行应用时,务必设置
debug=False。# app.py 最后 if __name__ == '__main__': app.run(debug=False) # 生产环境必须为 False - 文件上传限制:
- 保持
MAX_CONTENT_LENGTH限制。 - 在服务器端(如 Nginx)也设置客户端最大 body 大小。
- 考虑使用扩展如
Flask-WTF和Flask-Limiter来增强表单验证和频率限制。
- 保持
- SQL 注入防护:本项目使用参数化查询 (
?占位符),已有效防止 SQL 注入。切勿使用字符串拼接构造 SQL。
9.2 部署方案(以 Gunicorn + Nginx 为例)
- 安装生产 WSGI 服务器:在虚拟环境中安装 Gunicorn。
pip install gunicorn - 使用 Gunicorn 启动:
gunicorn -w 4 -b 127.0.0.1:8000 app:app-w 4表示使用 4 个 worker 进程,app:app指app.py文件中的app对象。 - 配置 Nginx 反向代理:
- 安装 Nginx。
- 编辑 Nginx 站点配置,将域名请求代理到 Gunicorn 的
127.0.0.1:8000。 - 配置 Nginx 处理静态文件(
/static/路径),减轻 Flask 负担。 - 配置 SSL 证书启用 HTTPS。
9.3 功能扩展建议
- 用户认证:使用
Flask-Login添加简单的登录功能,区分公开图库和私人上传。 - 分页:当图片数量很多时,在图库页面添加分页功能。
- 缩略图生成:上传时使用 Pillow 自动生成统一尺寸的缩略图,用于图库列表展示,提升加载速度。
- 标签系统:将
tags字段拆分为单独的表,实现多对多关系,方便按标签精确筛选。 - RESTful API:为前端(如 Vue/React)提供数据接口,实现前后端分离。
- 自动获取元数据:尝试从文件名或通过某些图片信息 API 自动填充角色、作品等信息。
通过这个项目,你不仅搭建了一个可用的个人图站,更实践了 Flask Web 开发的全流程,包括路由、数据库、表单、文件上传、模板渲染和基础前端。你可以在此基础上不断迭代,打造一个完全符合自己需求的二次元内容收藏与展示中心。