@kmlckj/licos-ai-cli 0.0.23 → 0.0.25

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.
@@ -37,7 +37,7 @@ while [ $# -gt 0 ]; do
37
37
  esac
38
38
  done
39
39
  is_port_free() {
40
- ! lsof -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1
40
+ ! nc -z -w 1 127.0.0.1 "$1" >/dev/null 2>&1
41
41
  }
42
42
  choose_next_free_port() {
43
43
  local start=$1
@@ -72,27 +72,18 @@ ensure_port() {
72
72
  return 0
73
73
  fi
74
74
  local choice
75
- if [ "$ASSUME_YES" = "1" ]; then choice="Y"; else read -r -p "是否关闭该端口的进程?[Y/n] " choice || choice="Y"; fi
75
+ if [ "${LICOS_DEV_KILL_PORTS:-0}" = "1" ]; then
76
+ if [ "$ASSUME_YES" = "1" ]; then choice="Y"; else read -r -p "是否关闭该端口的进程?[Y/n] " choice || choice="Y"; fi
77
+ else
78
+ choice="n"
79
+ fi
76
80
  if [ -z "$choice" ] || [ "$choice" = "y" ] || [ "$choice" = "Y" ]; then
77
- if command -v lsof &> /dev/null; then
78
- local pids
79
- pids=$(lsof -t -i tcp:"$port_val" -sTCP:LISTEN 2>/dev/null || true)
80
- if [ -n "$pids" ]; then
81
- echo "正在关闭进程:$pids"
82
- kill -9 $pids 2>/dev/null || echo "关闭进程失败:$pids"
83
- eval "$var_name=$port_val"
84
- else
85
- echo "未获取到占用该端口的进程"
86
- eval "$var_name=$port_val"
87
- fi
88
- else
89
- echo "缺少 lsof,无法自动关闭进程"
90
- eval "$var_name=$port_val"
91
- fi
81
+ fuser -k "${port_val}/tcp" 2>/dev/null || echo "关闭端口进程失败或端口未找到:$port_val"
82
+ eval "$var_name=$port_val"
92
83
  else
93
84
  local new_port
94
- new_port=$(choose_next_free_port "$port_val")
95
- info "使用新的端口:$new_port"
85
+ new_port=$(choose_next_free_port "$((port_val+1))")
86
+ echo "使用新的端口:$new_port"
96
87
  eval "$var_name=$new_port"
97
88
  fi
98
89
  fi
@@ -185,7 +176,7 @@ echo "正在检查依赖命令和目录是否存在..."
185
176
  # 检查核心命令
186
177
  check_command "npm"
187
178
  check_command "pnpm"
188
- check_command "lsof"
179
+ check_command "nc"
189
180
  check_command "bash"
190
181
 
191
182
  # 端口占用预检查与处理
@@ -24,20 +24,21 @@ pipe_to_log() {
24
24
  }
25
25
 
26
26
  kill_old_server() {
27
- if command -v lsof &> /dev/null; then
28
- local pids
29
- pids=$(lsof -t -i tcp:"$SERVER_PORT" -sTCP:LISTEN 2>/dev/null || true)
30
- if [ -n "$pids" ]; then
31
- for protected in $PROTECTED_PORTS; do
32
- if [ "$protected" = "$SERVER_PORT" ]; then
33
- echo "端口 $SERVER_PORT 是平台保护端口,不会关闭占用进程"
34
- return 0
35
- fi
36
- done
37
- echo "正在关闭旧的 server 进程:$pids"
38
- kill -9 $pids 2>/dev/null || echo "关闭进程失败:$pids"
39
- sleep 1
27
+ if ! nc -z -w 1 127.0.0.1 "$SERVER_PORT" >/dev/null 2>&1; then
28
+ return 0
29
+ fi
30
+ for protected in $PROTECTED_PORTS; do
31
+ if [ "$protected" = "$SERVER_PORT" ]; then
32
+ echo "端口 $SERVER_PORT 是平台保护端口,不会关闭占用进程"
33
+ return 0
40
34
  fi
35
+ done
36
+ if [ "${LICOS_DEV_KILL_PORTS:-0}" = "1" ]; then
37
+ echo "正在关闭旧的 server 端口:$SERVER_PORT"
38
+ fuser -k "${SERVER_PORT}/tcp" 2>/dev/null || echo "关闭端口进程失败或端口未找到:$SERVER_PORT"
39
+ sleep 1
40
+ else
41
+ echo "端口 $SERVER_PORT 已占用,未启用 LICOS_DEV_KILL_PORTS,跳过自动关闭"
41
42
  fi
42
43
  }
43
44
 
@@ -164,6 +164,9 @@ CRITICAL:
164
164
  - 默认先写 `className`,再考虑 `style`。
165
165
  - 颜色、间距、圆角、边框、阴影、排版、flex/grid、宽高等常规样式必须收敛在 Tailwind 类名中。
166
166
  - 禁止使用 `w-[340px]`、`text-[14px]`、`p-[16px]` 这类带 `px` 的 Tailwind 任意值。
167
+ - 禁止使用颜色不透明度简写,例如 `bg-primary/10`、`text-slate-500/70`、`border-white/20`;小程序端 opacity 容易丢失,必须拆成基础颜色类和 `bg-opacity-*` / `text-opacity-*` / `border-opacity-*`。
168
+ - 禁止使用小数值类名,例如 `space-y-1.5`、`w-0.5`、`h-2.5`;统一改成整数刻度,例如 `space-y-2`、`w-1`、`h-3`。
169
+ - 禁止使用 `peer-*`、`group-*`、`has-*`、复杂任意选择器和属性选择器类名;这些写法在小程序构建或上传时容易失败。
167
170
  - 禁止使用 `style={{ width: '200px' }}`、`fontSize: '14px'` 这类硬编码尺寸。
168
171
  - Taro 会通过 `pxtransform` 将尺寸转换为跨端单位(小程序 `rpx`、H5 `rem`),业务代码里直接写 `px` 容易导致不同端显示不一致。
169
172
  - `style` 只允许用于少量跨端兼容修正;`.css` 只用于 Tailwind 明显不适合的场景,且范围必须最小。
@@ -415,8 +418,8 @@ const { avatar_url } = res.data; // 报错或 undefined
415
418
  ### 跨端规则速查表
416
419
 
417
420
  - Taro 原生 Text 换行/白屏:小程序 block 正常,H5 inline 白屏 → 垂直 Text 添加 `block` 类 + 平台检 测直接判断
418
- - Taro 原生 Input 样式:H5 inline 导致样式失效 View 包裹,样式放外层
419
- - Taro 原生 Input/Button Flex:H5 不支持 flex View 包装,flex 放 View 上
421
+ - 输入框/多行输入:页面中使用 `@/components/ui/input` `@/components/ui/textarea`,不要直接从 `@tarojs/components` 导入原生 `Input` / `Textarea`
422
+ - 输入框和按钮组合:使用 `@/components/ui/input`、`@/components/ui/button` 和外层 `View` 布局;原生 Input/Button 只能出现在 `src/components/ui` 封装内部
420
423
  - Fixed + Flex:H5 Tailwind 失效 → 必须 `style={{ position: 'fixed', display: 'flex' }}`
421
424
  - 底部 TabBar 重叠 → 底部固定元素 `bottom: 50`+,列表加底部内边距
422
425
  - 原生组件:H5 不可用 → `Taro.getEnv() === WEAPP` + H5 降级
@@ -444,39 +447,36 @@ useEffect(() => { setIsWeapp(Taro.getEnv() === Taro.ENV_TYPE.WEAPP) }, [])
444
447
  <Text className="block text-sm text-gray-500">说明</Text>
445
448
  ```
446
449
 
447
- **Taro 原生 Input/Textarea 样式**:必须 View 包裹,样式放 View 上(H5 端 Input inline 元素)
450
+ **Input/Textarea 样式**:页面必须使用 UI 封装组件,原生 Input/Textarea 的兼容包装已经在 `src/components/ui` 内处理
448
451
 
449
452
  ```tsx
450
- // 正确:View 包裹
451
- <View className="bg-gray-50 rounded-xl px-4 py-3">
452
- <Input className="w-full bg-transparent" placeholder="请输入内容" />
453
- </View>
454
- // ❌ 错误:H5 端样式不生效
455
- <Input className="bg-gray-50 rounded-xl px-4 py-3 w-full" />
453
+ import { Input } from '@/components/ui/input'
454
+ import { Textarea } from '@/components/ui/textarea'
456
455
 
457
- // ✅ Textarea 同理
458
- <View className="bg-gray-50 rounded-2xl p-4 mb-4">
459
- <Textarea style={{ width: '100%', minHeight: '100px', backgroundColor: 'transparent' }} placeholder="请输入详细描述..." maxlength={500} />
460
- </View>
456
+ // ✅ 正确:使用 UI 封装
457
+ <Input className="bg-gray-50" placeholder="请输入内容" />
458
+ <Textarea className="bg-gray-50" placeholder="请输入详细描述..." maxlength={500} />
459
+
460
+ // ❌ 错误:页面直接使用原生 Input/Textarea 会被 pnpm validate 拦截
461
+ // import { Input, Textarea } from '@tarojs/components'
461
462
  ```
462
463
 
463
- **Taro 原生 Input + Button Flex 布局**:flex View,Input `width: 100%`
464
+ **Input + Button Flex 布局**:flex 放外层 `View`,控件使用 UI 封装组件
464
465
 
465
466
  ```tsx
466
- // 正确:View 包装 + inline style
467
- <View style={{ display: 'flex', flexDirection: 'row', gap: '8px', padding: '12px' }}>
468
- <View style={{ flex: 1, backgroundColor: '#f5f5f5', borderRadius: '20px', padding: '8px 12px' }}>
469
- <Input style={{ width: '100%', fontSize: '14px' }} placeholder="输入消息..." />
470
- </View>
471
- <View style={{ flexShrink: 0 }}>
472
- <Button size="mini" type="primary">发送</Button>
467
+ import { Button } from '@/components/ui/button'
468
+ import { Input } from '@/components/ui/input'
469
+
470
+ // 正确:外层布局 + UI 组件
471
+ <View className="flex flex-row gap-2 p-3">
472
+ <View className="flex-1">
473
+ <Input placeholder="输入消息..." />
473
474
  </View>
474
- </View>
475
- // ❌ 错误:H5 端 Input 不支持 flex
476
- <View style={{ display: 'flex', flexDirection: 'row', gap: '8px' }}>
477
- <Input style={{ flex: 1 }} placeholder="输入消息..." />
478
475
  <Button>发送</Button>
479
476
  </View>
477
+
478
+ // ❌ 错误:页面直接使用原生 Input/Button 会被 pnpm validate 拦截
479
+ // import { Button, Input } from '@tarojs/components'
480
480
  ```
481
481
 
482
482
  **Fixed + Flex 布局**:必须 inline style(Tailwind fixed+flex 在 H5 失效),`bottom: 50` 避开 TabBar
package/lib/cli.js CHANGED
@@ -2107,7 +2107,7 @@ const EventBuilder = {
2107
2107
  };
2108
2108
 
2109
2109
  var name = "@kmlckj/licos-ai-cli";
2110
- var version = "0.0.23";
2110
+ var version = "0.0.25";
2111
2111
  var description = "LICOS AI coding workspace CLI - project template engine and dev tools";
2112
2112
  var license = "MIT";
2113
2113
  var author = "kmlckj";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kmlckj/licos-ai-cli",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "description": "LICOS AI coding workspace CLI - project template engine and dev tools",
5
5
  "license": "MIT",
6
6
  "author": "kmlckj",