1
0
mirror of https://github.com/ZSCNetSupportDept/website.git synced 2025-10-28 17:05:03 +08:00

13 Commits

Author SHA1 Message Date
dependabot[bot]
29643aba2d Bump nanoid from 3.3.7 to 3.3.8
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 06:12:40 +00:00
govolokatliai
afc432298e Web后端教程:优化了语言,让他对新手更加友好 2024-11-03 14:38:48 +08:00
govolokatliai
c249213cc6 完善Web后端教程-增加HTTP协议和AJAX例子 2024-11-03 13:59:41 +08:00
govolokatliai
af35ada10e 继续完善Web后端的教程。。。 2024-11-02 19:55:40 +08:00
govolokatliai
124b80857b 完善了Web后端教程 2024-11-02 16:01:52 +08:00
govolokatliai
19ebcc67d4 增加了系列文章-Web后端培训 2024-11-01 18:56:26 +08:00
govolokatliai
1faabe5bc1 增加在文档最后显示最近修改时间 2024-10-31 19:01:55 +08:00
govolokatliai
3f4bff2f66 新建文章集-git培训,规划开发组项目 2024-10-14 21:23:30 +08:00
govolokatliai
755a0cd758 增加了提示 2024-09-27 23:22:19 +08:00
govolokatliai
7a5d8a7ff0 增加了指南 2024-09-27 23:18:18 +08:00
govolokatliai
325f5b906f 增加一篇指南 2024-09-27 21:58:15 +08:00
govolokatliai
48c28f77ba 后端API文档(内测) 2024-09-23 01:25:50 +08:00
govolokatliai
c1f35228c4 更新recruitment.html 2024-09-05 17:11:38 +08:00
33 changed files with 1208 additions and 4 deletions

View File

@@ -0,0 +1,78 @@
# 给纯新手的网维快速入门指南
许多新进网维的小伙伴们都可能对我们的日常工作一脸懵:网维是干什么的,我们到底在修什么?其他人说的交换机,主线到底是什么?
甚至有很多正式成员都搞不明白这个问题,为了提升大家的业务水平和网络技术,我们特意编写了这份指南,希望能对你有些许的用处。
<!--truncate-->
## 网络
网维,那不就是修网络的吗?但是,网络是什么?他究竟是什么样的?为什么我可以访问到遥远彼方的内容(网页,游戏,等)?
首先我们需要知道计算机中的一切数据都是一串二进制数字也就是许多的01010101101010.........,网络的本质就是在计算机之间传输这些数字如何进行传输呢通常是使用物理现实的两种状态来表示0和1这两个数字。
比如一个电路简单点说有一个电灯电路闭合电灯亮我们定义这样的状态是1,反之电路断开电灯暗我们定义这样的状态为0,我们让计算机监听这个电路的状态通过电路断开闭合状态不断的超高速的变化就可以传递01010101这些数字来进行信息的传递。
:::info 信息
这里有我们写的一篇科普文章,介绍了网线的一些概念:[Click Me](/docs/wiki/基础知识/科普/网线是什么)
:::
不一定需要电路这种介质还可以是无线电波例如定义电波幅度大于某个值为1,小于某个值为0或者大于某个频率为0,小于某个频率为1,让计算机接受这样的电波并解读,也可以传递信息。
其实,简单地说,前者就是以太网(有线网)本质,网线本质上就是电线,里面是以高频率断断续续的电流,把电线接到计算机里,计算机就可以依据电路的变化情况来获取信息.而后者则是无线网(Wi-Fi,移动通信技术等)本质,他们通过调制电磁波来传递信息。
### 网维
网维主要修的是学生宿舍的以太网,在每个宿舍的每个人的桌子前,都有一个网线端口,用户将网线插入端口和计算机,即可连接到宿舍的楼层线路,端口后面是墙线,意思是它是埋在墙里的,我们一般情况下没法动他
依据宿舍片区的不同,墙线可能直接通去了机房,也有可能是连接到了宿舍的路由器(交换机/光猫),经过这一层转发,再前往机房。
:::tip 提示
你可以在片区信息中查看各个片区的具体结构
:::
路由器是什么?交换机和光猫又是什么?这个问题如果专业地展开来讲有点难懂,对于新手来说,你可以简单的理解为他们都是中转站,电线在这里经过出去的电线继续信息的传递,而不是直接一根线连到网络上去
无线路由器(或者有路由功能的光猫)还可以让用户通过无线方式接入线路,比如,如果你想坐高铁,从中山坐到广州南,然后再从广州南做到其他地方,但是没必要全程坐高铁,你可以打车,坐地铁到广州南,然后再坐高铁。这里一样的,不管有线还是无线的接入,在网关(我们对这些设备的统称)都是转换成有线再出去,
出去是去哪里呢?在宿舍的结构中,是去了机房(或者说,弱电井),宿舍去机房的线就叫做主线(只有通过网关中继的地方才会有主线的概念,直连机房的就直接是墙线)
线路到了机房,一般会接入一个叫做配线架的设备,这个也是一个中继器,方便我们维修(如果是线路坏了的话),配线架的端口总是成对的,有一个进口就会有出口,一般进口都是不用我们去管的,线路经过出口出来,连接到交换机上,我们网维的工作一般追踪到这里,再往后的问题就不是我们的职责了,
交换机有运营商的区别,用户需要接到他宽带开通的运营商对应的交换机上,通过一类叫做“拨号”的协议来进行认证,向运营商用自己的账号请求登录,请求运营商允许联网,这样也方便运营商计费(和学校监控!,交换机通常都是集成了光纤功能在这里将电路的信号调制成光的信号这也是一种传输0101010的方式然后接入运营商的网络访问全国和全球的互联网
## 维修
上面就是我们学校宿舍网络的结构了,网维的工作,本质就是维护这样的结构正常运行,在这些环节中,每一个都有可能出错,一般来说,我们最常见的有两种错误:硬件(物理层)错误(651)和软件错误(691).
### 651错误
硬件错误,通常在拨号时会给出`651`错误,本质上,这种错误就是物理连接出现了问题,要么是墙线老化接触不良了,要么是主线出现了问题,要么是交换机,配线架没有接好,要么是网线问题,对于这种问题,我们通常通过寻线对线器来解决,排查问题
排查问题一般都是调试可能出错的因素,例如,你用一根确定了的是好的网线直连端口对线没问题,但是用户的线连接端口就有问题,那么就是用户的线有问题
:::info 信息
关于更多651错误请查阅wiki相关页面也请查阅`技能`板块中`对线``寻线`的条目
:::
### 691错误
软件错误,通常会在拨号时给出`691`错误,本质上,这意味着物理连接是通的,但是运营商那边拒绝的用户的登录,有几种可能:
1. 交换机接错了,用户是某个运营商,你接到了其他的运营商的交换机,当然报错喽~
2. 短时间内过多的登录,被运营商拉黑了,需要稍等一会子
3. 宽带欠费,停机
4. 账号密码错误
5. 运营商会绑定MAC地址来限制多设备在更换电脑或者转接器等设备时会遇到这样的情况可以打电话给运营商要求所谓的“解绑刷新”也可以组长
:::info 信息
关于更多691错误请查阅wiki的相关页面和相应的文章
:::
## 总结
这里只是一篇简要的指南我们在这里介绍了网络的基本概念让你对你所要维修的系统有一个大概的了解你可以继续去看wiki中的相关条目来进一步扩充你的知识希望你在网维的时光过得愉快

View File

@@ -0,0 +1,44 @@
# 概览Git
这里是git的一个简短教程
## 目录
本教程的目录。。。
1. 介绍-做为版本控制系统的git
- 什么是版本控制系统(VCS)?
- git是如何进行版本控制的
2. git的基础概念
- 新建一个git仓库
- 跟踪文件,暂存文件
- 提交commit
- 分支(branch)介绍
- 合并-merge与rebase
- cherry-pick
- HEAD和相对引用
3. 远程仓库
- clone和origin
- 远程分支是什么
- fetch , pull & push !
4. 托管平台
- github
- gitlab
- gitea
5. 高级
- GUI
- git-gui
- vscode上的一些扩展
- lazygit
- 自建git服务
- gitea
- 参考
- pro git
- learngitbranching.js.org

View File

@@ -0,0 +1 @@
# 什么是版本控制系统(VCS)?

View File

@@ -0,0 +1 @@
# git是如何进行版本控制的

View File

@@ -0,0 +1 @@
# 新建一个git仓库

View File

@@ -0,0 +1 @@
# 跟踪文件,暂存文件

View File

@@ -0,0 +1 @@
# 提交commit

View File

@@ -0,0 +1 @@
# 分支(branch)介绍

View File

@@ -0,0 +1 @@
# HEAD和相对引用

View File

@@ -0,0 +1 @@
# 合并-merge与rebase

View File

@@ -0,0 +1 @@
# clone和origin

View File

@@ -0,0 +1 @@
# 远程分支是什么

View File

@@ -0,0 +1 @@
# fetch , pull & push !

View File

@@ -0,0 +1 @@
# github

View File

@@ -0,0 +1 @@
# gitlab

View File

@@ -0,0 +1 @@
# gitea

View File

@@ -0,0 +1 @@
# GUI

View File

@@ -0,0 +1 @@
# 自建Git服务

View File

@@ -0,0 +1 @@
# 参考

View File

@@ -0,0 +1,213 @@
# Web后端的简单介绍
这篇文章将带你学习构建一个Web后端的简单知识;作为一篇基础的教程,我们在教程里不会太多涉及诸如缓存,消息队列等高级内容,而是专注于基础的部分;我们也不会在一开始就涉及到具体的编程语言代码,而是将这篇文章作为一个理论性的介绍.你可能至少需要了解一些计算机的基础知识比如html等才可以了解文章中的一些概念.
## Web的历史
进行Web后端开发首先需要知道Web的一些概念实际上“后端”这个概念不是一开始就存在的随着人们对互联网需求的不断复杂化后端的概念才出现了我们首先来了解Web的发展历史
### 静态网页
互联网最开始只有静态网页所谓“静态”指的是网页中的内容是完全固定的在服务器端存储了内容固定的html,css或者是其他的什么文件用户访问网页就是通过互联网查看这些固定的文件。在这种情况下你访问一个网站从本质上更像是访问远端计算机上的某个文件夹
例如如果要建立一个网站那就在你的电脑上安装一个HTTP服务器比如apache,nginx在软件的设置里指定你电脑上的某个文件夹为网站的根文件夹然后去买一个域名网址的意思把域名的DNS绑定到你电脑的IP地址上那么其他人在浏览器上输入你的域名就可以访问根文件夹下面的内容了。比如在根文件夹下面放一个`index.html`,那访问域名时,浏览器就会默认显示这个文件的内容,可以在下面放一些图片,比如根文件夹下面有:
`/foo.jpg``/subfolder/bar.jpg`,那么别人在浏览器上面输入`http://yourdomain.com/foo.jpg``http://yourdomain.com/subfolder/bar.jpg`就可以访问到对应的文件。
这种方法很原始,但是如果需求不是很大的话,你也可以使用这种静态网页,你现在正在看的文章,其实就是一个静态的网页
这些访问都是通过HTTP协议来进行的在这里我们需要详细介绍HTTP协议以及HTTP协议的方法
#### HTTP协议
HTTPHyperText Transfer Protocol即超文本传输协议是一个网络客户端比如浏览器和服务端比如服务器当然普通的电脑也可以之间沟通的协议让浏览器可以对服务器上的某个文件进行操作最常见也是大家最熟悉的用途就是获取这个文件然后显示出来我们上面举的例子包括我们日常浏览网站的本质就是在获取服务器上面的内容(实际上HTTP协议可以做的不止这些下面会讲到)
一个完整的HTTP通信包含了请求和回应,请求有客户端发起,回应是服务端返回给客户端
##### HTTP的请求
严谨地说一个HTTP请求包含请求头(HTTP Request Header)和请求体(Request Body)一个HTTP的请求头主要包含了
- 目标网站:资源存在的网站,例如`example.org`
- URL,用于指定需要操作的是哪一个文件,例如`example.org/hahaha.txt`
- 方法用于指定操作即对URL指定的资源进行什么操作比如访问这个文件
- 自定义参数前面说的URL和方法都是通过键值对的形式存在于请求头上的作为请求头的参数键值对就是形如`a=b`的表达式你也可以自定义一些键值对在请求头里这表现为附加在URL之后的一系列键值对通过?开头,&分割,例如`example.org/hello.html?locale=zh-CN&custom=wuwuwu`,这就告诉服务器:两个参数:`locale=zh-CN,custom=wuwuwu`这些参数是可选的自定义的参数可以用于被后端解析现在不理解也没关系关于URL参数的话题我们在之后谈
- cookie:cookie是服务器放在浏览器里的一些临时缓存可以干一些事情当然需要有这个东西才会在请求头里带着我们也以后再谈
对于某些方法,需要在请求时向服务器夹带一些东西,请求体就是装载这些东西的
###### HTTP方法
HTTP方法定义了这个请求具体要对指定的文件做什么其中
- GET:获取指定的资源
- POST:上传指定的资源
- PUT:更新指定的资源,如果没有就创建一个
- PATCH:修改指定的资源
- DELETE:删除指指定的资源
- HEAD:和GET差不多但是只要求服务器返回回应头可以用在试探文件的大小上来判断文件的更新情况从而决定下一步操作
我们日常使用浏览器,比如在地址栏中输入`baidu.com`,其实就是在对这个地址做GET请求一般用户使用浏览器自己是不能做出除了GET之外的请求的但是其他请求在现代的网站中被经常使用这其实是前端脚本在工作以后会解释
如果使用某一些方法的话需要上传一些东西那么这些东西就需要放在请求体里面比如POST等
##### HTTP的响应
其实回应也分为回应头和回应体,回应头主要包含:
- 状态码针对请求的回应有对应的状态比如如果GET请求没有问题成功返回的话就返回200 OK状态码如果找不到请求里对应的文件就会返回`404 Not Found`
- 内容格式:向浏览器说明回应体(若有)是什么格式的,文本文件的编码设置等比如html文件图片这决定了浏览器如何对待这些文件
- 内容的大小:返回所请求资源的大小(若有)
回应体就是包含了回应的主体内容了如果是GET请求的话那么就回应了所GET文件的内容如果是其他请求的话可能也会没有回应体具体看使用的方法
##### 一个例子
`GET`方法从服务器获得一个资源我们在浏览器的地址栏输入一个地址时就是在对这个URI做`GET`请求,前面的例子也是通过`GET`方法来进行的。
比如,发送`GET developer.zsxyww.com/test/test.txt`,那么就会把我们服务器上的test.txt这个文件发过来
`POST`方法向服务器上传一个资源,例如使用某个客户端发送`POST http://example.org/someprogram.exe`在request body里面带上你的这个文件那么`example.org`网站的根目录下就会多出一个叫做`someprogram.exe`的文件
除了上面介绍的这些方法,还有`DELETE`,`PATCH`等方法,分别对应了删除,修改一个资源,你可以在你的电脑上通过`curl`等程序,或者通过浏览器控制台来进行常规的`GET`之外的方法请求
:::tip 提示
httpbin.org 这个网站可以让你试验HTTP协议的方法
:::
不管使用的是什么方法HTTP协议传输的对象都是一些固定静态的文件这些文件的内容是什么就是什么不会变化这样的网页就叫做静态网页。
### 动态网页
这样的网页是不能满足大家对互联网的需求的举例子来说淘宝上有数不清的商品在售卖如果淘宝为每一个商品都在服务器目录下面创建一个html文件好让大家通过访问`http://taobao.com/someproduct.html`来查看商品信息,那这个工作量就非常大了,还有一些更重要的问题:这样的网页,基本上没有交互的功能,我们希望用户可以点击按钮就能购买商品,商家填写表单就能上传商品
#### CGI
这些都是静态互联网无法解决的问题所以程序员们开发了一个叫CGI(Common Gateway Interface,通用网关接口)的技术这种技术在用户请求网站的内容时让一个脚本劫持用户的请求返回给用户一个脚本动态生成的html文件比如如果用户想知道报名数据库里面目前所有的报名人员发送`GET http://example.org/allVolunteer.html`CGI程序发现给本机请求`allVolunteer.html`这个文件,并且程序的代码里写了:如果接受到对`/allVolunteer.html`的请求那就去查找数据库里面的全部报名人员并将返回结果插入到一个模板html文件中。程序返回这个文件于是用户就受到了CGI程序动态产生的html.
虽然CGI现在很少见了但是将一个发送到服务器的地址请求劫持到脚本函数上是现代动态网站的常用思路。
#### JavaScript
除了服务器浏览器也在为适配动态网站而更新。在1995年网景公司的员工发明了一种编程语言叫做"JavaScript",这是对当时新兴的Java和Java Applet的回应这种语言最大的特点就是它被设计在浏览器中运行并且可以调用相关接口来操作页面htmlcss内容和进行HTTP请求他们让自己家的网景浏览器率先支持了这种编程语言(这个浏览器就是火狐浏览器的前身),这极大的提高了浏览器对于动态网页的支持。
#### AJAX(Asynchronous JavaScript and XML)
尽管是在浏览器里的语言但是作为一个完整编程语言的JavaScript还是非常强大的在有了操作DOM,发起HTTP请求的能力后JavaScript,搭配一些后端的程序可以做到CGI传统动态页面没有办法做到的功能动态更新用户html页面上的内容。传统的后端CGI,可以动态生成html,但是这个html生成之后到用户的手里还是不会变化的而JavaScript作为一个编程语言,通过运行在用户浏览器,可以操作html内容和发起HTTP请求便可以自己异步地对服务器发送一些请求依据这些内容便可以部分改变用户浏览器所显示的HTML,CSS只需要浏览器重新渲染一遍就行了这种技术就叫做AJAX,Asynchronous JavaScript and XML
AJAX与传统动态页面的不同点是在获取新数据时不是刷新全部的页面而是让JavaScript操作页面的部分内容。同时后端也不是返回html而是返回一些可以被JavaScript理解的序列化数据例如纯文本、XML,JSON等前端的脚本根据这些数据来操作用户的html
##### 例子
比如在浏览我们的wiki网站时虽然我们的wiki是静态网页你会发现页面的大部分元素都是重叠的比如页面最上面的导航栏sidebar,页脚等样式也是一样的在切换不同的页面时每次获取html都要重新获取这些重复的部分这样就造成了一些浪费如果使用AJAX技术那么只需要第一次打开网站的时候加载这些框架性的元素然后再加载一个JavaScript脚本点击sidebar的时候就将那个文章的内容本身拿过来然后替换掉原有的页面内容这样就更加节省这种部分更新页面内容而不重新加载整个页面的技术就叫做AJAX
再举一个例子,比如我们的报名系统有一个查询功能如果输入的用户在数据库存在的话返回这个用户的全部信息如果不存在那么要给用户显示一条错误信息这种信息如果要单独给用户发送一个新页面的话是很麻烦的用户端的体验也不好我们希望在按下查询按钮之后直接在原来的页面旁边显示服务器返回的结果如果没有AJAX技术那么我们只能把用户的当前页面重新发过去但是把查询结果也放里面因为传统没有JavaScript的网页没有办法对数据进行一些简单的操作只是被动的渲染html.css文件而AJAX技术就允许我们直接把返回的数据本身发送到客户端而且发送的数据也不止局限于HTML,CSS,而可以是一个XML,JSON,或是直接返回状态码,让客户端脚本负责解析这些数据,并将这些数据变成浏览器其他部分可以直接渲染的文件
当一个URL不是返回一个HTML数据而是返回一些不是给用户本人准备的数据时当这些路径不止于接受GET请求时这些路径就和我们传统静态网站的URL代表一个文件时所表现的路径有所不同了
这些后端路径不是给用户设计的通过浏览器直接访问这些地方大概会返回一些用户难以读懂的代码他们是给JavaScript,或者另一种程序设计的这种路径就叫做web API他们是两个程序通过HTTP交互的地方而不是人机交互的界面我们先举一个例子再解释这个问题
:::tip 提示
AJAX技术在今天已经非常常用了以至于很多人都意识不到他们在使用AJAX技术
:::
##### 一个AJAX报名系统的例子
下面举一个例子来详细说明AJAX的工作原理用户需要通过一个网页进行某项活动的报名填写个人信息然后点击网页上的提交按钮服务端会返回报名的结果成功还是失败与传统的方法不同服务器返回信息时不是重新返回一个HTML,而是让浏览器直接在原有的界面上(比如提交按钮的下面)显示报名的状态
用户通过浏览器输入地址,使用`GET`方法发起对`http://example.org/submit.html`的请求服务器获得请求后在root目录下面找到submit.html文件,浏览器得到文件后开始解析渲染这个文件发现这个html在头部又要求浏览器向服务器获取`submit.js`文件,于是浏览器不需要用户处理自己又发送了一条`GET`的HTTP Request,并且执行返回的脚本这个脚本的内容是监听html文件中提交按钮的“点击”事件当按钮被点击时执行某个函数。
返回的html文件包括了提示框要求用户输入姓名手机空闲时间等信息在这些输入栏的最下面有一个提交按钮当点击这个按钮时脚本就会被激活脚本执行的函数将读取用户从上面输入进来的内容做一些简单的认证比如说手机号的格式等然后将这些信息组织成一个XML文件当然,AJAX中的X就是XML咯现在其实也可以用其他的方法序列化比如JSON什么的向服务器发送一个`POST`请求,地址是`http://example.org/api/submit/submit.php`,在请求体中包含刚才的XML文件。
服务器在接收这个请求后,就会将,这个请求的上下文全部转交给`submit.php`这个脚本脚本再做一些工作录入数据库如果一切都成功了就向客户端发送回应成功反之则回应失败的消息回应的内容可以是一个纯文本或者直接是状态码比如就返回一个JSON:
```JSON
{
"status":"success",
"submit":{
"name":"小明",
"freeday":"2023-11-25",
"phone":10000000000
},
"createdAt":"2023-10-25_9:23:22"
}
```
在JavaScript脚本接收到回应后根据返回的内容操作html文件的内容在提交按钮的下面一行插入一个文本块
```HTML
<div id="json_responses">
<p id="json:status">提交成功!你提交了:</p>
<p id="json:submit.name">姓名:小明</p>
<p id="json:submit.freeday">空闲时间2023-11-25</p>
<p id="json:submit.phone">手机号10000000000</p>
<p id="json:createdAt">服务端提交创建时间2023-10-25 9:23:22</p>
</div>
```
或者其他的信息
#### URI在现代的意义
从刚才的这个例子中我们可以看到网站的URI,其实慢慢的不止可以指代一个文件了,他更多的是指代一个资源,或者一个业务,向`submit.php`提交一个`POST`请求,难道是在远端创建一个`submit.php`程序?其实在这里更多是指将客户端的数据上传到这个`/api/submit/submit.php`的业务窗口,我们的后端开发也是建立在这种对虚拟的路径的请求下的。例如我们设计一个报名系统我们可以设计一个API接口叫做`POST http://api.yourwebsite.io/newVolunteer`,接受浏览器js的报名信息提交在服务器根本就没有`/newVolunteer`这个文件,连文件夹都不一定会有,全靠路由在工作(见下篇文章)
### Web应用
#### WebSocket
HTTP的动态网站已经很好了但是协议本身有一个缺点:一个HTTP连接分为请求和响应只能由客户端发起请求服务端返回响应如果客户端没有先发一点什么给服务端的话服务端是没办法先给客户端发信息的这就给一些更加复杂的要求增添了障碍比如通过浏览器和别人聊天需要接受来自服务器发给你的其他人的聊天的信息或者是在浏览器上玩游戏需要和服务器交换数据。这可以通过轮询来解决但是这样还是不方便。
WebSocket是一个全新的协议支持客户端和服务器的全双工通信即客户端和服务器都可以主动地发消息而且可以同时进行而且是采用较小的数据帧格式降低了网络开销提高了数据传输速度。WebSocket在建立连接后保持长时间有效不需要为每次消息发送重新建立连接因此效率更高。
为了兼容HTTP协议WebSocket也是监听80和443端口(HTTPS),握手采用了HTTP协议通过升级协议来建立连接如果可以升级服务器会返回101状态码升级连接.
:::info 信息
对于WebSocket过于详细的介绍超出了本篇文章的内容可以自行了解
:::
##### Server-Sent Events(SSE)
WebSocket是一个全新的协议兼容性可能不是那么好如果要求比较低的话可以看一看Server-Sent Events,这个协议基于HTTP,允许服务器主动给客户端发送信息,当然也请自行了解。
#### 在Web上运行应用
传统观念里一个应用程序是在计算机上直接运行的但是在介绍了上面的技术之后我们可以想到在Web上也是可以运行应用程序的通过现代的高性能JavaScript运行时可以提供类似于原生的运行速度通过WebSocket,可以快速的更新内容现在的HTML和CSS也足够强大用户的机器性能也越来越强了而且开发Web应用可以直接使用成熟的Web技术栈在浏览器中运行也更安全以至于现在很多本地的应用也开始使用Web技术了(electron)。
例如我们所使用的腾讯文档支持多人协作编辑就使用了WebSocket技术来向你主动发送其他人对文档编辑的信息
#### 单页应用(SPA)
一个现代的网站或者说一个提供服务的Web应用流行单页应用架构顾名思义服务器只会在用户打开网页时加载一段html文件后面的全部内容都是通过js动态更新的js和服务器的后端接口交互主要是采用AJAX,对于某些复杂的需求可能会需要使用前面的技术WebSocket或者SSE
`React.js`就是贯彻单页应用思想最彻底的前端框架,单页应用的坏处就是打破了为静态网页文件设计的“收藏”功能和前进后退也不利于SEO和无障碍因为用户在网站上只打开一个网页网页的内容根据用户操作由浏览器脚本动态更新而生成的html也大多没有做语义化优化难以被理解和解析
SPA的例子就是邮箱应用比如Gmail,通过浏览器访问你的邮箱通过邮箱的主页面点某个邮件你并没有进入一个新的页面而是在原有的页面上内容变成了邮件查看的界面如果在主页面上点击发件的话同样也没有一个发件页面而是直接呈现发件的UI
有时候通过AJAX调用API的HTTP交互没办法满足一些需求比如说服务器主动推送信息或者流式传输比如直播平台游戏等这个时候就需要使用前面提到的技术前面的腾讯文档就是一个例子还有就是网络聊天室matrix之类需要向浏览器主动推送信息还有直播平台需要将源源不断的多媒体数据传递到用户那里还有网络游戏需要快速在浏览器和服务器之间交换游戏数据但是一般这些应用的基础框架都是建立在传统AJAX上的只是业务部分采用其他协议实现这些现代的应用慢慢地将计算量转移到了前端而后端只负责存储和提供查询数据甚至后端都不用负责产生html,只需要提供API,来为前端提供数据就行
##### WebAssembly
WebAssembly是最近新出现的技术他允许开发者将C/C++ , Rust等原本的一些编译型语言编译成浏览器可以执行的字节码使得在浏览器中也可以执行这些程序目前也有一些使用WebAssembly的应用可以去看看最大的好处就是不会JavaScript也能开发前端也可以复用以前的代码当然这个其实是前端的内容
## Web后端-是干什么的?
前面用非常长的一段文字来介绍Web的发展历史就是为了说明Web后端是干什么的或者说编写一个Web后端需要干什么
如果你想写一个静态网站那么简单的http服务器就可以满足你不需要你手动写什么代码如果你想写一个基于AJAX的服务比如我们网维现在的报修系统那么你需要设计好API,和前端沟通好序列化相关事项或者是返回JSON信息什么的让前端处理还是返回html让浏览器渲染;如果你想写一个WebSocket的Web应用那就要难一些了可能需要掌握一些并发编程的知识才可以写出一个可以使用的服务
我们接下来的教程将注重开发一个现代的AJAX后端服务同时辅助提供一些静态文件托管的功能。
### Web后端的组成
一个Web后端主要由以下部分组成
- 路由(router)
- 处理(handler)
- 数据库/ORM
- 鉴权
- 模板(如果需要)
详细的信息,请阅读下一篇文章:[Click Me](./基于HTTP的Web后端的组成)
:::tip 提示
读完这篇文章之后,你可以回顾文章里的内容,问一问自己:
- Web经历了哪些发展阶段
- 前后端之间是如何使用HTTP协议交互的
- AJAX技术是什么是如何支撑起现代的网页的(单页应用)
推荐在看下一篇文章之前看看下面的参考文章
:::
## 参考
在读完这篇文章后你可以去详细阅读这篇文档https://developer.mozilla.org/zh-CN/docs/Learn/Server-side/First_steps/Introduction (**强烈推荐!**)
这里是关于HTTP协议的详细介绍https://developer.mozilla.org/zh-CN/docs/Web/HTTP

View File

@@ -0,0 +1,156 @@
# 基于HTTP的Web后端的组成
一个基于HTTP的Web后端通常有以下部分组成:
##### 路由系统(router)
路由系统负责处理用户访问网页时的请求路径/方法,并转交给对应的处理者
##### 处理者(handler)
处理者负责处理用户的请求读取用户在URI中的参数和请求体中的内容如果有统称为上下文(Context),负责返回请求所对应的回应
有的系统还会继续细分,将业务层和接口层分开(这种情况下通常接口层是和路由功能合并的)
_最低要求是这个另外通常一个后端系统还需要连接一个数据库:_
##### 数据库
通常是兼容SQL协议的关系型数据库负责存储后端所需要用到和产生的信息
_其实很多后端系统无非就是对数据库的增删改查(所谓的CRUD),可以说这些系统就是数据库的一层方便wrapper_
##### 鉴权系统
通常,我们系统的内容不打算对互联网上的任何一个人开放,所以我们需要一些方法来验证访问者的身份
##### 模板系统optional
如果你打算通过后端渲染HTML返回到用户浏览器那你需要一套模板来方便地将动态内容插入到模板里面返回给用户如果是一个纯粹API的站点还是想直接把工作甩给前端你就可以不用配置模板
此外,还有一些外围的工作:
##### 反向代理
通常我们的Web后端服务不是直接暴露对外访问的而是经过一层代理的转发这样更加的安全配置也更加简单服务只需要监听本地端口
##### 配置系统
你的系统需要读取配置,比如监听端口,数据库连接,还有其他服务的密钥等
##### CI/CD
自动化配置构建,部署,测试等工作,让你专注代码工作,而不用把心思过多地放在部署构建这些工作上面
## 路由
假设你的一个报名服务架设在`service.io`上:
首先,用户访问这个网址时需要显示一段欢迎文字,然后将他们引导到报名的页面
那么,你应该在用户访问`/`时返回一个html文件里面含有导向`/volunteer.html`的超链接
`/volunteer.html`里面的前端代码需要以AJAX的形式与后端API交互比如
`service.io/api/register`接受POST请求前端上传报名人的信息后端录入数据库,并返回录入的信息全部以JSON序列化
`service.io/api/view`接受GET请求让这个报名人查看自己的报名信息返回JSON格式
`service.io/api/cancel`接受POST请求取消某个报名人的信息成功则返回相应状态码
`service.io/admin/viewAll`让管理员查看当前的所有报名接受GET请求
`service.io/admin/cancel`让管理员取消任意的报名,接受的POST
在现代网站设计中,我们不是在根目录下面创建对应的文件(实际上,连根目录都不需要了),我们使用一些叫做“路由器(router)”的模块,当用户通过一定的方法请求一定的路径时就把这些请求转交到相应的handler
### URI参数
参数在正常路径后面,以?开始,以&分割,以键值对的形式存在
例如:`service.io/api/register?name=小明&phone=10000000000&freeday=2024-9-25`
这样的参数可以被许多后端框架使用内置的解析器解析
### 参数化路径
这种路径通常是配合REST风格的接口来设计的比如
`service.io/api/users/小明`
类似于这样的路径,许多后端框架可以使用`service.io/api/users/:user`这样的形式来匹配在转交给的handler中可以读取`:user`参数,从而返回参数所指定的资源
### API设计
API的设计包括了路径的设计和接口格式的设计一般小项目可以相对地随便一点但是大项目还是需要认真一点的
#### 传统
我们刚才所举的例子就是一个传统的API设计一个路径就对应了一个业务点一般只会使用`GET``POST`来对应获取和上传,前后端的交互一般在文档里自行约定,或者采用内置的表单(如果数据比较简单的话)
#### REST
REST的意思是“表现层状态转换”英语Representational State Transfer缩写REST这种风格的要点是一个URI表示一个资源而不是一个业务同时充分地利用HTTP方法
例如,我们在前面定义了`Register`,`View``Cancel`三个API,如果是要上传什么就用`POST`,获取`GET`,一个路径表示的是一个业务而不是系统的某个资源下面来看看REST怎么写
`POST service.io/api/users/小明` 用户小明提交一个报名,具体的报名信息在请求体里,这将在数据库里面创建一个小明的报名记录
`GET service.io/api/users/小明` 用户小明查看自己的报名信息
`DELETE service.io/api/users/小明` 取消小明的报名
`PUT service.io/api/users/小明` 修改小明的报名信息,新信息放在请求体里面了
可以发现REST风格的API可以看作是对传统静态网页互联网的回归这种风格直观简洁兼容性更好更加利于缓存等
#### GraphQL
GraphQL是一种用于API交互的查询语言他意图解决接口格式定义和多次查询带来的复杂问题
首先后端需要支持GraphQL,然后前端需要在API请求中注明自己想后端用什么格式呈现什么想要的信息这样就不需要前端多次请求不同的业务了
这对大型系统或许比较友好,但是如果只是一些小项目的话,这可能有些复杂,具体可以自己去了解
## handler
handler可以说是一个后端系统的核心了因为他们是实际处理业务的地方
### 面向对象与模型
虽然可以使用其他的范式但是最推荐的是依据OOP的原则将需要处理的模型写成对象将一系列操作写成对象的方法
例如,报名系统本质上就是处理“报名人”这个对象的各种操作,我们可以定义:
```Go
type Volunteer struct{
config.DB
id int
Name string
Phone int
FreeDay time.Time
Note string
}
func (v *volunteer)Add()error{
if err:=db.addVolunteer(v.MainConnection) err!=nil{
return err
}
return nil
}
```
要设计一个登记报名的handler,就只需要将前端发过来的信息反序列化到Volunteer对象里然后调用Add方法即可这种思路就叫做面向对象
所设计的Volunteer和他的一系列方法就叫做“模型”
## 数据库
数据库为后端的业务数据提供了方便的存储和查询服务,这里指的是结构化数据,其他需求可以去看高级教程
### SQLite
这是个轻量级的数据库,一个数据库就是一个文件,通常用于业务量比较小的场景或者是本地开发的场景
### PostgreSQL
这个可以说是目前最厉害的开源数据库了,不仅提供了常规的结构化功能,而且对于一些简单的非结构化存储需求也可以胜任,但是本身的资源消耗是有点高的
### 选择数据库的各种考量
- 业务量如果业务量比较小的话就使用SQLite吧
- 兼容性:如果现有的环境和业务依赖于某个数据库,那么就继续用吧
### ORM
ORM是对数据库的一层抽象让你专注于业务逻辑的开发而不用担心具体的数据库问题如果对于性能或者其他的方面没有很大的需求的话建议在你的项目里使用ORM
## 鉴权
### Session
### JWT
### OAuth2.0
## 模板
### Jinja2

View File

@@ -0,0 +1,11 @@
# 高级教程
本篇是Web后端的进阶系列文章
## 缓存
### 为什么我们需要缓存?
对于某些需要高频读写的数据,放在数据库中的速度会比较慢,所以我们需要一个缓存俩提供快速访问,这些缓存通常放在内存中,提供最快的访问速度
### Redis 和 Memcached
## 消息队列
## 日志与监控
## NoSQL与非结构化数据

View File

@@ -0,0 +1,21 @@
# 后端API服务
## 介绍
该项目作为网维的统一后端API接口而设计连接网维的数据库并提供一系列接口给前端以支持网维日常的业务逻辑其他开发人员可以直接调用这些接口从而专注与前端以便于降低整个系统设计的复杂度
该项目采用Go语言编写Web框架采用echo,ORM框架为gorm,
## 项目地址
https://github.com/ZSCNetSupportDept/zscnetworksupport-api
## 构建
要想构建该项目,你需要安装`Go``make`,在一台linux机器上构建
输入`make install`即可安装本项目的依赖,而不构建
输入`make build`即可构建该项目,项目放在`make`文件夹下
## 部署
只需要把可执行文件放在生产环境下运行即可,本项目可能会提供一些静态文件访问,需要将`static`放在与可执行文件相同的目录下
## 配置
程序接受,且只接受一个参数,为配置文件的路径,关于配置文件的格式,请参照“配置”一章
## 运行
运行后程序会将日志和错误文件输出到stdout中你可以配置系统服务来使程序开机自启动将输出定向到日志或者stderr里
在运行程序之后你还要配置一些反向代理的软件来将流量导向程序所监听的端口你还要定期续期https证书以保证https访问

View File

@@ -0,0 +1,13 @@
# 配置
# 介绍
配置为一个`json`文件,其中,各个字段的定义如下:
`port`:一个数字,为程序所监听的端口
`database`:
- `Type`:一个字符串,指定了所使用的数据库的类型,需要在`MySQL` `PostgreSQL` `SQLite`中选择一个
- `Path`:对于SQLite填写数据库的位置对于其他的数据库填写URL
- `Port`:数据库所监听的端口SQLite可以不用填以下也是
- `User`:数据库用户名
- `name`:数据库名称,
- `Password`:数据库密码

View File

@@ -0,0 +1,22 @@
# 结构
仓库项目的结构如下:
`main.go`:项目程序的起点,从此处开始运行
`config`:存放了读取配置,提供配置变量相关的代码
`databases`:提供了连接数据库相关的代码,提供主数据库连接变量(Usingdb)
`handlers`:为handler的存放地点一类业务为一个对象handler作为其方法实现
`model`:业务所采用的模型,定义了一个业务对象的存储和相关方法
`use`:在这里注册所有需要提供的API和中间件,程序将使用这里的配置
`make`:存放了构建所产生的程序
`static`:存放了静态文件以进行路由
## 原理
当程序运行时:
main()将调用sysinit(),读取参数中的配置,将配置记录在全局变量`config.UseConfig`

Binary file not shown.

View File

@@ -1,17 +1,21 @@
# 网络维护科wiki首页
:::tip 提示
**至手机用户:点击页面左上角的三条杠打开导航栏,以浏览本站**\
**推荐使用电脑端访问**
:::
## 介绍
这里是中山学院网络维护科wiki,记录了网络维护工作的相关知识wiki的内容都是历代网维的成员整理总结的你也可以贡献自己的内容
:::warning 注意
本wiki还在大量开发中许多条目可能会不完善或者缺失仅供开发组组员和正式成员测试参考使用,如果你对wiki的编写和维护感兴趣可以访问我们的[github源代码仓库](https://github.com/ZSCNetSupportDept/website),具体的细节请联系开发组组长
:::
## wiki的内容
**wiki基本由以下部分组成**
### 技能
@@ -33,3 +37,15 @@ MacOS的修理事项
这里是新版wiki,但是旧版wiki依然可用你可以通过[wiki.zsxyww.com](https://wiki.zsxyww.com) 来访问,上面还有没有迁移的许多旧文章,我们目前在逐步转移这些文章
## 贡献
如果你想为本wiki添砖加瓦可以在仓库里PR:[wiki的github仓库](https://github.com/ZSCNetSupportDept/website)
:::tip 提示
对于新手如果wiki不能解决你的问题和其他疑惑可以随意向组长科长,api,或者其他人请教我们也会加油完善wiki的
:::

0
docs/wiki/gitignore/.gitignore vendored Normal file
View File

View File

@@ -0,0 +1,604 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Megan Conkle <megan.conkle@kdemail.net>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/******************************************************************************/
/* Scrollbars */
/******************************************************************************/
ghostwriter--MarkdownEditor QAbstractScrollArea::corner,
ghostwriter--HtmlPreview QAbstractScrollArea::corner,
ghostwriter--Sidebar QAbstractScrollArea::corner {
background: transparent;
}
ghostwriter--MarkdownEditor QAbstractScrollArea,
ghostwriter--HtmlPreview QAbstractScrollArea,
ghostwriter--Sidebar QAbstractScrollArea {
padding: 3px 3px 0px 3px;
margin: 0
}
ghostwriter--Sidebar MarkdownEditor::horizontal,
ghostwriter--Sidebar HtmlPreview::horizontal,
ghostwriter--Sidebar QScrollBar::horizontal {
height: 16px;
margin: 5px;
border: 0;
background: transparent;
}
ghostwriter--MarkdownEditor QScrollBar::vertical,
ghostwriter--HtmlPreview QScrollBar::vertical,
ghostwriter--Sidebar QScrollBar::vertical {
width: 16px;
margin: 5px;
border: 0;
background: transparent;
}
ghostwriter--MarkdownEditor QScrollBar::horizontal:hover,
ghostwriter--HtmlPreview QScrollBar::horizontal:hover,
ghostwriter--Sidebar QScrollBar::horizontal:hover {
background-color: #202325;
border-radius: 3px;
}
ghostwriter--MarkdownEditor QScrollBar::vertical:hover,
ghostwriter--HtmlPreview QScrollBar::vertical:hover,
ghostwriter--Sidebar QScrollBar::vertical:hover {
background-color: #202325;
border-radius: 3px;
}
ghostwriter--MarkdownEditor QScrollBar::handle:horizontal,
ghostwriter--HtmlPreview QScrollBar::handle:horizontal,
ghostwriter--Sidebar QScrollBar::handle:horizontal {
min-width: 50px;
border: 0;
background: #444749;
border-radius: 3px;
}
ghostwriter--MarkdownEditor QScrollBar::handle:horizontal,
ghostwriter--HtmlPreview QScrollBar::handle:horizontal,
ghostwriter--Sidebar QScrollBar::handle:horizontal {
min-width: 50px;
border: 0;
background: #444749;
border-radius: 3px;
}
ghostwriter--MarkdownEditor QScrollBar::handle:vertical,
ghostwriter--HtmlPreview QScrollBar::handle:vertical,
ghostwriter--Sidebar QScrollBar::handle:vertical {
min-height: 50px;
border: 0;
background: #444749;
border-radius: 3px;
}
ghostwriter--MarkdownEditor QScrollBar::handle:horizontal:hover,
ghostwriter--HtmlPreview QScrollBar::handle:horizontal:hover,
ghostwriter--Sidebar QScrollBar::handle:horizontal:hover {
background: #3daee9;
}
ghostwriter--MarkdownEditor QScrollBar::handle:vertical:hover,
ghostwriter--HtmlPreview QScrollBar::handle:vertical:hover,
ghostwriter--Sidebar QScrollBar::handle:vertical:hover {
background: #3daee9;
}
ghostwriter--MarkdownEditor QScrollBar::add-line,
ghostwriter--HtmlPreview QScrollBar::add-line,
ghostwriter--Sidebar QScrollBar::add-line,
ghostwriter--MarkdownEditor QScrollBar::sub-line,
ghostwriter--HtmlPreview QScrollBar::sub-line,
ghostwriter--Sidebar QScrollBar::sub-line,
ghostwriter--MarkdownEditor QScrollBar::add-page,
ghostwriter--HtmlPreview QScrollBar::add-page,
ghostwriter--Sidebar QScrollBar::add-page,
ghostwriter--MarkdownEditor QScrollBar::sub-page,
ghostwriter--HtmlPreview QScrollBar::sub-page,
ghostwriter--Sidebar QScrollBar::sub-page,
ghostwriter--MarkdownEditor QScrollBar::down-arrow,
ghostwriter--HtmlPreview QScrollBar::down-arrow,
ghostwriter--Sidebar QScrollBar::down-arrow,
ghostwriter--MarkdownEditor QScrollBar::right-arrow,
ghostwriter--HtmlPreview QScrollBar::right-arrow,
ghostwriter--Sidebar QScrollBar::right-arrow {
background: transparent;
border: 0
}
/******************************************************************************/
/* Menu Bar */
/******************************************************************************/
QMainWindow QMenuBar {
color: #bdc3c7;
background-color: #151719;
font-size: 10pt;
spacing: 2px;
border: 0px;
border-bottom: 1px;
border-color: #2c2f31;
border-style: solid;
padding: 1px 0px 1px 0px;
}
QMainWindow QMenuBar::item {
padding: 2px 7px 2px 7px;
border: 0px;
margin: 2px;
border-radius: 5px;
}
QMainWindow QMenuBar::item:selected {
background-color: #25282c;
}
QMainWindow QMenuBar::item:hover {
background-color: #373d42;
}
QMainWindow QMenuBar::item:pressed {
background-color: #1f2225;
}
/******************************************************************************/
/* Popup menus */
/******************************************************************************/
QMainWindow QMenu,
QMenuBar QMenu {
color: #bdc3c7;
background-color: #1a1d1f;
border: 0px;
padding: 7px 0px 7px 0px;
}
QMainWindow QMenu::item,
QMenuBar QMenu::item {
background-color: transparent;
padding: 5px 10px 5px 10px;
margin: 0px 0px 0px 0px;
}
QMainWindow QMenu::indicator,
QMenuBar QMenu::indicator {
width: 16px;
height: 16px;
background-color: #25282c;
padding: 0px 5px 0px 5px;
margin: 0px 5px 0px 5px;
}
QMainWindow QMenu::indicator::unchecked,
QMenuBar QMenu::indicator::unchecked {
width: 16px;
height: 16px;
background-color: #25282c;
border-radius: 2px;
border-style: solid;
border-width: 1px;
border-color: #bdc3c7;
margin: 0px 5px 0px 5px;
}
QMainWindow QMenu::indicator::checked,
QMenuBar QMenu::indicator::checked {
width: 16px;
height: 16px;
background-color: #074051;
border-radius: 2px;
border-style: solid;
border-width: 1px;
border-color: #bdc3c7;
margin: 0px 5px 0px 5px;
}
QMainWindow QMenu::item:selected,
QMenuBar QMenu::item::selected {
background-color: #074051;
color: #bdc3c7;
}
QMainWindow QMenu::icon,
QMenuBar QMenu::icon {
border-radius: 2px;
border-width: 0px;
padding: 1px 3px 1px 3px;
margin: 0px 3px 0px 3px;
}
QMainWindow QMenu::icon::checked,
QMenuBar QMenu::icon::checked {
background-color: #373d42;
}
/******************************************************************************/
/* Editor */
/******************************************************************************/
QMainWindow QPlainTextEdit {
border: 0;
margin: 0;
padding: 5px;
background-color: #151719;
color: #bdc3c7;
selection-color: #bdc3c7;
selection-background-color: #074051;
font-family: Noto Sans Mono;
font-size: 15pt;
}
QMainWindow QSplitter::handle {
border: 0;
padding: 0;
margin: 0;
background-color: #2c2f31;
}
QMainWindow QSplitter::handle:vertical {
height: 1px;
}
QMainWindow QSplitter::handle:horizontal {
width: 1px;
}
/******************************************************************************/
/* Sidebar and Activity Bar */
/******************************************************************************/
/* Sidebar */
QMainWindow ghostwriter--Sidebar,
QSplitter ghostwriter--Sidebar {
border: 0;
margin: 0;
padding: 0;
background-color: #151719;
}
ghostwriter--Sidebar QStackedWidget {
border: 0;
padding: 1;
margin: 0;
background-color: #151719;
border-width: 0px;
}
/* Activity bar tabs */
ghostwriter--Sidebar QPushButton[checkable="true"] {
icon-size: 22px;
min-width: 40px;
max-width: 40px;
height: 40px;
outline: none;
margin: 0;
padding: 0;
border: 0;
background-color: transparent;
color: #8b8f92;
border-width: 0px;
border-left-width: 3px;
border-style: solid;
border-color: transparent;
border-radius: 0px;
}
ghostwriter--Sidebar QPushButton:checked {
border-color: #3daee9;
color: #bdc3c7;
background-color: #202325;
}
ghostwriter--Sidebar QPushButton:hover {
background-color: #202325;
}
ghostwriter--Sidebar QPushButton:checked:hover {
border-color: #3daee9;
color: #bdc3c7;
background-color: #202325;
}
/* Activity bar buttons */
ghostwriter--Sidebar QPushButton[checkable="false"] {
icon-size: 22px;
padding: 0;
margin: 0;
border: 0;
border-radius: 5px;
background-color: transparent;
color: #8b8f92;
width: 40px;
height: 40px;
}
ghostwriter--Sidebar QPushButton[checkable="false"]:hover {
color: #bdc3c7;
background-color: #202325;
}
ghostwriter--Sidebar QPushButton[checkable="false"]:pressed {
color: #bdc3c7;
background-color: transparent;
}
/* Stacked widgets inside sidebar pane */
ghostwriter--Sidebar QListWidget {
outline: none;
border: 0;
padding: 1;
background-color: #151719;
color: #bdc3c7;
font-size: 11pt;
font-weight: normal
}
ghostwriter--Sidebar QListWidget::item {
border: 0;
padding: 1 0 1 0;
margin: 0;
background-color: #151719;
color: #bdc3c7;
font-weight: normal
}
ghostwriter--Sidebar QListWidget::item:selected {
border-radius: 0px;
color: #bdc3c7;
background-color: #074051;
}
ghostwriter--Sidebar QLabel {
border: 0;
padding: 0;
margin: 0;
background-color: transparent;
font-size: 11pt;
color: #bdc3c7;
}
/******************************************************************************/
/* Status bar */
/******************************************************************************/
QStatusBar {
margin: 0;
padding: 0;
border-top: 1px solid #2c2f31;
border-left: 0;
border-right: 0;
border-bottom: 0;
background: #151719;
color: #8b8f92;
}
QStatusBar QLabel {
font-size: 11pt;
margin: 0px;
padding: 5px;
border: 0;
background: transparent;
color: #8b8f92;
}
QStatusBar QToolButton {
padding: 5 5 5 5;
margin: 0;
border: 0;
border-radius: 5px;
color: #8b8f92;
background-color: transparent;
font-size: 16px;
width: 32px;
height: 16px;
}
QStatusBar QToolButton:hover,
QStatusBar QToolButton:checked:hover {
background-color: #373d42;
}
QStatusBar QToolButton:pressed,
QStatusBar QToolButton:checked:pressed {
color: #73777a;
background-color: #1f2225;
}
QStatusBar QToolButton:flat,
QStatusBar QToolButton:checked {
background-color: #25282c;
}
QStatusBar QComboBox {
height: 22px;
border: 0px;
margin: 0;
padding: 0;
color: #8b8f92;
background-color: #151719;
font-size: 11pt;
}
QStatusBar QComboBox:hover {
border-bottom: 2px solid #3daee9;
}
QStatusBar QListView {
padding: 7px 0px 7px 0px;
margin: 0px;
color: #bdc3c7;
background-color: #151719;
}
QStatusBar QListView::item {
background-color: transparent;
padding: 5px 10px 5px 10px;
margin: 0px;
}
QStatusBar QListView::item:selected {
background-color: #074051;
color: #bdc3c7;
}
QStatusBar QComboBox::drop-down {
border: 0;
margin: 0;
padding: 0;
height: 20px;
width: 20px;
}
QStatusBar QComboBox::down-arrow {
border: 0;
margin: 0;
padding: 0;
height: 14px;
width: 14px;
image: url(/tmp/lIaSog.png)
}
QStatusBar QComboBox::drop-down:hover {
border-radius: 10px;
background-color: #373d42;
}
QStatusBar #leftStatusBarWidget,
QStatusBar #midStatusBarWidget,
QStatusBar #rightStatusBarWidget {
border: 0;
margin: 0;
padding: 0;
}
/******************************************************************************/
/* Find and Replace Pane */
/******************************************************************************/
ghostwriter--FindReplace QLabel {
font-size: 11pt;
margin: 0px;
padding: 5px;
border: 0;
background: transparent;
color: #8b8f92;
}
ghostwriter--FindReplace QPushButton {
font-size: 16px;
padding: 5 5 5 5;
margin: 0;
border: 0;
border-radius: 5px;
color: #8b8f92;
background-color: transparent;
min-width: 16px;
}
ghostwriter--FindReplace QPushButton:pressed {
color: #9da2a6;
background-color: transparent;
}
ghostwriter--FindReplace QPushButton:hover {
color: #ffffff;
background-color: transparent;
}
ghostwriter--FindReplace QPushButton:disabled {
color: #adb3b6;
background-color: transparent;
}
ghostwriter--FindReplace QPushButton[checkable="true"] {
color: #8b8f92;
background-color: transparent;
min-width: 32px;
height: 16px;
}
ghostwriter--FindReplace QPushButton[checkable="true"]:disabled,
ghostwriter--FindReplace QPushButton:flat:disabled {
color: #adb3b6;
background-color: #272a2e;
}
ghostwriter--FindReplace QPushButton[checkable="true"]:hover,
ghostwriter--FindReplace QPushButton:checked:hover {
background-color: #d0d7db;
background-color: #373d42;
}
ghostwriter--FindReplace QPushButton[checkable="true"]:pressed,
ghostwriter--FindReplace QPushButton:checked:pressed {
color: #73777a;
background-color: #1f2225;
}
ghostwriter--FindReplace QPushButton:checked {
background-color: #25282c;
}
ghostwriter--FindReplace QPushButton:flat {
color: #8b8f92;
background-color: #25282c;
font-weight: bold;
}
ghostwriter--FindReplace QPushButton:flat:hover {
color: #d0d7db;
background-color: #373d42;
}
ghostwriter--FindReplace QPushButton:flat:pressed {
color: #73777a;
background-color: #1f2225;
}
ghostwriter--FindReplace QPushButton:flat:disabled {
color: #adb3b6;
background-color: #272a2e;
}
ghostwriter--FindReplace QPushButton#matchCaseButton,
ghostwriter--FindReplace QPushButton#regexButton {
font-size: 16px;
font-family: default;
font-weight: bold;
}
ghostwriter--FindReplace QPushButton#replaceButton,
ghostwriter--FindReplace QPushButton#replaceAllButton {
font-size: 11pt;
font-family: default;
}
ghostwriter--FindReplace QPushButton#findReplaceCloseButton {
padding: 0;
margin: 0;
icon-size: 16px;
}
ghostwriter--FindReplace QLineEdit {
color: #bdc3c7;
background-color: #202325;
border: 0px;
border-radius: 3px;
selection-color: #bdc3c7;
selection-background-color: #074051;
}
ghostwriter--FindReplace QLineEdit:focus {
border: 1px solid #1d2022;
}

View File

@@ -48,6 +48,7 @@ const config = {
// Remove this to remove the "edit this page" links.
editUrl:
'https://github.com/ZSCNetSupportDept/website/tree/master',
showLastUpdateTime: true,
},
blog: {
showReadingTime: true,

7
package-lock.json generated
View File

@@ -11152,16 +11152,15 @@
}
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},

View File

@@ -92,6 +92,7 @@ button {
<li class="button">
<button type="submit">提交</button>
</li>
<p align=center><a href=https://zsxyww.com>之前的提交信息有误?点这里修改</a></p>
</ul>
</form>
<message note="这里是后端返回的信息容器">

View File

@@ -1,3 +1,11 @@
# 备忘录
**这里是网站开发备忘录有什么想法事情都可以记在这里善用Markdown功能**
- 在正式成员中招募一些人来持续维护wiki
## 开发组业务
报修系统
招新系统
网站
开发组网站(wiki和文档)
服务器运维