├── #start-bert-linux.sh ├── #start-bert服务启动脚本.bat ├── #start-mongodb启动脚本.bat ├── .gitignore ├── Dockerfile.backend ├── Dockerfile.frontend ├── LICENSE ├── README.md ├── backend ├── __init__.py ├── app │ ├── __init__.py │ ├── case │ │ ├── caseSuite.py │ │ ├── testReport.py │ │ └── testingCase.py │ ├── host │ │ └── host.py │ ├── mail │ │ ├── mail.py │ │ └── mailSender.py │ ├── models │ │ ├── adminUser.py │ │ ├── caseSuite.py │ │ ├── cronTab.py │ │ ├── host.py │ │ ├── mail.py │ │ ├── mailSender.py │ │ ├── project.py │ │ ├── testReport.py │ │ └── testingCase.py │ ├── notice │ │ └── webhook.py │ ├── project │ │ └── project.py │ ├── timer │ │ └── cronTab.py │ └── user │ │ ├── adminUser.py │ │ └── user.py ├── config.py ├── createAdminUser.py ├── logs │ ├── .__log.lock │ └── log.log.2020-03-07 ├── requirements.txt ├── run.py ├── run.sh ├── testframe │ └── interfaceTest │ │ └── tester.py └── utils │ ├── __init__.py │ ├── common.py │ ├── cron │ ├── __init__.py │ ├── cronManager.py │ └── interfaceTestCron.py │ ├── log_config.py │ ├── mango.py │ ├── nlp │ ├── Nlper.py │ └── __init__.py │ └── sendReportEmail.py ├── deploy ├── dist ├── index.html └── static │ ├── css │ ├── app.5ba2ecb0d2a9faaae6de321adc514f91.css │ └── app.5ba2ecb0d2a9faaae6de321adc514f91.css.map │ ├── favicon.ico │ ├── fonts │ ├── element-icons.6f0a763.ttf │ ├── fontawesome-webfont.674f50d.eot │ ├── fontawesome-webfont.af7ae50.woff2 │ ├── fontawesome-webfont.b06871f.ttf │ ├── fontawesome-webfont.fee66e7.woff │ ├── icomoon.5fadf3a.woff │ ├── icomoon.aa6f949.ttf │ ├── icomoon.c440c59.eot │ ├── iconfont.824ae76.ttf │ └── iconfont.9465461.eot │ ├── img │ ├── Banner.df97073.jpg │ ├── fontawesome-webfont.912ec66.svg │ ├── hello.614f7c7.jpg │ ├── icomoon.513433b.svg │ ├── iconfont.3b1767f.svg │ ├── logo.e8aa977.jpg │ └── userphoto.9511e5e.jpg │ └── js │ ├── app.f3be4ad6cbc7d9c1ac8f.js │ ├── app.f3be4ad6cbc7d9c1ac8f.js.map │ ├── manifest.2ae2e69a05c33dfc65f8.js │ ├── manifest.2ae2e69a05c33dfc65f8.js.map │ ├── vendor.5f4553d2fa7e029bc778.js │ └── vendor.5f4553d2fa7e029bc778.js.map ├── frontend ├── .babelrc ├── .editorconfig ├── .gitignore ├── .postcssrc.js ├── 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 │ └── webpack.test.conf.js ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js ├── favicon.ico ├── index.html ├── package-lock.json ├── package.json ├── src │ ├── App.vue │ ├── api │ │ ├── caseSuite.js │ │ ├── common.js │ │ ├── cron.js │ │ ├── host.js │ │ ├── index.js │ │ ├── mail.js │ │ ├── mailSender.js │ │ ├── project.js │ │ ├── testCase.js │ │ ├── testReport.js │ │ └── user.js │ ├── assets │ │ ├── css │ │ │ ├── animate.min.css │ │ │ ├── element-#FF9E1B │ │ │ │ ├── alert.css │ │ │ │ ├── aside.css │ │ │ │ ├── autocomplete.css │ │ │ │ ├── badge.css │ │ │ │ ├── base.css │ │ │ │ ├── breadcrumb-item.css │ │ │ │ ├── breadcrumb.css │ │ │ │ ├── button-group.css │ │ │ │ ├── button.css │ │ │ │ ├── card.css │ │ │ │ ├── carousel-item.css │ │ │ │ ├── carousel.css │ │ │ │ ├── cascader.css │ │ │ │ ├── checkbox-button.css │ │ │ │ ├── checkbox-group.css │ │ │ │ ├── checkbox.css │ │ │ │ ├── col.css │ │ │ │ ├── collapse-item.css │ │ │ │ ├── collapse.css │ │ │ │ ├── color-picker.css │ │ │ │ ├── container.css │ │ │ │ ├── date-picker.css │ │ │ │ ├── dialog.css │ │ │ │ ├── display.css │ │ │ │ ├── dropdown-item.css │ │ │ │ ├── dropdown-menu.css │ │ │ │ ├── dropdown.css │ │ │ │ ├── fonts │ │ │ │ │ ├── element-icons.ttf │ │ │ │ │ └── element-icons.woff │ │ │ │ ├── footer.css │ │ │ │ ├── form-item.css │ │ │ │ ├── form.css │ │ │ │ ├── header.css │ │ │ │ ├── icon.css │ │ │ │ ├── index.css │ │ │ │ ├── input-number.css │ │ │ │ ├── input.css │ │ │ │ ├── loading.css │ │ │ │ ├── main.css │ │ │ │ ├── menu-item-group.css │ │ │ │ ├── menu-item.css │ │ │ │ ├── menu.css │ │ │ │ ├── message-box.css │ │ │ │ ├── message.css │ │ │ │ ├── notification.css │ │ │ │ ├── option-group.css │ │ │ │ ├── option.css │ │ │ │ ├── pagination.css │ │ │ │ ├── popover.css │ │ │ │ ├── popper.css │ │ │ │ ├── progress.css │ │ │ │ ├── radio-button.css │ │ │ │ ├── radio-group.css │ │ │ │ ├── radio.css │ │ │ │ ├── rate.css │ │ │ │ ├── reset.css │ │ │ │ ├── row.css │ │ │ │ ├── scrollbar.css │ │ │ │ ├── select-dropdown.css │ │ │ │ ├── select.css │ │ │ │ ├── slider.css │ │ │ │ ├── spinner.css │ │ │ │ ├── step.css │ │ │ │ ├── steps.css │ │ │ │ ├── submenu.css │ │ │ │ ├── switch.css │ │ │ │ ├── tab-pane.css │ │ │ │ ├── table-column.css │ │ │ │ ├── table.css │ │ │ │ ├── tabs.css │ │ │ │ ├── tag.css │ │ │ │ ├── time-picker.css │ │ │ │ ├── time-select.css │ │ │ │ ├── tooltip.css │ │ │ │ ├── transfer.css │ │ │ │ ├── tree.css │ │ │ │ └── upload.css │ │ │ ├── quill.snow.css │ │ │ └── reset.css │ │ ├── fonts │ │ │ ├── demo.css │ │ │ ├── demo_fontclass.html │ │ │ ├── demo_symbol.html │ │ │ ├── demo_unicode.html │ │ │ ├── icomoon.css │ │ │ ├── icomoon.eot │ │ │ ├── icomoon.svg │ │ │ ├── icomoon.ttf │ │ │ ├── icomoon.woff │ │ │ ├── iconfont.css │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.js │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ └── iconfont.woff │ │ ├── imgs │ │ │ ├── Banner.jpg │ │ │ ├── Banner2.jpg │ │ │ ├── assets │ │ │ │ ├── icon-no.svg │ │ │ │ ├── icon-yes.svg │ │ │ │ ├── member.png │ │ │ │ └── wx.jpg │ │ │ ├── favicon.ico │ │ │ ├── hello.jpg │ │ │ ├── i-am-strong.jpg │ │ │ ├── icon-no.svg │ │ │ ├── icon-yes.svg │ │ │ ├── logo.jpg │ │ │ ├── member.png │ │ │ ├── userphoto.jpg │ │ │ └── wx.jpg │ │ ├── js │ │ │ ├── dom.js │ │ │ └── util.js │ │ ├── scss │ │ │ ├── custom-el-var.scss │ │ │ └── dashboard-ojo-palette.scss │ │ └── svg │ │ │ └── loading.svg │ ├── main.js │ ├── router │ │ └── index.js │ ├── styles │ │ └── vars.scss │ ├── utils │ │ ├── cookie.js │ │ └── request.js │ ├── views │ │ ├── About.vue │ │ ├── Home.vue │ │ ├── Login.vue │ │ ├── More.vue │ │ ├── Project.vue │ │ ├── UITest.vue │ │ ├── common │ │ │ └── Header.vue │ │ └── interfaceTestProject │ │ │ ├── ProjectList.vue │ │ │ ├── ProjectReport.vue │ │ │ ├── api │ │ │ └── automation │ │ │ │ ├── AddCaseApi.vue │ │ │ │ ├── AutomationTest.vue │ │ │ │ ├── CaseApiList.vue │ │ │ │ ├── CaseSuiteList.vue │ │ │ │ ├── CronList.vue │ │ │ │ └── UpdateCaseApi.vue │ │ │ └── global │ │ │ ├── GlobalMail.vue │ │ │ └── Globalhost.vue │ └── vuex │ │ ├── actions.js │ │ ├── getters.js │ │ └── store.js ├── static │ ├── .gitkeep │ └── favicon.ico └── test │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── HelloWorld.spec.js ├── images ├── NLP模型启动成功输出.png ├── NLP部署失败.png ├── SeeYou平台思维导图.jpg ├── 不使用NLP模型方法1.png ├── 不使用NLP模型方法2.png ├── 定时任务配置.png ├── 控制台输出1.png ├── 控制台输出2.png ├── 操作界面展示.png ├── 数据导入展示.png ├── 测试报告展示.png └── 用例接口列表界面展示.jpg └── node_modules └── .package_versions.json /#start-bert-linux.sh: -------------------------------------------------------------------------------- 1 | rem kill the existing process 2 | ps -ef | grep 'bert-serving-start' | grep -v grep | awk '{print $2}' | xargs kill -s SIGINT 3 | 4 | rem run bert, need to enter the same root 5 | nohup bert-serving-start -model_dir ./chinese_L-12_H-768_A-12/ -num_worker=1 > bert.log 2>&1 & -------------------------------------------------------------------------------- /#start-bert服务启动脚本.bat: -------------------------------------------------------------------------------- 1 | rem 这个脚本放到与模型文件夹同级目录执行 2 | :: 需要安装 python 依赖包 3 | :: pip install tensorflow==1.14.0 -i https://pypi.tuna.tsinghua.edu.cn/simple 4 | :: pip install bert-serving-server==1.10.1 -i https://pypi.tuna.tsinghua.edu.cn/simple 5 | :: pip install bert-serving-client==1.10.1 -i https://pypi.tuna.tsinghua.edu.cn/simple 6 | 7 | bert-serving-start -model_dir ./chinese_L-12_H-768_A-12/ -num_worker=1 8 | 9 | pause -------------------------------------------------------------------------------- /#start-mongodb启动脚本.bat: -------------------------------------------------------------------------------- 1 | mongod --dbpath C:\MongoDB\data\db -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/.xml 2 | /my_venv/ 3 | # Created by .ignore support plugin (hsz.mobi) 4 | ### Python template 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | 9 | 10 | # Environments 11 | .env 12 | .venv 13 | env/ 14 | venv/ 15 | ENV/ 16 | env.bak/ 17 | venv.bak/ 18 | 19 | # Spyder project settings 20 | .spyderproject 21 | .spyproject 22 | 23 | # Rope project settings 24 | .ropeproject 25 | 26 | # mkdocs documentation 27 | /site 28 | 29 | # mypy 30 | .mypy_cache/ 31 | .dmypy.json 32 | dmypy.json 33 | 34 | # Pyre type checker 35 | .pyre/ 36 | 37 | .idea/ 38 | /data/sqlResult_1558435.csv 39 | /log/ 40 | /logs/ 41 | 42 | /my_venv/ 43 | /chinese_L-12_H-768_A-12.zip 44 | /chinese_L-12_H-768_A-12/ 45 | /mongodb-win32-x86_64-2012plus-4.2.3-signed.msi 46 | /frontend/node_modules/ 47 | /SeeYou-Linux 环境下 Docker 容器化部署.md 48 | /backend/logs/ 49 | /backend/temp.py 50 | -------------------------------------------------------------------------------- /Dockerfile.backend: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | USER root 4 | 5 | ENV WORKING_DIR /app/SeeYou-Platform 6 | 7 | ENV AUTOTEST_PLATFORM_ENV=${AUTOTEST_PLATFORM_ENV} 8 | ENV AUTOTEST_PLATFORM_MONGO_HOST=${AUTOTEST_PLATFORM_MONGO_HOST} 9 | ENV AUTOTEST_PLATFORM_MONGO_PORT=${AUTOTEST_PLATFORM_MONGO_PORT} 10 | ENV AUTOTEST_PLATFORM_MONGO_USERNAME=${AUTOTEST_PLATFORM_MONGO_USERNAME} 11 | ENV AUTOTEST_PLATFORM_MONGO_PASSWORD=${AUTOTEST_PLATFORM_MONGO_PASSWORD} 12 | ENV AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME=${AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME} 13 | 14 | COPY backend/utils /${WORKING_DIR}/backend/utils 15 | COPY backend/testframe /${WORKING_DIR}/backend/testframe 16 | 17 | COPY backend/requirements.txt /${WORKING_DIR}/backend/requirements.txt 18 | COPY backend/config.py /${WORKING_DIR}/backend/config.py 19 | COPY backend/app /${WORKING_DIR}/backend/app 20 | COPY backend/controllers /${WORKING_DIR}/backend/controllers 21 | COPY backend/models /${WORKING_DIR}/backend/models 22 | COPY backend/createAdminUser.py /${WORKING_DIR}/backend/createAdminUser.py 23 | COPY backend/run.py /${WORKING_DIR}/backend/run.py 24 | COPY ./dist /${WORKING_DIR}/dist 25 | 26 | RUN sh -c "echo 'Asia/Shanghai' > /etc/timezone" \ 27 | && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ 28 | && export AUTOTEST_PLATFORM_ENV=${AUTOTEST_PLATFORM_ENV}\ 29 | && export AUTOTEST_PLATFORM_MONGO_HOST=${AUTOTEST_PLATFORM_MONGO_HOST}\ 30 | && export AUTOTEST_PLATFORM_MONGO_PORT=${AUTOTEST_PLATFORM_MONGO_PORT}\ 31 | && export AUTOTEST_PLATFORM_NLP_SERVER_HOST=${AUTOTEST_PLATFORM_NLP_SERVER_HOST}\ 32 | && export AUTOTEST_PLATFORM_MONGO_USERNAME=${AUTOTEST_PLATFORM_MONGO_USERNAME}\ 33 | && export AUTOTEST_PLATFORM_MONGO_PASSWORD=${AUTOTEST_PLATFORM_MONGO_PASSWORD}\ 34 | && export AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME=${AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME}\ 35 | && pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple\ 36 | && cd ${WORKING_DIR}/backend\ 37 | && pip install -r ./requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 38 | 39 | ENTRYPOINT cd ${WORKING_DIR}/backend; python createAdminUser.py; python run.py; 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Dockerfile.frontend: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | 3 | USER root 4 | 5 | ENV WORKING_DIR /app/SeeYou-Platform 6 | # Provides cached layer for node_modules 7 | COPY frontend ${WORKING_DIR}/frontend 8 | 9 | RUN sh -c "echo 'Asia/Shanghai' > /etc/timezone" \ 10 | && cd ${WORKING_DIR}/frontend \ 11 | && npm install -g cnpm --registry=https://registry.npm.taobao.org \ 12 | && cnpm install phantomjs-prebuilt@2.1.16 --ignore-scripts \ 13 | && cnpm rebuild node-sass \ 14 | && cnpm install 15 | 16 | ENTRYPOINT cd ${WORKING_DIR}/frontend; npm run build 17 | -------------------------------------------------------------------------------- /backend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/__init__.py -------------------------------------------------------------------------------- /backend/app/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import sys 4 | 5 | sys.path.append('..') 6 | from flask import Flask 7 | from flask_cors import CORS 8 | from utils.mango import * 9 | from utils.log_config import logger 10 | from config import Config 11 | from flask_login import LoginManager 12 | from datetime import timedelta 13 | 14 | logger.info('Starting Flask Project, 初始化项目') 15 | app = Flask(__name__, 16 | static_folder="../../dist/static", 17 | template_folder="../../dist") 18 | 19 | _config = Config() 20 | app.config['SECRET_KEY'] = _config.get_secret_key() 21 | app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7) # 设置session的保存时间。 22 | login_manager = LoginManager() 23 | login_manager.init_app(app) 24 | cors = CORS(app, supports_credentials=True) 25 | 26 | conn, db = connect(_config.get_mongo_default_db_name(), 27 | ip=_config.get_mongo_host(), 28 | port=int(_config.get_mongo_port()), 29 | username=_config.get_mongo_username(), 30 | password=_config.get_mongo_password()) 31 | 32 | from utils.cron.cronManager import CronManager 33 | 34 | cron_manager = CronManager() 35 | cron_manager.start() 36 | 37 | # # 如果不需要bert NLP词向量模型 38 | # # 1. 将下面4行代码注释掉 39 | # # 2. 再将 ./backend/testframe/interfaceTest/tester.py 中的下列代码修改成 pass: 40 | # from utils.nlp.Nlper import Nlper 41 | # from bert_serving.client import BertClient 42 | # bert_ip = _config.get_nlp_server_host() if _config.get_nlp_server_host() else '127.0.0.1' 43 | # bert_client = BertClient(ip=bert_ip, timeout=10000) 44 | # nlper = Nlper(bert_client) 45 | 46 | 47 | # 导入mongo的ORM 48 | from app.models import adminUser, caseSuite, cronTab, host, mail, mailSender, project, testingCase, testReport 49 | # 导入路由 50 | from app.user import user 51 | from app.project import project 52 | from app.host import host 53 | from app.case import caseSuite, testingCase, testReport 54 | from app.mail import mail, mailSender 55 | from app.timer import cronTab 56 | from app.notice import webhook 57 | -------------------------------------------------------------------------------- /backend/app/case/caseSuite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.caseSuite import CaseSuite 6 | from app.models.testingCase import TestingCase 7 | from bson import ObjectId 8 | from utils import common 9 | import datetime 10 | from flask_login import login_required 11 | 12 | 13 | # 管理测试项目中的接口用例组信息 14 | @app.route('/api/project//caseSuiteList', methods=['GET', 'POST']) 15 | @login_required 16 | def case_suite_list(project_id): 17 | total_num, case_suites = common.get_total_num_and_arranged_data(CaseSuite, request.args, fuzzy_fields=['name']) 18 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': case_suites}}) 19 | 20 | 21 | @app.route('/api/project//addCaseSuite', methods=['POST']) 22 | @login_required 23 | def add_case_suite(project_id): 24 | request_data = request.get_json() 25 | request_data["status"] = True 26 | request_data["projectId"] = ObjectId(project_id) 27 | request_data["lastUpdateTime"] = datetime.datetime.utcnow() 28 | request_data["createAt"] = datetime.datetime.utcnow() 29 | 30 | try: 31 | filtered_data = CaseSuite.filter_field(request.get_json(), use_set_default=True) 32 | CaseSuite.insert(filtered_data) 33 | return jsonify({'status': 'ok', 'data': '添加成功'}) 34 | except BaseException as e: 35 | return jsonify({'status': 'failed', 'data': '添加失败 %s' % e}) 36 | 37 | 38 | @app.route('/api/project//caseSuiteList//copyCaseSuite', methods=['POST']) 39 | @login_required 40 | def copy_case_suite(project_id, case_suite_id): 41 | try: 42 | test_case_suite = list(CaseSuite.find({'_id': ObjectId(case_suite_id)}))[0] 43 | test_case_suite['originCaseSuiteIds'] = [] if 'originCaseSuiteIds' not in test_case_suite \ 44 | else test_case_suite['originCaseSuiteIds'] 45 | origin_case_suite_id_info = dict() 46 | origin_case_suite_id_info['_id'] = test_case_suite.pop('_id') if test_case_suite.get('_id') else None 47 | origin_case_suite_id_info['copiedAt'] = datetime.datetime.utcnow() 48 | test_case_suite['originCaseSuiteIds'].append(origin_case_suite_id_info) 49 | 50 | def get_new_create_at(create_at): 51 | time_quantity = 1 52 | while True: 53 | new_create_at = create_at - datetime.timedelta(milliseconds=time_quantity) 54 | find_result = list(CaseSuite.find({'createAt': new_create_at})) 55 | has_identical_create_at_case_suite = True if len(find_result) > 0 else False 56 | if not has_identical_create_at_case_suite: 57 | return new_create_at 58 | else: 59 | time_quantity += 1 60 | 61 | case_suite_create_at = test_case_suite.get('createAt') 62 | new_case_suite_create_at = get_new_create_at(case_suite_create_at) # 超前插入,精髓 63 | new_case_suite_suffix = '(复制版)' 64 | case_suite_name = test_case_suite.pop('name') + new_case_suite_suffix \ 65 | if 'name' in test_case_suite else '未知用例组' + new_case_suite_suffix 66 | test_case_suite['createAt'] = new_case_suite_create_at 67 | test_case_suite['name'] = case_suite_name 68 | new_case_suite_id = CaseSuite.insert(test_case_suite) 69 | 70 | query = {'caseSuiteId': ObjectId(case_suite_id), 'isDeleted': {'$ne': True}} 71 | test_cases = list(TestingCase.find(query)) 72 | 73 | def substitute_info(testing_case): 74 | testing_case['originTestingCaseIds'] = [] if 'originTestingCaseIds' not in testing_case \ 75 | else testing_case['originTestingCaseIds'] 76 | origin_testing_case_id_info = dict() 77 | origin_testing_case_id_info['_id'] = testing_case.pop('_id') if testing_case.get('_id') else None 78 | origin_testing_case_id_info['copiedAt'] = datetime.datetime.utcnow() 79 | testing_case['originTestingCaseIds'].append(origin_testing_case_id_info) 80 | testing_case['caseSuiteId'] = new_case_suite_id 81 | return testing_case 82 | 83 | substituted_test_cases = list(map(substitute_info, test_cases)) 84 | for substituted_test_case in substituted_test_cases: 85 | TestingCase.insert(substituted_test_case) 86 | return jsonify({'status': 'ok', 'data': '复制成功'}) 87 | except BaseException as e: 88 | return jsonify({'status': 'failed', 'data': '复制失败 %s' % e}) 89 | 90 | 91 | @app.route('/api/project//caseSuiteList//updateCaseSuite', methods=['POST']) 92 | @login_required 93 | def update_case_suite(project_id, case_suite_id): 94 | try: 95 | filtered_data = CaseSuite.filter_field(request.get_json()) 96 | for key, value in filtered_data.items(): 97 | CaseSuite.update({"_id": ObjectId(case_suite_id)}, 98 | {'$set': {key: value}}) 99 | update_response = CaseSuite.update({"_id": ObjectId(case_suite_id)}, 100 | {'$set': {'lastUpdateTime': datetime.datetime.utcnow()}},) 101 | if update_response["n"] == 0: 102 | return jsonify({'status': 'failed', 'data': '未找到相应更新数据!'}) 103 | return jsonify({'status': 'ok', 'data': '更新成功'}) 104 | except BaseException as e: 105 | return jsonify({'status': 'failed', 'data': '更新失败: %s' % e}) 106 | 107 | 108 | -------------------------------------------------------------------------------- /backend/app/case/testReport.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.testReport import TestReport 6 | from bson import ObjectId 7 | from utils import common 8 | from flask_login import login_required 9 | 10 | 11 | @app.route('/api/project//reportsList', methods=['GET', 'POST']) 12 | @login_required 13 | def reports_list(project_id): 14 | # TODO 性能优化 15 | total_num, test_reports = common.get_total_num_and_arranged_data(TestReport, request.args) 16 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': test_reports}}) 17 | 18 | 19 | @app.route('/api/project//reportsList/', methods=['GET']) 20 | @login_required 21 | def report_detail(project_id, report_id): 22 | test_report = list(TestReport.find({'_id': ObjectId(report_id)})) 23 | test_report = common.format_response_in_dic(test_report[0]) 24 | return jsonify({'status': 'ok', 'data': test_report}) if test_report else \ 25 | jsonify({'status': 'failed', 'data': '未找到报告详情'}) 26 | -------------------------------------------------------------------------------- /backend/app/host/host.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.host import Host 6 | from bson import ObjectId 7 | from utils import common 8 | import datetime 9 | from flask_login import login_required 10 | from utils.log_config import logger 11 | 12 | @app.route('/api/project//hostList', methods=['GET']) 13 | @login_required 14 | def host_list(project_id): 15 | total_num, hosts = common.get_total_num_and_arranged_data(Host, request.args) 16 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': hosts}}) 17 | 18 | 19 | @app.route('/api/project//addHost', methods=['POST']) 20 | @login_required 21 | def add_host(project_id): 22 | try: 23 | request.get_json()["status"] = True 24 | request.get_json()["projectId"] = ObjectId(project_id) 25 | request.get_json()["createAt"] = datetime.datetime.utcnow() 26 | request.get_json()["lastUpdateTime"] = datetime.datetime.utcnow() 27 | filtered_data = Host.filter_field(request.get_json(), use_set_default=True) 28 | Host.insert(filtered_data) 29 | logger.info('添加域名成功') 30 | return jsonify({'status': 'ok', 'data': '新建成功'}) 31 | except BaseException as e: 32 | return jsonify({'status': 'failed', 'data': '新建失败 %s' % e}) 33 | 34 | 35 | @app.route('/api/project//hostList//updateHost', methods=['POST']) 36 | @login_required 37 | def update_host(project_id, host_id): 38 | try: 39 | filtered_data = Host.filter_field(request.get_json()) 40 | for key, value in filtered_data.items(): 41 | Host.update({"_id": ObjectId(host_id)}, 42 | {'$set': {key: value}}) 43 | update_response = Host.update({"_id": ObjectId(host_id)}, 44 | {'$set': {'lastUpdateTime': datetime.datetime.utcnow()}}) 45 | if update_response["n"] == 0: 46 | return jsonify({'status': 'failed', 'data': '未找到相应更新数据!'}) 47 | return jsonify({'status': 'ok', 'data': '更新成功'}) 48 | except BaseException as e: 49 | return jsonify({'status': 'failed', 'data': '更新失败: %s' % e}) 50 | 51 | 52 | -------------------------------------------------------------------------------- /backend/app/mail/mail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.mail import Mail 6 | from bson import ObjectId 7 | from utils import common 8 | import datetime 9 | from flask_login import login_required 10 | 11 | 12 | @app.route('/api/project//mailList', methods=['GET']) 13 | @login_required 14 | def mail_list(project_id): 15 | total_num, mails = common.get_total_num_and_arranged_data(Mail, request.args) 16 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': mails}}) 17 | 18 | 19 | @app.route('/api/project//addMail', methods=['POST']) 20 | @login_required 21 | def add_mail(project_id): 22 | try: 23 | request.get_json()["status"] = True 24 | request.get_json()["projectId"] = ObjectId(project_id) 25 | request.get_json()["createAt"] = datetime.datetime.utcnow() 26 | request.get_json()["lastUpdateTime"] = datetime.datetime.utcnow() 27 | filtered_data = Mail.filter_field(request.get_json(), use_set_default=True) 28 | Mail.insert(filtered_data) 29 | return jsonify({'status': 'ok', 'data': '新建成功'}) 30 | except BaseException as e: 31 | return jsonify({'status': 'failed', 'data': '新建失败 %s' % e}) 32 | 33 | 34 | @app.route('/api/project//mailList//updateMail', methods=['POST']) 35 | @login_required 36 | def update_mail(project_id, mail_id): 37 | try: 38 | filtered_data = Mail.filter_field(request.get_json()) 39 | for key, value in filtered_data.items(): 40 | Mail.update({"_id": ObjectId(mail_id)}, 41 | {'$set': {key: value}}) 42 | update_response = Mail.update({"_id": ObjectId(mail_id)}, 43 | {'$set': {'lastUpdateTime': datetime.datetime.utcnow()}}) 44 | if update_response["n"] == 0: 45 | return jsonify({'status': 'failed', 'data': '未找到相应更新数据!'}) 46 | return jsonify({'status': 'ok', 'data': '更新成功'}) 47 | except BaseException as e: 48 | return jsonify({'status': 'failed', 'data': '更新失败: %s' % e}) 49 | 50 | 51 | -------------------------------------------------------------------------------- /backend/app/mail/mailSender.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.mailSender import MailSender 6 | from bson import ObjectId 7 | from utils import common 8 | from utils.sendReportEmail import send_report_email 9 | import datetime 10 | from flask_login import login_required 11 | 12 | 13 | @app.route('/api/project//mailSenderList', methods=['GET']) 14 | @login_required 15 | def mail_sender_list(project_id): 16 | total_num, mail_senders = common.get_total_num_and_arranged_data(MailSender, request.args) 17 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': mail_senders}}) 18 | 19 | 20 | @app.route('/api/project//addMailSender', methods=['POST']) 21 | @login_required 22 | def add_mail_sender(project_id): 23 | try: 24 | request.get_json()["status"] = True 25 | request.get_json()["projectId"] = ObjectId(project_id) 26 | request.get_json()["createAt"] = datetime.datetime.utcnow() 27 | request.get_json()["lastUpdateTime"] = datetime.datetime.utcnow() 28 | filtered_data = MailSender.filter_field(request.get_json(), use_set_default=True) 29 | MailSender.insert(filtered_data) 30 | return jsonify({'status': 'ok', 'data': '新建成功'}) 31 | except BaseException as e: 32 | return jsonify({'status': 'failed', 'data': '新建失败 %s' % e}) 33 | 34 | 35 | @app.route('/api/project//mailSenderList//updateMailSender', methods=['POST']) 36 | @login_required 37 | def update_mail_sender(project_id, host_id): 38 | try: 39 | filtered_data = MailSender.filter_field(request.get_json()) 40 | for key, value in filtered_data.items(): 41 | MailSender.update({"_id": ObjectId(host_id)}, 42 | {'$set': {key: value}}) 43 | update_response = MailSender.update({"_id": ObjectId(host_id)}, 44 | {'$set': {'lastUpdateTime': datetime.datetime.utcnow()}}) 45 | if update_response["n"] == 0: 46 | return jsonify({'status': 'failed', 'data': '未找到相应更新数据!'}) 47 | return jsonify({'status': 'ok', 'data': '更新成功'}) 48 | except BaseException as e: 49 | return jsonify({'status': 'failed', 'data': '更新失败: %s' % e}) 50 | 51 | 52 | @app.route('/api/testEmailSender', methods=['POST']) 53 | @login_required 54 | def test_email_sender(): 55 | request_data = request.get_json() 56 | user_name = request_data.get('username') 57 | pass_word = request_data.get('password') 58 | if send_report_email(user_name, pass_word, [user_name], '发件人测试', '发件人测试'): 59 | return jsonify({'status': 'ok', 'data': '验证通过 (*^▽^*) 您可以放心「提交」了'}) 60 | else: 61 | return jsonify({'status': 'failed', 'data': '验证失败 o(╥﹏╥)o'}) 62 | 63 | -------------------------------------------------------------------------------- /backend/app/models/adminUser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class AdminUser(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'adminUser' 14 | 15 | # 字段 16 | 17 | _id = ObjectIdField() 18 | username = StringField(unique=True) 19 | password = StringField() 20 | nickName = StringField(unique=True) 21 | isDeleted = BooleanField(field_name='isDeleted', default=False) 22 | roleIds = ArrayField() 23 | createAt = DateField() 24 | lastUpdateTime = DateField() 25 | 26 | def __str__(self): 27 | return "username:{} - password:{} - nickName:{}"\ 28 | .format(self.username, self.password, self.nickName) 29 | 30 | 31 | if __name__ == '__main__': 32 | pass 33 | 34 | -------------------------------------------------------------------------------- /backend/app/models/caseSuite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class CaseSuite(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'caseSuite' 14 | 15 | 16 | # 字段 17 | name = StringField() 18 | isDeleted = BooleanField(field_name='isDeleted', default=False) 19 | _id = ObjectIdField() 20 | projectId = ObjectIdField() 21 | originApiSuiteId = ObjectIdField() 22 | originCaseSuiteIds = ArrayField(field_name='originCaseSuiteIds', default=[]) 23 | description = StringField() 24 | status = BooleanField(field_name='status', default=False) 25 | originApiId = ObjectIdField() 26 | createAt = DateField() 27 | creatorNickName = StringField() 28 | lastUpdateTime = DateField() 29 | lastUpdatorNickName = StringField() 30 | 31 | def __str__(self): 32 | return "name:{}"\ 33 | .format(self.name) 34 | 35 | 36 | if __name__ == '__main__': 37 | pass -------------------------------------------------------------------------------- /backend/app/models/cronTab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | # 10 | class CronTab(Model): 11 | 12 | class Meta: 13 | database = db 14 | collection = 'apscheduler.cronTab' 15 | 16 | 17 | # 字段 18 | _id = StringField() 19 | projectId = ObjectIdField() 20 | name = StringField() 21 | description = StringField() 22 | isDeleted = BooleanField(field_name='isDeleted', default=False) 23 | isExecuteForbiddenedCase = BooleanField(field_name='isExecuteForbiddenedCase', default=False) 24 | testCaseSuiteIdList = ArrayField() 25 | testCaseIdList = ArrayField() 26 | testDomain = StringField() 27 | next_run_time = FloatField() 28 | triggerType = StringField() 29 | interval = FloatField() 30 | runDate = DateField() 31 | alarmMailList = ArrayField() 32 | isDingDingNotify = BooleanField(field_name='isDingDingNotify', default=False) 33 | dingdingAccessToken = StringField() 34 | dingdingNotifyStrategy = DictField(field_name='dingdingNotifyStrategy', 35 | default={'success': True, 'fail': True}, 36 | expected_structure={ 37 | 'expectedTypeRange': [dict], 38 | 'expectedDict': { 39 | 'success': {'expectedTypeRange': [bool]}, 40 | 'fail': {'expectedTypeRange': [bool]} 41 | } 42 | }) 43 | isEnterpriseWechatNotify = BooleanField(field_name='isEnterpriseWechatNotify', default=False) 44 | enterpriseWechatAccessToken = StringField() 45 | enterpriseWechatNotifyStrategy = DictField(field_name='enterpriseWechatNotifyStrategy', 46 | default={'success': True, 'fail': True}, 47 | expected_structure={ 48 | 'expectedTypeRange': [dict], 49 | 'expectedDict': { 50 | 'success': {'expectedTypeRange': [bool]}, 51 | 'fail': {'expectedTypeRange': [bool]} 52 | } 53 | }) 54 | status = StringField(field_name='status', default='CREATED') 55 | createAt = DateField() 56 | creatorNickName = StringField() 57 | lastUpdateTime = DateField() 58 | lastUpdatorNickName = StringField() 59 | 60 | def __str__(self): 61 | return "_id:{}"\ 62 | .format(self._id) 63 | 64 | 65 | if __name__ == '__main__': 66 | pass 67 | -------------------------------------------------------------------------------- /backend/app/models/host.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class Host(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'host' 14 | 15 | 16 | # 字段 17 | name = StringField() 18 | isDeleted = BooleanField(field_name='isDeleted', default=False) 19 | _id = ObjectIdField() 20 | projectId = ObjectIdField() 21 | host = StringField() 22 | description = StringField() 23 | status = BooleanField(field_name='status', default=False) 24 | createAt = DateField() 25 | creatorNickName = StringField() 26 | lastUpdateTime = DateField() 27 | lastUpdatorNickName = StringField() 28 | 29 | def __str__(self): 30 | return "name:{} - host:{} - description:{} - status:{}"\ 31 | .format(self.name, self.description, self.description, self.status) 32 | 33 | 34 | if __name__ == '__main__': 35 | pass -------------------------------------------------------------------------------- /backend/app/models/mail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class Mail(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'mail' 14 | 15 | 16 | # 字段 17 | name = StringField() 18 | isDeleted = BooleanField(field_name='isDeleted', default=False) 19 | _id = ObjectIdField() 20 | projectId = ObjectIdField() 21 | mailAddress = StringField() 22 | description = StringField() 23 | status = BooleanField(field_name='status', default=False) 24 | createAt = DateField() 25 | creatorNickName = StringField() 26 | lastUpdateTime = DateField() 27 | lastUpdatorNickName = StringField() 28 | 29 | def __str__(self): 30 | return "name:{} - email:{} - description:{} - status:{}"\ 31 | .format(self.name, self.mailAddress, self.description, self.status) 32 | 33 | 34 | if __name__ == '__main__': 35 | pass 36 | -------------------------------------------------------------------------------- /backend/app/models/mailSender.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class MailSender(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'mailSender' 14 | 15 | 16 | # 字段 17 | username = StringField() 18 | password = StringField() 19 | _id = ObjectIdField() 20 | projectId = ObjectIdField() 21 | createAt = DateField() 22 | status = BooleanField(field_name='status', default=True) 23 | creatorNickName = StringField() 24 | lastUpdateTime = DateField() 25 | lastUpdatorNickName = StringField() 26 | 27 | if __name__ == '__main__': 28 | pass -------------------------------------------------------------------------------- /backend/app/models/project.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | # 类名定义 collection 8 | class Project(Model): 9 | 10 | class Meta: 11 | database = db 12 | collection = 'project' 13 | 14 | 15 | # 字段 16 | name = StringField() 17 | isDeleted = BooleanField(field_name='isDeleted', default=False) 18 | _id = ObjectIdField() 19 | version = StringField() 20 | description = StringField() 21 | projectTestType = StringField() 22 | status = BooleanField(field_name='status', default=True) 23 | createAt = DateField() 24 | creatorNickName = StringField() 25 | lastUpdateTime = DateField() 26 | lastUpdatorNickName = StringField() 27 | 28 | # 性能测试字段 29 | loopNum = IntField() 30 | mailList = ArrayField() 31 | domain = StringField() 32 | 33 | 34 | def __str__(self): 35 | return "name:{} - description:{} - projectTestType:{} - status:{}"\ 36 | .format(self.name, self.description, self.projectTestType, self.status) 37 | 38 | 39 | if __name__ == '__main__': 40 | pass -------------------------------------------------------------------------------- /backend/app/models/testReport.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from app import db 5 | from utils.mango import * 6 | 7 | 8 | # 类名定义 collection 9 | class TestReport(Model): 10 | 11 | class Meta: 12 | database = db 13 | collection = 'testReport' 14 | 15 | 16 | # 字段 17 | _id = ObjectIdField() 18 | isDeleted = BooleanField(field_name='isDeleted', default=False) 19 | projectId = ObjectIdField() 20 | createAt = DateField() 21 | lastUpdateTime = DateField() 22 | testCount = IntField() 23 | passCount = IntField() 24 | failedCount = IntField() 25 | passRate = StringField() 26 | testDetail = ArrayField() 27 | comeFrom = StringField() 28 | executorNickName = StringField() 29 | cronId = StringField() 30 | 31 | def __str__(self): 32 | return "createAt:{}"\ 33 | .format(self.createAt) 34 | 35 | 36 | if __name__ == '__main__': 37 | pass 38 | -------------------------------------------------------------------------------- /backend/app/notice/webhook.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | from github_webhook import Webhook 3 | from utils.cron.interfaceTestCron import Cron 4 | from app.models.cronTab import CronTab 5 | from app import cron_manager 6 | from utils import common 7 | import datetime 8 | webhook = Webhook(app, endpoint='/api/webhook') 9 | 10 | 11 | @webhook.hook(event_type='ExecTest') # Defines a handler for the 'ExecTest' event 12 | def on_exec_test(data): 13 | try: 14 | data['testCaseSuiteIdList'] = data['testCaseSuiteIdList'].strip().split(';') 15 | except BaseException: 16 | raise TypeError('参数 「testCaseSuiteIdList」 不合法') 17 | 18 | try: 19 | data['testDomain'] = data['testDomain'].strip() 20 | except BaseException: 21 | raise TypeError('参数 「testDomain」 不合法') 22 | 23 | data['isExecuteForbiddenedCase'] = True if data.get('isExecuteForbiddenedCase') \ 24 | and common.can_convert_to_str(data.get('isExecuteForbiddenedCase'))\ 25 | and data.get('isExecuteForbiddenedCase').upper() == 'TRUE' else False 26 | 27 | data['isDingDingNotify'] = True if data.get('isDingDingNotify')\ 28 | and common.can_convert_to_str(data.get('isDingDingNotify'))\ 29 | and data.get('isDingDingNotify').upper() == 'TRUE' else False 30 | 31 | data['isEnterpriseWechatNotify'] = True if data.get('isEnterpriseWechatNotify')\ 32 | and common.can_convert_to_str(data.get('isEnterpriseWechatNotify')) \ 33 | and data.get('isEnterpriseWechatNotify').upper() == 'TRUE' else False 34 | 35 | data['dingdingAccessToken'] = data.get('dingdingAccessToken').strip() if data.get('dingdingAccessToken')\ 36 | and common.can_convert_to_str(data.get('dingdingAccessToken')) else None 37 | 38 | data['enterpriseWechatAccessToken'] = data.get('enterpriseWechatAccessToken').strip()\ 39 | if data.get('enterpriseWechatAccessToken') and common.can_convert_to_str(data.get('enterpriseWechatAccessToken')) else None 40 | 41 | try: 42 | data['alarmMailList'] = data['alarmMailList'].strip().split(';') if data.get('alarmMailList') else [] 43 | except BaseException: 44 | raise TypeError('参数 「alarmMailList」 不合法') 45 | 46 | data["testCaseIdList"] = [] 47 | data['triggerType'] = "date" 48 | data['runDate'] = datetime.datetime.now() # 瞬间触发 49 | filtered_data = CronTab.filter_field(data, use_set_default=True) 50 | cron = Cron(test_case_suite_id_list=filtered_data.get('testCaseSuiteIdList'), 51 | test_domain=filtered_data.get('testDomain'), 52 | alarm_mail_list=filtered_data.get('alarmMailList'), 53 | trigger_type=filtered_data.get('triggerType'), 54 | test_case_id_list=filtered_data.get('testCaseIdList'), 55 | is_execute_forbiddened_case=filtered_data.get('isExecuteForbiddenedCase'), 56 | run_date=filtered_data.get('runDate'), 57 | is_ding_ding_notify=filtered_data.get('isDingDingNotify'), 58 | ding_ding_access_token=filtered_data.get('dingdingAccessToken'), 59 | is_enterprise_wechat_notify=filtered_data.get('isEnterpriseWechatNotify'), 60 | enterprise_wechat_access_token=filtered_data.get('enterpriseWechatAccessToken'), 61 | is_web_hook=True) 62 | cron_manager.add_cron(cron) 63 | 64 | -------------------------------------------------------------------------------- /backend/app/project/project.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request 5 | from app.models.project import Project 6 | from bson import ObjectId 7 | from utils import common 8 | from flask_login import login_required 9 | import datetime 10 | 11 | 12 | @app.route('/api/project/projectList', methods=['GET']) 13 | @login_required 14 | def project_list(): 15 | total_num, projects = common.get_total_num_and_arranged_data(Project, request.args, fuzzy_fields=['name']) 16 | return jsonify({'status': 'ok', 'data': {'totalNum': total_num, 'rows': projects}}) 17 | 18 | 19 | @app.route('/api/project/', methods=['GET']) 20 | @login_required 21 | def get_project(project_id): 22 | res = Project.find_one({'_id': ObjectId(project_id)}) 23 | return jsonify({'status': 'ok', 'data': common.format_response_in_dic(res)}) 24 | 25 | 26 | @app.route('/api/project/addProject', methods=['POST']) 27 | @login_required 28 | def add_project(): 29 | try: 30 | request.get_json()["status"] = True 31 | request.get_json()["createAt"] = datetime.datetime.utcnow() 32 | request.get_json()["lastUpdateTime"] = datetime.datetime.utcnow() 33 | filtered_data = Project.filter_field(request.get_json(), use_set_default=True) 34 | Project.insert(filtered_data) 35 | return jsonify({'status': 'ok', 'data': '新建成功'}) 36 | except BaseException as e: 37 | return jsonify({'status': 'failed', 'data': '新建失败 %s' % e}) 38 | 39 | 40 | @app.route('/api/project//updateProject', methods=['POST']) 41 | @login_required 42 | def update_project(project_id): 43 | try: 44 | filtered_data = Project.filter_field(request.get_json()) 45 | for key, value in filtered_data.items(): 46 | Project.update({"_id": ObjectId(project_id)}, 47 | {'$set': {key: value}}) 48 | update_response = Project.update({"_id": ObjectId(project_id)}, 49 | {'$set': {'lastUpdateTime': datetime.datetime.utcnow()}},) 50 | if update_response["n"] == 0: 51 | return jsonify({'status': 'failed', 'data': '未找到相应更新数据!'}) 52 | return jsonify({'status': 'ok', 'data': '更新成功'}) 53 | except BaseException as e: 54 | return jsonify({'status': 'failed', 'data': '更新失败: %s' % e}) 55 | 56 | 57 | -------------------------------------------------------------------------------- /backend/app/user/adminUser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | 5 | 6 | @app.route('/api/adminUser', methods=['GET']) 7 | def admin_user(): 8 | pass 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /backend/app/user/user.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from app import app 4 | from flask import jsonify, request, render_template, make_response, abort 5 | from app.models.adminUser import AdminUser 6 | from flask_login import UserMixin, login_user, logout_user 7 | from app import login_manager 8 | from werkzeug.security import generate_password_hash 9 | from werkzeug.security import check_password_hash 10 | 11 | 12 | class User(UserMixin): 13 | 14 | @staticmethod 15 | def query_user(user_name): 16 | try: 17 | user = AdminUser.find_one({'username': user_name, 'isDeleted': {"$ne": True}}) 18 | return user 19 | except BaseException: 20 | pass 21 | 22 | @staticmethod 23 | def get_nick_name(user_name): 24 | try: 25 | user = AdminUser.find_one({'username': user_name, 'isDeleted': {"$ne": True}}) 26 | nick_name = user['nickName'] if user else '未知用户' 27 | return nick_name 28 | except BaseException: 29 | return '未知用户' 30 | 31 | 32 | class SecretUser(User): 33 | 34 | def __init__(self, username=None, password=None): 35 | self.username = username 36 | self.set_password(password) 37 | 38 | def set_password(self, password): 39 | self.pw_hash = generate_password_hash(password) 40 | 41 | def check_password(self, password): 42 | return check_password_hash(self.pw_hash, password) 43 | 44 | 45 | @app.route('/', methods=['GET', 'POST']) 46 | def home(): 47 | return render_template('index.html') 48 | 49 | 50 | @login_manager.user_loader 51 | def load_user(user_id): 52 | if User.query_user(user_id) is not None: 53 | curr_user = User() 54 | curr_user.id = user_id 55 | return curr_user 56 | 57 | 58 | @login_manager.unauthorized_handler 59 | def unauthorized_handler(): 60 | abort(401) 61 | 62 | 63 | @app.route('/api/login', methods=['POST']) 64 | def log_in(): 65 | request_data = request.get_json() 66 | user_name = request_data.get('username') if request_data else None 67 | pass_word = request_data.get('password') if request_data else None 68 | user = User.query_user(user_name) 69 | if user is not None and user['password'] == pass_word: 70 | curr_user = User() 71 | curr_user.id = user_name 72 | login_user(curr_user, remember=True) 73 | nick_name = User.get_nick_name(user_name) 74 | res = make_response(jsonify({'status': 'ok', 'data': {'nickName': nick_name}})) 75 | return res 76 | return jsonify({'status': 'failed', 'data': '用户名 / 密码错误!'}) 77 | 78 | 79 | @app.route('/api/logout', methods=['POST', 'GET']) 80 | def log_out(): 81 | try: 82 | logout_user() 83 | res = make_response(jsonify({'status': 'ok', 'data': '退出登录成功'})) 84 | return res 85 | except BaseException: 86 | return jsonify({'status': 'failed', 'data': '退出登录失败!'}) 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /backend/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | # @Time : 2020/1/1 13:14 4 | # @Software: PyCharm 5 | # @Author : https://github.com/Valuebai/ 6 | """ 7 | 通过设置window或者linux系统的环境变量,来区分dev,test,pro环境 8 | 9 | Usage Example 10 | ------------- 11 | ::windows添加环境变量有两种方式: 12 | 第一种方式 :windows下,在“系统设置”——“环境变量”——“用户变量”下,点击“新建” 添加进 13 | 第二种方式 :pycharm-设置环境变量,点击pycharm右上角的“Edit Configuration”, 14 | 然后点击environment variables末端的一个文件夹图标,进入第二个对话框,点击加号新增 15 | 16 | Flask生成SECRET_KEY 17 | >> import os 18 | >> os.urandom(24) 19 | """ 20 | import os 21 | 22 | env_dist = os.environ 23 | 24 | 25 | class Config: 26 | _SEEYOU_PLATFORM_ENV = env_dist.get('SEEYOU_PLATFORM_ENV', 'dev') # (必填) 27 | _SEEYOU_PLATFORM_MONGO_HOST = env_dist.get('SEEYOU_PLATFORM_MONGO_HOST', '127.0.0.1') # 数据库的地址和端口(必填) 28 | _SEEYOU_PLATFORM_MONGO_PORT = env_dist.get('SEEYOU_PLATFORM_MONGO_PORT', '27017') 29 | _SEEYOU_PLATFORM_MONGO_USERNAME = env_dist.get('SEEYOU_PLATFORM_MONGO_USERNAME') # 表示数据库的帐号密码(若无可不填) 30 | _SEEYOU_PLATFORM_MONGO_PASSWORD = env_dist.get('SEEYOU_PLATFORM_MONGO_PASSWORD') 31 | _SEEYOU_PLATFORM_MONGO_DEFAULT_DBNAME = env_dist.get('SEEYOU_PLATFORM_MONGO_DEFAULT_DBNAME', 'test_mongodb') 32 | _SEEYOU_PLATFORM_NLP_SERVER_HOST = env_dist.get('SEEYOU_PLATFORM_NLP_SERVER_HOST', 'localhost') 33 | _SEEYOU_PLATFORM_SECRET_KEY = env_dist.get( 34 | 'SEEYOU_PLATFORM_SECRET_KEY', 35 | b'2H\xf0\xd3|\xee{c\x9c}\xf4\x147E\xdf\xca\xaa\x17\xfd\x17\xd5[cD') 36 | 37 | def get_env(self): 38 | """获取环境变量""" 39 | return self._SEEYOU_PLATFORM_ENV 40 | 41 | def set_env(self, env): 42 | """设置环境变量""" 43 | self._SEEYOU_PLATFORM_ENV = env 44 | 45 | def get_nlp_server_host(self): 46 | """获取nlp bert as serving host""" 47 | return self._SEEYOU_PLATFORM_NLP_SERVER_HOST 48 | 49 | def set_nlp_server_host(self, host): 50 | """设置nlp bert as serving host""" 51 | self._SEEYOU_PLATFORM_NLP_SERVER_HOST = host 52 | 53 | def get_mongo_host(self): 54 | """获取mongo host""" 55 | return self._SEEYOU_PLATFORM_MONGO_HOST 56 | 57 | def set_mongo_host(self, host): 58 | """设置mongo host""" 59 | self._SEEYOU_PLATFORM_MONGO_HOST = host 60 | 61 | def get_mongo_port(self): 62 | """获取mongo port""" 63 | return self._SEEYOU_PLATFORM_MONGO_PORT 64 | 65 | def set_mongo_port(self, port): 66 | """设置mongo port""" 67 | self._SEEYOU_PLATFORM_MONGO_PORT = port 68 | 69 | def get_mongo_username(self): 70 | """获取mongo username""" 71 | return self._SEEYOU_PLATFORM_MONGO_USERNAME 72 | 73 | def set_mongo_username(self, username): 74 | """设置mongo username""" 75 | self._SEEYOU_PLATFORM_MONGO_USERNAME = username 76 | 77 | def get_mongo_password(self): 78 | """获取mongo password""" 79 | return self._SEEYOU_PLATFORM_MONGO_PASSWORD 80 | 81 | def set_mongo_password(self, password): 82 | """设置mongo password""" 83 | self._SEEYOU_PLATFORM_MONGO_PASSWORD = password 84 | 85 | def get_mongo_default_db_name(self): 86 | """获取mongo 默认链接DB名称""" 87 | return self._SEEYOU_PLATFORM_MONGO_DEFAULT_DBNAME 88 | 89 | def set_mongo_default_db_name(self, db_name): 90 | """设置mongo 默认链接DB名称""" 91 | self._SEEYOU_PLATFORM_MONGO_DEFAULT_DBNAME = db_name 92 | 93 | def get_secret_key(self): 94 | """获取密钥""" 95 | return self._SEEYOU_PLATFORM_SECRET_KEY 96 | 97 | def set_secret_key(self, secret_key): 98 | """设置密钥""" 99 | self._SEEYOU_PLATFORM_SECRET_KEY = secret_key 100 | 101 | 102 | if __name__ == '__main__': 103 | config = Config() 104 | print('SEEYOU_PLATFORM_ENV: ----------> %s' % config.get_env()) 105 | print('SEEYOU_PLATFORM_MONGO_HOST: ----------> %s' % config.get_mongo_host()) 106 | print('SEEYOU_PLATFORM_MONGO_PORT: ----------> %s' % config.get_mongo_port()) 107 | print('SEEYOU_PLATFORM_NLP_SERVER_HOST: ----------> %s' % config.get_nlp_server_host()) 108 | print('SEEYOU_PLATFORM_MONGO_USERNAME: ----------> %s' % config.get_mongo_username()) 109 | print('SEEYOU_PLATFORM_MONGO_PASSWORD: ----------> %s' % config.get_mongo_password()) 110 | print('SEEYOU_PLATFORM_MONGO_DEFAULT_DBNAME: ----------> %s' % config.get_mongo_default_db_name()) 111 | print('SEEYOU_PLATFORM_SECRET_KEY: ----------> %s' % config.get_secret_key()) 112 | -------------------------------------------------------------------------------- /backend/createAdminUser.py: -------------------------------------------------------------------------------- 1 | from utils.mango import * 2 | from utils import common 3 | import config as configuration 4 | import pymongo.errors as database_errors 5 | 6 | if __name__ == '__main__': 7 | config = configuration.Config() 8 | conn, db = connect(config.get_mongo_default_db_name(), 9 | ip=config.get_mongo_host(), 10 | port=int(config.get_mongo_port()), 11 | username=config.get_mongo_username(), 12 | password=config.get_mongo_password()) 13 | 14 | user_name = 'admin' 15 | random_pass_word = common.get_random_key() 16 | nick_name = '系统管理员' 17 | 18 | administrator_info = { 19 | 'username': user_name, 20 | 'password': random_pass_word, 21 | 'nickName': nick_name 22 | } 23 | 24 | if db['adminUser'].find_one({'username': user_name}): 25 | print('您已经创建过管理员用户啦! / you have already created adminUser account!') 26 | else: 27 | try: 28 | db['adminUser'].insert(administrator_info) 29 | except database_errors.DuplicateKeyError as e: 30 | print('您已经创建过管理员用户啦! / you have already created adminUser account!') 31 | else: 32 | print('管理员账号创建成功~ / adminUser has been successfully created~') 33 | print('username: %s, password: %s' % (user_name, random_pass_word)) 34 | print('请记录并妥善保管好账号密码~ / please take good care of your account~') 35 | -------------------------------------------------------------------------------- /backend/logs/.__log.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/logs/.__log.lock -------------------------------------------------------------------------------- /backend/logs/log.log.2020-03-07: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/logs/log.log.2020-03-07 -------------------------------------------------------------------------------- /backend/requirements.txt: -------------------------------------------------------------------------------- 1 | tzlocal==2.0.0 2 | XlsxWriter==1.2.1 3 | pytz==2019.2 4 | Flask==1.1.1 5 | pymongo==3.9.0 6 | xlrd==1.2.0 7 | numpy==1.16.2 8 | bert_serving_server==1.10.1 9 | bert-serving-client==1.10.1 10 | APScheduler==3.6.1 11 | requests==2.22.0 12 | Flask_Cors==3.0.8 13 | Werkzeug==0.15.5 14 | bert_serving==0.0.1 15 | python_dateutil==2.8.1 16 | flask_login==0.5.0 17 | github_webhook==1.0.3 18 | -------------------------------------------------------------------------------- /backend/run.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | from app import app 3 | 4 | if __name__ == '__main__': 5 | app.run(debug=True, host='0.0.0.0', port=5050) -------------------------------------------------------------------------------- /backend/run.sh: -------------------------------------------------------------------------------- 1 | # shell杀死指定端口的进程,写到部署脚本里面 2 | kill -9 $(netstat -nlp | grep :5050 | awk '{print $7}' | awk -F"/" '{ print $1 }') 3 | 4 | # 另一个启动方式nohup python3 -u run.py > nohup.log 2>&1 & 5 | # 后台运行 6 | nohup gunicorn -w 4 -b 0.0.0.0:5050 run:app > gunicorn.log 2>&1 & 7 | -------------------------------------------------------------------------------- /backend/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/utils/__init__.py -------------------------------------------------------------------------------- /backend/utils/cron/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/utils/cron/__init__.py -------------------------------------------------------------------------------- /backend/utils/nlp/Nlper.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | from sklearn.metrics.pairwise import cosine_similarity 4 | 5 | class Nlper: 6 | 7 | def __init__(self, bert_client): 8 | self.bert_client = bert_client 9 | 10 | def get_text_similarity(self, base_text, compared_text): 11 | tensors = self.bert_client.encode([base_text,compared_text]) 12 | print('2个文本相似度为:',cosine_similarity(tensors)[0][1]) 13 | return cosine_similarity(tensors)[0][1] 14 | 15 | @staticmethod 16 | # 翻译函数,word 需要翻译的内容 17 | def translate(word): 18 | # 有道词典 api 19 | url = 'http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule&smartresult=ugc&sessionFrom=null' 20 | # 传输的参数,其中 i 为需要翻译的内容 21 | key = { 22 | 'type': "AUTO", 23 | 'i': word, 24 | "doctype": "json", 25 | "version": "2.1", 26 | "keyfrom": "fanyi.web", 27 | "ue": "UTF-8", 28 | "action": "FY_BY_CLICKBUTTON", 29 | "typoResult": "true" 30 | } 31 | # key 这个字典为发送给有道词典服务器的内容 32 | response = requests.post(url, data=key) 33 | # 判断服务器是否相应成功 34 | if response.status_code == 200: 35 | # 然后相应的结果 36 | return json.loads(response.text)['translateResult'][0][0]['tgt'] 37 | else: 38 | print("有道词典调用失败") 39 | # 相应失败就返回空 40 | return None 41 | 42 | 43 | if __name__ == '__main__': 44 | from app import nlper 45 | r = nlper.get_text_similarity('美国','中国') 46 | print(r) 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /backend/utils/nlp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/backend/utils/nlp/__init__.py -------------------------------------------------------------------------------- /backend/utils/sendReportEmail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import smtplib 5 | from email.mime.text import MIMEText 6 | from email.mime.multipart import MIMEMultipart 7 | from email.mime.application import MIMEApplication 8 | 9 | 10 | #发送邮件 11 | #title:标题 12 | #conen:内容 13 | 14 | 15 | def send_report_email(username, password, mail_namelist, title, content, attachment=None): 16 | try: 17 | msg = MIMEMultipart() 18 | msg['from'] = username 19 | msg['to'] = ";".join(mail_namelist) 20 | msg['subject'] = title 21 | txt = MIMEText(content, 'html', 'utf-8') 22 | msg.attach(txt) 23 | 24 | if attachment: 25 | # 添加附件 26 | part = MIMEApplication(open(attachment, 'rb').read()) 27 | part.add_header('Content-Disposition', 'attachment', filename= 28 | attachment) 29 | msg.attach(part) 30 | 31 | # 设置服务器、端口 32 | s = smtplib.SMTP_SSL("smtp.qq.com", 465) 33 | # 登录邮箱 34 | s.login(username, password) 35 | # 发送邮件 36 | s.sendmail(username, mail_namelist, msg.as_string()) 37 | s.quit() 38 | print("email successfully send") 39 | return True 40 | except smtplib.SMTPException as e: 41 | print("send email failed : %s" % e) 42 | return False 43 | except BaseException as e: 44 | print("BaseException: %s" % e) 45 | return False 46 | 47 | 48 | if __name__ == '__main__': 49 | pass 50 | 51 | 52 | -------------------------------------------------------------------------------- /deploy: -------------------------------------------------------------------------------- 1 | docker rm seeyou-platform-frontend; 2 | docker stop seeyou-platform-backend; 3 | docker rm seeyou-platform-backend; 4 | 5 | docker build -f Dockerfile.frontend -t seeyou-platform-frontend .; 6 | docker run --name seeyou-platform-frontend seeyou-platform-frontend; 7 | docker cp seeyou-platform-frontend:/app/seeyou-platform/dist ./; 8 | 9 | docker build -f Dockerfile.backend \ 10 | -t seeyou-platform-backend .; 11 | 12 | echo "AUTOTEST_PLATFORM_ENV=${AUTOTEST_PLATFORM_ENV} 13 | AUTOTEST_PLATFORM_MONGO_HOST=${AUTOTEST_PLATFORM_MONGO_HOST} 14 | AUTOTEST_PLATFORM_MONGO_PORT=${AUTOTEST_PLATFORM_MONGO_PORT} 15 | AUTOTEST_PLATFORM_NLP_SERVER_HOST=${AUTOTEST_PLATFORM_NLP_SERVER_HOST} 16 | AUTOTEST_PLATFORM_MONGO_USERNAME=${AUTOTEST_PLATFORM_MONGO_USERNAME} 17 | AUTOTEST_PLATFORM_MONGO_PASSWORD=${AUTOTEST_PLATFORM_MONGO_PASSWORD} 18 | AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME=${AUTOTEST_PLATFORM_MONGO_DEFAULT_DBNAME}" > Envlist.txt; 19 | 20 | docker run --name seeyou-platform-backend \ 21 | --env-file="./Envlist.txt" \ 22 | -p $1:5050 \ 23 | seeyou-platform-backend; 24 | 25 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | seeyou-platform
-------------------------------------------------------------------------------- /dist/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/favicon.ico -------------------------------------------------------------------------------- /dist/static/fonts/element-icons.6f0a763.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/element-icons.6f0a763.ttf -------------------------------------------------------------------------------- /dist/static/fonts/fontawesome-webfont.674f50d.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/fontawesome-webfont.674f50d.eot -------------------------------------------------------------------------------- /dist/static/fonts/fontawesome-webfont.af7ae50.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/fontawesome-webfont.af7ae50.woff2 -------------------------------------------------------------------------------- /dist/static/fonts/fontawesome-webfont.b06871f.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/fontawesome-webfont.b06871f.ttf -------------------------------------------------------------------------------- /dist/static/fonts/fontawesome-webfont.fee66e7.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/fontawesome-webfont.fee66e7.woff -------------------------------------------------------------------------------- /dist/static/fonts/icomoon.5fadf3a.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/icomoon.5fadf3a.woff -------------------------------------------------------------------------------- /dist/static/fonts/icomoon.aa6f949.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/icomoon.aa6f949.ttf -------------------------------------------------------------------------------- /dist/static/fonts/icomoon.c440c59.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/icomoon.c440c59.eot -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.824ae76.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/iconfont.824ae76.ttf -------------------------------------------------------------------------------- /dist/static/fonts/iconfont.9465461.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/fonts/iconfont.9465461.eot -------------------------------------------------------------------------------- /dist/static/img/Banner.df97073.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/img/Banner.df97073.jpg -------------------------------------------------------------------------------- /dist/static/img/hello.614f7c7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/img/hello.614f7c7.jpg -------------------------------------------------------------------------------- /dist/static/img/logo.e8aa977.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/img/logo.e8aa977.jpg -------------------------------------------------------------------------------- /dist/static/img/userphoto.9511e5e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/dist/static/img/userphoto.9511e5e.jpg -------------------------------------------------------------------------------- /dist/static/js/manifest.2ae2e69a05c33dfc65f8.js: -------------------------------------------------------------------------------- 1 | !function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "istanbul"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | 9 | # Editor directories and files 10 | .idea 11 | .vscode 12 | *.suo 13 | *.ntvs* 14 | *.njsproj 15 | *.sln 16 | -------------------------------------------------------------------------------- /frontend/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /frontend/build/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/build/logo.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 'scss': path.resolve(__dirname, '../src/style'), 31 | 'scss_vars': '@/styles/vars.scss' 32 | } 33 | }, 34 | module: { 35 | rules: [ 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 | }, 72 | node: { 73 | // prevent webpack from injecting useless setImmediate polyfill because Vue 74 | // source contains it (although only uses it if it's native). 75 | setImmediate: false, 76 | // prevent webpack from injecting mocks to Node native modules 77 | // that does not make sense for the client 78 | dgram: 'empty', 79 | fs: 'empty', 80 | net: 'empty', 81 | tls: 'empty', 82 | child_process: 'empty' 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /frontend/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // This is the webpack config used for unit tests. 3 | 4 | const utils = require('./utils') 5 | const webpack = require('webpack') 6 | const merge = require('webpack-merge') 7 | const baseWebpackConfig = require('./webpack.base.conf') 8 | 9 | const webpackConfig = merge(baseWebpackConfig, { 10 | // use inline sourcemap for karma-sourcemap-loader 11 | module: { 12 | rules: utils.styleLoaders() 13 | }, 14 | devtool: '#inline-source-map', 15 | resolveLoader: { 16 | alias: { 17 | // necessary to to make lang="scss" work in test when using vue-loader's ?inject option 18 | // see discussion at https://github.com/vuejs/vue-loader/issues/724 19 | 'scss-loader': 'sass-loader' 20 | } 21 | }, 22 | plugins: [ 23 | new webpack.DefinePlugin({ 24 | 'process.env': require('../config/test.env') 25 | }) 26 | ] 27 | }) 28 | 29 | // no need for app entry during tests 30 | delete webpackConfig.entry 31 | 32 | module.exports = webpackConfig 33 | -------------------------------------------------------------------------------- /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 | BASE_API: '"http://localhost:5050"', 8 | CASE_IMPORT_URI: '"/api/importTestCases"' 9 | }) 10 | 11 | 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /frontend/config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"', 4 | CASE_IMPORT_URI: '"/api/importTestCases"' 5 | } 6 | -------------------------------------------------------------------------------- /frontend/config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /frontend/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/favicon.ico -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | seeyou-platform 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 68 | -------------------------------------------------------------------------------- /frontend/src/api/caseSuite.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getCaseSuiteList (project_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/caseSuiteList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function addCaseSuite (project_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/addCaseSuite`, 15 | headers: header, 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateCaseSuite (project_id, case_suite_id, params, header) { 22 | return request({ 23 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/updateCaseSuite`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | export function copyCaseSuite (project_id, case_suite_id, params, header) { 31 | return request({ 32 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/copyCaseSuite`, 33 | method: 'POST', 34 | headers: header, 35 | data: params 36 | }) 37 | } 38 | 39 | -------------------------------------------------------------------------------- /frontend/src/api/common.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function startInterfaceTest (params, header) { 4 | return request({ 5 | url: `/api/startInterfaceTesting`, 6 | method: 'POST', 7 | headers: header, 8 | data: params 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /frontend/src/api/cron.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getCrons (params, header) { 4 | return request({ 5 | url: `/api/cronList`, 6 | method: 'GET', 7 | headers: header, 8 | params: params 9 | }) 10 | } 11 | 12 | export function addCron (project_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/addCron`, 15 | method: 'POST', 16 | headers: header, 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateCron (cron_id, params, header) { 22 | return request({ 23 | url: `/api/cronList/${cron_id}/updateCron`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | export function pauseCron (cron_id, params, header) { 31 | return request({ 32 | url: `/api/cronList/${cron_id}/pauseCron`, 33 | method: 'POST', 34 | headers: header, 35 | data: params 36 | }) 37 | } 38 | 39 | export function resumeCron (cron_id, params, header) { 40 | return request({ 41 | url: `/api/cronList/${cron_id}/resumeCron`, 42 | method: 'POST', 43 | headers: header, 44 | data: params 45 | }) 46 | } 47 | 48 | export function delCron (cron_id, params, header) { 49 | return request({ 50 | url: `/api/cronList/${cron_id}/delCron`, 51 | method: 'POST', 52 | headers: header, 53 | data: params 54 | }) 55 | } 56 | 57 | export function startScheduler(params, header) { 58 | return request({ 59 | url: `/api/cronList/start`, 60 | method: 'POST', 61 | headers: header, 62 | data: params 63 | }) 64 | } 65 | 66 | export function shutdownScheduler (params, header) { 67 | return request({ 68 | url: `/api/cronList/shutdown`, 69 | method: 'POST', 70 | headers: header, 71 | data: params 72 | }) 73 | } 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /frontend/src/api/host.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getHosts (project_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/hostList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function addHost(project_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/addHost`, 15 | headers: header, 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateHost (project_id, host_id, params, header) { 22 | return request({ 23 | url: `/api/project/${project_id}/hostList/${host_id}/updateHost`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | -------------------------------------------------------------------------------- /frontend/src/api/index.js: -------------------------------------------------------------------------------- 1 | import * as api from './'; 2 | 3 | export default api; 4 | -------------------------------------------------------------------------------- /frontend/src/api/mail.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getMails (project_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/mailList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function addMail(project_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/addMail`, 15 | headers: header, 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateMail (project_id, mail_id, params, header) { 22 | return request({ 23 | url: `/api/project/${project_id}/mailList/${mail_id}/updateMail`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | -------------------------------------------------------------------------------- /frontend/src/api/mailSender.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getMailSender (project_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/mailSenderList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function addMailSender(project_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/addMailSender`, 15 | headers: header, 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateMailSender (project_id, sender_id, params, header) { 22 | return request({ 23 | url: `/api/project/${project_id}/mailSenderList/${sender_id}/updateMailSender`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | export function testMailSender (params, header) { 31 | return request({ 32 | url: `/api/testEmailSender`, 33 | method: 'POST', 34 | headers: header, 35 | data: params 36 | }) 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /frontend/src/api/project.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getProjects (params, header) { 4 | return request({ 5 | url: `/api/project/projectList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function getProjectInfo(project_id) { 13 | return request({ 14 | url: `/api/project/${project_id}`, 15 | method: 'GET' 16 | }) 17 | } 18 | 19 | export function addProject (params, header) { 20 | return request({ 21 | url: `/api/project/addProject`, 22 | headers: header, 23 | method: 'POST', 24 | data: params 25 | }) 26 | } 27 | 28 | export function updateProject (project_id, params, header) { 29 | return request({ 30 | url: `/api/project/${project_id}/updateProject`, 31 | method: 'POST', 32 | headers: header, 33 | data: params 34 | }) 35 | } 36 | 37 | -------------------------------------------------------------------------------- /frontend/src/api/testCase.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getCaseList (project_id, case_suite_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/caseList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function addCase (project_id, case_suite_id, params, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/addCase`, 15 | headers: header, 16 | method: 'POST', 17 | data: params 18 | }) 19 | } 20 | 21 | export function updateCase (project_id, case_suite_id, case_id, params, header) { 22 | return request({ 23 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/caseList/${case_id}/updateCase`, 24 | method: 'POST', 25 | headers: header, 26 | data: params 27 | }) 28 | } 29 | 30 | export function copyCase (project_id, case_suite_id, case_id, params, header) { 31 | return request({ 32 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/caseList/${case_id}/copyCase`, 33 | method: 'POST', 34 | headers: header, 35 | data: params 36 | }) 37 | } 38 | 39 | export function exportTestCases (params, header) { 40 | return request({ 41 | url: `/api/exportTestCases`, 42 | method: 'POST', 43 | headers: header, 44 | responseType: 'blob', 45 | data: params 46 | }) 47 | 48 | } 49 | export function getCaseDetail (project_id, case_suite_id, case_id, header) { 50 | return request({ 51 | url: `/api/project/${project_id}/caseSuiteList/${case_suite_id}/caseList/${case_id}`, 52 | method: 'GET', 53 | headers: header, 54 | params: null 55 | }) 56 | } 57 | 58 | export function getLastSingleTestResult (case_id, header) { 59 | return request({ 60 | url: `/api/getLastSingleTestResult/${case_id}`, 61 | method: 'GET', 62 | headers: header, 63 | params: null 64 | }) 65 | } 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /frontend/src/api/testReport.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getReportList (project_id, params, header) { 4 | return request({ 5 | url: `/api/project/${project_id}/reportsList`, 6 | headers: header, 7 | params: params, 8 | method: 'GET' 9 | }) 10 | } 11 | 12 | export function getReportDetail (project_id, report_id, header) { 13 | return request({ 14 | url: `/api/project/${project_id}/reportsList/${report_id}`, 15 | headers: header, 16 | params: null, 17 | method: 'GET' 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /frontend/src/api/user.js: -------------------------------------------------------------------------------- 1 | 2 | import request from '@/utils/request' 3 | 4 | export function login (params, header) { 5 | return request({ 6 | url: '/api/login', 7 | headers: header, 8 | method: 'POST', 9 | data: params 10 | }) 11 | } 12 | 13 | export function logout (params, header) { 14 | return request({ 15 | url: '/api/logout', 16 | headers: header, 17 | method: 'POST', 18 | data: params 19 | }) 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /frontend/src/assets/css/animate.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | /*! 4 | * animate.css -http://daneden.me/animate 5 | * Version - 3.6.1 6 | * Licensed under the MIT license - http://opensource.org/licenses/MIT 7 | * 8 | * Copyright (c) 2018 Daniel Eden 9 | */ 10 | 11 | .animated{animation-duration:1s;animation-fill-mode:both}.animated.infinite{animation-iteration-count:infinite}@keyframes fadeInDown{0%{opacity:0;transform:translate3d(0,-100%,0)}to{opacity:1;transform:translateZ(0)}}.fadeInDown{animation-name:fadeInDown}@keyframes fadeOutUp{0%{opacity:1}to{opacity:0;transform:translate3d(0,-100%,0)}}.fadeOutUp{animation-name:fadeOutUp} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/alert.css: -------------------------------------------------------------------------------- 1 | .el-alert{width:100%;padding:8px 16px;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;background-color:#fff;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}.el-alert.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-alert--success{background-color:#f0f9eb;color:#67c23a}.el-alert--success .el-alert__description{color:#67c23a}.el-alert--info{background-color:#f4f4f5;color:#909399}.el-alert--info .el-alert__description{color:#909399}.el-alert--warning{background-color:#fdf6ec;color:#e6a23c}.el-alert--warning .el-alert__description{color:#e6a23c}.el-alert--error{background-color:#fef0f0;color:#f56c6c}.el-alert--error .el-alert__description{color:#f56c6c}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:12px;margin:5px 0 0}.el-alert__closebtn{font-size:12px;color:#c0c4cc;opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-alert-fade-enter,.el-alert-fade-leave-active{opacity:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/aside.css: -------------------------------------------------------------------------------- 1 | .el-aside{overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/badge.css: -------------------------------------------------------------------------------- 1 | .el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#f56c6c;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #fff}.el-badge__content.is-fixed{position:absolute;top:0;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/breadcrumb-item.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/breadcrumb-item.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/breadcrumb.css: -------------------------------------------------------------------------------- 1 | .el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb::after,.el-breadcrumb::before{display:table;content:""}.el-breadcrumb::after{clear:both}.el-breadcrumb__separator{margin:0 9px;font-weight:700;color:#c0c4cc}.el-breadcrumb__separator[class*=icon]{margin:0 6px;font-weight:400}.el-breadcrumb__item{float:left}.el-breadcrumb__inner{color:#606266}.el-breadcrumb__inner a,.el-breadcrumb__inner.is-link{font-weight:700;text-decoration:none;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1);color:#303133}.el-breadcrumb__inner a:hover,.el-breadcrumb__inner.is-link:hover{color:#FF9E1B;cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{font-weight:400;color:#606266;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/button-group.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/button-group.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/card.css: -------------------------------------------------------------------------------- 1 | .el-card{border-radius:4px;border:1px solid #ebeef5;background-color:#fff;overflow:hidden;color:#303133;-webkit-transition:.3s;transition:.3s}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-card__header{padding:18px 20px;border-bottom:1px solid #ebeef5;-webkit-box-sizing:border-box;box-sizing:border-box}.el-card__body{padding:20px} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/carousel-item.css: -------------------------------------------------------------------------------- 1 | .el-carousel__item,.el-carousel__mask{position:absolute;height:100%;top:0;left:0}.el-carousel__item{width:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item.is-animating{-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card{width:50%;-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:2}.el-carousel__mask{width:100%;background-color:#fff;opacity:.24;-webkit-transition:.2s;transition:.2s} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/carousel.css: -------------------------------------------------------------------------------- 1 | .el-carousel{overflow-x:hidden;position:relative}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;outline:0;padding:0;margin:0;height:36px;width:36px;cursor:pointer;-webkit-transition:.3s;transition:.3s;border-radius:50%;background-color:rgba(31,45,61,.11);color:#fff;position:absolute;top:50%;z-index:10;-webkit-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{position:absolute;list-style:none;bottom:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);margin:0;padding:0;z-index:2}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-webkit-transform:none;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#c0c4cc;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;-webkit-transform:none;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{display:inline-block;background-color:transparent;padding:12px 4px;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#fff;border:none;outline:0;padding:0;margin:0;cursor:pointer;-webkit-transition:.3s;transition:.3s}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{-webkit-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{-webkit-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/checkbox-button.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/checkbox-button.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/checkbox-group.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/checkbox-group.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/collapse-item.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/collapse-item.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/collapse.css: -------------------------------------------------------------------------------- 1 | .el-fade-in-enter,.el-fade-in-leave-active,.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.fade-in-linear-enter-active,.fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.el-fade-in-enter-active,.el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center top;transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:center bottom;transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1),-webkit-transform .3s cubic-bezier(.23,1,.32,1);-webkit-transform-origin:top left;transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.el-list-enter-active,.el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-collapse{border-top:1px solid #ebeef5;border-bottom:1px solid #ebeef5}.el-collapse-item__header{height:48px;line-height:48px;background-color:#fff;color:#303133;cursor:pointer;border-bottom:1px solid #ebeef5;font-size:13px;font-weight:500;-webkit-transition:border-bottom-color .3s;transition:border-bottom-color .3s;outline:0}.el-collapse-item__arrow{margin-right:8px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;float:right;line-height:48px;font-weight:300}.el-collapse-item__arrow.is-active{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:#FF9E1B}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{will-change:height;background-color:#fff;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #ebeef5}.el-collapse-item__content{padding-bottom:25px;font-size:13px;color:#303133;line-height:1.769230769230769}.el-collapse-item:last-child{margin-bottom:-1px} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/container.css: -------------------------------------------------------------------------------- 1 | .el-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;-webkit-box-sizing:border-box;box-sizing:border-box;min-width:0}.el-container.is-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/dialog.css: -------------------------------------------------------------------------------- 1 | .v-modal-enter{-webkit-animation:v-modal-in .2s ease;animation:v-modal-in .2s ease}.v-modal-leave{-webkit-animation:v-modal-out .2s ease forwards;animation:v-modal-out .2s ease forwards}@-webkit-keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-in{0%{opacity:0}}@-webkit-keyframes v-modal-out{100%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-popup-parent--hidden{overflow:hidden}.el-dialog{position:relative;margin:0 auto 50px;background:#fff;border-radius:2px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.3);box-shadow:0 1px 3px rgba(0,0,0,.3);-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.el-dialog.is-fullscreen{width:100%;margin-top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.el-dialog__header{padding:20px 20px 10px}.el-dialog__headerbtn{position:absolute;top:20px;right:20px;padding:0;background:0 0;border:none;outline:0;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#909399}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#FF9E1B}.el-dialog__title{line-height:24px;font-size:18px;color:#303133}.el-dialog__body{padding:30px 20px;color:#606266;font-size:14px}.el-dialog__footer{padding:10px 20px 20px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{text-align:initial;padding:25px 25px 30px}.el-dialog--center .el-dialog__footer{text-align:inherit}.dialog-fade-enter-active{-webkit-animation:dialog-fade-in .3s;animation:dialog-fade-in .3s}.dialog-fade-leave-active{-webkit-animation:dialog-fade-out .3s;animation:dialog-fade-out .3s}@-webkit-keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/display.css: -------------------------------------------------------------------------------- 1 | @media only screen and (max-width:767px){.hidden-xs-only{display:none!important}}@media only screen and (min-width:768px){.hidden-sm-and-up{display:none!important}}@media only screen and (min-width:768px) and (max-width:991px){.hidden-sm-only{display:none!important}}@media only screen and (max-width:991px){.hidden-sm-and-down{display:none!important}}@media only screen and (min-width:992px){.hidden-md-and-up{display:none!important}}@media only screen and (min-width:992px) and (max-width:1199px){.hidden-md-only{display:none!important}}@media only screen and (max-width:1199px){.hidden-md-and-down{display:none!important}}@media only screen and (min-width:1200px){.hidden-lg-and-up{display:none!important}}@media only screen and (min-width:1200px) and (max-width:1919px){.hidden-lg-only{display:none!important}}@media only screen and (max-width:1919px){.hidden-lg-and-down{display:none!important}}@media only screen and (min-width:1920px){.hidden-xl-only{display:none!important}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/dropdown-item.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/dropdown-item.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/dropdown-menu.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/dropdown-menu.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/fonts/element-icons.ttf -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/fonts/element-icons.woff -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/footer.css: -------------------------------------------------------------------------------- 1 | .el-footer{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/form-item.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/form-item.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/form.css: -------------------------------------------------------------------------------- 1 | .el-form--inline .el-form-item,.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form-item::after,.el-form-item__content::after{clear:both}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{margin-right:10px}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form-item__content .el-input-group,.el-form-item__label{vertical-align:middle}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item::after,.el-form-item::before{display:table;content:""}.el-form-item .el-form-item{margin-bottom:0}.el-form-item--mini.el-form-item,.el-form-item--small.el-form-item{margin-bottom:18px}.el-form-item .el-input__validateIcon{display:none}.el-form-item--medium .el-form-item__content,.el-form-item--medium .el-form-item__label{line-height:36px}.el-form-item--small .el-form-item__content,.el-form-item--small .el-form-item__label{line-height:32px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item--mini .el-form-item__content,.el-form-item--mini .el-form-item__label{line-height:28px}.el-form-item--mini .el-form-item__error{padding-top:1px}.el-form-item__label{text-align:right;float:left;font-size:14px;color:#606266;line-height:40px;padding:0 12px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.el-form-item__content{line-height:40px;position:relative;font-size:14px}.el-form-item__content::after,.el-form-item__content::before{display:table;content:""}.el-form-item__error{color:#f56c6c;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{content:'*';color:#f56c6c;margin-right:4px}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus{border-color:#f56c6c}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__validateIcon{color:#f56c6c}.el-form-item.is-success .el-input__inner,.el-form-item.is-success .el-input__inner:focus,.el-form-item.is-success .el-textarea__inner,.el-form-item.is-success .el-textarea__inner:focus{border-color:#67c23a}.el-form-item.is-success .el-input-group__append .el-input__inner,.el-form-item.is-success .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-success .el-input__validateIcon{color:#67c23a}.el-form-item--feedback .el-input__validateIcon{display:inline-block} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/header.css: -------------------------------------------------------------------------------- 1 | .el-header{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-flex-negative:0;flex-shrink:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/icon.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:element-icons;src:url(fonts/element-icons.woff) format("woff"),url(fonts/element-icons.ttf) format("truetype");font-weight:400;font-style:normal}[class*=" el-icon-"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-info:before{content:"\e61a"}.el-icon-error:before{content:"\e62c"}.el-icon-success:before{content:"\e62d"}.el-icon-warning:before{content:"\e62e"}.el-icon-question:before{content:"\e634"}.el-icon-back:before{content:"\e606"}.el-icon-arrow-left:before{content:"\e600"}.el-icon-arrow-down:before{content:"\e603"}.el-icon-arrow-right:before{content:"\e604"}.el-icon-arrow-up:before{content:"\e605"}.el-icon-caret-left:before{content:"\e60a"}.el-icon-caret-bottom:before{content:"\e60b"}.el-icon-caret-top:before{content:"\e60c"}.el-icon-caret-right:before{content:"\e60e"}.el-icon-d-arrow-left:before{content:"\e610"}.el-icon-d-arrow-right:before{content:"\e613"}.el-icon-minus:before{content:"\e621"}.el-icon-plus:before{content:"\e62b"}.el-icon-remove:before{content:"\e635"}.el-icon-circle-plus:before{content:"\e601"}.el-icon-remove-outline:before{content:"\e63c"}.el-icon-circle-plus-outline:before{content:"\e602"}.el-icon-close:before{content:"\e60f"}.el-icon-check:before{content:"\e611"}.el-icon-circle-close:before{content:"\e607"}.el-icon-circle-check:before{content:"\e639"}.el-icon-circle-close-outline:before{content:"\e609"}.el-icon-circle-check-outline:before{content:"\e63e"}.el-icon-zoom-out:before{content:"\e645"}.el-icon-zoom-in:before{content:"\e641"}.el-icon-d-caret:before{content:"\e615"}.el-icon-sort:before{content:"\e640"}.el-icon-sort-down:before{content:"\e630"}.el-icon-sort-up:before{content:"\e631"}.el-icon-tickets:before{content:"\e63f"}.el-icon-document:before{content:"\e614"}.el-icon-goods:before{content:"\e618"}.el-icon-sold-out:before{content:"\e63b"}.el-icon-news:before{content:"\e625"}.el-icon-message:before{content:"\e61b"}.el-icon-date:before{content:"\e608"}.el-icon-printer:before{content:"\e62f"}.el-icon-time:before{content:"\e642"}.el-icon-bell:before{content:"\e622"}.el-icon-mobile-phone:before{content:"\e624"}.el-icon-service:before{content:"\e63a"}.el-icon-view:before{content:"\e643"}.el-icon-menu:before{content:"\e620"}.el-icon-more:before{content:"\e646"}.el-icon-more-outline:before{content:"\e626"}.el-icon-star-on:before{content:"\e637"}.el-icon-star-off:before{content:"\e63d"}.el-icon-location:before{content:"\e61d"}.el-icon-location-outline:before{content:"\e61f"}.el-icon-phone:before{content:"\e627"}.el-icon-phone-outline:before{content:"\e628"}.el-icon-picture:before{content:"\e629"}.el-icon-picture-outline:before{content:"\e62a"}.el-icon-delete:before{content:"\e612"}.el-icon-search:before{content:"\e619"}.el-icon-edit:before{content:"\e61c"}.el-icon-edit-outline:before{content:"\e616"}.el-icon-rank:before{content:"\e632"}.el-icon-refresh:before{content:"\e633"}.el-icon-share:before{content:"\e636"}.el-icon-setting:before{content:"\e638"}.el-icon-upload:before{content:"\e60d"}.el-icon-upload2:before{content:"\e644"}.el-icon-download:before{content:"\e617"}.el-icon-loading:before{content:"\e61e"}.el-icon-loading{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@-webkit-keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}@keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/loading.css: -------------------------------------------------------------------------------- 1 | .el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{position:absolute;z-index:2000;background-color:rgba(255,255,255,.9);margin:0;top:0;right:0;bottom:0;left:0;-webkit-transition:opacity .3s;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-loading-spinner .el-loading-text{color:#FF9E1B;margin:3px 0;font-size:14px}.el-loading-spinner .circular{height:42px;width:42px;-webkit-animation:loading-rotate 2s linear infinite;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{-webkit-animation:loading-dash 1.5s ease-in-out infinite;animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#FF9E1B;stroke-linecap:round}.el-loading-spinner i{color:#FF9E1B}.el-loading-fade-enter,.el-loading-fade-leave-active{opacity:0}@-webkit-keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/main.css: -------------------------------------------------------------------------------- 1 | .el-main{display:block;-webkit-box-flex:1;-ms-flex:1;flex:1;-ms-flex-preferred-size:auto;flex-basis:auto;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box;padding:20px} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/menu-item-group.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/menu-item-group.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/menu-item.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/menu-item.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/message.css: -------------------------------------------------------------------------------- 1 | .el-message__closeBtn:focus,.el-message__content:focus{outline-width:0}.el-message{min-width:380px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;border-width:1px;border-style:solid;border-color:#ebeef5;position:fixed;left:50%;top:20px;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:#edf2fc;-webkit-transition:opacity .3s,-webkit-transform .4s;transition:opacity .3s,-webkit-transform .4s;transition:opacity .3s,transform .4s;transition:opacity .3s,transform .4s,-webkit-transform .4s;overflow:hidden;padding:15px 15px 15px 20px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-message.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--info .el-message__content{color:#909399}.el-message--success{background-color:#f0f9eb;border-color:#e1f3d8}.el-message--success .el-message__content{color:#67c23a}.el-message--warning{background-color:#fdf6ec;border-color:#faecd8}.el-message--warning .el-message__content{color:#e6a23c}.el-message--error{background-color:#fef0f0;border-color:#fde2e2}.el-message--error .el-message__content{color:#f56c6c}.el-message__icon{margin-right:10px}.el-message__content{padding:0;font-size:14px;line-height:1}.el-message__closeBtn{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;color:#c0c4cc;font-size:16px}.el-message__closeBtn:hover{color:#909399}.el-message .el-icon-success{color:#67c23a}.el-message .el-icon-error{color:#f56c6c}.el-message .el-icon-info{color:#909399}.el-message .el-icon-warning{color:#e6a23c}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;-webkit-transform:translate(-50%,-100%);transform:translate(-50%,-100%)} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/notification.css: -------------------------------------------------------------------------------- 1 | .el-notification{display:-webkit-box;display:-ms-flexbox;display:flex;width:330px;padding:14px 26px 14px 13px;border-radius:8px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #ebeef5;position:fixed;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;overflow:hidden}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:13px}.el-notification__title{font-weight:700;font-size:16px;color:#303133;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0;color:#606266;text-align:justify}.el-notification__content p{margin:0}.el-notification__icon{height:24px;width:24px;font-size:24px}.el-notification__closeBtn{position:absolute;top:18px;right:15px;cursor:pointer;color:#909399;font-size:16px}.el-notification__closeBtn:hover{color:#606266}.el-notification .el-icon-success{color:#67c23a}.el-notification .el-icon-error{color:#f56c6c}.el-notification .el-icon-info{color:#909399}.el-notification .el-icon-warning{color:#e6a23c}.el-notification-fade-enter.right{right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.el-notification-fade-enter.left{left:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.el-notification-fade-leave-active{opacity:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/option-group.css: -------------------------------------------------------------------------------- 1 | .el-select-group{margin:0;padding:0}.el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type)::after{content:'';position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#e4e7ed}.el-select-group__title{padding-left:20px;font-size:12px;color:#909399;line-height:30px}.el-select-group .el-select-dropdown__item{padding-left:20px} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/option.css: -------------------------------------------------------------------------------- 1 | .el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#606266;height:34px;line-height:34px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.is-disabled{color:#c0c4cc;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#fff}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#f5f7fa}.el-select-dropdown__item.selected{color:#FF9E1B;font-weight:700} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/popover.css: -------------------------------------------------------------------------------- 1 | .el-popper .popper__arrow,.el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.el-popper .popper__arrow::after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#ebeef5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#ebeef5}.el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#ebeef5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#ebeef5}.el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.el-popover{position:absolute;background:#fff;min-width:150px;border-radius:4px;border:1px solid #ebeef5;padding:12px;z-index:2000;color:#606266;line-height:1.4;text-align:justify;font-size:14px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-popover--plain{padding:18px 20px}.el-popover__title{color:#303133;font-size:16px;line-height:1;margin-bottom:12px}.el-popover:focus,.el-popover:focus:active,.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing){outline-width:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/popper.css: -------------------------------------------------------------------------------- 1 | .el-popper .popper__arrow,.el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.el-popper .popper__arrow::after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#ebeef5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#ebeef5}.el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#ebeef5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#ebeef5}.el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/progress.css: -------------------------------------------------------------------------------- 1 | .el-progress{position:relative;line-height:1}.el-progress__text{font-size:14px;color:#606266;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle{display:inline-block}.el-progress--circle .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}.el-progress--circle .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress-bar,.el-progress-bar__inner::after,.el-progress-bar__innerText{display:inline-block;vertical-align:middle}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:#67c23a}.el-progress.is-success .el-progress__text{color:#67c23a}.el-progress.is-exception .el-progress-bar__inner{background-color:#f56c6c}.el-progress.is-exception .el-progress__text{color:#f56c6c}.el-progress-bar{padding-right:50px;width:100%;margin-right:-55px;-webkit-box-sizing:border-box;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#ebeef5;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#FF9E1B;text-align:right;border-radius:100px;line-height:1;white-space:nowrap}.el-progress-bar__inner::after{content:"";height:100%}.el-progress-bar__innerText{color:#fff;font-size:12px;margin:0 5px}@-webkit-keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/radio-button.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.el-radio-button,.el-radio-button__inner{display:inline-block;position:relative;outline:0}.el-radio-button__inner{line-height:1;white-space:nowrap;vertical-align:middle;background:#fff;border:1px solid #dcdfe6;font-weight:500;border-left:0;color:#606266;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;cursor:pointer;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.el-radio-button__inner.is-round{padding:12px 20px}.el-radio-button__inner:hover{color:#FF9E1B}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #dcdfe6;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#fff;background-color:#FF9E1B;border-color:#FF9E1B;-webkit-box-shadow:-1px 0 0 0 #FF9E1B;box-shadow:-1px 0 0 0 #FF9E1B}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#c0c4cc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#ebeef5;-webkit-box-shadow:none;box-shadow:none}.el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#f2f6fc}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button--medium .el-radio-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.el-radio-button--small .el-radio-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.el-radio-button--small .el-radio-button__inner.is-round{padding:9px 15px}.el-radio-button--mini .el-radio-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){-webkit-box-shadow:0 0 2px 2px #FF9E1B;box-shadow:0 0 2px 2px #FF9E1B} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/radio-group.css: -------------------------------------------------------------------------------- 1 | .el-radio-group{display:inline-block;line-height:1;vertical-align:middle;font-size:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/radio.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.el-radio,.el-radio--medium.is-bordered .el-radio__label{font-size:14px}.el-radio,.el-radio__input{white-space:nowrap;line-height:1;outline:0}.el-radio,.el-radio__inner,.el-radio__input{position:relative;display:inline-block}.el-radio{color:#606266;font-weight:500;cursor:pointer;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-radio.is-bordered{padding:12px 20px 0 10px;border-radius:4px;border:1px solid #dcdfe6;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px}.el-radio.is-bordered.is-checked{border-color:#FF9E1B}.el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:#ebeef5}.el-radio__input.is-disabled .el-radio__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#f5f7fa;border-color:#e4e7ed}.el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.el-radio--medium.is-bordered{padding:10px 20px 0 10px;border-radius:4px;height:36px}.el-radio--mini.is-bordered .el-radio__label,.el-radio--small.is-bordered .el-radio__label{font-size:12px}.el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.el-radio--small.is-bordered{padding:8px 15px 0 10px;border-radius:3px;height:32px}.el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio--mini.is-bordered{padding:6px 15px 0 10px;border-radius:3px;height:28px}.el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio+.el-radio{margin-left:30px}.el-radio__input{cursor:pointer;vertical-align:middle}.el-radio__input.is-disabled .el-radio__inner{cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner::after{cursor:not-allowed;background-color:#f5f7fa}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner::after{background-color:#c0c4cc}.el-radio__input.is-disabled+span.el-radio__label{color:#c0c4cc;cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{border-color:#FF9E1B;background:#FF9E1B}.el-radio__input.is-checked .el-radio__inner::after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:#FF9E1B}.el-radio__input.is-focus .el-radio__inner{border-color:#FF9E1B}.el-radio__inner{border:1px solid #dcdfe6;border-radius:100%;width:14px;height:14px;background-color:#fff;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box}.el-radio__inner:hover{border-color:#FF9E1B}.el-radio__inner::after{width:4px;height:4px;border-radius:100%;background-color:#fff;content:"";position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);-webkit-transition:-webkit-transform .15s ease-in;transition:-webkit-transform .15s ease-in;transition:transform .15s ease-in;transition:transform .15s ease-in,-webkit-transform .15s ease-in}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{-webkit-box-shadow:0 0 2px 2px #FF9E1B;box-shadow:0 0 2px 2px #FF9E1B}.el-radio__label{font-size:14px;padding-left:10px} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/rate.css: -------------------------------------------------------------------------------- 1 | .el-rate__icon,.el-rate__item{position:relative;display:inline-block}.el-rate{height:20px;line-height:1}.el-rate:active,.el-rate:focus{outline-width:0}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon{font-size:18px;margin-right:6px;color:#c0c4cc;-webkit-transition:.3s;transition:.3s}.el-rate__decimal,.el-rate__icon .path2{position:absolute;top:0;left:0}.el-rate__icon.hover{-webkit-transform:scale(1.15);transform:scale(1.15)}.el-rate__decimal{display:inline-block;overflow:hidden}.el-rate__text{font-size:14px;vertical-align:middle} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/reset.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";body{font-family:"Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;font-weight:400;font-size:14px;color:#000;-webkit-font-smoothing:antialiased}a{color:#FF9E1B;text-decoration:none}a:focus,a:hover{color:rgb(255, 177, 73)}a:active{color:rgb(230, 142, 24)}h1,h2,h3,h4,h5,h6{color:#606266;font-weight:inherit}h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child,h6:first-child,p:first-child{margin-top:0}h1:last-child,h2:last-child,h3:last-child,h4:last-child,h5:last-child,h6:last-child,p:last-child{margin-bottom:0}h1{font-size:20px}h2{font-size:18px}h3{font-size:16px}h4,h5,h6,p{font-size:inherit}p{line-height:1.8}sub,sup{font-size:13px}small{font-size:12px}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/row.css: -------------------------------------------------------------------------------- 1 | .el-row{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box}.el-row::after,.el-row::before{display:table;content:""}.el-row::after{clear:both}.el-row--flex{display:-webkit-box;display:-ms-flexbox;display:flex}.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-row--flex.is-justify-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-space-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-align-middle{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-row--flex.is-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/scrollbar.css: -------------------------------------------------------------------------------- 1 | .el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active>.el-scrollbar__bar,.el-scrollbar:focus>.el-scrollbar__bar,.el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.el-scrollbar__wrap{overflow:scroll;height:100%}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(144,147,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.el-scrollbar__thumb:hover{background-color:rgba(144,147,153,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/select-dropdown.css: -------------------------------------------------------------------------------- 1 | .el-popper .popper__arrow,.el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.el-popper .popper__arrow::after{content:" ";border-width:6px}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#ebeef5;border-bottom-width:0}.el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#ebeef5}.el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#ebeef5;border-left-width:0}.el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#ebeef5}.el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #e4e7ed;border-radius:4px;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:5px 0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#FF9E1B;background-color:#fff}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#f5f7fa}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:20px;font-family:element-icons;content:"\E611";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/spinner.css: -------------------------------------------------------------------------------- 1 | .el-time-spinner{width:100%;white-space:nowrap}.el-spinner{display:inline-block;vertical-align:middle}.el-spinner-inner{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;-webkit-animation:dash 1.5s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/step.css: -------------------------------------------------------------------------------- 1 | .el-step{position:relative;-ms-flex-negative:1;flex-shrink:1}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{-ms-flex-preferred-size:auto!important;flex-basis:auto!important;-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{color:#303133;border-color:#303133}.el-step__head.is-wait{color:#c0c4cc;border-color:#c0c4cc}.el-step__head.is-success{color:#67c23a;border-color:#67c23a}.el-step__head.is-error{color:#f56c6c;border-color:#f56c6c}.el-step__head.is-finish{color:#FF9E1B;border-color:#FF9E1B}.el-step__icon{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:24px;height:24px;font-size:14px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#fff;-webkit-transition:.15s ease-out;transition:.15s ease-out}.el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{-webkit-transform:translateY(1px);transform:translateY(1px)}.el-step__line{position:absolute;border-color:inherit;background-color:#c0c4cc}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;-webkit-transition:.15s ease-out;transition:.15s ease-out;-webkit-box-sizing:border-box;box-sizing:border-box;width:0;height:0}.el-step__main{white-space:normal;text-align:left}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{font-weight:700;color:#303133}.el-step__title.is-wait{color:#c0c4cc}.el-step__title.is-success{color:#67c23a}.el-step__title.is-error{color:#f56c6c}.el-step__title.is-finish{color:#FF9E1B}.el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.el-step__description.is-process{color:#303133}.el-step__description.is-wait{color:#c0c4cc}.el-step__description.is-success{color:#67c23a}.el-step__description.is-error{color:#f56c6c}.el-step__description.is-finish{color:#FF9E1B}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.el-step.is-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.el-step.is-vertical .el-step__head{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{padding-left:10px;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.el-step.is-simple .el-step__icon{background:0 0;width:16px;height:16px;font-size:12px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{-webkit-transform:scale(.8) translateY(1px);transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.el-step.is-simple .el-step__arrow::after,.el-step.is-simple .el-step__arrow::before{content:'';display:inline-block;position:absolute;height:15px;width:1px;background:#c0c4cc}.el-step.is-simple .el-step__arrow::before{-webkit-transform:rotate(-45deg) translateY(-4px);transform:rotate(-45deg) translateY(-4px);-webkit-transform-origin:0 0;transform-origin:0 0}.el-step.is-simple .el-step__arrow::after{-webkit-transform:rotate(45deg) translateY(4px);transform:rotate(45deg) translateY(4px);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/steps.css: -------------------------------------------------------------------------------- 1 | .el-steps{display:-webkit-box;display:-ms-flexbox;display:flex}.el-steps--simple{padding:13px 8%;border-radius:4px;background:#f5f7fa}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{height:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column;flex-flow:column} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/submenu.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/submenu.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/switch.css: -------------------------------------------------------------------------------- 1 | .el-switch{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:relative;font-size:14px;line-height:20px;height:20px;vertical-align:middle}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__core,.el-switch__label{display:inline-block;cursor:pointer;vertical-align:middle}.el-switch__label{-webkit-transition:.2s;transition:.2s;height:20px;font-size:14px;font-weight:500;color:#303133}.el-switch__label.is-active{color:#FF9E1B}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{line-height:1;font-size:14px;display:inline-block}.el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.el-switch__core{margin:0;position:relative;width:40px;height:20px;border:1px solid #dcdfe6;outline:0;border-radius:10px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#dcdfe6;-webkit-transition:border-color .3s,background-color .3s;transition:border-color .3s,background-color .3s}.el-switch__core:after{content:"";position:absolute;top:1px;left:1px;border-radius:100%;-webkit-transition:all .3s;transition:all .3s;width:16px;height:16px;background-color:#fff}.el-switch.is-checked .el-switch__core{border-color:#FF9E1B;background-color:#FF9E1B}.el-switch.is-checked .el-switch__core::after{left:100%;margin-left:-17px}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/tab-pane.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/css/element-#FF9E1B/tab-pane.css -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/tag.css: -------------------------------------------------------------------------------- 1 | .el-tag{background-color:rgba(64,158,255,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#FF9E1B;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(64,158,255,.2);white-space:nowrap}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:16px;width:16px;line-height:16px;vertical-align:middle;top:-1px;right:-5px;color:#FF9E1B}.el-tag .el-icon-close::before{display:block}.el-tag .el-icon-close:hover{background-color:#FF9E1B;color:#fff}.el-tag--info,.el-tag--info .el-tag__close{color:#909399}.el-tag--info{background-color:rgba(144,147,153,.1);border-color:rgba(144,147,153,.2)}.el-tag--info.is-hit{border-color:#909399}.el-tag--info .el-tag__close:hover{background-color:#909399;color:#fff}.el-tag--success{background-color:rgba(103,194,58,.1);border-color:rgba(103,194,58,.2);color:#67c23a}.el-tag--success.is-hit{border-color:#67c23a}.el-tag--success .el-tag__close{color:#67c23a}.el-tag--success .el-tag__close:hover{background-color:#67c23a;color:#fff}.el-tag--warning{background-color:rgba(230,162,60,.1);border-color:rgba(230,162,60,.2);color:#e6a23c}.el-tag--warning.is-hit{border-color:#e6a23c}.el-tag--warning .el-tag__close{color:#e6a23c}.el-tag--warning .el-tag__close:hover{background-color:#e6a23c;color:#fff}.el-tag--danger{background-color:rgba(245,108,108,.1);border-color:rgba(245,108,108,.2);color:#f56c6c}.el-tag--danger.is-hit{border-color:#f56c6c}.el-tag--danger .el-tag__close{color:#f56c6c}.el-tag--danger .el-tag__close:hover{background-color:#f56c6c;color:#fff}.el-tag--medium{height:28px;line-height:26px}.el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--small{height:24px;padding:0 8px;line-height:22px}.el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.el-tag--mini{height:20px;padding:0 5px;line-height:19px}.el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)} -------------------------------------------------------------------------------- /frontend/src/assets/css/element-#FF9E1B/tooltip.css: -------------------------------------------------------------------------------- 1 | .el-tooltip:focus:hover,.el-tooltip:focus:not(.focusing){outline-width:0}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2;min-width:10px}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow::after{content:" ";border-width:5px}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#303133;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#303133}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#303133;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#303133}.el-tooltip__popper.is-dark{background:#303133;color:#fff}.el-tooltip__popper.is-light{background:#fff;border:1px solid #303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#fff}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#fff}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#303133}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#fff}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#303133}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#fff} -------------------------------------------------------------------------------- /frontend/src/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) 3 | * http://cssreset.com 4 | */ 5 | html, body, div, span, applet, object, iframe, 6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 7 | a, abbr, acronym, address, big, cite, code, 8 | del, dfn, em, img, ins, kbd, q, s, samp, 9 | small, strike, strong, sub, sup, tt, var, 10 | b, u, i, center, 11 | dl, dt, dd, ol, ul, li, 12 | fieldset, form, label, legend, 13 | table, caption, tbody, tfoot, thead, tr, th, td, 14 | article, aside, canvas, details, embed, 15 | figure, figcaption, footer, header, 16 | menu, nav, output, ruby, section, summary, 17 | time, mark, audio, video, input { 18 | margin: 0; 19 | padding: 0; 20 | border: 0; 21 | font-size: 100%; 22 | font-weight: normal; 23 | vertical-align: baseline; 24 | } 25 | 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, menu, nav, section { 29 | display: block; 30 | } 31 | 32 | body { 33 | line-height: 1; 34 | } 35 | 36 | blockquote, q { 37 | quotes: none; 38 | } 39 | 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: none; 43 | } 44 | 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | 50 | /* custom */ 51 | a { 52 | color: #7e8c8d; 53 | text-decoration: none; 54 | backface-visibility: hidden; 55 | } 56 | 57 | li { 58 | list-style: none; 59 | } 60 | :focus{ 61 | outline: none; 62 | } 63 | 64 | html{ 65 | height: 100%; 66 | } 67 | body { 68 | position: relative; 69 | min-height: 100%; 70 | box-sizing: border-box; 71 | -webkit-text-size-adjust: none; 72 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 73 | } 74 | .iconfont{ 75 | margin-right: 5px; 76 | } 77 | .icomoon{ 78 | font-size: 14px; 79 | margin-right: 5px; 80 | } 81 | .outer-box{ 82 | box-shadow: 0 1px 2px rgba(0,0,0,.05), 0 0 0 1px rgba(63,63,68,.1); 83 | background-color: #fff; 84 | } 85 | .flex-center{ 86 | display: flex; 87 | justify-content: center; 88 | align-items: center; 89 | } 90 | .flex-column{ 91 | flex-direction: column; 92 | } 93 | .el-button-group{ 94 | background-color: transparent; 95 | } 96 | .bg-transparent{ 97 | background-color: transparent; 98 | } 99 | .cicle{ 100 | border-radius: 50%; 101 | } 102 | .placeholder{ 103 | font-size: 12px; 104 | color: #909399; 105 | } 106 | .margin-right-5px{ 107 | margin-right: 5px; 108 | } 109 | body .el-button i{ 110 | font-size: 12px; 111 | } 112 | body .el-button--primary{ 113 | background-color: #FF9E1B; 114 | border-color: #FF9E1B; 115 | color: #fff; 116 | } 117 | body .el-button--primary:hover{ 118 | background: #ffb44f; 119 | border-color: #ffb44f; 120 | color: #fff; 121 | } 122 | body .el-button--primary.is-disabled, 123 | body .el-button--primary.is-disabled:hover{ 124 | background: #f8d6a7; 125 | border-color: #f8d6a7; 126 | color: #fff; 127 | } 128 | 129 | body .el-button--primary:active, 130 | body .el-button--primary:focus{ 131 | background: #ec9219; 132 | border-color: #ec9219; 133 | color: #fff; 134 | } 135 | body .el-button--small{ 136 | padding: 10px 24px; 137 | } 138 | body .el-input__inner:focus{ 139 | box-shadow: 0 0 0 2px rgba(255,158,27,0.20); 140 | } 141 | @keyframes fadeInDown { 142 | from { 143 | opacity: 0; 144 | transform: translate3d(0, -20px, 0); 145 | } 146 | 147 | to { 148 | opacity: 1; 149 | transform: translate3d(0, 0, 0); 150 | } 151 | } 152 | @keyframes fadeOutDown { 153 | from { 154 | opacity: 1; 155 | transform: translate3d(0, 0, 0); 156 | } 157 | to { 158 | opacity: 0; 159 | transform: translate3d(0, -20px, 0); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /frontend/src/assets/fonts/icomoon.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icomoon'; 3 | src: url('icomoon.eot?klm8by'); 4 | src: url('icomoon.eot?klm8by#iefix') format('embedded-opentype'), 5 | url('icomoon.ttf?klm8by') format('truetype'), 6 | url('icomoon.woff?klm8by') format('woff'), 7 | url('icomoon.svg?klm8by#icomoon') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | .icomoon { 13 | /* use !important to prevent issues with browser extensions that change fonts */ 14 | font-family: 'icomoon' !important; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | 22 | /* Better Font Rendering =========== */ 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .icon-aa:before { 28 | content: "\e900"; 29 | } 30 | .icon-1:before { 31 | content: "\e901"; 32 | } 33 | .icon-2:before { 34 | content: "\e902"; 35 | } 36 | .icon-3:before { 37 | content: "\e903"; 38 | } 39 | .icon-4:before { 40 | content: "\e904"; 41 | } 42 | .icon-5:before { 43 | content: "\e905"; 44 | } 45 | .icon-23:before { 46 | content: "\e906"; 47 | } 48 | .icon-24:before { 49 | content: "\e907"; 50 | } 51 | .icon-25:before { 52 | content: "\e908"; 53 | } 54 | .icon-26:before { 55 | content: "\e909"; 56 | } 57 | .icon-27:before { 58 | content: "\e90a"; 59 | } 60 | .icon-28 .path1:before { 61 | content: "\e90b"; 62 | color: rgb(0, 0, 0); 63 | } 64 | .icon-28 .path2:before { 65 | content: "\e90c"; 66 | margin-left: -1em; 67 | color: rgb(255, 255, 255); 68 | } 69 | .icon-29:before { 70 | content: "\e90d"; 71 | } 72 | .icon-30:before { 73 | content: "\e90e"; 74 | } 75 | .icon-6:before { 76 | content: "\e90f"; 77 | } 78 | .icon-7:before { 79 | content: "\e910"; 80 | } 81 | .icon-8:before { 82 | content: "\e911"; 83 | } 84 | .icon-9:before { 85 | content: "\e912"; 86 | } 87 | .icon-10:before { 88 | content: "\e913"; 89 | } 90 | .icon-11:before { 91 | content: "\e914"; 92 | } 93 | .icon-44:before { 94 | content: "\e915"; 95 | } 96 | .icon-31:before { 97 | content: "\e916"; 98 | } 99 | .icon-32:before { 100 | content: "\e917"; 101 | } 102 | .icon---1:before { 103 | content: "\e918"; 104 | } 105 | .icon-33:before { 106 | content: "\e919"; 107 | } 108 | .icon-34:before { 109 | content: "\e91a"; 110 | } 111 | .icon-35:before { 112 | content: "\e91b"; 113 | } 114 | .icon-36:before { 115 | content: "\e91c"; 116 | } 117 | .icon-12:before { 118 | content: "\e91d"; 119 | } 120 | .icon-13:before { 121 | content: "\e91e"; 122 | } 123 | .icon-14:before { 124 | content: "\e91f"; 125 | } 126 | .icon-15:before { 127 | content: "\e920"; 128 | } 129 | .icon-16:before { 130 | content: "\e921"; 131 | } 132 | .icon-17:before { 133 | content: "\e922"; 134 | } 135 | .icon-45:before { 136 | content: "\e923"; 137 | } 138 | .icon-37:before { 139 | content: "\e924"; 140 | } 141 | .icon-38:before { 142 | content: "\e925"; 143 | } 144 | .icon-39:before { 145 | content: "\e926"; 146 | } 147 | .icon-40:before { 148 | content: "\e927"; 149 | } 150 | .icon-41:before { 151 | content: "\e928"; 152 | } 153 | .icon-42:before { 154 | content: "\e929"; 155 | } 156 | .icon-43:before { 157 | content: "\e92a"; 158 | } 159 | .icon---:before { 160 | content: "\e92b"; 161 | } 162 | .icon-18:before { 163 | content: "\e92c"; 164 | } 165 | .icon-19:before { 166 | content: "\e92d"; 167 | } 168 | .icon-20:before { 169 | content: "\e92e"; 170 | } 171 | .icon-21:before { 172 | content: "\e92f"; 173 | } 174 | .icon-22:before { 175 | content: "\e930"; 176 | } 177 | -------------------------------------------------------------------------------- /frontend/src/assets/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/icomoon.eot -------------------------------------------------------------------------------- /frontend/src/assets/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/icomoon.ttf -------------------------------------------------------------------------------- /frontend/src/assets/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/icomoon.woff -------------------------------------------------------------------------------- /frontend/src/assets/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/iconfont.eot -------------------------------------------------------------------------------- /frontend/src/assets/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/iconfont.ttf -------------------------------------------------------------------------------- /frontend/src/assets/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/fonts/iconfont.woff -------------------------------------------------------------------------------- /frontend/src/assets/imgs/Banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/Banner.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/Banner2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/Banner2.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/assets/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/imgs/assets/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/imgs/assets/member.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/assets/member.png -------------------------------------------------------------------------------- /frontend/src/assets/imgs/assets/wx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/assets/wx.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/favicon.ico -------------------------------------------------------------------------------- /frontend/src/assets/imgs/hello.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/hello.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/i-am-strong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/i-am-strong.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/imgs/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /frontend/src/assets/imgs/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/logo.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/member.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/member.png -------------------------------------------------------------------------------- /frontend/src/assets/imgs/userphoto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/userphoto.jpg -------------------------------------------------------------------------------- /frontend/src/assets/imgs/wx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/src/assets/imgs/wx.jpg -------------------------------------------------------------------------------- /frontend/src/assets/js/dom.js: -------------------------------------------------------------------------------- 1 | export function parentsUntil (el, selector, filter) { 2 | const result = [] 3 | const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector 4 | 5 | el = el.parentElement 6 | 7 | while (el && !matchesSelector.call(el, selector)) { 8 | if (!filter) { 9 | result.push(el) 10 | } else { 11 | if (matchesSelector.call(el, filter)) { 12 | result.push(el) 13 | } 14 | } 15 | 16 | el = el.parentElement 17 | } 18 | 19 | return result 20 | } 21 | 22 | export function closest (el, selector) { 23 | const matchesSelector = el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector 24 | 25 | while (el) { 26 | if (matchesSelector.call(el, selector)) { 27 | return el 28 | } else { 29 | el = el.parentElement 30 | } 31 | } 32 | 33 | return null 34 | } 35 | -------------------------------------------------------------------------------- /frontend/src/assets/js/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 格式化日期 3 | * @param {string} dateLike 一个可以转换为日期对象的字符串 4 | * @param {string} format 格式字符串 5 | */ 6 | export function formatDate (dateLike, format) { 7 | const date = new Date(dateLike) 8 | const hours = '' + date.getHours() 9 | const mins = '' + date.getMinutes() 10 | const seconds = '' + date.getSeconds() 11 | const fullYears = '' + date.getFullYear() 12 | const months = '' + (date.getMonth() + 1) 13 | const days = '' + date.getDate() 14 | const years = fullYears.substring(2) 15 | let result 16 | 17 | format = format || 'YYYY-MM-DD' 18 | result = format.replace('YYYY', fullYears) 19 | result = result.replace('YY', years) 20 | result = result.replace('MM', months.padStart(2, '0')) 21 | result = result.replace('DD', days.padStart(2, '0')) 22 | result = result.replace('hh', hours.padStart(2, '0')) 23 | result = result.replace('mm', mins.padStart(2, '0')) 24 | result = result.replace('ss', seconds.padStart(2, '0')) 25 | 26 | return result 27 | } 28 | 29 | /** 30 | * 根据字符串路径生成一个js对象 31 | * @param {string} field 字符串路径 32 | * @param {fixed} value 路径末端的值 33 | * 例: field: 'a.b' 34 | * value: 2 35 | * 则返回 { a: { b: 2 } } 36 | */ 37 | export function newObject (field, value) { 38 | if (!field) return 39 | const fields = field.split('.') 40 | const result = {} 41 | let temp = result 42 | 43 | for (let i = 0; i < fields.length; i++) { 44 | if (i === fields.length - 1) { 45 | temp[fields[i]] = value 46 | } else { 47 | temp[fields[i]] = {} 48 | temp = temp[fields[i]] 49 | } 50 | } 51 | 52 | return result 53 | } 54 | 55 | /** 56 | * 根据字符串获取嵌套数据 57 | * @param {object} data 数据源 58 | * @param {string} field 目标数据路径 59 | * 例: data: { a: { b: 2 } } 60 | * field: 'a.b' 61 | * 则返回 2 62 | */ 63 | export function getValueFromObject (data, field) { 64 | if (!field) { 65 | return 66 | } 67 | 68 | const fields = field.split('.') 69 | let result = data 70 | 71 | fields.forEach(f => { 72 | if (result) { 73 | result = result[f] 74 | } 75 | }) 76 | 77 | return result 78 | } 79 | 80 | export function checkEmpty (fields) { 81 | if (!Array.isArray(fields)) { 82 | return false 83 | } 84 | 85 | return !fields.some(element => { 86 | return element === '' || element === null || element === undefined || element.length === 0 || (typeof element === 'number' && isNaN(element)) 87 | }) 88 | } 89 | 90 | /** 91 | * 将基础类型的变量值转换为易懂的文字 92 | * @param {mixed} value 变量值 93 | * @param {string} type 变量值类型 94 | * @param {array} options 选项列表(针对type为Option) 95 | */ 96 | export function varToText (value, type, options) { 97 | if (type === 'Boolean') { 98 | if (value === true) { 99 | return '是/有' 100 | } 101 | 102 | if (value === false) { 103 | return '否/无' 104 | } 105 | 106 | return value 107 | } 108 | 109 | if (type === 'Option' && Array.isArray(options)) { 110 | const targetOption = options.find(o => o.value === value) 111 | 112 | return targetOption ? targetOption.label : '' 113 | } 114 | 115 | return value 116 | } 117 | -------------------------------------------------------------------------------- /frontend/src/assets/scss/custom-el-var.scss: -------------------------------------------------------------------------------- 1 | // $--color-primary: #6B5CAF; 2 | $--color-primary: #FF9E1B; 3 | 4 | $--font-path: '~element-ui/packages/theme-chalk/src/fonts'; 5 | @import "~element-ui/packages/theme-chalk/src/index"; 6 | 7 | .fcube .el-input__inner:focus{ 8 | border-color: $--color-primary; 9 | } -------------------------------------------------------------------------------- /frontend/src/assets/scss/dashboard-ojo-palette.scss: -------------------------------------------------------------------------------- 1 | $ghost-white: #F2F1F8; 2 | $fog: #DDD4EA; 3 | $perfume: #C7ADE9; 4 | $blue-marguerite: #6B5CAF; 5 | $portage: #8C94CE; 6 | $purple-mountain-s-majesty: #9280AF; 7 | -------------------------------------------------------------------------------- /frontend/src/assets/svg/loading.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 routerPromise from '@/utils/getUserRouters' 4 | import Vue from 'vue' 5 | 6 | import ElementUI from 'element-ui' 7 | import VueClipboard from 'vue-clipboard2' 8 | import ToggleButton from 'vue-js-toggle-button' 9 | import App from './App.vue' 10 | import router from './router' 11 | import store from './vuex/store' 12 | import {getCookie, setCookie, delCookie} from '@/utils/cookie' 13 | import './assets/css/element-#FF9E1B/index.css' 14 | import './assets/css/reset.css' 15 | import './assets/fonts/iconfont.css' 16 | import './assets/fonts/icomoon.css' 17 | import 'font-awesome/css/font-awesome.min.css' 18 | import easyDialog from 'leiang-easy-dialog' 19 | import Header from "./views/common/Header"; 20 | 21 | Vue.use(easyDialog) 22 | Vue.config.productionTip = false 23 | Vue.use(ToggleButton) 24 | Vue.use(VueClipboard) 25 | Vue.use(ElementUI) 26 | Vue.component("header-view", Header) 27 | 28 | router.beforeEach(async (to, from, next) => { 29 | 30 | if (to.matched.length === 0) { //匹配前往的路由不存在 31 | next('/interfaceProjectList') 32 | return 33 | } 34 | 35 | if (['/login'].indexOf(to.path) === -1) { 36 | let nickName = getCookie('nickName') 37 | //TODO 判断太草率 38 | nickName !== '' ? 39 | to.path.trim() === '/' ? 40 | next('/interfaceProjectList') : 41 | next() : 42 | next('/login') 43 | } else { 44 | next() 45 | } 46 | }) 47 | 48 | /* eslint-disable no-new */ 49 | new Vue({ 50 | el: '#app', 51 | router, 52 | store, 53 | components: {App}, 54 | template: '' 55 | }) 56 | -------------------------------------------------------------------------------- /frontend/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import interfaceProjectList from '@/views/interfaceTestProject/ProjectList' 4 | import login from '@/views/Login' 5 | import projectInfo from '@/views/Project' 6 | import home from '@/views/Home' 7 | import about from '@/views/About' 8 | import more from '@/views/More' 9 | import uitest from '@/views/UITest' 10 | import automationTest from '@/views/interfaceTestProject/api/automation/AutomationTest' 11 | import cronList from '@/views/interfaceTestProject/api/automation/CronList' 12 | import caseSuiteList from '@/views/interfaceTestProject/api/automation/CaseSuiteList' 13 | import caseApiList from '@/views/interfaceTestProject/api/automation/CaseApiList' 14 | import addCaseApi from '@/views/interfaceTestProject/api/automation/AddCaseApi' 15 | import updateCaseApi from '@/views/interfaceTestProject/api/automation/UpdateCaseApi' 16 | import globalHost from '@/views/interfaceTestProject/global/Globalhost' 17 | import globalMail from '@/views/interfaceTestProject/global/GlobalMail' 18 | import projectReport from '@/views/interfaceTestProject/ProjectReport' 19 | Vue.use(Router) 20 | 21 | export default new Router({ 22 | routes: [ 23 | { 24 | path: '/login', 25 | name: 'login', 26 | component: login, 27 | hidden: true, 28 | projectHidden: true 29 | }, 30 | { 31 | path: '/', 32 | component: home, 33 | name: '', 34 | projectHidden: true, 35 | children: [ 36 | { path: '/interfaceProjectList', component: interfaceProjectList, iconCls:'fa fa-plug', name: 'API接口测试'}, 37 | { path: '/UIProjectList', component: uitest, iconCls:'fa fa-random', name: 'UI AutoTest'}, 38 | { path: '/aboutAuthor', component: about, iconCls:'fa fa-id-card-o', name: 'About me'}, 39 | { path: '/more', component: more, iconCls:'fa fa-heart', name: 'More'}, 40 | ] 41 | }, 42 | { 43 | path: '/interfaceTestProject/:project_id', 44 | component: projectInfo, 45 | name: '项目', 46 | hidden: true, 47 | children: [ 48 | { 49 | path: '/automationTest/:project_id', 50 | component: automationTest, 51 | name: '自动化测试', 52 | leaf: true, 53 | child: true, 54 | children: [ 55 | { path: '/interfaceTestProject/:project_id/caseSuiteList', component: caseSuiteList, name: '用例列表'}, 56 | { path: '/interfaceTestProject/:project_id/caseApiList/caseSuiteId=:case_suite_id', component: caseApiList, name: '用例接口列表'}, 57 | { path: '/interfaceTestProject/:project_id/updateCaseApi/caseSuiteId=:case_suite_id/testingCaseId=:case_id', component: updateCaseApi, name: '修改用例'} 58 | ] 59 | }, 60 | { 61 | path: '/interfaceTestProject/:project_id/GlobalHost', 62 | component: globalHost, 63 | name: 'Host配置', 64 | leaf: true 65 | }, 66 | { 67 | path: '/interfaceTestProject/:project_id/GlobalMail', 68 | component: globalMail, 69 | name: '邮箱配置', 70 | leaf: true 71 | }, 72 | { 73 | path: '/interfaceTestProject/:project_id/CronList', 74 | component: cronList, 75 | name: '定时任务', 76 | leaf: true 77 | }, 78 | { path: '/interfaceTestProject/:project_id/projectReport', component: projectReport, name: '测试报告', leaf: true} 79 | ] 80 | } 81 | ] 82 | }) 83 | -------------------------------------------------------------------------------- /frontend/src/styles/vars.scss: -------------------------------------------------------------------------------- 1 | $color-primary: #20a0ff;//#18c79c -------------------------------------------------------------------------------- /frontend/src/utils/cookie.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by hfy on 18/4/8. 3 | */ 4 | export function getCookie (name) { 5 | if (document.cookie.length>0) 6 | 7 | { 8 | 9 | let tmp_cookie = document.cookie, 10 | 11 | tmp_c1 = (tmp_cookie.indexOf(" "+name+"=")>0) ? (tmp_cookie.indexOf(" "+name+"=")+1) : 0, 12 | 13 | tmp_c2 = (tmp_cookie.indexOf(";"+name+"=")>0) ? (tmp_cookie.indexOf(";"+name+"=")+1) : 0, 14 | 15 | tmp_c3 = (tmp_cookie.indexOf(name+"=")===0) ? 0 : -1, 16 | 17 | c_start=tmp_c1 || tmp_c2 || tmp_c3; 18 | 19 | if (c_start!==-1) 20 | 21 | { 22 | 23 | c_start=c_start + name.length+1; 24 | 25 | let c_end=tmp_cookie.indexOf(";",c_start); 26 | 27 | if (c_end===-1) c_end=tmp_cookie.length; 28 | 29 | return (tmp_cookie.substring(c_start,c_end)); 30 | 31 | } 32 | 33 | } 34 | 35 | return ""; 36 | } 37 | 38 | export function setCookie(name, value, day) { 39 | 40 | if (day !== 0) { //当设置的时间等于0时,不设置expires属性,cookie在浏览器关闭后删除 41 | 42 | let exp = new Date(); 43 | exp.setTime(exp.getTime() + day * 24 * 60 * 60 * 1000); 44 | document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString(); 45 | 46 | } else { 47 | 48 | document.cookie = name + "=" + escape(value); 49 | 50 | } 51 | 52 | }; 53 | 54 | export function delCookie (name) { 55 | let exp = new Date() 56 | exp.setTime(exp.getTime() - 10000) 57 | let cval = getCookie(name); 58 | if(cval!=null) 59 | document.cookie= name + "="+cval+";expires="+exp.toGMTString(); 60 | 61 | } 62 | 63 | -------------------------------------------------------------------------------- /frontend/src/utils/request.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | import axios from 'axios' 4 | import router from '../router' 5 | 6 | const service = axios.create({ 7 | baseURL: process.env.BASE_API, 8 | withCredentials: true, 9 | timeout: 60000 10 | }) 11 | 12 | service.interceptors.response.use((response) => { 13 | return response.data 14 | }, (error) => { 15 | if (error && error.response) { 16 | if (error.response.status === 401){ 17 | router.replace({name: 'login'}) 18 | return {'status': 'failed', 'data': '请先登录~'} 19 | } 20 | else if (error.response.status === 403){ 21 | return {'status': 'failed', 'data': '当前用户没有操作权限哦~'} 22 | } 23 | else if (error.response.status === 500){ 24 | return {'status': 'failed', 'data': '服务器内部错误啦~请尝试刷新重试'} 25 | } 26 | else if (error.response.status === 501){ 27 | return {'status': 'failed', 'data': '服务器发生神秘事件~请尝试刷新重试'} 28 | } 29 | else if (error.response.status === 502){ 30 | return {'status': 'failed', 'data': '服务器网关坏掉啦~请尝试刷新重试'} 31 | } 32 | else if (error.response.status === 503){ 33 | return {'status': 'failed', 'data': '服务器不可用啦~请尝试刷新重试'} 34 | } 35 | else if (error.response.status === 504){ 36 | return {'status': 'failed', 'data': '服务器响应超时啦~请尝试刷新重试'} 37 | } 38 | return Promise.reject(error.response.data) 39 | } 40 | return Promise.reject(error) 41 | }) 42 | export default service 43 | -------------------------------------------------------------------------------- /frontend/src/views/About.vue: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /frontend/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 71 | 72 | 159 | -------------------------------------------------------------------------------- /frontend/src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 80 | 81 | 143 | -------------------------------------------------------------------------------- /frontend/src/views/More.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /frontend/src/views/Project.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 82 | 83 | 101 | -------------------------------------------------------------------------------- /frontend/src/views/UITest.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /frontend/src/views/interfaceTestProject/api/automation/AutomationTest.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 30 | 31 | 54 | -------------------------------------------------------------------------------- /frontend/src/vuex/actions.js: -------------------------------------------------------------------------------- 1 | // 接口用例页面分页排序等信息 2 | export const setApiCasePageInfo = ({commit}) => { 3 | commit('setApiCasePageInfo') 4 | } 5 | // 用例列表页面分页排序等信息 6 | export const setApiCaseSuitePageInfo = ({commit}) => { 7 | commit('setApiCaseSuitePageInfo') 8 | } 9 | -------------------------------------------------------------------------------- /frontend/src/vuex/getters.js: -------------------------------------------------------------------------------- 1 | // 获取接口用例页面分页排序等信息 2 | export const getApiCasePageInfo = state => { 3 | return state.apiCasePageInfo 4 | }; 5 | // 获取用例列表页面分页排序等信息 6 | export const getApiCaseSuitePageInfo = state => { 7 | return state.apiCaseSuitePageInfo 8 | }; 9 | -------------------------------------------------------------------------------- /frontend/src/vuex/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import * as actions from './actions' 4 | import * as getters from './getters' 5 | 6 | Vue.use(Vuex); 7 | 8 | // 应用初始状态 9 | const state = { 10 | initPageInfo:{ 11 | size: 10, 12 | skip: 0, 13 | sortBy: 'createAt', 14 | order: 'descending', 15 | currentPage: 1, 16 | }, 17 | apiCasePageInfo:[], 18 | apiCaseSuitePageInfo:[], 19 | }; 20 | 21 | // 定义所需的 mutations 22 | const mutations = { 23 | setApiCasePageInfo(state, info) { 24 | let identicalIdIndex = state.apiCasePageInfo.findIndex(i => i.caseSuiteId === info.caseSuiteId) 25 | let hasIdenticalInfo = identicalIdIndex === -1 ? false : true 26 | hasIdenticalInfo ? state.apiCasePageInfo[identicalIdIndex] = 27 | Object.assign({}, state.apiCasePageInfo[identicalIdIndex], info): 28 | state.apiCasePageInfo.push(Object.assign({}, state.initPageInfo, info)) 29 | }, 30 | setApiCaseSuitePageInfo(state, info) { 31 | let identicalIdIndex = state.apiCaseSuitePageInfo.findIndex(i => i.projectId === info.projectId) 32 | let hasIdenticalInfo = identicalIdIndex === -1 ? false : true 33 | hasIdenticalInfo ? state.apiCaseSuitePageInfo[identicalIdIndex] = 34 | Object.assign({}, state.apiCaseSuitePageInfo[identicalIdIndex], info): 35 | state.apiCaseSuitePageInfo.push(Object.assign({}, state.initPageInfo, info)) 36 | } 37 | }; 38 | 39 | // 创建 store 实例 40 | export default new Vuex.Store({ 41 | actions, 42 | getters, 43 | state, 44 | mutations, 45 | namespaces: true 46 | }) 47 | -------------------------------------------------------------------------------- /frontend/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/static/.gitkeep -------------------------------------------------------------------------------- /frontend/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/frontend/static/favicon.ico -------------------------------------------------------------------------------- /frontend/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /frontend/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /frontend/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function karmaConfig (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /frontend/test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /images/NLP模型启动成功输出.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/NLP模型启动成功输出.png -------------------------------------------------------------------------------- /images/NLP部署失败.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/NLP部署失败.png -------------------------------------------------------------------------------- /images/SeeYou平台思维导图.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/SeeYou平台思维导图.jpg -------------------------------------------------------------------------------- /images/不使用NLP模型方法1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/不使用NLP模型方法1.png -------------------------------------------------------------------------------- /images/不使用NLP模型方法2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/不使用NLP模型方法2.png -------------------------------------------------------------------------------- /images/定时任务配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/定时任务配置.png -------------------------------------------------------------------------------- /images/控制台输出1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/控制台输出1.png -------------------------------------------------------------------------------- /images/控制台输出2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/控制台输出2.png -------------------------------------------------------------------------------- /images/操作界面展示.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/操作界面展示.png -------------------------------------------------------------------------------- /images/数据导入展示.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/数据导入展示.png -------------------------------------------------------------------------------- /images/测试报告展示.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/测试报告展示.png -------------------------------------------------------------------------------- /images/用例接口列表界面展示.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Valuebai/SeeYou-Platform/2585e0b20137a65e62522ed3e7ea38c31bd1c573/images/用例接口列表界面展示.jpg -------------------------------------------------------------------------------- /node_modules/.package_versions.json: -------------------------------------------------------------------------------- 1 | {} --------------------------------------------------------------------------------