Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,33 +256,32 @@

1. **克隆项目**
```bash
git clone https://github.com/codestyle-team/codestyle.git
git clone https://github.com/itxaiohanglover/codestyle
cd codestyle
```

2. **配置数据库**
```bash
# 创建数据库
mysql -u root -p
CREATE DATABASE codestyle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
mysql -u root -p你的密码 -e "CREATE DATABASE codestyle_admin DEFAULT CHARACTER SET utf8mb4 COLLATE
utf8mb4_unicode_ci;"

# 导入表结构和数据
mysql -u root -p你的密码 codestyle_admin < main_table.sql
mysql -u root -p你的密码 codestyle_admin < main_data.sql
```

# 导入初始化脚本
mysql -u root -p codestyle < docs/sql/init.sql
```

3. **配置应用**
```bash
# 修改后端配置
cd codestyle-admin/codestyle-server/src/main/resources
cp application-dev.yml.example application-dev.yml
# 编辑 application-dev.yml,配置数据库、Redis、ES 连接信息
编辑 application-dev.yml,将数据库密码改为 你的密码:
password: ${DB_PWD:你的密码}
```

4. **启动后端**
```bash
cd codestyle-admin
mvn clean package -DskipTests
java -jar codestyle-server/target/codestyle-server.jar
mvn clean package -DskipTests -Pfat-jar
java -jar codestyle-server/target/codestyle-admin.jar
```

5. **启动前端**
Expand All @@ -294,7 +293,8 @@

6. **访问应用**
- 前端地址:http://localhost:5173
- 后端地址:http://localhost:8080
- 后端地址:http://localhost:8000
- API文档:http://localhost:8000/doc.html
- 默认账号:admin / admin123

### Docker 部署
Expand Down
56 changes: 0 additions & 56 deletions codestyle-admin-web/src/types/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,7 @@ export {}

declare module 'vue' {
export interface GlobalComponents {
Avatar: typeof import('./../components/Avatar/index.vue')['default']
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
CellCopy: typeof import('./../components/CellCopy/index.vue')['default']
Chart: typeof import('./../components/Chart/index.vue')['default']
ColumnSetting: typeof import('./../components/GiTable/src/components/ColumnSetting.vue')['default']
CronForm: typeof import('./../components/GenCron/CronForm/index.vue')['default']
CronModal: typeof import('./../components/GenCron/CronModal/index.vue')['default']
DateRangePicker: typeof import('./../components/DateRangePicker/index.vue')['default']
DayForm: typeof import('./../components/GenCron/CronForm/component/day-form.vue')['default']
FilePreview: typeof import('./../components/FilePreview/index.vue')['default']
GiCellAvatar: typeof import('./../components/GiCell/GiCellAvatar.vue')['default']
GiCellGender: typeof import('./../components/GiCell/GiCellGender.vue')['default']
GiCellStatus: typeof import('./../components/GiCell/GiCellStatus.vue')['default']
GiCellTag: typeof import('./../components/GiCell/GiCellTag.vue')['default']
GiCellTags: typeof import('./../components/GiCell/GiCellTags.vue')['default']
GiCodeView: typeof import('./../components/GiCodeView/index.vue')['default']
GiDot: typeof import('./../components/GiDot/index.tsx')['default']
GiEditTable: typeof import('./../components/GiEditTable/GiEditTable.vue')['default']
GiFooter: typeof import('./../components/GiFooter/index.vue')['default']
GiForm: typeof import('./../components/GiForm/src/GiForm.vue')['default']
GiIconBox: typeof import('./../components/GiIconBox/index.vue')['default']
GiIconSelector: typeof import('./../components/GiIconSelector/index.vue')['default']
GiIframe: typeof import('./../components/GiIframe/index.vue')['default']
GiOption: typeof import('./../components/GiOption/index.vue')['default']
GiOptionItem: typeof import('./../components/GiOptionItem/index.vue')['default']
GiPageLayout: typeof import('./../components/GiPageLayout/index.vue')['default']
GiSpace: typeof import('./../components/GiSpace/index.vue')['default']
GiSplitButton: typeof import('./../components/GiSplitButton/index.vue')['default']
GiSplitPane: typeof import('./../components/GiSplitPane/index.vue')['default']
GiSplitPaneFlexibleBox: typeof import('./../components/GiSplitPane/components/GiSplitPaneFlexibleBox.vue')['default']
GiSvgIcon: typeof import('./../components/GiSvgIcon/index.vue')['default']
GiTable: typeof import('./../components/GiTable/src/GiTable.vue')['default']
GiTag: typeof import('./../components/GiTag/index.tsx')['default']
GiThemeBtn: typeof import('./../components/GiThemeBtn/index.vue')['default']
HourForm: typeof import('./../components/GenCron/CronForm/component/hour-form.vue')['default']
Icon403: typeof import('./../components/icons/Icon403.vue')['default']
Icon404: typeof import('./../components/icons/Icon404.vue')['default']
Icon500: typeof import('./../components/icons/Icon500.vue')['default']
IconBorders: typeof import('./../components/icons/IconBorders.vue')['default']
IconTableSize: typeof import('./../components/icons/IconTableSize.vue')['default']
IconTreeAdd: typeof import('./../components/icons/IconTreeAdd.vue')['default']
IconTreeReduce: typeof import('./../components/icons/IconTreeReduce.vue')['default']
JsonPretty: typeof import('./../components/JsonPretty/index.vue')['default']
MinuteForm: typeof import('./../components/GenCron/CronForm/component/minute-form.vue')['default']
MonthForm: typeof import('./../components/GenCron/CronForm/component/month-form.vue')['default']
MultipartUpload: typeof import('./../components/MultipartUpload/index.vue')['default']
ParentView: typeof import('./../components/ParentView/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SecondForm: typeof import('./../components/GenCron/CronForm/component/second-form.vue')['default']
SplitPanel: typeof import('./../components/SplitPanel/index.vue')['default']
TextCopy: typeof import('./../components/TextCopy/index.vue')['default']
UserSelect: typeof import('./../components/UserSelect/index.vue')['default']
Verify: typeof import('./../components/Verify/index.vue')['default']
VerifyPoints: typeof import('./../components/Verify/Verify/VerifyPoints.vue')['default']
VerifySlide: typeof import('./../components/Verify/Verify/VerifySlide.vue')['default']
WeekForm: typeof import('./../components/GenCron/CronForm/component/week-form.vue')['default']
YearForm: typeof import('./../components/GenCron/CronForm/component/year-form.vue')['default']
}
}
43 changes: 38 additions & 5 deletions codestyle-admin-web/src/views/template/list/PreviewModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import axios from 'axios'
import { Message } from '@arco-design/web-vue'
import { useClipboard } from '@vueuse/core'
import { marked } from 'marked'
Expand Down Expand Up @@ -228,24 +229,56 @@ watch(copied, () => {

const onDownload = async () => {
const d = templateData.value
if (!d) return
if (!d) {
console.log('[Download] templateData is null')
return
}
console.log('[Download] Starting download:', JSON.parse(JSON.stringify(d)))
try {
console.log('[Download] Step 1: Recording download count for id:', d.id)
await recordDownload(d.id)
console.log('[Download] Step 2: Download recorded, checking params - groupId:', d.groupId, 'artifactId:', d.artifactId, 'version:', d.version)
if (d.groupId && d.artifactId && d.version) {
const res = await downloadTemplate(d.groupId, d.artifactId, d.version)
console.log('[Download] Step 3: Calling downloadTemplate API with params:', d.groupId, d.artifactId, d.version)
// 直接用 axios 测试,不通过封装
const baseURL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
const token = localStorage.getItem('token')
console.log('[Download] Token exists:', !!token, 'Token:', token ? token.substring(0, 20) + '...' : null)
const res = await axios.get(`${baseURL}/open-api/template/download`, {
params: { groupId: d.groupId, artifactId: d.artifactId, version: d.version },
responseType: 'blob',
headers: token ? { Authorization: `Bearer ${token}` } : {}
})
console.log('[Download] Step 4: API response status:', res.status, res.statusText)
console.log('[Download] Step 5: Creating blob and download link')
const url = URL.createObjectURL(new Blob([res.data]))
const a = document.createElement('a')
a.href = url
a.download = `${d.artifactId}-${d.version}.zip`
a.download = `${d.name || d.artifactId}-${d.version}.zip`
a.click()
URL.revokeObjectURL(url)
console.log('[Download] Step 6: Download completed')
} else if (d.downloadUrl) {
console.log('[Download] Using downloadUrl fallback:', d.downloadUrl)
const base = import.meta.env.VITE_API_BASE_URL || ''
window.open(`${base}${d.downloadUrl}`, '_blank')
}
Message.success('下载成功')
} catch {
Message.error('下载失败')
} catch (err: any) {
console.error('[Download] Error:', err)
console.error('[Download] Error status:', err?.response?.status)
console.error('[Download] Error statusText:', err?.response?.statusText)
console.error('[Download] Error data:', err?.response?.data)
// 尝试读取 blob 错误信息
if (err?.response?.data instanceof Blob) {
const text = await err.response.data.text()
console.error('[Download] Blob error text:', text)
try {
const json = JSON.parse(text)
console.error('[Download] Blob error JSON:', json)
} catch {}
}
Message.error('下载失败: ' + (err?.response?.statusText || err?.message || '未知错误'))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ spring.datasource:
# 请务必提前创建好名为 codestyle_admin 的数据库,如果使用其他数据库名请注意同步修改 DB_NAME 配置
url: jdbc:p6spy:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:codestyle_admin}?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&autoReconnect=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: ${DB_USER:root}
password: ${DB_PWD:051105}
password: ${DB_PWD:admin123}
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
# Hikari 连接池配置
hikari:
Expand Down