This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
node_modules
|
||||
dist
|
||||
.env
|
||||
.env.local
|
||||
.git
|
||||
.gitignore
|
||||
.gitea
|
||||
*.md
|
||||
@@ -0,0 +1,104 @@
|
||||
name: my-v0
|
||||
run-name: '${{ gitea.actor }} is deploying my-v0'
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
env:
|
||||
IMAGE_NAME: my-v0
|
||||
BASE_IMAGE: my-v0-base
|
||||
HOST_PORT: 22787
|
||||
CONTAINER_PORT: 3000
|
||||
DOCKER_BUILDKIT: '0'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on:
|
||||
- self-hosted
|
||||
steps:
|
||||
- name: Prepare environment
|
||||
run: |
|
||||
STEP_START=$(date +%s)
|
||||
|
||||
if ! command -v docker > /dev/null 2>&1; then
|
||||
apk add docker-cli
|
||||
fi
|
||||
if ! command -v git > /dev/null 2>&1; then
|
||||
apk add git
|
||||
fi
|
||||
if ! command -v node > /dev/null 2>&1; then
|
||||
apk add nodejs
|
||||
fi
|
||||
|
||||
docker --version
|
||||
echo "BuildKit: ${DOCKER_BUILDKIT}"
|
||||
echo "Environment preparation took $(( $(date +%s) - STEP_START ))s"
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build base image when needed
|
||||
run: |
|
||||
STEP_START=$(date +%s)
|
||||
BASE_HASH=$(sha256sum Dockerfile.base | cut -c1-12)
|
||||
CURRENT_HASH=$(docker inspect $BASE_IMAGE:latest --format '{{index .Config.Labels "base.hash"}}' 2>/dev/null || echo "none")
|
||||
|
||||
if [ "$BASE_HASH" != "$CURRENT_HASH" ]; then
|
||||
docker build \
|
||||
--label "base.hash=$BASE_HASH" \
|
||||
-f Dockerfile.base \
|
||||
-t $BASE_IMAGE:latest .
|
||||
else
|
||||
echo "Base image is current (hash: $BASE_HASH)"
|
||||
fi
|
||||
|
||||
echo "Base image step took $(( $(date +%s) - STEP_START ))s"
|
||||
|
||||
- name: Build application image
|
||||
run: |
|
||||
STEP_START=$(date +%s)
|
||||
docker build -t $IMAGE_NAME:latest .
|
||||
docker images $IMAGE_NAME:latest --format "Image size: {{.Size}}"
|
||||
echo "Application image step took $(( $(date +%s) - STEP_START ))s"
|
||||
|
||||
- name: Deploy container
|
||||
run: |
|
||||
STEP_START=$(date +%s)
|
||||
|
||||
if docker ps -a --filter "name=^${IMAGE_NAME}$" -q | grep -q .; then
|
||||
docker stop --timeout 15 $IMAGE_NAME || true
|
||||
docker rm $IMAGE_NAME || true
|
||||
fi
|
||||
|
||||
docker run -d \
|
||||
--name $IMAGE_NAME \
|
||||
-p 127.0.0.1:$HOST_PORT:$CONTAINER_PORT \
|
||||
-e TZ=Asia/Shanghai \
|
||||
--restart unless-stopped \
|
||||
$IMAGE_NAME:latest
|
||||
|
||||
MAX_WAIT=60
|
||||
WAITED=0
|
||||
while [ $WAITED -lt $MAX_WAIT ]; do
|
||||
RUNNING_ID=$(docker ps --filter "name=^${IMAGE_NAME}$" --filter "status=running" -q)
|
||||
HEALTH=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' $IMAGE_NAME 2>/dev/null || echo "unknown")
|
||||
if [ -n "$RUNNING_ID" ] && [ "$HEALTH" = "healthy" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
WAITED=$((WAITED + 2))
|
||||
done
|
||||
|
||||
if docker ps --filter "name=^${IMAGE_NAME}$" --filter "status=running" -q | grep -q .; then
|
||||
docker ps --filter "name=^${IMAGE_NAME}$" --format "Status: {{.Status}}"
|
||||
echo "Startup wait: ${WAITED}s"
|
||||
else
|
||||
docker inspect $IMAGE_NAME --format 'ExitCode={{.State.ExitCode}} Error={{.State.Error}} StartedAt={{.State.StartedAt}} FinishedAt={{.State.FinishedAt}}' 2>/dev/null || true
|
||||
docker logs --tail 30 $IMAGE_NAME || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Deployment step took $(( $(date +%s) - STEP_START ))s"
|
||||
|
||||
- name: Show startup logs
|
||||
run: docker logs --tail 15 $IMAGE_NAME
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
FROM my-v0-base:latest AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
COPY . .
|
||||
RUN pnpm build
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget -q --spider http://127.0.0.1:3000/my-v0/ || exit 1
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -0,0 +1,3 @@
|
||||
FROM node:22-alpine
|
||||
|
||||
RUN npm install -g pnpm@10
|
||||
@@ -2,6 +2,14 @@
|
||||
|
||||
Vue 3 + Vite 大屏低代码编辑器前端
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **框架**:Vue 3、Vite、TypeScript、Pinia、Vue Router
|
||||
- **样式 / UI**:Tailwind CSS、Element Plus、Iconify
|
||||
- **画布**:vue3-moveable(拖拽缩放)、vue3-selecto(框选)、vue3-sketch-ruler(标尺)、vue-draggable-plus(图层拖拽排序)
|
||||
- **图表 / 编辑器**:ECharts、Monaco Editor
|
||||
- **数据**:Axios、Mock.js
|
||||
|
||||
## 开发
|
||||
|
||||
Node `^22.18.0 || >=24.12.0`,包管理器用 pnpm。
|
||||
|
||||
Vendored
-2
@@ -24,8 +24,6 @@ declare module 'vue' {
|
||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
MonacoEditor: typeof import('./src/components/MonacoEditor/index.vue')['default']
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
server {
|
||||
listen 3000;
|
||||
server_name _;
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location = /my-v0 {
|
||||
return 301 /my-v0/;
|
||||
}
|
||||
|
||||
location /my-v0/ {
|
||||
rewrite ^/my-v0/(.*)$ /$1 break;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
base: '/my-v0/',
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
@@ -25,4 +26,7 @@ export default defineConfig({
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
allowedHosts: ['www.qflink.xyz'],
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user