初始化本地仓库

This commit is contained in:
2026-08-31 11:33:59 +08:00
commit 663f74b633
2390 changed files with 402918 additions and 0 deletions
@@ -0,0 +1,18 @@
import request from '@/utils/http';
/**
* {{pluginName}} 插件 API
*/
export default {
/**
* 列表 API
* @param params 查询参数
* @returns 响应数据
*/
async test(params = {}) {
return request.get<{ msg?: string; data?: unknown }>({
url: '/{{pluginKey}}/index',
params
});
}
};
@@ -0,0 +1,19 @@
{
"{{pluginName}}": {
"title": "{{pluginTitle}}",
"description": "{{pluginDescription}}",
"list": "列表",
"add": "添加",
"edit": "编辑",
"delete": "删除",
"detail": "详情",
"save": "保存",
"cancel": "取消",
"search": "搜索",
"reset": "重置",
"confirm": "确认",
"success": "操作成功",
"error": "操作失败",
"loading": "加载中..."
}
}
@@ -0,0 +1,26 @@
import { AppRouteRecord } from '@/types/router'
import { RoutesAlias } from '@/router/routesAlias'
export default {
path: '/{{pluginName}}',
name: '{{camelPluginName}}',
component: RoutesAlias.Layout,
meta: {
title: '{{pluginTitle}}',
icon: 'ri:plugin-line',
module: '{{pluginName}}'
},
children: [
{
path: 'index',
name: '{{camelPluginName}}Index',
component: '/{{pluginKey}}/index/index',
meta: {
title: '首页',
icon: 'ri:home-line',
keepAlive: false,
module: '{{pluginName}}'
}
}
]
} as AppRouteRecord
@@ -0,0 +1,147 @@
<template>
<div class="{{pluginName}}-container">
<div class="plugin-header">
<h1>{{ $t('{{pluginName}}.title') }}</h1>
<p>{{ $t('{{pluginName}}.description') }}</p>
</div>
<div class="plugin-content">
<el-card shadow="hover">
<template #header>
<div class="card-header">
<span>{{ $t('{{pluginName}}.card_title') }}</span>
<el-button type="primary" @click="fetchTestData">
{{ $t('{{pluginName}}.refresh_btn') }}
</el-button>
</div>
</template>
<div v-loading="loading" class="card-body">
<div v-if="error" class="error-message">
<el-alert
:title="error"
type="error"
show-icon
/>
</div>
<div v-else-if="testData" class="plugin-data">
<el-descriptions :column="1" border>
<el-descriptions-item label="测试消息">
{{ testData.msg }}
</el-descriptions-item>
<el-descriptions-item label="数据">
{{ testData.data }}
</el-descriptions-item>
</el-descriptions>
</div>
<div v-else class="empty-state">
<el-empty description="暂无数据" />
</div>
</div>
</el-card>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import pluginApi from '../../../api/index';
export default defineComponent({
name: '{{camelPluginName}}View',
setup() {
const loading = ref(false);
const error = ref<string | null>(null);
const testData = ref<{ msg?: string; data?: unknown } | null>(null);
const fetchTestData = async () => {
loading.value = true;
error.value = null;
try {
const response = await pluginApi.test();
testData.value = response;
} catch (err: unknown) {
error.value = err instanceof Error ? err.message : '网络错误';
} finally {
loading.value = false;
}
};
// 初始加载数据
fetchTestData();
return {
loading,
error,
testData,
fetchTestData
}
}
});
</script>
<style scoped>
.{{pluginName}}-container {
padding: 20px;
min-height: 80vh;
}
.plugin-header {
margin-bottom: 30px;
text-align: center;
}
.plugin-header h1 {
font-size: 28px;
font-weight: 600;
margin-bottom: 10px;
color: #303133;
}
.plugin-header p {
font-size: 16px;
color: #606266;
}
.plugin-content {
max-width: 800px;
margin: 0 auto;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-body {
padding: 20px 0;
}
.error-message {
margin-bottom: 20px;
}
.plugin-data {
margin-top: 20px;
}
.plugin-data pre {
background-color: #f5f7fa;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
font-size: 14px;
line-height: 1.5;
}
.empty-state {
min-height: 300px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
@@ -0,0 +1,27 @@
<?php
return [
'name' => '{{pluginName}}',
'title' => '{{pluginTitle}}',
'type' => 'madong',
'description' => '{{pluginDescription}}',
'author' => 'Your Name',
'email' => 'your.email@example.com',
'version' => '1.0.0',
// Composer 依赖
'require' => [
'composer' => [],
],
// NPM 依赖
'npm_require' => [
'admin' => [],
'web' => [],
],
// 卸载配置
'uninstall' => [
'undeletable' => false, // 是否不可删除(true: 系统内置插件不可删除, false: 可删除)
'drop_tables' => true, // 删除数据表
'remove_dependencies' => false, // 移除合并的依赖
],
];
@@ -0,0 +1,9 @@
<?php
return [
'enable' => true,
'debug' => true,
'controller_suffix' => 'Controller',
'controller_reuse' => false,
'version' => '1.0.0',
];
@@ -0,0 +1,82 @@
<?php
/**
* {{camelPluginName}} 控制器
*/
namespace plugin\{{pluginName}}\app\adminapi\controller;
use app\adminapi\middleware\OperationMiddleware;
use app\adminapi\middleware\PermissionMiddleware;
use core\tool\Json;
use madong\swagger\annotation\response\DataResponse;
use madong\swagger\annotation\response\SimpleResponse;
use madong\swagger\attribute\Permission;
use madong\swagger\attribute\AllowAnonymous;
use OpenApi\Attributes as OA;
use support\annotation\Middleware;
use support\Request;
use support\Response;
#[Middleware(OperationMiddleware::class, PermissionMiddleware::class)]
class {{camelPluginName}}Controller
{
#[OA\Get(
path: '/{{pluginKey}}/index',
summary: '获取列表',
tags: ['{{pluginName}}']
)]
#[DataResponse(description: '获取成功')]
#[Permission(code: '{{pluginName}}:index', description: '列表权限')]
public function index(Request $request): Response
{
return Json::success('获取成功', []);
}
#[OA\Post(
path: '/{{pluginKey}}/create',
summary: '创建',
tags: ['{{pluginName}}']
)]
#[SimpleResponse(description: '创建成功')]
#[Permission(code: '{{pluginName}}:create', description: '创建权限')]
public function create(Request $request): Response
{
return Json::success('创建成功');
}
#[OA\Get(
path: '/{{pluginKey}}/info',
summary: '详情',
tags: ['{{pluginName}}']
)]
#[DataResponse(description: '获取成功')]
#[Permission(code: '{{pluginName}}:info', description: '详情权限')]
public function info(Request $request): Response
{
return Json::success('获取成功', []);
}
#[OA\Post(
path: '/{{pluginKey}}/update',
summary: '更新',
tags: ['{{pluginName}}']
)]
#[SimpleResponse(description: '更新成功')]
#[Permission(code: '{{pluginName}}:update', description: '更新权限')]
public function update(Request $request): Response
{
return Json::success('更新成功');
}
#[OA\Post(
path: '/{{pluginKey}}/delete',
summary: '删除',
tags: ['{{pluginName}}']
)]
#[SimpleResponse(description: '删除成功')]
#[Permission(code: '{{pluginName}}:delete', description: '删除权限')]
public function delete(Request $request): Response
{
return Json::success('删除成功');
}
}
@@ -0,0 +1,59 @@
<?php
namespace plugin\{{pluginName}};
use core\plugin\PluginInstall as BasePluginInstall;
/**
* 插件安装类
* 继承 PluginInstall 基类,自动处理:
* - 数据库迁移 (resource/database/migrations/)
* - 种子数据 (resource/database/seeds/)
*
* 菜单需要按需导入或卸载;模板在安装时导入,物理删除由删除插件阶段统一处理:
* - $this->importPluginMenus() - 导入菜单
* - $this->importTemplates() - 复制模板
* - $this->uninstallPluginMenus() - 卸载菜单
*/
class Install extends BasePluginInstall
{
/**
* 安装前回调
*/
protected function beforeInstall(string $version): void
{
$this->output(" 🔄 Running beforeInstall...\n");
}
/**
* 安装后回调 - 按需导入菜单和模板
*/
protected function afterInstall(string $version): void
{
$this->output(" 🔄 Running afterInstall...\n");
// 导入菜单
$this->importPluginMenus();
// 复制模板资源
$this->importTemplates();
}
/**
* 卸载前回调
*/
protected function beforeUninstall(string $version): void
{
$this->output(" 🔄 Running beforeUninstall...\n");
}
/**
* 卸载后回调 - 清理菜单
*/
protected function afterUninstall(string $version): void
{
$this->output(" 🔄 Running afterUninstall...\n");
// 卸载菜单
$this->uninstallPluginMenus();
}
}
@@ -0,0 +1,25 @@
<?php
/**
* 后台菜单配置
* 安装时会自动加载
*/
return [
[
'name' => '{{pluginTitle}}',
'code' => '{{pluginKey}}',
'app' => '{{pluginName}}',
'path' => '/{{pluginKey}}',
'icon' => 'plugin',
'children' => [
[
'name' => '列表',
'code' => '{{pluginKey}}:index',
'app' => '{{pluginName}}',
'path' => '/{{pluginKey}}/index',
'component' => '/{{pluginKey}}/index/index',
],
],
],
];
@@ -0,0 +1,9 @@
<?php
/**
* 前端菜单配置
*/
return [
// 前端菜单配置
];
@@ -0,0 +1,9 @@
<?php
/**
* Web 菜单配置
*/
return [
// Web 菜单配置
];
@@ -0,0 +1,87 @@
<?php
/**
* {{pluginName}} 插件路由配置
* 使用 Swagger 注解自动生成路由
*/
use Webman\Route;
use WebmanTech\Swagger\Swagger;
use OpenApi\Annotations as OA;
/**
* 注册 API 路由
*/
Route::group('/api', function () {
Swagger::create()->registerRoute([
'route_prefix' => '/{{pluginKey}}/openapi',
'register_route' => true,
'openapi_doc' => [
'scan_path' => [
base_path('plugin/{{pluginName}}/app/api'),
],
'modify' => function (OA\OpenApi $openapi) {
$openapi->info->title = '{{pluginTitle}} API';
$openapi->info->version = '1.0.0';
$openapi->servers = [
new OA\Server(
[
'url' => '/api',
'description' => request()->host(),
]
),
];
/** @phpstan-ignore-next-line */
if (!$openapi->components instanceof OA\Components) {
$openapi->components = new OA\Components([]);
}
$openapi->components->securitySchemes = [
new OA\SecurityScheme([
'securityScheme' => 'api_key',
'type' => 'apiKey',
'name' => config('core.jwt.app.token_name', 'Authorization'),
'in' => 'header',
]),
];
},
],
]);
});
/**
* 注册 AdminAPI 路由
*/
Route::group('/adminapi', function () {
Swagger::create()->registerRoute([
'route_prefix' => '/{{pluginKey}}/openapi',
'register_route' => true,
'openapi_doc' => [
'scan_path' => [
base_path('plugin/{{pluginName}}/app/adminapi'),
],
'modify' => function (OA\OpenApi $openapi) {
$openapi->info->title = '{{pluginTitle}} API';
$openapi->info->version = '1.0.0';
$openapi->servers = [
new OA\Server(
[
'url' => '/adminapi',
'description' => request()->host(),
]
),
];
/** @phpstan-ignore-next-line */
if (!$openapi->components instanceof OA\Components) {
$openapi->components = new OA\Components([]);
}
$openapi->components->securitySchemes = [
new OA\SecurityScheme([
'securityScheme' => 'api_key',
'type' => 'apiKey',
'name' => config('core.jwt.app.token_name', 'Authorization'),
'in' => 'header',
]),
];
},
],
]);
});
@@ -0,0 +1,7 @@
<?php
return [
'locale' => config('app.lang'),
'fallback_locale' => ['zh_CN', 'en'],
'path' => base_path() . '/plugin/{{pluginName}}/resource/translations',
];