mirror of
https://gitee.com/niucloud-team/niucloud.git
synced 2026-06-20 14:32:09 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67e7669694 | ||
|
|
9f683839e6 | ||
|
|
44805a4a1f | ||
|
|
0864a7a502 | ||
|
|
396eb8406d | ||
|
|
20db81d87e | ||
|
|
4309d7c458 | ||
|
|
9ed68ca110 | ||
|
|
b4ebe684b2 |
@ -125,5 +125,5 @@ niucloud-admin-saas是一款快速开发通用管理后台框架,整体功能
|
|||||||
All rights reserved。
|
All rights reserved。
|
||||||
|
|
||||||
杭州数字云动科技有限公司
|
杭州数字云动科技有限公司
|
||||||
杭州牛之云科技有限公司
|
杭州牛之云科技有限公司
|
||||||
提供技术支持
|
提供技术支持
|
||||||
@ -8,4 +8,4 @@ VITE_IMG_DOMAIN=''
|
|||||||
VITE_REQUEST_HEADER_TOKEN_KEY='token'
|
VITE_REQUEST_HEADER_TOKEN_KEY='token'
|
||||||
|
|
||||||
# 请求时header中站点的参数名
|
# 请求时header中站点的参数名
|
||||||
VITE_REQUEST_HEADER_SITEID_KEY='site-id'
|
VITE_REQUEST_HEADER_SITEID_KEY='site-id'
|
||||||
@ -1,143 +0,0 @@
|
|||||||
# NiuCloud Admin 开发规范
|
|
||||||
|
|
||||||
## 技术栈区分
|
|
||||||
|
|
||||||
本项目采用前后端分离架构,包含两个主要前端部分:
|
|
||||||
|
|
||||||
1. **PC端后台管理系统**
|
|
||||||
- 框架: Vue 3 + TypeScript + Vite
|
|
||||||
- UI组件库: Element Plus
|
|
||||||
- 状态管理: Pinia
|
|
||||||
- 样式处理: SCSS + Tailwind CSS
|
|
||||||
|
|
||||||
2. **移动端应用**
|
|
||||||
- 框架: uni-app + Vue 3 + TypeScript
|
|
||||||
- UI组件库: uview-plus
|
|
||||||
- 状态管理: Pinia
|
|
||||||
- 样式处理: SCSS + Windi CSS
|
|
||||||
|
|
||||||
## 关键组件使用规范
|
|
||||||
|
|
||||||
### 消息提示组件
|
|
||||||
|
|
||||||
**重要注意事项:请根据开发平台选择正确的消息提示组件!**
|
|
||||||
|
|
||||||
#### PC端 (admin目录)
|
|
||||||
- **必须使用Element Plus的消息提示组件**,而不是uni-app的方法
|
|
||||||
- 主要组件包括:`ElMessage`、`ElMessageBox`、`ElNotification`等
|
|
||||||
- 导入方式:`import { ElMessage, ElMessageBox } from 'element-plus'`
|
|
||||||
- 使用示例:
|
|
||||||
```typescript
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
|
|
||||||
// 成功消息
|
|
||||||
ElMessage.success('操作成功')
|
|
||||||
|
|
||||||
// 错误消息
|
|
||||||
ElMessage.error('操作失败')
|
|
||||||
|
|
||||||
// 确认对话框
|
|
||||||
ElMessageBox.confirm('确定要执行此操作吗?', '提示', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning'
|
|
||||||
}).then(() => {
|
|
||||||
// 用户点击确认后的逻辑
|
|
||||||
}).catch(() => {
|
|
||||||
// 用户点击取消后的逻辑
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 移动端 (uni-app目录)
|
|
||||||
- **使用uni-app提供的API**进行消息提示
|
|
||||||
- 主要方法包括:`uni.showToast`、`uni.showModal`、`uni.showLoading`等
|
|
||||||
- 使用示例:
|
|
||||||
```typescript
|
|
||||||
// 成功提示
|
|
||||||
uni.showToast({
|
|
||||||
title: '操作成功',
|
|
||||||
icon: 'success',
|
|
||||||
duration: 2000
|
|
||||||
})
|
|
||||||
|
|
||||||
// 模态对话框
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定要执行此操作吗?',
|
|
||||||
success: (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
// 用户点击确认后的逻辑
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## API请求规范
|
|
||||||
|
|
||||||
### PC端API请求
|
|
||||||
- 使用`@/utils/request.ts`封装的请求工具
|
|
||||||
- 支持`showSuccessMessage`和`showErrorMessage`选项控制消息显示
|
|
||||||
- 示例:
|
|
||||||
```typescript
|
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// GET请求
|
|
||||||
export function getOrderList(params: Record<string, any>) {
|
|
||||||
return request.get('order/list', params)
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST请求(带成功消息)
|
|
||||||
export function createOrder(params: Record<string, any>) {
|
|
||||||
return request.post('order/create', params, { showSuccessMessage: true })
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 移动端API请求
|
|
||||||
- 使用uni-app的`uni.request`或封装的请求工具
|
|
||||||
- 示例:
|
|
||||||
```typescript
|
|
||||||
// 发送请求
|
|
||||||
uni.request({
|
|
||||||
url: 'https://example.com/api/order/list',
|
|
||||||
method: 'GET',
|
|
||||||
data: {
|
|
||||||
page: 1,
|
|
||||||
limit: 10
|
|
||||||
},
|
|
||||||
success: (res) => {
|
|
||||||
// 处理成功响应
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
// 处理请求失败
|
|
||||||
}
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## 代码风格规范
|
|
||||||
|
|
||||||
1. **文件命名**
|
|
||||||
- 组件文件:PascalCase,如 `OrderList.vue`
|
|
||||||
- 普通文件:kebab-case 或 camelCase,如 `api-service.ts` 或 `commonUtils.ts`
|
|
||||||
|
|
||||||
2. **TypeScript规范**
|
|
||||||
- 为函数参数、返回值和重要变量添加明确的类型注解
|
|
||||||
- 使用接口 (interface) 定义复杂数据结构
|
|
||||||
- 避免 `any` 类型的滥用
|
|
||||||
|
|
||||||
3. **Vue组件规范**
|
|
||||||
- 使用 Vue 3 Composition API 和 `<script setup lang="ts">` 语法
|
|
||||||
- 组件样式建议使用 scoped 属性或 CSS Modules
|
|
||||||
|
|
||||||
## 国际化规范
|
|
||||||
|
|
||||||
- PC端使用Vue I18n进行国际化,语言文件位于`src/lang`目录
|
|
||||||
- 移动端同样使用Vue I18n,语言文件位于`src/app/locale`目录
|
|
||||||
- 使用`t('key')`函数获取翻译文本
|
|
||||||
|
|
||||||
## 其他重要规范
|
|
||||||
|
|
||||||
- 严格遵循RESTful API设计规范
|
|
||||||
- 统一处理API响应数据和错误情况
|
|
||||||
- 代码提交前确保通过TypeScript类型检查
|
|
||||||
- 组件开发遵循高内聚低耦合原则
|
|
||||||
- 优先复用现有组件和工具函数
|
|
||||||
1
admin/auto-imports.d.ts
vendored
1
admin/auto-imports.d.ts
vendored
@ -1,7 +1,6 @@
|
|||||||
// Generated by 'unplugin-auto-import'
|
// Generated by 'unplugin-auto-import'
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
const ElMessage: typeof import('element-plus/es')['ElMessage']
|
|
||||||
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
|
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
|
||||||
const ElNotification: typeof import('element-plus/es')['ElNotification']
|
const ElNotification: typeof import('element-plus/es')['ElNotification']
|
||||||
}
|
}
|
||||||
|
|||||||
17
admin/components.d.ts
vendored
17
admin/components.d.ts
vendored
@ -21,22 +21,16 @@ declare module '@vue/runtime-core' {
|
|||||||
ElCarousel: typeof import('element-plus/es')['ElCarousel']
|
ElCarousel: typeof import('element-plus/es')['ElCarousel']
|
||||||
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
|
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
|
||||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
|
||||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
|
||||||
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
|
||||||
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
|
||||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
|
||||||
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
ElDrawer: typeof import('element-plus/es')['ElDrawer']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
ElEmpty: typeof import('element-plus/es')['ElEmpty']
|
|
||||||
ElForm: typeof import('element-plus/es')['ElForm']
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
@ -44,27 +38,19 @@ declare module '@vue/runtime-core' {
|
|||||||
ElImage: typeof import('element-plus/es')['ElImage']
|
ElImage: typeof import('element-plus/es')['ElImage']
|
||||||
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
|
||||||
ElLink: typeof import('element-plus/es')['ElLink']
|
|
||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
ElOption: typeof import('element-plus/es')['ElOption']
|
ElOption: typeof import('element-plus/es')['ElOption']
|
||||||
ElOptionGroup: typeof import('element-plus/es')['ElOptionGroup']
|
|
||||||
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
|
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
|
||||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||||
ElProgress: typeof import('element-plus/es')['ElProgress']
|
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
|
||||||
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
|
||||||
ElResult: typeof import('element-plus/es')['ElResult']
|
ElResult: typeof import('element-plus/es')['ElResult']
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
|
||||||
ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
|
ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
|
||||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
|
||||||
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
ElStatistic: typeof import('element-plus/es')['ElStatistic']
|
||||||
ElStep: typeof import('element-plus/es')['ElStep']
|
ElStep: typeof import('element-plus/es')['ElStep']
|
||||||
ElSteps: typeof import('element-plus/es')['ElSteps']
|
ElSteps: typeof import('element-plus/es')['ElSteps']
|
||||||
@ -77,10 +63,7 @@ declare module '@vue/runtime-core' {
|
|||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTimeline: typeof import('element-plus/es')['ElTimeline']
|
ElTimeline: typeof import('element-plus/es')['ElTimeline']
|
||||||
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
|
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
|
||||||
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
ElTree: typeof import('element-plus/es')['ElTree']
|
|
||||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
|
||||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||||
ExportSure: typeof import('./src/components/export-sure/index.vue')['default']
|
ExportSure: typeof import('./src/components/export-sure/index.vue')['default']
|
||||||
HeatMap: typeof import('./src/components/heat-map/index.vue')['default']
|
HeatMap: typeof import('./src/components/heat-map/index.vue')['default']
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 && vite build && node publish.cjs",
|
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build && node publish.cjs",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export function installAddon(params: Record<string, any>) {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function cloudInstallAddon(params: Record<string, any>) {
|
export function cloudInstallAddon(params: Record<string, any>) {
|
||||||
return request.post(`addon/cloudinstall/${ params.addon }`, params)
|
return request.post(`addon/cloudinstall/${ params.addon }`, params, { showErrorMessage: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,36 +1,90 @@
|
|||||||
|
import axios from 'axios'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
import storage from '@/utils/storage'
|
||||||
|
|
||||||
/**
|
export const CLOUD_COMPILE_BASE_URL = 'http://go.site.niucloud.com'
|
||||||
* 云编译
|
|
||||||
*/
|
function createCloudCompileRequest() {
|
||||||
export function cloudBuild() {
|
const instance = axios.create({
|
||||||
return request.post('niucloud/build', {})
|
baseURL: CLOUD_COMPILE_BASE_URL,
|
||||||
|
timeout: 0,
|
||||||
|
headers: {
|
||||||
|
'lang': storage.get('lang') ?? 'zh-cn'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
const token = storage.get('token')
|
||||||
|
if (token) {
|
||||||
|
config.headers['token'] = token
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
return Promise.reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
return Promise.reject(err)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
const cloudCompileRequest = createCloudCompileRequest()
|
||||||
|
|
||||||
|
export function cloudBuild() {
|
||||||
|
return request.post('niucloud/build')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取云编译任务
|
|
||||||
*/
|
|
||||||
export function getCloudBuildTask() {
|
export function getCloudBuildTask() {
|
||||||
return request.get('niucloud/build')
|
return request.get('niucloud/build')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 云编译前检测
|
|
||||||
*/
|
|
||||||
export function getCloudBuildLog() {
|
export function getCloudBuildLog() {
|
||||||
return request.get('niucloud/build/log')
|
return request.get('niucloud/build/log')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除
|
|
||||||
*/
|
|
||||||
export function clearCloudBuildTask() {
|
export function clearCloudBuildTask() {
|
||||||
return request.post('niucloud/build/clear')
|
return request.post('niucloud/build/clear', {}, { showErrorMessage: false, showSuccessMessage: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 云编译前检测
|
|
||||||
*/
|
|
||||||
export function preBuildCheck() {
|
export function preBuildCheck() {
|
||||||
return request.get('niucloud/build/check')
|
return request.get('niucloud/build/check')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCloudBuildQueuePosition(taskId: string) {
|
||||||
|
return cloudCompileRequest.get('/cloud/queue_position', { params: { task_id: taskId } })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCloudBuildSseUrl(taskId: string): string {
|
||||||
|
return `${CLOUD_COMPILE_BASE_URL}/cloud/sse?task_id=${taskId}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCloudCompileLocalUrl() {
|
||||||
|
return request.get('niucloud/build/get_local_url')
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setCloudCompileLocalUrl(url: string) {
|
||||||
|
return request.post('niucloud/build/set_local_url', { url })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function startServerDownload(taskId: string, downloadUrl: string, authorizeCode: string, timestamp: string) {
|
||||||
|
return request.post('niucloud/build/start_server_download', {
|
||||||
|
task_id: taskId,
|
||||||
|
download_url: downloadUrl,
|
||||||
|
authorize_code: authorizeCode,
|
||||||
|
timestamp
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSseBuildLog(taskId: string) {
|
||||||
|
return request.get('niucloud/build/get_sse_build_log', { params: { task_id: taskId } })
|
||||||
|
}
|
||||||
|
|||||||
@ -77,6 +77,15 @@ export function getWeappUploadLog(key: string) {
|
|||||||
return request.get(`weapp/upload/${ key }`)
|
return request.get(`weapp/upload/${ key }`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接获取小程序上传日志(不更新状态)
|
||||||
|
* @param key
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function fetchWeappUploadLog(key: string) {
|
||||||
|
return request.get(`weapp/upload_log/${ key }`)
|
||||||
|
}
|
||||||
|
|
||||||
/***************************************************** 管理端 ****************************************************/
|
/***************************************************** 管理端 ****************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -70,7 +70,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end mt-[20px]" v-show="cloudBuildTask">
|
<div class="flex justify-end mt-[20px]" v-show="cloudBuildTask">
|
||||||
<el-button @click="dialogCancel()" class="!w-[90px]">取消</el-button>
|
<el-button @click="dialogCancel()" class="!w-[90px]">取消</el-button>
|
||||||
<el-button type="primary" :loading="timeloading" class="!w-[140px]">已用时 {{ formattedDuration }}</el-button>
|
<el-button type="primary" :loading="timeloading" class="!w-[140px]" v-if="!errorInfo">已用时 {{ formattedDuration }}</el-button>
|
||||||
|
<el-button type="primary" @click="active = 'error'" v-if="errorInfo">下一步</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="active == 'error'">
|
<div v-show="active == 'error'">
|
||||||
@ -81,10 +82,18 @@
|
|||||||
<img src="@/app/assets/images/error_icon.png" alt="">
|
<img src="@/app/assets/images/error_icon.png" alt="">
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<el-scrollbar class="max-h-[150px] !overflow-auto text-[15px] text-[#4F516D] mb-[15px] mt-[-15px]">
|
<el-scrollbar class="max-h-[150px] !overflow-auto text-[15px] text-[#4F516D] mb-[15px] mt-[-15px]" v-if="errorInfo">
|
||||||
{{errorInfo}}
|
{{errorInfo}}
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
<el-alert :closable="false" class="!mb-[15px] !w-full" v-if="errorAnalysis.analysis" type="warning">
|
||||||
|
<template #default>
|
||||||
|
<div class="text-left">
|
||||||
|
错误分析:{{ errorAnalysis.analysis }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-alert>
|
||||||
<el-button @click="handleReturn" class="!w-[90px]">错误信息</el-button>
|
<el-button @click="handleReturn" class="!w-[90px]">错误信息</el-button>
|
||||||
|
<el-button @click="againBuild" type="primary" plain class="!w-[90px]" v-if="errorAnalysis.error_addon">重新编译</el-button>
|
||||||
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
<el-button @click="showDialog=false" type="primary" class="!w-[90px]">完成</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-result>
|
</el-result>
|
||||||
@ -106,29 +115,358 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-show="active == 'again_build'">
|
||||||
|
<div class="h-[50vh] flex flex-col">
|
||||||
|
<div class="flex-1 h-0 flex items-center flex-col">
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
:data="installedAddonList"
|
||||||
|
row-key="key"
|
||||||
|
size="large"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55" />
|
||||||
|
<el-table-column label="应用信息" align="left" width="300">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex items-center cursor-pointer relative left-[-10px]">
|
||||||
|
<el-image class="w-[54px] h-[54px] rounded-[5px]" :src="row.icon" fit="contain">
|
||||||
|
<template #error>
|
||||||
|
<div class="flex items-center w-full h-full rounded-[5px]">
|
||||||
|
<img class="max-w-full max-h-full" src="@/app/assets/images/icon-addon-one.png" alt="" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
<div class="flex-1 w-0 flex flex-col justify-center pl-[20px] font-500 text-[13px]">
|
||||||
|
<div class="w-[236px] truncate leading-[18px]">{{ row.title }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="编译结果" align="left">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div class="flex items-center" v-if="errorAnalysis.error_addon && errorAnalysis.error_addon != row.key">
|
||||||
|
<el-icon class="text-success mr-1"><SuccessFilled /></el-icon> 编译成功
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex items-center">
|
||||||
|
<el-icon class="text-error mr-1"><WarningFilled /></el-icon> 编译失败,请排除该插件后重新进行编译
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end mt-[20px]">
|
||||||
|
<el-button @click="dialogCancel()" class="!w-[90px]">取消</el-button>
|
||||||
|
<el-button @click="active = 'error'" plain type="primary" class="!w-[90px]">上一步</el-button>
|
||||||
|
<el-button type="primary" @click="againBuild" :loading="loading" class="!w-[100px]">开始编译</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, h, watch, computed } from 'vue'
|
import { ref, watch, computed } from 'vue'
|
||||||
import { t } from '@/lang'
|
import { t } from '@/lang'
|
||||||
import { getCloudBuildLog, getCloudBuildTask, cloudBuild, clearCloudBuildTask, preBuildCheck } from '@/app/api/cloud'
|
import { getCloudBuildLog, getCloudBuildTask, cloudBuild, clearCloudBuildTask, preBuildCheck, getCloudBuildQueuePosition, getCloudBuildSseUrl, CLOUD_COMPILE_BASE_URL, startServerDownload, getSseBuildLog } from '@/app/api/cloud'
|
||||||
|
import { getInstalledAddonList } from '@/app/api/addon'
|
||||||
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
import { Terminal, TerminalFlash } from 'vue-web-terminal'
|
||||||
import 'vue-web-terminal/lib/theme/dark.css'
|
import 'vue-web-terminal/lib/theme/dark.css'
|
||||||
import { AnyObject } from '@/types/global'
|
import { AnyObject } from '@/types/global'
|
||||||
import { ElNotification, ElMessageBox } from 'element-plus'
|
import {ElNotification, ElMessageBox, ElMessage} from 'element-plus'
|
||||||
|
|
||||||
const showDialog = ref<boolean>(false)
|
const showDialog = ref<boolean>(false)
|
||||||
const terminalId = ref(Date.now());
|
const terminalId = ref(Date.now())
|
||||||
const cloudBuildTask = ref<null | AnyObject>(null)
|
const cloudBuildTask = ref<null | AnyObject>(null)
|
||||||
const active = ref('build')
|
const active = ref('build')
|
||||||
const cloudBuildCheck = ref<null | AnyObject>(null)
|
const cloudBuildCheck = ref<null | AnyObject>(null)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const terminalRef = ref(null)
|
const terminalRef = ref(null)
|
||||||
|
const selectAddon = ref([])
|
||||||
|
const installedAddonList = ref([])
|
||||||
|
const tableRef = ref(null)
|
||||||
|
|
||||||
|
getInstalledAddonList().then(({ data }) => {
|
||||||
|
installedAddonList.value = Object.values(data)
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleSelectionChange = (rows) => {
|
||||||
|
selectAddon.value = rows.map(row => {
|
||||||
|
return row.key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let cloudBuildLog = []
|
let cloudBuildLog = []
|
||||||
|
let eventSource: EventSource | null = null
|
||||||
|
|
||||||
|
interface SSEMessage {
|
||||||
|
type: string
|
||||||
|
task_id?: string
|
||||||
|
percent?: number
|
||||||
|
action?: string
|
||||||
|
msg?: string
|
||||||
|
code?: string
|
||||||
|
time?: string
|
||||||
|
download_url?: string
|
||||||
|
download_percent?: number
|
||||||
|
downloaded_bytes?: number
|
||||||
|
total_bytes?: number
|
||||||
|
authorize_code?: string
|
||||||
|
timestamp?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectSSE = (taskId: string) => {
|
||||||
|
if (eventSource) {
|
||||||
|
eventSource.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = getCloudBuildSseUrl(taskId)
|
||||||
|
eventSource = new EventSource(url)
|
||||||
|
|
||||||
|
eventSource.onopen = () => {
|
||||||
|
console.log('SSE connected')
|
||||||
|
}
|
||||||
|
|
||||||
|
eventSource.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse(event.data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE parse error:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventSource.addEventListener('progress', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE progress parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('complete', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE complete parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('failed', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE failed parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('heartbeat', () => {
|
||||||
|
console.log('SSE heartbeat')
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('download_start', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE download_start parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('download_progress', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE download_progress parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('download_complete', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('SSE download_complete parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.onerror = (error) => {
|
||||||
|
console.error('SSE error:', error)
|
||||||
|
setTimeout(() => {
|
||||||
|
if (showDialog.value && cloudBuildTask.value) {
|
||||||
|
getCloudBuildLogFn()
|
||||||
|
}
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSSEMessage = (data: SSEMessage) => {
|
||||||
|
if (!showDialog.value) return
|
||||||
|
|
||||||
|
if (data.type === 'progress' && data.action) {
|
||||||
|
if (!cloudBuildLog.includes(data.action)) {
|
||||||
|
if (cloudBuildLog.length === 0) {
|
||||||
|
const storedTime = localStorage.getItem('cloud_build_start_time')
|
||||||
|
if (storedTime) {
|
||||||
|
buildStartTime.value = Number(storedTime)
|
||||||
|
} else {
|
||||||
|
const now = Date.now()
|
||||||
|
buildStartTime.value = now
|
||||||
|
localStorage.setItem('cloud_build_start_time', String(now))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDuration.value = Math.floor((Date.now() - buildStartTime.value) / 1000)
|
||||||
|
buildTimer && clearInterval(buildTimer)
|
||||||
|
buildTimer = setInterval(() => {
|
||||||
|
if (buildStartTime.value) {
|
||||||
|
buildDuration.value = Math.floor((Date.now() - buildStartTime.value) / 1000)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('开始编译')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.action.indexOf('云编译任务正在排队') != -1) {
|
||||||
|
cloudQueue = data.action
|
||||||
|
cloudBuildLog.push(data.action)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
cloudQueue = null
|
||||||
|
}
|
||||||
|
|
||||||
|
terminalRef.value.pushMessage({ content: `${data.action}` })
|
||||||
|
cloudBuildLog.push(data.action)
|
||||||
|
|
||||||
|
if (data.code === '0' && data.msg) {
|
||||||
|
errorAnalysis.value = {}
|
||||||
|
errorInfo.value = data.msg
|
||||||
|
terminalRef.value.pushMessage({ content: data.msg, class: 'error' })
|
||||||
|
timeloading.value = false
|
||||||
|
active.value = 'error'
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
clearCloudBuildTask()
|
||||||
|
buildTimer && clearInterval(buildTimer)
|
||||||
|
buildTimer = null
|
||||||
|
localStorage.removeItem('cloud_build_start_time')
|
||||||
|
localStorage.removeItem('cloud_build_task')
|
||||||
|
closeSSE()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (data.type === 'complete') {
|
||||||
|
terminalRef.value.pushMessage({ content: '编译完成' })
|
||||||
|
} else if (data.type === 'failed') {
|
||||||
|
errorInfo.value = data.msg || '编译失败'
|
||||||
|
active.value = 'error'
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
clearCloudBuildTask()
|
||||||
|
buildTimer && clearInterval(buildTimer)
|
||||||
|
buildTimer = null
|
||||||
|
localStorage.removeItem('cloud_build_start_time')
|
||||||
|
localStorage.removeItem('cloud_build_task')
|
||||||
|
closeSSE()
|
||||||
|
} else if (data.type === 'download_start') {
|
||||||
|
if (data.action && !cloudBuildLog.includes(data.action)) {
|
||||||
|
terminalRef.value.pushMessage({ content: data.action })
|
||||||
|
cloudBuildLog.push(data.action)
|
||||||
|
}
|
||||||
|
} else if (data.type === 'download_progress') {
|
||||||
|
const percent = data.download_percent || 0
|
||||||
|
const downloaded = data.downloaded_bytes || 0
|
||||||
|
const total = data.total_bytes || 0
|
||||||
|
const downloadedMB = (downloaded / 1024 / 1024).toFixed(2)
|
||||||
|
const totalMB = (total / 1024 / 1024).toFixed(2)
|
||||||
|
terminalRef.value.pushMessage({ content: `下载进度: ${percent}% (${downloadedMB}MB / ${totalMB}MB)` })
|
||||||
|
} else if (data.type === 'download_complete') {
|
||||||
|
if (data.action && !cloudBuildLog.includes(data.action)) {
|
||||||
|
terminalRef.value.pushMessage({ content: data.action })
|
||||||
|
cloudBuildLog.push(data.action)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.download_url && data.task_id) {
|
||||||
|
startServerDownloadFn(data.task_id, data.download_url, data.authorize_code, data.timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let downloadPollingTimer: number | null = null
|
||||||
|
|
||||||
|
const startServerDownloadFn = async (taskId: string, downloadUrl: string, authorizeCode: string, timestamp: string) => {
|
||||||
|
try {
|
||||||
|
terminalRef.value.pushMessage({ content: '正在启动后台下载...' })
|
||||||
|
|
||||||
|
const parseUrl = new URL(downloadUrl, CLOUD_COMPILE_BASE_URL)
|
||||||
|
const authorize_code = parseUrl.searchParams.get('authorize_code') || authorizeCode || ''
|
||||||
|
const ts = parseUrl.searchParams.get('timestamp') || timestamp || ''
|
||||||
|
|
||||||
|
await startServerDownload(taskId, downloadUrl, authorize_code, ts)
|
||||||
|
|
||||||
|
downloadPollingTimer = setTimeout(async () => {
|
||||||
|
if (!downloadPollingTimer) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getSseBuildLog(taskId)
|
||||||
|
if (res.code === 1) {
|
||||||
|
const { status, percent, msg } = res.data
|
||||||
|
|
||||||
|
if (status === 'downloading') {
|
||||||
|
terminalRef.value.pushMessage({ content: `下载进度: ${percent}% - ${msg}` })
|
||||||
|
} else if (status === 'unzipping') {
|
||||||
|
terminalRef.value.pushMessage({ content: msg })
|
||||||
|
} else if (status === 'completed') {
|
||||||
|
terminalRef.value.pushMessage({ content: '部署完成!' })
|
||||||
|
downloadPollingTimer && clearInterval(downloadPollingTimer)
|
||||||
|
downloadPollingTimer = null
|
||||||
|
active.value = 'complete'
|
||||||
|
timeloading.value = false
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
clearCloudBuildTask()
|
||||||
|
buildTimer && clearInterval(buildTimer)
|
||||||
|
buildTimer = null
|
||||||
|
localStorage.removeItem('cloud_build_start_time')
|
||||||
|
localStorage.removeItem('cloud_build_task')
|
||||||
|
closeSSE()
|
||||||
|
ElMessage.success('编译部署完成')
|
||||||
|
} else if (status === 'error') {
|
||||||
|
terminalRef.value.pushMessage({ content: `错误: ${msg}`, class: 'error' })
|
||||||
|
downloadPollingTimer && clearInterval(downloadPollingTimer)
|
||||||
|
downloadPollingTimer = null
|
||||||
|
errorInfo.value = msg
|
||||||
|
active.value = 'error'
|
||||||
|
timeloading.value = false
|
||||||
|
clearCloudBuildTask()
|
||||||
|
closeSSE()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
terminalRef.value.pushMessage({ content: '获取下载进度失败', class: 'error' })
|
||||||
|
downloadPollingTimer && clearInterval(downloadPollingTimer)
|
||||||
|
downloadPollingTimer = null
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Polling error:', e)
|
||||||
|
}
|
||||||
|
}, 2000)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('启动后台下载失败:', error)
|
||||||
|
terminalRef.value.pushMessage({ content: '启动后台下载失败', class: 'error' })
|
||||||
|
errorInfo.value = '启动后台下载失败'
|
||||||
|
active.value = 'error'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeSSE = () => {
|
||||||
|
if (eventSource) {
|
||||||
|
eventSource.close()
|
||||||
|
eventSource = null
|
||||||
|
}
|
||||||
|
if (downloadPollingTimer) {
|
||||||
|
clearInterval(downloadPollingTimer)
|
||||||
|
downloadPollingTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 计时器相关
|
|
||||||
const buildStartTime = ref<number | null>(null)
|
const buildStartTime = ref<number | null>(null)
|
||||||
const buildDuration = ref<number>(0)
|
const buildDuration = ref<number>(0)
|
||||||
let buildTimer: number | null = null
|
let buildTimer: number | null = null
|
||||||
@ -157,6 +495,7 @@ const getCloudBuildTaskFn = () => {
|
|||||||
getCloudBuildTaskFn()
|
getCloudBuildTaskFn()
|
||||||
const errorInfo = ref('')
|
const errorInfo = ref('')
|
||||||
const timeloading = ref(false)
|
const timeloading = ref(false)
|
||||||
|
const errorAnalysis = ref({})
|
||||||
const getCloudBuildLogFn = () => {
|
const getCloudBuildLogFn = () => {
|
||||||
timeloading.value = true
|
timeloading.value = true
|
||||||
getCloudBuildLog().then(res => {
|
getCloudBuildLog().then(res => {
|
||||||
@ -202,10 +541,18 @@ const getCloudBuildLogFn = () => {
|
|||||||
|
|
||||||
data[0].forEach(item => {
|
data[0].forEach(item => {
|
||||||
if (!cloudBuildLog.includes(item.action)) {
|
if (!cloudBuildLog.includes(item.action)) {
|
||||||
|
if (item.action.indexOf('云编译任务正在排队') != -1) {
|
||||||
|
cloudQueue = item.action
|
||||||
|
cloudBuildLog.push(item.action)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
cloudQueue = null
|
||||||
|
}
|
||||||
terminalRef.value.pushMessage({ content: `${item.action}` })
|
terminalRef.value.pushMessage({ content: `${item.action}` })
|
||||||
cloudBuildLog.push(item.action)
|
cloudBuildLog.push(item.action)
|
||||||
|
|
||||||
if (item.code == 0) {
|
if (item.code === '0') {
|
||||||
|
errorAnalysis.value = res.data.error_analysis || {}
|
||||||
error = item.msg
|
error = item.msg
|
||||||
terminalRef.value.pushMessage({ content: item.msg, class: 'error' })
|
terminalRef.value.pushMessage({ content: item.msg, class: 'error' })
|
||||||
timeloading.value = false
|
timeloading.value = false
|
||||||
@ -234,7 +581,7 @@ const getCloudBuildLogFn = () => {
|
|||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getCloudBuildLogFn()
|
getCloudBuildLogFn()
|
||||||
}, 2000)
|
}, 5000)
|
||||||
}).catch()
|
}).catch()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,10 +618,17 @@ const open = async () => {
|
|||||||
loading.value = true
|
loading.value = true
|
||||||
active.value = 'build'
|
active.value = 'build'
|
||||||
closeType.value = 'normal'
|
closeType.value = 'normal'
|
||||||
|
cloudBuildLog = []
|
||||||
|
|
||||||
if (cloudBuildTask.value) {
|
if (cloudBuildTask.value) {
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
loading.value = false
|
loading.value = false
|
||||||
getCloudBuildLogFn()
|
const taskId = (cloudBuildTask.value as any).task_id
|
||||||
|
if (taskId) {
|
||||||
|
connectSSE(taskId)
|
||||||
|
} else {
|
||||||
|
getCloudBuildLogFn()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +638,12 @@ const open = async () => {
|
|||||||
loading.value = false
|
loading.value = false
|
||||||
cloudBuildTask.value = data
|
cloudBuildTask.value = data
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
getCloudBuildLogFn()
|
const taskId = data.task_id
|
||||||
|
if (taskId) {
|
||||||
|
connectSSE(taskId)
|
||||||
|
} else {
|
||||||
|
getCloudBuildLogFn()
|
||||||
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -294,22 +653,80 @@ const open = async () => {
|
|||||||
cloudBuildCheck.value = data
|
cloudBuildCheck.value = data
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
}
|
}
|
||||||
|
}).catch((e) => {
|
||||||
|
loading.value = false
|
||||||
|
showDialog.value = false
|
||||||
|
if (e.code && e.code == 601) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'云编译服务未启动,必须在启动后进行云编译!',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
confirmButtonText: '重新检测',
|
||||||
|
cancelButtonText: '查看操作手册',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
open()
|
||||||
|
}).catch((action) => {
|
||||||
|
action == 'cancel' && window.open('https://doc.press.niucloud.com/php/saas-framework/use/other/third-party-cloud-compilation.html', '_blank')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ElMessage({ message: e.msg, type: 'error' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const againBuild = () => {
|
||||||
|
if (active.value != 'again_build') {
|
||||||
|
active.value = 'again_build'
|
||||||
|
selectAddon.value = installedAddonList.value.map((item) => {
|
||||||
|
tableRef.value.toggleRowSelection(item, true)
|
||||||
|
return item.key
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loading.value = true
|
||||||
|
cloudBuildLog = []
|
||||||
|
cloudBuild().then(({ data }) => {
|
||||||
|
active.value = 'build'
|
||||||
|
loading.value = false
|
||||||
|
cloudBuildTask.value = data
|
||||||
|
showDialog.value = true
|
||||||
|
localStorage.removeItem('cloud_build_start_time')
|
||||||
|
const taskId = data.task_id
|
||||||
|
if (taskId) {
|
||||||
|
connectSSE(taskId)
|
||||||
|
} else {
|
||||||
|
getCloudBuildLogFn()
|
||||||
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
|
loading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectable = (row: any) => {
|
||||||
|
return selectAddon.value.includes(row.key)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 升级进度动画
|
* 升级进度动画
|
||||||
*/
|
*/
|
||||||
let flashInterval: null | number = null
|
let flashInterval: null | number = null
|
||||||
const terminalFlash = new TerminalFlash()
|
let terminalFlash = null
|
||||||
|
let cloudQueue = null
|
||||||
const onExecCmd = (key, command, success, failed, name) => {
|
const onExecCmd = (key, command, success, failed, name) => {
|
||||||
if (command == '开始编译') {
|
if (command == '开始编译') {
|
||||||
|
terminalFlash = new TerminalFlash()
|
||||||
success(terminalFlash)
|
success(terminalFlash)
|
||||||
const frames = makeIterator(['/', '——', '\\', '|'])
|
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||||
flashInterval = setInterval(() => {
|
flashInterval = setInterval(() => {
|
||||||
terminalFlash.flush('> ' + frames.next().value)
|
if (cloudQueue) {
|
||||||
|
terminalFlash.flush(cloudQueue + '<br>> ' + frames.next().value)
|
||||||
|
} else {
|
||||||
|
terminalFlash.flush('> ' + frames.next().value)
|
||||||
|
}
|
||||||
}, 150)
|
}, 150)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -327,6 +744,7 @@ const makeIterator = (array: string[]) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dialogClose = (done: () => {}) => {
|
const dialogClose = (done: () => {}) => {
|
||||||
|
closeSSE()
|
||||||
if (active.value == 'build' && cloudBuildTask.value && closeType.value == 'normal') {
|
if (active.value == 'build' && cloudBuildTask.value && closeType.value == 'normal') {
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
t('cloudbuild.showDialogCloseTips'),
|
t('cloudbuild.showDialogCloseTips'),
|
||||||
@ -352,6 +770,7 @@ const dialogClose = (done: () => {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const dialogCancel = () => {
|
const dialogCancel = () => {
|
||||||
|
closeSSE()
|
||||||
if (active.value == 'build' && cloudBuildTask.value && closeType.value == 'normal') {
|
if (active.value == 'build' && cloudBuildTask.value && closeType.value == 'normal') {
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
t('cloudbuild.showDialogCloseTips'),
|
t('cloudbuild.showDialogCloseTips'),
|
||||||
@ -382,10 +801,12 @@ const cloudBuildCheckDirFn = () => {
|
|||||||
|
|
||||||
watch(() => showDialog.value, () => {
|
watch(() => showDialog.value, () => {
|
||||||
if (!showDialog.value) {
|
if (!showDialog.value) {
|
||||||
|
closeSSE()
|
||||||
cloudBuildTask.value = null
|
cloudBuildTask.value = null
|
||||||
active.value = 'build'
|
active.value = 'build'
|
||||||
cloudBuildLog = []
|
cloudBuildLog = []
|
||||||
flashInterval && clearInterval(flashInterval)
|
flashInterval && clearInterval(flashInterval)
|
||||||
|
terminalFlash && terminalFlash.finish()
|
||||||
buildTimer && clearInterval(buildTimer)
|
buildTimer && clearInterval(buildTimer)
|
||||||
buildStartTime.value = null
|
buildStartTime.value = null
|
||||||
buildDuration.value = 0
|
buildDuration.value = 0
|
||||||
|
|||||||
@ -356,8 +356,14 @@ const getUpgradeTaskFn = () => {
|
|||||||
|
|
||||||
data.log.forEach((item) => {
|
data.log.forEach((item) => {
|
||||||
if (!upgradeLog.includes(item)) {
|
if (!upgradeLog.includes(item)) {
|
||||||
terminalRef.value.pushMessage({ content: `${item}` })
|
if (item.indexOf('云编译任务正在排队') != -1) {
|
||||||
upgradeLog.push(item)
|
cloudQueue = item
|
||||||
|
upgradeLog.push(item)
|
||||||
|
} else {
|
||||||
|
cloudQueue = null
|
||||||
|
terminalRef.value.pushMessage({ content: `${item}` })
|
||||||
|
upgradeLog.push(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 安装失败
|
// 安装失败
|
||||||
@ -438,7 +444,7 @@ const executeUpgradeFn = () => {
|
|||||||
executeUpgrade().then(() => {
|
executeUpgrade().then(() => {
|
||||||
getUpgradeTaskFn()
|
getUpgradeTaskFn()
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
if (err.message.indexOf('队列') != -1) {
|
if (err.msg.indexOf('队列') != -1) {
|
||||||
retrySecond.value = 30
|
retrySecond.value = 30
|
||||||
retrySecondInterval = setInterval(() => {
|
retrySecondInterval = setInterval(() => {
|
||||||
retrySecond.value--
|
retrySecond.value--
|
||||||
@ -447,6 +453,26 @@ const executeUpgradeFn = () => {
|
|||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
cloudBuildErrorTipsShowDialog.value = true
|
cloudBuildErrorTipsShowDialog.value = true
|
||||||
|
} else if (err.code && err.code == 601) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'云编译服务未启动,必须在启动后进行云编译!',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
confirmButtonText: '重新检测',
|
||||||
|
cancelButtonText: '查看操作手册',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
open()
|
||||||
|
}).catch((action) => {
|
||||||
|
action == 'cancel' && window.open('https://doc.press.niucloud.com/php/saas-framework/use/other/third-party-cloud-compilation.html', '_blank')
|
||||||
|
})
|
||||||
|
} else if (err.response && err.response.status && err.response.status == 502) {
|
||||||
|
ElMessage({ dangerouslyUseHTMLString: true, duration: 5000, message: '程序执行超时请先调整超时限制, 具体操作方法<a style="text-decoration: underline;" href="https://doc.press.niucloud.com/php/v6-shop/use/chang-jian-wen-ti-chu-li/er-shi-ba-3001-an-88c5-sheng-ji-guo-cheng-zhong-ti-shi-201c-502-bad-gateway-201d-wen-ti-jie-jue.html#%E5%AE%89%E8%A3%85-%E5%8D%87%E7%BA%A7%E5%AE%8C%E6%88%90%E5%90%8E-%E4%BA%91%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B%E4%B8%AD%E6%8F%90%E7%A4%BA-502-bad-gateway-%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3" target="blank">点击查看相关手册</a>', type: 'error' })
|
||||||
|
setTimeout(() => {
|
||||||
|
executeUpgradeFn()
|
||||||
|
}, 5000)
|
||||||
} else {
|
} else {
|
||||||
ElMessage({ message: err.message, type: 'error' })
|
ElMessage({ message: err.message, type: 'error' })
|
||||||
}
|
}
|
||||||
@ -526,8 +552,26 @@ const upgradeAddonFn = () => {
|
|||||||
|
|
||||||
upgradeAddon(appKey, upgradeOption.value).then(() => {
|
upgradeAddon(appKey, upgradeOption.value).then(() => {
|
||||||
getUpgradeTaskFn()
|
getUpgradeTaskFn()
|
||||||
}).catch(() => {
|
}).catch((res) => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
if (res.code && res.code == 601) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'云编译服务未启动,必须在启动后进行云编译!',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
confirmButtonText: '重新检测',
|
||||||
|
cancelButtonText: '查看操作手册',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
upgradeAddonFn()
|
||||||
|
}).catch((action) => {
|
||||||
|
action == 'cancel' && window.open('https://doc.press.niucloud.com/php/saas-framework/use/other/third-party-cloud-compilation.html', '_blank')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ElMessage({ message: res.msg, type: 'error' })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const dialogUpgradePrompt = ref(false)
|
const dialogUpgradePrompt = ref(false)
|
||||||
@ -589,12 +633,18 @@ const open = (addonKey: string = '', callback = null, otherData: any = {}) => {
|
|||||||
*/
|
*/
|
||||||
let flashInterval: any = null
|
let flashInterval: any = null
|
||||||
const terminalFlash = new TerminalFlash()
|
const terminalFlash = new TerminalFlash()
|
||||||
|
let cloudQueue = null
|
||||||
|
|
||||||
const onExecCmd = (key, command, success, failed, name) => {
|
const onExecCmd = (key, command, success, failed, name) => {
|
||||||
if (command == '开始升级') {
|
if (command == '开始升级') {
|
||||||
success(terminalFlash)
|
success(terminalFlash)
|
||||||
const frames = makeIterator(['/', '——', '\\', '|'])
|
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||||
flashInterval = setInterval(() => {
|
flashInterval = setInterval(() => {
|
||||||
terminalFlash.flush('> ' + frames.next().value)
|
if (cloudQueue) {
|
||||||
|
terminalFlash.flush(cloudQueue + '<br>> ' + frames.next().value)
|
||||||
|
} else {
|
||||||
|
terminalFlash.flush('> ' + frames.next().value)
|
||||||
|
}
|
||||||
}, 150)
|
}, 150)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,6 +675,14 @@ const dialogClose = (done: () => {}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', function (event) {
|
||||||
|
if (showDialog.value && active.value == 'upgrade' && upgradeTask.value && ['upgradeComplete', 'restoreComplete'].includes(upgradeTask.value.step) === false && !isBack.value) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.returnValue = ''
|
||||||
|
return t('upgrade.showDialogCloseTips')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => showDialog.value,
|
() => showDialog.value,
|
||||||
() => {
|
() => {
|
||||||
|
|||||||
441
admin/src/app/components/weappupload/index.vue
Normal file
441
admin/src/app/components/weappupload/index.vue
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog v-model="showDialog" title="小程序上传" width="850px" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="dialogClose">
|
||||||
|
<div v-show="active == 'upload'" class="h-[50vh]" v-loading="loading">
|
||||||
|
<div class="h-[45vh]" v-show="cloudBuildTask">
|
||||||
|
<terminal ref="terminalRef" :name="`weappupload-${terminalId}`" context="" :init-log="null" :show-header="false" :show-log-time="true" @exec-cmd="onExecCmd"/>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end mt-[20px]" v-show="cloudBuildTask">
|
||||||
|
<el-button @click="dialogCancel()">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="timeloading" class="!w-[140px]" v-if="!errorInfo">已用时 {{ formattedDuration }}</el-button>
|
||||||
|
<el-button type="primary" @click="active = 'error'" v-if="errorInfo">下一步</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="active == 'complete'">
|
||||||
|
<div class="h-[50vh] flex flex-col">
|
||||||
|
<div class="flex-1 h-0 flex justify-center items-center flex-col">
|
||||||
|
<el-result icon="success" title="上传成功">
|
||||||
|
<template #sub-title>
|
||||||
|
<p class="text-[16px]">小程序上传成功,耗时 {{ formattedDuration }}</p>
|
||||||
|
</template>
|
||||||
|
<template #extra>
|
||||||
|
<el-button type="primary" @click="handleComplete">完成</el-button>
|
||||||
|
</template>
|
||||||
|
</el-result>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="active == 'error'">
|
||||||
|
<div class="h-[50vh] flex flex-col">
|
||||||
|
<div class="flex-1 h-0 flex justify-center items-center flex-col">
|
||||||
|
<el-result icon="error" title="上传失败">
|
||||||
|
<template #extra>
|
||||||
|
<p class="text-[14px] text-red-500 mb-[10px]" v-if="errorInfo">错误信息: {{ errorInfo }}</p>
|
||||||
|
<el-button type="primary" @click="handleErrorNextStep">下一步</el-button>
|
||||||
|
</template>
|
||||||
|
</el-result>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, nextTick, onUnmounted, computed } from 'vue'
|
||||||
|
import { t } from '@/lang'
|
||||||
|
import { getWeappUploadLog, fetchWeappUploadLog } from '@/app/api/weapp'
|
||||||
|
import { CLOUD_COMPILE_BASE_URL } from '@/app/api/cloud'
|
||||||
|
import { Terminal } from 'vue-web-terminal'
|
||||||
|
import 'vue-web-terminal/lib/theme/dark.css'
|
||||||
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const showDialog = ref(false)
|
||||||
|
const terminalId = ref(Date.now())
|
||||||
|
const cloudBuildTask = ref<any>(null)
|
||||||
|
const active = ref('upload')
|
||||||
|
const loading = ref(false)
|
||||||
|
const terminalRef = ref(null)
|
||||||
|
const errorInfo = ref('')
|
||||||
|
const timeloading = ref(false)
|
||||||
|
const errorAnalysis = ref({})
|
||||||
|
|
||||||
|
let uploadLog: any[] = []
|
||||||
|
let eventSource: EventSource | null = null
|
||||||
|
const uploadStartTime = ref<number | null>(null)
|
||||||
|
const uploadDuration = ref(0)
|
||||||
|
let durationTimer: number | null = null
|
||||||
|
|
||||||
|
interface TerminalMessage {
|
||||||
|
content: string
|
||||||
|
class?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let messageQueue: TerminalMessage[] = []
|
||||||
|
let messageQueueTimer: number | null = null
|
||||||
|
const MESSAGE_FLUSH_INTERVAL = 300
|
||||||
|
|
||||||
|
const flushMessageQueue = () => {
|
||||||
|
if (!terminalRef.value || messageQueue.length === 0) return
|
||||||
|
while (messageQueue.length > 0) {
|
||||||
|
const msg = messageQueue.shift()
|
||||||
|
if (msg) {
|
||||||
|
terminalRef.value.pushMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queueMessage = (content: string, className?: string) => {
|
||||||
|
messageQueue.push({ content, class: className })
|
||||||
|
if (messageQueueTimer === null) {
|
||||||
|
messageQueueTimer = window.setTimeout(() => {
|
||||||
|
flushMessageQueue()
|
||||||
|
messageQueueTimer = null
|
||||||
|
}, MESSAGE_FLUSH_INTERVAL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearMessageQueue = () => {
|
||||||
|
messageQueue = []
|
||||||
|
if (messageQueueTimer !== null) {
|
||||||
|
clearTimeout(messageQueueTimer)
|
||||||
|
messageQueueTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedDuration = computed(() => {
|
||||||
|
const seconds = uploadDuration.value
|
||||||
|
const mins = Math.floor(seconds / 60)
|
||||||
|
const secs = seconds % 60
|
||||||
|
return mins > 0 ? `${mins}分${secs}秒` : `${secs}秒`
|
||||||
|
})
|
||||||
|
|
||||||
|
const onExecCmd = (cmd: string) => {
|
||||||
|
}
|
||||||
|
|
||||||
|
const getWeappSseUrl = (taskId: string): string => {
|
||||||
|
return `${CLOUD_COMPILE_BASE_URL}/cloud/weapp_sse?task_id=${taskId}`
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SSEMessage {
|
||||||
|
type: string
|
||||||
|
task_id?: string
|
||||||
|
percent?: number
|
||||||
|
action?: string
|
||||||
|
msg?: string
|
||||||
|
code?: string
|
||||||
|
time?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectSSE = (taskId: string) => {
|
||||||
|
if (eventSource) {
|
||||||
|
eventSource.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = getWeappSseUrl(taskId)
|
||||||
|
eventSource = new EventSource(url)
|
||||||
|
|
||||||
|
eventSource.onopen = () => {
|
||||||
|
console.log('Weapp SSE connected')
|
||||||
|
}
|
||||||
|
|
||||||
|
eventSource.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse(event.data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Weapp SSE parse error:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eventSource.addEventListener('progress', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Weapp SSE progress parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('complete', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Weapp SSE complete parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.addEventListener('failed', (event) => {
|
||||||
|
try {
|
||||||
|
const data: SSEMessage = JSON.parse((event as MessageEvent).data)
|
||||||
|
handleSSEMessage(data)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Weapp SSE failed parse error:', e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
eventSource.onerror = (error) => {
|
||||||
|
console.error('Weapp SSE error:', error)
|
||||||
|
closeSSE()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeSSE = () => {
|
||||||
|
if (eventSource) {
|
||||||
|
eventSource.close()
|
||||||
|
eventSource = null
|
||||||
|
}
|
||||||
|
clearMessageQueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
const earlyLogCheck = (taskKey: string): Promise<boolean> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
fetchWeappUploadLog(taskKey).then(res => {
|
||||||
|
const data = (res.data && res.data.data) ? res.data.data : []
|
||||||
|
if (data[0] && data[0].length) {
|
||||||
|
const last = data[0][data[0].length - 1]
|
||||||
|
if (last.code == 1 && last.percent == 100) {
|
||||||
|
resolve(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (last.code == 0) {
|
||||||
|
resolve(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(false)
|
||||||
|
}).catch(() => {
|
||||||
|
resolve(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSSEMessage = (data: SSEMessage) => {
|
||||||
|
if (!showDialog.value) return
|
||||||
|
|
||||||
|
if (data.type === 'progress' && data.action) {
|
||||||
|
if (!uploadLog.includes(data.action)) {
|
||||||
|
if (uploadLog.length === 0) {
|
||||||
|
const now = Date.now()
|
||||||
|
uploadStartTime.value = now
|
||||||
|
uploadDuration.value = 0
|
||||||
|
durationTimer && clearInterval(durationTimer)
|
||||||
|
durationTimer = setInterval(() => {
|
||||||
|
if (uploadStartTime.value) {
|
||||||
|
uploadDuration.value = Math.floor((Date.now() - uploadStartTime.value) / 1000)
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('开始上传')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
queueMessage(`${data.action}`)
|
||||||
|
uploadLog.push(data.action)
|
||||||
|
|
||||||
|
if (data.code === '0') {
|
||||||
|
errorInfo.value = data.msg || '上传失败'
|
||||||
|
timeloading.value = false
|
||||||
|
active.value = 'error'
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
if (props.onError) {
|
||||||
|
props.onError()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.code === '1' && data.percent === 100) {
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
queueMessage('上传完成')
|
||||||
|
timeloading.value = false
|
||||||
|
active.value = 'complete'
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
ElMessage.success('上传成功')
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (data.type === 'complete') {
|
||||||
|
getWeappUploadLog(data.task_id)
|
||||||
|
queueMessage('上传完成')
|
||||||
|
timeloading.value = false
|
||||||
|
active.value = 'complete'
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
ElMessage.success('上传成功')
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess()
|
||||||
|
}
|
||||||
|
} else if (data.type === 'failed') {
|
||||||
|
errorInfo.value = data.msg || '上传失败'
|
||||||
|
timeloading.value = false
|
||||||
|
active.value = 'error'
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
if (props.onError) {
|
||||||
|
props.onError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadDurationTimerClear = () => {
|
||||||
|
if (durationTimer) {
|
||||||
|
clearInterval(durationTimer)
|
||||||
|
durationTimer = null
|
||||||
|
}
|
||||||
|
uploadStartTime.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogClose = (done: () => void) => {
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
if (active.value == 'upload' && cloudBuildTask.value) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'确定要关闭上传窗口吗?关闭后将停止当前上传任务',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确认',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
done()
|
||||||
|
}).catch(() => { })
|
||||||
|
} else {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogCancel = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleComplete = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleErrorNextStep = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
if (props.onError) {
|
||||||
|
props.onError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
onSuccess?: () => void
|
||||||
|
onError?: () => void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const open = async (taskKey: string, task?: any) => {
|
||||||
|
loading.value = true
|
||||||
|
active.value = 'upload'
|
||||||
|
uploadLog = []
|
||||||
|
clearMessageQueue()
|
||||||
|
errorInfo.value = ''
|
||||||
|
errorAnalysis.value = {}
|
||||||
|
timeloading.value = true
|
||||||
|
terminalId.value = Date.now()
|
||||||
|
|
||||||
|
const taskData = task || cloudBuildTask.value
|
||||||
|
|
||||||
|
if (taskData) {
|
||||||
|
cloudBuildTask.value = taskData
|
||||||
|
if (taskData.status == 0) {
|
||||||
|
loading.value = false
|
||||||
|
const isCompleted = await earlyLogCheck(taskData.task_key)
|
||||||
|
if (isCompleted) {
|
||||||
|
closeSSE()
|
||||||
|
getWeappUploadLog(taskData.task_key)
|
||||||
|
showDialog.value = true
|
||||||
|
active.value = 'complete'
|
||||||
|
loading.value = false
|
||||||
|
uploadDuration.value = taskData.update_time - taskData.create_time
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('上传完成')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showDialog.value = true
|
||||||
|
connectSSE(taskData.task_key)
|
||||||
|
} else if (taskData.status == 1) {
|
||||||
|
active.value = 'complete'
|
||||||
|
loading.value = false
|
||||||
|
uploadDuration.value = taskData.update_time - taskData.create_time
|
||||||
|
showDialog.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('上传完成')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (props.onSuccess) {
|
||||||
|
props.onSuccess()
|
||||||
|
}
|
||||||
|
} else if (taskData.status == -1 || taskData.status == -2) {
|
||||||
|
active.value = 'error'
|
||||||
|
loading.value = false
|
||||||
|
errorInfo.value = taskData.fail_reason || '上传失败'
|
||||||
|
showDialog.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
if (terminalRef.value) {
|
||||||
|
terminalRef.value.execute('clear')
|
||||||
|
terminalRef.value.execute('上传失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (props.onError) {
|
||||||
|
props.onError()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loading.value = false
|
||||||
|
showDialog.value = true
|
||||||
|
connectSSE(taskData.task_key)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setTask = (task: any) => {
|
||||||
|
cloudBuildTask.value = task
|
||||||
|
}
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
closeSSE()
|
||||||
|
uploadDurationTimerClear()
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
setTask,
|
||||||
|
cloudBuildTask,
|
||||||
|
loading,
|
||||||
|
showDialog
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@ -46,5 +46,28 @@
|
|||||||
"uploadWeapp": "上传小程序",
|
"uploadWeapp": "上传小程序",
|
||||||
"undoAudit" : "撤回审核",
|
"undoAudit" : "撤回审核",
|
||||||
"undoAuditTips" : "撤回代码审核,单个账号每天审核撤回次数最多不超过 5 次(每天的额度从0点开始生效),一个月不超过 10 次。是否要继续撤回?",
|
"undoAuditTips" : "撤回代码审核,单个账号每天审核撤回次数最多不超过 5 次(每天的额度从0点开始生效),一个月不超过 10 次。是否要继续撤回?",
|
||||||
"helpInfo": "查看帮助"
|
"helpInfo": "查看帮助",
|
||||||
|
"weappUpload": {
|
||||||
|
"title": "小程序上传",
|
||||||
|
"noTask": "暂无上传任务",
|
||||||
|
"uploadFailed": "上传失败",
|
||||||
|
"uploadSuccess": "上传成功",
|
||||||
|
"uploadSuccessDesc": "小程序上传成功,耗时",
|
||||||
|
"usedTime": "已用时",
|
||||||
|
"startUpload": "开始上传",
|
||||||
|
"uploadComplete": "上传完成",
|
||||||
|
"dialogCloseTips": "确定要关闭上传窗口吗?关闭后将停止当前上传任务",
|
||||||
|
"errorInfo": "错误信息",
|
||||||
|
"errorAnalysis": "错误分析",
|
||||||
|
"complete": "完成",
|
||||||
|
"return": "返回",
|
||||||
|
"nextStep": "下一步",
|
||||||
|
"waitingUpload": "等待上传任务...",
|
||||||
|
"minute": "分",
|
||||||
|
"second": "秒",
|
||||||
|
"dot": ".",
|
||||||
|
"defaultDesc": "默认为列表版本号递增,自定义则为手动输入版本号进行上传,首位必须大于1"
|
||||||
|
},
|
||||||
|
"minute": "分",
|
||||||
|
"second": "秒"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,11 +110,11 @@
|
|||||||
<el-form-item prop="code1">
|
<el-form-item prop="code1">
|
||||||
<el-input v-model.number="form.code1" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
<el-input v-model.number="form.code1" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<span class="mx-[10px]">.</span>
|
<span class="mx-[10px]">{{ t('weappUpload.dot') }}</span>
|
||||||
<el-form-item prop="code2">
|
<el-form-item prop="code2">
|
||||||
<el-input v-model.number="form.code2" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
<el-input v-model.number="form.code2" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<span class="mx-[10px]">.</span>
|
<span class="mx-[10px]">{{ t('weappUpload.dot') }}</span>
|
||||||
<el-form-item prop="code3">
|
<el-form-item prop="code3">
|
||||||
<el-input v-model.number="form.code3" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
<el-input v-model.number="form.code3" class="!w-[70px]" :placeholder="t('codePlaceholder')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -155,6 +155,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<component :is="WeappUpload" ref="weappUploadRef" @success="getWeappVersionListFn" @error="getWeappVersionListFn" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -168,12 +170,17 @@ import { ElMessageBox } from 'element-plus'
|
|||||||
import { AnyObject } from '@/types/global'
|
import { AnyObject } from '@/types/global'
|
||||||
import Storage from '@/utils/storage'
|
import Storage from '@/utils/storage'
|
||||||
import { siteWeappCommit, undoAudit } from "@/app/api/wxoplatform";
|
import { siteWeappCommit, undoAudit } from "@/app/api/wxoplatform";
|
||||||
|
import WeappUpload from '@/app/components/weappupload/index.vue'
|
||||||
|
// 使用导入的组件,避免未读取警告
|
||||||
|
const WeappUploadComponent = WeappUpload
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pageName = route.meta.title
|
const pageName = route.meta.title
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
|
const weappUploadRef = ref<any>(null)
|
||||||
|
|
||||||
const weappTableData:{
|
const weappTableData:{
|
||||||
page: number,
|
page: number,
|
||||||
limit: number,
|
limit: number,
|
||||||
@ -286,19 +293,24 @@ const formRules = reactive({
|
|||||||
/**
|
/**
|
||||||
* 获取版本列表
|
* 获取版本列表
|
||||||
*/
|
*/
|
||||||
const getWeappVersionListFn = (page: number = 1) => {
|
const getWeappVersionListFn = (page?: number) => {
|
||||||
weappTableData.loading = true
|
weappTableData.loading = true
|
||||||
weappTableData.page = page
|
if (page) weappTableData.page = page
|
||||||
|
|
||||||
getWeappVersionList({
|
return getWeappVersionList({
|
||||||
page: weappTableData.page,
|
page: weappTableData.page,
|
||||||
limit: weappTableData.limit
|
limit: weappTableData.limit
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
weappTableData.loading = false
|
weappTableData.loading = false
|
||||||
weappTableData.data = res.data.data
|
weappTableData.data = res.data.data
|
||||||
weappTableData.total = res.data.total
|
weappTableData.total = res.data.total
|
||||||
if (page == 1 && weappTableData.data.length && weappTableData.data[0].status == 0) getWeappUploadLogFn(weappTableData.data[0].task_key)
|
|
||||||
weappTableData.version_info = res.data.version_info
|
weappTableData.version_info = res.data.version_info
|
||||||
|
|
||||||
|
const uploadingTask = res.data.data.find((d: any) => d.status == 0)
|
||||||
|
if (uploadingTask && weappUploadRef.value) {
|
||||||
|
weappUploadRef.value.setTask(uploadingTask)
|
||||||
|
weappUploadRef.value.open(uploadingTask.task_key, uploadingTask)
|
||||||
|
}
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
weappTableData.loading = false
|
weappTableData.loading = false
|
||||||
})
|
})
|
||||||
@ -367,15 +379,35 @@ const insert = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploading.value) return
|
if (uploading.value) {
|
||||||
|
const ref = weappUploadRef.value
|
||||||
|
if (ref && ref.cloudBuildTask && ref.cloudBuildTask.task_key) {
|
||||||
|
ref.open(ref.cloudBuildTask.task_key, ref.cloudBuildTask)
|
||||||
|
} else if (ref) {
|
||||||
|
ref.showDialog = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
uploading.value = true
|
uploading.value = true
|
||||||
|
|
||||||
previewContent.value = ''
|
previewContent.value = ''
|
||||||
|
|
||||||
setWeappVersion(form.value).then(res => {
|
setWeappVersion(form.value).then(res => {
|
||||||
getWeappVersionListFn()
|
const versionId = res.data
|
||||||
getWeappPreviewImage()
|
|
||||||
uploading.value = false
|
getWeappVersionListFn().then(() => {
|
||||||
|
const item = weappTableData.data.find((d: any) => d.id === versionId)
|
||||||
|
if (item && item.task_key) {
|
||||||
|
const ref = weappUploadRef.value
|
||||||
|
if (ref) {
|
||||||
|
ref.open(item.task_key, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getWeappPreviewImage()
|
||||||
|
uploading.value = false
|
||||||
|
}).catch(() => {
|
||||||
|
uploading.value = false
|
||||||
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
uploading.value = false
|
uploading.value = false
|
||||||
})
|
})
|
||||||
@ -388,6 +420,7 @@ const localInsert = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const previewContent = ref('')
|
const previewContent = ref('')
|
||||||
|
|
||||||
const getWeappPreviewImage = () => {
|
const getWeappPreviewImage = () => {
|
||||||
if (!authCode.value) return
|
if (!authCode.value) return
|
||||||
getWeappPreview().then(res => {
|
getWeappPreview().then(res => {
|
||||||
@ -395,21 +428,55 @@ const getWeappPreviewImage = () => {
|
|||||||
}).catch()
|
}).catch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentUploadKey = ref<string | null>(null)
|
||||||
|
const uploadPollingCount = ref(0)
|
||||||
|
const maxPollingCount = 150
|
||||||
|
|
||||||
const getWeappUploadLogFn = (key: string) => {
|
const getWeappUploadLogFn = (key: string) => {
|
||||||
|
if (!key) return
|
||||||
|
|
||||||
|
if (currentUploadKey.value !== key) {
|
||||||
|
currentUploadKey.value = key
|
||||||
|
uploadPollingCount.value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadPollingCount.value++
|
||||||
|
|
||||||
|
if (uploadPollingCount.value > maxPollingCount) {
|
||||||
|
currentUploadKey.value = null
|
||||||
|
uploadPollingCount.value = 0
|
||||||
|
uploading.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
getWeappUploadLog(key).then(res => {
|
getWeappUploadLog(key).then(res => {
|
||||||
const data = res.data.data ?? []
|
if (currentUploadKey.value !== key) return
|
||||||
|
|
||||||
|
const data = (res.data && res.data.data) ? res.data.data : []
|
||||||
if (data[0] && data[0].length) {
|
if (data[0] && data[0].length) {
|
||||||
const last = data[0][data[0].length - 1]
|
const last = data[0][data[0].length - 1]
|
||||||
if (last.code == 0) {
|
if (last.code == 0) {
|
||||||
|
currentUploadKey.value = null
|
||||||
|
uploadPollingCount.value = 0
|
||||||
getWeappVersionListFn()
|
getWeappVersionListFn()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (last.code == 1 && last.percent == 100) {
|
if (last.code == 1 && last.percent == 100) {
|
||||||
|
currentUploadKey.value = null
|
||||||
|
uploadPollingCount.value = 0
|
||||||
getWeappVersionListFn()
|
getWeappVersionListFn()
|
||||||
getWeappPreviewImage()
|
getWeappPreviewImage()
|
||||||
!Storage.get('weappUploadTipsLock') && (uploadSuccessShowDialog.value = true)
|
!Storage.get('weappUploadTipsLock') && (uploadSuccessShowDialog.value = true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (currentUploadKey.value === key) {
|
||||||
|
setTimeout(() => {
|
||||||
|
getWeappUploadLogFn(key)
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
if (currentUploadKey.value === key) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getWeappUploadLogFn(key)
|
getWeappUploadLogFn(key)
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form :inline="true" :model="searchParam" ref="searchFormRef" class="search-form" v-if="!loading && !isShowDetail && (activeName == 'installed' || activeName == 'all' || activeName == 'uninstalled')">
|
<el-form :inline="true" :model="searchParam" ref="searchFormRef" class="search-form" v-if="!loading && !isShowDetail && (activeName == 'installed' || activeName == 'all' || activeName == 'uninstalled')">
|
||||||
<el-form-item prop="type">
|
<el-form-item prop="type">
|
||||||
<el-select v-model="searchParam.type" clearable :placeholder="t('应用类型')" class="input-width">
|
<el-select v-model="searchParam.type" clearable :placeholder="t('应用类型')" class="input-width">
|
||||||
@ -83,7 +83,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-button class="ml-[auto]" @click="updateInformationFn({ key: 'niucloud-admin' })">
|
<el-button class="ml-[auto]" @click="updateInformationFn({ key: 'niucloud-admin' })">
|
||||||
<el-icon class="mr-[5px]">
|
<el-icon class="mr-[5px]">
|
||||||
<DocumentCopy />
|
<DocumentCopy />
|
||||||
@ -139,7 +139,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex-1 w-0">
|
<div class="flex-1 w-0">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<p class="text-[16px] text-[#374151] truncate leading-[20px]" :title="row.title">{{ row.title }}</p>
|
<p class="text-[16px] text-[#374151] truncate leading-[20px]" :title="row.title">{{ row.title }}</p>
|
||||||
<span :class="{'app-ident': row.type == 'app', 'addon-ident': row.type == 'addon'}">{{row.type == 'app' ? '应用' : '插件'}}</span>
|
<span :class="{'app-ident': row.type == 'app', 'addon-ident': row.type == 'addon'}">{{row.type == 'app' ? '应用' : '插件'}}</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-[#4F516D] truncate mt-[2px] font-bold" :title="row.key">{{ row.key }}</p>
|
<p class="text-xs text-[#4F516D] truncate mt-[2px] font-bold" :title="row.key">{{ row.key }}</p>
|
||||||
@ -1245,12 +1245,18 @@ const installCheckResult = ref({})
|
|||||||
|
|
||||||
let flashInterval = null
|
let flashInterval = null
|
||||||
const terminalFlash = new TerminalFlash()
|
const terminalFlash = new TerminalFlash()
|
||||||
|
let cloudQueue = null
|
||||||
|
|
||||||
const onExecCmd = (key, command, success, failed, name) => {
|
const onExecCmd = (key, command, success, failed, name) => {
|
||||||
if (command == '开始安装插件') {
|
if (command == '开始安装插件') {
|
||||||
success(terminalFlash)
|
success(terminalFlash)
|
||||||
const frames = makeIterator(['/', '——', '\\', '|'])
|
const frames = makeIterator(['/', '——', '\\', '|'])
|
||||||
flashInterval = setInterval(() => {
|
flashInterval = setInterval(() => {
|
||||||
terminalFlash.flush('> ' + frames.next().value)
|
if (cloudQueue) {
|
||||||
|
terminalFlash.flush(cloudQueue + '<br>> ' + frames.next().value)
|
||||||
|
} else {
|
||||||
|
terminalFlash.flush('> ' + frames.next().value)
|
||||||
|
}
|
||||||
}, 150)
|
}, 150)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1342,7 +1348,7 @@ const getInstallTask = (first: boolean = true) => {
|
|||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getInstallTask(false)
|
getInstallTask(false)
|
||||||
}, 2000)
|
}, 5000)
|
||||||
} else {
|
} else {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
installStep.value = 2
|
installStep.value = 2
|
||||||
@ -1442,6 +1448,24 @@ const handleCloudInstall = () => {
|
|||||||
})
|
})
|
||||||
.catch((res) => {
|
.catch((res) => {
|
||||||
cloudInstalling.value = false
|
cloudInstalling.value = false
|
||||||
|
if (res.code && res.code == 601) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'云编译服务未启动,必须在启动后进行云编译!',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
distinguishCancelAndClose: true,
|
||||||
|
confirmButtonText: '重新检测',
|
||||||
|
cancelButtonText: '查看操作手册',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
handleCloudInstall()
|
||||||
|
}).catch((action) => {
|
||||||
|
action == 'cancel' && window.open('https://doc.press.niucloud.com/php/saas-framework/use/other/third-party-cloud-compilation.html', '_blank')
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ElMessage({ message: res.msg, type: 'error' })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1470,6 +1494,13 @@ const getCloudInstallLog = () => {
|
|||||||
if (data[0] && data[0].length && installShowDialog.value == true) {
|
if (data[0] && data[0].length && installShowDialog.value == true) {
|
||||||
data[0].forEach((item) => {
|
data[0].forEach((item) => {
|
||||||
if (!installLog.includes(item.action)) {
|
if (!installLog.includes(item.action)) {
|
||||||
|
if (item.action.indexOf('云编译任务正在排队') != -1) {
|
||||||
|
cloudQueue = item.action
|
||||||
|
installLog.push(item.action)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
cloudQueue = null
|
||||||
|
}
|
||||||
terminalRef.value.pushMessage({ content: `${item.action}` })
|
terminalRef.value.pushMessage({ content: `${item.action}` })
|
||||||
installLog.push(item.action)
|
installLog.push(item.action)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -101,46 +101,46 @@ getTransferSceneFn()
|
|||||||
|
|
||||||
// 更改场景值(最终修复版)
|
// 更改场景值(最终修复版)
|
||||||
const handleInput = (e: any, key: any, data: any) => {
|
const handleInput = (e: any, key: any, data: any) => {
|
||||||
const val = e.target.value?.trim() || ''
|
const val = e.target.value?.trim() || ''
|
||||||
const originalVal = originalValues.value[key] || ''
|
const originalVal = originalValues.value[key] || ''
|
||||||
|
|
||||||
// 有值 → 清空:必须提交接口置空
|
// 有值 → 清空:必须提交接口置空
|
||||||
if (val === '' && originalVal !== '') {
|
if (val === '' && originalVal !== '') {
|
||||||
data.error = false
|
data.error = false
|
||||||
setSceneId({
|
setSceneId({
|
||||||
scene: key,
|
scene: key,
|
||||||
scene_id: ''
|
scene_id: ''
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
data.disabled = true
|
data.disabled = true
|
||||||
getTransferSceneFn()
|
getTransferSceneFn()
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 本来就空:不提交
|
// 本来就空:不提交
|
||||||
if (val === '' && originalVal === '') {
|
if (val === '' && originalVal === '') {
|
||||||
data.error = false
|
data.error = false
|
||||||
data.disabled = true
|
data.disabled = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 有值但长度不够:提示,不提交
|
// 有值但长度不够:提示,不提交
|
||||||
if (val.length < 4) {
|
if (val.length < 4) {
|
||||||
data.error = true
|
data.error = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 合法 4-5 位:提交
|
// 合法 4-5 位:提交
|
||||||
if (val.length >= 4 && val.length <= 5) {
|
if (val.length >= 4 && val.length <= 5) {
|
||||||
data.error = false
|
data.error = false
|
||||||
setSceneId({
|
setSceneId({
|
||||||
scene: key,
|
scene: key,
|
||||||
scene_id: val
|
scene_id: val
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
data.disabled = true
|
data.disabled = true
|
||||||
getTransferSceneFn()
|
getTransferSceneFn()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputRefs = ref<any>({})
|
const inputRefs = ref<any>({})
|
||||||
|
|||||||
@ -87,7 +87,7 @@
|
|||||||
<el-table-column :label="t('siteInfo')" width="300" align="left">
|
<el-table-column :label="t('siteInfo')" width="300" align="left">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-if="row.logo" :src="img(row.logo)" alt="">
|
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-if="row.icon" :src="img(row.icon)" alt="">
|
||||||
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-else src="@/app/assets/images/site_default.png" alt="">
|
<img class="w-[54px] h-[54px] mr-[10px] rounded-[4px]" v-else src="@/app/assets/images/site_default.png" alt="">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span>{{ row.site_name || '' }}</span>
|
<span>{{ row.site_name || '' }}</span>
|
||||||
|
|||||||
@ -1 +1,3 @@
|
|||||||
/* addon-iconfont.css */
|
@import "addon/home_service/iconfont.css";
|
||||||
|
@import "addon/o2o/iconfont.css";
|
||||||
|
@import "addon/tourism/iconfont.css";
|
||||||
|
|||||||
38
admin/src/styles/icon/addon/home_service/iconfont.css
Normal file
38
admin/src/styles/icon/addon/home_service/iconfont.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "o2o"; /* Project id 4412516 */
|
||||||
|
src: url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff2?t=1705720131974') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff?t=1705720131974') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.ttf?t=1705720131974') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o {
|
||||||
|
font-family: "o2o" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-danhanghuadong:before {
|
||||||
|
content: "\e66f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-yuanjiao:before {
|
||||||
|
content: "\e6c0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-gl-square:before {
|
||||||
|
content: "\ea92";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo12:before {
|
||||||
|
content: "\e699";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo11:before {
|
||||||
|
content: "\e6d4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-jishi:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
51
admin/src/styles/icon/addon/home_service/iconfont.json
Normal file
51
admin/src/styles/icon/addon/home_service/iconfont.json
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"id": "4412516",
|
||||||
|
"name": "上门服务",
|
||||||
|
"font_family": "o2o",
|
||||||
|
"css_prefix_text": "o2o-icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "30621139",
|
||||||
|
"name": "单行滑动",
|
||||||
|
"font_class": "danhanghuadong",
|
||||||
|
"unicode": "e66f",
|
||||||
|
"unicode_decimal": 58991
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7149037",
|
||||||
|
"name": "圆角",
|
||||||
|
"font_class": "yuanjiao",
|
||||||
|
"unicode": "e6c0",
|
||||||
|
"unicode_decimal": 59072
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7594344",
|
||||||
|
"name": "20gl-square",
|
||||||
|
"font_class": "gl-square",
|
||||||
|
"unicode": "ea92",
|
||||||
|
"unicode_decimal": 60050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "10133070",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo12",
|
||||||
|
"unicode": "e699",
|
||||||
|
"unicode_decimal": 59033
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "14652583",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo11",
|
||||||
|
"unicode": "e6d4",
|
||||||
|
"unicode_decimal": 59092
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6818781",
|
||||||
|
"name": "技师",
|
||||||
|
"font_class": "jishi",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
38
admin/src/styles/icon/addon/o2o/iconfont.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "o2o"; /* Project id 4412516 */
|
||||||
|
src: url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff2?t=1705720131974') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.woff?t=1705720131974') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4412516_cacqsbew46.ttf?t=1705720131974') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o {
|
||||||
|
font-family: "o2o" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-danhanghuadong:before {
|
||||||
|
content: "\e66f";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-yuanjiao:before {
|
||||||
|
content: "\e6c0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-gl-square:before {
|
||||||
|
content: "\ea92";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo12:before {
|
||||||
|
content: "\e699";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-sousuo11:before {
|
||||||
|
content: "\e6d4";
|
||||||
|
}
|
||||||
|
|
||||||
|
.o2o-icon-jishi:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
51
admin/src/styles/icon/addon/o2o/iconfont.json
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"id": "4412516",
|
||||||
|
"name": "上门服务",
|
||||||
|
"font_family": "o2o",
|
||||||
|
"css_prefix_text": "o2o-icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "30621139",
|
||||||
|
"name": "单行滑动",
|
||||||
|
"font_class": "danhanghuadong",
|
||||||
|
"unicode": "e66f",
|
||||||
|
"unicode_decimal": 58991
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7149037",
|
||||||
|
"name": "圆角",
|
||||||
|
"font_class": "yuanjiao",
|
||||||
|
"unicode": "e6c0",
|
||||||
|
"unicode_decimal": 59072
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7594344",
|
||||||
|
"name": "20gl-square",
|
||||||
|
"font_class": "gl-square",
|
||||||
|
"unicode": "ea92",
|
||||||
|
"unicode_decimal": 60050
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "10133070",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo12",
|
||||||
|
"unicode": "e699",
|
||||||
|
"unicode_decimal": 59033
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "14652583",
|
||||||
|
"name": "搜索",
|
||||||
|
"font_class": "sousuo11",
|
||||||
|
"unicode": "e6d4",
|
||||||
|
"unicode_decimal": 59092
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "6818781",
|
||||||
|
"name": "技师",
|
||||||
|
"font_class": "jishi",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
58
admin/src/styles/icon/addon/tourism/iconfont.css
Normal file
58
admin/src/styles/icon/addon/tourism/iconfont.css
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "tourism"; /* Project id 4137250 */
|
||||||
|
src: url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff2?t=1687685028672') format('woff2'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.woff?t=1687685028672') format('woff'),
|
||||||
|
url('//at.alicdn.com/t/c/font_4137250_st1ha9l0k1e.ttf?t=1687685028672') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism {
|
||||||
|
font-family: "tourism" !important;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-feiji:before {
|
||||||
|
content: "\e600";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou:before {
|
||||||
|
content: "\e6a9";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyouchanpin:before {
|
||||||
|
content: "\e63b";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou1:before {
|
||||||
|
content: "\e623";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou2:before {
|
||||||
|
content: "\e601";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou3:before {
|
||||||
|
content: "\e60c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyoubaochedingdan:before {
|
||||||
|
content: "\e612";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou4:before {
|
||||||
|
content: "\e653";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou5:before {
|
||||||
|
content: "\e610";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyouguanguang:before {
|
||||||
|
content: "\e87e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.tourism-icon-lvyou6:before {
|
||||||
|
content: "\e642";
|
||||||
|
}
|
||||||
86
admin/src/styles/icon/addon/tourism/iconfont.json
Normal file
86
admin/src/styles/icon/addon/tourism/iconfont.json
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"id": "4137250",
|
||||||
|
"name": "旅游业",
|
||||||
|
"font_family": "tourism",
|
||||||
|
"css_prefix_text": "tourism-icon-",
|
||||||
|
"description": "",
|
||||||
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "1443",
|
||||||
|
"name": "飞机",
|
||||||
|
"font_class": "feiji",
|
||||||
|
"unicode": "e600",
|
||||||
|
"unicode_decimal": 58880
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "446824",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou",
|
||||||
|
"unicode": "e6a9",
|
||||||
|
"unicode_decimal": 59049
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1167173",
|
||||||
|
"name": "旅游产品",
|
||||||
|
"font_class": "lvyouchanpin",
|
||||||
|
"unicode": "e63b",
|
||||||
|
"unicode_decimal": 58939
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1354920",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou1",
|
||||||
|
"unicode": "e623",
|
||||||
|
"unicode_decimal": 58915
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1505555",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou2",
|
||||||
|
"unicode": "e601",
|
||||||
|
"unicode_decimal": 58881
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "2121726",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou3",
|
||||||
|
"unicode": "e60c",
|
||||||
|
"unicode_decimal": 58892
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "2357494",
|
||||||
|
"name": "旅游包车订单",
|
||||||
|
"font_class": "lvyoubaochedingdan",
|
||||||
|
"unicode": "e612",
|
||||||
|
"unicode_decimal": 58898
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "3944019",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou4",
|
||||||
|
"unicode": "e653",
|
||||||
|
"unicode_decimal": 58963
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "4838220",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou5",
|
||||||
|
"unicode": "e610",
|
||||||
|
"unicode_decimal": 58896
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "7444178",
|
||||||
|
"name": "旅游观光",
|
||||||
|
"font_class": "lvyouguanguang",
|
||||||
|
"unicode": "e87e",
|
||||||
|
"unicode_decimal": 59518
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9748082",
|
||||||
|
"name": "旅游",
|
||||||
|
"font_class": "lvyou6",
|
||||||
|
"unicode": "e642",
|
||||||
|
"unicode_decimal": 58946
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -21,6 +21,27 @@ interface requestResponse extends AxiosResponse {
|
|||||||
config: InternalRequestConfig
|
config: InternalRequestConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ErrorResponse {
|
||||||
|
msg: string = '';
|
||||||
|
code: number = 0;
|
||||||
|
response: any = null;
|
||||||
|
|
||||||
|
constructor(msg: string);
|
||||||
|
constructor(code: number, msg: string, response: any);
|
||||||
|
|
||||||
|
constructor(arg1?: string | number, arg2?: string, arg3?: any) {
|
||||||
|
if (typeof arg1 === 'number') {
|
||||||
|
this.code = arg1;
|
||||||
|
this.msg = arg2 || '';
|
||||||
|
this.response = arg3; // 修正点3:补上漏掉的赋值
|
||||||
|
} else {
|
||||||
|
this.msg = (arg1 as string) || '';
|
||||||
|
this.code = 0;
|
||||||
|
this.response = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
private instance: AxiosInstance;
|
private instance: AxiosInstance;
|
||||||
|
|
||||||
@ -45,7 +66,7 @@ class Request {
|
|||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
(err: any) => {
|
(err: any) => {
|
||||||
return Promise.reject(err)
|
return Promise.reject(new ErrorResponse(0, err.message, err.response))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,7 +78,7 @@ class Request {
|
|||||||
if (res.code != 1) {
|
if (res.code != 1) {
|
||||||
this.handleAuthError(res.code)
|
this.handleAuthError(res.code)
|
||||||
if (res.code != 401 && response.config.showErrorMessage !== false) this.showElMessage({ message: res.msg, type: 'error', dangerouslyUseHTMLString: true, duration: 5000 })
|
if (res.code != 401 && response.config.showErrorMessage !== false) this.showElMessage({ message: res.msg, type: 'error', dangerouslyUseHTMLString: true, duration: 5000 })
|
||||||
return Promise.reject(new Error(res.msg || 'Error'))
|
return Promise.reject(res)
|
||||||
} else {
|
} else {
|
||||||
if (response.config.showSuccessMessage) ElMessage({ message: res.msg, type: 'success' })
|
if (response.config.showSuccessMessage) ElMessage({ message: res.msg, type: 'success' })
|
||||||
return res
|
return res
|
||||||
@ -67,7 +88,7 @@ class Request {
|
|||||||
},
|
},
|
||||||
(err: any) => {
|
(err: any) => {
|
||||||
this.handleNetworkError(err)
|
this.handleNetworkError(err)
|
||||||
return Promise.reject(err)
|
return Promise.reject(new ErrorResponse(0, err.message, err.response))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -195,7 +216,7 @@ class Request {
|
|||||||
this.messageCache.set(cacheKey, { timestamp: now });
|
this.messageCache.set(cacheKey, { timestamp: now });
|
||||||
ElMessage(options)
|
ElMessage(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定期清理过期缓存,防止内存泄漏
|
// 定期清理过期缓存,防止内存泄漏
|
||||||
if (this.messageCache.size > this.MAX_CACHE_SIZE) {
|
if (this.messageCache.size > this.MAX_CACHE_SIZE) {
|
||||||
for (const [key, value] of this.messageCache.entries()) {
|
for (const [key, value] of this.messageCache.entries()) {
|
||||||
|
|||||||
@ -108,7 +108,7 @@ class ExceptionHandle extends Handle
|
|||||||
} else if ($e instanceof RouteNotFoundException) {
|
} else if ($e instanceof RouteNotFoundException) {
|
||||||
return fail('当前访问路由未定义或不匹配 路由地址:' . request()->baseUrl());
|
return fail('当前访问路由未定义或不匹配 路由地址:' . request()->baseUrl());
|
||||||
} else if($e instanceof \RuntimeException){
|
} else if($e instanceof \RuntimeException){
|
||||||
return fail($e->getMessage(), $massageData);
|
return fail($e->getMessage(), $massageData, $e->getCode() ?: 0);
|
||||||
} else {
|
} else {
|
||||||
return $this->handleException($e);
|
return $this->handleException($e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,10 @@ class Cloud extends BaseAdminController
|
|||||||
* @return \think\Response
|
* @return \think\Response
|
||||||
*/
|
*/
|
||||||
public function build() {
|
public function build() {
|
||||||
return success(data:(new CoreCloudBuildService())->cloudBuild());
|
$data = $this->request->params([
|
||||||
|
[ 'addon', [] ]
|
||||||
|
]);
|
||||||
|
return success(data:(new CoreCloudBuildService())->cloudBuild($data['addon']));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +82,7 @@ class Cloud extends BaseAdminController
|
|||||||
$data = $this->request->params([
|
$data = $this->request->params([
|
||||||
[ 'url', '' ],
|
[ 'url', '' ],
|
||||||
]);
|
]);
|
||||||
$is_connected = (new CloudService(true,$data['url']))->is_connected;
|
$is_connected = (new CloudService(true, $data['url']))->is_connected;
|
||||||
return success('SUCCESS',$is_connected);
|
return success('SUCCESS',$is_connected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +94,8 @@ class Cloud extends BaseAdminController
|
|||||||
public function setLocalCloudCompileConfig()
|
public function setLocalCloudCompileConfig()
|
||||||
{
|
{
|
||||||
$data = $this->request->params([
|
$data = $this->request->params([
|
||||||
|
[ 'is_open', 0],
|
||||||
[ 'url', '' ],
|
[ 'url', '' ],
|
||||||
[ 'is_open', 0 ],
|
|
||||||
]);
|
]);
|
||||||
return success('SUCCESS',(new NiucloudService())->setLocalCloudCompileConfig($data));
|
return success('SUCCESS',(new NiucloudService())->setLocalCloudCompileConfig($data));
|
||||||
}
|
}
|
||||||
@ -106,4 +109,36 @@ class Cloud extends BaseAdminController
|
|||||||
{
|
{
|
||||||
return success('SUCCESS',(new NiucloudService())->getLocalCloudCompileConfig());
|
return success('SUCCESS',(new NiucloudService())->getLocalCloudCompileConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动后台下载(SSE编译完成后调用)
|
||||||
|
* @description 启动后台下载
|
||||||
|
* @return \think\Response
|
||||||
|
*/
|
||||||
|
public function startServerDownload()
|
||||||
|
{
|
||||||
|
$data = $this->request->params([
|
||||||
|
[ 'task_id', '' ],
|
||||||
|
[ 'download_url', '' ],
|
||||||
|
[ 'authorize_code', '' ],
|
||||||
|
[ 'timestamp', '' ],
|
||||||
|
]);
|
||||||
|
return success('操作成功', (new CoreCloudBuildService())->startServerDownload(
|
||||||
|
$data['task_id'],
|
||||||
|
$data['download_url'],
|
||||||
|
$data['authorize_code'],
|
||||||
|
$data['timestamp']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后台下载进度
|
||||||
|
* @description 获取后台下载进度
|
||||||
|
* @return \think\Response
|
||||||
|
*/
|
||||||
|
public function getSseBuildLog()
|
||||||
|
{
|
||||||
|
$taskId = $this->request->param('task_id', '');
|
||||||
|
return success('操作成功', (new CoreCloudBuildService())->getSseBuildLog($taskId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,4 +89,13 @@ class Version extends BaseAdminController
|
|||||||
public function uploadLog(string $key) {
|
public function uploadLog(string $key) {
|
||||||
return success(data: (new WeappVersionService())->getUploadLog($key));
|
return success(data: (new WeappVersionService())->getUploadLog($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接获取小程序上传日志(不更新状态)
|
||||||
|
* @param string $key
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function getUploadLogOnly(string $key) {
|
||||||
|
return success(data: (new WeappVersionService())->getUploadLogOnly($key));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,10 @@ Route::group('niucloud', function() {
|
|||||||
Route::post('build/set_local_url', 'niucloud.Cloud/setLocalCloudCompileConfig');
|
Route::post('build/set_local_url', 'niucloud.Cloud/setLocalCloudCompileConfig');
|
||||||
//获取本地服务器地址
|
//获取本地服务器地址
|
||||||
Route::get('build/get_local_url', 'niucloud.Cloud/getLocalCloudCompileConfig');
|
Route::get('build/get_local_url', 'niucloud.Cloud/getLocalCloudCompileConfig');
|
||||||
|
//启动后台下载(SSE编译完成后)
|
||||||
|
Route::post('build/start_server_download', 'niucloud.Cloud/startServerDownload');
|
||||||
|
//获取后台下载进度
|
||||||
|
Route::get('build/get_sse_build_log', 'niucloud.Cloud/getSseBuildLog');
|
||||||
})->middleware([
|
})->middleware([
|
||||||
AdminCheckToken::class,
|
AdminCheckToken::class,
|
||||||
AdminCheckRole::class,
|
AdminCheckRole::class,
|
||||||
|
|||||||
@ -44,8 +44,10 @@ Route::group('weapp', function() {
|
|||||||
Route::get('version', 'weapp.Version/lists');
|
Route::get('version', 'weapp.Version/lists');
|
||||||
//获取预览码
|
//获取预览码
|
||||||
Route::get('preview', 'weapp.Version/preview');
|
Route::get('preview', 'weapp.Version/preview');
|
||||||
//获取小程序上传日志
|
//获取小程序上传日志(会更新状态)
|
||||||
Route::get('upload/:key', 'weapp.Version/uploadLog');
|
Route::get('upload/:key', 'weapp.Version/uploadLog');
|
||||||
|
//直接获取小程序上传日志(不更新状态)
|
||||||
|
Route::get('upload_log/:key', 'weapp.Version/getUploadLogOnly');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ class Pay extends BaseApiController
|
|||||||
*/
|
*/
|
||||||
public function notify($site_id, $channel, $type, $action)
|
public function notify($site_id, $channel, $type, $action)
|
||||||
{
|
{
|
||||||
|
$this->request->siteId($site_id);
|
||||||
return (new PayService())->notify($channel, $type, $action);
|
return (new PayService())->notify($channel, $type, $action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@ Route::group('pay',function () {
|
|||||||
Route::get('friendspay/info/:trade_type/:trade_id', 'pay.Pay/friendspayInfo');
|
Route::get('friendspay/info/:trade_type/:trade_id', 'pay.Pay/friendspayInfo');
|
||||||
|
|
||||||
})->middleware(ApiChannel::class)
|
})->middleware(ApiChannel::class)
|
||||||
|
->middleware(ApiCheckToken::class, false)//表示验证登录
|
||||||
->middleware(ApiLog::class);
|
->middleware(ApiLog::class);
|
||||||
|
|
||||||
Route::group('pay',function () {
|
Route::group('pay',function () {
|
||||||
@ -50,4 +51,4 @@ Route::group('transfer',function () {
|
|||||||
|
|
||||||
})->middleware(ApiChannel::class)
|
})->middleware(ApiChannel::class)
|
||||||
->middleware(ApiCheckToken::class, true)//表示验证登录
|
->middleware(ApiCheckToken::class, true)//表示验证登录
|
||||||
->middleware(ApiLog::class);
|
->middleware(ApiLog::class);
|
||||||
|
|||||||
@ -56,9 +56,6 @@ class Index extends BaseInstall
|
|||||||
//sodium
|
//sodium
|
||||||
$sodium = extension_loaded('sodium');
|
$sodium = extension_loaded('sodium');
|
||||||
$system_variables[] = [ "name" => "sodium", "need" => "开启", "status" => $sodium ];
|
$system_variables[] = [ "name" => "sodium", "need" => "开启", "status" => $sodium ];
|
||||||
//imagick
|
|
||||||
$imagick = extension_loaded('imagick');
|
|
||||||
$system_variables[] = [ "name" => "imagick", "need" => "开启", "status" => $imagick ];
|
|
||||||
|
|
||||||
$root_path = str_replace("\\", DIRECTORY_SEPARATOR, dirname(__FILE__, 4));
|
$root_path = str_replace("\\", DIRECTORY_SEPARATOR, dirname(__FILE__, 4));
|
||||||
$root_path = str_replace("../", DIRECTORY_SEPARATOR, $root_path);
|
$root_path = str_replace("../", DIRECTORY_SEPARATOR, $root_path);
|
||||||
@ -91,7 +88,7 @@ class Index extends BaseInstall
|
|||||||
$this->assign("name", $name);
|
$this->assign("name", $name);
|
||||||
$this->assign("verison", $verison);
|
$this->assign("verison", $verison);
|
||||||
$this->assign("dirs_list", $dirs_list);
|
$this->assign("dirs_list", $dirs_list);
|
||||||
if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir && $imagick) {
|
if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir) {
|
||||||
$continue = true;
|
$continue = true;
|
||||||
} else {
|
} else {
|
||||||
$continue = false;
|
$continue = false;
|
||||||
@ -419,7 +416,7 @@ class Index extends BaseInstall
|
|||||||
}
|
}
|
||||||
|
|
||||||
//如果数据库不存在,我们就进行创建。
|
//如果数据库不存在,我们就进行创建。
|
||||||
$dbsql = "CREATE DATABASE `$dbname`";
|
$dbsql = "CREATE DATABASE `$dbname` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci";
|
||||||
$db_create = mysqli_query($conn, $dbsql);
|
$db_create = mysqli_query($conn, $dbsql);
|
||||||
if (!$db_create) {
|
if (!$db_create) {
|
||||||
return fail('创建数据库失败,请确认是否有足够的权限!');
|
return fail('创建数据库失败,请确认是否有足够的权限!');
|
||||||
|
|||||||
@ -79,7 +79,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="onetd">数据库编码:</td>
|
<td class="onetd">数据库编码:</td>
|
||||||
<td>
|
<td>
|
||||||
<label class="install-code">UTF8</label>
|
<label class="install-code">utf8mb4</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -320,7 +320,7 @@ return [
|
|||||||
'NEED_TO_AUTHORIZE_FIRST' => '使用云服务需先进行授权',
|
'NEED_TO_AUTHORIZE_FIRST' => '使用云服务需先进行授权',
|
||||||
'WEAPP_UPLOADING' => '小程序有正在上传的版本,请等待上一版本上传完毕后再进行操作',
|
'WEAPP_UPLOADING' => '小程序有正在上传的版本,请等待上一版本上传完毕后再进行操作',
|
||||||
'CLOUD_BUILD_TASK_EXIST' => '已有正在执行中的编译任务',
|
'CLOUD_BUILD_TASK_EXIST' => '已有正在执行中的编译任务',
|
||||||
'CONNECT_FAIL' => '连接失败',
|
'CONNECT_FAIL' => '云编译服务连接失败',
|
||||||
|
|
||||||
//核销相关
|
//核销相关
|
||||||
'VERIFY_TYPE_ERROR' => '核销类型错误',
|
'VERIFY_TYPE_ERROR' => '核销类型错误',
|
||||||
|
|||||||
@ -110,13 +110,22 @@ class AuthService extends BaseAdminService
|
|||||||
if (strpos($rule, $item) !== false) return;
|
if (strpos($rule, $item) !== false) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$authinfo = (new CoreAuthService())->getAuthInfo()['data'] ?? [];;
|
$authinfo = [];
|
||||||
|
try {
|
||||||
|
$authinfo = (new CoreAuthService())->getAuthInfo()['data'] ?? [];;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
}
|
||||||
if (empty($authinfo)) return;
|
if (empty($authinfo)) return;
|
||||||
|
|
||||||
if (!$this->isCheckDomain()) return;
|
if (!$this->isCheckDomain()) return;
|
||||||
|
|
||||||
$site_address = $authinfo['site_address'] ?? '';
|
$site_address = $authinfo['site_address'] ?? '';
|
||||||
$domain = request()->domain();
|
$domain = request()->domain();
|
||||||
|
|
||||||
|
// 如果是站点域名不进行验证
|
||||||
|
$site_id = (new CoreSiteService())->getSiteIdByDomain($domain);
|
||||||
|
if (!empty($site_id)) return;
|
||||||
|
|
||||||
if (!empty($site_address) && strpos($domain, $site_address) !== false) return;
|
if (!empty($site_address) && strpos($domain, $site_address) !== false) return;
|
||||||
|
|
||||||
throw new CommonException("授权域名校验失败!请确保当前访问域名与授权码绑定的域名一致");
|
throw new CommonException("授权域名校验失败!请确保当前访问域名与授权码绑定的域名一致");
|
||||||
|
|||||||
@ -96,7 +96,6 @@ class NiucloudService extends BaseAdminService
|
|||||||
* @return \app\model\sys\SysConfig|bool|\think\Model
|
* @return \app\model\sys\SysConfig|bool|\think\Model
|
||||||
*/
|
*/
|
||||||
public function setLocalCloudCompileConfig($data){
|
public function setLocalCloudCompileConfig($data){
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'baseUri' => $data['url'],
|
'baseUri' => $data['url'],
|
||||||
'isOpen' => $data['is_open'],
|
'isOpen' => $data['is_open'],
|
||||||
|
|||||||
@ -35,6 +35,7 @@ use core\exception\CloudBuildException;
|
|||||||
use core\exception\CommonException;
|
use core\exception\CommonException;
|
||||||
use core\util\DbBackup;
|
use core\util\DbBackup;
|
||||||
use core\util\niucloud\BaseNiucloudClient;
|
use core\util\niucloud\BaseNiucloudClient;
|
||||||
|
use core\util\niucloud\CloudService;
|
||||||
use think\facade\Cache;
|
use think\facade\Cache;
|
||||||
use think\facade\Db;
|
use think\facade\Db;
|
||||||
use think\facade\Log;
|
use think\facade\Log;
|
||||||
@ -228,28 +229,31 @@ class UpgradeService extends BaseAdminService
|
|||||||
$response = ( new CoreAddonCloudService() )->upgradeAddon($upgrade);
|
$response = ( new CoreAddonCloudService() )->upgradeAddon($upgrade);
|
||||||
if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
|
if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
|
||||||
|
|
||||||
|
$key = uniqid();
|
||||||
|
$upgrade_dir = $this->upgrade_dir . $key . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
if (!is_dir($upgrade_dir)) {
|
||||||
|
dir_mkdir($upgrade_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否需要备份
|
||||||
|
$is_need_backup = $data['is_need_backup'] ?? true;
|
||||||
|
if (!$is_need_backup) {
|
||||||
|
unset($this->steps['backupCode']);
|
||||||
|
unset($this->steps['backupSql']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否需要云编译
|
||||||
|
$is_need_cloudbuild = $data['is_need_cloudbuild'] ?? true;
|
||||||
|
if (!$is_need_cloudbuild) {
|
||||||
|
unset($this->steps['cloudBuild']);
|
||||||
|
unset($this->steps['gteCloudBuildLog']);
|
||||||
|
} else {
|
||||||
|
// 校验云编译服务
|
||||||
|
(new CloudService())->checkLocal();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$key = uniqid();
|
|
||||||
$upgrade_dir = $this->upgrade_dir . $key . DIRECTORY_SEPARATOR;
|
|
||||||
|
|
||||||
if (!is_dir($upgrade_dir)) {
|
|
||||||
dir_mkdir($upgrade_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否需要备份
|
|
||||||
$is_need_backup = $data['is_need_backup'] ?? true;
|
|
||||||
if (!$is_need_backup) {
|
|
||||||
unset($this->steps['backupCode']);
|
|
||||||
unset($this->steps['backupSql']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否需要云编译
|
|
||||||
$is_need_cloudbuild = $data['is_need_cloudbuild'] ?? true;
|
|
||||||
if (!$is_need_cloudbuild) {
|
|
||||||
unset($this->steps['cloudBuild']);
|
|
||||||
unset($this->steps['gteCloudBuildLog']);
|
|
||||||
}
|
|
||||||
|
|
||||||
$upgrade_task = [
|
$upgrade_task = [
|
||||||
'key' => $key,
|
'key' => $key,
|
||||||
'upgrade' => $upgrade,
|
'upgrade' => $upgrade,
|
||||||
@ -731,7 +735,15 @@ class UpgradeService extends BaseAdminService
|
|||||||
*/
|
*/
|
||||||
public function cloudBuild()
|
public function cloudBuild()
|
||||||
{
|
{
|
||||||
( new CoreCloudBuildService() )->cloudBuild();
|
try {
|
||||||
|
( new CoreCloudBuildService() )->cloudBuild();
|
||||||
|
} catch (CommonException $e) {
|
||||||
|
if ($e->getCode() == 601) {
|
||||||
|
( new CoreCloudBuildService() )->cloudBuild(['checkLocal' => false]);
|
||||||
|
} else {
|
||||||
|
throw new CommonException($e->getMessage(), $e->getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -13,6 +13,7 @@ namespace app\service\admin\weapp;
|
|||||||
|
|
||||||
use app\dict\common\CommonDict;
|
use app\dict\common\CommonDict;
|
||||||
use app\model\sys\SysConfig;
|
use app\model\sys\SysConfig;
|
||||||
|
use app\service\core\sys\CoreConfigService;
|
||||||
use app\service\core\weapp\CoreWeappConfigService;
|
use app\service\core\weapp\CoreWeappConfigService;
|
||||||
use app\service\core\wxoplatform\CoreOplatformService;
|
use app\service\core\wxoplatform\CoreOplatformService;
|
||||||
use core\base\BaseAdminService;
|
use core\base\BaseAdminService;
|
||||||
@ -80,6 +81,12 @@ class WeappConfigService extends BaseAdminService
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getWeappStaticInfo(){
|
public function getWeappStaticInfo(){
|
||||||
|
$local_cloud_compile_config = (new CoreConfigService())->getConfig(0, 'LOCAL_CLOUD_COMPILE_CONFIG')['value'] ?? [];
|
||||||
|
$baseUri = $local_cloud_compile_config['baseUri'] ?? '';
|
||||||
|
if (empty($baseUri)) $baseUri = 'oss.niucloud.com';
|
||||||
|
$baseUri = str_replace('http://', '', $baseUri);
|
||||||
|
$baseUri = str_replace('https://', '', $baseUri);
|
||||||
|
|
||||||
$domain = request()->domain();
|
$domain = request()->domain();
|
||||||
$domain = str_replace('http://', 'https://', $domain);
|
$domain = str_replace('http://', 'https://', $domain);
|
||||||
return [
|
return [
|
||||||
@ -88,7 +95,7 @@ class WeappConfigService extends BaseAdminService
|
|||||||
'socket_url' => "wss://".request()->host(),
|
'socket_url' => "wss://".request()->host(),
|
||||||
'upload_url' => $domain,
|
'upload_url' => $domain,
|
||||||
'download_url' => $domain,
|
'download_url' => $domain,
|
||||||
'upload_ip' => gethostbyname('oss.niucloud.com')
|
'upload_ip' => gethostbyname($baseUri)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -141,17 +141,30 @@ class WeappVersionService extends BaseAdminService
|
|||||||
|
|
||||||
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) {
|
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) {
|
||||||
$last = end($build_log['data'][0]);
|
$last = end($build_log['data'][0]);
|
||||||
|
file_put_contents(runtime_path() . 'debug_log.txt', date('Y-m-d H:i:s') . " | key: $key | last_code: {$last['code']} | last_percent: {$last['percent']}\n", FILE_APPEND);
|
||||||
if ($last['code'] == 0) {
|
if ($last['code'] == 0) {
|
||||||
(new WeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_FAIL, 'fail_reason' => $last['msg'] ?? '', 'update_time' => time()], ['task_key' => $key]);
|
$res = (new WeappVersion())->where(['task_key' => $key])->update(['status' => CloudDict::APPLET_UPLOAD_FAIL, 'fail_reason' => $last['msg'] ?? '', 'update_time' => time()]);
|
||||||
|
file_put_contents(runtime_path() . 'debug_log.txt', date('Y-m-d H:i:s') . " | fail update result: $res\n", FILE_APPEND);
|
||||||
return $build_log;
|
return $build_log;
|
||||||
}
|
}
|
||||||
if ($last['percent'] == 100) {
|
if ($last['percent'] == 100) {
|
||||||
(new WeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_SUCCESS, 'update_time' => time()], ['task_key' => $key]);
|
$res = (new WeappVersion())->where(['task_key' => $key])->update(['status' => CloudDict::APPLET_UPLOAD_SUCCESS, 'update_time' => time()]);
|
||||||
|
file_put_contents(runtime_path() . 'debug_log.txt', date('Y-m-d H:i:s') . " | success update result: $res\n", FILE_APPEND);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $build_log;
|
return $build_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接获取小程序上传日志(不更新状态)
|
||||||
|
* @param string $key
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function getUploadLogOnly(string $key)
|
||||||
|
{
|
||||||
|
return (new CoreWeappCloudService())->getWeappCompileLog($key);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取小程序上传日志
|
* 获取小程序上传日志
|
||||||
* @param string $key
|
* @param string $key
|
||||||
|
|||||||
@ -23,6 +23,7 @@ use core\exception\AuthException;
|
|||||||
use think\db\exception\DataNotFoundException;
|
use think\db\exception\DataNotFoundException;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use think\db\exception\ModelNotFoundException;
|
use think\db\exception\ModelNotFoundException;
|
||||||
|
use think\facade\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录服务层
|
* 登录服务层
|
||||||
@ -78,8 +79,14 @@ class RegisterService extends BaseApiService
|
|||||||
}
|
}
|
||||||
$member_id = ( new MemberService() )->add($data);
|
$member_id = ( new MemberService() )->add($data);
|
||||||
$data[ 'member_id' ] = $member_id;
|
$data[ 'member_id' ] = $member_id;
|
||||||
event('MemberRegister', $data);
|
|
||||||
SetMemberNoJob::dispatch([ 'site_id' => $this->site_id, 'member_id' => $member_id ]);
|
SetMemberNoJob::dispatch([ 'site_id' => $this->site_id, 'member_id' => $member_id ]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
event('MemberRegister', $data);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::write('MemberRegister event error');
|
||||||
|
Log::write($e->getTrace());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$member_info = $member_service->findMemberInfo([ 'member_id' => $member_id, 'site_id' => $this->site_id ]);
|
$member_info = $member_service->findMemberInfo([ 'member_id' => $member_id, 'site_id' => $this->site_id ]);
|
||||||
if ($member_info->isEmpty()) throw new AuthException('MEMBER_NOT_EXIST');//账号不存在
|
if ($member_info->isEmpty()) throw new AuthException('MEMBER_NOT_EXIST');//账号不存在
|
||||||
|
|||||||
@ -17,6 +17,7 @@ use core\exception\CommonException;
|
|||||||
use core\util\niucloud\BaseNiucloudClient;
|
use core\util\niucloud\BaseNiucloudClient;
|
||||||
use core\util\niucloud\CloudService;
|
use core\util\niucloud\CloudService;
|
||||||
use think\facade\Cache;
|
use think\facade\Cache;
|
||||||
|
use think\facade\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
@ -86,7 +87,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
'authorize_code' => $this->auth_code,
|
'authorize_code' => $this->auth_code,
|
||||||
'timestamp' => $install_task['timestamp']
|
'timestamp' => $install_task['timestamp']
|
||||||
];
|
];
|
||||||
$response = (new CloudService())->httpPost('cloud/build?' . http_build_query($query), [
|
$response = (new CloudService(true))->httpPost('cloud/build?' . http_build_query($query), [
|
||||||
'multipart' => [
|
'multipart' => [
|
||||||
[
|
[
|
||||||
'name' => 'file',
|
'name' => 'file',
|
||||||
@ -122,11 +123,11 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
'authorize_code' => $this->auth_code,
|
'authorize_code' => $this->auth_code,
|
||||||
'timestamp' => $install_task['timestamp']
|
'timestamp' => $install_task['timestamp']
|
||||||
];
|
];
|
||||||
$build_log = (new CloudService())->httpGet('cloud/get_build_logs?' . http_build_query($query));
|
$build_log = (new CloudService(true))->httpGet('cloud/get_build_logs?' . http_build_query($query));
|
||||||
|
|
||||||
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) {
|
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) {
|
||||||
$last = end($build_log['data'][0]);
|
$last = end($build_log['data'][0]);
|
||||||
if ($last['percent'] == 100 && $last['code'] == 0) {
|
if ((int) $last['code'] == 0) {
|
||||||
(new CoreAddonInstallService($addon))->installExceptionHandle();
|
(new CoreAddonInstallService($addon))->installExceptionHandle();
|
||||||
$install_task['error'] = 'ADDON_INSTALL_FAIL';
|
$install_task['error'] = 'ADDON_INSTALL_FAIL';
|
||||||
Cache::set('install_task', $install_task, 10);
|
Cache::set('install_task', $install_task, 10);
|
||||||
@ -162,8 +163,8 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
|
|
||||||
$cache = Cache::get('build_success_' . $addon);
|
$cache = Cache::get('build_success_' . $addon);
|
||||||
|
|
||||||
if (is_null($cache)) {
|
if (is_null($cache) || !isset($cache[ 'index' ])) {
|
||||||
$response = (new CloudService())->request('HEAD','cloud/build_download?' . http_build_query($query), [
|
$response = (new CloudService(true))->request('HEAD','cloud/build_download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => 'bytes=0-']
|
'headers' => ['Range' => 'bytes=0-']
|
||||||
]);
|
]);
|
||||||
$length = $response->getHeader('Content-range');
|
$length = $response->getHeader('Content-range');
|
||||||
@ -187,7 +188,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
$end = ($cache['index'] + 1) * $chunk_size;
|
$end = ($cache['index'] + 1) * $chunk_size;
|
||||||
$end = min($end, $cache['length']);
|
$end = min($end, $cache['length']);
|
||||||
|
|
||||||
$response = (new CloudService())->request('GET','cloud/build_download?' . http_build_query($query), [
|
$response = (new CloudService(true))->request('GET','cloud/build_download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => "bytes={$start}-{$end}"]
|
'headers' => ['Range' => "bytes={$start}-{$end}"]
|
||||||
]);
|
]);
|
||||||
fwrite($zip_resource, $response->getBody());
|
fwrite($zip_resource, $response->getBody());
|
||||||
@ -225,10 +226,18 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
|
|
||||||
Cache::set('build_success_' . $addon, null);
|
Cache::set('build_success_' . $addon, null);
|
||||||
} else {
|
} else {
|
||||||
Cache::set('build_success_' . $addon, null);
|
if (!isset($cache[ 'retry' ])) {
|
||||||
// 调用插件安装异常处理
|
unlink($zip_file);
|
||||||
(new CoreAddonInstallService($addon))->installExceptionHandle();
|
$cache['retry'] = 1;
|
||||||
throw new CommonException('Zip decompression failed');
|
unset($cache['index']);
|
||||||
|
Cache::set('build_success_' . $addon, $cache);
|
||||||
|
$log[] = [ 'code' => 1, 'msg' => '编译包解压失败,尝试重新下载', 'action' => '编译包解压失败,尝试重新下载', 'percent' => '100' ];
|
||||||
|
} else {
|
||||||
|
Cache::set('build_success_' . $addon, null);
|
||||||
|
// 调用插件安装异常处理
|
||||||
|
(new CoreAddonInstallService($addon))->installExceptionHandle();
|
||||||
|
throw new CommonException('Zip decompression failed');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +260,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
'token' => $action_token['data']['token'] ?? ''
|
'token' => $action_token['data']['token'] ?? ''
|
||||||
];
|
];
|
||||||
// 获取文件大小
|
// 获取文件大小
|
||||||
$response = (new CloudService())->request('HEAD','cloud/download?' . http_build_query($query), [
|
$response = (new CloudService(false, 'http://oss.niucloud.com/'))->request('HEAD','cloud/download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => 'bytes=0-']
|
'headers' => ['Range' => 'bytes=0-']
|
||||||
]);
|
]);
|
||||||
$length = $response->getHeader('Content-range');
|
$length = $response->getHeader('Content-range');
|
||||||
@ -263,7 +272,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
$zip_file = $temp_dir . $addon . '.zip';
|
$zip_file = $temp_dir . $addon . '.zip';
|
||||||
$zip_resource = fopen($zip_file, 'w');
|
$zip_resource = fopen($zip_file, 'w');
|
||||||
|
|
||||||
$response = (new CloudService())->request('GET','cloud/download?' . http_build_query($query), [
|
$response = (new CloudService(false, 'http://oss.niucloud.com/'))->request('GET','cloud/download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => "bytes=0-{$length}"]
|
'headers' => ['Range' => "bytes=0-{$length}"]
|
||||||
]);
|
]);
|
||||||
fwrite($zip_resource, $response->getBody());
|
fwrite($zip_resource, $response->getBody());
|
||||||
@ -286,7 +295,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
'token' => $action_token['data']['token'] ?? ''
|
'token' => $action_token['data']['token'] ?? ''
|
||||||
];
|
];
|
||||||
// 获取文件大小
|
// 获取文件大小
|
||||||
$response = (new CloudService())->httpGet('cloud/upgrade?' . http_build_query($query));
|
$response = (new CloudService(false, 'http://oss.niucloud.com/'))->httpGet('cloud/upgrade?' . http_build_query($query));
|
||||||
$response['token'] = $query['token'];
|
$response['token'] = $query['token'];
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@ -309,7 +318,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
$chunk_size = 1 * 1024 * 1024;
|
$chunk_size = 1 * 1024 * 1024;
|
||||||
|
|
||||||
if ($index == -1) {
|
if ($index == -1) {
|
||||||
$response = (new CloudService())->request('HEAD','cloud/upgrade/download?' . http_build_query($query), [
|
$response = (new CloudService(false, 'http://oss.niucloud.com/'))->request('HEAD','cloud/upgrade/download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => 'bytes=0-']
|
'headers' => ['Range' => 'bytes=0-']
|
||||||
]);
|
]);
|
||||||
$length = $response->getHeader('Content-range');
|
$length = $response->getHeader('Content-range');
|
||||||
@ -327,7 +336,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
|
|||||||
$end = ($index + 1) * $chunk_size;
|
$end = ($index + 1) * $chunk_size;
|
||||||
$end = min($end, $length);
|
$end = min($end, $length);
|
||||||
|
|
||||||
$response = (new CloudService())->request('GET','cloud/upgrade/download?' . http_build_query($query), [
|
$response = (new CloudService(false, 'http://oss.niucloud.com/'))->request('GET','cloud/upgrade/download?' . http_build_query($query), [
|
||||||
'headers' => ['Range' => "bytes={$start}-{$end}"]
|
'headers' => ['Range' => "bytes={$start}-{$end}"]
|
||||||
]);
|
]);
|
||||||
fwrite($zip_resource, $response->getBody());
|
fwrite($zip_resource, $response->getBody());
|
||||||
|
|||||||
@ -18,7 +18,9 @@ use app\service\core\menu\CoreMenuService;
|
|||||||
use app\service\core\schedule\CoreScheduleInstallService;
|
use app\service\core\schedule\CoreScheduleInstallService;
|
||||||
use core\exception\AddonException;
|
use core\exception\AddonException;
|
||||||
use core\exception\CommonException;
|
use core\exception\CommonException;
|
||||||
|
use core\util\niucloud\CloudService;
|
||||||
use core\util\Terminal;
|
use core\util\Terminal;
|
||||||
|
use EasyWeChat\Kernel\Exceptions\Exception;
|
||||||
use think\db\exception\DbException;
|
use think\db\exception\DbException;
|
||||||
use think\db\exception\PDOException;
|
use think\db\exception\PDOException;
|
||||||
use think\facade\Cache;
|
use think\facade\Cache;
|
||||||
@ -224,7 +226,16 @@ class CoreAddonInstallService extends CoreAddonBaseService
|
|||||||
$this->backupFrontend();
|
$this->backupFrontend();
|
||||||
|
|
||||||
$tips = [];
|
$tips = [];
|
||||||
if ($mode != 'cloud') $tips[] = get_lang('dict_addon.install_after_update');
|
if ($mode != 'cloud') {
|
||||||
|
$tips[] = get_lang('dict_addon.install_after_update');
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
(new CloudService())->checkLocal();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Cache::set('install_task', null);
|
||||||
|
throw new CommonException($e->getMessage(), $e->getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->addon_list as $addon) {
|
foreach ($this->addon_list as $addon) {
|
||||||
$this->install_task['addon'] = $addon;
|
$this->install_task['addon'] = $addon;
|
||||||
@ -625,6 +636,7 @@ class CoreAddonInstallService extends CoreAddonBaseService
|
|||||||
$addon_info = $core_addon_service->getInfoByKey($this->addon);
|
$addon_info = $core_addon_service->getInfoByKey($this->addon);
|
||||||
if (empty($addon_info)) throw new AddonException('NOT_UNINSTALL');
|
if (empty($addon_info)) throw new AddonException('NOT_UNINSTALL');
|
||||||
if (!$this->uninstallSql()) throw new AddonException('ADDON_SQL_FAIL');
|
if (!$this->uninstallSql()) throw new AddonException('ADDON_SQL_FAIL');
|
||||||
|
if (!$this->uninstallDir()) throw new AddonException('ADDON_DIR_FAIL');
|
||||||
|
|
||||||
// 卸载菜单
|
// 卸载菜单
|
||||||
$this->uninstallMenu();
|
$this->uninstallMenu();
|
||||||
|
|||||||
@ -15,6 +15,7 @@ use app\dict\addon\AddonDict;
|
|||||||
use app\model\addon\Addon;
|
use app\model\addon\Addon;
|
||||||
use app\service\core\addon\CoreAddonBaseService;
|
use app\service\core\addon\CoreAddonBaseService;
|
||||||
use app\service\core\addon\CoreAddonDevelopDownloadService;
|
use app\service\core\addon\CoreAddonDevelopDownloadService;
|
||||||
|
use app\service\core\addon\CoreAddonService;
|
||||||
use app\service\core\addon\WapTrait;
|
use app\service\core\addon\WapTrait;
|
||||||
use core\base\BaseCoreService;
|
use core\base\BaseCoreService;
|
||||||
use core\exception\CloudBuildException;
|
use core\exception\CloudBuildException;
|
||||||
@ -105,6 +106,7 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
|
|
||||||
// 是否通过校验
|
// 是否通过校验
|
||||||
$data[ 'is_pass' ] = !in_array(false, $check_res);
|
$data[ 'is_pass' ] = !in_array(false, $check_res);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,14 +115,25 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
* @return array
|
* @return array
|
||||||
* @throws GuzzleException
|
* @throws GuzzleException
|
||||||
*/
|
*/
|
||||||
public function cloudBuild()
|
public function cloudBuild($param = [])
|
||||||
{
|
{
|
||||||
if (empty($this->auth_code)) {
|
if (empty($this->auth_code)) {
|
||||||
throw new CommonException('CLOUD_BUILD_AUTH_CODE_NOT_FOUND');
|
throw new CommonException('CLOUD_BUILD_AUTH_CODE_NOT_FOUND');
|
||||||
}
|
}
|
||||||
if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST');
|
if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST');
|
||||||
|
|
||||||
$action_token = ( new CoreModuleService() )->getActionToken('cloudbuild', [ 'data' => [ 'product_key' => BaseNiucloudClient::PRODUCT ] ]);
|
// 全部插件
|
||||||
|
$all_addon = array_keys((new CoreAddonService())->getInstallAddonList());
|
||||||
|
// 排除的插件
|
||||||
|
$exclude_addon = [];
|
||||||
|
if (isset($param['addon']) && !empty($param['addon'])) $exclude_addon = array_values(array_diff($all_addon, $param['addon']));
|
||||||
|
|
||||||
|
$action_token = [ 'data' => [] ];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$action_token = ( new CoreModuleService() )->getActionToken('cloudbuild', [ 'data' => [ 'product_key' => BaseNiucloudClient::PRODUCT ] ]);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
// 上传任务key
|
// 上传任务key
|
||||||
$task_key = uniqid();
|
$task_key = uniqid();
|
||||||
@ -134,18 +147,24 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
// 拷贝手机端文件
|
// 拷贝手机端文件
|
||||||
$wap_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%wap%' ] ])->field('id')->findOrEmpty();
|
$wap_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%wap%' ] ])->field('id')->findOrEmpty();
|
||||||
if ($wap_is_compile->isEmpty()) {
|
if ($wap_is_compile->isEmpty()) {
|
||||||
dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'unpackage', 'dist', '.git' ]);
|
dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'unpackage', 'dist', '.git', ...$exclude_addon ]);
|
||||||
$this->handleUniapp($package_dir . 'uni-app');
|
// 如果有排除的插件
|
||||||
|
if (!empty($exclude_addon)) {
|
||||||
|
// 处理pages.json
|
||||||
|
$this->handlePageCode($package_dir . 'uni-app' . DIRECTORY_SEPARATOR .'src' . DIRECTORY_SEPARATOR, $param['addon']);
|
||||||
|
// 处理diy-group
|
||||||
|
$this->compileDiyComponentsCode($package_dir . 'uni-app'. DIRECTORY_SEPARATOR .'src' . DIRECTORY_SEPARATOR, $exclude_addon[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 拷贝admin端文件
|
// 拷贝admin端文件
|
||||||
$admin_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%admin%' ] ])->field('id')->findOrEmpty();
|
$admin_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%admin%' ] ])->field('id')->findOrEmpty();
|
||||||
if ($admin_is_compile->isEmpty()) {
|
if ($admin_is_compile->isEmpty()) {
|
||||||
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea', '.git' ]);
|
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea', '.git', ...$exclude_addon ]);
|
||||||
}
|
}
|
||||||
// 拷贝web端文件
|
// 拷贝web端文件
|
||||||
$web_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%web%' ] ])->field('id')->findOrEmpty();
|
$web_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%web%' ] ])->field('id')->findOrEmpty();
|
||||||
if ($web_is_compile->isEmpty()) {
|
if ($web_is_compile->isEmpty()) {
|
||||||
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt', '.git' ]);
|
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt', '.git', ...$exclude_addon ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->handleCustomPort($package_dir);
|
$this->handleCustomPort($package_dir);
|
||||||
@ -159,7 +178,10 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
'token' => $action_token[ 'data' ][ 'token' ] ?? ''
|
'token' => $action_token[ 'data' ][ 'token' ] ?? ''
|
||||||
];
|
];
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
$response = ( new CloudService(true) )->httpPost('cloud/build?' . http_build_query($query), [
|
|
||||||
|
$param['checkLocal'] = $param['checkLocal'] ?? true;
|
||||||
|
|
||||||
|
$response = ( new CloudService($param['checkLocal']) )->httpPost('cloud/build?' . http_build_query($query), [
|
||||||
'multipart' => [
|
'multipart' => [
|
||||||
[
|
[
|
||||||
'name' => 'file',
|
'name' => 'file',
|
||||||
@ -173,17 +195,45 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
|
|
||||||
$this->build_task = [
|
$this->build_task = [
|
||||||
'task_key' => $task_key,
|
'task_key' => $task_key,
|
||||||
'timestamp' => $query[ 'timestamp' ]
|
'timestamp' => $query[ 'timestamp' ],
|
||||||
|
'checkLocal' => $param['checkLocal'],
|
||||||
|
'task_id' => $response['data']['task_id'] ?? '',
|
||||||
|
'auth_code' => $this->auth_code
|
||||||
];
|
];
|
||||||
Cache::set($this->cache_key, $this->build_task);
|
Cache::set($this->cache_key, $this->build_task);
|
||||||
|
|
||||||
return $this->build_task;
|
return $this->build_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleUniapp(string $dir)
|
private function handlePageCode($compile_path, $addon_arr)
|
||||||
{
|
{
|
||||||
$addon = ( new Addon() )->where([ [ 'status', '=', AddonDict::ON ] ])->value('key', '');
|
$pages = [];
|
||||||
$this->compileDiyComponentsCode($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $addon);
|
foreach ($addon_arr as $addon) {
|
||||||
|
if (!file_exists($this->geAddonPackagePath($addon) . 'uni-app-pages.php')) continue;
|
||||||
|
$uniapp_pages = require $this->geAddonPackagePath($addon) . 'uni-app-pages.php';
|
||||||
|
if (empty($uniapp_pages[ 'pages' ])) continue;
|
||||||
|
|
||||||
|
$page_begin = strtoupper($addon) . '_PAGE_BEGIN';
|
||||||
|
$page_end = strtoupper($addon) . '_PAGE_END';
|
||||||
|
|
||||||
|
// 对0.2.0之前的版本做处理
|
||||||
|
$uniapp_pages[ 'pages' ] = preg_replace_callback('/(.*)(\\r\\n.*\/\/ PAGE_END.*)/s', function ($match) {
|
||||||
|
return $match[ 1 ] . ( substr($match[ 1 ], -1) == ',' ? '' : ',' ) . $match[ 2 ];
|
||||||
|
}, $uniapp_pages[ 'pages' ]);
|
||||||
|
|
||||||
|
$uniapp_pages[ 'pages' ] = str_replace('PAGE_BEGIN', $page_begin, $uniapp_pages[ 'pages' ]);
|
||||||
|
$uniapp_pages[ 'pages' ] = str_replace('PAGE_END', $page_end, $uniapp_pages[ 'pages' ]);
|
||||||
|
$uniapp_pages[ 'pages' ] = str_replace('{{addon_name}}', $addon, $uniapp_pages[ 'pages' ]);
|
||||||
|
|
||||||
|
$pages[] = $uniapp_pages[ 'pages' ];
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = @file_get_contents($compile_path . "pages.json");
|
||||||
|
$content = preg_replace_callback('/(.*\/\/ \{\{ PAGE_BEGAIN \}\})(.*)(\/\/ \{\{ PAGE_END \}\}.*)/s', function ($match) use ($pages) {
|
||||||
|
return $match[ 1 ] . PHP_EOL . implode(PHP_EOL, $pages) . PHP_EOL . $match[ 3 ];
|
||||||
|
}, $content);
|
||||||
|
|
||||||
|
// 找到页面路由文件 pages.json,写入内容
|
||||||
|
return file_put_contents($compile_path . "pages.json", $content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleCustomPort(string $package_dir)
|
private function handleCustomPort(string $package_dir)
|
||||||
@ -226,10 +276,16 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
'authorize_code' => $this->auth_code,
|
'authorize_code' => $this->auth_code,
|
||||||
'timestamp' => $this->build_task[ 'timestamp' ]
|
'timestamp' => $this->build_task[ 'timestamp' ]
|
||||||
];
|
];
|
||||||
$build_log = ( new CloudService(true) )->httpGet('cloud/get_build_logs?' . http_build_query($query));
|
$build_log = ( new CloudService($this->build_task['checkLocal'] ?? false) )->httpGet('cloud/get_build_logs?' . http_build_query($query));
|
||||||
|
|
||||||
if (isset($build_log[ 'data' ]) && isset($build_log[ 'data' ][ 0 ]) && is_array($build_log[ 'data' ][ 0 ])) {
|
if (isset($build_log[ 'data' ]) && isset($build_log[ 'data' ][ 0 ]) && is_array($build_log[ 'data' ][ 0 ])) {
|
||||||
$last = end($build_log[ 'data' ][ 0 ]);
|
$last = end($build_log[ 'data' ][ 0 ]);
|
||||||
|
foreach ($build_log[ 'data' ][ 0 ] as $item) {
|
||||||
|
if ($item['code'] == 0) {
|
||||||
|
$build_log[ 'error_analysis' ] = $this->buildResultAnalysis($item[ 'msg' ]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ($last[ 'percent' ] == 100 && $last[ 'code' ] == 1) {
|
if ($last[ 'percent' ] == 100 && $last[ 'code' ] == 1) {
|
||||||
$build_log[ 'data' ][ 0 ] = $this->buildSuccess($build_log[ 'data' ][ 0 ]);
|
$build_log[ 'data' ][ 0 ] = $this->buildSuccess($build_log[ 'data' ][ 0 ]);
|
||||||
}
|
}
|
||||||
@ -237,6 +293,15 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
return $build_log;
|
return $build_log;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编译异常分析
|
||||||
|
* @param $msg
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function buildResultAnalysis($msg) {
|
||||||
|
return ( new CoreModuleService() )->buildResultAnalysis($msg);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编译完成
|
* 编译完成
|
||||||
* @param array $log
|
* @param array $log
|
||||||
@ -253,7 +318,7 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;
|
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
if (!isset($this->build_task[ 'index' ])) {
|
if (!isset($this->build_task[ 'index' ])) {
|
||||||
$response = ( new CloudService(true) )->request('HEAD', 'cloud/build_download?' . http_build_query($query), [
|
$response = ( new CloudService($this->build_task['checkLocal'] ?? false) )->request('HEAD', 'cloud/build_download?' . http_build_query($query), [
|
||||||
'headers' => [ 'Range' => 'bytes=0-' ]
|
'headers' => [ 'Range' => 'bytes=0-' ]
|
||||||
]);
|
]);
|
||||||
$length = $response->getHeader('Content-range');
|
$length = $response->getHeader('Content-range');
|
||||||
@ -271,7 +336,7 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
$end = ( $this->build_task[ 'index' ] + 1 ) * $chunk_size;
|
$end = ( $this->build_task[ 'index' ] + 1 ) * $chunk_size;
|
||||||
$end = min($end, $this->build_task[ 'length' ]);
|
$end = min($end, $this->build_task[ 'length' ]);
|
||||||
|
|
||||||
$response = ( new CloudService(true) )->request('GET', 'cloud/build_download?' . http_build_query($query), [
|
$response = ( new CloudService($this->build_task['checkLocal'] ?? false) )->request('GET', 'cloud/build_download?' . http_build_query($query), [
|
||||||
'headers' => [ 'Range' => "bytes={$start}-{$end}" ]
|
'headers' => [ 'Range' => "bytes={$start}-{$end}" ]
|
||||||
]);
|
]);
|
||||||
fwrite($zip_resource, $response->getBody());
|
fwrite($zip_resource, $response->getBody());
|
||||||
@ -290,9 +355,21 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
$zip->extractTo($temp_dir . 'download');
|
$zip->extractTo($temp_dir . 'download');
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
|
if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'admin')) {
|
||||||
|
@del_target_dir(public_path() .'admin', true);
|
||||||
|
}
|
||||||
|
if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'web')) {
|
||||||
|
@del_target_dir(public_path() .'web', true);
|
||||||
|
}
|
||||||
|
if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'wap')) {
|
||||||
|
@del_target_dir(public_path() .'wap', true);
|
||||||
|
}
|
||||||
|
|
||||||
$exclude_files = ['favicon.ico', 'niucloud.ico'];
|
$exclude_files = ['favicon.ico', 'niucloud.ico'];
|
||||||
dir_copy($temp_dir . 'download', root_path(), exclude_files: $exclude_files);
|
dir_copy($temp_dir . 'download', root_path(), exclude_files: $exclude_files);
|
||||||
|
|
||||||
|
$this->buildResultAnalysis('success');
|
||||||
|
|
||||||
$this->clearTask();
|
$this->clearTask();
|
||||||
} else {
|
} else {
|
||||||
// 压缩包解压失败 尝试重新下载
|
// 压缩包解压失败 尝试重新下载
|
||||||
@ -304,6 +381,7 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
$log[] = [ 'code' => 1, 'msg' => '编译包解压失败,尝试重新下载', 'action' => '编译包解压失败,尝试重新下载', 'percent' => '100' ];
|
$log[] = [ 'code' => 1, 'msg' => '编译包解压失败,尝试重新下载', 'action' => '编译包解压失败,尝试重新下载', 'percent' => '100' ];
|
||||||
} else {
|
} else {
|
||||||
$log[] = [ 'code' => 0, 'msg' => '编译包解压失败', 'action' => '编译包解压', 'percent' => '100' ];
|
$log[] = [ 'code' => 0, 'msg' => '编译包解压失败', 'action' => '编译包解压', 'percent' => '100' ];
|
||||||
|
$this->buildResultAnalysis('编译包解压失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,8 +400,276 @@ class CoreCloudBuildService extends BaseCoreService
|
|||||||
public function clearTask()
|
public function clearTask()
|
||||||
{
|
{
|
||||||
if (!$this->build_task) return;
|
if (!$this->build_task) return;
|
||||||
|
|
||||||
|
if (isset($this->build_task['task_id']) && !empty($this->build_task['task_id'])) {
|
||||||
|
try {
|
||||||
|
( new CloudService($this->build_task['checkLocal'] ?? false) )->httpPost('cloud/cancel', [
|
||||||
|
'json' => [
|
||||||
|
'task_id' => $this->build_task['task_id']
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;
|
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;
|
||||||
@del_target_dir($temp_dir, true);
|
@del_target_dir($temp_dir, true);
|
||||||
Cache::set($this->cache_key, null);
|
Cache::set($this->cache_key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取插件定义的package目录
|
||||||
|
* @param string $addon
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function geAddonPackagePath(string $addon)
|
||||||
|
{
|
||||||
|
return root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSE编译完成后,PHP后台执行下载解压部署
|
||||||
|
* @param string $taskId 任务ID
|
||||||
|
* @param string $downloadUrl 下载链接
|
||||||
|
* @param string $authorizeCode 授权码
|
||||||
|
* @param string $timestamp 时间戳
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function startServerDownload(string $taskId, string $downloadUrl, string $authorizeCode, string $timestamp)
|
||||||
|
{
|
||||||
|
$taskKey = 'sse_build_' . $taskId;
|
||||||
|
$tempDir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $taskKey . DIRECTORY_SEPARATOR;
|
||||||
|
if (!is_dir($tempDir)) {
|
||||||
|
mkdir($tempDir, 0755, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$downloadInfo = [
|
||||||
|
'task_id' => $taskId,
|
||||||
|
'task_key' => $taskKey,
|
||||||
|
'download_url' => $downloadUrl,
|
||||||
|
'authorize_code' => $authorizeCode,
|
||||||
|
'timestamp' => $timestamp,
|
||||||
|
'temp_dir' => $tempDir,
|
||||||
|
'zip_file' => $tempDir . 'download.zip',
|
||||||
|
'chunk_size' => 1 * 1024 * 1024,
|
||||||
|
'status' => 'downloading',
|
||||||
|
'msg' => '准备下载...'
|
||||||
|
];
|
||||||
|
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return ['code' => 1, 'msg' => '初始化成功', 'data' => [
|
||||||
|
'task_key' => $taskKey,
|
||||||
|
'cache_key' => 'cloud_build_' . $taskKey,
|
||||||
|
'cache_exists' => Cache::has('cloud_build_' . $taskKey)
|
||||||
|
]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取SSE编译后续操作的进度(参考 buildSuccess 逻辑)
|
||||||
|
* @param string $taskId 任务ID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSseBuildLog(string $taskId)
|
||||||
|
{
|
||||||
|
$taskKey = 'sse_build_' . $taskId;
|
||||||
|
$cacheKey = 'cloud_build_' . $taskKey;
|
||||||
|
|
||||||
|
$hasBefore = Cache::has($cacheKey);
|
||||||
|
$downloadInfo = Cache::get($cacheKey);
|
||||||
|
|
||||||
|
if (empty($downloadInfo)) {
|
||||||
|
return ['code' => 0, 'msg' => '任务不存在或已过期', 'status' => 'error', 'debug' => [
|
||||||
|
'task_id' => $taskId,
|
||||||
|
'task_key' => $taskKey,
|
||||||
|
'cache_key' => $cacheKey,
|
||||||
|
'cache_has_before' => $hasBefore
|
||||||
|
]];
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = [
|
||||||
|
'authorize_code' => $downloadInfo['authorize_code'],
|
||||||
|
'timestamp' => $downloadInfo['timestamp']
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!isset($downloadInfo['index'])) {
|
||||||
|
$response = ( new CloudService(true) )->request('HEAD', 'cloud/build_download?' . http_build_query($query), [
|
||||||
|
'headers' => ['Range' => 'bytes=0-']
|
||||||
|
]);
|
||||||
|
$contentRange = $response->getHeader('Content-range');
|
||||||
|
$length = (int) explode("/", $contentRange[0])[1];
|
||||||
|
$chunkSize = $downloadInfo['chunk_size'];
|
||||||
|
$step = (int) ceil($length / $chunkSize);
|
||||||
|
|
||||||
|
$downloadInfo['index'] = 0;
|
||||||
|
$downloadInfo['length'] = $length;
|
||||||
|
$downloadInfo['step'] = $step;
|
||||||
|
$downloadInfo['downloaded_bytes'] = 0;
|
||||||
|
$downloadInfo['percent'] = 0;
|
||||||
|
$downloadInfo['msg'] = '开始下载...';
|
||||||
|
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 1,
|
||||||
|
'status' => 'downloading',
|
||||||
|
'percent' => 0,
|
||||||
|
'downloaded_bytes' => 0,
|
||||||
|
'total_bytes' => $length,
|
||||||
|
'msg' => '开始下载...'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$zipFile = $downloadInfo['zip_file'];
|
||||||
|
$zipResource = fopen($zipFile, 'a');
|
||||||
|
|
||||||
|
if (($downloadInfo['index'] + 1) <= $downloadInfo['step']) {
|
||||||
|
$start = $downloadInfo['index'] * $downloadInfo['chunk_size'];
|
||||||
|
$end = ($downloadInfo['index'] + 1) * $downloadInfo['chunk_size'];
|
||||||
|
$end = min($end, $downloadInfo['length']);
|
||||||
|
$expectedBytes = $end - $start;
|
||||||
|
|
||||||
|
$response = ( new CloudService(true) )->request('GET', 'cloud/build_download?' . http_build_query($query), [
|
||||||
|
'headers' => ['Range' => "bytes={$start}-{$end}"]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$body = $response->getBody();
|
||||||
|
$actualBytes = strlen($body);
|
||||||
|
$contentRange = $response->getHeader('Content-Range');
|
||||||
|
$contentRangeStr = is_array($contentRange) ? ($contentRange[0] ?? '') : $contentRange;
|
||||||
|
|
||||||
|
if ($actualBytes != $expectedBytes) {
|
||||||
|
$downloadInfo['downloaded_bytes'] = filesize($zipFile);
|
||||||
|
$downloadInfo['msg'] = "分片{$downloadInfo['index']}大小不符: 期望{$expectedBytes}, 实际{$actualBytes}";
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 1,
|
||||||
|
'status' => 'downloading',
|
||||||
|
'percent' => $downloadInfo['percent'],
|
||||||
|
'downloaded_bytes' => $downloadInfo['downloaded_bytes'],
|
||||||
|
'total_bytes' => $downloadInfo['length'],
|
||||||
|
'msg' => $downloadInfo['msg'],
|
||||||
|
'debug' => [
|
||||||
|
'chunk_index' => $downloadInfo['index'],
|
||||||
|
'expected_bytes' => $expectedBytes,
|
||||||
|
'actual_bytes' => $actualBytes,
|
||||||
|
'content_range' => $contentRangeStr
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($zipResource, $body);
|
||||||
|
fclose($zipResource);
|
||||||
|
|
||||||
|
$downloadInfo['index'] += 1;
|
||||||
|
$downloadInfo['downloaded_bytes'] = filesize($zipFile);
|
||||||
|
$downloadInfo['percent'] = round($downloadInfo['index'] / $downloadInfo['step'] * 100);
|
||||||
|
$downloadInfo['msg'] = '编译包下载中,已下载' . $downloadInfo['percent'] . '%';
|
||||||
|
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 1,
|
||||||
|
'status' => 'downloading',
|
||||||
|
'percent' => $downloadInfo['percent'],
|
||||||
|
'downloaded_bytes' => $downloadInfo['downloaded_bytes'],
|
||||||
|
'total_bytes' => $downloadInfo['length'],
|
||||||
|
'msg' => $downloadInfo['msg']
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
fclose($zipResource);
|
||||||
|
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
$zipOpenResult = $zip->open($zipFile);
|
||||||
|
if ($zipOpenResult === true) {
|
||||||
|
$extractDir = $downloadInfo['temp_dir'] . 'download' . DIRECTORY_SEPARATOR;
|
||||||
|
dir_mkdir($extractDir);
|
||||||
|
|
||||||
|
$zipContents = [];
|
||||||
|
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||||
|
$zipContents[] = $zip->getNameIndex($i);
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->extractTo($extractDir);
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
$downloadInfo['msg'] = '解压成功,文件数:' . count($zipContents);
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
$tempDir = $downloadInfo['temp_dir'];
|
||||||
|
|
||||||
|
if (is_dir($tempDir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'admin')) {
|
||||||
|
@del_target_dir(public_path() . 'admin', true);
|
||||||
|
}
|
||||||
|
if (is_dir($tempDir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'web')) {
|
||||||
|
@del_target_dir(public_path() . 'web', true);
|
||||||
|
}
|
||||||
|
if (is_dir($tempDir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'wap')) {
|
||||||
|
@del_target_dir(public_path() . 'wap', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$excludeFiles = ['favicon.ico', 'niucloud.ico'];
|
||||||
|
dir_copy($tempDir . 'download', root_path(), exclude_files: $excludeFiles);
|
||||||
|
|
||||||
|
$this->buildResultAnalysis('success');
|
||||||
|
|
||||||
|
$downloadInfo['status'] = 'completed';
|
||||||
|
$downloadInfo['percent'] = 100;
|
||||||
|
$downloadInfo['msg'] = '部署完成';
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 1,
|
||||||
|
'status' => 'completed',
|
||||||
|
'percent' => 100,
|
||||||
|
'downloaded_bytes' => $downloadInfo['downloaded_bytes'],
|
||||||
|
'total_bytes' => $downloadInfo['length'],
|
||||||
|
'msg' => '部署完成'
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
if (!isset($downloadInfo['retry'])) {
|
||||||
|
unlink($zipFile);
|
||||||
|
$downloadInfo['retry'] = 1;
|
||||||
|
unset($downloadInfo['index']);
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 1,
|
||||||
|
'status' => 'downloading',
|
||||||
|
'percent' => 0,
|
||||||
|
'downloaded_bytes' => 0,
|
||||||
|
'total_bytes' => $downloadInfo['length'] ?? 0,
|
||||||
|
'msg' => '编译包解压失败,尝试重新下载',
|
||||||
|
'debug' => [
|
||||||
|
'zip_file' => $zipFile,
|
||||||
|
'zip_size' => file_exists($zipFile) ? filesize($zipFile) : 'not exists',
|
||||||
|
'zip_open_result' => $zipOpenResult,
|
||||||
|
'extract_dir' => $downloadInfo['temp_dir'] . 'download' . DIRECTORY_SEPARATOR,
|
||||||
|
'temp_dir' => $downloadInfo['temp_dir']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$downloadInfo['status'] = 'error';
|
||||||
|
$downloadInfo['msg'] = '编译包解压失败';
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => 0,
|
||||||
|
'status' => 'error',
|
||||||
|
'percent' => $downloadInfo['percent'] ?? 0,
|
||||||
|
'msg' => '编译包解压失败'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$downloadInfo['status'] = 'error';
|
||||||
|
$downloadInfo['msg'] = $e->getMessage();
|
||||||
|
Cache::set('cloud_build_' . $taskKey, $downloadInfo, 7200);
|
||||||
|
|
||||||
|
return ['code' => 0, 'msg' => $e->getMessage(), 'status' => 'error'];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,4 +164,18 @@ class CoreModuleService extends BaseNiucloudClient
|
|||||||
{
|
{
|
||||||
return $this->httpGet('store/app_version/list', [ 'product_key' => self::PRODUCT, 'app_key' => $app_key ])[ 'data' ] ?? false;
|
return $this->httpGet('store/app_version/list', [ 'product_key' => self::PRODUCT, 'app_key' => $app_key ])[ 'data' ] ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编译异常分析
|
||||||
|
* @param string $msg
|
||||||
|
* @return array|\core\util\niucloud\Response|object|ResponseInterface
|
||||||
|
* @throws GuzzleException
|
||||||
|
*/
|
||||||
|
public function buildResultAnalysis(string $msg)
|
||||||
|
{
|
||||||
|
$params = [
|
||||||
|
'msg' => $msg,
|
||||||
|
];
|
||||||
|
return $this->httpPost('build_error_analysis', $params)['data'] ?? [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -323,7 +323,17 @@ class CorePayService extends BaseCoreService
|
|||||||
public function createByTrade($site_id, $trade_type, $trade_id)
|
public function createByTrade($site_id, $trade_type, $trade_id)
|
||||||
{
|
{
|
||||||
//创建新的支付单据
|
//创建新的支付单据
|
||||||
$data = array_values(array_filter(event('PayCreate', [ 'site_id' => $site_id, 'trade_type' => $trade_type, 'trade_id' => $trade_id ])))[ 0 ] ?? [];
|
$event_result = event('PayCreate', [ 'site_id' => $site_id, 'trade_type' => $trade_type, 'trade_id' => $trade_id ]);
|
||||||
|
|
||||||
|
// PHP 8.0+ 兼容性处理:确保 event 返回值是数组
|
||||||
|
if (!is_array($event_result)) {
|
||||||
|
$event_result = [];
|
||||||
|
}
|
||||||
|
// 过滤掉 false/null 等无效值,只保留有效的数组元素
|
||||||
|
$filtered = array_values(array_filter($event_result, function($item) {
|
||||||
|
return is_array($item) && !empty($item);
|
||||||
|
}));
|
||||||
|
$data = !empty($filtered) ? $filtered[0] : [];
|
||||||
if (empty($data)) throw new PayException('PAY_NOT_FOUND_TRADE');//找不到可支付的交易
|
if (empty($data)) throw new PayException('PAY_NOT_FOUND_TRADE');//找不到可支付的交易
|
||||||
|
|
||||||
if (isset($data[ 'status' ]) && $data[ 'money' ] == 0) {
|
if (isset($data[ 'status' ]) && $data[ 'money' ] == 0) {
|
||||||
|
|||||||
@ -64,7 +64,7 @@ class CoreWeappCloudService extends CoreCloudBaseService
|
|||||||
*/
|
*/
|
||||||
public function uploadWeapp(array $data)
|
public function uploadWeapp(array $data)
|
||||||
{
|
{
|
||||||
if (strpos($this->config[ 'base_url' ], 'https://') === false) throw new CommonException('CURR_SITE_IS_NOT_OPEN_SSL');
|
// if (strpos($this->config[ 'base_url' ], 'https://') === false) throw new CommonException('CURR_SITE_IS_NOT_OPEN_SSL');
|
||||||
$this->site_id = $data[ 'site_id' ] ?? 0;
|
$this->site_id = $data[ 'site_id' ] ?? 0;
|
||||||
|
|
||||||
if (empty($this->config[ 'app_id' ])) throw new CommonException('WEAPP_APPID_EMPTY');
|
if (empty($this->config[ 'app_id' ])) throw new CommonException('WEAPP_APPID_EMPTY');
|
||||||
@ -126,7 +126,8 @@ class CoreWeappCloudService extends CoreCloudBaseService
|
|||||||
|
|
||||||
if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
|
if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
|
||||||
|
|
||||||
return [ 'key' => $query[ 'timestamp' ] ];
|
$task_id = $response[ 'data' ][ 'task_id' ] ?? $query[ 'timestamp' ];
|
||||||
|
return [ 'key' => $task_id ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -306,14 +307,13 @@ class CoreWeappCloudService extends CoreCloudBaseService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取小程序编译日志
|
* 获取小程序编译日志
|
||||||
* @param string $timestamp
|
* @param string $taskId 任务ID (格式: authorize_code_timestamp)
|
||||||
* @return \Psr\Http\Message\ResponseInterface
|
* @return \Psr\Http\Message\ResponseInterface
|
||||||
*/
|
*/
|
||||||
public function getWeappCompileLog(string $timestamp)
|
public function getWeappCompileLog(string $taskId)
|
||||||
{
|
{
|
||||||
$query = [
|
$query = [
|
||||||
'authorize_code' => $this->auth_code,
|
'task_id' => $taskId
|
||||||
'timestamp' => $timestamp
|
|
||||||
];
|
];
|
||||||
return ( new CloudService(true) )->httpGet('cloud/get_weapp_logs?' . http_build_query($query));
|
return ( new CloudService(true) )->httpGet('cloud/get_weapp_logs?' . http_build_query($query));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,12 +66,18 @@ class CoreOplatformConfigService extends BaseCoreService
|
|||||||
public function getStaticInfo(){
|
public function getStaticInfo(){
|
||||||
$wap_domain = (new CoreSysConfigService())->getSceneDomain(0)['wap_url'] ?? '';
|
$wap_domain = (new CoreSysConfigService())->getSceneDomain(0)['wap_url'] ?? '';
|
||||||
|
|
||||||
|
$local_cloud_compile_config = (new CoreConfigService())->getConfig(0, 'LOCAL_CLOUD_COMPILE_CONFIG')['value'] ?? [];
|
||||||
|
$baseUri = $local_cloud_compile_config['baseUri'] ?? '';
|
||||||
|
if (empty($baseUri)) $baseUri = 'oss.niucloud.com';
|
||||||
|
$baseUri = str_replace('http://', '', $baseUri);
|
||||||
|
$baseUri = str_replace('https://', '', $baseUri);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'auth_serve_url' => (string)url('/adminapi/wxoplatform/server',[],'', true), // 授权事件接收配置
|
'auth_serve_url' => (string)url('/adminapi/wxoplatform/server',[],'', true), // 授权事件接收配置
|
||||||
'message_serve_url' => (string)url('/adminapi/wxoplatform/message/$APPID$', [],'',true), // 消息与事件接收配置
|
'message_serve_url' => (string)url('/adminapi/wxoplatform/message/$APPID$', [],'',true), // 消息与事件接收配置
|
||||||
'auth_launch_domain' => parse_url(request()->domain())['host'] ?? '', // 授权发起页域名
|
'auth_launch_domain' => parse_url(request()->domain())['host'] ?? '', // 授权发起页域名
|
||||||
'wechat_auth_domain' => parse_url($wap_domain)['host'] ?? '', // 公众号开发域名
|
'wechat_auth_domain' => parse_url($wap_domain)['host'] ?? '', // 公众号开发域名
|
||||||
'upload_ip' => gethostbyname('oss.niucloud.com')
|
'upload_ip' => gethostbyname($baseUri)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
niucloud/app/upgrade/v124/upgrade.sql
Normal file
2
niucloud/app/upgrade/v124/upgrade.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE weapp_version
|
||||||
|
CHANGE COLUMN task_key task_key varchar(255) NOT NULL DEFAULT '' COMMENT '上传任务key';
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'version' => '1.2.2',
|
'version' => '1.2.4',
|
||||||
'code' => '202604010001'
|
'code' => '202606060001'
|
||||||
];
|
];
|
||||||
|
|||||||
@ -15,40 +15,37 @@ class CloudService
|
|||||||
{
|
{
|
||||||
use HasHttpRequests;
|
use HasHttpRequests;
|
||||||
|
|
||||||
private $baseUri = 'http://oss.niucloud.com/';
|
private $baseUri = 'http://go.site.niucloud.com/';
|
||||||
|
|
||||||
public $is_connected = false;
|
public $is_connected = false;
|
||||||
|
|
||||||
public function __construct($checkLocal = false, $local_cloud_compile = '') {
|
public function __construct($checkLocal = false, $local_cloud_compile = '') {
|
||||||
$this->baseUri = 'http://' . gethostbyname('oss.niucloud.com') . ':8000/';
|
if (!empty($local_cloud_compile)) $this->baseUri = $local_cloud_compile;
|
||||||
if ($checkLocal) $this->is_connected = $this->checkLocal($local_cloud_compile);
|
if ($checkLocal) $this->is_connected = $this->checkLocal($local_cloud_compile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkLocal($local_cloud_compile) {
|
public function checkLocal($local_cloud_compile = '') {
|
||||||
$baseUri = $this->baseUri;
|
$baseUri = $this->baseUri;
|
||||||
|
|
||||||
$local_cloud_compile_config = (new CoreConfigService())->getConfig(0, 'LOCAL_CLOUD_COMPILE_CONFIG')['value'] ?? [];
|
|
||||||
if (!empty($local_cloud_compile_config) && isset($local_cloud_compile_config['isOpen']) && $local_cloud_compile_config['isOpen'] == 1){
|
|
||||||
$baseUri = $local_cloud_compile_config['baseUri'] ?? '';
|
|
||||||
if (empty($baseUri)){
|
|
||||||
throw new CommonException("已开启`第三方云编译`,但未配置云编译服务器地址,详情查看:平台端》云编译》第三方云编译");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($local_cloud_compile)){
|
if (!empty($local_cloud_compile)){
|
||||||
$baseUri = $local_cloud_compile;
|
$baseUri = $local_cloud_compile;
|
||||||
|
} else {
|
||||||
|
$local_cloud_compile_config = (new CoreConfigService())->getConfig(0, 'LOCAL_CLOUD_COMPILE_CONFIG')['value'] ?? [];
|
||||||
|
$isOpen = $local_cloud_compile_config['isOpen'] ?? 1;
|
||||||
|
|
||||||
|
if ($isOpen){
|
||||||
|
$baseUri = $local_cloud_compile_config['baseUri'] ?? '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_connected = false;
|
$is_connected = false;
|
||||||
try {
|
try {
|
||||||
$res = (new Client(['base_uri' => $baseUri ]))->request("GET", '', []);
|
$res = (new Client(['base_uri' => $baseUri ]))->request("GET", '', []);
|
||||||
// dd($res->getBody()->getContents());
|
|
||||||
if ($res->getStatusCode() == '200' && $res->getBody()->getContents() == '欢迎使用NiuCloud编译服务!') {
|
if ($res->getStatusCode() == '200' && $res->getBody()->getContents() == '欢迎使用NiuCloud编译服务!') {
|
||||||
$this->baseUri = $baseUri;
|
$this->baseUri = $baseUri;
|
||||||
$is_connected = true;
|
$is_connected = true;
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
throw new CommonException('CONNECT_FAIL');
|
|
||||||
}
|
}
|
||||||
return $is_connected;
|
return $is_connected;
|
||||||
}
|
}
|
||||||
|
|||||||
2
niucloud/public/.gitignore
vendored
2
niucloud/public/.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
/.htaccess
|
/.htaccess
|
||||||
upload
|
upload
|
||||||
nginx.htaccess
|
nginx.htaccess
|
||||||
.htaccess
|
.htaccess
|
||||||
1
niucloud/public/admin/assets/404-45293806.js
Normal file
1
niucloud/public/admin/assets/404-45293806.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{d as l,r as d,u as i,o as p,c as m,a as t,b as u,e as x,w as v,f,E as h,p as b,g as I,h as g,i as S,t as w}from"./index-8eead49b.js";/* empty css */import{_ as B}from"./error-54aee623.js";import{_ as k}from"./_plugin-vue_export-helper-c27b6911.js";const o=e=>(b("data-v-4f4088b5"),e=e(),I(),e),y={class:"error"},C={class:"flex items-center"},E=o(()=>t("div",null,[t("img",{class:"w-[240px]",src:B})],-1)),N={class:"text-left ml-[100px]"},V=o(()=>t("div",{class:"error-text text-[28px] font-bold"},"404错误!",-1)),R=o(()=>t("div",{class:"text-[#222] text-[20px] mt-[15px]"},"哎呀,出错了!您访问的页面不存在...",-1)),U=o(()=>t("div",{class:"text-[#c4c2c2] text-[12px] mt-[5px]"},"尝试检查URL的错误,然后点击浏览器刷新按钮。",-1)),$={class:"mt-[40px]"},D=l({__name:"404",setup(e){let s=null;const a=d(5),c=i();return s=setInterval(()=>{a.value===0?(clearInterval(s),c.go(-1)):a.value--},1e3),p(()=>{s&&clearInterval(s)}),(_,n)=>{const r=h;return g(),m("div",y,[t("div",C,[u(_.$slots,"content",{},()=>[E],!0),t("div",N,[V,R,U,t("div",$,[x(r,{class:"bottom",onClick:n[0]||(n[0]=L=>f(c).go(-1))},{default:v(()=>[S(w(a.value)+" 秒后返回上一页",1)]),_:1})])])])])}}});const A=k(D,[["__scopeId","data-v-4f4088b5"]]);export{A as default};
|
||||||
@ -1 +0,0 @@
|
|||||||
import{d as l,r as d,u as i,o as p,c as u,a as t,b as m,e as x,w as v,f,E as h,p as b,g,h as I,i as w,t as S}from"./index-42af2821.js";/* empty css */import{_ as B}from"./_plugin-vue_export-helper-c27b6911.js";const k=""+new URL("error-ab7e4004.png",import.meta.url).href,o=e=>(b("data-v-4f4088b5"),e=e(),g(),e),y={class:"error"},C={class:"flex items-center"},E=o(()=>t("div",null,[t("img",{class:"w-[240px]",src:k})],-1)),N={class:"text-left ml-[100px]"},R=o(()=>t("div",{class:"error-text text-[28px] font-bold"},"404错误!",-1)),U=o(()=>t("div",{class:"text-[#222] text-[20px] mt-[15px]"},"哎呀,出错了!您访问的页面不存在...",-1)),V=o(()=>t("div",{class:"text-[#c4c2c2] text-[12px] mt-[5px]"},"尝试检查URL的错误,然后点击浏览器刷新按钮。",-1)),L={class:"mt-[40px]"},$=l({__name:"404",setup(e){let s=null;const a=d(5),n=i();return s=setInterval(()=>{a.value===0?(clearInterval(s),n.go(-1)):a.value--},1e3),p(()=>{s&&clearInterval(s)}),(r,c)=>{const _=h;return I(),u("div",y,[t("div",C,[m(r.$slots,"content",{},()=>[E],!0),t("div",N,[R,U,V,t("div",L,[x(_,{class:"bottom",onClick:c[0]||(c[0]=D=>f(n).go(-1))},{default:v(()=>[w(S(a.value)+" 秒后返回上一页",1)]),_:1})])])])])}}});const z=B($,[["__scopeId","data-v-4f4088b5"]]);export{z as default};
|
|
||||||
1
niucloud/public/admin/assets/App-6c7eb125.js
Normal file
1
niucloud/public/admin/assets/App-6c7eb125.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{dY as f}from"./index-8eead49b.js";export{f as default};
|
||||||
@ -1 +0,0 @@
|
|||||||
import{dD as f}from"./index-42af2821.js";export{f as default};
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
.upload-demo[data-v-d439b536]{width:100%;border:1px dashed #dcdcdc;border-radius:6px;padding:20px;text-align:center}.copy-icon[data-v-d439b536]{cursor:pointer;margin-left:8px;color:#606266;font-size:18px}.copy-icon[data-v-d439b536]:hover{color:#409eff}
|
||||||
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/Verify-92009dcf.js
Normal file
1
niucloud/public/admin/assets/Verify-92009dcf.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import z from"./VerifySlide-02eb59d1.js";import g from"./VerifyPoints-e2bb084a.js";import{P as k,r as o,m as w,bc as T,Y as V,Z as B,h as p,c as u,a as c,i as N,C as y,y as d,v as C,bb as P,x as v}from"./index-8eead49b.js";import{_ as j}from"./_plugin-vue_export-helper-c27b6911.js";import"./index-b4a6dc9f.js";const O={name:"Vue2Verify",components:{VerifySlide:z,VerifyPoints:g},props:{captchaType:{type:String,required:!0},figure:{type:Number},arith:{type:Number},mode:{type:String,default:"pop"},vSpace:{type:Number},explain:{type:String},imgSize:{type:Object,default(){return{width:"310px",height:"155px"}}},blockSize:{type:Object},barSize:{type:Object}},setup(m){const{captchaType:i,figure:e,arith:t,mode:n,vSpace:h,explain:f,imgSize:R,blockSize:W,barSize:Y}=k(m),a=o(!1),r=o(void 0),s=o(void 0),l=o({}),S=w(()=>n.value=="pop"?a.value:!0),b=()=>{l.value.refresh&&l.value.refresh()},x=()=>{a.value=!1,b()},_=()=>{n.value=="pop"&&(a.value=!0)};return T(()=>{switch(i.value){case"blockPuzzle":r.value="2",s.value="VerifySlide";break;case"clickWord":r.value="",s.value="VerifyPoints";break}}),{clickShow:a,verifyType:r,componentType:s,instance:l,showBox:S,closeBox:x,show:_}}},D={key:0,class:"verifybox-top"},E=c("i",{class:"iconfont icon-close"},null,-1),q=[E];function I(m,i,e,t,n,h){return V((p(),u("div",{class:v(e.mode=="pop"?"mask":"")},[c("div",{class:v(e.mode=="pop"?"verifybox":""),style:d({"max-width":parseInt(e.imgSize.width)+30+"px"})},[e.mode=="pop"?(p(),u("div",D,[N(" 请完成安全验证 "),c("span",{class:"verifybox-close",onClick:i[0]||(i[0]=(...f)=>t.closeBox&&t.closeBox(...f))},q)])):y("",!0),c("div",{class:"verifybox-bottom",style:d({padding:e.mode=="pop"?"15px":"0"})},[t.componentType?(p(),C(P(t.componentType),{key:0,captchaType:e.captchaType,type:t.verifyType,figure:e.figure,arith:e.arith,mode:e.mode,vSpace:e.vSpace,explain:e.explain,imgSize:e.imgSize,blockSize:e.blockSize,barSize:e.barSize,ref:"instance"},null,8,["captchaType","type","figure","arith","mode","vSpace","explain","imgSize","blockSize","barSize"])):y("",!0)],4)],6)],2)),[[B,t.showBox]])}const J=j(O,[["render",I]]);export{J as default};
|
||||||
@ -1 +0,0 @@
|
|||||||
import z from"./VerifySlide-9050bdca.js";import g from"./VerifyPoints-796482d6.js";import{P as k,r as o,m as w,bb as T,Y as V,Z as B,h as p,c as u,a as c,i as N,C as y,y as d,v as C,bc as P,x as v}from"./index-42af2821.js";import{_ as j}from"./_plugin-vue_export-helper-c27b6911.js";import"./index-7b692db8.js";const O={name:"Vue2Verify",components:{VerifySlide:z,VerifyPoints:g},props:{captchaType:{type:String,required:!0},figure:{type:Number},arith:{type:Number},mode:{type:String,default:"pop"},vSpace:{type:Number},explain:{type:String},imgSize:{type:Object,default(){return{width:"310px",height:"155px"}}},blockSize:{type:Object},barSize:{type:Object}},setup(m){const{captchaType:i,figure:e,arith:t,mode:n,vSpace:h,explain:f,imgSize:R,blockSize:W,barSize:Y}=k(m),a=o(!1),r=o(void 0),s=o(void 0),l=o({}),S=w(()=>n.value=="pop"?a.value:!0),b=()=>{l.value.refresh&&l.value.refresh()},x=()=>{a.value=!1,b()},_=()=>{n.value=="pop"&&(a.value=!0)};return T(()=>{switch(i.value){case"blockPuzzle":r.value="2",s.value="VerifySlide";break;case"clickWord":r.value="",s.value="VerifyPoints";break}}),{clickShow:a,verifyType:r,componentType:s,instance:l,showBox:S,closeBox:x,show:_}}},D={key:0,class:"verifybox-top"},E=c("i",{class:"iconfont icon-close"},null,-1),q=[E];function I(m,i,e,t,n,h){return V((p(),u("div",{class:v(e.mode=="pop"?"mask":"")},[c("div",{class:v(e.mode=="pop"?"verifybox":""),style:d({"max-width":parseInt(e.imgSize.width)+30+"px"})},[e.mode=="pop"?(p(),u("div",D,[N(" 请完成安全验证 "),c("span",{class:"verifybox-close",onClick:i[0]||(i[0]=(...f)=>t.closeBox&&t.closeBox(...f))},q)])):y("",!0),c("div",{class:"verifybox-bottom",style:d({padding:e.mode=="pop"?"15px":"0"})},[t.componentType?(p(),C(P(t.componentType),{key:0,captchaType:e.captchaType,type:t.verifyType,figure:e.figure,arith:e.arith,mode:e.mode,vSpace:e.vSpace,explain:e.explain,imgSize:e.imgSize,blockSize:e.blockSize,barSize:e.barSize,ref:"instance"},null,8,["captchaType","type","figure","arith","mode","vSpace","explain","imgSize","blockSize","barSize"])):y("",!0)],4)],6)],2)),[[B,t.showBox]])}const J=j(O,[["render",I]]);export{J as default};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
import{r as F,a as M,b as K,c as Y}from"./index-7b692db8.js";import{P as Z,bd as G,r as s,q as m,aZ as X,h as H,c as I,a as l,y as A,Y as Q,Z as U,F as $,V as ee,t as q,ax as te}from"./index-42af2821.js";import{_ as ae}from"./_plugin-vue_export-helper-c27b6911.js";const ie={name:"VerifyPoints",props:{mode:{type:String,default:"fixed"},captchaType:{type:String},vSpace:{type:Number,default:5},imgSize:{type:Object,default(){return{width:"310px",height:"155px"}}},barSize:{type:Object,default(){return{width:"310px",height:"40px"}}}},setup(N,f){const{mode:_,captchaType:e,vSpace:L,imgSize:R,barSize:c}=Z(N),{proxy:n}=G(),h=s(""),z=s(3),p=m([]),a=m([]),o=s(1),O=s(""),w=m([]),v=s(""),u=m({imgHeight:0,imgWidth:0,barHeight:0,barWidth:0}),y=m([]),d=s(""),b=s(void 0),x=s(void 0),j=s(!0),C=s(!0),V=()=>{p.splice(0,p.length),a.splice(0,a.length),o.value=1,B(),te(()=>{const{imgHeight:i,imgWidth:t,barHeight:g,barWidth:r}=F(n);u.imgHeight=i,u.imgWidth=t,u.barHeight=g,u.barWidth=r,n.$parent.$emit("ready",n)})};X(()=>{V(),n.$el.onselectstart=function(){return!1}});const S=s(null),D=i=>{if(a.push(k(S,i)),o.value==z.value){o.value=P(k(S,i));const t=J(a,u);a.length=0,a.push(...t),setTimeout(()=>{const g=h.value?M(v.value+"---"+JSON.stringify(a),h.value):v.value+"---"+JSON.stringify(a),r={captchaType:e.value,captcha_code:h.value?M(JSON.stringify(a),h.value):JSON.stringify(a),captcha_key:v.value};K(r).then(W=>{W.code==1?(b.value="#4cae4c",x.value="#5cb85c",d.value="验证成功",C.value=!1,_.value=="pop"&&setTimeout(()=>{n.$parent.clickShow=!1,T()},1500),n.$parent.$emit("success",{captchaVerification:g})):(n.$parent.$emit("error",n),b.value="#d9534f",x.value="#d9534f",d.value="验证失败",setTimeout(()=>{T()},700))})},400)}o.value<z.value&&(o.value=P(k(S,i)))},k=function(i,t){const g=t.offsetX,r=t.offsetY;return{x:g,y:r}},P=function(i){return y.push(Object.assign({},i)),o.value+1},T=function(){y.splice(0,y.length),b.value="#000",x.value="#ddd",C.value=!0,p.splice(0,p.length),a.splice(0,a.length),o.value=1,B(),d.value="验证失败",j.value=!0};function B(){const i={captchaType:e.value};Y(i).then(t=>{t.code==1?(O.value=t.data.originalImageBase64,v.value=t.data.token,h.value=t.data.secretKey,w.value=t.data.wordList,d.value="请依次点击【"+w.value.join(",")+"】"):d.value=t.msg})}const J=function(i,t){return i.map(r=>{const W=Math.round(310*r.x/parseInt(t.imgWidth)),E=Math.round(155*r.y/parseInt(t.imgHeight));return{x:W,y:E}})};return{secretKey:h,checkNum:z,fontPos:p,checkPosArr:a,num:o,pointBackImgBase:O,pointTextList:w,backToken:v,setSize:u,tempPoints:y,text:d,barAreaColor:b,barAreaBorderColor:x,showRefresh:j,bindingClick:C,init:V,canvas:S,canvasClick:D,getMousePos:k,createPoint:P,refresh:T,getPictrue:B,pointTransfrom:J}}},ne={style:{position:"relative"}},se={class:"verify-img-out"},oe=l("i",{class:"iconfont icon-refresh"},null,-1),re=[oe],ce=["src"],le={class:"verify-msg"};function he(N,f,_,e,L,R){return H(),I("div",ne,[l("div",se,[l("div",{class:"verify-img-panel",style:A({width:e.setSize.imgWidth,height:e.setSize.imgHeight,"background-size":e.setSize.imgWidth+" "+e.setSize.imgHeight,"margin-bottom":_.vSpace+"px"})},[Q(l("div",{class:"verify-refresh",style:{"z-index":"3"},onClick:f[0]||(f[0]=(...c)=>e.refresh&&e.refresh(...c))},re,512),[[U,e.showRefresh]]),l("img",{src:"data:image/png;base64,"+e.pointBackImgBase,ref:"canvas",alt:"",style:{width:"100%",height:"100%",display:"block"},onClick:f[1]||(f[1]=c=>e.bindingClick?e.canvasClick(c):void 0)},null,8,ce),(H(!0),I($,null,ee(e.tempPoints,(c,n)=>(H(),I("div",{key:n,class:"point-area",style:A({"background-color":"#1abd6c",color:"#fff","z-index":9999,width:"20px",height:"20px","text-align":"center","line-height":"20px","border-radius":"50%",position:"absolute",top:parseInt(c.y-10)+"px",left:parseInt(c.x-10)+"px"})},q(n+1),5))),128))],4)]),l("div",{class:"verify-bar-area",style:A({width:e.setSize.imgWidth,color:this.barAreaColor,"border-color":this.barAreaBorderColor,"line-height":this.barSize.height})},[l("span",le,q(e.text),1)],4)])}const fe=ae(ie,[["render",he]]);export{fe as default};
|
|
||||||
1
niucloud/public/admin/assets/VerifyPoints-e2bb084a.js
Normal file
1
niucloud/public/admin/assets/VerifyPoints-e2bb084a.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{r as F,a as M,b as K,c as Y}from"./index-b4a6dc9f.js";import{P as Z,bd as G,r as s,q as m,aZ as X,h as H,c as I,a as l,y as A,Y as Q,Z as U,F as $,V as ee,t as q,ax as te}from"./index-8eead49b.js";import{_ as ae}from"./_plugin-vue_export-helper-c27b6911.js";const ie={name:"VerifyPoints",props:{mode:{type:String,default:"fixed"},captchaType:{type:String},vSpace:{type:Number,default:5},imgSize:{type:Object,default(){return{width:"310px",height:"155px"}}},barSize:{type:Object,default(){return{width:"310px",height:"40px"}}}},setup(N,f){const{mode:_,captchaType:e,vSpace:L,imgSize:R,barSize:c}=Z(N),{proxy:n}=G(),h=s(""),z=s(3),p=m([]),a=m([]),o=s(1),O=s(""),w=m([]),v=s(""),u=m({imgHeight:0,imgWidth:0,barHeight:0,barWidth:0}),y=m([]),d=s(""),b=s(void 0),x=s(void 0),j=s(!0),C=s(!0),V=()=>{p.splice(0,p.length),a.splice(0,a.length),o.value=1,B(),te(()=>{const{imgHeight:i,imgWidth:t,barHeight:g,barWidth:r}=F(n);u.imgHeight=i,u.imgWidth=t,u.barHeight=g,u.barWidth=r,n.$parent.$emit("ready",n)})};X(()=>{V(),n.$el.onselectstart=function(){return!1}});const S=s(null),D=i=>{if(a.push(k(S,i)),o.value==z.value){o.value=P(k(S,i));const t=J(a,u);a.length=0,a.push(...t),setTimeout(()=>{const g=h.value?M(v.value+"---"+JSON.stringify(a),h.value):v.value+"---"+JSON.stringify(a),r={captchaType:e.value,captcha_code:h.value?M(JSON.stringify(a),h.value):JSON.stringify(a),captcha_key:v.value};K(r).then(W=>{W.code==1?(b.value="#4cae4c",x.value="#5cb85c",d.value="验证成功",C.value=!1,_.value=="pop"&&setTimeout(()=>{n.$parent.clickShow=!1,T()},1500),n.$parent.$emit("success",{captchaVerification:g})):(n.$parent.$emit("error",n),b.value="#d9534f",x.value="#d9534f",d.value="验证失败",setTimeout(()=>{T()},700))})},400)}o.value<z.value&&(o.value=P(k(S,i)))},k=function(i,t){const g=t.offsetX,r=t.offsetY;return{x:g,y:r}},P=function(i){return y.push(Object.assign({},i)),o.value+1},T=function(){y.splice(0,y.length),b.value="#000",x.value="#ddd",C.value=!0,p.splice(0,p.length),a.splice(0,a.length),o.value=1,B(),d.value="验证失败",j.value=!0};function B(){const i={captchaType:e.value};Y(i).then(t=>{t.code==1?(O.value=t.data.originalImageBase64,v.value=t.data.token,h.value=t.data.secretKey,w.value=t.data.wordList,d.value="请依次点击【"+w.value.join(",")+"】"):d.value=t.msg})}const J=function(i,t){return i.map(r=>{const W=Math.round(310*r.x/parseInt(t.imgWidth)),E=Math.round(155*r.y/parseInt(t.imgHeight));return{x:W,y:E}})};return{secretKey:h,checkNum:z,fontPos:p,checkPosArr:a,num:o,pointBackImgBase:O,pointTextList:w,backToken:v,setSize:u,tempPoints:y,text:d,barAreaColor:b,barAreaBorderColor:x,showRefresh:j,bindingClick:C,init:V,canvas:S,canvasClick:D,getMousePos:k,createPoint:P,refresh:T,getPictrue:B,pointTransfrom:J}}},ne={style:{position:"relative"}},se={class:"verify-img-out"},oe=l("i",{class:"iconfont icon-refresh"},null,-1),re=[oe],ce=["src"],le={class:"verify-msg"};function he(N,f,_,e,L,R){return H(),I("div",ne,[l("div",se,[l("div",{class:"verify-img-panel",style:A({width:e.setSize.imgWidth,height:e.setSize.imgHeight,"background-size":e.setSize.imgWidth+" "+e.setSize.imgHeight,"margin-bottom":_.vSpace+"px"})},[Q(l("div",{class:"verify-refresh",style:{"z-index":"3"},onClick:f[0]||(f[0]=(...c)=>e.refresh&&e.refresh(...c))},re,512),[[U,e.showRefresh]]),l("img",{src:"data:image/png;base64,"+e.pointBackImgBase,ref:"canvas",alt:"",style:{width:"100%",height:"100%",display:"block"},onClick:f[1]||(f[1]=c=>e.bindingClick?e.canvasClick(c):void 0)},null,8,ce),(H(!0),I($,null,ee(e.tempPoints,(c,n)=>(H(),I("div",{key:n,class:"point-area",style:A({"background-color":"#1abd6c",color:"#fff","z-index":9999,width:"20px",height:"20px","text-align":"center","line-height":"20px","border-radius":"50%",position:"absolute",top:parseInt(c.y-10)+"px",left:parseInt(c.x-10)+"px"})},q(n+1),5))),128))],4)]),l("div",{class:"verify-bar-area",style:A({width:e.setSize.imgWidth,color:this.barAreaColor,"border-color":this.barAreaBorderColor,"line-height":this.barSize.height})},[l("span",le,q(e.text),1)],4)])}const fe=ae(ie,[["render",he]]);export{fe as default};
|
||||||
1
niucloud/public/admin/assets/VerifySlide-02eb59d1.js
Normal file
1
niucloud/public/admin/assets/VerifySlide-02eb59d1.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
import{d as V,k as B,u as N,r as x,aZ as S,h as T,c as j,e as o,w as s,a as t,t as n,f as e,s as a,i as h,B as I,aH as R,aI as $,E as q,a_ as D,a$ as F,b0 as H,K,b1 as M,a8 as P}from"./index-42af2821.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as Q}from"./aliapp-f3406b1b.js";const U={class:"main-container"},Z={class:"flex justify-between items-center"},z={class:"text-page-title"},G={class:"p-[20px]"},J={class:"panel-title !text-sm"},L={class:"text-[14px] font-[700]"},O={class:"text-[#999]"},W={class:"mt-[20px] mb-[40px] h-[32px]"},X={class:"text-[14px] font-[700]"},Y={class:"text-[#999]"},tt={class:"mt-[20px] mb-[40px] h-[32px]"},et={class:"text-[14px] font-[700]"},st={class:"text-[#999]"},at=t("div",{class:"mt-[20px] mb-[40px] h-[32px]"},null,-1),ot={class:"text-[14px] font-[700]"},nt={class:"text-[#999]"},lt={class:"flex justify-center"},ct={class:"w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]"},pt={class:"mt-[22px] text-center"},it={class:"text-[12px]"},bt=V({__name:"access",setup(_t){const f=B(),d=N(),v=f.meta.title,_=x("/channel/aliapp"),p=x("");S(async()=>{const c=await Q();p.value=c.data.qr_code});const w=c=>{window.open(c,"_blank")},b=c=>{d.push({path:_.value})};return(c,l)=>{const g=R,C=$,m=q,i=D,E=F,u=H,y=K,k=M,A=P;return T(),j("div",U,[o(A,{class:"card !border-none",shadow:"never"},{default:s(()=>[t("div",Z,[t("span",z,n(e(v)),1)]),o(C,{modelValue:_.value,"onUpdate:modelValue":l[0]||(l[0]=r=>_.value=r),class:"my-[20px]",onTabChange:b},{default:s(()=>[o(g,{label:e(a)("weappAccessFlow"),name:"/channel/aliapp"},null,8,["label"])]),_:1},8,["modelValue"]),t("div",G,[t("h3",J,n(e(a)("weappInlet")),1),o(k,null,{default:s(()=>[o(u,{span:20},{default:s(()=>[o(E,{active:4,direction:"vertical"},{default:s(()=>[o(i,null,{title:s(()=>[t("p",L,n(e(a)("weappAttestation")),1)]),description:s(()=>[t("span",O,n(e(a)("weappAttest")),1),t("div",W,[o(m,{type:"primary",onClick:l[1]||(l[1]=r=>w("https://open.alipay.com/develop/manage"))},{default:s(()=>[h(n(e(a)("clickAccess")),1)]),_:1})])]),_:1}),o(i,null,{title:s(()=>[t("p",X,n(e(a)("weappSetting")),1)]),description:s(()=>[t("span",Y,n(e(a)("emplace")),1),t("div",tt,[o(m,{type:"primary",plain:"",onClick:l[2]||(l[2]=r=>e(d).push("/channel/aliapp/config"))},{default:s(()=>[h(n(e(a)("weappSettingBtn")),1)]),_:1})])]),_:1}),o(i,null,{title:s(()=>[t("p",et,n(e(a)("uploadVersion")),1)]),description:s(()=>[t("span",st,n(e(a)("releaseCourse")),1),at]),_:1}),o(i,null,{title:s(()=>[t("p",ot,n(e(a)("completeAccess")),1)]),description:s(()=>[t("span",nt,n(e(a)("releaseCourse")),1)]),_:1})]),_:1})]),_:1}),o(u,{span:4},{default:s(()=>[t("div",lt,[o(y,{class:"w-[180px] h-[180px]",src:p.value?e(I)(p.value):""},{error:s(()=>[t("div",ct,[t("span",null,n(p.value?e(a)("fileErr"):e(a)("emptyQrCode")),1)])]),_:1},8,["src"])]),t("div",pt,[t("p",it,n(e(a)("clickAccess2")),1)])]),_:1})]),_:1})])]),_:1})])}}});export{bt as default};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
import{d as B,k as T,u as $,r as c,aZ as I,b6 as M,o as R,h as W,c as q,e,w as t,a as s,t as o,f as n,s as a,i as u,aH as A,aI as L,E as U,a_ as j,a$ as D,b0 as F,b1 as G,a8 as H}from"./index-42af2821.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as P}from"./wechat-6fe57299.js";const Z={class:"main-container"},z={class:"flex justify-between items-center"},J={class:"text-page-title"},K={class:"p-[20px]"},O={class:"panel-title !text-sm"},Q={class:"text-[14px] font-[700]"},X={class:"text-[#999]"},Y={class:"mt-[20px] mb-[40px] h-[32px]"},tt={class:"text-[14px] font-[700]"},et={class:"mt-[20px] mb-[40px] h-[32px]"},nt={class:"text-[14px] font-[700]"},st={class:"mt-[20px] mb-[40px] h-[32px]"},dt=B({__name:"access",setup(at){const f=T(),_=$(),x=f.meta.title,r=c("/channel/app"),b=c(""),g=c({}),w=c({}),h=async()=>{await P().then(({data:l})=>{g.value=l,b.value=l.qr_code})};I(async()=>{await h(),await M().then(({data:l})=>{w.value=l}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&h()})}),R(()=>{document.removeEventListener("visibilitychange",()=>{})});const y=l=>{window.open(l,"_blank")},C=l=>{_.push({path:r.value})};return(l,i)=>{const v=A,E=L,d=U,m=j,k=D,V=F,S=G,N=H;return W(),q("div",Z,[e(N,{class:"card !border-none",shadow:"never"},{default:t(()=>[s("div",z,[s("span",J,o(n(x)),1)]),e(E,{modelValue:r.value,"onUpdate:modelValue":i[0]||(i[0]=p=>r.value=p),class:"my-[20px]",onTabChange:C},{default:t(()=>[e(v,{label:n(a)("accessFlow"),name:"/channel/app"},null,8,["label"]),e(v,{label:n(a)("versionManage"),name:"/channel/app/version"},null,8,["label"])]),_:1},8,["modelValue"]),s("div",K,[s("h3",O,o(n(a)("appInlet")),1),e(S,null,{default:t(()=>[e(V,{span:20},{default:t(()=>[e(k,{class:"!mt-[10px]",active:3,direction:"vertical"},{default:t(()=>[e(m,null,{title:t(()=>[s("p",Q,o(n(a)("uniappApp")),1)]),description:t(()=>[s("span",X,o(n(a)("appAttestation1")),1),s("div",Y,[e(d,{type:"primary",onClick:i[1]||(i[1]=p=>y("https://dcloud.io/"))},{default:t(()=>[u(o(n(a)("toCreate")),1)]),_:1})])]),_:1}),e(m,null,{title:t(()=>[s("p",tt,o(n(a)("appSetting")),1)]),description:t(()=>[s("div",et,[e(d,{type:"primary",onClick:i[2]||(i[2]=p=>n(_).push("/channel/app/config"))},{default:t(()=>[u(o(n(a)("settingInfo")),1)]),_:1})])]),_:1}),e(m,null,{title:t(()=>[s("p",nt,o(n(a)("versionManage")),1)]),description:t(()=>[s("div",st,[e(d,{type:"primary",plain:"",onClick:i[3]||(i[3]=p=>n(_).push("/channel/app/version"))},{default:t(()=>[u(o(n(a)("releaseVersion")),1)]),_:1})])]),_:1})]),_:1})]),_:1})]),_:1})])]),_:1})])}}});export{dt as default};
|
|
||||||
1
niucloud/public/admin/assets/access-25e8e612.js
Normal file
1
niucloud/public/admin/assets/access-25e8e612.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{d as $,k as q,u as j,r as u,aZ as F,b6 as I,o as R,h as w,c as y,e as a,w as s,a as n,t as o,f as e,s as t,i as r,F as U,v as z,B as L,aH as M,aI as D,E as G,a_ as H,a$ as K,b0 as P,K as Q,b1 as Z,a8 as J}from"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as O}from"./wechat-cb4e6ea9.js";import{a as X}from"./wxoplatform-105b4bfa.js";const Y={class:"main-container"},ee={class:"flex justify-between items-center"},te={class:"text-page-title"},ae={class:"p-[20px]"},se={class:"panel-title !text-sm"},ne={class:"text-[14px] font-[700]"},oe={class:"text-[#999]"},le={class:"mt-[20px] mb-[40px] h-[32px]"},ce={class:"text-[14px] font-[700]"},ie={class:"text-[#999]"},pe={class:"mt-[20px] mb-[40px] h-[32px]"},re={class:"text-[14px] font-[700]"},_e={class:"text-[#999]"},de={class:"mt-[20px] mb-[40px] h-[32px]"},me={class:"flex justify-center"},ue={class:"w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]"},he={class:"mt-[22px] text-center"},fe={class:"text-[12px]"},Be=$({__name:"access",setup(ve){const k=q(),_=j(),C=k.meta.title,h=u("/channel/wechat"),d=u(""),f=u({}),v=u({}),b=async()=>{await O().then(({data:l})=>{f.value=l,d.value=l.qr_code})};F(async()=>{await b(),await I().then(({data:l})=>{v.value=l}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&b()})}),R(()=>{document.removeEventListener("visibilitychange",()=>{})});const E=l=>{window.open(l,"_blank")},A=l=>{_.push({path:h.value})},S=()=>{X().then(({data:l})=>{window.open(l)})};return(l,c)=>{const m=M,B=D,i=G,x=H,V=K,g=P,N=Q,T=Z,W=J;return w(),y("div",Y,[a(W,{class:"card !border-none",shadow:"never"},{default:s(()=>[n("div",ee,[n("span",te,o(e(C)),1)]),a(B,{modelValue:h.value,"onUpdate:modelValue":c[0]||(c[0]=p=>h.value=p),class:"my-[20px]",onTabChange:A},{default:s(()=>[a(m,{label:e(t)("wechatAccessFlow"),name:"/channel/wechat"},null,8,["label"]),a(m,{label:e(t)("customMenu"),name:"/channel/wechat/menu"},null,8,["label"]),a(m,{label:e(t)("wechatTemplate"),name:"/channel/wechat/message"},null,8,["label"]),a(m,{label:e(t)("reply"),name:"/channel/wechat/reply"},null,8,["label"])]),_:1},8,["modelValue"]),n("div",ae,[n("h3",se,o(e(t)("wechatInlet")),1),a(T,null,{default:s(()=>[a(g,{span:20},{default:s(()=>[a(V,{class:"!mt-[10px]",active:3,direction:"vertical"},{default:s(()=>[a(x,null,{title:s(()=>[n("p",ne,o(e(t)("wechatAttestation")),1)]),description:s(()=>[n("span",oe,o(e(t)("wechatAttestation1")),1),n("div",le,[a(i,{type:"primary",onClick:c[1]||(c[1]=p=>E("https://mp.weixin.qq.com/"))},{default:s(()=>[r(o(e(t)("clickAccess")),1)]),_:1})])]),_:1}),a(x,null,{title:s(()=>[n("p",ce,o(e(t)("wechatSetting")),1)]),description:s(()=>[n("span",ie,o(e(t)("wechatSetting1")),1),n("div",pe,[v.value.app_id&&v.value.app_secret?(w(),y(U,{key:0},[a(i,{type:"primary",onClick:c[2]||(c[2]=p=>e(_).push("/channel/wechat/config"))},{default:s(()=>[r(o(f.value.app_id?e(t)("seeConfig"):e(t)("clickSetting")),1)]),_:1}),a(i,{type:"primary",plain:"",onClick:S},{default:s(()=>[r(o(f.value.is_authorization?e(t)("refreshAuth"):e(t)("authWechat")),1)]),_:1})],64)):(w(),z(i,{key:1,type:"primary",onClick:c[3]||(c[3]=p=>e(_).push("/channel/wechat/config"))},{default:s(()=>[r(o(e(t)("clickSetting")),1)]),_:1}))])]),_:1}),a(x,null,{title:s(()=>[n("p",re,o(e(t)("wechatAccess")),1)]),description:s(()=>[n("span",_e,o(e(t)("wechatAccess")),1),n("div",de,[a(i,{type:"primary",plain:"",onClick:c[4]||(c[4]=p=>e(_).push("/channel/wechat/course"))},{default:s(()=>[r(o(e(t)("releaseCourse")),1)]),_:1})])]),_:1})]),_:1})]),_:1}),a(g,{span:4},{default:s(()=>[n("div",me,[a(N,{class:"w-[180px] h-[180px]",src:d.value?e(L)(d.value):""},{error:s(()=>[n("div",ue,[n("span",null,o(d.value?e(t)("fileErr"):e(t)("emptyQrCode")),1)])]),_:1},8,["src"])]),n("div",he,[n("p",fe,o(e(t)("clickAccess2")),1)])]),_:1})]),_:1})])]),_:1})])}}});export{Be as default};
|
||||||
1
niucloud/public/admin/assets/access-4e12d8de.js
Normal file
1
niucloud/public/admin/assets/access-4e12d8de.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{d as V,k as B,u as N,r as x,aZ as S,h as T,c as j,e as o,w as s,a as t,t as n,f as e,s as a,i as h,B as I,aH as R,aI as $,E as q,a_ as D,a$ as F,b0 as H,K,b1 as M,a8 as P}from"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as Q}from"./aliapp-72a6151f.js";const U={class:"main-container"},Z={class:"flex justify-between items-center"},z={class:"text-page-title"},G={class:"p-[20px]"},J={class:"panel-title !text-sm"},L={class:"text-[14px] font-[700]"},O={class:"text-[#999]"},W={class:"mt-[20px] mb-[40px] h-[32px]"},X={class:"text-[14px] font-[700]"},Y={class:"text-[#999]"},tt={class:"mt-[20px] mb-[40px] h-[32px]"},et={class:"text-[14px] font-[700]"},st={class:"text-[#999]"},at=t("div",{class:"mt-[20px] mb-[40px] h-[32px]"},null,-1),ot={class:"text-[14px] font-[700]"},nt={class:"text-[#999]"},lt={class:"flex justify-center"},ct={class:"w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]"},pt={class:"mt-[22px] text-center"},it={class:"text-[12px]"},bt=V({__name:"access",setup(_t){const f=B(),d=N(),v=f.meta.title,_=x("/channel/aliapp"),p=x("");S(async()=>{const c=await Q();p.value=c.data.qr_code});const w=c=>{window.open(c,"_blank")},b=c=>{d.push({path:_.value})};return(c,l)=>{const g=R,C=$,m=q,i=D,E=F,u=H,y=K,k=M,A=P;return T(),j("div",U,[o(A,{class:"card !border-none",shadow:"never"},{default:s(()=>[t("div",Z,[t("span",z,n(e(v)),1)]),o(C,{modelValue:_.value,"onUpdate:modelValue":l[0]||(l[0]=r=>_.value=r),class:"my-[20px]",onTabChange:b},{default:s(()=>[o(g,{label:e(a)("weappAccessFlow"),name:"/channel/aliapp"},null,8,["label"])]),_:1},8,["modelValue"]),t("div",G,[t("h3",J,n(e(a)("weappInlet")),1),o(k,null,{default:s(()=>[o(u,{span:20},{default:s(()=>[o(E,{active:4,direction:"vertical"},{default:s(()=>[o(i,null,{title:s(()=>[t("p",L,n(e(a)("weappAttestation")),1)]),description:s(()=>[t("span",O,n(e(a)("weappAttest")),1),t("div",W,[o(m,{type:"primary",onClick:l[1]||(l[1]=r=>w("https://open.alipay.com/develop/manage"))},{default:s(()=>[h(n(e(a)("clickAccess")),1)]),_:1})])]),_:1}),o(i,null,{title:s(()=>[t("p",X,n(e(a)("weappSetting")),1)]),description:s(()=>[t("span",Y,n(e(a)("emplace")),1),t("div",tt,[o(m,{type:"primary",plain:"",onClick:l[2]||(l[2]=r=>e(d).push("/channel/aliapp/config"))},{default:s(()=>[h(n(e(a)("weappSettingBtn")),1)]),_:1})])]),_:1}),o(i,null,{title:s(()=>[t("p",et,n(e(a)("uploadVersion")),1)]),description:s(()=>[t("span",st,n(e(a)("releaseCourse")),1),at]),_:1}),o(i,null,{title:s(()=>[t("p",ot,n(e(a)("completeAccess")),1)]),description:s(()=>[t("span",nt,n(e(a)("releaseCourse")),1)]),_:1})]),_:1})]),_:1}),o(u,{span:4},{default:s(()=>[t("div",lt,[o(y,{class:"w-[180px] h-[180px]",src:p.value?e(I)(p.value):""},{error:s(()=>[t("div",ct,[t("span",null,n(p.value?e(a)("fileErr"):e(a)("emptyQrCode")),1)])]),_:1},8,["src"])]),t("div",pt,[t("p",it,n(e(a)("clickAccess2")),1)])]),_:1})]),_:1})])]),_:1})])}}});export{bt as default};
|
||||||
@ -1 +0,0 @@
|
|||||||
import{d as $,k as q,u as j,r as u,aZ as F,b6 as I,o as R,h as w,c as y,e as a,w as s,a as n,t as o,f as e,s as t,i as r,F as U,v as z,B as L,aH as M,aI as D,E as G,a_ as H,a$ as K,b0 as P,K as Q,b1 as Z,a8 as J}from"./index-42af2821.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as O}from"./wechat-6fe57299.js";import{a as X}from"./wxoplatform-2136ae22.js";const Y={class:"main-container"},ee={class:"flex justify-between items-center"},te={class:"text-page-title"},ae={class:"p-[20px]"},se={class:"panel-title !text-sm"},ne={class:"text-[14px] font-[700]"},oe={class:"text-[#999]"},le={class:"mt-[20px] mb-[40px] h-[32px]"},ce={class:"text-[14px] font-[700]"},ie={class:"text-[#999]"},pe={class:"mt-[20px] mb-[40px] h-[32px]"},re={class:"text-[14px] font-[700]"},_e={class:"text-[#999]"},de={class:"mt-[20px] mb-[40px] h-[32px]"},me={class:"flex justify-center"},ue={class:"w-[100%] h-[100%] flex items-center justify-center bg-[#f5f7fa]"},he={class:"mt-[22px] text-center"},fe={class:"text-[12px]"},Be=$({__name:"access",setup(ve){const k=q(),_=j(),C=k.meta.title,h=u("/channel/wechat"),d=u(""),f=u({}),v=u({}),b=async()=>{await O().then(({data:l})=>{f.value=l,d.value=l.qr_code})};F(async()=>{await b(),await I().then(({data:l})=>{v.value=l}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&b()})}),R(()=>{document.removeEventListener("visibilitychange",()=>{})});const E=l=>{window.open(l,"_blank")},A=l=>{_.push({path:h.value})},S=()=>{X().then(({data:l})=>{window.open(l)})};return(l,c)=>{const m=M,B=D,i=G,x=H,V=K,g=P,N=Q,T=Z,W=J;return w(),y("div",Y,[a(W,{class:"card !border-none",shadow:"never"},{default:s(()=>[n("div",ee,[n("span",te,o(e(C)),1)]),a(B,{modelValue:h.value,"onUpdate:modelValue":c[0]||(c[0]=p=>h.value=p),class:"my-[20px]",onTabChange:A},{default:s(()=>[a(m,{label:e(t)("wechatAccessFlow"),name:"/channel/wechat"},null,8,["label"]),a(m,{label:e(t)("customMenu"),name:"/channel/wechat/menu"},null,8,["label"]),a(m,{label:e(t)("wechatTemplate"),name:"/channel/wechat/message"},null,8,["label"]),a(m,{label:e(t)("reply"),name:"/channel/wechat/reply"},null,8,["label"])]),_:1},8,["modelValue"]),n("div",ae,[n("h3",se,o(e(t)("wechatInlet")),1),a(T,null,{default:s(()=>[a(g,{span:20},{default:s(()=>[a(V,{class:"!mt-[10px]",active:3,direction:"vertical"},{default:s(()=>[a(x,null,{title:s(()=>[n("p",ne,o(e(t)("wechatAttestation")),1)]),description:s(()=>[n("span",oe,o(e(t)("wechatAttestation1")),1),n("div",le,[a(i,{type:"primary",onClick:c[1]||(c[1]=p=>E("https://mp.weixin.qq.com/"))},{default:s(()=>[r(o(e(t)("clickAccess")),1)]),_:1})])]),_:1}),a(x,null,{title:s(()=>[n("p",ce,o(e(t)("wechatSetting")),1)]),description:s(()=>[n("span",ie,o(e(t)("wechatSetting1")),1),n("div",pe,[v.value.app_id&&v.value.app_secret?(w(),y(U,{key:0},[a(i,{type:"primary",onClick:c[2]||(c[2]=p=>e(_).push("/channel/wechat/config"))},{default:s(()=>[r(o(f.value.app_id?e(t)("seeConfig"):e(t)("clickSetting")),1)]),_:1}),a(i,{type:"primary",plain:"",onClick:S},{default:s(()=>[r(o(f.value.is_authorization?e(t)("refreshAuth"):e(t)("authWechat")),1)]),_:1})],64)):(w(),z(i,{key:1,type:"primary",onClick:c[3]||(c[3]=p=>e(_).push("/channel/wechat/config"))},{default:s(()=>[r(o(e(t)("clickSetting")),1)]),_:1}))])]),_:1}),a(x,null,{title:s(()=>[n("p",re,o(e(t)("wechatAccess")),1)]),description:s(()=>[n("span",_e,o(e(t)("wechatAccess")),1),n("div",de,[a(i,{type:"primary",plain:"",onClick:c[4]||(c[4]=p=>e(_).push("/channel/wechat/course"))},{default:s(()=>[r(o(e(t)("releaseCourse")),1)]),_:1})])]),_:1})]),_:1})]),_:1}),a(g,{span:4},{default:s(()=>[n("div",me,[a(N,{class:"w-[180px] h-[180px]",src:d.value?e(L)(d.value):""},{error:s(()=>[n("div",ue,[n("span",null,o(d.value?e(t)("fileErr"):e(t)("emptyQrCode")),1)])]),_:1},8,["src"])]),n("div",he,[n("p",fe,o(e(t)("clickAccess2")),1)])]),_:1})]),_:1})])]),_:1})])}}});export{Be as default};
|
|
||||||
1
niucloud/public/admin/assets/access-61851911.js
Normal file
1
niucloud/public/admin/assets/access-61851911.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{d as B,k as T,u as $,r as c,aZ as I,b6 as M,o as R,h as W,c as q,e,w as t,a as s,t as o,f as n,s as a,i as u,aH as A,aI as L,E as U,a_ as j,a$ as D,b0 as F,b1 as G,a8 as H}from"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import{g as P}from"./wechat-cb4e6ea9.js";const Z={class:"main-container"},z={class:"flex justify-between items-center"},J={class:"text-page-title"},K={class:"p-[20px]"},O={class:"panel-title !text-sm"},Q={class:"text-[14px] font-[700]"},X={class:"text-[#999]"},Y={class:"mt-[20px] mb-[40px] h-[32px]"},tt={class:"text-[14px] font-[700]"},et={class:"mt-[20px] mb-[40px] h-[32px]"},nt={class:"text-[14px] font-[700]"},st={class:"mt-[20px] mb-[40px] h-[32px]"},dt=B({__name:"access",setup(at){const f=T(),_=$(),x=f.meta.title,r=c("/channel/app"),b=c(""),g=c({}),w=c({}),h=async()=>{await P().then(({data:l})=>{g.value=l,b.value=l.qr_code})};I(async()=>{await h(),await M().then(({data:l})=>{w.value=l}),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"&&h()})}),R(()=>{document.removeEventListener("visibilitychange",()=>{})});const y=l=>{window.open(l,"_blank")},C=l=>{_.push({path:r.value})};return(l,i)=>{const v=A,E=L,d=U,m=j,k=D,V=F,S=G,N=H;return W(),q("div",Z,[e(N,{class:"card !border-none",shadow:"never"},{default:t(()=>[s("div",z,[s("span",J,o(n(x)),1)]),e(E,{modelValue:r.value,"onUpdate:modelValue":i[0]||(i[0]=p=>r.value=p),class:"my-[20px]",onTabChange:C},{default:t(()=>[e(v,{label:n(a)("accessFlow"),name:"/channel/app"},null,8,["label"]),e(v,{label:n(a)("versionManage"),name:"/channel/app/version"},null,8,["label"])]),_:1},8,["modelValue"]),s("div",K,[s("h3",O,o(n(a)("appInlet")),1),e(S,null,{default:t(()=>[e(V,{span:20},{default:t(()=>[e(k,{class:"!mt-[10px]",active:3,direction:"vertical"},{default:t(()=>[e(m,null,{title:t(()=>[s("p",Q,o(n(a)("uniappApp")),1)]),description:t(()=>[s("span",X,o(n(a)("appAttestation1")),1),s("div",Y,[e(d,{type:"primary",onClick:i[1]||(i[1]=p=>y("https://dcloud.io/"))},{default:t(()=>[u(o(n(a)("toCreate")),1)]),_:1})])]),_:1}),e(m,null,{title:t(()=>[s("p",tt,o(n(a)("appSetting")),1)]),description:t(()=>[s("div",et,[e(d,{type:"primary",onClick:i[2]||(i[2]=p=>n(_).push("/channel/app/config"))},{default:t(()=>[u(o(n(a)("settingInfo")),1)]),_:1})])]),_:1}),e(m,null,{title:t(()=>[s("p",nt,o(n(a)("versionManage")),1)]),description:t(()=>[s("div",st,[e(d,{type:"primary",plain:"",onClick:i[3]||(i[3]=p=>n(_).push("/channel/app/version"))},{default:t(()=>[u(o(n(a)("releaseVersion")),1)]),_:1})])]),_:1})]),_:1})]),_:1})]),_:1})])]),_:1})])}}});export{dt as default};
|
||||||
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/access-cf866f9d.js
Normal file
1
niucloud/public/admin/assets/access-cf866f9d.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/account-8a79bbdc.js
Normal file
1
niucloud/public/admin/assets/account-8a79bbdc.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/active-132d6527.js
Normal file
1
niucloud/public/admin/assets/active-132d6527.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{b5 as t}from"./index-8eead49b.js";function r(e){return t.get("relay/pages",{params:e})}function o(){return t.get("relay/init")}function n(e){return t.get("diy/list",{params:e})}function u(e){return t.post("relay/batch_set",e,{showSuccessMessage:!0})}function l(e){return t.post("relay/add",e,{showSuccessMessage:!0})}function c(e){return t.put(`relay/edit/${e.id}`,e,{showSuccessMessage:!0})}function y(e){return t.get(`relay/detail/${e}`)}function i(){return t.get("relay/share")}function g(e){return t.put(`relay/close/${e}`,{showSuccessMessage:!0})}function d(e){return t.delete(`relay/delete/${e}`,{showSuccessMessage:!0})}function f(){return t.get("relay/goods_of_select_source")}function R(e,a){return t.get(`relay/goods_of_select/${e}`,{params:a})}function h(e){return t.get("relay/stat/total",{params:e})}function S(e){return t.get("relay/stat/day",{params:e})}function p(e){return t.get("relay/stat/hour",{params:e})}function w(e){return t.get("relay/stat/channel",{params:e})}function M(e){return t.get("relay/diy/goods",{params:e})}function _(e){return t.get("relay/receive_list",{params:e})}function m(e){return t.post("relay/code/import",e,{showSuccessMessage:!0})}function C(e){return t.post("relay/code/delete",e,{showSuccessMessage:!0})}function $(e){return t.post("relay/code/clear",e,{showSuccessMessage:!0})}export{y as a,_ as b,$ as c,m as d,u as e,n as f,M as g,f as h,R as i,i as j,o as k,c as l,l as m,r as n,d as o,g as p,S as q,C as r,w as s,h as t,p as u};
|
||||||
1
niucloud/public/admin/assets/active-a803f547.js
Normal file
1
niucloud/public/admin/assets/active-a803f547.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{b5 as t}from"./index-8eead49b.js";function s(e){return t.get("friend_help/pages",{params:e})}function i(){return t.get("friend_help/init")}function o(e){return t.get("diy/list",{params:e})}function d(e){return t.post("friend_help/batch_set",e,{showSuccessMessage:!0})}function u(e){return t.post("friend_help/add",e,{showSuccessMessage:!0})}function l(e){return t.put(`friend_help/edit/${e.id}`,e,{showSuccessMessage:!0})}function a(e){return t.get(`friend_help/detail/${e}`)}function c(){return t.get("friend_help/share")}function p(e){return t.put(`friend_help/close/${e}`,{showSuccessMessage:!0})}function f(e){return t.delete(`friend_help/delete/${e}`,{showSuccessMessage:!0})}function g(){return t.get("friend_help/goods_of_select_source")}function h(e,n){return t.get(`friend_help/goods_of_select/${e}`,{params:n})}function _(e){return t.get("friend_help/stat/total",{params:e})}function H(e){return t.get("friend_help/stat/day",{params:e})}function F(e){return t.get("friend_help/stat/hour",{params:e})}function S(e){return t.get("friend_help/stat/channel",{params:e})}function w(e){return t.get("friend_help/diy/goods",{params:e})}function M(e){return t.get("friend_help/receive_list",{params:e})}function m(e){return t.post("friend_help/code/import",e,{showSuccessMessage:!0})}function y(e){return t.post("friend_help/code/delete",e,{showSuccessMessage:!0})}function C(e){return t.post("friend_help/code/clear",e,{showSuccessMessage:!0})}export{a,o as b,M as c,C as d,m as e,y as f,w as g,d as h,g as i,h as j,c as k,i as l,l as m,u as n,s as o,f as p,p as q,H as r,S as s,_ as t,F as u};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./active-detail-popup.vue_vue_type_script_setup_true_lang-6b999cc5.js";import"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-tooltip-4ed993c7.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-form-item-4ed993c7.js";/* empty css */import"./goods_default-247a7f2b.js";import"./active-a803f547.js";export{o as default};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./active-detail-popup.vue_vue_type_script_setup_true_lang-5aee9bbd.js";import"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-tooltip-4ed993c7.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-form-item-4ed993c7.js";/* empty css */import"./goods_default-995568ac.js";import"./active-f3a52d93.js";export{o as default};
|
||||||
@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./active-detail-popup.vue_vue_type_script_setup_true_lang-20981cd7.js";import"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-tooltip-4ed993c7.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-form-item-4ed993c7.js";/* empty css */import"./goods_default-664bb559.js";import"./active-132d6527.js";export{o as default};
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/active-dfc9a127.js
Normal file
1
niucloud/public/admin/assets/active-dfc9a127.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{b5 as t}from"./index-8eead49b.js";function l(e){return t.get("seckill/lists",{params:e})}function c(e){return t.get(`seckill/info/${e}`)}function i(e){return t.post("seckill/add",e,{showSuccessMessage:!0})}function o(e){return t.post("seckill/close",e,{showSuccessMessage:!0})}function n(e){return t.put(`seckill/edit/${e.id}`,e,{showSuccessMessage:!0})}function u(e){return t.post("seckill/delete",e,{showSuccessMessage:!0})}function r(){return t.get("seckill/init")}function a(){return t.get("seckill/select")}function k(e){return t.get("seckill/stat/total",{params:e})}function g(e){return t.get("seckill/stat/day",{params:e})}function S(e){return t.get("seckill/stat/hour",{params:e})}function d(e){return t.get("seckill/stat/channel",{params:e})}function f(e){return t.get("seckill/time/select",{params:e})}function h(e){return t.get("seckill/activeGoods/select",{params:e})}function p(e){return t.get("seckill/goods/receive_list",{params:e})}function w(e){return t.post("seckill/goods/code/import",e,{showSuccessMessage:!0})}function M(e){return t.post("seckill/goods/code/delete",e,{showSuccessMessage:!0})}function m(e){return t.post("seckill/goods/code/clear",e,{showSuccessMessage:!0})}export{p as a,m as b,w as c,c as d,r as e,n as f,a as g,i as h,l as i,u as j,o as k,g as l,d as m,f as n,h as o,k as p,S as q,M as s};
|
||||||
1
niucloud/public/admin/assets/active-f3a52d93.js
Normal file
1
niucloud/public/admin/assets/active-f3a52d93.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{b5 as n}from"./index-8eead49b.js";function a(t){return n.get("pintuan/pages",{params:t})}function s(){return n.get("pintuan/init")}function i(t){return n.get("diy/list",{params:t})}function o(t){return n.post("pintuan/batch_set",t,{showSuccessMessage:!0})}function r(t){return n.post("pintuan/add",t,{showSuccessMessage:!0})}function c(t){return n.put(`pintuan/edit/${t.id}`,t,{showSuccessMessage:!0})}function g(t){return n.get(`pintuan/detail/${t}`)}function p(){return n.get("pintuan/share")}function d(t){return n.put(`pintuan/close/${t}`,{showSuccessMessage:!0})}function f(t){return n.delete(`pintuan/delete/${t}`,{showSuccessMessage:!0})}function l(){return n.get("pintuan/goods_of_select_source")}function h(t,e){return n.get(`pintuan/goods_of_select/${t}`,{params:e})}function P(t){return n.get("pintuan/stat/total",{params:t})}function S(t){return n.get("pintuan/stat/day",{params:t})}function w(t){return n.get("pintuan/stat/hour",{params:t})}function M(t){return n.get("pintuan/stat/channel",{params:t})}function _(t){return n.get("pintuan/diy/goods",{params:t})}function m(t){return n.get("pintuan/receive_list",{params:t})}function y(t){return n.post("pintuan/code/import",t,{showSuccessMessage:!0})}function C(t){return n.post("pintuan/code/delete",t,{showSuccessMessage:!0})}function $(t){return n.post("pintuan/code/clear",t,{showSuccessMessage:!0})}export{g as a,i as b,m as c,$ as d,y as e,o as f,_ as g,l as h,h as i,p as j,s as k,c as l,r as m,a as n,f as o,C as p,d as q,S as r,M as s,P as t,w as u};
|
||||||
1
niucloud/public/admin/assets/active.edit-511741ad.js
Normal file
1
niucloud/public/admin/assets/active.edit-511741ad.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/active.edit-66a82aae.js
Normal file
1
niucloud/public/admin/assets/active.edit-66a82aae.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/active.edit-b0e69387.js
Normal file
1
niucloud/public/admin/assets/active.edit-b0e69387.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/active.list-659081d5.js
Normal file
1
niucloud/public/admin/assets/active.list-659081d5.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
const e="活动名称",t="请输入活动名称",l="活动规则说明",c="请输入活动规则说明",a="活动开始时间",s="请输入活动开始时间",o="活动结束时间",i="请输入活动结束时间",r="排序",d="请输入排序",n="活动状态",m="创建时间",k="请输入创建时间",T="更新时间",h="请输入更新时间",P="添加秒杀活动",p="编辑秒杀活动",u="确定要删除该数据吗?",D="请选择开始时间",N="请选择结束时间",R={seckillName:e,seckillNamePlaceholder:t,seckillRemark:l,seckillRemarkPlaceholder:c,startTime:a,startTimePlaceholder:s,endTime:o,endTimePlaceholder:i,sort:r,sortPlaceholder:d,status:n,createTime:m,createTimePlaceholder:k,updateTime:T,updateTimePlaceholder:h,addSeckill:P,updateSeckill:p,seckillDeleteTips:u,startDate:D,endDate:N};export{P as addSeckill,m as createTime,k as createTimePlaceholder,R as default,N as endDate,o as endTime,i as endTimePlaceholder,u as seckillDeleteTips,e as seckillName,t as seckillNamePlaceholder,l as seckillRemark,c as seckillRemarkPlaceholder,r as sort,d as sortPlaceholder,D as startDate,a as startTime,s as startTimePlaceholder,n as status,p as updateSeckill,T as updateTime,h as updateTimePlaceholder};
|
||||||
1
niucloud/public/admin/assets/add-038c4f20.js
Normal file
1
niucloud/public/admin/assets/add-038c4f20.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/add-164a0794.css
Normal file
1
niucloud/public/admin/assets/add-164a0794.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
input[data-v-88eb0e7f]::-webkit-outer-spin-button,input[data-v-88eb0e7f]::-webkit-inner-spin-button{-webkit-appearance:none!important;-moz-appearance:none!important;-o-appearance:none!important;appearance:none!important;margin:0}input[type=number][data-v-88eb0e7f]{-webkit-appearance:textfield;-moz-appearance:textfield;-o-appearance:textfield;appearance:textfield}.sku-form-item-wrap[data-v-88eb0e7f] .el-form-item__content{margin-left:0!important}.sku_list[data-v-88eb0e7f] .cell{overflow:initial!important}
|
||||||
1
niucloud/public/admin/assets/add-6e4b2d15.js
Normal file
1
niucloud/public/admin/assets/add-6e4b2d15.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/add-ab6f8ea6.js
Normal file
1
niucloud/public/admin/assets/add-ab6f8ea6.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/add-address-0f281edf.css
Normal file
1
niucloud/public/admin/assets/add-address-0f281edf.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
#AddressMap[data-v-4566f2d4]{border:1px solid #e4e4e4;border-radius:4px}
|
||||||
1
niucloud/public/admin/assets/add-address-69247f16.js
Normal file
1
niucloud/public/admin/assets/add-address-69247f16.js
Normal file
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/add-address-94b3d2eb.js
Normal file
1
niucloud/public/admin/assets/add-address-94b3d2eb.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{_ as o}from"./add-address.vue_vue_type_script_setup_true_lang-aadfa2f5.js";import"./index-8eead49b.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */import"./el-form-item-4ed993c7.js";import"./member-9b1f7f51.js";export{o as default};
|
||||||
File diff suppressed because one or more lines are too long
1
niucloud/public/admin/assets/add-cd275833.css
Normal file
1
niucloud/public/admin/assets/add-cd275833.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
.member-table[data-v-3e94f3c8] .cell{padding:0 12px!important}#TxMap[data-v-3e94f3c8]{border:1px solid #e4e4e4;border-radius:4px}.dialog-footer[data-v-3e94f3c8]{display:flex;justify-content:flex-end;gap:10px;margin-top:20px}.input-width[data-v-3e94f3c8]{width:500px}.fixed-footer-wrap .fixed-footer[data-v-3e94f3c8]{z-index:1999!important}
|
||||||
1
niucloud/public/admin/assets/add-d28d74b3.js
Normal file
1
niucloud/public/admin/assets/add-d28d74b3.js
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
|||||||
|
.spec-wrap[data-v-f9075805]{flex:1}.spec-wrap .spec-edit-list .spec-item[data-v-f9075805]{background:#f7f7f7;padding:20px;margin-bottom:20px;position:relative;border-radius:6px}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap[data-v-f9075805]{padding:25px 30px 0;position:relative}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap ul[data-v-f9075805]{display:flex;flex-wrap:wrap;flex:1;align-items:baseline}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap ul li[data-v-f9075805]{margin:0 10px 10px 0;position:relative}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap ul li .input-width[data-v-f9075805]{width:200px}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap ul li .icon[data-v-f9075805]{width:32px;padding:0;display:none;position:absolute;top:-12px;right:-20px;cursor:pointer}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap ul li:hover .icon[data-v-f9075805]{display:block}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap .add-spec-value[data-v-f9075805]{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.spec-wrap .spec-edit-list .spec-item .spec-value-wrap .box[data-v-f9075805]{position:absolute;top:0;left:10px;width:20px;height:40px;border:1px solid #b8b9bd;border-top:none;border-right:none}.spec-wrap .spec-edit-list .spec-item .del-spec[data-v-f9075805]{border:none;position:absolute;top:10px;right:10px;display:none;cursor:pointer}.spec-wrap .spec-edit-list .spec-item:hover .del-spec[data-v-f9075805]{display:block}.el-input__suffix[data-v-f9075805]{cursor:pointer}.el-table__row[data-v-f9075805]:focus{outline:none!important}.add-spec[data-v-f9075805]{margin-bottom:16px}.batch-operation-sku[data-v-f9075805]{display:flex;margin-bottom:16px;background-color:#fff;flex-wrap:nowrap;align-items:center}.batch-operation-sku label[data-v-f9075805]{font-size:14px;margin-right:10px}.batch-operation-sku .set-spec-select[data-v-f9075805]{margin-right:10px;max-width:130px}.batch-operation-sku .set-input[data-v-f9075805]{max-width:130px;min-width:60px;margin-right:10px}.editor-width[data-v-f9075805]{width:990px}.sku-table[data-v-f9075805] :focus{outline:none}.sku-form-item-wrap[data-v-f9075805] .el-form-item__content{margin-left:0!important}.sku-table[data-v-f9075805] .el-table__cell .cell{overflow:initial!important}.fixed-footer[data-v-f9075805]{z-index:4}.edui-default .edui-editor{z-index:1!important}.el-cascader__tags.is-validate{right:30px!important}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user