imom移动端打包部署
1. 安装nexus中央仓库
添加PVC:

创建deployment和svc:
kind: Deployment
apiVersion: apps/v1
metadata:
name: nexus3
namespace: common
labels:
app: nexus3
spec:
replicas: 1
selector:
matchLabels:
app: nexus3
template:
metadata:
creationTimestamp: null
labels:
app: nexus3
annotations:
kubesphere.io/creator: admin
kubesphere.io/restartedAt: '2024-09-03T03:02:34.074Z'
logging.kubesphere.io/logsidecar-config: '{}'
spec:
volumes:
- name: volume-c8wdzv
persistentVolumeClaim:
claimName: nexus3-pvc
containers:
- name: container-nexus3-rtsexq
image: '192.168.168.207:30002/public/sonatype/nexus3'
ports:
- name: tcp-8081
containerPort: 8081
protocol: TCP
resources:
requests:
memory: 2Gi
volumeMounts:
- name: volume-c8wdzv
mountPath: /nexus-data
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
serviceAccountName: default
serviceAccount: default
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
kind: Service
apiVersion: v1
metadata:
name: nexus3-svc
namespace: common
labels:
app: nexus3-svc
spec:
ports:
- name: http-nexus3
protocol: TCP
port: 8081
targetPort: 8081
nodePort: 31001
selector:
app: nexus3
type: NodePort
sessionAffinity: None
externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster
2. nexus配置
首次admin登录时,从容器的指定位置获取admin的登录密码。

然后在页面重置admin的密码。
按照下面的配置添加前端相关的npm仓库。
npm-hosted库:

npm-taobao, npm-tencent 库:


npm-dev 代理库:
这里注意要配置公司的nexus的外网库,可以拉取定制开发的软件包:

npm-group 库:
将npm-dev, npm-taobao, npm-tencent, npm-hosted 添加到当前组

配置完毕后,检查npm仓库列表:

3. 安装devops-biz
3.1 配置
添加 devops-conf 配置:
kind: ConfigMap
apiVersion: v1
metadata:
name: devops-conf
namespace: imom
annotations:
kubesphere.io/creator: daizhiqiang
data:
generate-apk.sh: >
#!/bin/bash
env=${1:-dev}
templateType=${2:-dme}
appCode=${3:-nationstar2024092711337449}
appid=${4:-__UNI__477F3DB}
appName=${5:-MBM}
packageName=${6:-com.nationstar.smt.dme.sie}
versionName=${7:-1.0.0}
versionCode=${8:-1}
site=${9:-http://localhost:8090}
storeFileUrl=${10:-http://localhost:8090/api/app/__UNI__477F3DB/package/keystore}
appKey=${11:-ed0fec369ec40d26871f2503441f2baf}
checkUpdateHost=${12:-http://localhost:8090}
#nexusUrl=${13:-http://192.168.181.114:8081}
nexusUrl=${13:-http://192.168.168.207:30998}
tenantId=${14:-hwstaff_p_apsimes}
updateMode=${15:-0}
rememberUsersLimit=${16:-1}
cliId=${17:-imom}
logPath="/var/log/apk/$appCode.log" # 日志路径
bakLogPath="/var/log/apk/$appCode.bak_$(date +"%Y%m%d_%H%M%S").log" #
备份日志文件路径
# 重新打包时,备份日志文件后覆盖
if [ -f "$logPath" ]; then
mv "$logPath" "$bakLogPath"
fi
uniTemplateDir="uni-$appCode" # 临时项目模板文件夹名称
apkTemplateDir="apk-$appCode" # 临时打包模板文件夹名称
# 设置陷阱,在脚本退出时执行 sync
trap 'sync' EXIT
# 全局异常处理函数
handler_error() {
rm -rf /Android/code/$uniTemplateDir/ /Android/code/$apkTemplateDir/
local exit_code=$?
local error_msg="发生异常,错误码:$exit_code"
echo "exec fail!" | tee -a "$logPath"
#exit $exit_code # 由于 set -e 开启了错误检查,所以不需要再干预退出脚本
}
# 全局异常捕获
trap handler_error ERR
# 将脚本的执行命令和输出都写入日志
exec > >(while IFS= read -r line; do echo "[$(date +"%Y-%m-%d %H:%M:%S")]
$line"; done | tee -a "$logPath") 2>&1
# 开启错误检查,命令执行返回非零的退出状态码时,直接退出脚本
set -e
# 打开命令追踪
set -x
# 安装并查看脚手架版本
if [[ $cliId == "dme" ]]; then
npm install -g sie-cli@1.13.0-alpha.2 --registry=$nexusUrl/repository/npm-group/ --no-cache
cliCmd="sie-cli"
else
npm install -g @imom/mobile-cli@0.1.2-alpha.14 --registry=$nexusUrl/repository/npm-group/
cliCmd="imom-cli"
fi
$cliCmd -V
# 使用脚手架生成移动端底座
echo "project generating..."
cd /Android/code
if [[ $checkUpdateHost == "" ]] || [[ $checkUpdateHost == " " ]]; then
checkUpdateHost="/devops"
fi
$cliCmd init -auto 是 -n $uniTemplateDir -$templateType -appCode $appCode
-site $site -checkUpdateHost $checkUpdateHost -tenantId $tenantId
-updateMode $updateMode -rememberUsersLimit $rememberUsersLimit
cd $uniTemplateDir
# 替换 APK 打包环境
sed -i "s/const env = process.env?.VUE_APP_ENV .*/const env =
process.env?.VUE_APP_ENV || \"$env\";/"
/Android/code/$uniTemplateDir/src/config/index.js
# 安装依赖
sed -i "s|http://192.168.181.114:8081|${nexusUrl}|g" yarn.lock
echo "installing..."
yarn install --registry=$nexusUrl/repository/npm-group/
cd src
yarn install --registry=$nexusUrl/repository/npm-group/
cd ..
ls
# 构建项目h5
mkdir -p /Android/code/h5-release/
echo "building..."
yarn run build:h5:$env
tar -cvzf ${appCode}-dist.tar.gz dist
cp -rf ${appCode}-dist.tar.gz /Android/code/h5-release/
# 构建项目app-plus
yarn run build:app-plus:$env
rm -rf $appid
mkdir $appid
cp -r dist/build/app-plus $appid/www
# 将生成的安卓格式的代码移入生成 APK 的模板中
echo "android source moving..."
rm -rf /Android/code/apk-template/simpleDemo/src/main/assets/apps/*
# 复制打包模板用于打包生成 APK
cp -r /Android/code/apk-template /Android/code/$apkTemplateDir
cp -r $appid /Android/code/$apkTemplateDir/simpleDemo/src/main/assets/apps/
# 替换版本号等基础信息
sed -i "s/<app appid=.*/<app appid=\"$appid\" appver=\"\"\/>/"
/Android/code/$apkTemplateDir/simpleDemo/src/main/assets/data/dcloud_control.xml
sed -i "s/<string name=.*/<string name=\"app_name\">$appName<\/string>/"
/Android/code/$apkTemplateDir/simpleDemo/src/main/res/values/strings.xml
sed -i
"s/outputFileName=.*/outputFileName=\"$appName-\${variant.name}-V\${variant.versionName}.apk\"/"
/Android/code/$apkTemplateDir/simpleDemo/build.gradle
sed -i "s/applicationId .*/applicationId \"$packageName\"/"
/Android/code/$apkTemplateDir/simpleDemo/build.gradle
sed -i "s/namespace .*/namespace \"$packageName\"/"
/Android/code/$apkTemplateDir/simpleDemo/build.gradle
sed -i "s/versionName \".*\"/versionName \"$versionName\"/"
/Android/code/$apkTemplateDir/simpleDemo/build.gradle
sed -i "s/versionCode .*/versionCode $versionCode/"
/Android/code/$apkTemplateDir/simpleDemo/build.gradle
sed -i "s/android:value=.*/android:value=\"$appKey\" \/>/"
/Android/code/$apkTemplateDir/simpleDemo/src/main/AndroidManifest.xml
sed -i
"s/android:authorities=.*/android:authorities=\"$packageName.dc.fileprovider\"/"
/Android/code/$apkTemplateDir/simpleDemo/src/main/AndroidManifest.xml
# 下载对应的签名证书,一个 appid 对应一个 keystore 文件
rm -f /Android/code/$apkTemplateDir/simpleDemo/sie-dme.keystore
wget -O /Android/code/$apkTemplateDir/simpleDemo/sie-dme.keystore
$storeFileUrl
# 生成 APK
echo "apk generating..."
cd /Android/code/$apkTemplateDir
./gradlew assembleRelease
# 复制 APK 留档
apkName=$(find
"/Android/code/$apkTemplateDir/simpleDemo/build/outputs/apk/release"
-maxdepth 1 -type f -name "*.apk" | sort | head -n 1 | xargs -I {} basename
{})
cp
/Android/code/$apkTemplateDir/simpleDemo/build/outputs/apk/release/$apkName
/Android/code/apk-release/
# 打包完成后删除模板
rm -rf /Android/code/$uniTemplateDir/ /Android/code/$apkTemplateDir/
echo "exec success! target path: /Android/code/apk-release/$apkName" | tee
-a "$logPath"
# 关闭命令追踪
#set +x
# 关闭错误检查
#set +e
biz-conf 添加devops-biz.yml 一项:
注意mysql与nexus的配置。
security:
oauth2:
client:
client-id: ENC(LcjZms1vqs1po+G3mQk17g==)
client-secret: ENC(LcjZms1vqs1po+G3mQk17g==)
scope: server
ignore-urls:
- /error
- /druid/**
- /actuator/**
- /v2/api-docs
spring:
http:
multipart:
encoding: UTF-8
autoconfigure:
exclude: org.springframework.cloud.gateway.config.GatewayAutoConfiguration,org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration
mybatis-flex:
datasource:
#imom-kernel主库
imom-kernel:
username: ${MYSQL_USER:root}
password: ${MYSQL_PWD:TODO_PASSWORD}
url: jdbc:mysql://10.0.0.27:3306/imom_devops?serverTimezone=UTC&characterEncoding=utf8
type: com.alibaba.druid.pool.DruidDataSource
druid:
max-wait: 10000
stat-view-servlet:
enabled: true
url-pattern: /druid/*
login-username: admin
login-password: Sie123456
filter:
stat:
enabled: true
log-slow-sql: true
wall:
config:
multi-statement-allow: true
logging:
level:
com.sie.mbm.mom.admin.upms.biz.mapper: debug
apilog:
interfaceFlag: false # 默认是true,是否打印接口日志,这个是总开关
mom:
tenant:
column: tenant_id
tables:
- sys_user
- sys_role
- sys_menu
- sys_dept
- sys_log
- sys_social_details
- sys_dict
- sys_dict_item
- sys_public_param
- sys_log
- sys_file
- sys_oauth_client_details
- sys_post
- sys_module
- mes_import_sol
- mes_import_sol_dtl
- mes_prod_feed_station_list
- mes_prod_feed_station_list_dtl
api:
api-source: class
publish-type: private
contextPath: /sie
app-module: sie.site.smt
permission-type: 3
enabled: false
delegator:
host: ${HUAWEI_API_URL:http://mbm-api-gateway.mbm:9090}
#----------------DME config begin------------------------
application:
appId: 0fa023ca177341a89eec915d43c86ad9
tenantId: -1
soa:
token:
url: https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens
hw:
auth:
loginAccount: sieadmin
loginPwd: Mbm@2023.
tenantId: hwstaff_p_apsimes
nexus:
url: http://nexus3-svc.common:8081
username: admin
password: TODO_PASSWORD
repository: npm-hosted
app:
list:
- appid: __UNI__6155926
appName: 标品SMT
packageName: com.smt.dme.sie
appKey: d46270d1021856fecc13ea5d810f0ffd
- appid: __UNI__477F3DB
appName: 国星SMT
packageName: com.nationstar.smt.dme.sie
appKey: ed0fec369ec40d26871f2503441f2baf
- appid: __UNI__E97732D
appName: 国星LED
packageName: com.nationstar.led.dme.sie
appKey: 311cf0b4a49524674b0c79353ae42723
- appid: __UNI__6155926
appName: 赛意IMOM标品
packageName: com.sie.imom.standard
appKey: d46270d1021856fecc13ea5d810f0ffd
envs:
- id: lmdev
label: 联明电源开发环境
host: http://10.0.0.23:32555/imomapi
# 检查更新接口(非必要不填)
checkUpdateHost:
tenantId: 067cfa58c8404a908780bda7e934e1b1
- id: lmprod
label: 联明电源生产环境
host: http://10.0.0.10:32555/imomapi
# 检查更新接口(非必要不填)
checkUpdateHost:
tenantId: 067cfa58c8404a908780bda7e934e1b1
- id: gnddev
label: 广能达开发环境
host: http://10.0.0.23:31555/imomapi
# 检查更新接口(非必要不填)
checkUpdateHost:
tenantId: 067cfa58c8404a908780bda7e934e1b1
- id: gndprod
label: 广能达生产环境
host: http://10.168.1.232:32555/imomapi
# 检查更新接口(非必要不填)
checkUpdateHost:
tenantId: 067cfa58c8404a908780bda7e934e1b1
#调用脚手架时的打包参数
package:
templateType: dme
shellCommend: /Android/code/generate-apk.sh
maxRunning: 2
appCode:
prefix: nationstar
3.2 存储PVC
添加devops-biz-log:

3.3 工作负载与服务
工作负载:
kind: Deployment
apiVersion: apps/v1
metadata:
name: devops-biz
namespace: imom
labels:
app: devops-biz
component: devops-biz
tier: backend
annotations:
deployment.kubernetes.io/revision: '1'
kubesphere.io/creator: daizhiqiang
spec:
replicas: 1
selector:
matchLabels:
app: devops-biz
component: devops-biz
tier: backend
template:
metadata:
creationTimestamp: null
labels:
app: devops-biz
component: devops-biz
tier: backend
annotations:
kubesphere.io/creator: daizhiqiang
spec:
volumes:
- name: volume-apk-log
persistentVolumeClaim:
claimName: devops-biz-log
- name: volume-biz-conf
configMap:
name: biz-conf
items:
- key: common.yml
path: common.yml
- key: devops-biz.yml
path: devops-biz.yml
defaultMode: 420
- name: volume-v4ewp7
persistentVolumeClaim:
claimName: devops-biz-log
- name: volume-generate-apk
configMap:
name: devops-conf
items:
- key: generate-apk.sh
path: generate-apk.sh
defaultMode: 365
containers:
- name: devops-biz
image: 'swr.cn-south-1.myhuaweicloud.com/imom-release/imom-devops:20260920.0-dev-release'
ports:
- name: http-0
containerPort: 80
protocol: TCP
env:
- name: GATEWAY_HOST
value: dev.api.dme.com
- name: GATEWAY_PORT
value: '80'
- name: NACOS_HOST
value: '192.168.168.207:30848'
- name: PROFILES_ACTIVE
value: dev
resources:
requests:
memory: 1536Mi
volumeMounts:
- name: volume-apk-log
mountPath: /var/log/apk/
- name: volume-biz-conf
readOnly: true
mountPath: /springboot_config
- name: volume-generate-apk
mountPath: /Android/code/generate-apk.sh
subPath: generate-apk.sh
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 80
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 1
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 80
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 3
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
imagePullSecrets:
- name: swr
schedulerName: default-scheduler
strategy:
type: Recreate
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
服务:
kind: Service
apiVersion: v1
metadata:
name: devops-biz
namespace: imom
labels:
app: devops-biz
component: devops-biz
spec:
ports:
- name: http-80
protocol: TCP
port: 80
targetPort: 80
selector:
app: devops-biz
component: devops-biz
tier: backend
type: NodePort
sessionAffinity: None
externalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
internalTrafficPolicy: Cluster
nginx-gateway转发配置:

location /devops/ {
# 包含跨域配置
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,renterid,siteid' always;
if ($request_method = 'OPTIONS') { return 204; }
proxy_pass http://devops-biz/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
移动端打包前端使用public-ui, 确保镜像比以下的镜像要新:
192.168.168.207:30002/imom/imom-public-ui-dev:20260915.1419
imom-public-ui 加入移动端外壳配置VITE_MOBILE_PATH:


栏目加入菜单配置.
业务包管理文根路径: imom-public/devops/#/appBusinessPackage

APP版本管理文根路径: imom-public/devops/#/appVersion

4. devops使用配置
4.1 导出npm包
从历史选择业务包

将勾选的包一个个下载:

4.2 导入npm包

4.3 生成APK

在"APP管理"中观察打包进度, 打包完成后,点击"下载":
