前端开发
本文档详细介绍 ElasticView 插件前端开发的技术栈、项目结构、开发流程和最佳实践。
技术栈
核心框架
- Vue 3 - 渐进式 JavaScript 框架
- Vite - 快速的构建工具和开发服务器
插件 SDK
- @elasticview/plugin-sdk - ElasticView 官方前端 SDK
项目结构
frontend/
├── src/
│ ├── api/ # API 接口定义
│ │ ├── es.ts # Elasticsearch 相关 API
│ │ ├── es-index.ts # ES 索引 API
│ │ └── ...
│ ├── components/ # 公共组件
│ ├── views/ # 页面视图
│ ├── router/ # 路由配置
│ │ └── index.ts # 路由定义
│ ├── lang/ # 国际化语言包
│ │ ├── en.ts # 英文语言包
│ │ └── zh-cn.ts # 中文语言包
│ ├── utils/ # 工具函数
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
├── package.json # 依赖配置
├── vite.config.ts # Vite 配置
├── tsconfig.json # TypeScript 配置
└── index.html # HTML 模板
快速开始
1. 安装依赖
bash
pnpm install @elasticview/plugin-sdk
2. 插件初始化
在 main.ts
中初始化 EV 前端插件:
typescript
import {setupEvPlugin} from '@elasticview/plugin-sdk'
import pluginJson from '../../plugin.json'
import App from "./App.vue";
import router from "./router/index.js"
import enLocale from "./lang/en";
import zhCnLocale from "./lang/zh-cn";
// 引入第三方组件库(可选,但推荐使用,可自动适配主题颜色)
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 插件启动时安装第三方插件的初始化钩子
const init = (app) => {
// 使用 Element Plus(可选)
app.use(ElementPlus)
return app
}
// 初始化插件
// 参数依次为:plugin.json配置文件,App.vue实例,路由,英文语言包,中文语言包,初始化钩子
setupEvPlugin(pluginJson, App, router, enLocale, zhCnLocale, init)
3. 路由配置
typescript
// src/router/index.ts
import pluginJson from '../../../plugin.json' //插件配置文件,json格式
export const routes = [
{
path: `/${pluginJson.plugin_alias}`,//根目录必须为插件名
component: ()=>import("@/layouts/Layout.vue"),//默认布局文件
children: [
{
path: 'hello-world',
component: ()=>import('@/views/helloworld/index.vue'),
name: 'hello-world',
meta: {
title: '访问es',
icon: 'el-icon-coin'
}
}
]
},
]
/****
新增页面后如果需要在ElasticView的菜单中展现出来,
则需要修改plugin.json中frontend_routes配置项,为routes中去除component属性的对应路由
plugin.json 例子:
{
...
"frontend_routes":[
{
path: 'hello-world',
name: 'hello-world',
meta: {
title: '访问es',
icon: 'el-icon-coin'
}
}
}
*/
4. 国际化配置
typescript
// src/lang/zh-cn.ts
export default {
hello: '你好',
welcome: '欢迎使用 ElasticView 插件',
}
// src/lang/en.ts
export default {
hello: 'Hello',
welcome: 'Welcome to ElasticView Plugin',
}
//模板中使用:{{$t('hello')}}
SDK 使用
HTTP 请求
typescript
// src/api/user.ts
import {request} from '@elasticview/plugin-sdk'
// 基础 POST 请求
export function createUser(data: any) {
return request({
url: `/api/user/create`,
method: 'post',
data
})
}
// 使用示例
const result = await createUser({
name: '张三',
email: 'zhangsan@example.com'
})
SDK 工具方法
typescript
// 在 Vue 组件中使用
<template>
<div :class="{'mobile-layout': isMobile, 'dark-theme': isDark}">
<el-button :size="layoutSize" @click="navigateToPage">
{{ $t('hello') }}
</el-button>
</div>
</template>
<script setup lang="ts">
import {computed, onMounted, onUnmounted} from 'vue'
import {sdk} from '@elasticview/plugin-sdk'
// 获取当前布局尺寸
const layoutSize = computed(() => {
return sdk.getLayoutSize()
})
// 检查是否为移动设备
const isMobile = computed(() => {
return sdk.IsMobile()
})
// 检查是否为暗色主题
const isDark = computed(() => {
return sdk.isDarkTheme()
})
// 获取当前语言
const currentLanguage = computed(() => {
return sdk.getLanguage()
})
// 获取路由实例
const router = sdk.getRouter()
// 编程式导航
const navigateToPage = () => {
router.push('/some-path')
}
// 获取事件总线实例
const eventBus = sdk.getEventBus()
const BusEnum = sdk.getBusEnum()
// 监听系统设置变更
onMounted(() => {
eventBus.on(BusEnum.changeEvSettings, (newSettings) => {
console.log('系统设置已更改:', newSettings)
// 处理设置变更逻辑
})
eventBus.on(BusEnum.changeEvAppConfig, (newConfig) => {
console.log('应用配置已更改:', newConfig)
// 处理配置变更逻辑
})
})
// 获取当前选中的数据源连接 ID
const currentConnId = computed(() => {
return sdk.GetSelectEsConnID()
})
// 获取当前用户所拥有的数据源列表
const handleLinkOperation = async () => {
try {
const result = await sdk.LinkOptAction()
console.log('您拥有的数据源:', result)
} catch (error) {
console.error('获取失败:', error)
}
}
// 调用其他插件的 API
const callAnotherPluginApi = async (data) => {
const response = await sdk.CallAnotherPluginApi('other-plugin-alias', {
url: `/api/DbInsert`,
method: 'post',
data
})
return response
}
// 插件长连接通信
onMounted(() => {
// 订阅频道消息
sdk.SubToChannel('my-channel', (message) => {
console.log('收到频道消息:', message)
})
})
// 发送频道消息
const sendChannelMessage = () => {
sdk.CallToChannel('my-channel', {
type: 'notification',
content: 'Hello from plugin!'
})
}
// 取消订阅(组件卸载时)
onUnmounted(() => {
sdk.UnSubscribeToChannel('my-channel')
})
// 获取当前用户 ID
const currentUserId = computed(() => {
return sdk.GetUserId()
})
</script>
尺寸枚举使用
typescript
<template>
<el-button :size="componentSize">按钮</el-button>
</template>
<script setup lang="ts">
import {computed} from 'vue'
import {sdk} from '@elasticview/plugin-sdk'
// 获取尺寸枚举
const SizeEnum = sdk.getSizeEnum()
// 尺寸值:
// SizeEnum.DEFAULT = "default"
// SizeEnum.LARGE = "large"
// SizeEnum.SMALL = "small"
// 根据尺寸设置样式
const componentSize = computed(() => {
const size = sdk.getLayoutSize()
switch(size) {
case SizeEnum.LARGE:
return 'large'
case SizeEnum.SMALL:
return 'small'
default:
return 'default'
}
})
</script>
主题适配
vue
<template>
<div class="theme-container" :class="themeClass">
<el-card>
<h3>主题自适应卡片</h3>
<p>根据系统主题自动调整样式</p>
</el-card>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { sdk } from '@elasticview/plugin-sdk'
const isDark = computed(() => sdk.isDarkTheme())
const themeClass = computed(() => ({
'dark-theme': isDark.value,
'light-theme': !isDark.value
}))
</script>
<style scoped>
.light-theme {
background-color: #ffffff;
color: #333333;
}
.dark-theme {
background-color: #1a1a1a;
color: #ffffff;
}
.dark-theme .el-card {
background-color: #2d2d2d;
border-color: #4d4d4d;
}
</style>
常见问题
Q: 为什么我的代码没有问题,但是插件页面一片空白?
A: 可能是因为plugin.json中的frontend_debug选项没有设置为true。
Q: 为什么我的代码没有问题,但是插件的菜单栏里没有具体页面入口?
A: 可能是因为plugin.json中的frontend_debug选项没有添加路由。
注意事项
- SDK 初始化 - 确保在
setupEvPlugin
初始化后再使用 SDK 方法 - 事件清理 - 组件卸载时需要清理事件监听器,避免内存泄漏
- 响应式设计 - 使用
sdk.IsMobile()
适配移动端布局 - 主题适配 - 使用
sdk.isDarkTheme()
支持深色主题 - 国际化 - 合理使用语言包,支持多语言切换
- API 路径 - 请求 URL 路径需要与后端插件接口路径一致