普通视图

发现新文章,点击刷新页面。
昨天以前智朋的个人博客

使用 PyQt 制作简易软件简明笔记

作者 coffeelize
2024年8月20日 20:30

缘由

最近在统计多组数据的重复性,利用到了标准差相关的公式,自然而然想到是使用 Excel 来处理公式。总之,模板是实现了,将公式一步一步拆解,饶了一大圈,发现最后 Excel 本身就内置了求取标准差的函数,还不如不要让我知道这个结果呢,伤心: (

image.png

不过,这也带来了一些思考。自认为自己用 Excel 还算用得多的了,根本没有听过用过这样的内置函数,能不能写个简单的程序,只要将数据往里面一扔,就可以自动出来计算结果呢 —> 于是开始了折腾

Step 1 搭建环境

  • 这里选择社区版的 Pycharm,免费,集成开发环境用起来也方便
  • 程序开发使用的是 PyQt 框架

刚安装完 Pycharm,会检测系统中是否已经安装好了 python,如果恰好没有安装过,那么根据软件的建议安装即可

写好的代码中若检测有问题,Pycharm 会在对应的位置进行提示,如一下这段程序,刚安装的 python 肯定是没有 PyQT6 的程序包的,可以通过提示(小红灯泡处,Alt+Enter)进行安装

image.png

新建项目,新建 python 文件,粘贴如下代码进行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton  

app = QApplication([]) # 创建应用程序对象

window = QWidget() # 创建窗口部件
layout = QVBoxLayout() # 创建布局管理器

button = QPushButton("点击我") # 创建按钮
layout.addWidget(button) # 将按钮添加到布局管理器中

window.setLayout(layout) # 设置窗口部件的布局
window.show() # 显示窗口

app.exec() # 进入应用程序的主循环

image.png

很好,说明各种环境已经搭建好了!

Step 2 实现基础功能

接下来尽管提需求,从开发者的角度出发,一步步给 GPT 进行引导,从易到难,功能从简单到复杂

例如我开始给 GPT 提需求:

我提供一组数据,点击按钮之后,就可以在一个输出位置输出这组数据的标准差

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import sys  
import numpy as np
from PyQt6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel, QLineEdit

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()

self.setWindowTitle("标准差计算器")
self.setGeometry(100, 100, 400, 200)

# 主部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)

# 布局
self.layout = QVBoxLayout()
self.central_widget.setLayout(self.layout)

# 输入框
self.data_input = QLineEdit()
self.data_input.setPlaceholderText("输入数据,用逗号分隔")
self.layout.addWidget(self.data_input)

# 计算按钮
self.calculate_button = QPushButton("计算标准差")
self.calculate_button.clicked.connect(self.calculate_standard_deviation)
self.layout.addWidget(self.calculate_button)

# 输出标签
self.result_label = QLabel("标准差:")
self.layout.addWidget(self.result_label)

def calculate_standard_deviation(self):
# 获取输入数据
data_text = self.data_input.text()
if not data_text:
self.result_label.setText("请先输入数据")
return

# 解析数据
try:
data = list(map(float, data_text.split(',')))
except ValueError:
self.result_label.setText("数据格式错误,请输入有效的数字")
return

# 计算标准差
std_dev = np.std(data)
self.result_label.setText(f"标准差:{std_dev:.2f}")

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())

image.png

好了,手动输入几组数据,确实能够计算出来标准差了,不过我们的数据来自 Excel,而且用逗号分隔数据的方式也不方便。于是就有了如下需求:

但是,你知道的,我的输入数据一般从 excel 中复制过来的,这种用逗号分隔数字的方式让我在输入的时候非常麻烦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QPlainTextEdit, QLabel
import numpy as np

class DataProcessingApp(QWidget):
def __init__(self):
super().__init__()

# 设置窗口标题和尺寸
self.setWindowTitle("数据处理应用")
self.setGeometry(100, 100, 400, 300)

# 创建布局和组件
layout = QVBoxLayout()

self.text_edit = QPlainTextEdit(self)
self.text_edit.setPlaceholderText("在这里粘贴数据...")
layout.addWidget(self.text_edit)

self.calculate_button = QPushButton("计算标准差", self)
self.calculate_button.clicked.connect(self.calculate_std_dev)
layout.addWidget(self.calculate_button)

self.result_label = QLabel("标准差:", self)
layout.addWidget(self.result_label)

self.setLayout(layout)

def calculate_std_dev(self):
# 获取文本内容
text = self.text_edit.toPlainText()

# 处理文本数据
try:
# 将文本数据按行分隔,然后按空格或制表符分隔
data = [float(num) for line in text.splitlines() for num in line.split()]
if data:
# 计算标准差
std_dev = np.std(data)
self.result_label.setText(f"标准差:{std_dev:.2f}")
else:
self.result_label.setText("标准差:无效数据")
except ValueError:
self.result_label.setText("标准差:数据格式错误")

app = QApplication([])
window = DataProcessingApp()
window.show()
app.exec()

image.png

以上这组数据就是直接从 Excel 粘贴进去的。看来功能 GPT 是帮我们实现了

Step 3 完善程序

接下来按照上面的步骤,进一步提需求,进一步完善程序代码
例如,可以增加一些数据清洗、数据输入验证、错处处理、历史记录、导出数据等功能
也可以对程序进行拆分,不同功能的代码写到不同的 py 文件中

image.png

当前的程序结构为

1
2
3
4
5
6
data_processor/

├── main.py
├── ui.py
├── processor.py
└── utils.py

主程序

main.py
1
2
3
4
5
6
7
8
9
import sys
from PyQt6.QtWidgets import QApplication
from ui import DataProcessorApp

if __name__ == "__main__":
app = QApplication(sys.argv)
processor = DataProcessorApp()
processor.show()
sys.exit(app.exec())

UI 界面

ui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QTextEdit, QLabel  
from PyQt6.QtGui import QFont, QColor
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPalette
from processor import DataProcessor


class DataProcessorApp(QWidget):
def __init__(self):
super().__init__()
self.processor = DataProcessor()
self.init_ui()

def init_ui(self):
# Set the overall layout and style
layout = QVBoxLayout()
self.setStyleSheet("background-color: #f0f0f0;")
self.setPalette(QPalette(QColor('#f0f0f0')))

# Create and style widgets
self.input_text = QTextEdit(self)
self.input_text.setPlaceholderText("在这里粘贴数据,每行一个数字")
self.input_text.setStyleSheet("font-size: 14px; padding: 10px; border: 1px solid #ccc;")
layout.addWidget(self.input_text)

self.mean_label = QLabel("平均值:", self)
self.mean_label.setStyleSheet("font-size: 16px; color: #333;")
layout.addWidget(self.mean_label)

self.variance_label = QLabel("方差:", self)
self.variance_label.setStyleSheet("font-size: 16px; color: #333;")
layout.addWidget(self.variance_label)

self.std_dev_label = QLabel("标准差:", self)
self.std_dev_label.setStyleSheet("font-size: 16px; color: #333;")
layout.addWidget(self.std_dev_label)

self.reliability_label = QLabel("重复性:", self)
self.reliability_label.setStyleSheet("font-size: 16px; color: #333;")
layout.addWidget(self.reliability_label)

process_button = QPushButton("计算标准差", self)
process_button.setStyleSheet(
"background-color: #4CAF50; color: white; font-size: 14px; padding: 10px; border: none; border-radius: 5px;")
process_button.clicked.connect(self.calculate_std_dev)
layout.addWidget(process_button)

reliability_button = QPushButton("计算重复性", self)
reliability_button.setStyleSheet(
"background-color: #2196F3; color: white; font-size: 14px; padding: 10px; border: none; border-radius: 5px;")
reliability_button.clicked.connect(self.calculate_reliability)
layout.addWidget(reliability_button)

self.history_text = QTextEdit(self)
self.history_text.setPlaceholderText("历史记录")
self.history_text.setReadOnly(True)
self.history_text.setStyleSheet("font-size: 14px; padding: 10px; border: 1px solid #ccc;")
layout.addWidget(self.history_text)

self.setLayout(layout)
self.setWindowTitle("数据处理程序")
self.setGeometry(100, 100, 500, 400)
self.setFont(QFont('Arial', 12))

def calculate_std_dev(self):
data = self.input_text.toPlainText().strip()
try:
numbers = [float(x) for x in data.split() if x.replace('.', '', 1).isdigit()]
if numbers:
std_dev = self.processor.calculate_std_dev(numbers)
mean, variance, std_dev, _ = self.processor.calculate_reliability(numbers)
self.mean_label.setText(f"平均值:{mean:.6f}")
self.variance_label.setText(f"方差:{variance:.6f}")
self.std_dev_label.setText(f"标准差:{std_dev:.6f}")
else:
self.std_dev_label.setText("标准差:无效数据")
self.mean_label.setText("平均值:无效数据")
self.variance_label.setText("方差:无效数据")
history = self.history_text.toPlainText()
new_entry = f"数据:{', '.join(map(str, numbers))} | 标准差:{std_dev:.6f} | 平均值:{mean:.6f} | 方差:{variance:.6f}\n"
self.history_text.setText(history + new_entry)
except Exception as e:
self.std_dev_label.setText(f"错误:{e}")
self.mean_label.setText("平均值:无效数据")
self.variance_label.setText("方差:无效数据")

def calculate_reliability(self):
data = self.input_text.toPlainText().strip()
try:
numbers = [float(x) for x in data.split() if x.replace('.', '', 1).isdigit()]
if numbers:
mean, variance, std_dev, reliability = self.processor.calculate_reliability(numbers)
self.mean_label.setText(f"平均值:{mean:.6f}")
self.variance_label.setText(f"方差:{variance:.6f}")
self.std_dev_label.setText(f"标准差:{std_dev:.6f}")
self.reliability_label.setText(f"重复性:{reliability:.6f}")
else:
self.reliability_label.setText("重复性:无效数据")
self.mean_label.setText("平均值:无效数据")
self.variance_label.setText("方差:无效数据")
self.std_dev_label.setText("标准差:无效数据")
history = self.history_text.toPlainText()
new_entry = f"数据:{', '.join(map(str, numbers))} | 标准差:{std_dev:.6f} | 重复性:{reliability:.6f} | 平均值:{mean:.6f} | 方差:{variance:.6f}\n"
self.history_text.setText(history + new_entry)
except Exception as e:
self.reliability_label.setText(f"错误:{e}")
self.mean_label.setText("平均值:无效数据")
self.variance_label.setText("方差:无效数据")
self.std_dev_label.setText("标准差:无效数据")

数据处理

processor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

class DataProcessor:
def calculate_std_dev(self, numbers):
return np.std(numbers, ddof=1)

def calculate_reliability(self, numbers):
mean = np.mean(numbers)
variance = np.var(numbers, ddof=1)
std_dev = np.sqrt(variance)
reliability = std_dev / mean
return mean, variance, std_dev, reliability

Step 4 打包程序

想要将整个程序打包成 exe 文件,这样方便在没有 python 环境时依然可以运行,步骤如下:

  • 安装 PyInstaller 包(可以直接在 powershell 中安装)
  • 使用 PyInstaller 打包脚本

1、在 PowerShell 中,运行如下命令

1
pip install pyinstaller

注意:前面已经安装了 python 程序,应该是可以使用 pip 命令了的。可输入 pip --version 命令查看。若该命令无法使用,很可能是没有将 python 解释器添加到环境变量中,可进行如下操作:

1
2
C:\Users\Administrator\AppData\Local\Programs\Python\Python312\
C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Scripts\

这里的路径请替换为实际安装 Python 的路径

image.png

2、运行 pyinstaller 命令打包程序

1
pyinstaller --onefile --windowed your_script.py
  • --onefile:将所有内容打包成一个单独的 .exe 文件。
  • --windowed:用于创建一个没有命令行窗口的图形界面应用。

打包完成后,会生成几个文件夹:

  • dist 中包含生成的 exe 文件
  • build 中包含构建过程中的临时文件,可以删除。
  • your_script.spec 文件是 PyInstaller 的配置文件,可以根据需要进行修改。

image.png

.gif

恭喜你,得到了一款简易的小程序:)

明明程序实现的功能很简单,为什么生成的程序还那么大呢,例如生成上面的这个 exe 文件就有 50M。因为软件将一些必要的程序包(如 numpy 模块)都打包进去了,若之后再增加一些计算相关的各种功能进去,程序体积可能也只会大一丢丢吧

另外,打包时如何优化资源,排除掉一些不必要的模块还值得学学。不过,尽管文件体积大点,功能总算是实现了,还是蛮有成就感的

Word 操作指南

作者 coffeelize
2024年6月14日 15:19

粘贴时保留纯文本

参考资料:如何设置 WORD 粘贴时默认仅保留文本格式 - 百度经验

image.png

之后从浏览器中粘贴过来,就不需要在按一次 Ctrl,然后再按 T 了,直接粘贴为纯文本格式

image.png

使用自定义模板

参考资料:office 增加自定义文档模板_用户可自定义文档类型的模板,对文档模板进行规范,并可定义模板中的 “签字标记”-CSDN 博客

  1. 打开手头的 word 模板
  2. 另存为 dotx,会自动跳转到自定义 office 模板的文件夹路径,保存
  3. 再次新建 word 文档的时候,可从 个人 的模板中选择进行新建文档

image.png

image.png

Mathtype 插入公式

如果使用中文输入法,那么输出的 x 这样的字符就不是标准的数学字体,切换成英文

Word 自带的公式

有专用和线性区别,比如说如下的 Cambria Math 字体,还有两种显示模式

调整表格行高

问题:直接调整段落,设置为最小值,表格之间仍然还是有间隙

1、先手动减小这个高度

image.png

2、调整完之后,行与行之间的间隙没有了

image.png

3、此时在调整为最小值

image.png

网页文字复制

有些网站是禁止复制文字的 —> 在不使用浏览器插件的情况下,可以将网页保存为 mhtml 本地文件

Mermaid 甘特图

作者 coffeelize
2024年6月12日 21:15

参考资料

案例

1
2
3
4
5
6
7
8
9
10
11
12
gantt
title 项目进度
dateFormat YYYY-MM-DD
section 设计
任务1: a1, 2022-01-01, 3d
任务2: a2, after a1, 2d
%% 注释内容
section 开发
任务3: b1, after a2, 4d
里程碑: milestone, after b1
section 测试
任务4:c1, after b1, 2d

修改坐标轴格式

坐标轴(横坐标)默认输出日期格式为 YYYY-MM-DD,以天作为单位,如何以分钟或者秒作为横坐标的单位呢:

1
axisFormat %Y-%m-%d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%a - 缩写的星期几名称。
%A - 完整的星期几名称。
%b - 缩写的月份名称。
%B - 完整的月份名称。
%c - 日期和时间,格式为 "%a %b %e %H:%M:%S %Y"。
%d - 以十进制数表示的零填充的月份中的日期 [01,31]。
%e - 以十进制数表示的空格填充的月份中的日期 [ 1,31];等同于 %_d。
%H - 小时(24小时制)的十进制数表示 [00,23]。
%I - 小时(12小时制)的十进制数表示 [01,12]。
%j - 以十进制数表示的一年中的日期 [001,366]。
%m - 以十进制数表示的月份 [01,12]。
%M - 以十进制数表示的分钟 [00,59]。
%L - 以十进制数表示的毫秒数 [000, 999]。
%p - 上午(AM)或下午(PM)。
%S - 以十进制数表示的秒数 [00,61]。
%U - 以十进制数表示的一年中的周数(以星期日作为一周的第一天) [00,53]。
%w - 以十进制数表示的星期几 [0(星期日),6]。
%W - 以十进制数表示的一年中的周数(以星期一作为一周的第一天) [00,53]。
%x - 日期,格式为 "%m/%d/%Y"。
%X - 时间,格式为 "%H:%M:%S"。
%y - 以十进制数表示的不带世纪的年份 [00,99]。
%Y - 以十进制数表示的带世纪的年份。
%Z - 时区偏移,例如 "-0700"。
%% - 字面上的 "%" 字符。

例如需要将坐标轴改为小时和分钟,那么:

1
2
3
4
5
6
7
gantt
title 甘特图
+ axisFormat %H-%M
+ dateFormat HH:mm
section 样本1
任务1:a1,00:00, 70s
任务2:after a1, 100s

image.png

将坐标轴改成分钟和秒,那么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
gantt
title 效率计算
+ axisFormat %M:%S
+ dateFormat mm:ss
%% 进样
section 流程1
步骤1: milestone,a0,0,0s
步骤2: a1,after a0,8.6s
步骤3: a2,after a1,3s
步骤4: a3,after a2,10s
section 流程2
步骤2: b1,after a2,8.6s
步骤3: b2,after b1,3s
步骤4: b3,after b2,10s

image.png

给里程碑取别名

1
2
3
4
5
6
7
gantt
dateFormat HH:mm
axisFormat %H:%M
+ Initial milestone : milestone, m1, 17:49, 2m
Task A : 10m
Task B : 5m
+ Final milestone : milestone, m2, 18:08, 4m

image.png

某效率计算

案例分析如下,对于有同步运行的动作,可通过这种时间重叠的方式,求出仪器检测样本的最快时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
gantt
title 水分检测效率计算
axisFormat %M-%S
dateFormat mm-ss

section 样本1
开始检测: milestone,SF1-0,0,0s
样本瓶就位:SF1-1,after SF1-0,10s
夹取注射器: SF1-2,after SF1-0,10s
开盖:SF1-3,after SF1-1,10s
润洗3次注射器: SF1-4,after SF1-2,45s
抽取样品: SF1-5,after SF1-4,10s
拧盖:SF1-6,after SF1-5,10s
称重: SF1-7,after SF1-5,20s
注入仪器:SF1-8,after SF1-7,20s
称重: SF1-9,after SF1-8,20s
注射器放托盘: SF1-10,after SF1-9,10s
水分检测:SF1-11,after SF1-8,240s

section 样本2
样本瓶就位:SF2-1,after SF1-10,10s
夹取注射器: SF2-2,after SF1-10,10s
开盖:SF2-3,after SF2-1,10s
润洗3次注射器: SF2-4,after SF2-2,45s
抽取样品: SF2-5,after SF2-4,10s
拧盖:SF2-6,after SF2-5,10s
称重: SF2-7,after SF2-5,20s
注入仪器:SF2-8,after SF2-7,20s
称重: SF2-9,after SF2-8,20s
注射器放托盘: SF2-10,after SF2-9,10s
水分检测:SF2-11,after SF2-8,240s

section 样本3
样本瓶就位:SF3-1,after SF2-10,10s
夹取注射器: SF3-2,after SF2-10,10s
开盖:SF3-3,after SF3-1,10s
润洗3次注射器: SF3-4,after SF3-2,45s
抽取样品: SF3-5,after SF3-4,10s
拧盖:SF3-6,after SF3-5,10s
称重: SF3-7,after SF3-5,20s
注入仪器:SF3-8,after SF3-7,20s
称重: SF3-9,after SF3-8,20s
注射器放托盘: SF3-10,after SF3-9,10s
水分检测:SF3-11,after SF3-8,240s

image.png

Tips:每个样本检测需要执行的操作都是一样的。第一个样本的代码写完后,后续可以通过查找替换的方式,进行批量替换。例如在样本一中将 SF1-1 第一个 1 替换为 2,即 SF2-1,样本 2 的代码便很快可以修改完毕。

Axios 异步框架简明笔记

作者 coffeelize
2023年11月28日 20:13

Axios 异步框架简介

Axios 对原生的 AJAX 进行封装,简化书写

Axios 快速入门

  1. 引入 axios 的 js 文件
  2. 使用 axios 发送请求,并获取相应结果

详细步骤如下

一、在 webapp 下新建 js 文件夹,拷贝 axios 的 js 文件
二、新建 html 文件,引入 js 文件

1
<script src="js/axios-0.18.0.js"></script>

三、创建 AxiosServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AxiosServlet extends HttpServlet {  
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("get...");
//1.接收请求参数
String username = request.getParameter("username");
System.out.println(username);
//2.响应数据
response.getWriter().write("hello Axios");
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("post...");
this.doGet(request, response);
}
}

四、在 html 中编写 js 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>

<script>
//1.get
/* axios({
method:"get",
url:"http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan"
}).then(function (resp){
alert(resp.data);
})*/

//2.post
axios({
method: "get",
url: "http://localhost:8080/ajax-dmeo/axiosServlet",
//data是请求参数
data: "username=zhangsan"
}).then(function (resp) {
alert(resp.data);
})


</script>

</body>
</html>

代码说明及注意事项

  1. axios 大括号中的为 Java 中的对象
  2. .then() 方法是一个回调函数,如果响应接收到了的话就自动执行
  3. data: "username=zhangsan",data 是请求参数。这里可以传 JSON 格式的数据。除此之外,还可以传 JS 对象类型的数据(JSON 数据格式可以和 Java 中的对象数据格式通过某些方式进行转换),因为 Axios 框架会自动将这个 JS 对象转为 JSON 的数据格式
  4. Get 和 Post 两种方式传递参数的方式不一样,所以在 axios 方法中传入的对象(大括号包裹的内容)的方式不一样,一个写在 URL 中,一个写在 Data 属性中
  5. .then() 回调函数中,function 函数中的参数名可以不为 resp,随便一个都行,保持下面对象(resp.data)和这个参数名(resp)一致即可
  6. resp.data 即服务器端的 Servlet 响应过来的数据
1
2
3
4
5
6
7
8
9
10
11
flowchart RL
b1-->|"username = &quot;zhangsan&quot;"|servlet1
servlet1-->|data|b1
    subgraph Browsers
    b1
    b2
    end
    subgraph servers
    servlet1
    servlet2
    end

简单来说,Axios 实现的功能就是:通过 get 或 post 给 Servlet 传递一个参数(username=“zhangsan”),然后 Servlet 接收到这个参数,就可以进行判断的操作,根据判断的结果在给浏览器发送一个响应。浏览器收到响应数据(date)之后,就可以做出一些操作,比如弹出窗口操作。

Axios 请求方式别名

为了方便起见,Axios 已经为所有支持的请求方法提供了别名

发送 Get 请求

1
2
3
4
//1. Get方式  
axios.get("http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan").then(function (resp){
alert(resp.data);
})

发送 Post 请求

1
2
3
axios.post("http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan","username=zhangsan").then(function (resp){  
alert(resp.data);
})

原生的 Axios 书写方式 VS 别名的简化书写方式

  • 原生的书写格式:阅读性较好
  • 别名的方式:代码量少,基本上只需要填写必要的参数信息

Revision Letter

作者 coffeelize
2023年10月27日 13:56

输出结果

可以使用 Overleaf 在线编译(XeLaTeX),也可以本地编译

Revision_Letter_页面_1.jpg

Revision_Letter_页面_2.jpg

目录结构

1
2
3
4
5
│  Revision Letter.tex
│ setting.tex
└──figs
Fig1.png
Fig2.png

image.png

setting.tex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
\usepackage{amsfonts}%
\usepackage{amssymb}
\usepackage{mathrsfs}
\usepackage{latexsym,amsmath,amsfonts}
\usepackage{xcolor}% http://ctan.org/pkg/xcolor
\usepackage{ifmtarg}% http://ctan.org/pkg/ifmtarg
\usepackage{xifthen}% http://ctan.org/pkg/xifthen
\usepackage{environ}% http://ctan.org/pkg/environ
\usepackage{multido}% http://ctan.org/pkg/multido
\usepackage{lipsum,ctex}% http://ctan.org/pkg/lipsum


%\usepackage[displaymath]{lineno}
\usepackage[backref]{hyperref}
\linespread{1}
%\usepackage{showkeys}

%\usepackage{times}
\allowdisplaybreaks
%\date{\today}
\date{\today}
\newcommand{\red}{\color{red} } %红色字体
\def\ft{\frac d{dt}}
\def\pt{\partial_{t}}
\def\r{\mathbb{R}^2}
\def\no{\nonumber}
\def\eps{\epsilon}
\textwidth 150mm
\textheight 220mm
\voffset -25mm \hoffset -15mm\topmargin1.4 cm
\renewcommand{\baselinestretch}{1.235}

\makeatletter%
\newcommand{\commenthang}{% top comment decoration
\begingroup%
\setlength{\unitlength}{.005\linewidth}% \linewidth/200
\begin{picture}(0,0)(1.5,0)%
\linethickness{0.45pt} \color{blue!50}%
\put(-3,2){\line(1,0){206}}% Top line
\multido{\iA=2+-1,\iB=50+-10}{5}{% Top hangs
\color{blue!\iB}%
\put(-3,\iA){\line(0,-1){1}}% Top left hang
\put(203,\iA){\line(0,-1){1}}% Top right hang
}%
\end{picture}%
\endgroup%
}%
\newcommand{\commenthung}{% bottom comment decoration
\nobreak
\begingroup%
\setlength{\unitlength}{.005\linewidth}% \linewidth/200
\begin{picture}(0.0,0)(1.5,0)%
\linethickness{0.45pt} \color{blue!50}%
\put(-3,0){\line(1,0){206}}% Bottom line
\multido{\iA=0+1,\iB=50+-10}{5}{% Bottom hangs
\color{blue!\iB}%
\put(-3,\iA){\line(0,1){1}}% Bottom left hang
\put(203,\iA){\line(0,1){1}}% Bottom right hang
}%
\end{picture}%
\endgroup%
}%

\newcounter{comment}
\renewcommand{\thecomment}{\arabic{comment}}
\NewEnviron{comment}[1][]{%
\par\noindent\commenthang\par\nobreak\noindent%\addvspace{-.5ex}
\refstepcounter{comment}\postdisplaypenalty=10000 %
{\sffamily\bfseries\upshape Comment \thecomment\@ifnotmtarg{#1}{\ (#1)}}\ \ \ignorespaces%
\BODY % Typeset comment body/content
\par\addvspace{-1ex}\nobreak\noindent\commenthung\par\addvspace{.4ex}%
}
\makeatother

Revision Letter.tex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
\documentclass[reqno,12pt]{amsart}
\input{setting}
\usepackage{graphicx}
\usepackage{fontspec}
\usepackage{xcolor}
\usepackage{pifont}
\usepackage{zhlipsum}

\begin{document}

\begin{center}
\textbf{\Large Response to Reviewers}
\end{center}
\vspace{2ex}

\begin{flushleft}
尊敬的审稿专家和编辑老师:
\end{flushleft}

您们好!非常感谢您们提出的评审意见,您们的所有建议都非常的重要,它们对我的论文写作和科研工作都具有重要的指导意义,这些中肯的意见是对我莫大的鼓励与支持。在下文中,我们将解释如何在修订中充分考虑到您们的意见。

\begin{comment}
此类综述较多(尤其以外文为主),如何明确该文的特色、创新,仍需作者在引言部分明确论述;

\vspace{1ex}
\noindent{\bf Response \thecomment} 非常感谢专家提出的建议。我们已在引言部分重新修正和完善了这一部分内容, \textcolor{red}{修正后的内容如下}:

\zhlipsum[1]

再次感谢专家老师的宝贵意见。
\end{comment}

\begin{comment}
此类综述较多(尤其以外文为主),如何明确该文的特色、创新,仍需作者在引言部分明确论述;

\vspace{1ex}
\noindent{\bf Response \thecomment} 非常感谢专家提出的建议。我们已在引言部分重新修正和完善了这一部分内容, \textcolor{red}{修正后的内容如下}:

\zhlipsum[1]

再次感谢专家老师的宝贵意见。
\end{comment}

最后感谢审稿专家在百忙之中对论文提出的中肯建议,使论文质量得到提高。同时也感谢编辑老师辛苦的工作。

愿各位工作顺利,身体健康!

此致!

\noindent{敬礼!}

\vspace{2ex}
\begin{flushright}
全体作者

2022年9月23日
\end{flushright}

\end{document}

处理 PDF 中的表格

作者 coffeelize
2023年10月20日 23:03

处理程序

Windows - PDF Software: Open, Read & Edit PDFs | FineReader PDF

操作步骤

1、使用 Abbyy 打开 PDF 文件

20231021211516.png

2、按压左键拉动一个方框包含要复制的表格

3、点击第三个按钮,复制表格

4、识别成功后的变化

image.png

5、可以直接复制到 Excel 当中

image.png

对于中文字体和字号什么可能会有问题,可以全选,然后统一字体和字号

PDF 加密

作者 coffeelize
2023年10月19日 16:38

参考资料

口令密码

文件 —> 属性 (Ctrl+D) —> 安全性 —> 口令安全性

01-为PDF设置口令密码.gif

PDF 乱码

对于无需搜索的 PDF 文件,使用浏览器阅读(特殊需求)可能会出现中文乱码的情况(尤其是知网下载的中文文献),可以先将 PDF 导出为 JPG,再合并成 PDF

期刊审稿催稿信

作者 coffeelize
2023年10月15日 09:39

参考资料

催稿信

Dear Editor,

I write concerning the progress of our paper. It was initially submitted on May 13, 2023 and was assigned the manuscript number: xxxx. Now I am worrying about whether it still works normally because the submission has been kept “Under Review” for about two months, as showed on editorial manager. Would you mind checking on the progress of it for me? Your reply would be highly appreciated.

Thanks very much for your attention to our paper.

Best Regards.

Yours sincerely,
xxxx

修订稿催稿信

Dear Editor,

I apologize for the inconvenience. I am a graduating master’s student with the intention of pursuing a Ph.D. However, I am concerned about this, as I require another accepted or published paper to strengthen my Ph.D. application. Regarding my revised manuscript with the manuscript number xx-xxxx, which was submitted on xxxx-xx-xx, it is still under review. Could you kindly expedite the review process for my manuscript? I sincerely appreciate your assistance in this matter.

I look forward to hearing from you soon.

Best Regards,
xxxx

LaTeX 图片背景 eso-pic 宏包

作者 coffeelize
2024年6月21日 16:26

参考资料

用法

  • \AddToShipoutPictureBG:为每一页添加背景
  • \AddToShipoutPictureBG*:仅为当前页面添加背景
  • \AddToShipoutPictureFG:类似于 BG,但只作用于文档内容部分

一些预定于好的位置命令

  • AtPageUpperLeft
  • AtPageLowerLeft
  • AtPageCenter
  • AtTextUpperLeft
  • AtTextLowerLeft
  • AtTextCenter
  • AtStockUpperLeft
  • AtStockLowerLeft
  • AtStockCenter

案例分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
\documentclass{ctexart}
\usepackage{graphicx}
\usepackage{zhlipsum}
\usepackage{eso-pic}
\begin{document}
\zhlipsum[1-3]
\clearpage
\AddToShipoutPictureBG{
\includegraphics[width=\paperwidth,height=\paperheight]{example-image-duck}
}
\clearpage
\zhlipsum[1]
\clearpage
\zhlipsum[1]
\section{第一部分}

\end{document}

插入长宽和当前页面长宽一致的鸭子的背景图片

image.png

如果我们有比较好的背景图片,比如四角带有阴影的 png 图片或者设计好的图片,那么使用该宏包还是挺有效果的

部分说明

1
width=\paperwidth,height=\paperheight

表示图片的长宽和页面的长宽一致,将图片强制拉伸至页面长宽

1
2
3
example-image-duck
example-image-a
example-grid-100x100bp

这几个图片名称经常用于插入示范图片,分别代表 鸭子字母A长宽为10个单元格的网格表

注意使用 graphics 宏包(正常应为 graphicx 宏包)插入 includegraphics 命令时 texstudio 不会出现红色背景提示,但是编译出来老是报错 \end{document}

image.png

Axios 异步框架简明笔记

作者 coffeelize
2023年11月28日 20:13

Axios 异步框架简介

Axios 对原生的 AJAX 进行封装,简化书写

Axios 快速入门

  1. 引入 axios 的 js 文件
  2. 使用 axios 发送请求,并获取相应结果详细步骤如下

一、在 webapp 下新建 js 文件夹,拷贝 axios 的 js 文件
二、新建 html 文件,引入 js 文件

1
<script src="js/axios-0.18.0.js"></script>

三、创建 AxiosServlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AxiosServlet extends HttpServlet {  
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("get...");
//1.接收请求参数
String username = request.getParameter("username");
System.out.println(username);
//2.响应数据
response.getWriter().write("hello Axios");
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("post...");
this.doGet(request, response);
}
}

四、在 html 中编写 js 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>

<script src="js/axios-0.18.0.js"></script>

<script>
//1.get
/* axios({
method:"get",
url:"http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan"
}).then(function (resp){
alert(resp.data);
})*/

//2.post
axios({
method: "get",
url: "http://localhost:8080/ajax-dmeo/axiosServlet",
//data是请求参数
data: "username=zhangsan"
}).then(function (resp) {
alert(resp.data);
})


</script>

</body>
</html>

代码说明及注意事项

  1. axios 大括号中的为 Java 中的对象
  2. .then() 方法是一个回调函数,如果响应接收到了的话就自动执行
  3. data: "username=zhangsan",data 是请求参数。这里可以传 JSON 格式的数据。除此之外,还可以传 JS 对象类型的数据(JSON 数据格式可以和 Java 中的对象数据格式通过某些方式进行转换),因为 Axios 框架会自动将这个 JS 对象转为 JSON 的数据格式
  4. Get 和 Post 两种方式传递参数的方式不一样,所以在 axios 方法中传入的对象(大括号包裹的内容)的方式不一样,一个写在 URL 中,一个写在 Data 属性中
  5. .then() 回调函数中,function 函数中的参数名可以不为 resp,随便一个都行,保持下面对象(resp.data)和这个参数名(resp)一致即可
  6. resp.data 即服务器端的 Servlet 响应过来的数据
1
2
3
4
5
6
7
8
9
10
11
flowchart RL
b1-->|"username = &quot;zhangsan&quot;"|servlet1
servlet1-->|data|b1
    subgraph Browsers
    b1
    b2
    end
    subgraph servers
    servlet1
    servlet2
    end

简单来说,Axios 实现的功能就是:通过 get 或 post 给 Servlet 传递一个参数(username=“zhangsan”),然后 Servlet 接收到这个参数,就可以进行判断的操作,根据判断的结果在给浏览器发送一个响应。浏览器收到响应数据(date)之后,就可以做出一些操作,比如弹出窗口操作。

Axios 请求方式别名

为了方便起见,Axios 已经为所有支持的请求方法提供了别名

发送 Get 请求

1
2
3
4
//1. Get方式  
axios.get("http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan").then(function (resp){
alert(resp.data);
})

发送 Post 请求

1
2
3
axios.post("http://localhost:8080/ajax-dmeo/axiosServlet?username=zhangsan","username=zhangsan").then(function (resp){  
alert(resp.data);
})

原生的 Axios 书写方式 VS 别名的简化书写方式

  • 原生的书写格式:阅读性较好
  • 别名的方式:代码量少,基本上只需要填写必要的参数信息

LaTeX 投稿注意事项

作者 coffeelize
2023年10月31日 11:21

bib 参考文献

1、使用 % 可添加注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
% 旧文献
@article{latunussa2016analysis,
title={Analysis of material recovery from silicon photovoltaic panels},
author={LATUNUSSA, Cynthia and MANCINI, Lucia and BLENGINI, Giovanni and ARDENTE, Fulvio and PENNINGTON, David and others},
year={2016}
}

% 添加的新文献
@article{latunussa2016analysis,
number = {LB-NA-27797-EN-N},
address = {Luxembourg (Luxembourg)},
issn = {1831-9424},
year = {2016},
author = {LATUNUSSA, Cynthia and MANCINI, Lucia and BLENGINI, Giovanni and ARDENTE, Fulvio and PENNINGTON, David and others},
isbn = {978-92-79-57277-7},
publisher = {Publications Office of the European Union},
title = {Analysis of material recovery from silicon photovoltaic panels}
}

2、若使用本地 TeX Studio 进行编译,若参考文献信息不完整,编译时会有提示,可根据这些提示对参考文献信息进行手动补全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
You're missing a field part---line 77 of file cas-refs.bib
: number =
: ,
I'm skipping whatever remains of this entry
Repeated entry---line 153 of file cas-refs.bib
: @techreport{weckend2016end
: ,
I'm skipping whatever remains of this entry
Repeated entry---line 275 of file cas-refs.bib
: @article{li2022green
: ,
I'm skipping whatever remains of this entry
Warning--empty journal in latunussa2016analysis
(There were 3 error messages)

引用图片

  • 同一期刊,对这种格式还是比较宽松的,例如 Fig.4 a) and b) 以及 Fig.4 (b) 都是可以的
  • 大部分包含子图的图片在插入图片前已经提前组好(子图 a、b、c 这种序号也是手动添加的),而不是利用 LaTeX 命令将多张子图组成一张大图(虽然方便引用子图,但是实现子图的整齐排列过于困难)

image.png

image.png

特殊符号

参考:latex 排版服务,如何输入商标 R 符号,TM 符号,版权 c 符号

专有名词对照表

如果借助 GPT 这样的工具进行翻译,将这些专有名词塞给 GPT,GPT 会根据上下文进行翻译,可以很大程度上减少专有名词的翻译错误

1
2
3
4
5
6
7
8
9
10
11
下层EVA 请翻译为 back EVA;上层EVA 请翻译为 front EVA;背面金属化 请翻译为 back metallization;电池请翻译为 cell
背板 请翻译为:backsheet;有价部分请翻译为:Valuable components;有机物部分请翻译为:Organic components
上层封装材料 请翻译为:front encapsulation;下层封装材料请翻译为:back encapsulation
铝背电极:Aluminum Back Electrode
铝硅共晶层:Eutectic layer、Al-Si eutectic
铝掺杂p+层: Al-p+-layer、BSF
剩余的铝颗粒层:alumina paste layer

统一将 rear metallization layer —> back metallization
统一将 silicon cells —> solar cell;solar cell silicon wafer —> solar cell
统一将 upper —> front

Word2LaTeX

例如 Word 中的 符号,换成 LaTeX 之后,可以批量替换为 $\tccentigrade$,最好是对这些批量替换操作做一个记录

1
2
3
4
5
6
7
8
9
10
11
12
℃ —> $\tccentigrade$ 
× —> $\times$
± —> $\pm$
-145 —> $-$
µ —> \textmu
KAl(OH)4 —> $KAl(OH)_4$
(Tedlar®/PET/Tedlar®) —> $^\circledR$ 或者 $^{\textregistered}$ 或者 Tedlar/PET/Tedlar
90° —> 90^\circ
Figure —> 引用
Fig —> 引用
Fig.\ref —> Cref
\Cref{fig:1}(a)

实验室器材使用手册

作者 coffeelize
2023年10月27日 13:26

冷冻柜

  • 设定温度 (SP) 是唯一不需要通过输入密码就可以设定的参数
  • 若需修改 r1 和 r2 的数值,需要密码
  • 长按 Set 键大概 8 秒,确认密码后可以进入其他参数的设置,出厂设置的密码默认是 0
  • 特别注意参数 r1 (设定温度下限) 和 r2 (设定温度上限),设定温度时不要选错参数 (非 R1 和 R2)
  • 设定好 r1 和 r2 之后,设定温度 (SP) 就可以将温度设置在这个区间内,但是注意及时更新 SP 的设定值,因为这个设定值有可能是之前 r1-r2 区间内的值,而非本次设定的 r1-r2 区间内的值

注意事项:

  • 参数中既有 R1 和 R2,也有 r1 和 r2,设置低温参数时,只需设置 r1 和 r2 即可,不要动无关的参数
  • 做完冷冻实验后,第二天冰箱内部会有小水珠,需要及时擦干,否则会加速冷冻板生锈

液氮实验机

  • 实验机连接液氮罐的液相阀
  • 开机 –> 登录 –> 选择管理员用户 –> 密码 8686 –> 登录
  • 管理员初始密码 8686,操作员初始密码 88
  • 进入主控界面 –> 温区设置,可以调整冷冻时间、冷冻温度和保温时间
  • 设置好之后,回到主控界面 –> 自动启动
  • 温度尽量不要设置低于 -140℃,过低的温度会导致液氮的快速消耗,同时,可能会导致液氮以液体的形式直接从机内流出

颚式破碎机

  • 氧化锆颚式破碎机,颚板由定颚和动颚组成,调节两者间距时,注意不要让这两块颚板相互打着
❌
❌