Giter Club home page Giter Club logo

fabu.love's Introduction

typora-copy-images-to
./screenshots

爱发布

demo地址: https://fabu.apppills.com/ 该平台是类似于fir.im/蒲公英类似的一个平台.可以自己部署.

项目前后端分离开发:

前端使用 vue + element-ui

后端使用 nodejs + koa

Artboard

项目结构

.
├── LICENSE
├── README.md
├── client //web端代码 vue + element UI
├── docker  //使用docker部署的配置文件
├── fabu_nginx.conf  //server端nginx配置文件
├── screenshots  //屏幕截图
├── server  //服务端代码node+koa
└── wiki //todo 还在编写中

运行步骤

使用docker运行(建议)

ps:请先安装docker

  1. 下载源码 git clone https://github.com/HeadingMobile/fabu.love.git
  2. 执行cd docker
  3. 执行docker-compose up -d --build
  4. 打开浏览器 http://0.0.0.0:9898

本地运行

运行前准备

  • 安装 MongoDB (3.6)
  • 安装 Nodejs
  • 安装 pm2、babel-node
npm install -g pm2 babel-cli
  • 安装 cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org

1.clone 下载代码 git clone https://github.com/HeadingMobile/LoveFabu.git

2.运行server端

#进入项目根目录
cd server
cnpm install  #安装依赖
npm start

=============>>out
...
...
App is listening on 9898.
数据库连接成功
=============>>end

3.编译运行前端页面

cd client
cnpm install
npm run build #正式环境可以用该命令编译静态文件交给nginx
npm run dev  #本地运行可以使用该命令

============>>out
...
...
 DONE  Compiled successfully in 18546ms                                                
 I  Your application is running here: http://0.0.0.0:9898
============>>end

4.使用浏览器打开进入http://localhost:9898即可进入应用

项目配置说明

前端配置

无需配置

后端配置

参见 server/config.js

//需要修改配置可以修改config.js文件,也可以在部署的时候导出环境变量
//比如 export FABU_BASE_URL=https://127.0.0.1:9898

const common = {
    //baseUrl应用请求的url地址,比如https://fabu.love
    baseUrl: process.env.FABU_BASE_URL || "https://127.0.0.1:9898", 
    port: process.env.FABU_PORT || "9898", //server运行的端口
    apiPrefix: 'api',
    fileDir: process.env.FABU_UPLOAD_DIR || path.join(__dirname, ".."), //上传文件的存放目录
    secret: process.env.FABU_SECRET || "secretsecret", //secret
    //数据库用户 (没有开启mongodb用户认证的可以不填写)
    dbUser: process.env.FABU_DBUSER || undefined,  
    //数据库密码 (没有开启mongodb用户认证的可以不填写)
    dbPass: process.env.FABU_DBPWD || undefined,  
    dbName: process.env.FABU_DB_NAME || "fabulove", //数据库名称
    dbHost: process.env.FABU_DB_HOST || "localhost", //数据库地址
    dbPort: process.env.FABU_DB_PORT || "27017", //数据库端口
	
    //邮件相关配置 用于找回密码和邀请团队成员发送邮件
    emailService: process.env.FABU_EMAIL_SERVICE || "qq", 
    emailUser: process.env.FABU_EMAIL_USER || "", 
    emailPass: process.env.FABU_EMAIL_PASS || "",

    //是否允许用户注册,为否则后端注册接口不可用
    allowRegister: process.env.FABU_ALLOW_REGISTER || true, 

    //是否开启ldap 默认是false 如果公司没有ldap服务可以不用理会
    openLdap: process.env.FABU_ALLOW_LDAP || false, 
    ldapServer: process.env.FABU_LDAP_URL || "",  //ldap server url
    ldapUserDn: process.env.FABU_LDAP_USERDN || "", //ldap管理员dn 管理员用户名
    ldapBindCredentials: process.env.FABU_LDAP_CREDENTIALS || "", //ldap管理员密码
    ldapBase: process.env.FABU_LDAP_BASE || "" //ldap base

};

正式环境部署 nginx配置(注意请使用https部署,否则iOS会出现无法安装的问题)

可以按照项目根目录的 fabu_nginx.conf 文件进行配置

server{
  listen 80;
  server_name fabu.love;

  #root目录为项目根目录的client/dist目录下,前端静态页面
  root /home/ubuntu/fabulove/client/dist;
  index index.html;

  location / {
      try_files $uri $uri/ @router;
      index index.html;
  }

  location /upload/ {
      #该root目录为根目录下config.json文件里dir目录 上传的apk和ipa文件当作静态文件处理
      root /home/ubuntu/fabulove/upload;
      expires  30d;
  }

  location @router {  # vue的router配置
      rewrite ^.*$ /index.html last;
  }

  location /api/ {  #把以api打头的接口转发给后端server
    proxy_pass http://127.0.0.1:9898; #这里端口修改为后端服务运行的端口
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
  client_max_body_size 208M; #最大上传的ipa/apk文件大小
}

fabu.love's People

Contributors

agassiyzh avatar bellchet58 avatar cave- avatar darren-chenchen avatar dependabot[bot] avatar headingapp avatar realzzz1874 avatar wenzhenxi avatar zakiso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fabu.love's Issues

头像css优化建议

获得光标事件头像出现1px的位移
image
添加默认边框占位
.headernav-wrapper .rightWrapper .userwrapper {
display: inline-block;
height: 100%;
border-top: solid 1px #fff;
border-left: solid 1px #fff;
border-right: solid 1px #fff;
}

不同系统下上传apk解析iconPath路径错误

Mac:
9E91F723595D392DCBDEAD29AD5F31EC
Ubuntu16.04:
8192588D4A10EBDDF87D5A7AB9F69497

用的是同个文件apk,但application-icon-xxx解析到的值不一样。并且在Ubuntu下解析到的application-icon的路径实际并不存在,导致写入icon失败,最后导致了最后上传apk失败。而在Mac上则是正常上传。

所用的apk:
所用的apk

是否能提供合并应用功能

大多数应用都是安卓和IOS都有的,发布的时候也希望是安卓和IOS是同一个链接,看是否能提供下这方面的处理

Api接口调用

API调用的时候提示token没有 但是调用的参数中没有token字段啊请问再哪里设置的

设置版本灰度功能怎么使用?

我使用https://fabu.love/ 进行测试.
上传了两个版本. 两个版本都已经上线了.
设置其中一个为灰度版本, 限制ip访问, ip为我的外网ip. 但是没有作用. 网页链接上看到的总是比较大的版本. 请问此处的灰度版本应该如何测试? 如何理解.

api查看应用installUrl不带域名

上传应用的第一个版本1.2.0,installUrl如下图所示:
_20181112151642

上传应用新版本第二个版本,installUrl如下图所示:
_20181112152102

两个url一个带域名,一个不带域名,这样如果通过api获得下载地址,用这个下载地址下载app就会有问题

admin

你好,是否有管理员账号,如果关闭用户注册之后,怎么添加用户,ths

Build failed with errors.

Building server
Step 1/12 : FROM node:10.15.3
---> 64c810caf95a
Step 2/12 : RUN npm install -g babel-cli && npm install -g cnpm --registry=https://registry.npm.taobao.org
---> Using cache
---> be848f9f71c6
Step 3/12 : RUN mkdir -p /opt/data /opt/server /opt/web /opt/logs /var/cache/nginx/client_temp
---> Using cache
---> c1e20bc933ec
Step 4/12 : WORKDIR /opt/client
---> Using cache
---> 759ac0796d6c
Step 5/12 : ADD client /opt/client
---> Using cache
---> a2874a07a76f
Step 6/12 : RUN cnpm install
---> Using cache
---> 9cd22f0ca0db
Step 7/12 : RUN npm run build
---> Running in 5ec748f7ac87

[email protected] build /opt/client
node build/build.js

Hash: 489452285d9b5e369e46
Version: webpack 3.12.0
Time: 25699ms
Asset Size Chunks Chunk Names
static/js/3.d64badf3d6d1e280eeb2.js 22.5 kB 3 [emitted]
static/img/bg_picture.07f3585.png 279 kB [emitted] [big]
static/fonts/icomoon.d37bb3e.woff 12.9 kB [emitted]
static/fonts/icomoon.f0ddd02.eot 13 kB [emitted]
static/fonts/icomoon.aa27446.ttf 12.9 kB [emitted]
static/img/icomoon.754976f.svg 43.5 kB [emitted]
static/img/empty_app.576448a.png 15.6 kB [emitted]
static/img/ic_mobilphone.0bb8e79.png 127 kB [emitted]
static/img/box.43c604b.png 19.9 kB [emitted]
static/js/0.8b9db10eba034829d62d.js 1.61 kB 0 [emitted] vendor-async
static/js/1.9ccbee3f5983cb2114aa.js 25.8 kB 1, 8 [emitted]
static/js/2.596cebe6f2329203d471.js 39.6 kB 2 [emitted]
static/fonts/element-icons.6f0a763.ttf 11 kB [emitted]
static/js/4.2ec3ed405f6c72e56cc4.js 11.5 kB 4 [emitted]
static/js/5.3193cce99343c4169899.js 14.7 kB 5 [emitted]
static/js/6.2f77f61d496a8f7dbfdc.js 12.3 kB 6 [emitted]
static/js/7.c6e625d37fa62526e7ce.js 4.67 kB 7 [emitted]
static/js/8.9b7d731ef3bf1bc53a16.js 10.8 kB 8 [emitted]
static/js/9.b7fcd0a7668ff920f91e.js 205 bytes 9 [emitted]
static/js/vendor.563f3792d9a8030bae16.js 868 kB 10 [emitted] [big] vendor
static/js/app.784393e0f6d3168d6050.js 8.15 kB 11 [emitted] app
static/js/manifest.0ac94c2ed02821498f8e.js 1.63 kB 12 [emitted] manifest
static/css/app.3dfd2904b9e89665f80a84555ab68696.css 253 kB 11 [emitted] [big] app
index.html 765 bytes [emitted]

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue
Module not found: Error: Can't resolve '../../api/moudle/miniApi' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue 51:0-52
@ ./src/components/miniApplication/miniAppDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppList.vue
Module not found: Error: Can't resolve '../../api/moudle/miniApi' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppList.vue 47:0-52
@ ./src/components/miniApplication/miniAppList.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/qrCode.vue
Module not found: Error: Can't resolve '../../api/moudle/miniApi' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/qrCode.vue 37:0-52
@ ./src/components/miniApplication/qrCode.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue
@ ./src/components/miniApplication/miniAppDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetailHeader.vue
Module not found: Error: Can't resolve '../../api/moudle/miniApi' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetailHeader.vue 28:0-52
@ ./src/components/miniApplication/miniAppDetailHeader.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue
@ ./src/components/miniApplication/miniAppDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/auth/auth.vue
Module not found: Error: Can't resolve '../../common/js/utils' in '/opt/client/src/components/auth'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/auth/auth.vue 92:0-42
@ ./src/components/auth/auth.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/personalInfo.vue
Module not found: Error: Can't resolve '../../common/js/utils' in '/opt/client/src/components/user'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/personalInfo.vue 23:0-42
@ ./src/components/user/personalInfo.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userInfo.vue
@ ./src/components/user/userInfo.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/editorVersion.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/editorVersion.vue 54:0-48
@ ./src/components/appDetail/editorVersion.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appVersions.vue
@ ./src/components/appDetail/appVersions.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appVersions.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appVersions.vue 118:0-48
@ ./src/components/appDetail/appVersions.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appSetting.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appSetting.vue 29:0-48
@ ./src/components/appDetail/appSetting.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/graySetting.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/graySetting.vue 62:0-48
@ ./src/components/appDetail/graySetting.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appVersions.vue
@ ./src/components/appDetail/appVersions.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue 28:0-48
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetailHeader.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appDetail'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetailHeader.vue 41:0-48
@ ./src/components/appDetail/appDetailHeader.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appDetail/appDetail.vue
@ ./src/components/appDetail/appDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appList/appList.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/appList'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/appList/appList.vue 53:0-48
@ ./src/components/appList/appList.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/auth/auth.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/auth'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/auth/auth.vue 91:0-49
@ ./src/components/auth/auth.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/main/headerNav.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/main'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/main/headerNav.vue 55:0-106
@ ./src/components/main/headerNav.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/main/main.vue
@ ./src/components/main/main.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue 52:0-48
@ ./src/components/miniApplication/miniAppDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppList.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppList.vue 49:0-48
@ ./src/components/miniApplication/miniAppList.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetailHeader.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/miniApplication'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetailHeader.vue 29:0-48
@ ./src/components/miniApplication/miniAppDetailHeader.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/miniApplication/miniAppDetail.vue
@ ./src/components/miniApplication/miniAppDetail.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/team/teamMgr.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/team'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/team/teamMgr.vue 85:0-44
@ ./src/components/team/teamMgr.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/team/teamItem.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/team'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/team/teamItem.vue 21:0-44
@ ./src/components/team/teamItem.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/team/teamMgr.vue
@ ./src/components/team/teamMgr.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/changePassword.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/user'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/changePassword.vue 25:0-51
@ ./src/components/user/changePassword.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userInfo.vue
@ ./src/components/user/userInfo.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userMessage.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/user'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userMessage.vue 42:0-48
@ ./src/components/user/userMessage.vue
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/main/main.vue
@ ./src/components/main/main.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userInfo.vue
Module not found: Error: Can't resolve '../../mgr/userMgr' in '/opt/client/src/components/user'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/components/user/userInfo.vue 40:0-62
@ ./src/components/user/userInfo.vue
@ ./src/router/index.js
@ ./src/main.js

ERROR in ./src/api/basehttp.js
Module not found: Error: Can't resolve '../mgr/userMgr' in '/opt/client/src/api'
@ ./src/api/basehttp.js 5:0-48
@ ./src/main.js

ERROR in ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/App.vue
Module not found: Error: Can't resolve './mgr/userMgr' in '/opt/client/src'
@ ./node_modules/_babel-loader@7.1.5@babel-loader/lib!./node_modules/_vue-loader@13.7.3@vue-loader/lib/selector.js?type=script&index=0!./src/App.vue 9:0-44
@ ./src/App.vue
@ ./src/main.js

Build failed with errors.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: node build/build.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2019-04-20T08_27_35_133Z-debug.log
ERROR: Service 'server' failed to build: The command '/bin/sh -c npm run build' returned a non-zero code: 1

上传ipa报错 Callback must be a function

您好,
我在本地测试环境上传iOS 安装包ipa时报错,请问下是什么问题?

本机操作流程

  • mongoDB启动成功
  • server启动成功
  • client启动成功
  • 在本机登录 爱发布 成功,上传.ipa时报错.
  • .ipa 大小:9.8M
  • Demo fabu.love上提交是没问题的

本机环境:

macOS -v 10.13.4
db version v4.0.2
node -v v10.4.1
pm2 -v 3.1.2

报错信息:

Process API POST /api/apps/5b98d240574cf7230d86bc68/upload...
Process API error...
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
    at maybeCallback (fs.js:159:9)
    at Object.fs.exists (fs.js:237:3)
    at CertDownloader.pem (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@cert-downloader/index.js:96:18)
    at CertDownloader.verify (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@cert-downloader/index.js:131:11)
    at module.exports (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@provisioning/index.js:7:10)
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:731:23
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:673:13
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:230:13
    at _arrayEach (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:81:9)
    at _each (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:72:13)
    at async.forEachOf.async.eachOf (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:229:9)
    at _parallel (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:672:9)
    at Object.async.parallel (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@async/lib/async.js:687:9)
    at DecompressZip.<anonymous> (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@ipa-metadata/index.js:38:11)
    at DecompressZip.emit (events.js:182:13)
    at DecompressZip.EventEmitter.emit (domain.js:442:20)
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@decompress-zip/lib/decompress-zip.js:125:14
    at _fulfilled (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:854:54)
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:883:30
    at Promise.promise.promiseDispatch (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:816:13)
    at /Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:624:44
    at runSingle (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:137:13)
    at flush (/Users/leopardpan/Desktop/Tool/LoveFabu/server/node_modules/[email protected]@q/q.js:125:13)
    at process._tickCallback (internal/process/next_tick.js:61:11)
Process API GET /api/apps/5b98d240574cf7230d86bc68...

启动报错

npm start
Cannot find module 'C:\Users\rain\Desktop\fabu.love-master\server\node_modules_bcrypt@3.0.1@bcrypt\lib\binding\bcrypt_lib.node'

可以说一下数据库的详细配置吗

本地MAC环境以及云上CENTOS均上传报错,错误码:EACCES

console 错误信息如下,是有什么权限配置问题码?

{ Error: spawn EACCES
at ChildProcess.spawn (internal/child_process.js:330:11)
at exports.spawn (child_process.js:500:9)
at exports.execFile (child_process.js:210:15)
at parseApk (/Users/tan/Projects/fabu/server/library/apkparser/apkparser.js:19:10)
at Promise (/Users/tan/Projects/fabu/server/controllers/upload.js:277:9)
at new Promise ()
at parseApk (/Users/tan/Projects/fabu/server/controllers/upload.js:276:12)
at parseAppAndInsertToDB (/Users/tan/Projects/fabu/server/controllers/upload.js:116:22)
at upload (/Users/tan/Projects/fabu/server/controllers/upload.js:75:28)
at errno: 'EACCES', code: 'EACCES', syscall: 'spawn' }

docker安装时的错误

events.js:183
throw er; // Unhandled 'error' event
^

Error: listen EADDRINUSE :::9898
at Object._errnoException (util.js:1022:11)
at _exceptionWithHostPort (util.js:1044:20)
at Server.setupListenHandle [as _listen2] (net.js:1351:14)
at listenInCluster (net.js:1392:12)
at Server.listen (net.js:1476:7)
at Application.listen (/opt/server/node_modules/_koa@2.7.0@koa/lib/application.js:65:19)
at Object. (/opt/server/index.js:73:20)
at Module._compile (module.js:643:30)
at loader (/opt/server/node_modules/_babel-register@6.26.0@babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) [as .js] (/opt/server/node_modules/_babel-register@6.26.0@babel-register/lib/node.js:154:7)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
at Object. (/opt/server/node_modules/_babel-cli@6.26.0@babel-cli/lib/_babel-node.js:154:22)
at Module._compile (module.js:643:30)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
at startup (bootstrap_node.js:187:16)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: babel-node index.js
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2019-04-18T05_53_30_828Z-debug.log

实在搞不明白是什么原因了。有人知道吗?

做得非常好的项目,有几点疑问????

  1. 应用详情页显示的下载地址需要token才能访问?这个地址的意义是什么?
  2. 应用编辑里显示到下载页是什么意思,有什么作用
  3. 发布版本后,点击预览,希望下方可以显示历史版本,点击可以切换历史版本,这个非常重要
  4. 希望增加版本升级日志

上传错误:Callback must be a function

详细错误信息:
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
at maybeCallback (fs.js:127:9)
at Object.exists (fs.js:195:3)
at CertDownloader.pem (/root/fabu.love-master/server/node_modules/cert-downloader/index.js:96:18)
at CertDownloader.verify (/root/fabu.love-master/server/node_modules/cert-downloader/index.js:131:11)
at module.exports (/root/fabu.love-master/server/node_modules/provisioning/index.js:7:10)
at /root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:731:23
at /root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:673:13
at /root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:230:13
at _arrayEach (/root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:81:9)
at _each (/root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:72:13)
at async.forEachOf.async.eachOf (/root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:229:9)
at _parallel (/root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:672:9)
at Object.async.parallel (/root/fabu.love-master/server/node_modules/ipa-metadata/node_modules/async/lib/async.js:687:9)
at DecompressZip. (/root/fabu.love-master/server/node_modules/ipa-metadata/index.js:38:11)
at DecompressZip.emit (events.js:182:13)
at DecompressZip.EventEmitter.emit (domain.js:442:20)
at /root/fabu.love-master/server/node_modules/decompress-zip/lib/decompress-zip.js:125:14
at _fulfilled (/root/fabu.love-master/server/node_modules/q/q.js:854:54)
at /root/fabu.love-master/server/node_modules/q/q.js:883:30
at Promise.promise.promiseDispatch (/root/fabu.love-master/server/node_modules/q/q.js:816:13)
at /root/fabu.love-master/server/node_modules/q/q.js:624:44
at runSingle (/root/fabu.love-master/server/node_modules/q/q.js:137:13)

用docker启动,注册时报错

数据库提示连接成功,但是点击注册时候docker直接死掉,这是debug日志

0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ]
2 info using [email protected]
3 info using [email protected]
4 verbose run-script [ 'prestart', 'start', 'poststart' ]
5 info lifecycle [email protected]prestart: [email protected]
6 info lifecycle [email protected]
start: [email protected]
7 verbose lifecycle [email protected]start: unsafe-perm in lifecycle true
8 verbose lifecycle [email protected]
start: PATH: /usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/opt/server/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
9 verbose lifecycle [email protected]start: CWD: /opt/server
10 silly lifecycle [email protected]
start: Args: [ '-c', 'babel-node index.js' ]
11 info lifecycle [email protected]~start: Failed to exec start script
12 verbose stack Error: [email protected] start: babel-node index.js
12 verbose stack spawn ENOENT
12 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:48:18)
12 verbose stack at emitTwo (events.js:126:13)
12 verbose stack at ChildProcess.emit (events.js:214:7)
12 verbose stack at maybeClose (internal/child_process.js:925:16)
12 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)
13 verbose pkgid [email protected]
14 verbose cwd /opt/server
15 verbose Linux 3.10.0-957.el7.x86_64
16 verbose argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
17 verbose node v8.9.4
18 verbose npm v5.6.0
19 error file sh
20 error code ELIFECYCLE
21 error errno ENOENT
22 error syscall spawn
23 error [email protected] start: babel-node index.js
23 error spawn ENOENT
24 error Failed at the [email protected] start script.
24 error This is probably not a problem with npm. There is likely additional logging output above.
25 verbose exit [ 1, true ]

大佬感谢开源

顺便汇报个BUG,看很多人说ipa上传报错

Process API error...
{ Error: ENOENT: no such file or directory, rename 'xxxx.png' -> 'yyyy_i.png'
at Object.fs.renameSync (fs.js:766:18)
at extractIpaIcon (/root/git/LoveFabu/server/controllers/upload.js:263:18)
at
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
errno: -2,
code: 'ENOENT',
syscall: 'rename',
path: 'xxxx.png',
dest: 'yyyy.png' }

翻看upload.js 263行
await fs.renameSync(tmpOut, path.join(iconRelatePath, iconSuffix))
修改成
await fs.renameSync(tmpOut, path.join(uploadDir,iconRelatePath, iconSuffix))
即可解决问题,望测试修复

另:nginx配置文件中 upload的配置也建议优化
location /upload/ {
#该root目录为根目录下config.json文件里dir目录 上传的apk和ipa文件当作静态文件处理
root /home/ubuntu/fabulove/upload;
expires 30d;
}

如上app访问url https://xxx.com/upload/,
必须在/home/ubuntu/fabulove/upload下再ln -s 一个实际路径,
变成
/home/ubuntu/fabulove/upload/upload/
怪怪的,建议改成
root /home/ubuntu/fabulove/;

请教下gmail

错误信息如下:
{ Error: getaddrinfo ENOTFOUND gmail gmail:465
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:57:26)
errno: 'ENOTFOUND',
code: 'ECONNECTION',
syscall: 'getaddrinfo',
hostname: 'gmail',
host: 'gmail',
port: 465,
command: 'CONN' }

Unhandled rejection Error: invalid signature: 0xff8

上传包100%之后,报了如下错误:
Unhandled rejection Error: invalid signature: 0xff8 at /opt/server/node_modules/unzipper/lib/parse.js:62:26 at tryCatcher (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/promise.js:510:31) at Promise._settlePromise (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/promise.js:567:18) at Promise._settlePromiseCtx (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/promise.js:604:10) at Async._drainQueue (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/async.js:138:12) at Async._drainQueues (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/async.js:143:10) at Immediate.Async.drainQueues [as _onImmediate] (/opt/server/node_modules/unzipper/node_modules/bluebird/js/release/async.js:17:14) at runCallback (timers.js:705:18) at tryOnImmediate (timers.js:676:5) at processImmediate (timers.js:658:5) at process.topLevelDomainCallback (domain.js:120:23)

访问安卓下载页面白屏

机型:NokiaX6
浏览器:默认浏览器

预估是兼容问题,我下载uc以后可以正常打开,但是使用原生的就是白屏,控制台检查无错误信息输出

server npm install bcrypt failed

3671 verbose stack Error: [email protected] install: `node-pre-gyp install --fallback-to-build`
3671 verbose stack spawn ENOENT
3671 verbose stack     at ChildProcess.<anonymous> (/usr/share/npm/lib/utils/spawn.js:17:16)
3671 verbose stack     at emitTwo (events.js:87:13)
3671 verbose stack     at ChildProcess.emit (events.js:172:7)
3671 verbose stack     at maybeClose (internal/child_process.js:821:16)
3671 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
3672 verbose pkgid [email protected]
3673 verbose cwd /opt/fabu.love/server
3674 error Linux 4.4.0-127-generic
3675 error argv "/usr/bin/nodejs" "/usr/bin/npm" "install"
3676 error node v4.2.6
3677 error npm  v3.5.2
3678 error file sh
3679 error code ELIFECYCLE
3680 error errno ENOENT
3681 error syscall spawn
3682 error [email protected] install: `node-pre-gyp install --fallback-to-build`
3682 error spawn ENOENT
3683 error Failed at the [email protected] install script 'node-pre-gyp install --fallback-to-build'.
3683 error Make sure you have the latest version of node.js and npm installed.
3683 error If you do, this is most likely a problem with the bcrypt package,
3683 error not with npm itself.
3683 error Tell the author that this fails on your system:
3683 error     node-pre-gyp install --fallback-to-build
3683 error You can get information on how to open an issue for this project with:
3683 error     npm bugs bcrypt
3683 error Or if that isn't available, you can get their info via:
3683 error     npm owner ls bcrypt
3683 error There is likely additional logging output above.
3684 verbose exit [ 1, true ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.