├── .gitignore ├── JIA.xmind ├── README.md ├── backend ├── .funignore ├── .gitignore ├── Funfile ├── bootstrap ├── clazz.py ├── data │ └── .gitignore ├── func.py ├── main.py ├── template.yml └── test.py └── frontend ├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ ├── 600x200.png │ ├── logo.png │ ├── logo.svg │ └── placeholder.png ├── config.js ├── main.js ├── plugins │ └── vuetify.js └── utils.js ├── vue.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea/ -------------------------------------------------------------------------------- /JIA.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/JIA.xmind -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 学习通作业聚合 2 | ## 起因 3 | 学习通的应用设计极其反人类,如果你想知道自己还有什么作业,你得每门课点开挨个看一遍 4 | 5 | 为了节约生命,写了一个作业通的作业聚合 6 | 7 | ## Demo地址 8 | https://work.learningman.top/ 9 | 10 | (国内的两台机子都被学习通拉黑了 IP,只能部署到香港阿里云,导致后端的爬虫慢到离谱,TTFB 大部分时候都在 8s 左右,如果有条件的话,建议自行部署) 11 | 12 | 代码写得比较狂野,见谅 13 | 14 | ## TODO 15 | 理论上来说,爬虫的请求数可以缩到现在的三分之一,获取每条作业信息的三条请求中两条是无意义的 16 | 17 | 但我实在不想和学习通前端的代码继续搏斗了,真的没见过这么离谱的代码。 18 | 19 | 如果有人有能力的话,希望能帮忙修一修 20 | 21 | 工作量约等于重写) 22 | 23 | ## 最后 24 | 我这里应该放一个博文的链接,但是因为懒,还没写出来,所以我先放一个博客链接在这) 25 | 26 | https://learningman.top/ 27 | 28 | 我相信应该有人能用上) 29 | -------------------------------------------------------------------------------- /backend/.funignore: -------------------------------------------------------------------------------- 1 | .env 2 | template.yml 3 | .funignore 4 | venv/ 5 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | cover/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | .pybuilder/ 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | # For a library or package, you might want to ignore these files since the code is 89 | # intended to run in multiple environments; otherwise, check them in: 90 | # .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 96 | # install all needed dependencies. 97 | #Pipfile.lock 98 | 99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 100 | __pypackages__/ 101 | 102 | # Celery stuff 103 | celerybeat-schedule 104 | celerybeat.pid 105 | 106 | # SageMath parsed files 107 | *.sage.py 108 | 109 | # Environments 110 | .env 111 | .venv 112 | env/ 113 | venv/ 114 | ENV/ 115 | env.bak/ 116 | venv.bak/ 117 | 118 | # Spyder project settings 119 | .spyderproject 120 | .spyproject 121 | 122 | # Rope project settings 123 | .ropeproject 124 | 125 | # mkdocs documentation 126 | /site 127 | 128 | # mypy 129 | .mypy_cache/ 130 | .dmypy.json 131 | dmypy.json 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | 136 | # pytype static type analyzer 137 | .pytype/ 138 | 139 | # Cython debug symbols 140 | cython_debug/ 141 | 142 | ### Example user template template 143 | ### Example user template 144 | 145 | # IntelliJ project files 146 | .idea 147 | *.iml 148 | out 149 | gen 150 | 151 | .fun/ -------------------------------------------------------------------------------- /backend/Funfile: -------------------------------------------------------------------------------- 1 | RUNTIME custom 2 | RUN mkdir -p ~/.pip 3 | RUN echo "[global]" >> ~/.pip/pip.conf 4 | RUN echo "index-url = https://mirrors.aliyun.com/pypi/simple" >> ~/.pip/pip.conf 5 | RUN echo "[install]" >> ~/.pip/pip.conf 6 | RUN echo "trusted-host=mirrors.aliyun.com" >> ~/.pip/pip.conf 7 | RUN fun-install pip install uvicorn 8 | RUN fun-install pip install fastapi 9 | RUN fun-install pip install pydantic 10 | RUN fun-install pip install requests 11 | RUN fun-install pip install bs4 12 | RUN fun-install pip install lxml 13 | -------------------------------------------------------------------------------- /backend/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | uvicorn main:app --host=0.0.0.0 --port=9000 3 | -------------------------------------------------------------------------------- /backend/clazz.py: -------------------------------------------------------------------------------- 1 | from pydantic import BaseModel 2 | import threading 3 | 4 | from bs4 import BeautifulSoup 5 | 6 | 7 | class loginValid(BaseModel): 8 | enc: str 9 | uuid: str 10 | session: dict 11 | 12 | 13 | threadLock = threading.Lock() 14 | 15 | 16 | class workThread(threading.Thread): 17 | def __init__(self, singleCourse, s, allWorkInfo): 18 | threading.Thread.__init__(self) 19 | # singleCourse,s,allWorkInfo 20 | self.singleCourse = singleCourse 21 | self.s = s 22 | self.allWorkInfo = allWorkInfo 23 | 24 | def run(self): 25 | courseURL = str(self.singleCourse.find('a')['href']) 26 | courseName = str(self.singleCourse.find('span').string) 27 | teacherName = str(self.singleCourse.find('p').string) 28 | print(courseURL,courseName,teacherName) 29 | 30 | return 31 | 32 | courseHTML = self.s.get(url=courseURL).content.decode() 33 | courseHTMLBS = BeautifulSoup(courseHTML, 'lxml') 34 | 35 | courseWorkURL = str(courseHTMLBS.find('li', dataname="zy-stu").a['data-url']) + '&status=1' 36 | 37 | courseHTMLBS.decompose() 38 | # print(courseWorkURL) 39 | 40 | courseWorkHTML = self.s.get(courseWorkURL).content.decode() 41 | courseWorkHTMLBS = BeautifulSoup(courseWorkHTML, 'lxml') 42 | 43 | for oneWork in courseWorkHTMLBS.find_all('li'): 44 | if oneWork.find('div', class_='icon-zy-g'): 45 | continue 46 | workName = oneWork.find(class_='fl').string 47 | workURL = oneWork['data'] 48 | workTime = str(oneWork.find(class_='time').contents[-1]).replace('\r\n', '').strip() 49 | singleWorkInfo = { 50 | 'courseName': courseName, 51 | 'teacherName': teacherName, 52 | 'workName': workName, 53 | 'workTime': workTime, 54 | 'workURL': workURL 55 | } 56 | # print(singleWorkInfo) 57 | threadLock.acquire() 58 | self.allWorkInfo.append(singleWorkInfo.copy()) 59 | threadLock.release() 60 | courseWorkHTMLBS.decompose() 61 | -------------------------------------------------------------------------------- /backend/data/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | *.* -------------------------------------------------------------------------------- /backend/func.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import base64 3 | import pickle 4 | from functools import partial 5 | 6 | import requests 7 | from bs4 import BeautifulSoup 8 | 9 | # from clazz import * 10 | 11 | loginURL = 'https://passport2.chaoxing.com/login?fid=&newversion=true&refer=http%3A%2F%2Fi.chaoxing.com' 12 | ua = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 13 | 'Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51'} 14 | 15 | 16 | def save(filename, content): 17 | with open(f'./data/{filename}.pickle', 'wb') as f: 18 | pickle.dump(content, f) 19 | 20 | 21 | def load(filename): 22 | with open(f'./data/{filename}.pickle', 'rb') as f: 23 | return pickle.load(f) 24 | 25 | 26 | def checkXXTConnect(): 27 | req = requests.get(loginURL, headers=ua) 28 | return req.ok 29 | 30 | 31 | def getLoginSession(): 32 | session = requests.session() 33 | session.headers.update(ua) 34 | content = session.get(url=loginURL).content.decode() 35 | htmlTag = BeautifulSoup(content, 'lxml') 36 | enc = htmlTag.find(id='enc')['value'] 37 | uuid = htmlTag.find(id='uuid')['value'] 38 | # print(enc, uuid) 39 | htmlTag.decompose() 40 | return session, enc, uuid 41 | 42 | 43 | def getLoginCode(): # 150s有效期 44 | session, enc, uuid = getLoginSession() 45 | # 获取session 46 | # 写入auth类,写入session 47 | # 获取图片返回 48 | loginPicURL = f'https://passport2.chaoxing.com/createqr?uuid={uuid}' 49 | loginPic = session.get(url=loginPicURL).content 50 | loginPicBase64 = 'data:image/png;base64,' + base64.b64encode(loginPic).decode() # 转好DataURL 51 | cookie = session.cookies.get_dict() 52 | session.close() 53 | return loginPicBase64, enc, uuid, cookie 54 | 55 | 56 | def checkLoginAuth(valid): 57 | authURL = 'https://passport2.chaoxing.com/getauthstatus' 58 | with requests.session() as s: 59 | s.cookies.update(valid.session) 60 | s.headers.update(ua) 61 | status = s.post(url=authURL, data={ 62 | 'enc': valid.enc, 63 | 'uuid': valid.uuid 64 | }).json()['status'] 65 | if status: 66 | return True, s.cookies.get_dict() 67 | else: 68 | return False, None 69 | 70 | 71 | def verify(session: dict): 72 | verifyURL = "https://mooc2-ans.chaoxing.com/visit/interaction" 73 | with requests.session() as s: 74 | s.cookies.update(session) 75 | s.headers.update(ua) 76 | redirect = not s.get("https://mooc2-ans.chaoxing.com/visit/interaction", allow_redirects=False).is_redirect 77 | return redirect 78 | 79 | 80 | def create_task(coro): 81 | loop = asyncio.get_running_loop() 82 | return loop.create_task(coro) 83 | 84 | 85 | async def getWorkInfo(session: dict): 86 | allWorkInfo = [] 87 | tasks = [] 88 | 89 | s = requests.session() 90 | s.cookies.update(session) 91 | s.headers.update(ua) 92 | 93 | lock = asyncio.Lock() 94 | 95 | courseListURL = 'https://mooc2-ans.chaoxing.com/visit/courses/list?rss=1&start=0&size=500&catalogId=0&searchname=' 96 | 97 | html = s.get(url=courseListURL).content.decode() 98 | htmlBS = BeautifulSoup(html, 'lxml') 99 | for singleCourse in htmlBS.find_all(class_='course-info'): # 虽然连接是旧版本的,但是解析课程名称和教师名称更方便 100 | tasks.append(parseOneCourse(singleCourse, s, allWorkInfo, lock)) 101 | htmlBS.decompose() 102 | 103 | print(tasks) 104 | 105 | await asyncio.wait(tasks) 106 | 107 | print("After every Task") 108 | print(allWorkInfo) 109 | 110 | return allWorkInfo 111 | 112 | 113 | async def parseOneCourse(singleCourse, s, allWorkInfo, lock): 114 | courseURL = str(singleCourse.find('a')['href']) + "&ismooc2=1" 115 | courseName = str(singleCourse.find('span').string) 116 | teacherName = str(singleCourse.find('p').string) 117 | 118 | future = asyncio.get_event_loop().run_in_executor(None, partial(s.get, url=courseURL)) 119 | 120 | courseHTML = await future 121 | 122 | courseHTMLBS = BeautifulSoup(courseHTML.content.decode(), 'lxml') 123 | 124 | courseWorkURL = str(courseHTMLBS.find('li', dataname="zy-stu").a['data-url']) + '&status=1' 125 | 126 | courseHTMLBS.decompose() 127 | 128 | future = asyncio.get_event_loop().run_in_executor(None, partial(s.get, url=courseWorkURL)) 129 | 130 | courseWorkHTML = await future 131 | 132 | courseWorkHTMLBS = BeautifulSoup(courseWorkHTML.content.decode(), 'lxml') 133 | 134 | for oneWork in courseWorkHTMLBS.find_all('li'): 135 | if oneWork.find('div', class_='icon-zy-g') or oneWork.find('div', class_='icon-hp-gy'): 136 | continue 137 | 138 | workName = str(oneWork.find(class_='fl').string) 139 | workURL = str(oneWork['data']) 140 | 141 | timeObj = oneWork.find(class_='time') 142 | if timeObj: 143 | workTime = str(timeObj.contents[-1]).replace('\r\n', '').strip() 144 | else: 145 | workTime = "" 146 | 147 | singleWorkInfo = { 148 | 'courseName': courseName, 149 | 'teacherName': teacherName, 150 | 'workName': workName, 151 | 'workTime': workTime, 152 | 'workURL': workURL 153 | } 154 | oneWork.decompose() 155 | 156 | async with lock: 157 | allWorkInfo.append(singleWorkInfo.copy()) 158 | 159 | courseWorkHTMLBS.decompose() 160 | 161 | print("Finish one Task") 162 | -------------------------------------------------------------------------------- /backend/main.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | from fastapi import FastAPI, Body 3 | from fastapi.middleware.cors import CORSMiddleware 4 | 5 | from clazz import * 6 | from func import * 7 | 8 | app = FastAPI() 9 | 10 | app.add_middleware( 11 | CORSMiddleware, 12 | allow_origins=["*"], 13 | allow_credentials=True, 14 | allow_methods=["*"], 15 | allow_headers=["*"], 16 | ) 17 | 18 | @app.get('/') 19 | async def errorHandler(): 20 | return ['Nothing Here'] 21 | 22 | 23 | @app.get('/checkRunning') 24 | async def checkRunning(): 25 | return True 26 | 27 | 28 | @app.get('/checkXXTConnect') 29 | async def checkXXT(): 30 | return checkXXTConnect() 31 | # return False 32 | 33 | 34 | @app.get('/login/code') 35 | async def loginCode(): 36 | picBase64, enc, uuid, session = getLoginCode() 37 | valid = loginValid(enc=enc, uuid=uuid, session=session) 38 | 39 | return {'pic': picBase64, 'valid': valid} 40 | 41 | 42 | @app.post('/login/auth') 43 | async def auth( 44 | valid: loginValid = Body(..., embed=True) 45 | ): 46 | status, session = checkLoginAuth(valid) 47 | return { 48 | 'status': status, 49 | 'session': session 50 | } 51 | 52 | 53 | @app.post('/login/verifyCookies') 54 | async def verifyCookies( 55 | session: dict = Body(..., embed=True) 56 | ): 57 | return verify(session) 58 | 59 | 60 | @app.post('/info') 61 | async def info( 62 | session: dict = Body(..., embed=True) 63 | ): 64 | return {'workInfo': await getWorkInfo(session)} 65 | 66 | if __name__ == '__main__': 67 | uvicorn.run('main:app',port=4005,debug=True) -------------------------------------------------------------------------------- /backend/template.yml: -------------------------------------------------------------------------------- 1 | ROSTemplateFormatVersion: '2015-09-01' 2 | Transform: 'Aliyun::Serverless-2018-04-03' 3 | Resources: 4 | backend: 5 | Type: 'Aliyun::Serverless::Service' 6 | Properties: 7 | Description: 'fastapi' 8 | backend: 9 | Type: 'Aliyun::Serverless::Function' 10 | Properties: 11 | Handler: main.app 12 | Runtime: custom 13 | CodeUri: './' 14 | Events: 15 | httpTrigger: 16 | Type: HTTP 17 | Properties: 18 | AuthType: ANONYMOUS 19 | Methods: ['POST', 'GET'] 20 | my_domain: 21 | Type: 'Aliyun::Serverless::CustomDomain' 22 | Properties: 23 | DomainName: Auto 24 | Protocol: HTTP 25 | RouteConfig: 26 | Routes: 27 | '/*': 28 | ServiceName: backend 29 | FunctionName: backend -------------------------------------------------------------------------------- /backend/test.py: -------------------------------------------------------------------------------- 1 | def append(a: list): 2 | a.append("append") 3 | 4 | 5 | a = ['one'] 6 | 7 | append(a) 8 | 9 | print(a) 10 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # frontend 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.21.2", 12 | "core-js": "^3.6.5", 13 | "localStorage": "^1.0.4", 14 | "vue": "^2.6.11", 15 | "vuetify": "^2.6.10" 16 | }, 17 | "devDependencies": { 18 | "@vue/cli-plugin-babel": "~4.5.0", 19 | "@vue/cli-plugin-eslint": "~4.5.0", 20 | "@vue/cli-service": "~4.5.0", 21 | "babel-eslint": "^10.1.0", 22 | "css-loader": "^4.3.0", 23 | "eslint": "^6.7.2", 24 | "eslint-plugin-vue": "^6.2.2", 25 | "sass": "^1.19.0", 26 | "sass-loader": "^8.0.0", 27 | "vue-cli-plugin-vuetify": "~2.0.7", 28 | "vue-template-compiler": "^2.6.11", 29 | "vuetify-loader": "^1.3.0" 30 | }, 31 | "eslintConfig": { 32 | "root": true, 33 | "env": { 34 | "node": true 35 | }, 36 | "extends": [ 37 | "plugin:vue/essential", 38 | "eslint:recommended" 39 | ], 40 | "parserOptions": { 41 | "parser": "babel-eslint" 42 | }, 43 | "rules": {} 44 | }, 45 | "browserslist": [ 46 | "> 1%", 47 | "last 2 versions", 48 | "not dead" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | JobInfoAggregation 9 | 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 194 | 195 | 333 | 334 | -------------------------------------------------------------------------------- /frontend/src/assets/600x200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/src/assets/600x200.png -------------------------------------------------------------------------------- /frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/src/assets/logo.png -------------------------------------------------------------------------------- /frontend/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Artboard 46 2 | -------------------------------------------------------------------------------- /frontend/src/assets/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/src/assets/placeholder.png -------------------------------------------------------------------------------- /frontend/src/config.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/src/config.js -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import vuetify from './plugins/vuetify'; 4 | 5 | const isDebug_mode = process.env.NODE_ENV !== 'production' 6 | Vue.config.debug = isDebug_mode 7 | Vue.config.devtools = isDebug_mode 8 | Vue.config.productionTip = isDebug_mode 9 | 10 | if(isDebug_mode){ 11 | //Vue.prototype.$apiurl = 'http://127.0.0.1:8000' 12 | Vue.prototype.$apiurl = 'https://ajax.work.learningman.top' 13 | } else { 14 | Vue.prototype.$apiurl = 'https://ajax.work.learningman.top' 15 | } 16 | 17 | 18 | new Vue({ 19 | vuetify, 20 | render: h => h(App) 21 | }).$mount('#app') 22 | -------------------------------------------------------------------------------- /frontend/src/plugins/vuetify.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuetify from 'vuetify/lib'; 3 | 4 | Vue.use(Vuetify); 5 | 6 | export default new Vuetify({ 7 | }); 8 | -------------------------------------------------------------------------------- /frontend/src/utils.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zxilly/JobInformationAggregation/1f41b674dd33447da64b9c648f8a9f941cb96470/frontend/src/utils.js -------------------------------------------------------------------------------- /frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "transpileDependencies": [ 3 | "vuetify" 4 | ], 5 | 6 | chainWebpack(config) { 7 | // set whitespace 8 | config.module 9 | .rule("vue") 10 | .use("vue-loader") 11 | .loader("vue-loader") 12 | .tap(options => { 13 | options.compilerOptions.whitespace = 'preserve'; 14 | return options; 15 | }) 16 | .end(); 17 | } 18 | } 19 | 20 | --------------------------------------------------------------------------------