├── .all-contributorsrc ├── .gitignore ├── README.md ├── dataProcessing ├── Office_type_tree.xlsx ├── office.json ├── officeData.json └── position_json.py └── src ├── Dockerfile ├── cbdbweb ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── db.sqlite3 ├── frontend ├── build │ ├── build.js │ ├── check-versions.js │ ├── logo.png │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ └── webpack.prod.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ └── prod.env.js ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── src │ ├── App.vue │ ├── assets │ │ ├── devices.min.css │ │ ├── dynastyData.json │ │ ├── entryData.json │ │ ├── geodata_dev.json │ │ ├── lang │ │ │ ├── en.js │ │ │ └── zh-cmn-Hant.js │ │ ├── logo.png │ │ ├── officeData.json │ │ ├── relationData.json │ │ └── relationDataNetwork.json │ ├── components │ │ ├── README.md │ │ ├── global │ │ │ ├── nav-bottom.vue │ │ │ ├── nav-left.vue │ │ │ └── nav-top.vue │ │ ├── treeTable │ │ │ ├── tree-item.vue │ │ │ └── tree-table.vue │ │ ├── utility │ │ │ ├── import-place.vue │ │ │ ├── query-result.vue │ │ │ ├── select-entry.vue │ │ │ ├── select-office.vue │ │ │ ├── select-person.vue │ │ │ ├── select-place.vue │ │ │ ├── select-relation-network.vue │ │ │ ├── select-relationship.vue │ │ │ ├── show-source.vue │ │ │ ├── show-year.vue │ │ │ ├── utility-functions.js │ │ │ ├── view-selected.vue │ │ │ └── warning-text.vue │ │ └── views │ │ │ ├── home.vue │ │ │ ├── q-e-byEntry.vue │ │ │ ├── q-e-byOffice.vue │ │ │ ├── q-e-byPerson-test.vue │ │ │ ├── q-e-byPerson.vue │ │ │ ├── q-r-byAssociation.vue │ │ │ ├── q-r-byKinship.vue │ │ │ ├── q-r-byPlace.vue │ │ │ ├── q-r-bySocialNetwork.vue │ │ │ ├── q-r-twoPerson.vue │ │ │ └── sna.vue │ ├── main.js │ ├── router │ │ └── index.js │ └── store │ │ └── index.js └── static │ └── .gitkeep ├── manage.py └── requirements.txt /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "pleviumtan", 10 | "name": "Łøçꝁë Tân", 11 | "avatar_url": "https://avatars.githubusercontent.com/u/39882329?v=4", 12 | "profile": "https://github.com/pleviumtan", 13 | "contributions": [ 14 | "design", 15 | "code", 16 | "doc", 17 | "ideas" 18 | ] 19 | }, 20 | { 21 | "login": "CasewardBen", 22 | "name": "CasewardBen", 23 | "avatar_url": "https://avatars.githubusercontent.com/u/48239811?v=4", 24 | "profile": "https://github.com/CasewardBen", 25 | "contributions": [ 26 | "code", 27 | "data" 28 | ] 29 | }, 30 | { 31 | "login": "IceCodeNew", 32 | "name": "IceCodeNew", 33 | "avatar_url": "https://avatars.githubusercontent.com/u/32576256?v=4", 34 | "profile": "https://github.com/IceCodeNew", 35 | "contributions": [ 36 | "code", 37 | "infra", 38 | "maintenance" 39 | ] 40 | }, 41 | { 42 | "login": "zhangliyuan2013", 43 | "name": "zhangliyuan2013", 44 | "avatar_url": "https://avatars.githubusercontent.com/u/41323296?v=4", 45 | "profile": "https://github.com/zhangliyuan2013", 46 | "contributions": [ 47 | "code" 48 | ] 49 | }, 50 | { 51 | "login": "yuetieqi-meow", 52 | "name": "yuetieqi-meow", 53 | "avatar_url": "https://avatars.githubusercontent.com/u/44973544?v=4", 54 | "profile": "https://github.com/yuetieqi-meow", 55 | "contributions": [ 56 | "code" 57 | ] 58 | } 59 | ], 60 | "contributorsPerLine": 7, 61 | "projectName": "cbdb-online-query-app", 62 | "projectOwner": "cbdb-project", 63 | "repoType": "github", 64 | "repoHost": "https://github.com", 65 | "skipCi": true 66 | } 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /venv/ 3 | /src/cbdbweb/__pycache__/ 4 | /src/frontend/node_modules/ 5 | /src/frontend/dist/ 6 | /src/frontend/npm-debug.log* 7 | /src/frontend/yarn-debug.log* 8 | /src/frontend/yarn-error.log* 9 | *.zip 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | .babelrc 19 | .editorconfig 20 | .postcssrc.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧑‍🎓 User Guide/用户指南 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-) 4 | 5 | ### Quick Start in Local Server/在本地搭建服务器使用 6 | 📖[Quick start in local server/在本地搭建服务器使用](#qsdm) 7 | 8 | ### Guide for users/用户手册 9 | 📖[Guide for users/用户手册](https://github.com/yiruka114514/CBDBWebAppGuide/blob/master/CBDBWebGuide.pdf) 10 | 11 | ### API Document 12 | 📖[API Document/API文档](https://github.com/cbdb-project/cbdb-online-main-server/blob/develop/API.md) 13 | 14 | # 🧑‍🔧 Contributor Guide/开发指南 15 | ## ⚠️ Important Notice/重要提示 16 | ❌ Do not modify the master branch directly! Committing directly to the master branch will not trigger automatic deployment of code for CI/CD. 17 | ⭕️ Please create a new branch first and develop on the new branch. When development is complete, initiate a `Pull Request` to merge that branch onto the master branch. 18 | 19 | ❌ 请勿直接修改主分支!直接向主分支提交(`commit`)将不会触发持续集成自动部署代码。 20 | ⭕️ 请先新建一个分支,并在新建的分支上进行开发。开发完成后,发起 `Pull Request` 将该分支合并到主分支上。 21 | 22 | ## 📚 Project Structure/项目结构 23 | ``` 24 | cbdb-online-query-app/ 25 | ├── README.md 26 | ├── dataProcessing #Save codes and output of data processing. This directory is just for archive and has nothing to do with other parts. 27 | │   ├── Office_type_tree.xlsx 28 | │   ├── office.json 29 | │   ├── officeData.json 30 | │   └── position_json.py 31 | └── src #Core source code of this project. 32 | ├── cbdbweb #Backend 33 | ├── db.sqlite3 34 | ├── dockerfile 35 | ├── frontend # Frontend 36 | ├── manage.py #django dev-server entrance. See Backend > Running the server 37 | └── requirements.txt 38 | ``` 39 | ## 📕 Backend/后端 40 | ### Python Environment 41 | `3.6.x` 42 | 43 | ### Requirements/Python包依赖 44 | `Django ==3.0.8` 45 | `djangorestframework ==3.11.0` 46 | `mysqlclient ==2.0.1` 47 | `gunicorn==20.0.4` 48 | Please install above packages before running the server. 49 | 50 | ### 📚 Structure/结构 51 | ``` 52 | cbdbweb/ 53 | ├── __init__.py 54 | ├── asgi.py 55 | ├── settings.py 56 | ├── urls.py 57 | └── wsgi.py 58 | ``` 59 | 60 | ### Running the Server locally/在本地运行服务器 61 | 62 | ⚠️ If you just want to change the code of frontend, running the Webpack Dev Server is strongly recommanded. See [Quick start in local server/在本地搭建服务器使用](#qsdm) 63 | 64 | ⚠️ 如果你只是想修改前端代码,强烈建议运行 Webpack 的开发服务器。参见[Quick start in local server/在本地搭建服务器使用](#qsdm) 65 | 66 | #### Windows 67 | ``` 68 | cd src 69 | py manage.py runserver 70 | ``` 71 | 72 | #### MacOS 73 | ``` 74 | cd src 75 | python manage.py runserver 76 | ``` 77 | 78 | ## 📕 Frontend/前端 79 | ### 📚 Structure/结构 80 | 81 | ``` 82 | frontend/ 83 | ├── build #Settings for using webpack to bundle the project 84 | │   ├── build.js 85 | │   ├── check-versions.js 86 | │   ├── logo.png 87 | │   ├── utils.js 88 | │   ├── vue-loader.conf.js 89 | │   ├── webpack.base.conf.js 90 | │   ├── webpack.dev.conf.js 91 | │   └── webpack.prod.conf.js 92 | ├── config 93 | │   ├── dev.env.js 94 | │   ├── index.js 95 | │   └── prod.env.js 96 | ├── index.html 97 | ├── package-lock.json 98 | ├── package.json 99 | ├── postcss.config.js 100 | ├── src #Vue Project 101 | │   ├── App.vue 102 | │   ├── assets #Save resources like images, etc. 103 | │   ├── components #Save Vue components 104 | │   ├── main.js 105 | │   ├── router #Vue router 106 | │   └── store #Vuex 107 | └── static 108 | ``` 109 | 110 | ### Useful Commands/实用指令 111 | 112 | #### 🛠 Quick Start in Dev Mode/在本地快速搭建开发服务器 113 | ``` 114 | # go to the directory of FE first 115 | cd src/frontend 116 | 117 | # install dependencies 118 | npm install 119 | 120 | # equivalent to: npm run dev 121 | npm start 122 | ``` 123 | 124 | #### 🔧 Formatting Code/格式化代码 125 | ``` 126 | # go to the directory of FE first 127 | cd src/frontend 128 | 129 | # install dependencies 130 | npm install 131 | 132 | # install vue client globally. If it has already installed, skip this step. 133 | npm install -g @vue/cli 134 | 135 | # Formatting code 136 | npm run lint 137 | ``` 138 | 139 | #### 🔧 Other Commands/其他指令 140 | ``` 141 | #install dependencies 142 | npm install 143 | 144 | #server with hot reload at localhost:8080 145 | npm run dev 146 | 147 | #build for production with minification 148 | npm run build 149 | 150 | #build for production and view the bundle analyzer report 151 | npm run build --report 152 | ``` 153 | 154 | For a detailed explain on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 155 | 156 | ### Important Virables & Methods 157 | #### 目录 158 | * [query-result.vue](#query-result) 159 | * [select-entry.vue](#select-entry) 160 | #### src/components/utility/query-result.vue 161 | ##### 组件简介 162 | 用于展示各种查询的结果 163 | ##### Data 164 | * `currentPage`:`Number` 当前展示的页面,默认`1` 165 | * `startIdx`:`Number`从第几条记录开始向API请求结果,默认`0` 166 | * `offset`:`Number` 每页展示多少条记录,默认`100` 167 | * `isLoading`:`Bool` 是否正在加载,默认`false` 168 | * `selected`: `Array` 选中的记录 169 | ##### Methods 170 | * `onRowSelected(item,index,event)` 当一条记录被点击时触发,将被选中的记录加入 `selected` 中 171 | * `selectAllRows()` 选中所有的记录 172 | * `clearSelected()` 清除选中的所有记录 173 | * `exportData()` 对于选中的记录,生成导出文件,并下载到本地 174 | 175 | #### src/components/utility/select-entry.vue 176 | ##### 组件简介 177 | 用于查询入仕途径,并将其传递到父组件中 178 | ##### Data 179 | * `result`:`Object` 用于维护查询结果。有下列成员: 180 | * `query`:`String` 查询式的主体部分,用于向API发送请求 181 | * `start`:结果开始笔数,用于向API发送请求 182 | * `end`:结果结束笔数,用于向API发送请求 183 | * `total`:总共有多少笔结果,,用于向API发送请求 184 | * `formData`: `Object` 用于记录检索参数,生成查询式。有下列成员: 185 | * `eName`:`String` 入仕途径名 186 | * `accurate`:`Number` 是否采用精确匹配,是=1,否=0。 187 | * 📝关于上述两个成员,请参考 [API文档](https://github.com/cbdb-project/cbdb-online-main-server/blob/develop/API.md) 以获得更多资讯。 188 | * `treeDataSource`:`Object` 可折叠树状UI的数据,以`json`格式保存。(未来计划改成异步加载,提高页面渲染效率) 189 | * `fields`:`Array` 用于维护表格中的列名及是否可选等属性 190 | * `items`:`Array` 用于维护表格中API返回的结果记录 191 | * `selectedEntry`:`Array` 用于维护选中的记录 192 | * 📝关于上述两个成员,请参考 [BootstrapVue文档](https://bootstrap-vue.org/docs/components/table) 以获得更多资讯。 193 | 194 | ##### Methods 195 | * `close()` 点选关闭按钮时执行,清空`selectedEntry`关闭当前组件 196 | * `selectAllRows()` 🔗[参见此处](#select-all-rows) 197 | * `clearSelected()` 🔗[参见此处](#clear-selected) 198 | * `onRowSelected(items)` 当一条记录被点击时触发,将被选中的记录加入 `selectedEntry` 中 199 | * `onClearTable()` 清空结果记录 200 | * `haveSelected()` 当点击“选择”按钮时执行,将选中的结果同步到父组件,清空`selectedEntry`关闭当前组件 201 | * `handlerExpand(m:{Id:String, isExpand:Bool})` 当树状UI点击时触发,切换类目的展开/收起。`m`为被点击的类目。`m.Id`为类目的Id,用于 API 查询等。 202 | * `handleTableScroll()` 处理滚动加载,划到底层时向 API 继续请求结果 203 | * `find()` 用于按关键词查询入仕途径。 204 | 205 | ##### Watch 206 | `show` 当变量 `show:Bool` 的值为 `true` 时,监听键鼠滚动。 207 | 208 | #### src/components/utility/select-office.vue 209 | WIP 210 | 211 | ## Contributors ✨ 212 | 213 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 |

Łøçꝁë Tân

🎨 💻 📖 🤔

CasewardBen

💻 🔣

IceCodeNew

💻 🚇 🚧

zhangliyuan2013

💻

yuetieqi-meow

💻
227 | 228 | 229 | 230 | 231 | 232 | 233 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! -------------------------------------------------------------------------------- /dataProcessing/Office_type_tree.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/dataProcessing/Office_type_tree.xlsx -------------------------------------------------------------------------------- /dataProcessing/officeData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": 1, 4 | "ObjectName": "唐朝", 5 | "children": [ 6 | { 7 | "Id": 2, 8 | "ObjectName": "帝后制度类", 9 | "children": [ 10 | { 11 | "Id": 2, 12 | "ObjectName": "帝后门", 13 | "children":[ 14 | { 15 | "Id":14, 16 | "ObjectName":"内命妇" 17 | } 18 | ] 19 | } 20 | } 21 | ] 22 | }, 23 | { 24 | "Id": 16, 25 | "ObjectName":"辽朝", 26 | "children":[] 27 | }, 28 | { 29 | "Id": 17, 30 | "ObjectName":"元朝", 31 | "children":[] 32 | }, 33 | { 34 | "Id": 18, 35 | "ObjectName":"明朝", 36 | "children":[ 37 | { 38 | "Id": 18, 39 | "ObjectName":"明朝", 40 | "children":[ 41 | { 42 | "Id": 18, 43 | "ObjectName":"明朝", 44 | "children":[] 45 | } 46 | ] 47 | } 48 | ] 49 | }, 50 | { 51 | "Id": 19, 52 | "ObjectName":"清朝", 53 | "children":[] 54 | } 55 | ] 56 | -------------------------------------------------------------------------------- /dataProcessing/position_json.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import json 3 | import xlrd 4 | 5 | name="ObjectName" 6 | id="Id" 7 | children="children" 8 | 9 | data = xlrd.open_workbook('Office_type_tree.xlsx') 10 | raw_data=data.sheets()[0] 11 | 12 | tree_list=[] 13 | 14 | for i in range(1,raw_data.nrows): 15 | tmp_data=raw_data.row_values(i) 16 | pid=tmp_data[4] 17 | if pid == '0': 18 | tmp_dict={id:tmp_data[0],name:tmp_data[3]} 19 | tree_list.append(tmp_dict) 20 | else : 21 | left=len(pid) 22 | list_tmp=tree_list 23 | k=1 24 | while(left>0): 25 | nid=pid[:2*k] 26 | left -= 2 27 | flag = 0 28 | for j in range(len(list_tmp)): 29 | #print (list_tmp[j][id]) 30 | #print (nid) 31 | if list_tmp[j][id] == nid : 32 | flag = 1 33 | if children in list_tmp[j]: 34 | list_tmp=list_tmp[j][children] 35 | else: 36 | list_tmp[j][children]=[] 37 | list_tmp=list_tmp[j][children] 38 | if flag == 0: 39 | raise Exception("没有找到父节点") 40 | k+=1 41 | tmp_dict = {id: tmp_data[0], name: tmp_data[3] } 42 | list_tmp.append(tmp_dict) 43 | 44 | with open("office.json",'w',encoding='utf-8') as f: 45 | f.write(json.dumps(tree_list,indent=2,ensure_ascii=False)) 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-buster-slim AS builder 2 | 3 | LABEL maintainer="yiruka114514 " 4 | LABEL maintainer="IceCodeNew " 5 | 6 | COPY frontend /webapps/ 7 | WORKDIR /webapps 8 | RUN npm install \ 9 | && npm run build 10 | 11 | ################ 12 | 13 | FROM python:slim AS webserver 14 | 15 | LABEL maintainer="yiruka114514 " 16 | LABEL maintainer="IceCodeNew " 17 | # ENV PYTHONUNBUFFERED 1 18 | 19 | ## Installing OS Dependencies 20 | ARG DEBIAN_FRONTEND=noninteractive 21 | RUN sed -i -E 's/(deb|security).debian.org/mirrors.cloud.aliyuncs.com/' '/etc/apt/sources.list' 22 | RUN apt-get update && apt-get install -y --no-install-recommends \ 23 | libsqlite3-dev \ 24 | && apt-get -y full-upgrade \ 25 | && apt-get -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false -o APT::AutoRemove::SuggestsImportant=false purge \ 26 | && apt-get clean && rm -rf /var/lib/apt/lists/* 27 | 28 | COPY --from=builder /webapps/dist /webapps/frontend/dist/ 29 | COPY cbdbweb /webapps/cbdbweb/ 30 | COPY requirements.txt /webapps/ 31 | # COPY requirements-opt.txt /webapps/ 32 | WORKDIR /webapps 33 | 34 | RUN pip config set global.index-url 'http://mirrors.cloud.aliyuncs.com/pypi/simple' \ 35 | && pip config set global.trusted-host mirrors.cloud.aliyuncs.com 36 | RUN pip install --no-cache-dir -r /webapps/requirements.txt 37 | # RUN pip install --no-cache-dir -r /webapps/requirements-opt.txt 38 | 39 | ## Django service 40 | EXPOSE 8000 41 | ## default command to execute 42 | CMD ["gunicorn", "cbdbweb.wsgi:application", "--bind 127.0.0.1:8000", "--workers 3"] 43 | -------------------------------------------------------------------------------- /src/cbdbweb/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/cbdbweb/__init__.py -------------------------------------------------------------------------------- /src/cbdbweb/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for cbdbweb project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cbdbweb.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /src/cbdbweb/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for cbdbweb project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.8. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | # DEBUG = os.getenv('DJANGO_DEBUG', False) 27 | DEBUG = True 28 | 29 | ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', '127.0.0.1').split(',') 30 | 31 | 32 | # Application definition 33 | 34 | INSTALLED_APPS = [ 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.staticfiles', 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'django.contrib.sessions.middleware.SessionMiddleware', 46 | 'django.middleware.common.CommonMiddleware', 47 | #'django.middleware.csrf.CsrfViewMiddleware', 48 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 49 | 'django.contrib.messages.middleware.MessageMiddleware', 50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 51 | ] 52 | 53 | ROOT_URLCONF = 'cbdbweb.urls' 54 | 55 | TEMPLATES = [ 56 | { 57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 58 | 'DIRS': ['frontend/dist'], 59 | 'APP_DIRS': True, 60 | 'OPTIONS': { 61 | 'context_processors': [ 62 | 'django.template.context_processors.debug', 63 | 'django.template.context_processors.request', 64 | 'django.contrib.auth.context_processors.auth', 65 | 'django.contrib.messages.context_processors.messages', 66 | ], 67 | }, 68 | }, 69 | ] 70 | 71 | WSGI_APPLICATION = 'cbdbweb.wsgi.application' 72 | 73 | 74 | # Database 75 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 76 | 77 | DATABASES = { 78 | 'default': { 79 | 'ENGINE': 'django.db.backends.sqlite3', 80 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 81 | } 82 | } 83 | 84 | 85 | # Password validation 86 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 87 | 88 | AUTH_PASSWORD_VALIDATORS = [ 89 | { 90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 91 | }, 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 100 | }, 101 | ] 102 | 103 | 104 | # Internationalization 105 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 106 | 107 | LANGUAGE_CODE = 'en-us' 108 | 109 | TIME_ZONE = 'UTC' 110 | 111 | USE_I18N = True 112 | 113 | USE_L10N = True 114 | 115 | USE_TZ = True 116 | 117 | 118 | # Static files (CSS, JavaScript, Images) 119 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 120 | 121 | STATIC_URL = '/static/' 122 | # Add for vuejs 123 | STATICFILES_DIRS = [ 124 | os.path.join(BASE_DIR, "frontend/dist/static"), 125 | ] 126 | -------------------------------------------------------------------------------- /src/cbdbweb/urls.py: -------------------------------------------------------------------------------- 1 | """cbdbweb URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from django.views.generic import TemplateView 19 | from django.conf import settings 20 | from django.conf.urls import url, include 21 | from django.conf.urls.static import static 22 | 23 | urlpatterns = [ 24 | url(r'^$', TemplateView.as_view(template_name="index.html")), 25 | #url(r'^static/(?P.*)$','django.views.static.serve',{'document_root':settings.STATICFILES_DIRS}), 26 | path('admin/', admin.site.urls), 27 | ]+ static(settings.STATIC_URL, document_root=settings.STATICFILES_DIRS[0]) 28 | -------------------------------------------------------------------------------- /src/cbdbweb/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cbdbweb project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cbdbweb.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /src/db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/db.sqlite3 -------------------------------------------------------------------------------- /src/frontend/build/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | require('./check-versions')() 3 | 4 | process.env.NODE_ENV = 'production' 5 | 6 | const ora = require('ora') 7 | const rm = require('rimraf') 8 | const path = require('path') 9 | const chalk = require('chalk') 10 | const webpack = require('webpack') 11 | const config = require('../config') 12 | const webpackConfig = require('./webpack.prod.conf') 13 | 14 | const spinner = ora('building for production...') 15 | spinner.start() 16 | 17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 18 | if (err) throw err 19 | webpack(webpackConfig, (err, stats) => { 20 | spinner.stop() 21 | if (err) throw err 22 | process.stdout.write(stats.toString({ 23 | colors: true, 24 | modules: false, 25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 26 | chunks: false, 27 | chunkModules: false 28 | }) + '\n\n') 29 | 30 | if (stats.hasErrors()) { 31 | console.log(chalk.red(' Build failed with errors.\n')) 32 | process.exit(1) 33 | } 34 | 35 | console.log(chalk.cyan(' Build complete.\n')) 36 | console.log(chalk.yellow( 37 | ' Tip: built files are meant to be served over an HTTP server.\n' + 38 | ' Opening index.html over file:// won\'t work.\n' 39 | )) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /src/frontend/build/check-versions.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const chalk = require('chalk') 3 | const semver = require('semver') 4 | const packageConfig = require('../package.json') 5 | const shell = require('shelljs') 6 | 7 | function exec (cmd) { 8 | return require('child_process').execSync(cmd).toString().trim() 9 | } 10 | 11 | const versionRequirements = [ 12 | { 13 | name: 'node', 14 | currentVersion: semver.clean(process.version), 15 | versionRequirement: packageConfig.engines.node 16 | } 17 | ] 18 | 19 | if (shell.which('npm')) { 20 | versionRequirements.push({ 21 | name: 'npm', 22 | currentVersion: exec('npm --version'), 23 | versionRequirement: packageConfig.engines.npm 24 | }) 25 | } 26 | 27 | module.exports = function () { 28 | const warnings = [] 29 | 30 | for (let i = 0; i < versionRequirements.length; i++) { 31 | const mod = versionRequirements[i] 32 | 33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 34 | warnings.push(mod.name + ': ' + 35 | chalk.red(mod.currentVersion) + ' should be ' + 36 | chalk.green(mod.versionRequirement) 37 | ) 38 | } 39 | } 40 | 41 | if (warnings.length) { 42 | console.log('') 43 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 44 | console.log() 45 | 46 | for (let i = 0; i < warnings.length; i++) { 47 | const warning = warnings[i] 48 | console.log(' ' + warning) 49 | } 50 | 51 | console.log() 52 | process.exit(1) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/frontend/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/frontend/build/logo.png -------------------------------------------------------------------------------- /src/frontend/build/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const config = require('../config') 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 5 | const packageConfig = require('../package.json') 6 | 7 | exports.assetsPath = function (_path) { 8 | const assetsSubDirectory = process.env.NODE_ENV === 'production' 9 | ? config.build.assetsSubDirectory 10 | : config.dev.assetsSubDirectory 11 | 12 | return path.posix.join(assetsSubDirectory, _path) 13 | } 14 | 15 | exports.cssLoaders = function (options) { 16 | options = options || {} 17 | 18 | const cssLoader = { 19 | loader: 'css-loader', 20 | options: { 21 | sourceMap: options.sourceMap 22 | } 23 | } 24 | 25 | const postcssLoader = { 26 | loader: 'postcss-loader', 27 | options: { 28 | sourceMap: options.sourceMap 29 | } 30 | } 31 | 32 | // generate loader string to be used with extract text plugin 33 | function generateLoaders (loader, loaderOptions) { 34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] 35 | 36 | if (loader) { 37 | loaders.push({ 38 | loader: loader + '-loader', 39 | options: Object.assign({}, loaderOptions, { 40 | sourceMap: options.sourceMap 41 | }) 42 | }) 43 | } 44 | 45 | // Extract CSS when that option is specified 46 | // (which is the case during production build) 47 | if (options.extract) { 48 | return ExtractTextPlugin.extract({ 49 | use: loaders, 50 | fallback: 'vue-style-loader' 51 | }) 52 | } else { 53 | return ['vue-style-loader'].concat(loaders) 54 | } 55 | } 56 | 57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 58 | return { 59 | css: generateLoaders(), 60 | postcss: generateLoaders(), 61 | less: generateLoaders('less'), 62 | sass: generateLoaders('sass', { indentedSyntax: true }), 63 | scss: generateLoaders('sass'), 64 | stylus: generateLoaders('stylus'), 65 | styl: generateLoaders('stylus') 66 | } 67 | } 68 | 69 | // Generate loaders for standalone style files (outside of .vue) 70 | exports.styleLoaders = function (options) { 71 | const output = [] 72 | const loaders = exports.cssLoaders(options) 73 | 74 | for (const extension in loaders) { 75 | const loader = loaders[extension] 76 | output.push({ 77 | test: new RegExp('\\.' + extension + '$'), 78 | use: loader 79 | }) 80 | } 81 | 82 | return output 83 | } 84 | 85 | exports.createNotifierCallback = () => { 86 | const notifier = require('node-notifier') 87 | 88 | return (severity, errors) => { 89 | if (severity !== 'error') return 90 | 91 | const error = errors[0] 92 | const filename = error.file && error.file.split('!').pop() 93 | 94 | notifier.notify({ 95 | title: packageConfig.name, 96 | message: severity + ': ' + error.name, 97 | subtitle: filename || '', 98 | icon: path.join(__dirname, 'logo.png') 99 | }) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/frontend/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const config = require('../config') 4 | const isProduction = process.env.NODE_ENV === 'production' 5 | const sourceMapEnabled = isProduction 6 | ? config.build.productionSourceMap 7 | : config.dev.cssSourceMap 8 | 9 | module.exports = { 10 | loaders: utils.cssLoaders({ 11 | sourceMap: sourceMapEnabled, 12 | extract: isProduction 13 | }), 14 | cssSourceMap: sourceMapEnabled, 15 | cacheBusting: config.dev.cacheBusting, 16 | transformToRequire: { 17 | video: ['src', 'poster'], 18 | source: 'src', 19 | img: 'src', 20 | image: 'xlink:href' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/frontend/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const config = require('../config') 5 | const vueLoaderConfig = require('./vue-loader.conf') 6 | 7 | function resolve (dir) { 8 | return path.join(__dirname, '..', dir) 9 | } 10 | 11 | 12 | 13 | module.exports = { 14 | context: path.resolve(__dirname, '../'), 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | //处理字体文件 35 | {test:/\.(ttf|eot|svg|woff|woff2|otf)$/, use: 'url-loader'}, 36 | { 37 | test: /\.vue$/, 38 | loader: 'vue-loader', 39 | options: vueLoaderConfig 40 | }, 41 | { 42 | test: /\.js$/, 43 | loader: 'babel-loader', 44 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')] 45 | }, 46 | { 47 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 48 | loader: 'url-loader', 49 | options: { 50 | limit: 10000, 51 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 52 | } 53 | }, 54 | { 55 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 56 | loader: 'url-loader', 57 | options: { 58 | limit: 10000, 59 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 60 | } 61 | }, 62 | { 63 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 64 | loader: 'url-loader', 65 | options: { 66 | limit: 10000, 67 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 68 | } 69 | }, 70 | { 71 | test: /\.js$/, 72 | loader: 'babel-loader', 73 | exclude: /node_modules/, 74 | options: {//如果有这个设置则不用再添加.babelrc文件进行配置 75 | "babelrc": false,// 不采用.babelrc的配置 76 | "plugins": [ 77 | "dynamic-import-webpack" 78 | ] 79 | } 80 | } 81 | ] 82 | }, 83 | /* 84 | externals: { 85 | "echarts": "echarts" 86 | }, 87 | */ 88 | node: { 89 | // prevent webpack from injecting useless setImmediate polyfill because Vue 90 | // source contains it (although only uses it if it's native). 91 | setImmediate: false, 92 | // prevent webpack from injecting mocks to Node native modules 93 | // that does not make sense for the client 94 | dgram: 'empty', 95 | fs: 'empty', 96 | net: 'empty', 97 | tls: 'empty', 98 | child_process: 'empty' 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/frontend/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const utils = require('./utils') 3 | const webpack = require('webpack') 4 | const config = require('../config') 5 | const merge = require('webpack-merge') 6 | const path = require('path') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 11 | const portfinder = require('portfinder') 12 | 13 | const HOST = process.env.HOST 14 | const PORT = process.env.PORT && Number(process.env.PORT) 15 | 16 | const devWebpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) 19 | }, 20 | // cheap-module-eval-source-map is faster for development 21 | devtool: config.dev.devtool, 22 | 23 | // these devServer options should be customized in /config/index.js 24 | devServer: { 25 | clientLogLevel: 'warning', 26 | historyApiFallback: { 27 | rewrites: [ 28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, 29 | ], 30 | }, 31 | hot: true, 32 | contentBase: false, // since we use CopyWebpackPlugin. 33 | compress: true, 34 | host: HOST || config.dev.host, 35 | port: PORT || config.dev.port, 36 | open: config.dev.autoOpenBrowser, 37 | overlay: config.dev.errorOverlay 38 | ? { warnings: false, errors: true } 39 | : false, 40 | publicPath: config.dev.assetsPublicPath, 41 | proxy: config.dev.proxyTable, 42 | quiet: true, // necessary for FriendlyErrorsPlugin 43 | watchOptions: { 44 | poll: config.dev.poll, 45 | } 46 | }, 47 | plugins: [ 48 | new webpack.DefinePlugin({ 49 | 'process.env': require('../config/dev.env') 50 | }), 51 | new webpack.HotModuleReplacementPlugin(), 52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. 53 | new webpack.NoEmitOnErrorsPlugin(), 54 | // https://github.com/ampedandwired/html-webpack-plugin 55 | new HtmlWebpackPlugin({ 56 | filename: 'index.html', 57 | template: 'index.html', 58 | inject: true 59 | }), 60 | // copy custom static assets 61 | new CopyWebpackPlugin([ 62 | { 63 | from: path.resolve(__dirname, '../static'), 64 | to: config.dev.assetsSubDirectory, 65 | ignore: ['.*'] 66 | } 67 | ]) 68 | ] 69 | }) 70 | 71 | module.exports = new Promise((resolve, reject) => { 72 | portfinder.basePort = process.env.PORT || config.dev.port 73 | portfinder.getPort((err, port) => { 74 | if (err) { 75 | reject(err) 76 | } else { 77 | // publish the new Port, necessary for e2e tests 78 | process.env.PORT = port 79 | // add port to devServer config 80 | devWebpackConfig.devServer.port = port 81 | 82 | // Add FriendlyErrorsPlugin 83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ 84 | compilationSuccessInfo: { 85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`], 86 | }, 87 | onErrors: config.dev.notifyOnErrors 88 | ? utils.createNotifierCallback() 89 | : undefined 90 | })) 91 | 92 | resolve(devWebpackConfig) 93 | } 94 | }) 95 | }) 96 | -------------------------------------------------------------------------------- /src/frontend/build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const utils = require('./utils') 4 | const webpack = require('webpack') 5 | const config = require('../config') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | const CopyWebpackPlugin = require('copy-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 13 | 14 | const env = require('../config/prod.env') 15 | 16 | const webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: 19 | utils.styleLoaders({ 20 | sourceMap: config.build.productionSourceMap, 21 | extract: true, 22 | usePostCSS: true 23 | }) 24 | }, 25 | devtool: config.build.productionSourceMap ? config.build.devtool : false, 26 | output: { 27 | path: config.build.assetsRoot, 28 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 29 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 30 | }, 31 | plugins: [ 32 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 33 | new webpack.DefinePlugin({ 34 | 'process.env': env 35 | }), 36 | new UglifyJsPlugin({ 37 | uglifyOptions: { 38 | compress: { 39 | warnings: false 40 | } 41 | }, 42 | sourceMap: config.build.productionSourceMap, 43 | parallel: true 44 | }), 45 | // extract css into its own file 46 | new ExtractTextPlugin({ 47 | filename: utils.assetsPath('css/[name].[contenthash].css'), 48 | // Setting the following option to `false` will not extract CSS from codesplit chunks. 49 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. 50 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 51 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 52 | allChunks: true, 53 | }), 54 | // Compress extracted CSS. We are using this plugin so that possible 55 | // duplicated CSS from different components can be deduped. 56 | new OptimizeCSSPlugin({ 57 | cssProcessorOptions: config.build.productionSourceMap 58 | ? { safe: true, map: { inline: false } } 59 | : { safe: true } 60 | }), 61 | // generate dist index.html with correct asset hash for caching. 62 | // you can customize output by editing /index.html 63 | // see https://github.com/ampedandwired/html-webpack-plugin 64 | new HtmlWebpackPlugin({ 65 | filename: config.build.index, 66 | template: 'index.html', 67 | inject: true, 68 | minify: { 69 | removeComments: true, 70 | collapseWhitespace: true, 71 | removeAttributeQuotes: true 72 | // more options: 73 | // https://github.com/kangax/html-minifier#options-quick-reference 74 | }, 75 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 76 | chunksSortMode: 'dependency' 77 | }), 78 | // keep module.id stable when vendor modules does not change 79 | new webpack.HashedModuleIdsPlugin(), 80 | // enable scope hoisting 81 | new webpack.optimize.ModuleConcatenationPlugin(), 82 | // split vendor js into its own file 83 | new webpack.optimize.CommonsChunkPlugin({ 84 | name: 'vendor', 85 | minChunks (module) { 86 | // any required modules inside node_modules are extracted to vendor 87 | return ( 88 | module.resource && 89 | /\.js$/.test(module.resource) && 90 | module.resource.indexOf( 91 | path.join(__dirname, '../node_modules') 92 | ) === 0 93 | ) 94 | } 95 | }), 96 | // extract webpack runtime and module manifest to its own file in order to 97 | // prevent vendor hash from being updated whenever app bundle is updated 98 | new webpack.optimize.CommonsChunkPlugin({ 99 | name: 'manifest', 100 | minChunks: Infinity 101 | }), 102 | // This instance extracts shared chunks from code splitted chunks and bundles them 103 | // in a separate chunk, similar to the vendor chunk 104 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 105 | new webpack.optimize.CommonsChunkPlugin({ 106 | name: 'app', 107 | async: 'vendor-async', 108 | children: true, 109 | minChunks: 3 110 | }), 111 | 112 | // copy custom static assets 113 | new CopyWebpackPlugin([ 114 | { 115 | from: path.resolve(__dirname, '../static'), 116 | to: config.build.assetsSubDirectory, 117 | ignore: ['.*'] 118 | } 119 | ]) 120 | ] 121 | }) 122 | 123 | if (config.build.productionGzip) { 124 | const CompressionWebpackPlugin = require('compression-webpack-plugin') 125 | 126 | webpackConfig.plugins.push( 127 | new CompressionWebpackPlugin({ 128 | asset: '[path].gz[query]', 129 | algorithm: 'gzip', 130 | test: new RegExp( 131 | '\\.(' + 132 | config.build.productionGzipExtensions.join('|') + 133 | ')$' 134 | ), 135 | threshold: 10240, 136 | minRatio: 0.8 137 | }) 138 | ) 139 | } 140 | 141 | if (config.build.bundleAnalyzerReport) { 142 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 143 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 144 | } 145 | 146 | module.exports = webpackConfig 147 | -------------------------------------------------------------------------------- /src/frontend/config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /src/frontend/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: {}, 14 | 15 | // Various Dev Server settings 16 | host: 'localhost', // can be overwritten by process.env.HOST 17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 18 | autoOpenBrowser: false, 19 | errorOverlay: true, 20 | notifyOnErrors: true, 21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 22 | 23 | 24 | /** 25 | * Source Maps 26 | */ 27 | 28 | // https://webpack.js.org/configuration/devtool/#development 29 | devtool: 'cheap-module-eval-source-map', 30 | 31 | // If you have problems debugging vue-files in devtools, 32 | // set this to false - it *may* help 33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 34 | cacheBusting: true, 35 | 36 | cssSourceMap: true 37 | }, 38 | 39 | build: { 40 | // Template for index.html 41 | index: path.resolve(__dirname, '../dist/index.html'), 42 | 43 | // Paths 44 | assetsRoot: path.resolve(__dirname, '../dist'), 45 | assetsSubDirectory: 'static', 46 | assetsPublicPath: '/', 47 | 48 | /** 49 | * Source Maps 50 | */ 51 | 52 | productionSourceMap: true, 53 | // https://webpack.js.org/configuration/devtool/#production 54 | devtool: '#source-map', 55 | 56 | // Gzip off by default as many popular static hosts such as 57 | // Surge or Netlify already gzip all static assets for you. 58 | // Before setting to `true`, make sure to: 59 | // npm install --save-dev compression-webpack-plugin 60 | productionGzip: false, 61 | productionGzipExtensions: ['js', 'css'], 62 | 63 | // Run the build command with an extra argument to 64 | // View the bundle analyzer report after build finishes: 65 | // `npm run build --report` 66 | // Set to `true` or `false` to always turn it on or off 67 | bundleAnalyzerReport: process.env.npm_config_report 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/frontend/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | cbdb-new 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cbdb-new", 3 | "version": "1.0.0", 4 | "description": "", 5 | "author": "Plevium Tandanu ", 6 | "private": true, 7 | "sideEffects": false, 8 | "scripts": { 9 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 10 | "start": "npm run dev", 11 | "quick-start": "npm install && npm run dev", 12 | "build": "node build/build.js", 13 | "analyze": "NODE_ENV=production npm_config_report=true npm run build", 14 | "lint": "vue-cli-service lint" 15 | }, 16 | "dependencies": { 17 | "axios": "^0.19.2", 18 | "bootstrap": "^4.4.1", 19 | "bootstrap-vue": "^2.5.0", 20 | "echarts": "^4.7.0", 21 | "install": "^0.13.0", 22 | "jquery": "^3.4.1", 23 | "npm": "^6.13.2", 24 | "portal-vue": "^2.1.6", 25 | "vue": "^2.5.2", 26 | "vue-axios": "^2.1.5", 27 | "vue-i18n": "^8.15.3", 28 | "vue-router": "^3.0.1", 29 | "vuex": "^3.1.2" 30 | }, 31 | "devDependencies": { 32 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 33 | "@vue/cli-plugin-babel": "~4.5.0", 34 | "@vue/cli-plugin-eslint": "~4.5.0", 35 | "@vue/cli-service": "~4.5.0", 36 | "@vue/eslint-config-prettier": "^6.0.0", 37 | "babel-eslint": "^10.1.0", 38 | "eslint": "^6.7.2", 39 | "eslint-plugin-prettier": "^3.3.1", 40 | "eslint-plugin-vue": "^6.2.2", 41 | "babel-plugin-dynamic-import-webpack": "^1.1.0", 42 | "autoprefixer": "^7.1.2", 43 | "babel-core": "^6.22.1", 44 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 45 | "babel-loader": "^7.1.1", 46 | "babel-plugin-syntax-jsx": "^6.18.0", 47 | "babel-plugin-transform-vue-jsx": "^3.5.0", 48 | "babel-preset-env": "^1.3.2", 49 | "babel-preset-stage-2": "^6.22.0", 50 | "chalk": "^2.0.1", 51 | "copy-webpack-plugin": "^4.0.1", 52 | "css-loader": "^0.28.0", 53 | "extract-text-webpack-plugin": "^3.0.0", 54 | "file-loader": "^1.1.4", 55 | "friendly-errors-webpack-plugin": "^1.6.1", 56 | "html-webpack-plugin": "^2.30.1", 57 | "less": "^3.10.3", 58 | "less-loader": "^5.0.0", 59 | "node-notifier": "^5.1.2", 60 | "optimize-css-assets-webpack-plugin": "^3.2.0", 61 | "ora": "^1.2.0", 62 | "portfinder": "^1.0.13", 63 | "postcss-import": "^11.0.0", 64 | "postcss-loader": "^2.0.8", 65 | "postcss-url": "^7.2.1", 66 | "rimraf": "^2.6.0", 67 | "semver": "^5.3.0", 68 | "shelljs": "^0.7.6", 69 | "uglifyjs-webpack-plugin": "^1.1.1", 70 | "url-loader": "^0.5.8", 71 | "vue-loader": "^13.3.0", 72 | "vue-style-loader": "^3.0.1", 73 | "vue-template-compiler": "^2.5.2", 74 | "webpack": "^3.12.0", 75 | "webpack-bundle-analyzer": "^2.9.0", 76 | "webpack-dev-server": "^2.9.1", 77 | "webpack-merge": "^4.1.0" 78 | }, 79 | "eslintConfig": { 80 | "root": true, 81 | "env": { 82 | "node": true 83 | }, 84 | "extends": [ 85 | "plugin:vue/essential", 86 | "eslint:recommended", 87 | "@vue/prettier" 88 | ], 89 | "parserOptions": { 90 | "parser": "babel-eslint" 91 | }, 92 | "rules": {} 93 | }, 94 | "engines": { 95 | "node": ">= 6.0.0", 96 | "npm": ">= 3.0.0" 97 | }, 98 | "browserslist": [ 99 | "> 1%", 100 | "last 2 versions", 101 | "not ie <= 8" 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /src/frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: { browsers: "last 5 version" } 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /src/frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 29 | 30 | 82 | -------------------------------------------------------------------------------- /src/frontend/src/assets/dynastyData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "c_dy":0, 4 | "c_dynasty_chn":"未詳", 5 | "c_dynasty":"unknown" 6 | }, 7 | { 8 | "c_dy":1, 9 | "c_dynasty_chn":"漢前", 10 | "c_dynasty":"Pre-Han" 11 | }, 12 | { 13 | "c_dy":2, 14 | "c_dynasty_chn":"秦漢", 15 | "c_dynasty":"QinHan" 16 | }, 17 | { 18 | "c_dy":3, 19 | "c_dynasty_chn":"三國", 20 | "c_dynasty":"SanGuo" 21 | }, 22 | { 23 | "c_dy":4, 24 | "c_dynasty_chn":"南北朝", 25 | "c_dynasty":"NanBei Chao" 26 | }, 27 | { 28 | "c_dy":5, 29 | "c_dynasty_chn":"隋", 30 | "c_dynasty":"Sui" 31 | }, 32 | { 33 | "c_dy":6, 34 | "c_dynasty_chn":"唐", 35 | "c_dynasty":"Tang" 36 | }, 37 | { 38 | "c_dy":7, 39 | "c_dynasty_chn":"五代", 40 | "c_dynasty":"Five Dynasties" 41 | }, 42 | { 43 | "c_dy":8, 44 | "c_dynasty_chn":"後蜀", 45 | "c_dynasty":"Later Shu (10 states)" 46 | }, 47 | { 48 | "c_dy":9, 49 | "c_dynasty_chn":"吳", 50 | "c_dynasty":"Wu" 51 | }, 52 | { 53 | "c_dy":10, 54 | "c_dynasty_chn":"南唐", 55 | "c_dynasty":"Southern Tang (10 states)" 56 | }, 57 | { 58 | "c_dy":11, 59 | "c_dynasty_chn":"吳越", 60 | "c_dynasty":"WuYue (10 states)" 61 | }, 62 | { 63 | "c_dy":12, 64 | "c_dynasty_chn":"閩國", 65 | "c_dynasty":"Min (10 states)" 66 | }, 67 | { 68 | "c_dy":13, 69 | "c_dynasty_chn":"南漢", 70 | "c_dynasty":"Southern Han (10 states)" 71 | }, 72 | { 73 | "c_dy":14, 74 | "c_dynasty_chn":"高麗", 75 | "c_dynasty":"Koryo" 76 | }, 77 | { 78 | "c_dy":15, 79 | "c_dynasty_chn":"宋", 80 | "c_dynasty":"Song" 81 | }, 82 | { 83 | "c_dy":16, 84 | "c_dynasty_chn":"遼", 85 | "c_dynasty":"Liao" 86 | }, 87 | { 88 | "c_dy":17, 89 | "c_dynasty_chn":"金", 90 | "c_dynasty":"Jin" 91 | }, 92 | { 93 | "c_dy":18, 94 | "c_dynasty_chn":"元", 95 | "c_dynasty":"Yuan" 96 | }, 97 | { 98 | "c_dy":19, 99 | "c_dynasty_chn":"明", 100 | "c_dynasty":"Ming" 101 | }, 102 | { 103 | "c_dy":20, 104 | "c_dynasty_chn":"清", 105 | "c_dynasty":"Qing" 106 | }, 107 | { 108 | "c_dy":21, 109 | "c_dynasty_chn":"中華民國", 110 | "c_dynasty":"Republic of China" 111 | }, 112 | { 113 | "c_dy":22, 114 | "c_dynasty_chn":"中華人民共和國", 115 | "c_dynasty":"People's Republic of China" 116 | }, 117 | { 118 | "c_dy":23, 119 | "c_dynasty_chn":"西晉", 120 | "c_dynasty":"Western Jin" 121 | }, 122 | { 123 | "c_dy":24, 124 | "c_dynasty_chn":"陳", 125 | "c_dynasty":"Chen" 126 | }, 127 | { 128 | "c_dy":25, 129 | "c_dynasty_chn":"東漢", 130 | "c_dynasty":"Eastern Han" 131 | }, 132 | { 133 | "c_dy":26, 134 | "c_dynasty_chn":"三國魏", 135 | "c_dynasty":"SanGuo Wei" 136 | }, 137 | { 138 | "c_dy":27, 139 | "c_dynasty_chn":"東晉", 140 | "c_dynasty":"Eastern Jin" 141 | }, 142 | { 143 | "c_dy":28, 144 | "c_dynasty_chn":"宋(劉)", 145 | "c_dynasty":"Song (Liu)" 146 | }, 147 | { 148 | "c_dy":29, 149 | "c_dynasty_chn":"西漢", 150 | "c_dynasty":"Western Han" 151 | }, 152 | { 153 | "c_dy":30, 154 | "c_dynasty_chn":"北魏", 155 | "c_dynasty":"Northern Wei" 156 | }, 157 | { 158 | "c_dy":31, 159 | "c_dynasty_chn":"北周", 160 | "c_dynasty":"Northern Zhou" 161 | }, 162 | { 163 | "c_dy":32, 164 | "c_dynasty_chn":"南齌", 165 | "c_dynasty":"Southern Qi" 166 | }, 167 | { 168 | "c_dy":34, 169 | "c_dynasty_chn":"後梁", 170 | "c_dynasty":"Later Liang (5 dynasties)" 171 | }, 172 | { 173 | "c_dy":35, 174 | "c_dynasty_chn":"北齊", 175 | "c_dynasty":"Northern Qi" 176 | }, 177 | { 178 | "c_dy":36, 179 | "c_dynasty_chn":"吳(楊)", 180 | "c_dynasty":"Wu (Yang: 10 states)" 181 | }, 182 | { 183 | "c_dy":37, 184 | "c_dynasty_chn":"西梁", 185 | "c_dynasty":"Western Liang" 186 | }, 187 | { 188 | "c_dy":38, 189 | "c_dynasty_chn":"楚(馬)", 190 | "c_dynasty":"Chu (Ma:10 states)" 191 | }, 192 | { 193 | "c_dy":39, 194 | "c_dynasty_chn":"前燕", 195 | "c_dynasty":"Former Yan (16 states)" 196 | }, 197 | { 198 | "c_dy":40, 199 | "c_dynasty_chn":"西魏", 200 | "c_dynasty":"Western Wei" 201 | }, 202 | { 203 | "c_dy":41, 204 | "c_dynasty_chn":"東魏", 205 | "c_dynasty":"Eastern Wei" 206 | }, 207 | { 208 | "c_dy":42, 209 | "c_dynasty_chn":"三國吳", 210 | "c_dynasty":"SanGuo Wu" 211 | }, 212 | { 213 | "c_dy":44, 214 | "c_dynasty_chn":"南梁", 215 | "c_dynasty":"Southern Liang" 216 | }, 217 | { 218 | "c_dy":45, 219 | "c_dynasty_chn":"後秦", 220 | "c_dynasty":"Later Qin (16 states)" 221 | }, 222 | { 223 | "c_dy":46, 224 | "c_dynasty_chn":"新", 225 | "c_dynasty":"Xin (Wang Mang)" 226 | }, 227 | { 228 | "c_dy":47, 229 | "c_dynasty_chn":"後唐", 230 | "c_dynasty":"Later Tang (5 dynasties)" 231 | }, 232 | { 233 | "c_dy":48, 234 | "c_dynasty_chn":"後晉", 235 | "c_dynasty":"Later Jin (5 dynasties)" 236 | }, 237 | { 238 | "c_dy":49, 239 | "c_dynasty_chn":"後周", 240 | "c_dynasty":"Later Zhou (5 dynasties)" 241 | }, 242 | { 243 | "c_dy":50, 244 | "c_dynasty_chn":"南燕", 245 | "c_dynasty":"Southern Yan (16 states)" 246 | }, 247 | { 248 | "c_dy":51, 249 | "c_dynasty_chn":"前涼", 250 | "c_dynasty":"Former Liang (16 states)" 251 | }, 252 | { 253 | "c_dy":52, 254 | "c_dynasty_chn":"後漢", 255 | "c_dynasty":"Later Han (5 dynasties)" 256 | }, 257 | { 258 | "c_dy":53, 259 | "c_dynasty_chn":"三國蜀", 260 | "c_dynasty":"SanGuo Shu" 261 | }, 262 | { 263 | "c_dy":55, 264 | "c_dynasty_chn":"南平", 265 | "c_dynasty":"Nanping (10 states)" 266 | }, 267 | { 268 | "c_dy":56, 269 | "c_dynasty_chn":"西涼", 270 | "c_dynasty":"Western Liang (16 states)" 271 | }, 272 | { 273 | "c_dy":57, 274 | "c_dynasty_chn":"偽齊", 275 | "c_dynasty":"Qi (Wei Qi)" 276 | }, 277 | { 278 | "c_dy":58, 279 | "c_dynasty_chn":"高麗", 280 | "c_dynasty":"Korea" 281 | }, 282 | { 283 | "c_dy":59, 284 | "c_dynasty_chn":"西遼", 285 | "c_dynasty":"Qara-Khitay" 286 | }, 287 | { 288 | "c_dy":60, 289 | "c_dynasty_chn":"北燕", 290 | "c_dynasty":"Northern Yan (16 states)" 291 | }, 292 | { 293 | "c_dy":61, 294 | "c_dynasty_chn":"贏秦", 295 | "c_dynasty":"Ying Qin" 296 | }, 297 | { 298 | "c_dy":62, 299 | "c_dynasty_chn":"北涼", 300 | "c_dynasty":"Northern Liang (16 states" 301 | }, 302 | { 303 | "c_dy":63, 304 | "c_dynasty_chn":"後燕", 305 | "c_dynasty":"Later Yan (16 states)" 306 | }, 307 | { 308 | "c_dy":64, 309 | "c_dynasty_chn":"後趙", 310 | "c_dynasty":"Later Zhao (16 states)" 311 | }, 312 | { 313 | "c_dy":65, 314 | "c_dynasty_chn":"前秦", 315 | "c_dynasty":"Former Qin (16 states)" 316 | }, 317 | { 318 | "c_dy":66, 319 | "c_dynasty_chn":"北漢", 320 | "c_dynasty":"Northern Han (10 states)" 321 | }, 322 | { 323 | "c_dy":67, 324 | "c_dynasty_chn":"新羅", 325 | "c_dynasty":"Xinluo (Korea)" 326 | }, 327 | { 328 | "c_dy":68, 329 | "c_dynasty_chn":"東梁", 330 | "c_dynasty":"Eastern Liang (North. Dy)" 331 | }, 332 | { 333 | "c_dy":69, 334 | "c_dynasty_chn":"前趙", 335 | "c_dynasty":"Former Zhao (16 states)" 336 | }, 337 | { 338 | "c_dy":70, 339 | "c_dynasty_chn":"成漢", 340 | "c_dynasty":"Cheng Han (16 states)" 341 | }, 342 | { 343 | "c_dy":71, 344 | "c_dynasty_chn":"夏", 345 | "c_dynasty":"Xia (16 states)" 346 | }, 347 | { 348 | "c_dy":72, 349 | "c_dynasty_chn":"西秦", 350 | "c_dynasty":"Western Qin (16 states)" 351 | }, 352 | { 353 | "c_dy":73, 354 | "c_dynasty_chn":"後涼", 355 | "c_dynasty":"Later Liang (16 states)" 356 | }, 357 | { 358 | "c_dy":74, 359 | "c_dynasty_chn":"南涼", 360 | "c_dynasty":"Southern Liang (16 states)" 361 | }, 362 | { 363 | "c_dy":75, 364 | "c_dynasty_chn":"前蜀", 365 | "c_dynasty":"Former Shu (10 states)" 366 | }, 367 | { 368 | "c_dy":76, 369 | "c_dynasty_chn":"西燕", 370 | "c_dynasty":"Western Yan (16 states)" 371 | }, 372 | { 373 | "c_dy":77, 374 | "c_dynasty_chn":"周", 375 | "c_dynasty":"Zhou (Wu Zetian)" 376 | }, 377 | { 378 | "c_dy":78, 379 | "c_dynasty_chn":"西夏", 380 | "c_dynasty":"Western Xia" 381 | }, 382 | { 383 | "c_dy":79, 384 | "c_dynasty_chn":"北元", 385 | "c_dynasty":"Northern Yuan" 386 | }, 387 | { 388 | "c_dy":80, 389 | "c_dynasty_chn":"南明", 390 | "c_dynasty":"Soutthern Ming" 391 | }, 392 | { 393 | "c_dy":81, 394 | "c_dynasty_chn":"鄭(王世充)", 395 | "c_dynasty":"Zheng (Wang Shichong)" 396 | }, 397 | { 398 | "c_dy":82, 399 | "c_dynasty_chn":"晉", 400 | "c_dynasty":"Jin" 401 | }, 402 | { 403 | "c_dy":83, 404 | "c_dynasty_chn":"漢", 405 | "c_dynasty":"Han" 406 | } 407 | ] -------------------------------------------------------------------------------- /src/frontend/src/assets/entryData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id":"00", 4 | "ObjectName":"未知入仕途径" 5 | }, 6 | { 7 | "Id":"01", 8 | "ObjectName":"宫廷门" 9 | }, 10 | { 11 | "Id":"02", 12 | "ObjectName":"血亲门" 13 | }, 14 | { 15 | "Id":"03", 16 | "ObjectName":"姻亲门" 17 | }, 18 | { 19 | "Id":"04", 20 | "ObjectName": "科举门", 21 | "children": [ 22 | { 23 | "Id":"0401", 24 | "ObjectName": "正常科举" 25 | }, 26 | { 27 | "Id": "0402", 28 | "ObjectName": "非正常科举" 29 | }, 30 | { 31 | "Id": "0403", 32 | "ObjectName": "制举" 33 | }, 34 | { 35 | "Id": "0404", 36 | "ObjectName": "其他举" 37 | } 38 | ] 39 | }, 40 | { 41 | "Id": "05", 42 | "ObjectName": "学校门", 43 | "children": [ 44 | { 45 | "Id": "0501", 46 | "ObjectName": "学生门" 47 | }, 48 | { 49 | "Id": "0502", 50 | "ObjectName": "监生门" 51 | }, 52 | { 53 | "Id": "0503", 54 | "ObjectName": "贡生门" 55 | } 56 | ] 57 | }, 58 | { 59 | "Id":"06", 60 | "ObjectName":"恩荫门", 61 | "children":[] 62 | }, 63 | { 64 | "Id":"07", 65 | "ObjectName":"徵召门", 66 | "children":[] 67 | }, 68 | { 69 | "Id":"08", 70 | "ObjectName":"荐举门", 71 | "children":[] 72 | }, 73 | { 74 | "Id":"09", 75 | "ObjectName":"军功补授门", 76 | "children":[] 77 | }, 78 | { 79 | "Id":"10", 80 | "ObjectName":"技进门" 81 | }, 82 | { 83 | "Id":"11", 84 | "ObjectName":"归降门" 85 | }, 86 | { 87 | "Id":"12", 88 | "ObjectName":"进纳门" 89 | }, 90 | { 91 | "Id":"13", 92 | "ObjectName":"特旨门" 93 | }, 94 | { 95 | "Id":"14", 96 | "ObjectName":"宗教门" 97 | }, 98 | { 99 | "Id":"15", 100 | "ObjectName":"求官不得门" 101 | }, 102 | { 103 | "Id":"16", 104 | "ObjectName":"七色补官门" 105 | }, 106 | { 107 | "Id":"90", 108 | "ObjectName":"其他入仕途径" 109 | }, 110 | { 111 | "Id":"99", 112 | "ObjectName":"Temp" 113 | } 114 | ] 115 | -------------------------------------------------------------------------------- /src/frontend/src/assets/geodata_dev.json: -------------------------------------------------------------------------------- 1 | [{"\ufeffName": "Zhang Yong", "NameChn": "張詠", "Sex": "M", "IndexYear": " 1005", "AddrID": " 11273", "AddrName": "Juancheng", "AddrChn": "鄄城", "X": " 115.5583", "Y": " 35.61019", "xy_count": " 1"}, {"\ufeffName": "Zhang Dun", "NameChn": "章惇", "Sex": "M", "IndexYear": " 1094", "AddrID": " 13892", "AddrName": "Pucheng", "AddrChn": "浦城", "X": " 118.536255", "Y": " 27.924686", "xy_count": " 6"}, {"\ufeffName": "Zhang Dexiang", "NameChn": "章得象", "Sex": "M", "IndexYear": " 1037", "AddrID": " 13892", "AddrName": "Pucheng", "AddrChn": "浦城", "X": " 118.536255", "Y": " 27.924686", "xy_count": " 6"}, {"\ufeffName": "Zhao Changyan", "NameChn": "趙昌言", "Sex": "M", "IndexYear": " 1004", "AddrID": " 100115", "AddrName": "Xiaoyi", "AddrChn": "孝義", "X": " 111.782768", "Y": " 37.143234", "xy_count": " 1"}, {"\ufeffName": "Zhao Zhen", "NameChn": "趙稹", "Sex": "M", "IndexYear": " 1022", "AddrID": " 11268", "AddrName": "Shanfu", "AddrChn": "單父", "X": " 116.079254", "Y": " 34.797901", "xy_count": " 1"}] -------------------------------------------------------------------------------- /src/frontend/src/assets/lang/en.js: -------------------------------------------------------------------------------- 1 | /* 2 | 命名规则:第一级索引的名字跟组件导出的名字保持一致 3 | 如 navbarTop 4 | */ 5 | module.exports = { 6 | navbarTop: { 7 | title: "CBDB Web Query System", 8 | help: "Help", 9 | report: "Report", 10 | lang: "Languages", 11 | user: { 12 | profile: "Profile", 13 | logOut: "Log Out" 14 | } 15 | }, 16 | navbarLeft: { 17 | home: "Home", 18 | entityQuery: "Entity Query", 19 | entityQueryByPerson: "Look up Data on an Individual", 20 | entityQueryByOffice: "Query Office Holding", 21 | entityQueryByEntry: "Query by Methods of Entry into Government", 22 | entityQueryByPlace: "Look At Place", 23 | relationQuery: "Relation Query", 24 | relationQueryByKinship: "By Kinship", 25 | relationQueryByAssociation: "By Association", 26 | relationQueryBySocialNetwork: "Social Network", 27 | relationQueryTwoPerson: "Two Persons Relation", 28 | visualization: "Visualization", 29 | visualizationBySNA: "SNA Visualization", 30 | visualizationByGIS: "GIS Visualization", 31 | visualizationByGraphs: "Graphs Visualization", 32 | statistics: "Statistics" 33 | }, 34 | home: { 35 | introTitle: "About CBDB", 36 | introText: 37 | "The China Biographical Database is a freely accessible relational database with biographical information about approximately 470,000 individuals as of May 2020, primarily from the 7th through 19th centuries. With both online and offline versions, the data is meant to be useful for statistical, social network, and spatial analysis as well as serving as a kind of biographical reference.", 38 | historyText: 39 | "CBDB originates with the work of Robert M. Hartwell (1932–1996). Professor Hartwell bequeathed his estate, including the first version of this database, to the Harvard-Yenching Institute which ceded its ownership.The development of CBDB is now a joint project of:Fairbank Center for Chinese Studies at Harvard University (費正清中國研究中心)Institute of History and Philology of Academia Sinica (中研院歷史語言研究所)Center for Research on Ancient Chinese History at Peking University (北京大學中國古代史研究中心)", 40 | introDetail: "For more information, please visit:", 41 | introTitleProject: "About the System", 42 | introTextProject: 43 | "The CBDB Online Query System is an open source system developed by the joint team of Digital Humanity Center at Peking University, Fairbank Center for Chinese Studies at Harvard University, and Academia Sinica in Taiwan. The project aims to enhance the user experience by providing easier access to the CBDB and a simpler way to use it.", 44 | helpFileIntro: "For usage of the system, please visit:", 45 | guide: "Guide", 46 | contribution1: 47 | "We welcome all contributions to CBDB Online Query System🥺. For more information, please visit our ", 48 | contribution2: 49 | " and join in the development of CBDB Online Query System🤗. ", 50 | githubRepo: "Github repository", 51 | contributors: "Contributors" 52 | }, 53 | selectPerson: { 54 | selectButton: "SELECT PERSON", 55 | personName: "Name", 56 | importPersonPlaceholder: "Choose a file or drop it here...", 57 | dropFileHere: "Drop file here...", 58 | browseText: "Browse", 59 | browserNotSupportFileReader: 60 | "Sorry, this component cannot work on your browser. You can select people from database instead,' but we strongly recommend you to change a browser", 61 | cannotParse: 62 | "Sorry, we cannot parse the file you upload. Please check whether the data format is correct.", 63 | warning: 64 | "Please upload the .json file generated by this application, otherwise we cannot parse." 65 | }, 66 | selectEntry: { 67 | selectButton: "SELECT ENTRY" 68 | }, 69 | selectOffice: { 70 | selectButton: "SELECT OFFICE", 71 | officeName: "Office Name" 72 | }, 73 | selectPlace: { 74 | selectButton: "SELECT PLACE" 75 | }, 76 | selectRelationship: { 77 | association: "Association Name", 78 | selectButton: "SELECT RELATIONSHIP" 79 | }, 80 | selectTime: { 81 | selectButton: "SELEC TIME" 82 | }, 83 | globalTerm: { 84 | //全局術語 85 | search: "Search", 86 | all: "All", 87 | date: "Date", 88 | time: "Time", 89 | place: "Place", 90 | person: "Person", 91 | office: "Office", 92 | entry: "Entry", 93 | association: "association", 94 | queryInput: "Query Input", 95 | alternativeInput: "Alternative Input", 96 | requiredInput: "Required Input", 97 | resultShow: "Results Show", 98 | startTime: "Start Time", 99 | endTime: "End Time", 100 | isIndexYear: "Use Index Year", 101 | import: "Import", 102 | indexYear: "Index Year", 103 | gen: "Gender", 104 | personId: "Person ID", 105 | mCircle: "Mourning Circle", 106 | notes: "Notes", 107 | fromYear: "From", 108 | toYear: "To", 109 | range: "Range", 110 | nh: "Reign Year", 111 | year: "(Year)", 112 | month: "(Month)", 113 | day: "(Day)", 114 | intercalary: "(Intercalary)", 115 | source: "Source", 116 | pages: "Pages", 117 | details: "Details", 118 | before: "Before", 119 | after: "After", 120 | during: "During", 121 | true: "True", 122 | false: "False", 123 | male: "Male", 124 | female: "Female", 125 | ganzhi: "Day(stem/branch)", 126 | deathAge: "Death Age", 127 | deathAgeRange: "Death Age Range", 128 | status: "Status", 129 | posessions: "Possesions", 130 | sequence: "Sequence", 131 | and: "And", 132 | invalidInput: "Your input is invalid, please check.", 133 | cnOrPy: "In Chinese or Pinyin", 134 | selectFromDb: "Select", 135 | custom: "Customization", 136 | parse: "Parse", 137 | none: "None", 138 | searchTimeLong: 139 | "The search may take a long time to return result, please sit back and relax" 140 | }, 141 | entityQueryByPerson: { 142 | personId: "Person ID", 143 | personIndexYear: "index Year", 144 | personNameCh: "Chinese Person Name", 145 | personNameEn: "English Person Name", 146 | checkAndSearch: "Check Your Query Condition", 147 | checkRemind: "Please check the query condition before your search.", 148 | result: { 149 | basicInfo: "Basic Information", 150 | biSurnameEn: "(Pinyin)", 151 | biSurnameCh: "Surname(Chinese)", 152 | biNameEn: "(Pinyin)", 153 | biNameCh: "Name(Chinese)", 154 | biNote: "Notes", 155 | birthDeath: "Birth Death Years", 156 | dynasty: "Dynasty", 157 | choronym: "Chorony", 158 | householdStatus: "Household Status", 159 | ethnicity: "Ethnicity", 160 | birthYear: "Birth Year", 161 | deathYear: "Death Year", 162 | address: "Address", 163 | placeName: "Place Name", 164 | placeType: "Place Type", 165 | placeSeq: "Sequence", 166 | placeIsMaternal: "Is Maternal", 167 | altName: "Alt.Name", 168 | altNameCh: "Chinese Alt.Name", 169 | altNameEn: "Pinyin Alt.Name", 170 | altNameType: "Type", 171 | entry: "Entry", 172 | entryPlace: "Entry Place", 173 | entryRank: "Entry Rank", 174 | entrySequence: "Entry Sequence", 175 | entryParentalStatus: "Parental Status", 176 | entryYear: "Entry Year", 177 | entryAge: "Age", 178 | postings: "Postings", 179 | postCategory: "Post Category", 180 | postType: "Post Type", 181 | assumedPost: "Assumed Post?", 182 | kinshipType: "Kinship Type", 183 | kinName: "Kin's Name", 184 | association: "Association", 185 | associationType: "Association Type", 186 | associate: "Associate", 187 | firstPostingNote: "First Posting Note", 188 | kinship: "Kinship", 189 | writingRole: "Role", 190 | writings: "Writings", 191 | otherPlaces: "other places" 192 | } 193 | }, 194 | entityQueryByEntry: { 195 | entryYear: "Entry Year", 196 | householdAddrOnly: "Household addr. only", 197 | entryAddrOnly: "Entry location addr. only", 198 | householdEntry: "Household & Entry location addr." 199 | }, 200 | relationQueryByKinship: { 201 | maxAncestorGen: "Max Ancestor Gen.", 202 | maxDescendGen: "Max Descend Gen.", 203 | maxCollaternalLinks: "Max Collaternal Links", 204 | maxMarriageLinks: "Max Marriage Links", 205 | maxLoop: "Max Loop", 206 | maxLoopInvalid: "Must be a postive interger less than 5" 207 | }, 208 | relationQueryBySocialNetwork: { 209 | includeKinship: "Include Kinship", 210 | maxNodeDistance: "Max Node Distance", 211 | maxLoop: "Max Loop" 212 | }, 213 | relationQueryByPlace: { 214 | locationType: "Location Type", 215 | individual: "Individual", 216 | entry: "Entry", 217 | association: "Association", 218 | officePosting: "Office Posting", 219 | institutional: "Institutional", 220 | kinship: "Kinship", 221 | associate: "Associate" 222 | }, 223 | visualization: { 224 | selectFromSystem: "Import from System", 225 | localUpload: "Import from Local Files" 226 | } 227 | }; 228 | -------------------------------------------------------------------------------- /src/frontend/src/assets/lang/zh-cmn-Hant.js: -------------------------------------------------------------------------------- 1 | /* 2 | 命名规则:第一级索引的名字跟组件导出的名字保持一致 3 | 如 navbarTop 4 | */ 5 | module.exports = { 6 | navbarTop: { 7 | title: "CBDB Web 查詢系統", 8 | help: "幫助", 9 | report: "報告", 10 | lang: "語言", 11 | user: { 12 | profile: "個人資料", 13 | logOut: "登出" 14 | } 15 | }, 16 | navbarLeft: { 17 | home: "首頁", 18 | entityQuery: "查詢人物", 19 | entityQueryByPerson: "查詢個人信息", 20 | entityQueryByPersonIntro: 21 | "選擇一個人物,查看其生卒年月、著作、任官經歷、人際關係等詳細信息", 22 | entityQueryByOffice: "按職官查询", 23 | entityQueryByOfficeIntro: 24 | "「查詢職官」不僅可以找到擔任特定官職的人, 還可以找到官僚系統中擔任較低(或較高級別)官職的群體。", 25 | entityQueryByEntry: "按入仕查询", 26 | entityQueryByEntryIntro: 27 | "「查詢入仕」可以找到在特定時段通過特定途 徑取得做官資格的群體。", 28 | entityQueryByPlace: "通過地區查詢", 29 | relationQuery: "查询人物關係", 30 | relationQueryByKinship: "通過親屬關係查詢", 31 | relationQueryByAssociation: "通過社會關係查詢", 32 | relationQueryBySocialNetwork: "查詢關係網絡", 33 | relationQueryTwoPerson: "查詢兩人間關係", 34 | visualization: "可视化", 35 | visualizationBySNA: "网络关系可视化", 36 | visualizationByGIS: "地理可视化", 37 | visualizationByGraphs: "图表可视化", 38 | statistics: "統計分析" 39 | }, 40 | home: { 41 | introTitle: "關於 CBDB", 42 | introText: 43 | "中國歷代人物傳記資料(或稱數據)庫係線上的關係型資料庫,其遠程目標在於系統性地收入中國歷史上所有重要的傳記資料,並將其內容毫無限制地、免費地公諸學術之用。截至 2020年5月為止,本資料庫共收錄約470,000人的傳記資料,這些人物主要出自七世紀至十九世紀,本資料庫現正致力於增錄更多唐代和明清的人物傳記資料。本資料庫除可作為人物傳記的一種參考資料外,亦冀可敷統計分析與空間分析之用。", 44 | historyText: 45 | "中國歷代人物傳記資料庫之始祖為郝若貝教授(Robert M. Hartwell)(1932 – 1996)。郝若貝教授將本資料庫初版及其他財產遺贈哈佛燕京學社。目前本資料庫的開發工作係由哈佛大學費正清中國研究中心、中央研究院歷史語言研究所及北京大學中國古代史研究中心三方合作進行。", 46 | introDetail: "欲了解更多資訊,請瀏覽:", 47 | introTitleProject: "關於本系統", 48 | introTextProject: 49 | "CBDB在線查詢系統建制計劃是一個開源項目。由北京大學數字人文研究中心、哈佛大學費正清中國研究中心CBDB項目組共同組成聯合團隊,並與台灣中研院進行合作,對CBDB在線系統進行重構。項目旨在通過提供更便捷的CBDB接入方式和更簡潔的操作方式,以增強用戶體驗。", 50 | helpFileIntro: "關於本系統的使用說明,請參照:", 51 | guide: "使用指南", 52 | contribution1: "我們歡迎諸位以各種方式完善CBDB在線查詢系統🥺。請訪問我們的", 53 | contribution2: "以獲得更多資訊,並加入到CBDB在線查詢系統的開發中🤗。", 54 | githubRepo: "Github 程式碼倉庫", 55 | contributors: "貢獻者" 56 | }, 57 | selectPerson: { 58 | selectButton: "選取人物", 59 | personName: "人物姓名", 60 | importPersonPlaceholder: "點此上載文檔或直接拖拽文檔到此處", 61 | dropFileHere: "拖拽文檔至此", 62 | browseText: "瀏覽", 63 | browserNotSupportFileReader: 64 | "抱歉,當前組件無法在您的瀏覽器上運作。您可以改用“從資料庫選取的方法,但我們更建議您換一個瀏覽器。”", 65 | cannotParse: "抱歉,無法解析您上載的文檔。請檢查資料格式是否正確", 66 | warning: "請上載本系統生成的.json文檔,否則無法解析" 67 | }, 68 | selectEntry: { 69 | selectButton: "選取入仕途徑" 70 | }, 71 | selectOffice: { 72 | selectButton: "選取官職", 73 | officeName: "官職名" 74 | }, 75 | selectPlace: { 76 | selectButton: "選取地點" 77 | }, 78 | selectRelationship: { 79 | association: "社會關係名", 80 | selectButton: "選取關係" 81 | }, 82 | selectTime: { 83 | selectButton: "選取時間" 84 | }, 85 | globalTerm: { 86 | //全局術語 87 | search: "檢索", 88 | all: "所有", 89 | date: "日期", 90 | time: "時間", 91 | place: "地點", 92 | person: "人物", 93 | office: "官職", 94 | entry: "入仕途徑", 95 | association: "社會關係", 96 | queryInput: "查詢式輸入", 97 | alternativeInput: "可選條件", 98 | requiredInput: "必選條件", 99 | resultShow: "結果展現", 100 | startTime: "開始時間", 101 | endTime: "結束時間", 102 | isIndexYear: "啟用指數年", 103 | import: "加載", 104 | indexYear: "指數年", 105 | gen: "性別", 106 | personId: "人物代碼", 107 | mCircle: "五服", 108 | notes: "注", 109 | fromYear: "始年", 110 | toYear: "終年", 111 | range: "範圍", 112 | nh: "年號", 113 | year: "年", 114 | month: "月", 115 | day: "日", 116 | intercalary: "閏", 117 | source: "出處", 118 | pages: "頁碼/條目", 119 | details: "詳情", 120 | before: "之前", 121 | after: "之後", 122 | during: "之間", 123 | true: "是", 124 | false: "否", 125 | male: "男", 126 | female: "女", 127 | ganzhi: "日(干支)", 128 | deathAge: "享年", 129 | deathAgeRange: "享年範圍", 130 | status: "社會地位", 131 | posessions: "財產", 132 | sequence: "次序", 133 | and: "和其他", 134 | invalidInput: "您的輸入不符合檢索要求,請檢查", 135 | cnOrPy: "可輸入漢字或拼音", 136 | selectFromDb: "從資料庫選取", 137 | custom: "自定義", 138 | parse: "解析", 139 | none: "無", 140 | searchTimeLong: "檢索時間可能較長,請您耐心等候" 141 | }, 142 | entityQueryByPerson: { 143 | personId: "人物代碼", 144 | personNameCh: "人名-中文", 145 | personNameEn: "人名-英文", 146 | personIndexYear: "指數年", 147 | checkAndSearch: "檢索條件確認", 148 | checkRemind: "請於檢索前確認要查詢的人物信息", 149 | result: { 150 | basicInfo: "人物基本信息", 151 | biSurnameEn: "(Pinyin)", 152 | biSurnameCh: "姓(中文)", 153 | biNameEn: "(Pinyin)", 154 | biNameCh: "名(中文)", 155 | biNote: "注", 156 | birthDeath: "生卒年月", 157 | dynasty: "朝代", 158 | choronym: "郡望", 159 | householdStatus: "戶籍狀態", 160 | ethnicity: "種族", 161 | birthYear: "生年", 162 | deathYear: "卒年", 163 | earliestYear: "最早在世年", 164 | latestYear: "最晚在世年", 165 | address: "地址", 166 | placeName: "地名", 167 | placeType: "地址類別", 168 | placeSeq: "遷徙次序", 169 | placeIsMaternal: "娘家地址", 170 | altName: "別名", 171 | altNameCh: "別名漢字", 172 | altNameEn: "別名拼音", 173 | altNameType: "別名類型", 174 | entry: "入仕信息", 175 | entryPlace: "入仕地點", 176 | entryRank: "科的名次", 177 | entrySequence: "入仕順序", 178 | entryParentalStatus: "雙親地位", 179 | entryYear: "入仕年份", 180 | entryAge: "入仕年齡", 181 | postings: "官職", 182 | kinshipType: "親屬關係類別", 183 | kinName: "親戚姓名", 184 | associationType: "社會關係類別", 185 | associate: "社會關係人", 186 | firstPostingNote: "釋褐官註", 187 | kinship: "親屬關係", 188 | writingRole: "角色", 189 | writings: "著述", 190 | otherPlaces: "個地點", 191 | association: "社會關係" 192 | } 193 | }, 194 | entityQueryByEntry: { 195 | entryYear: "入仕年", 196 | householdAddrOnly: "僅戶籍地點", 197 | entryAddrOnly: "僅入仕地點", 198 | householdEntry: "戶籍地點和入仕地點" 199 | }, 200 | relationQueryByKinship: { 201 | maxAncestorGen: "最大祖先距離(代)", 202 | maxDescendGen: "最大後代距離(代)", 203 | maxCollaternalLinks: "最大同輩距離(代)", 204 | maxMarriageLinks: "最大姻親距離(代)", 205 | maxLoop: "最大循環次數", 206 | maxLoopInvalid: "需為一個小於5的正整數" 207 | }, 208 | relationQueryBySocialNetwork: { 209 | includeKinship: "包含親屬關係", 210 | maxNodeDistance: "距離限制", 211 | maxLoop: "循環數限制" 212 | }, 213 | relationQueryByPlace: { 214 | locationType: "地點類型", 215 | individual: "人", 216 | entry: "入仕", 217 | association: "社會關係", 218 | officePosting: "職官", 219 | institutional: "社交機構", 220 | kinship: "親屬", 221 | associate: "社會關係的人" 222 | }, 223 | visualization: { 224 | selectFromSystem: "從系統加載", 225 | localUpload: "從本地加載" 226 | } 227 | }; 228 | -------------------------------------------------------------------------------- /src/frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/frontend/src/assets/logo.png -------------------------------------------------------------------------------- /src/frontend/src/assets/relationData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "1", 4 | "ObjectName": "社會關係(籠統)", 5 | "children": [ 6 | { 7 | "Id": "0101", 8 | "ObjectName": "社會關係(籠統)" 9 | }, 10 | { 11 | "Id": "0102", 12 | "ObjectName": "同為⋯⋯之成員" 13 | }, 14 | { 15 | "Id": "0103", 16 | "ObjectName": "社會交際" 17 | } 18 | ] 19 | }, 20 | { 21 | "Id": "02", 22 | "ObjectName": "學術關係類", 23 | "children": [ 24 | { 25 | "Id": "0202", 26 | "ObjectName": "師生關係" 27 | }, 28 | { 29 | "Id": "0203", 30 | "ObjectName": "學術交往" 31 | }, 32 | { 33 | "Id": "0204", 34 | "ObjectName": "學術主題相近" 35 | }, 36 | { 37 | "Id":"0205", 38 | "ObjectName":"同為⋯⋯之成員" 39 | }, 40 | { 41 | "Id":"0206", 42 | "ObjectName":"學術襄助" 43 | }, 44 | { 45 | "Id":"0207", 46 | "ObjectName":"文學藝術交往" 47 | }, 48 | { 49 | "Id":"0208", 50 | "ObjectName":"學術攻訐" 51 | } 52 | ] 53 | }, 54 | { 55 | "Id":"03", 56 | "ObjectName":"朋友關係類", 57 | "children":[ 58 | { 59 | "Id":14, 60 | "ObjectName":"朋友關係(籠統)" 61 | } 62 | ] 63 | }, 64 | { 65 | "Id":"04", 66 | "ObjectName":"政治關係類", 67 | "children":[ 68 | { 69 | "Id":"0401", 70 | "ObjectName":"政治關係(籠統)" 71 | }, 72 | { 73 | "Id":"0402", 74 | "ObjectName":"官場關係(平級)" 75 | }, 76 | { 77 | "Id":"0403", 78 | "ObjectName":"官場關係(下屬)" 79 | }, 80 | { 81 | "Id":"0404", 82 | "ObjectName":"官場關係(上司)" 83 | }, 84 | { 85 | "Id":"0405", 86 | "ObjectName":"政治奥援" 87 | }, 88 | { 89 | "Id":"0406", 90 | "ObjectName":"薦舉保任" 91 | }, 92 | { 93 | "Id":"0407", 94 | "ObjectName":"政治對抗" 95 | } 96 | ] 97 | }, 98 | { 99 | "Id":"05", 100 | "ObjectName":"著述關係類", 101 | "children":[ 102 | { 103 | "Id":"0501", 104 | "ObjectName":"著述關係(籠統)" 105 | }, 106 | { 107 | "Id":"0502", 108 | "ObjectName":"記詠文字" 109 | }, 110 | { 111 | "Id":"0503", 112 | "ObjectName":"墓誌文字" 113 | }, 114 | { 115 | "Id":"0504", 116 | "ObjectName":"序跋文字" 117 | }, 118 | { 119 | "Id":"0505", 120 | "ObjectName":"禮儀文字" 121 | }, 122 | { 123 | "Id":"0506", 124 | "ObjectName":"传记文字" 125 | }, 126 | { 127 | "Id":"0507", 128 | "ObjectName":"論說文字" 129 | }, 130 | { 131 | "Id":"0508", 132 | "ObjectName":"箴銘文字" 133 | }, 134 | { 135 | "Id":"0509", 136 | "ObjectName":"書札文字" 137 | }, 138 | { 139 | "Id":"0510", 140 | "ObjectName":"應酬文字" 141 | } 142 | ] 143 | }, 144 | { 145 | "Id":"06", 146 | "ObjectName":"軍事關係類", 147 | "children":[ 148 | { 149 | "Id":"0601", 150 | "ObjectName":"軍事關係(籠統)" 151 | }, 152 | { 153 | "Id":"0602", 154 | "ObjectName":"軍事支持" 155 | }, 156 | { 157 | "Id":"0603", 158 | "ObjectName":"軍事對抗" 159 | } 160 | ] 161 | }, 162 | { 163 | "Id":"07", 164 | "ObjectName":"醫療關係類", 165 | "children":[ 166 | { 167 | "Id":"0701", 168 | "ObjectName":"醫療關係(籠統)" 169 | } 170 | ] 171 | }, 172 | { 173 | "Id":"08", 174 | "ObjectName":"宗教關係類", 175 | "children":[ 176 | { 177 | "Id":"0801", 178 | "ObjectName":"宗教關係(籠統)" 179 | } 180 | ] 181 | }, 182 | { 183 | "Id":"09", 184 | "ObjectName":"家庭關係類", 185 | "children":[ 186 | { 187 | "Id":"0901", 188 | "ObjectName":"家庭關係(籠統)" 189 | } 190 | ] 191 | }, 192 | { 193 | "Id":"10", 194 | "ObjectName":"財務關係類", 195 | "children":[ 196 | { 197 | "Id":"1001", 198 | "ObjectName":"財務關係(籠統)" 199 | } 200 | ] 201 | } 202 | ] 203 | -------------------------------------------------------------------------------- /src/frontend/src/assets/relationDataNetwork.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Id": "02", 4 | "ObjectName": "學術關係類" 5 | }, 6 | { 7 | "Id":"03", 8 | "ObjectName":"朋友關係類" 9 | }, 10 | { 11 | "Id":"04", 12 | "ObjectName":"政治關係類" 13 | }, 14 | { 15 | "Id":"05", 16 | "ObjectName":"著述關係類" 17 | }, 18 | { 19 | "Id":"06", 20 | "ObjectName":"軍事關係類" 21 | }, 22 | { 23 | "Id":"07", 24 | "ObjectName":"醫療關係類" 25 | }, 26 | { 27 | "Id":"08", 28 | "ObjectName":"宗教關係類" 29 | }, 30 | { 31 | "Id":"09", 32 | "ObjectName":"家庭關係類" 33 | }, 34 | { 35 | "Id":"10", 36 | "ObjectName":"財務關係類" 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /src/frontend/src/components/README.md: -------------------------------------------------------------------------------- 1 | # Project Structure 2 | ``` 3 | . 4 | ├── README.md 5 | ├── global 6 | │   ├── nav-bottom.vue 7 | │   ├── nav-left.vue 8 | │   └── nav-top.vue 9 | ├── treeTable 10 | │   ├── tree-item.vue 11 | │   └── tree-table.vue 12 | ├── utility 13 | │   ├── import-place.vue 14 | │   ├── query-result.vue 15 | │   ├── select-entry.vue 16 | │   ├── select-office.vue 17 | │   ├── select-person.vue 18 | │   ├── select-place.vue 19 | │   ├── select-relationship.vue 20 | │   ├── select-time.vue 21 | │   ├── show-source.vue 22 | │   ├── show-year.vue 23 | │   ├── utility-functions.js 24 | │   └── view-selected.vue 25 | └── views 26 | ├── home.vue 27 | ├── q-e-byEntry.vue 28 | ├── q-e-byOffice.vue 29 | ├── q-e-byPerson-test.vue 30 | ├── q-e-byPerson.vue 31 | ├── q-r-byAssociation.vue 32 | ├── q-r-byKinship.vue 33 | ├── q-r-byPlace.vue 34 | ├── q-r-bySocialNetwork.vue 35 | ├── q-r-twoPerson.vue 36 | └── sna.vue 37 | ``` -------------------------------------------------------------------------------- /src/frontend/src/components/global/nav-bottom.vue: -------------------------------------------------------------------------------- 1 | 14 | 22 | -------------------------------------------------------------------------------- /src/frontend/src/components/global/nav-left.vue: -------------------------------------------------------------------------------- 1 | 148 | 149 | 172 | 198 | -------------------------------------------------------------------------------- /src/frontend/src/components/global/nav-top.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 62 | 63 | 82 | -------------------------------------------------------------------------------- /src/frontend/src/components/treeTable/tree-item.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 126 | -------------------------------------------------------------------------------- /src/frontend/src/components/treeTable/tree-table.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 115 | 116 | 409 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/import-place.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 293 | 294 | 300 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/query-result.vue: -------------------------------------------------------------------------------- 1 | 84 | 85 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-entry.vue: -------------------------------------------------------------------------------- 1 | 133 | 134 | 250 | 251 | 257 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-office.vue: -------------------------------------------------------------------------------- 1 | 141 | 142 | 275 | 276 | 282 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-person.vue: -------------------------------------------------------------------------------- 1 | 247 | 248 | 400 | 401 | 408 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-place.vue: -------------------------------------------------------------------------------- 1 | 147 | 148 | 342 | 343 | 349 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-relation-network.vue: -------------------------------------------------------------------------------- 1 | 93 | 94 | 183 | 184 | 190 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/select-relationship.vue: -------------------------------------------------------------------------------- 1 | 123 | 124 | 225 | 226 | 232 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/show-source.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 31 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/show-year.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 112 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/utility-functions.js: -------------------------------------------------------------------------------- 1 | //判斷輸入欄是否為空 2 | function isNull(i) { 3 | return i === undefined || i === null || i === ""; 4 | } 5 | 6 | //字符串首字母大写 7 | function capitalizeFirst(s) { 8 | if (s === null || s === undefined || s === "") return ""; 9 | return s.substring(0, 1).toUpperCase() + s.substring(1); 10 | } 11 | 12 | //判斷年代輸入是否有效 13 | /** 14 | * @param {String} 指數年是startTime還是endTime 15 | * @return {Boolean} null or false 16 | **/ 17 | function yearValidation(idx) { 18 | const stReg = /.*startTime/i; 19 | const etReg = /.*endTime/i; 20 | //如果輸入為空,視為有效 21 | if (isNull(this.formData[idx])) return null; 22 | let year = /^\d{1,4}$/; 23 | //startTime 一欄只要輸入符合有且僅有1~4位數字的規則,視為有效 24 | //console.log(year.test(this.formData[idx])) 25 | if (stReg.test(idx)) return year.test(this.formData[idx]) ? null : false; 26 | else if (etReg.test(idx)) { 27 | //先判斷 endTime 一欄是否符合有且僅有1~4位數字的規則,如果不符合,視為無效 28 | if (year.test(this.formData[idx])) { 29 | /* 30 | //如果 endTime 有輸入數字,同時 startTime 也有輸入數字,判斷 endTime 的數字是否大於 startTime 的數字 31 | //如果小於,則視為無效 32 | //TO DO 33 | if(this.validation('startTime') == null && this.isNull('startTime')==false){ 34 | let st = parseInt(this.formData['startTime'], 10); 35 | let et = parseInt(this.formData['endTime'], 10); 36 | return et>st?null:false; 37 | } 38 | else return null; 39 | */ 40 | return null; 41 | } else return false; 42 | } 43 | } 44 | 45 | /** 46 | * @param {Number} //maxLoop 47 | * @return {Boolean} //null or false 48 | **/ 49 | function maxLoopValidation(num, maxVal = 5) { 50 | let reg = /^\d$/; 51 | if (reg.test(num) == false) return false; 52 | else { 53 | return num < maxVal ? null : false; 54 | } 55 | } 56 | 57 | //各種getter:用於將條件選取組件中選取到的結果轉移到主頁面中 58 | /** 59 | * @param {String} 要獲取的表格類型名称 60 | * @return {Function} 对应表格类型的getter 61 | **/ 62 | function getterBuilder(type) { 63 | let id = { 64 | peoplePlace: "pId", 65 | officePlace: "pId", 66 | office: "pId", 67 | entry: "eId", 68 | relation: "aId", 69 | person: "personId" 70 | }; 71 | /** 72 | * @param {Array,VueObject} 表格数据和vue实例 73 | * @return {Function} 对应表格类型的getter 74 | **/ 75 | //闭包 76 | return function(d, vm) { 77 | if (vm[type + "Field"].length === 0) vm[type + "Field"] = d["fields"]; 78 | let formData = vm["get" + capitalizeFirst(type) + "TableId"]; 79 | //console.log(formData) 80 | let after = d["items"].filter(i => formData.indexOf(i[id[type]]) === -1); 81 | after.forEach(i => { 82 | vm[type + "Table"].push(i); 83 | }); 84 | }; 85 | } 86 | 87 | var personGetter = getterBuilder("person"); 88 | var peoplePlaceGetter = getterBuilder("peoplePlace"); 89 | var officeGetter = getterBuilder("office"); 90 | var officePlaceGetter = getterBuilder("officePlace"); 91 | var entryGetter = getterBuilder("entry"); 92 | var relationGetter = getterBuilder("relation"); 93 | 94 | /** 95 | * @param {String,VueObject} 96 | * api名称和vue实例 97 | **/ 98 | function handleTableScroll(apiType, vm) { 99 | let st = vm.$refs.selectableTable; 100 | if ( 101 | st.$el.scrollHeight - st.$el.scrollTop <= st.$el.clientHeight && 102 | vm.isBusy === false 103 | ) 104 | if ( 105 | vm.result.end !== undefined && 106 | vm.result.total !== undefined && 107 | vm.result.end < vm.result.total 108 | ) { 109 | vm.isBusy = true; 110 | vm.isBusyLoad = true; 111 | vm.axios 112 | .get(vm.result.query + `&start=${vm.result.end + 1}&list=100`) 113 | .then( 114 | r => { 115 | //console.log(r.data.data) 116 | r.data.data.forEach(i => { 117 | vm.items.push(i); 118 | }); 119 | vm.result.start = parseInt(r.data.start); 120 | vm.result.end = parseInt(r.data.end); 121 | //vm.result.total = parseInt(r.data.total) 122 | }, 123 | e => { 124 | alert("Sorry, something went wrong..."); 125 | } 126 | ) 127 | .then(() => { 128 | vm.isBusy = false; 129 | vm.isBusyLoad = false; 130 | }); 131 | } 132 | } 133 | 134 | /** 135 | * @param {String,String,VueObject} 136 | * api名称 作为查询依据的id 和vue实例 137 | **/ 138 | function getListById(apiType, id, vm) { 139 | //console.log(id) 140 | let idType = apiType === "get_assoc" ? "aType" : "id"; 141 | if (vm.isBusy === false) { 142 | vm.isBusy = true; 143 | let query = `${vm.$store.state.global.apiAddress}${apiType}?${idType}=${id}`; 144 | //console.log(query) 145 | vm.axios.get(`${query}&start=1&list=100`).then( 146 | r => { 147 | //console.log(r.data) 148 | vm.items = r.data.data; 149 | vm.result.query = query; 150 | vm.result.start = parseInt(r.data.start); 151 | vm.result.end = parseInt(r.data.end); 152 | vm.result.total = parseInt(r.data.total); 153 | vm.$refs.selectableTable.$el.scrollTop = 0; //弹回最上方 154 | vm.isBusy = false; 155 | }, 156 | e => { 157 | alert("Network Error..."); 158 | vm.isBusy = false; 159 | } 160 | ); 161 | } 162 | } 163 | 164 | function getListByName(apiType, arg, vm) { 165 | /* 166 | arg[0]:name 167 | arg[1]:accurate 168 | arg[2]:startTime 169 | arg[3]:endTime 170 | */ 171 | //console.log(arg[0]) 172 | let dic = { 173 | place_list: "name", 174 | entry_list_by_name: "eName", 175 | office_list_by_name: "pName", 176 | find_assoc: "aName" 177 | }; 178 | if (vm.isBusy === false) { 179 | vm.isBusy = true; 180 | vm.isBusyFind = true; 181 | let query = `${vm.$store.state.global.apiAddress}${apiType}?${dic[apiType]}=${arg[0]}`; 182 | if (arg.length >= 1) query += `&accurate=${arg[1]}`; 183 | if (apiType === "place_list") 184 | query += `&startTime=${arg[2]}&endTime=${arg[3]}`; 185 | vm.axios 186 | .get(`${query}&start=1&list=100`) 187 | .then( 188 | r => { 189 | //console.log(r.data) 190 | vm.items = r.data.data; 191 | vm.result.query = query; 192 | vm.result.start = parseInt(r.data.start); 193 | vm.result.end = parseInt(r.data.end); 194 | vm.result.total = parseInt(r.data.total); 195 | vm.$refs.selectableTable.$el.scrollTop = 0; //弹回最上方 196 | }, 197 | e => { 198 | alert("Network Error..."); 199 | } 200 | ) 201 | .finally(() => { 202 | vm.isBusy = false; 203 | vm.isBusyFind = false; 204 | }); 205 | } 206 | } 207 | 208 | /** 209 | * @return {Array} 返回親屬關係的選項 210 | **/ 211 | function kinshipOptions() { 212 | return [ 213 | { 214 | text: this.$t("globalTerm.custom"), 215 | value: 0 216 | }, 217 | { 218 | text: this.$t("globalTerm.mCircle"), 219 | value: 1 220 | } 221 | ]; 222 | } 223 | 224 | function clearResultTable(vm) { 225 | vm.items.splice(0, vm.items.length); 226 | for (let prop in vm.result) { 227 | vm.result[prop] = undefined; 228 | } 229 | } 230 | 231 | function returnRelation(code, vm) { 232 | switch (code) { 233 | case "02": { 234 | vm.items = [ 235 | { 236 | aId: "0202", 237 | aNameChn: "師生關係" 238 | }, 239 | { 240 | aId: "0203", 241 | aNameChn: "學術交往" 242 | }, 243 | { 244 | aId: "0204", 245 | aNameChn: "學術主題相近" 246 | }, 247 | { 248 | aId: "0205", 249 | aNameChn: "同為成員" 250 | }, 251 | { 252 | aId: "0206", 253 | aNameChn: "學術襄助" 254 | }, 255 | { 256 | aId: "0207", 257 | aNameChn: "文學藝術交往" 258 | }, 259 | { 260 | aId: "0208", 261 | aNameChn: "學術攻訐" 262 | } 263 | ]; 264 | break; 265 | } 266 | case "03": { 267 | vm.items = [ 268 | { 269 | aId: "0301", 270 | aNameChn: "朋友關係" 271 | } 272 | ]; 273 | break; 274 | } 275 | case "04": { 276 | vm.items = [ 277 | { 278 | aId: "0402", 279 | aNameChn: "官場關係(平級)" 280 | }, 281 | { 282 | aId: "0403", 283 | aNameChn: "官場關係(下屬)" 284 | }, 285 | { 286 | aId: "0404", 287 | aNameChn: "官場關係(上司)" 288 | }, 289 | { 290 | aId: "0405", 291 | aNameChn: "政治奥援" 292 | }, 293 | { 294 | aId: "0406", 295 | aNameChn: "薦舉保任" 296 | }, 297 | { 298 | aId: "0407", 299 | aNameChn: "政治對抗" 300 | } 301 | ]; 302 | break; 303 | } 304 | case "05": { 305 | vm.items = [ 306 | { 307 | aId: "0502", 308 | aNameChn: "記詠文字" 309 | }, 310 | { 311 | aId: "0503", 312 | aNameChn: "墓誌文字" 313 | }, 314 | { 315 | aId: "0504", 316 | aNameChn: "序跋文字" 317 | }, 318 | { 319 | aId: "0505", 320 | aNameChn: "禮儀文字" 321 | }, 322 | { 323 | aId: "0506", 324 | aNameChn: "传记文字" 325 | }, 326 | { 327 | aId: "0507", 328 | aNameChn: "論說文字" 329 | }, 330 | { 331 | aId: "0508", 332 | aNameChn: "箴銘文字" 333 | }, 334 | { 335 | aId: "0509", 336 | aNameChn: "書札文字" 337 | }, 338 | { 339 | aId: "0510", 340 | aNameChn: "應酬文字" 341 | } 342 | ]; 343 | break; 344 | } 345 | case "06": { 346 | vm.items = [ 347 | { 348 | aId: "0602", 349 | aNameChn: "軍事支持" 350 | }, 351 | { 352 | aId: "0603", 353 | aNameChn: "軍事對抗" 354 | } 355 | ]; 356 | break; 357 | } 358 | case "07": { 359 | vm.items = [ 360 | { 361 | aId: "0701", 362 | aNameChn: "醫療關係" 363 | } 364 | ]; 365 | break; 366 | } 367 | case "08": { 368 | vm.items = [ 369 | { 370 | aId: "0801", 371 | aNameChn: "宗教關係" 372 | } 373 | ]; 374 | break; 375 | } 376 | case "09": { 377 | vm.items = [ 378 | { 379 | aId: "0901", 380 | aNameChn: "家庭關係" 381 | } 382 | ]; 383 | break; 384 | } 385 | case "10": { 386 | vm.items = [ 387 | { 388 | aId: "1001", 389 | aNameChn: "財務關係" 390 | } 391 | ]; 392 | break; 393 | } 394 | } 395 | } 396 | 397 | export { 398 | isNull, 399 | capitalizeFirst, 400 | yearValidation, 401 | peoplePlaceGetter, 402 | officePlaceGetter, 403 | officeGetter, 404 | entryGetter, 405 | personGetter, 406 | relationGetter, 407 | handleTableScroll as appendListById, 408 | getListById, 409 | getListByName, 410 | kinshipOptions, 411 | clearResultTable, 412 | returnRelation, 413 | maxLoopValidation 414 | }; 415 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/view-selected.vue: -------------------------------------------------------------------------------- 1 | 90 | 91 | 140 | -------------------------------------------------------------------------------- /src/frontend/src/components/utility/warning-text.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 30 | -------------------------------------------------------------------------------- /src/frontend/src/components/views/home.vue: -------------------------------------------------------------------------------- 1 | 147 | 148 | 153 | 154 | 155 | 188 | -------------------------------------------------------------------------------- /src/frontend/src/components/views/q-e-byPerson.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 78 | 79 | 80 | 105 | -------------------------------------------------------------------------------- /src/frontend/src/components/views/q-r-twoPerson.vue: -------------------------------------------------------------------------------- 1 | 154 | 155 | 256 | 257 | 258 | 283 | -------------------------------------------------------------------------------- /src/frontend/src/components/views/sna.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/frontend/src/components/views/sna.vue -------------------------------------------------------------------------------- /src/frontend/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from "vue"; 4 | import App from "./App"; 5 | //I18n 用于處理語言切換 6 | import VueI18n from "vue-i18n"; 7 | Vue.use(VueI18n); 8 | //router 用于处理路由 9 | import router from "./router"; 10 | //store 用于處理全局變數 11 | import store from "./store"; 12 | import { BootstrapVue, BootstrapVueIcons } from "bootstrap-vue"; 13 | Vue.use(BootstrapVue); 14 | //引入 bootstrap-vue 的 css 檔 15 | import "bootstrap/dist/css/bootstrap.css"; 16 | import "bootstrap-vue/dist/bootstrap-vue.css"; 17 | import "bootstrap-vue/dist/bootstrap-vue-icons.min.css"; 18 | Vue.use(BootstrapVueIcons); 19 | //引入 axios 和 vue-axios 20 | import axios from "axios"; 21 | import VueAxios from "vue-axios"; 22 | 23 | Vue.use(VueAxios, axios); 24 | 25 | Vue.config.productionTip = false; 26 | //初始化語言設定 27 | let langConfig = { 28 | locale: "zh-cmn-Hant", 29 | messages: { 30 | "zh-cmn-Hant": require("./assets/lang/zh-cmn-Hant"), 31 | en: require("./assets/lang/en") 32 | } 33 | }; 34 | //檢查本地是否有語言設定 35 | if (localStorage.lang) { 36 | langConfig.locale = localStorage.lang; 37 | } 38 | const i18n = new VueI18n(langConfig); 39 | 40 | /* eslint-disable no-new */ 41 | new Vue({ 42 | el: "#app", 43 | i18n, 44 | router, 45 | store, 46 | components: { App }, 47 | template: "" 48 | }); 49 | -------------------------------------------------------------------------------- /src/frontend/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Router from "vue-router"; 3 | const Home = () => import("@/components/views/home"); 4 | //import Home from '@/components/views/home' 5 | //const entityQueryByPerson = () => import('@/components/views/q-e-byPerson') 6 | import entityQueryByPerson from "@/components/views/q-e-byPerson"; 7 | const entityQueryByEntry = () => import("@/components/views/q-e-byEntry"); 8 | //import entityQueryByEntry from '@/components/views/q-e-byEntry' 9 | const entityQueryByOffice = () => import("@/components/views/q-e-byOffice"); 10 | //import entityQueryByOffice from '@/components/views/q-e-byOffice' 11 | //const relationQueryByPlace = () => import('@/components/views/q-r-byPlace') 12 | import relationQueryByPlace from "@/components/views/q-r-byPlace"; 13 | //const relationQueryByKinship = () => import('@/components/views/q-r-byKinship') 14 | import relationQueryByKinship from "@/components/views/q-r-byKinship"; 15 | const relationQueryByAssociation = () => 16 | import("@/components/views/q-r-byAssociation"); 17 | //import relationQueryByAssociation from '@/components/views/q-r-byAssociation' 18 | const relationQueryBySocialNetwork = () => 19 | import("@/components/views/q-r-bySocialNetwork"); 20 | //import relationQueryBySocialNetwork from '@/components/views/q-r-bySocialNetwork' 21 | //const relationQueryTwoPerson = () => import('@/components/views/q-r-twoPerson') 22 | import relationQueryTwoPerson from "@/components/views/q-e-byPerson-test"; 23 | //import visualizationBySNA from '@/components/views/vis-bySNA' 24 | Vue.use(Router); 25 | 26 | export default new Router({ 27 | routes: [ 28 | { 29 | path: "/index", 30 | name: "Index", 31 | component: Home 32 | }, 33 | { path: "/", redirect: { name: "Index" } }, 34 | { 35 | path: "/help", 36 | name: "Help" 37 | }, 38 | { 39 | path: "/q-entity/by-person", 40 | name: "Entity Query: By Person", 41 | component: entityQueryByPerson 42 | }, 43 | { 44 | path: "/q-entity/by-office", 45 | name: "Entity Query: By Office", 46 | component: entityQueryByOffice 47 | }, 48 | { 49 | path: "/q-entity/by-entry", 50 | name: "Entity Query: By Entry", 51 | component: entityQueryByEntry 52 | }, 53 | { 54 | path: "/q-relation/by-place", 55 | name: "Relation Query: By Place", 56 | component: relationQueryByPlace 57 | }, 58 | { 59 | path: "/q-relation/kinship", 60 | name: "Relation Query: By Kinship", 61 | component: relationQueryByKinship 62 | }, 63 | 64 | { 65 | path: "/q-relation/association", 66 | name: "Relation Query: By Association", 67 | component: relationQueryByAssociation 68 | }, 69 | { 70 | path: "/q-relation/by-social-network", 71 | name: "Relation Query: By Socialnetwork", 72 | component: relationQueryBySocialNetwork 73 | }, 74 | { 75 | path: "/q-relation/two-person", 76 | name: "Relation Query: Two Person", 77 | component: relationQueryTwoPerson 78 | } 79 | /* 80 | { 81 | path: '/visualization/SNA', 82 | name: 'Visualization: SNA', 83 | component: visualizationBySNA 84 | }, 85 | { 86 | path: '/visualization/GIS', 87 | name: 'Visualization: people', 88 | component: visualizationByPeople 89 | }, 90 | { 91 | path: '/visualization/Graphs', 92 | name: 'Visualization: Graphs', 93 | component: visualizationByGraphs 94 | }, 95 | */ 96 | ] 97 | }); 98 | -------------------------------------------------------------------------------- /src/frontend/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | 4 | Vue.use(Vuex); 5 | 6 | const moduleA = { 7 | state: { 8 | user: { 9 | uid: "114514", 10 | name: "北京大學" 11 | } 12 | }, 13 | mutations: {}, 14 | actions: {}, 15 | getters: {} 16 | }; 17 | 18 | const moduleB = { 19 | state: { 20 | serverAddress: "127.0.0.1", 21 | apiAddress: "https://input.cbdb.fas.harvard.edu/api/" 22 | //⬆️update: 2021.4 23 | //apiAddress: "http://47.114.119.106:8000/api/" 24 | //⬆️update: 2020.10 25 | //apiAddress:'http://162.105.134.121/api/' 26 | //apiAddress:'http://140.247.116.238:8888/api/' 27 | }, 28 | mutations: {}, 29 | actions: {}, 30 | getters: {} 31 | }; 32 | 33 | export default new Vuex.Store({ 34 | modules: { 35 | local: moduleA, 36 | global: moduleB 37 | } 38 | }); 39 | -------------------------------------------------------------------------------- /src/frontend/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cbdb-project/cbdb-online-query-app/9085030894273a6f45c735ddddb2da84f2e9d0f8/src/frontend/static/.gitkeep -------------------------------------------------------------------------------- /src/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cbdbweb.settings') 9 | try: 10 | from django.core.management import execute_from_command_line 11 | except ImportError as exc: 12 | raise ImportError( 13 | "Couldn't import Django. Are you sure it's installed and " 14 | "available on your PYTHONPATH environment variable? Did you " 15 | "forget to activate a virtual environment?" 16 | ) from exc 17 | execute_from_command_line(sys.argv) 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | -------------------------------------------------------------------------------- /src/requirements.txt: -------------------------------------------------------------------------------- 1 | #requirements.txt 2 | Django==3.1.2 3 | gunicorn==20.0.4 --------------------------------------------------------------------------------