4 | */
5 | (function ($) {
6 | 'use strict';
7 |
8 | $.fn.bootstrapTable.locales['zh-CN'] = {
9 | formatLoadingMessage: function () {
10 | return '正在努力地加载数据中,请稍候……';
11 | },
12 | formatRecordsPerPage: function (pageNumber) {
13 | return '每页显示 ' + pageNumber + ' 条记录';
14 | },
15 | formatShowingRows: function (pageFrom, pageTo, totalRows) {
16 | return '显示第 ' + pageFrom + ' 到第 ' + pageTo + ' 条记录,总共 ' + totalRows + ' 条记录';
17 | },
18 | formatSearch: function () {
19 | return '搜索';
20 | },
21 | formatNoMatches: function () {
22 | return '没有找到匹配的记录';
23 | },
24 | formatPaginationSwitch: function () {
25 | return '隐藏/显示分页';
26 | },
27 | formatRefresh: function () {
28 | return '刷新';
29 | },
30 | formatToggle: function () {
31 | return '切换';
32 | },
33 | formatColumns: function () {
34 | return '列';
35 | }
36 | };
37 |
38 | $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales['zh-CN']);
39 |
40 | })(jQuery);
41 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/diff/diff.js:
--------------------------------------------------------------------------------
1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE
3 |
4 | (function(mod) {
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS
6 | mod(require("../../lib/codemirror"));
7 | else if (typeof define == "function" && define.amd) // AMD
8 | define(["../../lib/codemirror"], mod);
9 | else // Plain browser env
10 | mod(CodeMirror);
11 | })(function(CodeMirror) {
12 | "use strict";
13 |
14 | CodeMirror.defineMode("diff", function() {
15 |
16 | var TOKEN_NAMES = {
17 | '+': 'positive',
18 | '-': 'negative',
19 | '@': 'meta'
20 | };
21 |
22 | return {
23 | token: function(stream) {
24 | var tw_pos = stream.string.search(/[\t ]+?$/);
25 |
26 | if (!stream.sol() || tw_pos === 0) {
27 | stream.skipToEnd();
28 | return ("error " + (
29 | TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');
30 | }
31 |
32 | var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();
33 |
34 | if (tw_pos === -1) {
35 | stream.skipToEnd();
36 | } else {
37 | stream.pos = tw_pos;
38 | }
39 |
40 | return token_name;
41 | }
42 | };
43 | });
44 |
45 | CodeMirror.defineMIME("text/x-diff", "diff");
46 |
47 | });
48 |
--------------------------------------------------------------------------------
/back/static/js/demo/bootstrap_table_test2.json:
--------------------------------------------------------------------------------
1 |
2 | [
3 | {
4 | "name": "asSelect",
5 | "star": 777,
6 | "license": "MIT",
7 | "description": "A jQuery plugin to select multiple elements with checkboxes and radio:)",
8 | "url": "https://github.com/amazingSurger/jquery-asSelect"
9 | },
10 | {
11 | "name": "Bootstrap Table",
12 | "star": 778,
13 | "license": "MIT & XXX",
14 | "description": "Bootstrap table displays data in a tabular format and offers rich support to radio, checkbox, sort, pagination and so on. ",
15 | "url": "https://github.com/wenzhixin/bootstrap-table"
16 | },
17 | {
18 | "name": "asDatepicker",
19 | "star": 779,
20 | "license": "MIT",
21 | "description": "A jQuery datepicker plugin for best .",
22 | "url": "https://github.com/amazingSurger/jquery-asDatepicker"
23 | },
24 | {
25 | "name": "asColorpicker",
26 | "star": 780,
27 | "license": "MIT",
28 | "description": "A jQuery colorpicker for best .",
29 | "url": "https://github.com/amazingSurger/jquery-asColorpicker"
30 | }
31 | ]
32 |
--------------------------------------------------------------------------------
/back/static/js/plugins/layer/layim/data/groups.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 1,
3 | "msg": "ok",
4 | "data": [
5 | {
6 | "id": "100001",
7 | "name": "無言的蒁説",
8 | "face": "img/a1.jpg"
9 | },
10 | {
11 | "id": "100002",
12 | "name": "婷宝奢侈品",
13 | "face": "img/a2.jpg"
14 | },
15 | {
16 | "id": "100003",
17 | "name": "忆恨思爱",
18 | "face": "img/a3.jpg"
19 | },
20 | {
21 | "id": "100004",
22 | "name": "天涯奥拓慢",
23 | "face": "img/a4.jpg"
24 | },
25 | {
26 | "id": "100005",
27 | "name": "雨落无声的天空",
28 | "face": "img/a5.jpg"
29 | },
30 | {
31 | "id": "100006",
32 | "name": "李越LycorisRadiate",
33 | "face": "img/a6.jpg"
34 | },
35 | {
36 | "id": "100007",
37 | "name": "冯胖妞张直丑",
38 | "face": "img/a7.jpg"
39 | },
40 | {
41 | "id": "100008",
42 | "name": "陈龙hmmm",
43 | "face": "img/a8.jpg"
44 | },
45 | {
46 | "id": "100009",
47 | "name": "别闹哥胆儿小",
48 | "face": "img/a9.jpg"
49 | },
50 | {
51 | "id": "100010",
52 | "name": "锅锅锅锅萌哒哒 ",
53 | "face": "img/a10.jpg"
54 | }
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/back/static/js/plugins/suggest/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "message": "",
3 | "value": [
4 | {
5 | "userName": "淳芸",
6 | "shortAccount": "chunyun",
7 | "userId": 20001
8 | }, {
9 | "userName": "orion-01",
10 | "shortAccount": "chunyun",
11 | "userId": 20000
12 | }, {
13 | "userName": "穆晓晨",
14 | "shortAccount": "chunyun",
15 | "userId": 20002
16 | }, {
17 | "userName": "张欢引",
18 | "shortAccount": "chunyun",
19 | "userId": 20003
20 | }, {
21 | "userName": "吴琼",
22 | "shortAccount": "wuqiong",
23 | "userId": 20004
24 | }, {
25 | "userName": "吴东鹏",
26 | "shortAccount": "wudongpeng",
27 | "userId": 20005
28 | }, {
29 | "userName": "黄少铅",
30 | "shortAccount": "huangshaoqian",
31 | "userId": 20006
32 | }, {
33 | "userName": "胡运燕",
34 | "shortAccount": "yunyan",
35 | "userId": 20007
36 | }, {
37 | "userName": "刘幸",
38 | "shortAccount": "liuxing",
39 | "userId": 20008
40 | }, {
41 | "userName": "陈媛媛",
42 | "shortAccount": "chenyuanyuan",
43 | "userId": 20009
44 | }, {
45 | "userName": "旷东林",
46 | "shortAccount": "chunyun",
47 | "userId": 20010
48 | }, {
49 | "userName": "唐宏禹",
50 | "shortAccount": "chunyun",
51 | "userId": 20011
52 | }, {
53 | "userName": "旷东林",
54 | "shortAccount": "kuangdonglin",
55 | "userId": 20010
56 | }, {
57 | "userName": "唐宏禹",
58 | "shortAccount": "tanghongyu",
59 | "userId": 20011
60 | }
61 | ],
62 | "code": 200,
63 | "redirect": ""
64 | }
65 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | appdirs==1.4.4
2 | asgiref==3.7.2
3 | attrs==23.2.0
4 | autobahn==23.6.2
5 | Automat==22.10.0
6 | background==0.2.1
7 | certifi==2023.11.17
8 | cffi==1.16.0
9 | channels==4.0.0
10 | colorama==0.4.6
11 | constantly==23.10.4
12 | contourpy==1.2.0
13 | cryptography==42.0.0
14 | cycler==0.12.1
15 | daphne==4.0.0
16 | Django==5.0.1
17 | django-background-tasks==1.2.5
18 | django-compat==1.0.15
19 | dwebsocket==0.5.12
20 | Faker==18.10.0
21 | fonttools==4.47.2
22 | greenlet==3.0.3
23 | h11==0.14.0
24 | hyperlink==21.0.0
25 | idna==3.6
26 | importlib-metadata==7.0.1
27 | incremental==22.10.0
28 | kiwisolver==1.4.5
29 | lxml==5.1.0
30 | matplotlib==3.8.2
31 | mysqlclient==2.2.1
32 | nest-asyncio==1.6.0
33 | numpy==1.26.3
34 | outcome==1.3.0.post0
35 | packaging==23.2
36 | pandas==2.2.0
37 | pillow==10.2.0
38 | pyasn1==0.5.1
39 | pyasn1-modules==0.3.0
40 | pycparser==2.21
41 | pyee==8.2.2
42 | PyMySQL==1.1.0
43 | pyOpenSSL==24.0.0
44 | pyparsing==3.1.1
45 | pyppeteer==1.0.2
46 | PySocks==1.7.1
47 | python-dateutil==2.8.2
48 | pytz==2023.3.post1
49 | selenium==4.17.2
50 | service-identity==24.1.0
51 | six==1.16.0
52 | sniffio==1.3.0
53 | sortedcontainers==2.4.0
54 | SQLAlchemy==2.0.25
55 | sqlparse==0.4.4
56 | tqdm==4.66.1
57 | trio==0.24.0
58 | trio-websocket==0.11.1
59 | Twisted==23.10.0
60 | twisted-iocpsupport==1.0.4
61 | txaio==23.1.1
62 | typing_extensions==4.9.0
63 | tzdata==2023.4
64 | urllib3==1.26.18
65 | websockets==10.4
66 | wordcloud==1.9.3
67 | wsproto==1.2.0
68 | zipp==3.17.0
69 | zope.interface==6.1
70 |
--------------------------------------------------------------------------------
/back/static/js/content.js:
--------------------------------------------------------------------------------
1 | // var $parentNode = window.parent.document;
2 |
3 | // function $childNode(name) {
4 | // return window.frames[name]
5 | // }
6 |
7 | // // tooltips
8 | // $('.tooltip-demo').tooltip({
9 | // selector: "[data-toggle=tooltip]",
10 | // container: "body"
11 | // });
12 |
13 | // // 使用animation.css修改Bootstrap Modal
14 | // $('.modal').appendTo("body");
15 |
16 | // $("[data-toggle=popover]").popover();
17 |
18 |
19 | //判断当前页面是否在iframe中
20 | if (top == this) {
21 | var gohome = '';
22 | $('body').append(gohome);
23 | }
24 |
25 | //animation.css
26 | function animationHover(element, animation) {
27 | element = $(element);
28 | element.hover(
29 | function () {
30 | element.addClass('animated ' + animation);
31 | },
32 | function () {
33 | //动画完成之前移除class
34 | window.setTimeout(function () {
35 | element.removeClass('animated ' + animation);
36 | }, 2000);
37 | });
38 | }
39 |
40 | //拖动面板
41 | function WinMove() {
42 | var element = "[class*=col]";
43 | var handle = ".ibox-title";
44 | var connect = "[class*=col]";
45 | $(element).sortable({
46 | handle: handle,
47 | connectWith: connect,
48 | tolerance: 'pointer',
49 | forcePlaceholderSize: true,
50 | opacity: 0.8,
51 | })
52 | .disableSelection();
53 | };
54 |
--------------------------------------------------------------------------------
/back/consumers.py:
--------------------------------------------------------------------------------
1 | import json
2 | import asyncio
3 | from channels.generic.websocket import AsyncWebsocketConsumer
4 | from channels.layers import get_channel_layer
5 | from asgiref.sync import async_to_sync
6 | from .utils.boss import run_crawl # 假设这是您的爬虫程序
7 |
8 |
9 | class ChatConsumer(AsyncWebsocketConsumer):
10 | def __init__(self, *args, **kwargs):
11 | super().__init__(*args, **kwargs)
12 | self.crawl_running = False # 控制爬虫运行的标志
13 | async def connect(self):
14 | await self.accept()
15 |
16 | async def disconnect(self, close_code):
17 | pass
18 |
19 | async def receive(self, text_data):
20 | text_data_json = json.loads(text_data)
21 | message = text_data_json['message']
22 |
23 | if message == "start":
24 | self.crawl_running = True
25 | await self.start_crawl()
26 | elif message == "stop":
27 | self.crawl_running = False
28 |
29 | async def start_crawl(self):
30 | try:
31 | # 确保 run_crawl 是一个生成器
32 | for output in run_crawl():
33 | if not self.crawl_running:
34 | break # 如果收到停止指令,退出循环
35 | send_msg = json.dumps({'message': output},ensure_ascii=False)
36 | # 解码 JSON 字符串中的 Unicode 转义字符
37 | print(f"向前端发送消息:{send_msg}")
38 | await self.send(text_data=send_msg)
39 | await asyncio.sleep(0.5) # 控制消息发送的速度
40 | except Exception as e:
41 | await self.send(text_data=json.dumps({'error': str(e)}))
42 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/ntriples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: NTriples mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
28 |
29 |
30 | NTriples mode
31 |
40 |
41 |
44 | MIME types defined: text/n-triples.
45 |
46 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/spreadsheet/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Spreadsheet mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
25 |
26 |
27 | Spreadsheet mode
28 |
29 |
30 |
37 |
38 | MIME types defined: text/x-spreadsheet.
39 |
40 | The Spreadsheet Mode
41 | Created by Robert Plummer
42 |
43 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/http/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: HTTP mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | HTTP mode
27 |
28 |
29 |
39 |
40 |
43 |
44 | MIME types defined: message/http.
45 |
46 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/solr/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Solr mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
33 |
34 |
35 | Solr mode
36 |
37 |
38 |
47 |
48 |
49 |
55 |
56 | MIME types defined: text/x-solr.
57 |
58 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/z80/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Z80 assembly mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | Z80 assembly mode
27 |
28 |
29 |
44 |
45 |
50 |
51 | MIME type defined: text/x-z80.
52 |
53 |
--------------------------------------------------------------------------------
/back/utils/decorators.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.decorators import login_required
2 | from django.shortcuts import HttpResponse
3 | """
4 | 获取用户session中的信息并返回
5 | """
6 |
7 | def get_user_from_session(view_func):
8 | def wrapper(request, *args, **kwargs):
9 | # 从会话中获取用户信息
10 | is_login = request.session.get('is_login')
11 | session_username = request.session.get("username")
12 | session_phone = request.session.get("phone")
13 | session_role = request.session.get("role")
14 | session_pic = request.session.get("pic")
15 | session_list = [is_login, session_username, session_phone, session_role, session_pic]
16 | # 将用户信息作为参数传递给视图函数
17 | return view_func(request, session_list=session_list,*args, **kwargs)
18 | return wrapper
19 |
20 |
21 | def has_permission(view_func):
22 | def _wrapped_view(request, *args, **kwargs):
23 | if request.user.is_authenticated:
24 | user_groups = Group.objects.filter(users=request.user) # 获取用户所属的权限组
25 | user_permissions = set() # 用于存储用户所具有的权限索引
26 | for group in user_groups:
27 | rules = group.rules.split(',') # 将权限组的rules字段拆分成索引列表
28 | user_permissions.update(rules) # 将权限索引添加到用户权限集合中
29 | requested_url = request.path_info # 获取请求的路由地址
30 | if requested_url in user_permissions:
31 | return view_func(request, *args, **kwargs)
32 | else:
33 | return HttpResponse("你没有访问这个页面的权限!")
34 | else:
35 | return HttpResponse("Please log in to access this page.")
36 | return login_required(_wrapped_view)
37 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/ecl/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: ECL mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | ECL mode
27 |
45 |
48 |
49 | Based on CodeMirror's clike mode. For more information see HPCC Systems web site.
50 | MIME types defined: text/x-ecl.
51 |
52 |
53 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/rust/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Rust mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | Rust mode
27 |
28 |
29 |
52 |
53 |
58 |
59 | MIME types defined: text/x-rustsrc.
60 |
61 |
--------------------------------------------------------------------------------
/back/static/css/plugins/iCheck/custom.css:
--------------------------------------------------------------------------------
1 | /* iCheck plugin Square skin, green
2 | ----------------------------------- */
3 | .icheckbox_square-green,
4 | .iradio_square-green {
5 | display: inline-block;
6 | *display: inline;
7 | vertical-align: middle;
8 | margin: 0;
9 | padding: 0;
10 | width: 22px;
11 | height: 22px;
12 | background: url(green.png) no-repeat;
13 | border: none;
14 | cursor: pointer;
15 | }
16 |
17 | .icheckbox_square-green {
18 | background-position: 0 0;
19 | }
20 | .icheckbox_square-green.hover {
21 | background-position: -24px 0;
22 | }
23 | .icheckbox_square-green.checked {
24 | background-position: -48px 0;
25 | }
26 | .icheckbox_square-green.disabled {
27 | background-position: -72px 0;
28 | cursor: default;
29 | }
30 | .icheckbox_square-green.checked.disabled {
31 | background-position: -96px 0;
32 | }
33 |
34 | .iradio_square-green {
35 | background-position: -120px 0;
36 | }
37 | .iradio_square-green.hover {
38 | background-position: -144px 0;
39 | }
40 | .iradio_square-green.checked {
41 | background-position: -168px 0;
42 | }
43 | .iradio_square-green.disabled {
44 | background-position: -192px 0;
45 | cursor: default;
46 | }
47 | .iradio_square-green.checked.disabled {
48 | background-position: -216px 0;
49 | }
50 |
51 | /* HiDPI support */
52 | @media (-o-min-device-pixel-ratio: 5/4), (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {
53 | .icheckbox_square-green,
54 | .iradio_square-green {
55 | background-image: url(green@2x.png);
56 | -webkit-background-size: 240px 24px;
57 | background-size: 240px 24px;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/back/static/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * bootstrap-table - v1.9.0 - 2015-09-30
3 | * https://github.com/wenzhixin/bootstrap-table
4 | * Copyright (c) 2015 zhixin wen
5 | * Licensed MIT License
6 | */
7 | !function(a){"use strict";var b=function(b,c){b.options.columnsHidden.length>0&&a.each(b.columns,function(d,e){-1!==b.options.columnsHidden.indexOf(e.field)&&e.visible!==c&&b.toggleColumn(a.fn.bootstrapTable.utils.getFieldIndex(b.columns,e.field),c,!0)})},c=function(a){(a.options.height||a.options.showFooter)&&setTimeout(a.resetView,1)},d=function(a,b,d){a.options.minHeight?b<=a.options.minWidth&&d<=a.options.minHeight?e(a):b>a.options.minWidth&&d>a.options.minHeight&&f(a):b<=a.options.minWidth?e(a):b>a.options.minWidth&&f(a),c(a)},e=function(a){g(a,!1),b(a,!1)},f=function(a){g(a,!0),b(a,!0)},g=function(a,b){a.options.cardView=b,a.toggleView()},h=function(a,b){var c;return function(){var d=this,e=arguments,f=function(){c=null,a.apply(d,e)};clearTimeout(c),c=setTimeout(f,b)}};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,heightThreshold:100,checkOnInit:!0,columnsHidden:[]});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){var b=this,c={width:a(window).width(),height:a(window).height()};if(a(window).on("resize orientationchange",h(function(){var e=a(this).height(),f=a(this).width();(Math.abs(c.height-e)>b.options.heightThreshold||c.width!=f)&&(d(b,f,e),c={width:f,height:e})},200)),this.options.checkOnInit){var e=a(window).height(),f=a(window).width();d(this,f,e),c={width:f,height:e}}}}}(jQuery);
8 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/turtle/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Turtle mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | Turtle mode
27 |
41 |
47 |
48 | MIME types defined: text/turtle.
49 |
50 |
51 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/pascal/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Pascal mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | Pascal mode
27 |
28 |
29 |
52 |
53 |
59 |
60 | MIME types defined: text/x-pascal.
61 |
62 |
--------------------------------------------------------------------------------
/back/static/js/plugins/codemirror/mode/pig/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeMirror: Pig Latin mode
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
26 | Pig Latin mode
27 |
39 |
40 |
47 |
48 |
49 | Simple mode that handles Pig Latin language.
50 |
51 |
52 | MIME type defined: text/x-pig
53 | (PIG code)
54 |