在这篇帖子中 Wilsons 佬提出了非数据库内容的视图呈现,也就是将数据库与视图分开看待。这种理念可以进一步延拓为为对笔记结构编码与筛选呈现的解耦,可以说触及了笔记管理的底层机理。本文尝试对此进行一些简单分析,从广义的属性 + 视图的概念出发考察笔记管理的通用逻辑。需要说明的是,这篇文章更多局限在工具层级讨论,旨在统一理解各种笔记管理手段,并不涉及上层的笔记方法与笔记理念,想看后者可以参考本人介绍卡片笔记法的文章。
怎样管理笔记,为什么要管理笔记?笔记是为了应对遗忘,将内容记录下来以后,将来大脑中找不到的东西,在笔记中就有可能找到。除记录以外,检索就是笔记的核心需求。
引言:笔记管理是为了增强可筛选性
各种笔记管理方法都是为了增强笔记的定向筛选能力,在进一步分析前有必要先考虑这样一件事:能否不依靠定向筛选做到检索呢?
针对特定目标笔记的检索方法大概分为几类:
- 全局搜索
- 定向筛选
- AI,启动
这篇文章分析了为什么不能只靠全局搜索作为笔记检索方法。只要笔记数量足够多,检索特定笔记时的噪声就会远高于信号。更糟的是,即便对同样一份事物的理解也会随时间发生变化,现在使用的术语可能与过去不同,从而导致检索失效。归根结底,将内容从大脑转录到笔记中固然降低了需要记住的东西,但搜索仍会将目标信息的记忆压力加诸使用者,且搜索行为本身也很难加深对笔记的印象。
这篇文章分析了为什么不能指望用人工智能取代笔记整理。这其实很容易理解,大模型本质上仍然是复读机,输出质量取决于输入质量。如果笔记库本来就有规整的体系清晰的结构,引入 AI 当然能锦上添花提供可靠助力;但是如果笔记本身就是一团混沌,那么就算用 AI 在史山淘金,提炼的内容也还是要靠人工进行检验,不做管理省下来的时间还是得填回去。良好的笔记管理与 AI 下游应用是相辅相成的。
除了搜索和 AI 以外,剩下的笔记检索方法基本可以称为筛选,也就是首先让笔记变得互不相同,然后根据这种区分性来过滤出想要找的笔记。本文使用广义的【属性】和【视图】两个概念名词描述笔记的筛选要素与筛选方式。属性指代建立筛选要素,视图指代呈现筛选结果。
广义属性与视图
在笔记管理中通过增加差异化信息提升笔记可筛选性并不是很陌生的行为,它有一个通俗说法叫做分类。即便完全不了解分类的人也知道使用文件夹划分信息,只要把同类笔记放在同一个文件夹内,就能通过打开文件夹汇总这类笔记,同时过滤掉其他非同类笔记。而将视角从文件夹转移到笔记本身来看,划定文件夹其实等价于为笔记赋予【所属文件夹】的信息属性,打开文件夹则等价于对这一信息属性进行一次筛选过滤。只是因为操作上会先建立文件夹,再在其中添加笔记,使得分类是在给笔记添加差异化信息这一点并不明显。各种分类方式无非是用不同手段增加笔记的信息属性作为可筛选要素。
分类是建立属性空间
文档树、标签、双链、数据库等各种分类手段在更高层级视角上是一回事,也就是为被分类的笔记添加特定信息属性,使其与其他笔记可区分:
| 分类手段 | 信息属性 | 分类方式 | 筛选汇总方式 |
|---|---|---|---|
| 文档树 | 上层文档 | 同类文档放在同一文档下层 | 展开文档执行汇总,其他文档被过滤 |
| 标签 | 标签 | 同类笔记具有同一标签 | 搜索标签执行汇总,其他笔记被过滤 |
| 双链 | 块引用 | 同类笔记引用同一个块 | 打开反链执行汇总,其他笔记被过滤 |
| 数据库 | 数据库 | 同类笔记绑定同一个数据库 | 找到数据库执行汇总,其他笔记被过滤 |
笔记具有的可以与其他笔记形成区分的元信息都可以抽象成笔记的信息属性,比如文件夹就是最常见的信息属性实现方式或者说分类方式。不同分类方式可以理解为信息属性的不同实现维度,而笔记系统的所有属性维度就共同组成了笔记的属性空间。分类就是在为笔记建立属性空间,自上而下管理是先有属性维度再写入笔记,自下而上管理则是先写入笔记再绑定属性维度。
各种属性维度在筛选便捷性上可能有差异,但本质其实一致,所以任何分类手段都是不应该被神话的。有的软件鼓吹自己抛弃了文件夹,纯靠标签大发神威;有的软件鼓吹自己抛弃了标签,纯靠双链大发神威;有的软件鼓吹自己把标签和双链结合,有的软件鼓吹自己把标签和数据库结合,这些都是值得被肯定的创新,但绝不至于上升到“下一代笔记软件”这种面向股市的说法。归根结底,【建立筛选要素-呈现筛选结果】的检索框架没有变化,不同属性维度相互具备可替代性非常正常,各种改进工作某种程度上仍属于工具细节打磨。
建立属性空间让笔记有了筛选的可能,接下来就要考虑怎样基于属性空间检索目标笔记。
视图是建立筛选呈现
对笔记进行筛选后的结果呈现可以抽象成广义上的视图,文档树的文档子层就是“子文档视图”,搜索面板查询标签就是“标签列表视图”,反链面板就是“反链卡片视图”,数据库自身带有表格视图和卡片视图。任何信息属性维度在定义时都会给出伴生的呈现方法,也就是前文表格列举的筛选汇总方式。
思源底层的万物皆为 JSON 对象,所以在更加广泛的含义上,各种功能也可以理解为从对象键值建立各种呈现视图。例如日记文档有 dailynote开头的自定义属性,而块属性也是一种信息属性维度,由此得到了日记文档这一分类,各种插件就可以基于此维度筛选出日记文档,并用文档流、日历面板等形式呈现。
虽然每种信息属性都自带原生呈现视图,但属性与视图分别负责笔记的信息界定与筛选呈现,两者并不一定要相互锁死。参考本文开头提到的数据库字段与画廊视图的拆分,笔记的整个属性空间与各种呈现视图也是可以解耦的,即通过查询从属性空间检索指定笔记,再将查询结果以某种视图呈现表达,实现任意的属性到视图的映射。此即基于广义的属性(Attribute)和视图(View)组成的笔记管理方法,可以称为 AV 工作流。
属性、视图解耦,查询作为接口。
基于查询从属性空间映射到视图空间
思源具备原生的 SQL 与 API 查询,Query View 插件则对查询结果的呈现方式提供了一次扩展,由此为灵活的信息属性查询筛选与视图呈现提供了可能。与原生呈现视图相比,自定义属性视图映射是对自定义笔记筛选规则的特化呈现。以下给出一些简单示例。
- 反链面板以外的双链层级呈现
思源的双链没有文档树、标签体系的树状结构呈现,原生关系图谱缺乏筛选手段稍显混乱。定义【若 a 使用动态锚文本引用 b,则 a 父块视为 b 的子级】,那么就相当于用双链定义了【上级块】的信息属性,由此使用 Query View 插件对上级块递归查询就可以得到反链层级“列表视图”:
同样是树状结构,列表视图某种意义上比看板还更灵活。
- 文档树以外的两级文档呈现
在文档树里一层层展开折叠查看同层子层文档较为繁琐,使用 Query View 插件对当前文档的同层和子层进行查询就可以得到两级文档“列表视图”:

理论上还可以进一步编写交互组件,在单个嵌入块内就能点击切换文档层级,这样相当于复刻了二级文档树。
- 标签搜索以外的标签呈现
上面的例子没有做可点击控件是因为本人比较菜,对 Query View 插件开发较为浅薄。插件作者给出过标签查询示例,就可以通过点击查询标签:

以上示例表明,在有了属性空间后,各种信息属性并不局限于依赖原生呈现视图进行检索,而可以用查询将筛选结果映射到自定义的呈现视图。建立分类时使用文档树、标签、双链哪种具体方式不重要,重要的是想清楚未来怎样对分类去做筛选,而这需要从一开始就明确笔记的区分规则。只要区分规则足够明确,筛选规则就能写得非常简单,至于最后呈现为何种视图就非常自由,并不影响对目标笔记的检索罗列。
理想情境下的 AV 工作流包含统一的属性空间和多样的视图空间,所有筛选要素都能归结为块级信息属性,所有筛选规则都能表现为对信息属性的查询处理。然而思源在这里有一组相对独立的信息属性维度与呈现视图,也就是数据库这个狭义的属性视图功能。换句话说,思源的属性空间分为块级信息属性、数据库字段两个独立部分,呈现视图分为数据库、嵌入块(及其升级版)两个独立部分。幸运的是查询 API 与动态数据库能将数据库与其他信息属性打通,不幸的是这种映射写起来尤为复杂。天杀的模板语法。
如果将未绑定块的主键视为一种特殊块类型“虚空块”,类似于将没有正文的标签视为一种特殊的反链文档,那么数据库功能理论上只需要新开发字段视图,而字段属性可以视为对原本块对象键值属性的修补。这样不会有现在的割裂情境,可谓皆大欢喜。遗憾的是 Notion 出的太早把大家带偏了。
数据库查询映射
如果秉持属性、视图解耦的理念,思源数据库功能应该分为字段属性和字段视图两部分,数据库本体提供了从字段属性到字段视图的映射。这种映射与基于查询的映射可以统一,实现广义属性与视图的大一统。
与基于块信息的管理方式不同,基于数据库进行管理会从数据库出发,把很多信息记录在数据库字段里。此时从数据库字段属性映射到查询视图可以在数据库以外灵活运用这些信息。个人认为这么做意义不大,因为数据库本身就(将会)具有很好的筛选能力,想在其他数据库调用也可以使用关联列和模板列,模板字段是支持筛选的,关联汇总字段也迟早支持筛选;想在数据库外部查看字段的最简单方法就是将主键绑定到块上,然后字段属性就成为块信息回归到广义信息属性上了。如果想通过查询提取字段属性内容,可以参考 Wilsons 佬的简单查询,或者本人以前的帖子里用的 Query View 插件 + 思源 API 查询。
比起数据库字段到非数据库视图的映射,或许非数据库信息属性到数据库视图的映射更有实用意义。如果说标签等其他信息属性具备的是【属性维度-属性值】的二级结构,由多个属性维度共同组成属性空间,那么单个数据库本身便具有【属性空间(数据库)-属性维度(字段列)-属性值(字段值)】的三级结构。从其他信息属性映射到数据库呈现时,既可以基于查询生成动态数据库,又可以基于模板列生成数据库字段。
这里提供一个从双链信息属性映射到数据库字段呈现的示例。块 @1a子层使用动态锚文本引用块 @1,那么对块 @1建立 SuperRef 或动态数据库就能汇总反链 @1a作为主键。接下来不是在数据库内编辑字段内容,而是在块 @1a子层引用块 attr1定义信息属性维度并使用含 ::的引用锚文本 [[::待插图]]定义属性值,那么可以用模板列提取属性值,实现属性查询汇总呈现:
代码参见本文附录。使用动态数据库和模板列可以让数据库聚合全局信息属性,自动获取文档数据,随后就能用数据库视图的筛选与呈现完成进一步过滤处理,配合卡片视图假装成底部反链都不在话下。求天求地不如求己,没有全局属性就用双链兜底
为什么要花很大力气把所有的属性空间与视图空间打通?将笔记管理做成类似前后端分离的架构其实还是为了提升可检索性,属性空间尽可能统一、视图空间尽可能丰富,就是尽可能减少筛选要素维护成本,增加筛选结果呈现手段,一份数据多样表达,彻底统一自下而上与自上而下管理。
以上是在【建立筛选要素-呈现筛选结果】的检索框架下,将各种笔记管理方式统一抽象为信息属性的构建与过滤,组成广义属性与视图的笔记管理工作流。不同分类手段虽然都有为笔记增添差异化信息的共性,但又各自存在擅长的用法领域。想要在统一的属性视图工作流中对这些分类手段取长补短,需要重新来观察各种信息属性的具体特性。
重新审视各种信息属性
容器唯一的文件夹
文件夹可能是最贴合物理现实的笔记管理方式,任何笔记的【所属文件夹】属性都具备唯一性,笔记的本体在文档树里只存在唯一定位路径。很多新生代笔记软件对此大加抨击,真实信息的复杂性不可能用单独一套 MECE 分类方法完美对号入座,认为应该尽可能淡化甚至完全优化掉文件夹管理体系。那么,这种检索路径唯一性有没有可能存在实用意义呢?有没有哪种信息在类型上是可以确定处理成非此即彼的?
一个简单例子是内容来源的内生性还是外生性,一份内容是出自自身思考分析还是外部摘录引用。如果笔记里有剪藏文章,那么剪藏完整的内容文字量会非常大,很容易在搜索查找过往想法时产生干扰。思源原生的全局搜索可以指定文档树路径,由此提供了相当简单的筛选剪枝,所以在思源笔记中将手写的内容如日记和剪藏粘贴的文档分笔记本放置是非常合适的,能将定向筛选与全局搜索结合得非常好。
此外,文件夹管理还有一个优势在于很容易整理归档。思源的笔记本可以被整个关闭,从而将用不到的笔记推出视野并提升软件性能。除了直接关闭外还可以基于路径配置忽略索引、忽略搜索,这都是文件夹结构路径唯一衍生的用法。
文件夹代表着文件本位的管理方法。除了文件结构外,文件名本身其实也是一种信息属性。这篇文章分析了怎样基于笔记标题编码实现分类,本人文章也有过相关分析。基于文件夹与文件的管理手段处处透着唯一性,这种唯一性虽然在分类上有些局限,但也意味着筛选手段相对简单。如果笔记检索难度并不高,文档树 + 原生搜索或许已经够用,【内容的位置】就是唯一需要的筛选要素。
多路多层的标签
标签体系可以说是仅次于文件夹体系的成熟管理手段。先进笔记标签体系基本都具备两个特性:
- 多重筛选
与文件夹这种一维信息属性不同,一份笔记可以绑定多个标签建立正交信息属性维度,沿不同方面筛选检索。例如,从状态出发可以绑定 #待整理,从领域出发可以绑定 #原子物理,从功能出发可以绑定 #资料,并进一步实现联合筛选,由此让笔记可以从各种角度都能被找到,或者在不想找到的时候也能提供更多的可过滤要素。
与其让每样东西都有位置,不如让它们同时出现在多个地方。 ——《万物皆无序》
- 层级继承
本文用信息属性称呼笔记的可筛选要素,一种信息属性应具备不同属性值使笔记可区分。一份笔记可以组合多种信息属性,一种信息属性可以筛选出多份笔记。在面向对象的理念中除了组合的概念还有继承的概念,那么笔记管理中是否存在这种继承概念?
继承源自信息属性的层级结构,具备子层信息属性的笔记等同视为具备其上层信息属性。反过来,从基于信息属性筛选的视角看,子层信息属性绑定的笔记也等同视为被上层信息属性绑定。文档树路径存在层级结构,具备子层路径的笔记同样具备其上层路径,对上层路径执行筛选时会同样影响其子层路径;多级标签存在层级结构,具备子级标签的笔记同样能用上级标签搜索(结尾不加 #),对上级标签执行过滤时能一同排除掉其子层标签。这种信息复用可以大幅度降低构建筛选要素时的工作量,不必像组合信息属性的用法那样一次绑定一堆,筛选过滤时也能有效提高检索效率。
以上讨论的是信息属性的层级结构,那么笔记本身是否具有层级结构?进一步的,笔记本身能否作为信息属性?这是双向链接最有魅力的特性。
属性自指的双链
在所有信息属性维度里,双向链接都是最为特殊的那个。其他分类方式都是为笔记的本体附加上各种外部信息属性,比如给文档附加所属文件夹,给内容块附加标签、块属性、数据库,无论如何都要在笔记以外新建一套管理体系,再在这个管理体系上再下功夫;只有双链完全凭依于笔记本身,块引用就是通过【将笔记绑定笔记】实现【将笔记绑定信息属性】,笔记的信息属性直接指向笔记自身而非外部系统。
双链体系的属性自指未必是绝对优点,因为这意味着除了笔记本身以外的一切管理都要自主设计一套笔记体系,怎样表达内容传递关系?怎样表达内容分类状态?怎样表达索引导航?怎样表达内容复用?怎样区分以上用法?在其他分类手段里普通而又理所当然的实现方式在双链体系里都要自行做好约定,虽然操作起来非常自由,但缺少权威背书的情境下,自下而上搭建笔记架构总会让人不那么安心。如果连记的笔记有什么使用目的都很难搞清楚,想在使用过程中根据自身情况调整笔记工作流就更加强人所难了。
本人肯定没有资格为双链用法背书,这里姑且简单介绍个人用法情况。采用只含动态锚文本引用的块表示将其上层块传递到被引块,描述内容从属关系;采用 #开头的文档命名表示该文档用作块引绑定的信息属性,如引用 [[#待整理]]表示内容待整理;采用 @开头的文档命名表示该文档用作 MOC 索引文档,前文的反链层级查询即为示例;采用含 ::的引用锚文本表示属性值和引用语义描述,如对 [[#待整理]]的引用写成静态锚文本 [[::待插图]],表示当前绑定“待整理”笔记的子级状态为“待插图”。以上所有用法都能用反链过滤面板插件实现筛选,也可以直接用 Query View 插件固化呈现。
块引用定义了笔记间关联的存在性,但链接本身不含语义,所以上文对链接功能进行了一些形式化规范处理。另一方面,虽然块引用本身没有描述关联原因,但其上下文会为链接本身提供更多信息,可以说链接与链接上下文是在互相补全,这也是双链将笔记本身作为信息属性的一种体现。甚至即便不去手动绑定块引关联,也可以由虚拟引用自动为内容增添筛选要素,且具备一定可控性。
前述分析均基于通过【将笔记绑定笔记】实现【将笔记绑定信息属性】,也就是将出链笔记视为待筛选内容,被引笔记视为某种信息属性。实际上这种汇总视角可以翻转过来,通过【将笔记绑定笔记】实现【将信息属性绑定笔记】,在表示信息属性的笔记里引用内容笔记,让后者的反链成为其属性面板。这样操作的缺点在于没法在一份笔记里完成信息属性关联,优点在于作为信息属性呈现面板的反链可以不在乎排列顺序,而更在乎顺序的正文可以手工组织。
以上各种分类手段形式上各有差异,本质上又都能视为对笔记信息属性的构建与筛选呈现。而最原汁原味体现这种理念的属性视图,肯定还得是数据库功能。
终结属性视图的数据库
与双链代表的完全归于内容本身的管理方式相反,数据库在某种程度上是完全基于元数据的管理手段。笔记绑定的数据库以角标形式非侵入式显示,像文档树一样完全不会对正文内容产生影响。某种意义上,数据库与数据库外的内容位于两个世界。也许这就是数据库让人感觉折腾的原因。
数据库作为属性视图一体化的存在,同时兼顾了信息属性的构筑、筛选、呈现。前述基于查询映射得到的呈现视图普遍只能以只读形式呈现,嵌入块、模板列都不方便直接修改本体,更难以在筛选中直接变更信息属性值;而数据库字段可以直接在数据库块或属性面板中实时修改,还能用单选列和多选列预设字段属性可用值,在元数据的层级上已经相当易用。
一个数据库本身代表着一份相对完整的属性空间,各种字段属性即为属性空间内的不同维度,每个维度可以设置不同取值。那么如果用到超过一个数据库,怎样在其他数据库调用字段属性?前文提到可以用关联汇总列或模板列调用字段属性。例如,在数据库 A 中新建关联列关联到数据库 B 的主键,那么基于这个关联列新建的汇总列就可以获取数据库 B 条目的其他字段属性并呈现其原值。虽然关联列不能直接绑定到主键以外的字段,但汇总列能弥补相关用法。
关联列的问题在于需要手动绑定主键,导致其用起来并不优于直接在单数据库内处理内容。考虑到关联列代表【从一个数据库提取若干条目后再组织其字段属性】,这个功能进一步发展得到的其实是属性视图的层级继承或者说“子级视图”,比如 Issue 11088 就想让关联汇总列发挥视图筛选功能,通过筛选自动汇总代替手工绑定主键来获取条目。其实【通过查询自动获取条目】已经可以用动态数据库实现了,有了条目后也可以用数据库模板列进一步获取其他字段属性。只是数据库查询 + 模板列语法的代码复杂性导致这套流程用在数据库上有点过于折腾了,总不能说数据库能终结属性视图的主要原因是模板语法太难写了()
其他软件的属性空间
提到数据库功能创新,让人印象深刻的可能是 Tana 提出的 SuperTag 的理念。这个功能名称上叫标签,不过它是在【将若干属性维度组成一个属性空间】,本质上其实是可继承的数据库,除了概念营销很难说有什么新东西,只能说提升了操作舒适性。
真正在底层设计上大有不同的其实是术语大神 Anytype,完全跳出了层级文件、关系型数据库等传统后端架构,而基于图数据库设计信息组织形式。本文语义中的笔记在 Anytype 中名为“对象”,本文的广义信息属性在 Anytype 中名为“关联”,本文的广义呈现视图在 Anytype 中名为“集合”和“集锦”,集合是根据指定规则筛选的汇总结果,集锦则是手动汇总结果。除了术语差异,Anytype 在广义属性视图的框架下做到了极致的统一,单论优雅程度可以冠名成笔记领域的超弦了。
即便 Anytype 底层设计如此完美,好像也没有颠覆笔记软件格局,毕竟笔记不是管理好信息就结束了,最后还是要反馈到现实工作才行。对于多数人而言可能在笔记里使用一些简单筛选要素就够用了,沉迷工具很容易把工具变成玩具,折腾半天一点现实任务都没推进。本文的 AV 工作流啰嗦了几千字,其实本质非常简单,找不到笔记就加信息,增加的信息想办法查出来,剩下的就是工具本身的设计与增强。
总结
本文将笔记检索视为建立筛选要素-呈现筛选结果的流程,从中提炼出笔记的信息属性与呈现视图两个广义概念,由此对各种笔记管理功能进行了统一考量。综合全文分析,可以认为思源笔记在属性空间的基础架构上已经非常完善,查询筛选的上限也非常高,最有改进意义的方面仍在于功能易用性。本文偏向工具层级讨论,因为不涉及具体笔记方法所以看起来可能有一些虚。各种分类手段既具有统一的属性视图本质,又各具特色,实际使用还是要根据自身需求能力和功能可用性自行适配。理念在方法之上、方法在工具之上,给需求以工具,而非给工具以需求。
附录
以下为文中提到的一些查询代码。
- 反链层级查询
参考此回帖。
- 两级文档查询
//!js
async function get_doc_children(doc_id) {
let doc_children = await Query.childDoc(doc_id);
let icons = doc_children.map(block => Query.Utils.docIcon(block));
doc_children = doc_children.addcols({ 'icon': icons });
return doc_children;
}
function generate_doc_display(doc_list, title) {
let doc_link_list = doc_list.map(item => item.icon + item.aslink);
debugger
doc_link_list = doc_link_list.join('\n\n');
return `
{{{row
${title}
${doc_link_list}
}}}
`;
}
const query = async () => {
let dv = Query.DataView(protyle, item, top);
const doc_id = dv.root_id;
const doc_children = await get_doc_children(doc_id);
const doc_path = await Query.sql(`select path from blocks where id='${doc_id}'`);
const parent_doc_id = ((path) => {
const parts = path.split('/').filter(Boolean);
return parts[parts.length - 2];
})(doc_path[0].path);
const parent_doc = await Query.sql(`select * from blocks where id='${parent_doc_id}'`);
const parent_doc_children = await get_doc_children(parent_doc_id);
const doc_children_display = generate_doc_display(doc_children, '子层文档:');
const parent_doc_children_display = generate_doc_display(parent_doc_children, '同层文档:');
const display_md = `
上层文档:${parent_doc[0].aslink}
---
{{{col
${parent_doc_children_display}
${doc_children_display}
}}}
`;
dv.addmd(display_md);
dv.render();
}
return query();
- 引用映射到数据库字段
动态数据库:
//!js
const block_id = '20250606010712-f0hhwgj';
const query = async () => {
const ans = await Query.sql(`
select parent_id from blocks where id in(
select block_id from refs
where def_block_id='${block_id}'
and markdown like '((${block_id} ''%'
)
;`);
return ans.pick('parent_id');
}
return query();
模板列:
.action{ $attr_block_id := "20250606010643-9dbp9ek" }
.action{ $blocks := querySpans "select * from spans where block_id in(select id from blocks where parent_id='?' ) and markdown like '((? %::%' " .id $attr_block_id }
.action{ if gt (len $blocks) 0 }
.action{ $text := (first $blocks).Content }
.action{ $splitResult := splitList "::" $text }
.action{ if gt (len $splitResult) 1 }
.action{ $ans := index $splitResult 1 }
.action{ $ans }
.action{ end }
.action{ end }




欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于