V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
robinshen
V2EX  ›  程序员

一个人(公司摸鱼+业余时间)开发了五年的开源项目:可用于自建 Git 服务,自带看板和 CI/CD,可替代 GitHub/GitLab(功能级的替代,而非小而美)

  robinshen · 187 天前 · 10964 次点击
这是一个创建于 187 天前的主题,其中的信息可能已经有所发展或是发生改变。

前两天发了一个版本更新的贴,没啥关注。腆着脸再发一个,详细介绍下这个项目的背景、特点、和相关技术栈。希望众 V 友轻喷。🙏

项目地址: https://github.com/theonedev/onedev

项目背景

在一家公司做 DevOps 相关工作,若干年前为了解决我们自己的痛点,开发了这个产品内部使用,饱受好评,我也就继续维护这个产品。行业的关系,公司难有大发展,但也倒不了,所以氛围宽松,基本上只要自己负责的那摊事不出问题,没人管你干什么。感谢公司对我摸鱼的宽容,做这个产品很开心,因为没有产品经理,没有业绩压力,不用处理无效需求,感觉每行代码都在让产品变得更好。也感谢来自客户的持续反馈,让我不至于空中楼阁鬼画符。

相比 GitHub/GitLab 有什么特点?

开箱即用的符号跳转

我们内部的一个需求是代码 Review 或者在线看代码时,要能够方便跳转到符号定义:

symbol.gif

这个功能使用 ANTLR 分析主流语言的语法,并提取符号定义进行增量存储,速度快,占用空间小。目前支持 Java, JavaScript, C, C++, CSharp, Go, PHP, Python, CSS, SCSS, LESS and R 。GitHub 前两年加入了这个功能,但是好像只是针对主分支; GitLab 需要在 CI 里做 LSIF 相关配置,并会占用大量空间。

静态分析结果直接标注在源码上,作为 Review 的辅助信息

annotation.png

当然 GitHub 有很多第三方工具可以做这个事情,但发现的问题都是显示在各个产品自己的网站上,与 Code Review 流程割裂开来了(比如说我们可以直接对某个代码风格问题加 Review 的相关说明等等)。另外这些第三方工具一般都需要额外收费。

Issue 字段和状态可定制,以及和 CI/CD 的深度集成

这里 GitHub/GitLab 的简单的 Open/Close 的状态完全不能满足我们的需求,特别是牵涉到客户创建的 Issue 时,比如说如果开发人员在 Commit 相关代码时 Close 相关 Issue ,客户得到通知会认为这个问题已经解决,会问应该更新到哪个发行版本;而如果在产品发布时 Close 相关 Issue ,测试人员在拿到测试版时也会困扰,因为相关 Issue 还是 Open 状态,不知道应该测试哪些 Issue 。为解决这个问题,我们定制了四个 Issue 状态:Open ,Committed ,Test Ready 和 Released 。当开发人员 Commit 代码时,相关 Issue 自动迁移到 Committed 状态;当包含这些 Commit 的代码被构建并部署到测试环境中时,相关 Issue 自动迁移到 Test Ready 状态,并通知 QA ,QA 可以在 Issue 的详情页面里了解部署到了哪个测试环境;当测试通过代码发布时,相关 Issue 自动迁移到 Released 状态,并通知客户,客户在 Issue 的详情页里可以得知关联的发行版。

custom-field.png


fixing-build.png

强大易用的 Commit/Issue/Build/Pull Request 查询语言

这个也是基于 ANTLR 做的,对语法规则进行预测来实现自动提示。这样无需学习语法就可以直接进行复杂查询,比如下面是我们客户经常做的事情:在升级前查询当前版本和最新版本之前都有哪些改动:

changes.gif

或者查询所有分配给我的高优先级的 Issue ,在指定的两个发行版之间改动了某个文件的所有 Commit 等等。查询可以保存并订阅,这样符合相关条件的事件发生时可以及时得到通知。

全功能的 CI/CD ,无需了解 Yaml 语法,上手非常简单

CI/CD 是花精力最多的部分了,虽然 CI/CD 的定义也是以 Yaml 文件的方式存储在仓库中,但提供了 UI 来生成该文件,用户无需了解任何相关语法即可进行配置

job-command.gif

而且在 Commit 页面可以直接运行 CI/CD 任务,使得 GitOps 来的更直观。灵活可定制的 CI/CD 选项页面让非开发人员也可以很容易的进行部署。

build-option.gif

部署一个用于构建的集群及其方便,只需一个 helm 命令就可以部署到 Kubernetes 中,将每个构建任务作为 Pod 运行,同时支持 Windows 和 Linux ;在没有 Kubernetes 的环境中,一行 docker 命令即可启动一个构建的 Agent ,而且 Agent 免于维护,自动升级。V 友们可以试试 GitLab 的构建集群配置,相对而言还是比较麻烦的。

摒弃 Organization ,将项目以树形结构组织以方便设置的继承

自从 GitHub 使用 Organization 后,似乎所有类似的软件都采用这种方式来组织项目了。这种方式对于面向公共服务的云平台而言可能比较合适,但对于公司内部使用感觉没有太大必要,而且还会带来很多麻烦,比如 GitLab 在 Group 级提供 Epic 功能,而在 Project 级提供 Issue 功能,但很多用户要求这两个功能能同时在 Group 级和 Project 级提供等等。我们的做法是将项目以树形结构组织,下级项目可以自动继承上级项目的设置,也可以按需复写。这使得大量项目的设置维护非常容易维护。

随时对代码进行标注和讨论,而不用依赖于 Pull Request

在浏览源码或者 Diff 时,可以对任意代码块即时发起讨论。讨论的内容将作为代码文档的一部分(即使代码改动甚至更名),方便其他人事后对代码进行阅读和理解。不同于其他的 Git 工具,代码 Comment 在侧边显示,避免割裂代码上下文,影响阅读。

file-comment.gif

另外每处讨论形成单独的 Topic ,使相关的人很容易知道哪里有新的改动或回复。

threaded-comments.png

资源占用相比 GitLab 小很多,速度快

个人使用的话,一台 1 核 2G 的机器足够了。比 Gitea/Gogs 的资源占用还是多的,不过如果 Gitea/Gogs 要做类似功能,受限于 Golang 的生态,可能要启动一些其他语言写的微服务(比如各种 Language Server ,Elastic Search 等),最终资源消耗一定不会小。

还有一个优点就是主服务可以运行在 Linux ,Mac ,Windows ,FreeBSD 等多平台上,可以使用内置文件数据库,也可以充分利用公司现有资源连接到 MySql/MariaDB/PostgreSQL/Oracle/SQL Server 等外置数据库。

技术栈

不够时髦,甚至有点羞于启齿,从头到脚 Java 一把撸(之前被一些 V 友喷用 Java 不够云原生😊)。不分前后端,所有的功能在一个 Maven 项目中( 40 万行代码左右)。使用 Wicket (估计很少人听说)直接把界面交互和后端逻辑封装在一个组件中,大部分配置界面通过 Annotation 自动生成。依赖注射和插件体系基于 Guice 。在 Eclipse 中启动项目大概耗时 20 秒,不过大部分时间热部署,改动代码后直接刷新页面就可以看到改动。

感谢 V 友们支持🙏

第 1 条附言  ·  186 天前

再贴两个我们也经常用的功能

对仓库进行实时符号搜索: symbol-search 对仓库进行正则表达式搜索: regex-search

虽然 IDE 也可以做这些事情,但是我们经常需要切换到以前的 commit 搜索(比如某个 Issue 对应的 Commit ),这在 IDE 里需要切换工作环境有点麻烦,不如直接打开 onedev 搜索方便

仓库代码使用 Lucene 分词,正则表达式本身先进行分词进行粗略查询,然后在结果里再进行精确匹配来提高速度。google code search 也采用类似方式: https://swtch.com/~rsc/regexp/regexp4.html

GitLab 好像一直没有做这个功能,也许是考虑到服务器负载问题。

第 2 条附言  ·  186 天前
有兴趣尝试的 V 友点这个五分钟教程(创建 react demo app ,并运行 CI ):
https://zhuanlan.zhihu.com/p/103410072
第 3 条附言  ·  186 天前
内存配置可以通过 conf/wrapper.conf 里修改,可以将 wrapper.java.maxmemory.percent=60 修改为 wrapper.java.maxmemory=512 (项目不大也可以改成 256 ),这样 JVM 和 git 总共消耗不会超过 1G ,对于一般的项目都足够了。
140 条回复    2022-05-17 09:18:29 +08:00
1  2  
Goooler
    1
Goooler  
   187 天前 via Android
太强了
yuan101010
    2
yuan101010  
   187 天前
respect
zuston
    3
zuston  
   187 天前 via iPhone
必须 star
adoal
    4
adoal  
   187 天前
做基础设施开发,厉害
coolrc
    5
coolrc  
   187 天前 via iPhone
👍
robinshen
    6
robinshen  
OP
   187 天前
感谢感谢 🙏
enchilada2020
    7
enchilada2020  
   187 天前 via Android
靠 我没脸再做 Dev 了 膝盖拿去 star 走你
giiiiiithub
    8
giiiiiithub  
   187 天前
牛逼
admpubcom
    9
admpubcom  
   187 天前 via iPhone
很强大,要是 golang 写的就好了
Yother
    10
Yother  
   187 天前 via Android
顶🔝🔝🔝。
jaywhen
    11
jaywhen  
   187 天前
大佬太谦虚了
robinshen
    12
robinshen  
OP
   187 天前
@admpubcom 当初也考虑过 golang ,但生态还是缺乏了些,比如没有好的语法分析工具,全文档索引工具,以及组件化的前段开发等等,现在情况可能有所改观,但也尾大难掉了,😂
cs419
    13
cs419  
   187 天前
看这英文文档 在外企么上班么
EPr2hh6LADQWqRVH
    14
EPr2hh6LADQWqRVH  
   187 天前   ❤️ 5
厉害了,这个直接拿出来找投资就行,贴个国产化标签,比前两天隔壁贴发的那个不知道强到哪里去了。

敢问贵司是哪家,这时间和人力投入,不一般
robinshen
    15
robinshen  
OP
   187 天前
@cs419 算是吧
MAGA2022
    16
MAGA2022  
   187 天前
太强了
robinshen
    17
robinshen  
OP
   187 天前
@avastms 目前比较喜欢这种状态,哪天公司把我干掉了再说吧。
admpubcom
    18
admpubcom  
   187 天前 via iPhone
@robinshen 有没有考虑加入订阅制仓库功能?类似于 github 新出的赞助商仓库功能。就是按照年或月支付订阅费后才能查看仓库里的代码😄
EPr2hh6LADQWqRVH
    19
EPr2hh6LADQWqRVH  
   187 天前
好像是 ThoughtWorks 难怪了
robinshen
    20
robinshen  
OP
   187 天前
@admpubcom 那个就不考虑了。MIT license ,包括全套开发环境搭建,希望为国内开源做点贡献。
robinshen
    21
robinshen  
OP
   187 天前
@avastms 并不是哦,这个就别挖了,保留点隐私,🙏
duke807
    22
duke807  
   187 天前 via Android
不知道有沒有類似 gerrit 的項目自動掃描功能:在指定存放 git 庫的目錄下,可以直接拷貝一些 bare git 庫進來,也可以改名和移動已存在的 git 庫,支持多級目錄,然後啟動或重啟 gerrit 的時候,所有的 git 庫的項目就建好了,可以通過 web 和 ssh 訪問了。對於有很多庫的公司來說比較方便,不然要一個一個添加,對於 android 系統這樣的源碼來說不敢想像。
robinshen
    23
robinshen  
OP
   187 天前
@duke807 这个暂时没有,可以通过下面链接创建相关需求:
https://code.onedev.io/projects/160/issues?query=%22Project%22+is+%22onedev/server%22
或者有任何疑问,也欢迎创建 support request
ericguo
    24
ericguo  
   187 天前   ❤️ 1
@avastms 确实 onedev 应该是目前相对最能替代 gitlab 的,佩服作者。

正好最近因为工作原因花了一个月系统的读了一下 gitlab 的文档和源码,说一下我的个人看法,

https://gitlab.cn/pricing/self-managed/feature-comparison/

首先可以看到现在即使是 github 也很难和 gitlab 拼功能了,gitlab 毕竟是 160 亿美刀市值的独立上市公司,每天的主仓库递交就起码上百,一个人都看不完一天的所有递交。。

https://about.gitlab.com/direction/#3-year-direction-video

另外它的方向现在是全流程,不单单是 CI/CD ,看板,当然 ondev 占用资源少于 gitlab 是真的,gitlab 至少要 4G 的机器,顺便更正一下,gitlab epic 现在也是支持继承的。

总的来说作为 Rails 程序员,我肯定还是选 Gitlab ,如果是 Java 程序员,可能选 onedev 是个不错的选择。
skiy
    25
skiy  
   187 天前
@avastms 其实都应该支持。中国基础软件太薄弱了,有团队、个人这么推动基础设施,我们都应该鼓励。

onedev 早就在 v2 看到过了,后来看到隔壁那个。我当时也想在回复的时候说这款的,但是感觉借人家楼不太礼貌。
Goooler
    26
Goooler  
   186 天前 via Android
要是能重构成 kotlin 就好了
robinshen
    27
robinshen  
OP
   186 天前
@ericguo 感谢这么细致的分析。GitLab 的一个问题是盈利压力太大,导致一直快速的开发新功能以吸引增量用户。对现有 Bug 的修改(比如 Runner 不太稳定,Build 莫名失败等)并不是很上心,功能做的也比较粗糙。而 OneDev 更强调稳定,目前已经修复所有已知的 bug ,要么不增加功能,要增加就做完善。还是相信这个市场需要多元的产品来满足不同需求的用户。
robinshen
    28
robinshen  
OP
   186 天前
@Goooler 这个实际上意义不太大,无非就是语法糖而已,不会有本质的改变。
haoliang
    29
haoliang  
   186 天前
这个项目从 12 年开始到现在 10 年时间;我的天哪,贵公司十年如一日地分配时间给这个项目,而且开发者长期一两个人
robinshen
    30
robinshen  
OP
   186 天前   ❤️ 2
@haoliang 17 年之前实际上都是公司内部开发,之后开源。开发者实际上就我一个人(不同时期不同的 id 而已)。公司谈不上分配时间给这个项目,大家上班都摸鱼,我摸鱼的方式是撸代码而已。
ericguo
    31
ericguo  
   186 天前
@robinshen 我只能说这个市场太卷了。。。可怕。。Gitlab 其实也是很值得尊敬的公司,它之前是默认开源所有公司资料的公司,另外其实它也很早就意识到了可能后面功能太多的问题:

https://about.gitlab.com/handbook/product/product-principles/#our-product-principles

Prioritize relentlessly. It is better to do a few things well than many things poorly.

太卷了,我只能说太卷了。。。
Goooler
    32
Goooler  
   186 天前
@robinshen 效率高太多了,真的很舒服
robinshen
    33
robinshen  
OP
   186 天前
@Goooler 嗯,有空研究下,谢谢建议。
haoliang
    34
haoliang  
   186 天前   ❤️ 2
让人感慨啊,时间在 OP 这里好像慢下来了,还有些岁月静好的感觉
robinshen
    35
robinshen  
OP
   186 天前
@ericguo 不用想着去盈利,就不会有卷的压力。当然前提是没有生存压力。
LittleControl
    36
LittleControl  
   186 天前
respect
miv
    37
miv  
   186 天前 via Android
@robinshen 太感谢了,mit 好评,谢谢大佬贡献
xingzhi
    38
xingzhi  
   186 天前
很强大,谢谢 lz 。
有一个疑惑,这个是公司内部项目,公司允许开源了吗,会不会有所有权问题。
不确定目前 theonedev 的主体是公司还是您个人?
robinshen
    39
robinshen  
OP
   186 天前
@xingzhi 说公司内部项目其实不太准确,应该是我个人项目,只是之前开发了在公司内部使用而已。否则怎么是摸鱼呢?
robinshen
    40
robinshen  
OP
   186 天前
愿意尝试的 v 友,可以看这里的五分钟教程:
https://zhuanlan.zhihu.com/p/103410072?
msg7086
    41
msg7086  
   186 天前
@xingzhi 打开帖子前我也有这个疑问。
@robinshen 在公司业务范围内催生出的项目,利用在公司的时间,使用公司的设备开发和维护,自然其所有权都是归公司所有的。
不太清楚你有没有和法务沟通过,或者公司有没有明确告诉你这个项目可以开源,否则那就是擅自公开公司机密,《侵犯商业秘密罪》了解一下。
如果公司明确同意的,那当然是没有问题的。项目做得这么好,要是在法务上翻车,那就太不值了。
wangxn
    42
wangxn  
   186 天前
其实楼主提到的那些功能都是小节,一般人都是和本地副本打交道,reviewer 还是少数。
最重要的是架构。比如分布式同步(跨国团队),横向扩展(几十 G 乃至几百 G 、几十万 commit 的大项目)啥的。
这是 GitHub Enterprise 做得比 GitLab 好的地方,而且我们公司在用的时候还发生了各种问题。
robinshen
    43
robinshen  
OP
   186 天前
@msg7086 多谢提醒,这些问题没有解决好,是不会冒风险开源的。
levinit
    44
levinit  
   186 天前 via iPhone
@robinshen 假如 我是说假如 有一天你不干这个公司的工作 这个产品可能被公司拿去 或者一部分权利被拿去 参考 nginx 的纠纷
37Y37
    45
37Y37  
   186 天前 via Android
太强了!同做 devops ,相比之下我写的都是玩具
robinshen
    46
robinshen  
OP
   186 天前
@wangxn 很多小团队没有那么高的并发需求。Review 我们还是用的很多的,另外最方便的地方还是 Issue ,Commit 和 Build 的无缝整合,真的省了很多麻烦。

其实对于很多大的 git 项目,onedev 即使在单机情况下也能处理的很好,比如在 demo 机上的 linux 仓库( 60 万 commit ,机器配置 2 核 8G ):
https://code.onedev.io/projects/29 ,大家可以试试看跟 GitLab 的性能比较
robinshen
    47
robinshen  
OP
   186 天前
@37Y37 其实都是真实需求驱动,没有这些,也只能做 GitHub/GitLab 的像素级 copy
robinshen
    48
robinshen  
OP
   186 天前
@wangxn 另外如果哪一天需要分布式的话,也完全可以做。只是刚开始就搞没有太大意义。GitLab 可能需要好几台机器搞分布式才能应付的场景,对 OneDev 一个单机就够了。
FranzKafka95
    49
FranzKafka95  
   186 天前 via Android
厉害呀,膜拜大佬
dreampet
    50
dreampet  
   186 天前
后续有没有考虑支持 LDAP 认证功能?
vHypnos
    51
vHypnos  
   186 天前 via iPhone
真正的大佬,🧎‍♂️
robinshen
    52
robinshen  
OP
   186 天前
@dreampet LDAP 已经支持了,也支持 OpenID 单点登录。众多琐碎的功能比如分支保护、通过 commit 历史自动推荐 reviewer 、通过邮件创建 issue 、自定义 issue 关联等等没有在帖子里提及。
lazyyz
    54
lazyyz  
   186 天前 via Android
真·大佬,已 Star ,马上搭建试试
bthulu
    55
bthulu  
   186 天前
@wangxn 有几百 G 的大项目吗, 莫不是用 git 来存取小姐姐?
0xfan
    56
0xfan  
   186 天前
强👍🏻,也真羡慕这样的公司氛围
cocong
    57
cocong  
   186 天前
MIT 协议,怕是很难赚到钱,只能说外企牛逼。
ZeroDu
    58
ZeroDu  
   186 天前
要是来个中文适配就很好了。国际化嘛,多种语言必备
nicebird
    59
nicebird  
   186 天前
牛啊
JamesChen
    60
JamesChen  
   186 天前   ❤️ 16
我看到你这开源项目很是感动,国内开源大环境乌烟瘴气,不少人都习惯了抄袭 /套皮 /做快餐式开源,我很久没见过有个人开源项目能做得这么专业+UI 也这么专业+持之以恒,不弃坑,不做快餐。
老哥的开源项目可贵,但你的开源精神其实更是难得,真得是给广大国内做开源的人树立了个好榜样,必须支持下。
dreampet
    61
dreampet  
   186 天前
@robinshen 不错,安排一个虚拟机部署测试下, 我们的版本库规模比较大( 20~30GB ),不知道性能如何
robinshen
    62
robinshen  
OP
   186 天前
@JamesChen 感谢认可 🙏 。
robinshen
    63
robinshen  
OP
   186 天前
@dreampet 这么大规模的还没有测试过。有啥问题可通过 Issues 反馈。
keppelfei
    64
keppelfei  
   186 天前
respect
blu10ph
    65
blu10ph  
   186 天前
很棒的项目!~
agileago
    66
agileago  
   186 天前
@robinshen 和 coding 相比呢? 感觉做的功能差不多,一个人对一个团队,厉害了
code4you
    67
code4you  
   186 天前
喜欢 UI +1
robinshen
    68
robinshen  
OP
   186 天前
@agileago coding 不太了解,知道的人可以说说对应的 feature
agileago
    69
agileago  
   186 天前
https://coding.net/ 仔细看了,和 coding 做的有一部分重合 这是他的演示项目,https://devops.coding.net/p/qmall 你这个确实可以取代内部 gitlab ,真棒
NoString
    70
NoString  
   186 天前
已 Start 雀氏牛逼
gowinder
    71
gowinder  
   186 天前
厉害了,肯定不容易
robinshen
    72
robinshen  
OP
   186 天前   ❤️ 2
再贴两个我们也经常用的功能

对仓库进行实时符号搜索:
https://raw.githubusercontent.com/wiki/theonedev/onedev/features/search-symbol.gif
对仓库进行正则表达式搜索:
https://raw.githubusercontent.com/wiki/theonedev/onedev/features/regex-search.gif

虽然 IDE 也可以做这些事情,但是我们经常需要切换到以前的 commit 搜索(比如某个 Issue 对应的 Commit ),这在 IDE 里需要切换工作环境有点麻烦,不如直接打开 onedev 搜索方便

仓库代码使用 Lucene 分词,正则表达式本身先进行分词进行粗略查询,然后在结果里再进行精确匹配来提高速度。google code search 也采用类似方式:
https://swtch.com/~rsc/regexp/regexp4.html

GitLab 好像一直没有做这个功能,也许是考虑到服务器负载问题。
Tom7
    73
Tom7  
   186 天前
大佬接受我的膝盖已 Start ,java 太不容易了,要会前后端,还要会运维。java 生态全面,要求也是最多的
offswitch
    74
offswitch  
   186 天前
能把 build 放到 github 上吗? ondev 上下载速度太慢了,而且还不支持恢复。
henryhu
    75
henryhu  
   186 天前
佩服了,被感动到了,都是我的榜样
aitaii
    76
aitaii  
   186 天前 via Android
很棒,感谢
robinshen
    77
robinshen  
OP
   186 天前
@offswitch 可能是网络原因吧,我这边很快就下完了。或者也可以考虑运行 docker 命令部署:
docker run --name onedev --rm -v /var/run/docker.sock:/var/run/docker.sock -v $(pwd)/onedev:/opt/onedev -p 6610:6610 -p 6611:6611 1dev/server
weishu
    78
weishu  
   186 天前
牛,支持!
robinshen
    79
robinshen  
OP
   186 天前
richardwong
    80
richardwong  
   186 天前
respect
ericgui
    81
ericgui  
   186 天前   ❤️ 2
为了你这个项目的健康发展,我建议你不要再提“公司摸鱼”,你在上班时间或者用公司的资源(电脑,网络等)开发出来的东西,知识产权属于公司
robinshen
    82
robinshen  
OP
   186 天前
@ericgui 感谢提醒 🙏
wowawesome
    83
wowawesome  
   186 天前
NB
d5
    84
d5  
   186 天前
这也太牛了👍
ShuoHui
    85
ShuoHui  
   186 天前 via iPhone
GitHub 用的是有点痛苦,试试看,先膜拜大神…
oyx
    86
oyx  
   186 天前
已 Start 期待大佬适配中文文档
aaronly
    87
aaronly  
   186 天前
有没有捐赠渠道?
robinshen
    88
robinshen  
OP
   186 天前
@aaronly 非常感谢,暂时还不需要哈,有机会能够使用并通过 issues 提供反馈就是最大的帮助了。看到这多 V 友的鼓励也是很感动。认认真真做事情大家还是认可的。💪
FightPig
    89
FightPig  
   186 天前
这个厉害了,
fe619742721
    90
fe619742721  
   186 天前
40 万行代码,太强了
i0error
    91
i0error  
   186 天前
NB
Natsume233
    92
Natsume233  
   186 天前
已 Start ,🐮🍺
Jaosn
    93
Jaosn  
   186 天前
nb
romisanic
    94
romisanic  
   186 天前
OP 实在是太强了 请收下我的膝盖和 star !
buruoyanyang
    95
buruoyanyang  
   186 天前
respect
pakro888
    96
pakro888  
   186 天前
太强了,收下我的膝盖
hjosama200
    97
hjosama200  
   186 天前
大佬牛逼哇,国产之光!
learningman
    98
learningman  
   186 天前
看了下前端感觉完成度很高,请问是自己设计的吗?有的时候写一些个人项目界面总是弄得很丑
robinshen
    99
robinshen  
OP
   186 天前
@learningman 买了 bootstrap 的模版,然后界面布局自己设计。
Jtyczc
    100
Jtyczc  
   186 天前
niubi
1  2  
关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2097 人在线   最高记录 5497   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 35ms · UTC 16:26 · PVG 00:26 · LAX 09:26 · JFK 12:26
Developed with CodeLauncher
♥ Do have faith in what you're doing.