mjpic 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/.vercel/project.json +1 -0
  2. package/README.md +105 -0
  3. package/api/cli.ts +42 -3
  4. package/deploy/mjpic-start.desktop +20 -0
  5. package/deploy/node_install.sh +111 -0
  6. package/deploy//344/275/277/347/224/250/350/257/264/346/230/216.txt +17 -0
  7. package/dist/cli/cli.js +36 -2
  8. package/dist/client/assets/{index-BQfYCBRX.js → index-C4AVPLLP.js} +25 -25
  9. package/dist/client/index.html +1 -1
  10. package/package.json +4 -3
  11. package/scripts/get-random-port.js +40 -0
  12. package/src/components/dialogs/SaveDialog.tsx +1 -1
  13. package/src/components/layout/Header.tsx +43 -18
  14. package/src/components/layout/RightPanel.tsx +0 -21
  15. package/vite.config.ts +3 -1
  16. package/tmp/guangxi.jpg +0 -0
  17. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.45_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/351/242/204/350/256/276/345/260/272/345/257/270.jpg +0 -0
  18. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.47.51_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/211/213/345/267/245/350/276/223/345/205/245/345/260/272/345/257/270.jpg +0 -0
  19. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.54.56_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/346/267/273/345/212/240/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
  20. package//345/217/202/350/200/203/345/233/276/347/211/207//346/210/252/345/261/2172026-02-18 16.55.11_/345/233/276/347/211/207/345/260/272/345/257/270/350/260/203/350/212/202_/345/210/240/351/231/244/345/270/270/347/224/250/345/260/272/345/257/270.jpg +0 -0
@@ -0,0 +1 @@
1
+ {"neverMindDeployCard":true}
package/README.md CHANGED
@@ -40,3 +40,108 @@ mjpic dev
40
40
  1. 克隆仓库
41
41
  2. 安装依赖:`npm install`
42
42
  3. 启动开发服务器:`npm run dev`
43
+
44
+
45
+ ## 安装使用
46
+
47
+ ### 安装
48
+
49
+ Q:Arm架构的麒麟操作系统V10如何安装Node.js?
50
+
51
+ ■ 豆包:
52
+
53
+ 方法一:直接手工安装
54
+
55
+ 访问Node.js官网 https://nodejs.org/zh-cn/download
56
+
57
+ uname -m # aarch64表示系统架构是ARM64
58
+
59
+ 下载Linux ARM64版本
60
+
61
+ cd ~/下载
62
+ wget https://nodejs.org/dist/v24.13.1/node-v24.13.1-linux-arm64.tar.xz
63
+ tar -xvf node-xxx-arm64.tar.xz
64
+ sudo mv node-xxx-arm64 /usr/local/nodejs
65
+
66
+ 配置环境变量
67
+
68
+ sudo vim /etc/profile
69
+ export NODE_HOME=/usr/local/nodejs
70
+ export PATH=$NODE_HOME/bin:$PATH
71
+ source /etc/profile
72
+
73
+ 测试安装是否成功
74
+
75
+ node -v
76
+
77
+ 方法二:配合`/deploy/node_install.sh`脚本安装
78
+
79
+ 1. 保存`node_install.sh 到`下载 目录。
80
+
81
+ 2. 打开终端(terminal)。
82
+
83
+ 3. 进入下载目录:
84
+
85
+ cd ~/下载
86
+
87
+ 4. 赋予脚本可执行权限:
88
+
89
+ chmod +x node_install.sh
90
+
91
+ 5. 以root权限运行脚本:
92
+
93
+ sudo ./node_install.sh
94
+
95
+ 6. 使环境变量生效
96
+
97
+ source ~/.bashrc
98
+
99
+ 7. 下载 敏捷图片(mjpic):
100
+
101
+ npm install mjpic@latest
102
+
103
+ 8. 运行 敏捷图片(mjpic):
104
+
105
+ npx mjpic build --port 3030
106
+
107
+ ### 创建桌面快捷方式
108
+
109
+ Q:如何在麒麟操作系统V10的桌面创建一个快捷方式,单击后直接在终端运行 npx mjpic build --port 3030 命令?
110
+
111
+ ■ 豆包:
112
+
113
+ 方法一:
114
+
115
+ cd ~/桌面
116
+
117
+ vim mjpic-start.desktop
118
+
119
+ [Desktop Entry]
120
+ 快捷方式类型(应用程序)
121
+ Type=Application
122
+ 显示名称(桌面显示的文件名)
123
+ Name=敏捷图片
124
+ 注释(鼠标悬停显示)
125
+ Comment=启动mjpic服务,端口3030
126
+ 图标(可选,可替换为自己的图标路径,也可留空)
127
+ Icon=image
128
+ 关键:执行的命令(xterm/gnome-terminal 打开终端并执行命令)
129
+ 麒麟V10优先用 gnome-terminal,若不行换 xterm
130
+ Exec=mate-terminal -- bash --login -c "source ~/.bashrc; npx mjpic build --port 3030; exec bash"
131
+ 执行终端窗口是否保持打开(yes=执行完不关闭,no=执行完关闭)
132
+ Terminal=yes
133
+ 分类(桌面显示的归类)
134
+ Categories=Graphics
135
+ 编码
136
+ Encoding=UTF-8
137
+ 是否允许执行
138
+ Executable=true
139
+
140
+ chmod +x ~/桌面/mjpic-start.desktop
141
+
142
+ 注:如有相关提示,选择始终允许执行。
143
+
144
+
145
+ 方法二:
146
+
147
+ 9. 关闭终端,保存 mjpic-start.desktop 到 桌面,右键属性勾选可执行权限。双击新建图标运行。
package/api/cli.ts CHANGED
@@ -5,6 +5,7 @@ import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { fileURLToPath } from 'url';
7
7
  import open from 'open';
8
+ import net from 'net';
8
9
  import app from './app.js';
9
10
 
10
11
  const __filename = fileURLToPath(import.meta.url);
@@ -12,8 +13,46 @@ const __dirname = path.dirname(__filename);
12
13
 
13
14
  const program = new Command();
14
15
 
15
- const startServer = async (options: { port: string; host: string }, file?: string) => {
16
- const port = parseInt(options.port, 10);
16
+ // Check if a port is available
17
+ const isPortAvailable = (port: number): Promise<boolean> => {
18
+ return new Promise((resolve) => {
19
+ const server = net.createServer();
20
+ server.once('error', () => resolve(false));
21
+ server.once('listening', () => {
22
+ server.close();
23
+ resolve(true);
24
+ });
25
+ server.listen(port);
26
+ });
27
+ };
28
+
29
+ // Generate a random port between min and max, excluding common ports
30
+ const getRandomPort = async (): Promise<number> => {
31
+ const commonPorts = [3000, 5000, 5173, 8000, 8080, 8888, 4200];
32
+ const min = 10000;
33
+ const max = 65535;
34
+
35
+ // Try up to 50 times to find a port
36
+ for (let i = 0; i < 50; i++) {
37
+ const port = Math.floor(Math.random() * (max - min + 1) + min);
38
+ if (!commonPorts.includes(port) && await isPortAvailable(port)) {
39
+ return port;
40
+ }
41
+ }
42
+
43
+ // Fallback to 0 (let OS choose) if we can't find one, though OS might pick a common one (unlikely)
44
+ return 0;
45
+ };
46
+
47
+ const startServer = async (options: { port?: string; host: string }, file?: string) => {
48
+ let port: number;
49
+
50
+ if (options.port) {
51
+ port = parseInt(options.port, 10);
52
+ } else {
53
+ port = await getRandomPort();
54
+ }
55
+
17
56
  const host = options.host;
18
57
 
19
58
  if (file) {
@@ -58,7 +97,7 @@ program
58
97
 
59
98
  const attachServeOptions = (cmd: Command) => {
60
99
  cmd
61
- .option('-p, --port <number>', 'server port', '3000')
100
+ .option('-p, --port <number>', 'server port')
62
101
  .option('--host <string>', 'server host', 'localhost')
63
102
  .argument('[file]', 'image file to open')
64
103
  .action(async (file, options) => {
@@ -0,0 +1,20 @@
1
+ [Desktop Entry]
2
+ # 快捷方式类型(应用程序)
3
+ Type=Application
4
+ # 显示名称(桌面显示的文件名)
5
+ Name=敏捷图片
6
+ # 注释(鼠标悬停显示)
7
+ Comment=启动mjpic服务,端口3030
8
+ # 图标(可选,可替换为自己的图标路径,也可留空)
9
+ Icon=image
10
+ # 关键:执行的命令(xterm/gnome-terminal 打开终端并执行命令)
11
+ # 麒麟V10优先用 gnome-terminal,若不行换 xterm
12
+ Exec=mate-terminal -- bash --login -c "source ~/.bashrc; npx mjpic build --port 3030; exec bash"
13
+ # 执行终端窗口是否保持打开(yes=执行完不关闭,no=执行完关闭)
14
+ Terminal=yes
15
+ # 分类(桌面显示的归类)
16
+ Categories=Graphics
17
+ # 编码
18
+ Encoding=UTF-8
19
+ # 是否允许执行
20
+ Executable=true
@@ -0,0 +1,111 @@
1
+ #!/bin/bash
2
+ # Node.js ARM64架构 麒麟V10 自动安装脚本
3
+ # 版本:v24.13.1
4
+ # 修复:sudo执行时使用原始用户目录 + 环境变量全局生效
5
+
6
+ # 定义Node.js版本和下载地址
7
+ NODE_VERSION="v24.13.1"
8
+ NODE_ARCH="linux-arm64"
9
+ NODE_PACKAGE="node-${NODE_VERSION}-${NODE_ARCH}.tar.xz"
10
+ DOWNLOAD_URL="https://nodejs.org/dist/${NODE_VERSION}/${NODE_PACKAGE}"
11
+ INSTALL_DIR="/usr/local/nodejs"
12
+
13
+ # 关键修复1:获取执行sudo前的原始用户(而非root)
14
+ ORIGINAL_USER=${SUDO_USER:-$USER}
15
+ ORIGINAL_USER_HOME="/home/${ORIGINAL_USER}"
16
+ DOWNLOAD_DIR="${ORIGINAL_USER_HOME}/下载"
17
+
18
+ # 检查是否为root权限(移动文件需要sudo)
19
+ if [ $EUID -ne 0 ]; then
20
+ echo "错误:请使用root权限运行此脚本(sudo ./node_install.sh)"
21
+ exit 1
22
+ fi
23
+
24
+ # 步骤1:进入原始用户的下载目录
25
+ echo "===== 进入原始用户(${ORIGINAL_USER})的下载目录:${DOWNLOAD_DIR} ====="
26
+ cd "${DOWNLOAD_DIR}" || {
27
+ echo "错误:${DOWNLOAD_DIR} 目录不存在,创建该目录..."
28
+ mkdir -p "${DOWNLOAD_DIR}"
29
+ chown "${ORIGINAL_USER}:${ORIGINAL_USER}" "${DOWNLOAD_DIR}"
30
+ cd "${DOWNLOAD_DIR}"
31
+ }
32
+
33
+ # 步骤2:下载Node.js安装包
34
+ echo -e "\n===== 开始下载Node.js ${NODE_VERSION} ====="
35
+ if [ -f "${NODE_PACKAGE}" ]; then
36
+ echo "检测到已存在同名安装包,跳过下载..."
37
+ else
38
+ wget "${DOWNLOAD_URL}" -O "${NODE_PACKAGE}" || {
39
+ echo "下载失败!请更换淘宝镜像源:"
40
+ echo "DOWNLOAD_URL=\"https://npm.taobao.org/mirrors/node/${NODE_VERSION}/${NODE_PACKAGE}\""
41
+ exit 1
42
+ }
43
+ chown "${ORIGINAL_USER}:${ORIGINAL_USER}" "${NODE_PACKAGE}"
44
+ fi
45
+
46
+ # 步骤3:解压安装包
47
+ echo -e "\n===== 解压安装包 ====="
48
+ tar -xvf "${NODE_PACKAGE}" || {
49
+ echo "解压失败!安装包可能损坏,请删除后重新下载"
50
+ exit 1
51
+ }
52
+ chown -R "${ORIGINAL_USER}:${ORIGINAL_USER}" "node-${NODE_VERSION}-${NODE_ARCH}"
53
+
54
+ # 步骤4:移动到系统目录
55
+ echo -e "\n===== 移动安装目录到 ${INSTALL_DIR} ====="
56
+ if [ -d "${INSTALL_DIR}" ]; then
57
+ echo "检测到已存在${INSTALL_DIR},先备份并删除..."
58
+ mv "${INSTALL_DIR}" "${INSTALL_DIR}_bak_$(date +%Y%m%d%H%M%S)"
59
+ fi
60
+ mv "node-${NODE_VERSION}-${NODE_ARCH}" "${INSTALL_DIR}" || {
61
+ echo "移动目录失败!请检查权限"
62
+ exit 1
63
+ }
64
+
65
+ # 步骤5:配置环境变量(关键修复2:确保全局生效)
66
+ echo -e "\n===== 配置系统环境变量 ====="
67
+ # 方案1:写入/etc/profile(系统级,所有用户生效)
68
+ if ! grep -q "NODE_HOME=${INSTALL_DIR}" /etc/profile; then
69
+ echo "" >> /etc/profile
70
+ echo "# Node.js environment variables" >> /etc/profile
71
+ echo "export NODE_HOME=${INSTALL_DIR}" >> /etc/profile
72
+ echo "export PATH=\$NODE_HOME/bin:\$PATH" >> /etc/profile
73
+ echo "系统级环境变量已添加到/etc/profile"
74
+ else
75
+ echo "系统级环境变量已存在,无需重复添加"
76
+ fi
77
+
78
+ # 方案2:写入原始用户的~/.bashrc(用户级,避免source失效)
79
+ USER_BASHRC="${ORIGINAL_USER_HOME}/.bashrc"
80
+ if ! grep -q "NODE_HOME=${INSTALL_DIR}" "${USER_BASHRC}"; then
81
+ echo "" >> "${USER_BASHRC}"
82
+ echo "# Node.js environment variables" >> "${USER_BASHRC}"
83
+ echo "export NODE_HOME=${INSTALL_DIR}" >> "${USER_BASHRC}"
84
+ echo "export PATH=\$NODE_HOME/bin:\$PATH" >> "${USER_BASHRC}"
85
+ chown "${ORIGINAL_USER}:${ORIGINAL_USER}" "${USER_BASHRC}"
86
+ echo "用户级环境变量已添加到${USER_BASHRC}"
87
+ else
88
+ echo "用户级环境变量已存在,无需重复添加"
89
+ fi
90
+
91
+ # 步骤6:验证安装(直接用绝对路径验证,避免环境变量未生效的误判)
92
+ echo -e "\n===== 验证安装结果 ====="
93
+ # 直接使用Node.js的绝对路径验证,不受当前shell环境影响
94
+ NODE_ABS_PATH="${INSTALL_DIR}/bin/node"
95
+ NPM_ABS_PATH="${INSTALL_DIR}/bin/npm"
96
+
97
+ if [ -f "${NODE_ABS_PATH}" ] && [ -f "${NPM_ABS_PATH}" ]; then
98
+ echo "Node.js 绝对路径验证:$(${NODE_ABS_PATH} -v)"
99
+ echo "npm 绝对路径验证:$(${NPM_ABS_PATH} -v)"
100
+ echo -e "\n===== 安装成功!====="
101
+ echo "注意:环境变量需以下方式生效:"
102
+ echo "1. 普通用户执行:source ~/.bashrc (立即生效)"
103
+ echo "2. 或重启终端/重新登录(永久生效)"
104
+ echo "3. 验证命令:node -v && npm -v"
105
+ else
106
+ echo -e "\n===== 安装失败!====="
107
+ echo "未找到Node.js/npm的可执行文件,请检查安装目录:${INSTALL_DIR}/bin"
108
+ exit 1
109
+ fi
110
+
111
+ exit 0
@@ -0,0 +1,17 @@
1
+ # 敏捷图片(mjpic)安装使用说明
2
+
3
+ 1. 保存 node_install.sh 到 下载 目录。
4
+ 2. 打开终端(terminal)。
5
+ 3. 进入下载目录:
6
+ cd ~/下载
7
+ 4. 赋予脚本可执行权限:
8
+ chmod +x node_install.sh
9
+ 5. 以root权限运行脚本:
10
+ sudo ./node_install.sh
11
+ 6. 使环境变量生效
12
+ source ~/.bashrc
13
+ 7. 下载 敏捷图片(mjpic):
14
+ npm install mjpic@latest
15
+ 8. 运行 敏捷图片(mjpic):
16
+ npx mjpic build --port 3030
17
+ 9. 关闭终端,保存 mjpic-start.desktop 到 桌面,右键属性勾选可执行权限。双击新建图标运行。
package/dist/cli/cli.js CHANGED
@@ -5,12 +5,46 @@ import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { fileURLToPath } from 'url';
7
7
  import open from 'open';
8
+ import net from 'net';
8
9
  import app from './app.js';
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = path.dirname(__filename);
11
12
  const program = new Command();
13
+ // Check if a port is available
14
+ const isPortAvailable = (port) => {
15
+ return new Promise((resolve) => {
16
+ const server = net.createServer();
17
+ server.once('error', () => resolve(false));
18
+ server.once('listening', () => {
19
+ server.close();
20
+ resolve(true);
21
+ });
22
+ server.listen(port);
23
+ });
24
+ };
25
+ // Generate a random port between min and max, excluding common ports
26
+ const getRandomPort = async () => {
27
+ const commonPorts = [3000, 5000, 5173, 8000, 8080, 8888, 4200];
28
+ const min = 10000;
29
+ const max = 65535;
30
+ // Try up to 50 times to find a port
31
+ for (let i = 0; i < 50; i++) {
32
+ const port = Math.floor(Math.random() * (max - min + 1) + min);
33
+ if (!commonPorts.includes(port) && await isPortAvailable(port)) {
34
+ return port;
35
+ }
36
+ }
37
+ // Fallback to 0 (let OS choose) if we can't find one, though OS might pick a common one (unlikely)
38
+ return 0;
39
+ };
12
40
  const startServer = async (options, file) => {
13
- const port = parseInt(options.port, 10);
41
+ let port;
42
+ if (options.port) {
43
+ port = parseInt(options.port, 10);
44
+ }
45
+ else {
46
+ port = await getRandomPort();
47
+ }
14
48
  const host = options.host;
15
49
  if (file) {
16
50
  const absPath = path.resolve(file);
@@ -47,7 +81,7 @@ program
47
81
  .version('1.0.6');
48
82
  const attachServeOptions = (cmd) => {
49
83
  cmd
50
- .option('-p, --port <number>', 'server port', '3000')
84
+ .option('-p, --port <number>', 'server port')
51
85
  .option('--host <string>', 'server host', 'localhost')
52
86
  .argument('[file]', 'image file to open')
53
87
  .action(async (file, options) => {