Compare commits
19 Commits
Author | SHA1 | Date |
---|---|---|
|
2c3e5fe10f | 3 years ago |
|
d0a2de9d07 | 3 years ago |
|
e7e360db60 | 4 years ago |
|
244bca2c2c | 4 years ago |
|
7619fc3a9d | 4 years ago |
|
eba23d6024 | 4 years ago |
|
8bd74f7c75 | 4 years ago |
|
f7fbdfc19a | 4 years ago |
|
d5d98515a0 | 4 years ago |
|
05a19463dd | 4 years ago |
|
fed5c223c3 | 4 years ago |
|
8fe7c7ba4b | 4 years ago |
|
2ee5dc2ac4 | 4 years ago |
|
871975049f | 4 years ago |
|
a73f14c3e9 | 4 years ago |
|
81b073aa2a | 4 years ago |
|
215192d1d5 | 4 years ago |
|
a063e9b1c9 | 4 years ago |
|
14f543c58e | 4 years ago |
41 changed files with 2462 additions and 699 deletions
@ -1 +1,2 @@ |
|||
VITE_API_URL=http://localhost:4001 |
|||
VITE_API_URL=https://test.tall.wiki |
|||
VITE_API_URL_NEW=http://101.201.226.163 |
|||
|
@ -1 +1,2 @@ |
|||
VITE_API_URL=http://139.196.27.233:29001 |
|||
VITE_API_URL=http://www.tall.wiki |
|||
VITE_API_URL_NEW=http://101.201.226.163 |
|||
|
@ -1 +1,2 @@ |
|||
VITE_API_URL=https://test.tall.wiki |
|||
VITE_API_URL_NEW=http://101.201.226.163 |
|||
|
File diff suppressed because it is too large
@ -0,0 +1,30 @@ |
|||
// noinspection SpellCheckingInspection
|
|||
|
|||
import http from 'utils/axios'; |
|||
|
|||
const apiUrl = import.meta.env.VITE_API_URL_NEW; |
|||
const business = `${apiUrl}/gateway/opt/business`; |
|||
|
|||
// 查询业务列表
|
|||
export const queryBusiness = params => http.post(`${business}/query`, params); |
|||
|
|||
// 查询业务下关联的插件
|
|||
export const queryPluginByBusiness = params => http.post(`${business}/queryPlugin`, params); |
|||
|
|||
// 关联业务和插件
|
|||
export const relevance = params => http.post(`${business}/relevance`, params); |
|||
|
|||
// 添加业务信息
|
|||
export const saveBusiness = params => http.post(`${business}/save`, params); |
|||
|
|||
// 修改业务下的插件配置信息
|
|||
export const updateConfig = params => http.post(`${business}/updateConfig`, params); |
|||
|
|||
// 通过id查询业务信息
|
|||
export const queryIdBusiness = params => http.post(`${business}/queryIdBusiness`, params); |
|||
|
|||
// 移除业务下关联的插件
|
|||
export const delRelevance = params => http.post(`${business}/delRelevance`, params); |
|||
|
|||
// 删除业务
|
|||
export const delBusiness = params => http.post(`${business}/del`, params); |
@ -0,0 +1,21 @@ |
|||
// noinspection SpellCheckingInspection
|
|||
|
|||
import http from 'utils/axios'; |
|||
|
|||
const apiUrl = import.meta.env.VITE_API_URL_NEW; |
|||
const plugin = `${apiUrl}/gateway/opt/plugin`; |
|||
|
|||
// 查询插件列表
|
|||
export const queryPlugins = params => http.post(`${plugin}/query`, params); |
|||
|
|||
// 获取一个随机id
|
|||
export const randomId = params => http.post(`${plugin}/randomId`, params); |
|||
|
|||
// 创建插件
|
|||
export const savePlugin = params => http.post(`${plugin}/save`, params); |
|||
|
|||
// 修改插件信息
|
|||
export const updatePlugin = params => http.post(`${plugin}/update`, params); |
|||
|
|||
// 删除插件
|
|||
export const delPlugin = params => http.post(`${plugin}/del`, params); |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 2.3 KiB |
@ -0,0 +1,19 @@ |
|||
<template> |
|||
<el-breadcrumb separator="/"> |
|||
<el-breadcrumb-item v-for="(item, index) in path" :key="index"> |
|||
<span @click="router.push({ name: item.name })" v-if="index !== path.length - 1" class="font-bold cursor-pointer">{{ |
|||
item.title |
|||
}}</span> |
|||
<span v-else>{{ item.title }}</span> |
|||
</el-breadcrumb-item> |
|||
</el-breadcrumb> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from 'vue-router'; |
|||
import { defineProps } from 'vue'; |
|||
|
|||
const router = useRouter(); |
|||
|
|||
defineProps({ path: { default: () => [], type: Array } }); |
|||
</script> |
@ -0,0 +1,81 @@ |
|||
<template> |
|||
<el-button type="primary" @click="data.dialogVisible = true">配置</el-button> |
|||
<el-dialog v-model="data.dialogVisible" title="配置" width="40%"> |
|||
<!-- main --> |
|||
<el-form ref="formRef" :model="form" :rules="rules" label-width="150px" class="forms"> |
|||
<el-form-item label="配置文件:" prop="config"> |
|||
<el-input v-model="form.config" type="textarea" placeholder="请输入配置文件"></el-input> |
|||
</el-form-item> |
|||
<el-form-item> <el-switch v-model="form.debug" class="mr-3"></el-switch> 是否开启debug模式 </el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="onSubmit()">发布</el-button> |
|||
<el-button @click="resetForm()">重置</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { defineProps, reactive, ref } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { updateConfig } from '@/apis/business'; |
|||
|
|||
const formRef = ref(null); |
|||
|
|||
const props = defineProps({ |
|||
businessPluginId: { default: '', type: String }, |
|||
oldConfig: { default: '', type: String }, |
|||
oldDebug: { default: 0, type: Number }, |
|||
}); |
|||
|
|||
const form = reactive({ |
|||
config: '', |
|||
debug: false, |
|||
}); |
|||
|
|||
const rules = { config: [{ required: true, message: '请输入配置文件', trigger: 'blur' }] }; |
|||
|
|||
const data = reactive({ dialogVisible: false }); |
|||
|
|||
if (props.oldConfig) { |
|||
form.config = props.oldConfig; |
|||
} |
|||
if (props.oldDebug) { |
|||
form.debug = props.oldDebug === 1; |
|||
} |
|||
|
|||
/** |
|||
* 配置修改 |
|||
* @param {object} params |
|||
*/ |
|||
function onSubmit() { |
|||
try { |
|||
formRef.value.validate(async valid => { |
|||
if (valid) { |
|||
const params = { |
|||
param: { |
|||
businessPluginId: props.businessPluginId, |
|||
config: form.config, |
|||
debug: form.debug ? 1 : 0, |
|||
}, |
|||
}; |
|||
await updateConfig(params); |
|||
ElMessage.success('配置修改成功'); |
|||
resetForm(); |
|||
data.dialogVisible = true; |
|||
} else { |
|||
console.log('error submit!!'); |
|||
return false; |
|||
} |
|||
}); |
|||
} catch (error) { |
|||
ElMessage.error(error || '配置修改失败'); |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
// 重置 |
|||
function resetForm() { |
|||
formRef.value.resetFields(); |
|||
} |
|||
</script> |
@ -0,0 +1,45 @@ |
|||
<template> |
|||
<el-menu :default-active="data.menuIndex" class="el-menu-demo" mode="vertical" @select="handleSelect"> |
|||
<el-menu-item :disabled="list.disabled" :index="index" @click="openPage(list.name)" v-for="(list, index) in data.menus" :key="index"> |
|||
{{ list.title }} |
|||
</el-menu-item> |
|||
</el-menu> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useStore } from 'vuex'; |
|||
import { reactive, computed, watchEffect } from 'vue'; |
|||
import { useRouter } from 'vue-router'; |
|||
|
|||
const store = useStore(); |
|||
const leftIndex = computed(() => store.state.plugin.leftIndex); |
|||
|
|||
const router = useRouter(); |
|||
const data = reactive({ |
|||
menus: [ |
|||
{ title: '概览', name: '', disabled: true }, |
|||
{ title: '创建业务', name: 'desk-add-business', disabled: false }, |
|||
{ title: '创建插件', name: 'desk-add-plugin', disabled: false }, |
|||
{ title: '我的业务', name: 'desk-business-list', disabled: false }, |
|||
{ title: '我的插件', name: 'desk-plugin-list', disabled: false }, |
|||
], |
|||
menuIndex: '', |
|||
}); |
|||
|
|||
console.log('menuIndex: ', data.menuIndex); |
|||
watchEffect(() => { |
|||
if (leftIndex && leftIndex.value) { |
|||
data.menuIndex = leftIndex.value; |
|||
console.log('data.menuIndex: ', data.menuIndex); |
|||
} |
|||
}); |
|||
|
|||
function handleSelect(e) { |
|||
store.commit('plugin/setLeftIndex', e); |
|||
} |
|||
|
|||
// 点击跳转路由 |
|||
function openPage(name) { |
|||
router.push({ name }); |
|||
} |
|||
</script> |
@ -0,0 +1,215 @@ |
|||
<template> |
|||
<div v-if="data.listArray && data.listArray.length"> |
|||
<div class="shop-content flex py-5" v-for="(list, index) in data.listArray" :key="list.id"> |
|||
<img :src="list.preview" alt="" class="shop-left" /> |
|||
<div class="shop-right ml-8"> |
|||
<div> |
|||
<span class="text-xl font-semibold">{{ list.name }}</span> <span class="ml-5 text-sm">{{ list.versions }}</span> |
|||
</div> |
|||
<div class="mt-4 desc text-sm"> |
|||
<span> 描述:</span> <span>{{ list.intro }}</span> |
|||
</div> |
|||
<div class="mt-5 text-sm" v-if="list.tags && list.tags.length"> |
|||
<el-tag v-for="item in list.tags" :type="item.btnType" class="mr-3" :key="item.name">{{ item.name }}</el-tag> |
|||
</div> |
|||
<div class="mt-5 text-sm flex flex-row"> |
|||
<span>行业:</span> <span>{{ list.industryName || '无' }}</span> <span class="ml-8">分类:</span> |
|||
<span>{{ list.sortName || '无' }}</span> |
|||
</div> |
|||
<div class="mt-4 text-sm"> |
|||
<span>更新日期:</span> <span>{{ list.updateTime || '无' }}</span> <span class="ml-8">作者:</span> |
|||
<span>{{ list.authorName || '无' }}</span> |
|||
</div> |
|||
<div class="mt-6"> |
|||
<el-popconfirm |
|||
title="确定要移除该插件吗?" |
|||
confirm-button-text="确定" |
|||
cancel-button-text="再想想" |
|||
v-if="showConfig" |
|||
@confirm="deleteRelevance(list)" |
|||
> |
|||
<template #reference> |
|||
<el-button type="primary">移除</el-button> |
|||
</template> |
|||
</el-popconfirm> |
|||
<el-button type="primary" disabled>下载源代码</el-button> |
|||
<el-button type="primary" disabled>下载示例代码</el-button> |
|||
<!-- 添加到业务弹框 --> |
|||
<el-popover placement="right" title="请选择业务" :width="240" trigger="click" v-if="!showConfig"> |
|||
<div class="radio-box"> |
|||
<Relevance |
|||
:businessLists="data.businessLists" |
|||
:pluginId="list.id" |
|||
:isLastPage="data.isLastPage" |
|||
@changePageNum="changePageNum" |
|||
/> |
|||
</div> |
|||
<template #reference> |
|||
<el-button type="primary" @click="handleQueryBusiness">添加到业务</el-button> |
|||
</template> |
|||
</el-popover> |
|||
<!-- 配置 --> |
|||
<!-- <el-button type="primary" v-if="showConfig" @click="data.dialogVisible = true">配置</el-button> --> |
|||
<Configure v-if="showConfig" :businessPluginId="list.businessPluginId" :oldConfig="list.config" :oldDebug="list.debug" /> |
|||
<!-- 预览 --> |
|||
<el-button type="primary" @click="collapseVisible(index)" style="margin-left: 10px">{{ |
|||
!list.visible ? '预览' : '关闭预览' |
|||
}}</el-button> |
|||
<div class="plugin-box" v-if="list.visible"> |
|||
<div class="plugin w-full h-full overflow-y-scroll"> |
|||
<Plugin :plugin="list" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<el-empty v-else description="暂无插件信息"></el-empty> |
|||
</template> |
|||
|
|||
<script lang="ts" setup="true"> |
|||
import { defineProps, reactive, watchEffect, defineEmits } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { queryBusiness, delRelevance } from '@/apis/business.js'; |
|||
|
|||
const data = reactive({ |
|||
currentPage: 1, |
|||
businessLists: [], |
|||
isLastPage: false, |
|||
listArray: [], |
|||
}); |
|||
|
|||
const props = defineProps({ |
|||
lists: { default: () => [], type: Array }, |
|||
showConfig: { default: false, type: Boolean }, |
|||
businessId: { default: '', type: String }, |
|||
}); |
|||
|
|||
const emit = defineEmits(['queryPluginOfBusiness']); |
|||
|
|||
watchEffect(() => { |
|||
if (props.lists && props.lists.length) { |
|||
data.listArray = []; |
|||
props.lists.forEach(item => { |
|||
item.visible = false; |
|||
data.listArray.push(item); |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
// 换页 |
|||
function changePageNum() { |
|||
data.currentPage++; |
|||
handleQueryBusiness(); |
|||
} |
|||
|
|||
/** |
|||
* 查询业务列表 |
|||
* @param {number} depth 查询深度 0则只查名称,1则查询全部 |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function handleQueryBusiness() { |
|||
try { |
|||
const { currentPage } = data; |
|||
if (currentPage === 1) { |
|||
data.businessLists = []; |
|||
} |
|||
const params = { |
|||
param: { |
|||
depth: 0, |
|||
name: '', |
|||
pageNum: currentPage, |
|||
pageSize: 10, |
|||
}, |
|||
}; |
|||
const res = await queryBusiness(params); |
|||
if (res.list.length) { |
|||
res.list.forEach(item => { |
|||
data.businessLists.push(item); |
|||
}); |
|||
} |
|||
data.currentPage = res.pageNum - 0; |
|||
data.isLastPage = res.isLastPage; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
// 预览 |
|||
function collapseVisible(index) { |
|||
data.listArray.forEach((item, i) => { |
|||
if (i === index) { |
|||
item.visible = !item.visible; |
|||
} else { |
|||
item.visible = false; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* 移除业务下的插件 |
|||
*/ |
|||
async function deleteRelevance(list) { |
|||
try { |
|||
const params = { param: { businessPluginId: list.businessPluginId } }; |
|||
await delRelevance(params); |
|||
ElMessage.success('删除成功'); |
|||
emit('queryPluginOfBusiness', props.businessId); |
|||
} catch (error) { |
|||
ElMessage.success(error || '删除失败'); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.el-input { |
|||
width: 20%; |
|||
margin-right: 2rem; |
|||
} |
|||
.el-select { |
|||
margin-right: 2rem; |
|||
width: 20%; |
|||
} |
|||
.desc { |
|||
height: 30px; |
|||
line-height: 15px; |
|||
text-overflow: -o-ellipsis-lastline; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 2; |
|||
line-clamp: 2; |
|||
-webkit-box-orient: vertical; |
|||
} |
|||
.shop-left { |
|||
width: 288px; |
|||
height: 263px; |
|||
} |
|||
|
|||
.radio-box { |
|||
width: 100%; |
|||
} |
|||
|
|||
.radio-box >>> .el-radio { |
|||
min-width: 100%; |
|||
margin: 0 !important; |
|||
} |
|||
|
|||
.plugin-box { |
|||
position: fixed; |
|||
right: 14rem; |
|||
background: url(../assets/iPhone13.png) no-repeat; |
|||
background-size: contain; |
|||
width: 19.375rem; |
|||
height: 39.2419rem; |
|||
top: calc(50vh - 289.93512px + 1.8rem); |
|||
padding: 2.8rem 1.2rem 2rem; |
|||
z-index: 99; |
|||
} |
|||
|
|||
.plugin::-webkit-scrollbar { |
|||
display: none; |
|||
} |
|||
</style> |
@ -0,0 +1,54 @@ |
|||
<template> |
|||
<div class="flex flex-row justify-space-between items-center"> |
|||
<div class="flex flex-row items-center"> |
|||
<div>业务名称:</div> |
|||
<el-input disabled v-model="data.keywords" placeholder="请输入业务名称或标签搜索" class="search-input mr-10" /> |
|||
<div>状态:</div> |
|||
<el-select disabled v-model="data.status" placeholder="请选择" class="search-input" @change="changeState"> |
|||
<el-option v-for="item in data.statusList" :key="item.value" :label="item.label" :value="item.value"> </el-option> |
|||
</el-select> |
|||
</div> |
|||
<div class="flex-1 ml-10"> |
|||
<el-button type="primary" size="small" class="w-60px h-40px" disabled>查询</el-button> |
|||
<el-button size="small" class="w-60px h-40px reset" disabled>重置</el-button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup="true"> |
|||
import { reactive } from 'vue'; |
|||
|
|||
const data = reactive({ |
|||
keywords: '', |
|||
status: '', |
|||
statusList: [ |
|||
{ |
|||
value: '状态一', |
|||
label: '状态一', |
|||
}, |
|||
{ |
|||
value: '状态二', |
|||
label: '状态二', |
|||
}, |
|||
{ |
|||
value: '状态三', |
|||
label: '状态三', |
|||
}, |
|||
], |
|||
}); |
|||
|
|||
function changeState(e) { |
|||
console.log('e: ', e); |
|||
data.status = e; |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.search-input { |
|||
width: 18rem; |
|||
} |
|||
|
|||
.reset { |
|||
margin-left: 0.75rem; |
|||
} |
|||
</style> |
@ -0,0 +1,117 @@ |
|||
<template> |
|||
<div v-if="lists && lists.length"> |
|||
<el-table :data="lists" class="bg-title" style="width: 100%"> |
|||
<el-table-column prop="name" label="业务名称"> </el-table-column> |
|||
<el-table-column prop="appId" label="APPID" width="300"> </el-table-column> |
|||
<el-table-column prop="startUsing" label="状态" key="slot" sortable> |
|||
<template #default="scope"> |
|||
<div class="flex flex-row items-center" @click="change(scope.row)"> |
|||
<div :class="scope.row.startUsing ? 'point bg-green-500' : 'point bg-red-500'"></div> |
|||
<span style="margin-left: 10px">{{ scope.row.startUsing ? '启动' : '禁用' }}</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="公开" sortable key="slot" width="180"> |
|||
<template #default="scope"> |
|||
<div class="flex flex-row items-center" @click="change(scope.row)"> |
|||
<div :class="scope.row.pub ? 'point bg-green-500' : 'point bg-red-500'"></div> |
|||
<span style="margin-left: 10px">{{ scope.row.pub ? '公开' : '非公开' }}</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column prop="createTime" :formatter="changeDate" label="创建日期" sortable></el-table-column> |
|||
<el-table-column label="操作" key="slot"> |
|||
<template #default="scope"> |
|||
<el-popconfirm |
|||
title="确定删除这条业务吗?" |
|||
confirm-button-text="确定" |
|||
cancel-button-text="再想想" |
|||
@confirm="deleteBusiness(scope.row)" |
|||
> |
|||
<template #reference> |
|||
<el-button type="text" size="small">删除</el-button> |
|||
</template> |
|||
</el-popconfirm> |
|||
<el-button type="text" size="small" disabled>配置</el-button>.. |
|||
<el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
<template slot="empty"> |
|||
<p>没有记录哦~</p> |
|||
</template> |
|||
</el-table> |
|||
</div> |
|||
<el-empty v-else description="暂无业务信息"></el-empty> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from 'vue-router'; |
|||
import { defineProps, defineEmits } from 'vue'; |
|||
import { useStore } from 'vuex'; |
|||
import time from 'utils/time'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { delBusiness } from '@/apis/business.js'; |
|||
|
|||
const router = useRouter(); |
|||
const store = useStore(); |
|||
defineProps({ |
|||
lists: { default: () => [], type: Array }, |
|||
currentPage: { default: 1, type: Number }, |
|||
pageSize: { default: 10, type: Number }, |
|||
total: { default: 0, type: Number }, |
|||
showConfig: { default: false, type: Boolean }, |
|||
}); |
|||
|
|||
const emit = defineEmits(['handleQueryBusiness']); |
|||
|
|||
function change(row) { |
|||
console.log('row: ', row); |
|||
} |
|||
|
|||
function handleClick(row) { |
|||
router.push({ name: 'business-detail', query: { id: row.id } }); |
|||
store.commit('plugin/setBusinessInfo', row); |
|||
} |
|||
|
|||
function changeDate(row) { |
|||
const value = row.createTime; |
|||
return time.dateFormat(value); |
|||
} |
|||
|
|||
/** |
|||
* 删除业务 |
|||
* @param {String} businessId |
|||
*/ |
|||
async function deleteBusiness(row) { |
|||
try { |
|||
// 这里写接口 记得加 async await |
|||
const params = { param: { businessId: row.id } }; |
|||
await delBusiness(params); |
|||
emit('handleQueryBusiness'); |
|||
ElMessage.success('删除成功'); |
|||
} catch (error) { |
|||
ElMessage.error(error || '删除失败'); |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.bg-title >>> thead tr th { |
|||
color: #333; |
|||
background: #fafafa; |
|||
border-top: 1px solid #e8e8e8; |
|||
} |
|||
.bg-title >>> thead tr th:first-child { |
|||
border-left: 1px solid #e8e8e8; |
|||
} |
|||
.bg-title >>> thead tr th:last-child { |
|||
border-right: 1px solid #e8e8e8; |
|||
} |
|||
|
|||
.point { |
|||
width: 6px; |
|||
height: 6px; |
|||
border-radius: 50%; |
|||
} |
|||
</style> |
@ -0,0 +1,69 @@ |
|||
<template> |
|||
<div class="pagination mt-15 flex flex-row-reverse"> |
|||
<el-config-provider :locale="zhCn"> |
|||
<el-pagination |
|||
@size-change="handleSizeChange" |
|||
@current-change="handleCurrentChange" |
|||
:current-page.sync="currentPage" |
|||
:page-size="pageSize" |
|||
layout="prev, pager, next, sizes, jumper" |
|||
:total="total" |
|||
:page-sizes="[10, 15, 20, 30, 40, 50]" |
|||
> |
|||
</el-pagination> |
|||
</el-config-provider> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup="true"> |
|||
import { defineProps, defineEmits } from 'vue'; |
|||
import { ElConfigProvider } from 'element-plus'; |
|||
import zhCn from 'element-plus/lib/locale/lang/zh-cn'; |
|||
|
|||
defineProps({ |
|||
currentPage: { default: 1, type: Number }, |
|||
pageSize: { default: 10, type: Number }, |
|||
total: { default: 0, type: Number }, |
|||
}); |
|||
|
|||
const emit = defineEmits(['handleSizeChange', 'handleCurrentChange']); |
|||
|
|||
function handleSizeChange(val) { |
|||
emit('handleSizeChange', val); |
|||
} |
|||
|
|||
function handleCurrentChange(val) { |
|||
emit('handleCurrentChange', val); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.pagination >>> .el-pager li, |
|||
.pagination >>> .btn-prev, |
|||
.pagination >>> .btn-next { |
|||
border: 1px solid #ccc; |
|||
width: 2rem; |
|||
height: 2rem; |
|||
line-height: 2rem; |
|||
text-align: center; |
|||
padding: 0; |
|||
margin: 0 8px; |
|||
border-radius: 6px; |
|||
font-weight: normal; |
|||
} |
|||
.pagination >>> .el-pager li.active { |
|||
border: 1px solid #409eff; |
|||
color: #fff; |
|||
background: #409eff; |
|||
} |
|||
.pagination >>> .el-input__inner { |
|||
height: 2rem; |
|||
line-height: 2rem; |
|||
border: 1px solid #ccc; |
|||
border-radius: 6px !important; |
|||
} |
|||
|
|||
.pagination >>> .el-pagination__jump { |
|||
margin-left: 0; |
|||
} |
|||
</style> |
@ -0,0 +1,85 @@ |
|||
<template> |
|||
<div class="u-font-14" style="height: 100%"> |
|||
<div v-if="data.pluginContent"> |
|||
<div :data-token="token" :data-uid="userId" style="height: 100%" v-html="data.pluginContent"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed, reactive, nextTick, defineProps } from 'vue'; |
|||
import { useStore } from 'vuex'; |
|||
|
|||
const props = defineProps({ plugin: { default: () => {}, type: Object } }); |
|||
const store = useStore(); |
|||
const token = computed(() => store.state.user.token); |
|||
const userId = computed(() => store.state.user.userId); |
|||
const data = reactive({ pluginContent: null }); |
|||
|
|||
setPlugin(); |
|||
|
|||
// 获取插件信息 |
|||
function setPlugin() { |
|||
let id = ''; |
|||
if (props.plugin) { |
|||
if (props.plugin.id) { |
|||
id = props.plugin.id; |
|||
} |
|||
if (props.plugin.pluginId) { |
|||
id = props.plugin.pluginId; |
|||
} |
|||
} |
|||
if (!props.plugin || !id) { |
|||
previewAddPlugin(); |
|||
return; |
|||
} |
|||
const reg = /data-root=["|']?(\w+)["|']?/gi; |
|||
let uuid = ''; |
|||
// FIXME: 没有兼容 只有js, 没有html的情况 |
|||
if (props.plugin.html) { |
|||
// 查有没有data-root=“xxx” 有的话 将xxx替换为 pluginTaskId |
|||
if (reg.test(props.plugin.html)) { |
|||
uuid = RegExp.$1; |
|||
const str = props.plugin.html.replace(new RegExp(uuid, 'g'), `p${id}`); |
|||
data.pluginContent = str; |
|||
} else { |
|||
data.pluginContent = props.plugin.html; |
|||
} |
|||
const str = props.plugin.js.replace(new RegExp(uuid, 'g'), `p${id}`); |
|||
handleDom(str, id); |
|||
} |
|||
} |
|||
|
|||
// 创建script dom |
|||
function handleDom(js, id) { |
|||
const domList = Array.from(document.getElementsByTagName('script')); |
|||
const index = domList.findIndex(item => item.id === `p${id}`); |
|||
if (index >= 0) { |
|||
document.body.removeChild(document.getElementById(`p${id}`)); |
|||
} |
|||
const scriptDom = document.createElement('script'); |
|||
scriptDom.id = `p${id}`; |
|||
scriptDom.setAttribute('data-type', 'plugin'); |
|||
scriptDom.innerHTML = js; |
|||
nextTick(() => { |
|||
document.body.append(scriptDom); |
|||
}); |
|||
} |
|||
|
|||
// 没有id |
|||
function previewAddPlugin() { |
|||
console.log('props.plugin: ', props.plugin); |
|||
// FIXME: 没有兼容 只有js, 没有html的情况 |
|||
if (props.plugin.html) { |
|||
// 查有没有data-root=“xxx” 有的话 将xxx替换为 pluginTaskId |
|||
data.pluginContent = props.plugin.html; |
|||
const scriptDom = document.createElement('script'); |
|||
scriptDom.setAttribute('data-type', 'plugin'); |
|||
scriptDom.innerHTML = props.plugin.js; |
|||
console.log('scriptDom: ', scriptDom); |
|||
nextTick(() => { |
|||
document.body.append(scriptDom); |
|||
}); |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,113 @@ |
|||
<template> |
|||
<div v-if="lists && lists.length"> |
|||
<el-table :data="lists" class="bg-title" style="width: 100%"> |
|||
<el-table-column prop="name" label="插件名称"> </el-table-column> |
|||
<el-table-column prop="appId" label="APPID"> </el-table-column> |
|||
<el-table-column prop="startUsing" label="状态" key="slot" sortable> |
|||
<template #default="scope"> |
|||
<div class="flex flex-row items-center" @click="change(scope.row)"> |
|||
<div :class="!scope.row.startUsing ? 'point bg-green-500' : 'point bg-red-500'"></div> |
|||
<span style="margin-left: 10px">{{ !scope.row.startUsing ? '启动' : '禁用' }}</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column prop="pub" label="公开" sortable key="slot"> |
|||
<template #default="scope"> |
|||
<div class="flex flex-row items-center" @click="change(scope.row)"> |
|||
<div :class="!scope.row.pub ? 'point bg-green-500' : 'point bg-red-500'"></div> |
|||
<span style="margin-left: 10px">{{ !scope.row.pub ? '公开' : '非公开' }}</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column prop="createTime" :formatter="changeCreateDate" label="创建日期" sortable></el-table-column> |
|||
<el-table-column prop="updateTime" :formatter="changeUpdateDate" label="更新日期" sortable></el-table-column> |
|||
<el-table-column label="操作" key="slot"> |
|||
<template #default="scope"> |
|||
<el-popconfirm |
|||
title="确定删除这条业务吗?" |
|||
confirm-button-text="确定" |
|||
cancel-button-text="再想想" |
|||
@confirm="deletePlugin(scope.row)" |
|||
> |
|||
<template #reference> |
|||
<el-button type="text" size="small">删除</el-button> |
|||
</template> |
|||
</el-popconfirm> |
|||
<el-button type="text" size="small" disabled>配置</el-button>.. |
|||
<el-button type="text" size="small" disabled>查看</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
<template slot="empty"> |
|||
<p>没有记录哦~</p> |
|||
</template> |
|||
</el-table> |
|||
</div> |
|||
<el-empty v-else description="暂无业务信息"></el-empty> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { defineProps, defineEmits } from 'vue'; |
|||
import time from 'utils/time'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { delPlugin } from '@/apis/plugin.js'; |
|||
|
|||
defineProps({ |
|||
lists: { default: () => [], type: Array }, |
|||
currentPage: { default: 1, type: Number }, |
|||
pageSize: { default: 10, type: Number }, |
|||
total: { default: 0, type: Number }, |
|||
showConfig: { default: false, type: Boolean }, |
|||
}); |
|||
|
|||
const emit = defineEmits(['handleQueryPlugins']); |
|||
|
|||
function change(row) { |
|||
console.log('row: ', row); |
|||
} |
|||
|
|||
function changeCreateDate(row) { |
|||
const value = row && row.createTime ? row.createTime : ''; |
|||
return time.dateFormat(value); |
|||
} |
|||
|
|||
function changeUpdateDate(row) { |
|||
const value = row && row.updateTime ? row.updateTime : ''; |
|||
return time.dateFormat(value); |
|||
} |
|||
|
|||
/** |
|||
* 删除插件 |
|||
* @param {String} businessId |
|||
*/ |
|||
async function deletePlugin(row) { |
|||
try { |
|||
const params = { param: { id: row.id } }; |
|||
await delPlugin(params); |
|||
ElMessage.success('删除成功'); |
|||
emit('handleQueryPlugins'); |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
ElMessage.error(error || '删除失败'); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.bg-title >>> thead tr th { |
|||
color: #333; |
|||
background: #fafafa; |
|||
border-top: 1px solid #e8e8e8; |
|||
} |
|||
.bg-title >>> thead tr th:first-child { |
|||
border-left: 1px solid #e8e8e8; |
|||
} |
|||
.bg-title >>> thead tr th:last-child { |
|||
border-right: 1px solid #e8e8e8; |
|||
} |
|||
|
|||
.point { |
|||
width: 6px; |
|||
height: 6px; |
|||
border-radius: 50%; |
|||
} |
|||
</style> |
@ -0,0 +1,71 @@ |
|||
<template> |
|||
<el-scrollbar height="200px" @scroll="scroll"> |
|||
<el-radio @change="chooseBusiness" v-model="data.isCollapse" :label="business.id" v-for="business in businessLists" :key="business.id"> |
|||
{{ business.name }} |
|||
</el-radio> |
|||
<div class="loading my-2" v-if="!businessLists.length">暂无数据</div> |
|||
<div class="loading my-2" v-else>{{ isLastPage ? '到底啦~' : '加载中...' }}</div> |
|||
</el-scrollbar> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { reactive, defineProps, defineEmits } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { relevance } from '@/apis/business.js'; |
|||
|
|||
const props = defineProps({ |
|||
businessLists: { default: () => [], type: Array }, |
|||
pluginId: { default: '', type: String }, |
|||
businessId: { default: '', type: String }, |
|||
isLastPage: { default: false, type: Boolean }, |
|||
}); |
|||
|
|||
const emit = defineEmits(['changePageNum', 'query']); |
|||
|
|||
const data = reactive({ |
|||
isCollapse: '', |
|||
showLoading: false, |
|||
scrollTop: 0, |
|||
}); |
|||
|
|||
function scroll(e) { |
|||
if (props.isLastPage) return; |
|||
data.scrollTop = e.scrollTop; |
|||
if (e.scrollTop === 220) { |
|||
emit('changePageNum'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 关联业务和插件 |
|||
* @param {string} businessId 业务id |
|||
* @param {string} pluginId 插件id |
|||
*/ |
|||
async function chooseBusiness(e) { |
|||
try { |
|||
data.isCollapse = e; |
|||
const params = { |
|||
param: { |
|||
businessId: props.businessId ? props.businessId : e, |
|||
pluginId: props.pluginId ? props.pluginId : e, |
|||
}, |
|||
}; |
|||
await relevance(params); |
|||
ElMessage.success('关联成功'); |
|||
if (props.businessId) { |
|||
emit('query', props.businessId); |
|||
} |
|||
} catch (error) { |
|||
ElMessage.error(error || '关联失败'); |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.loading { |
|||
width: 100%; |
|||
text-align: center; |
|||
color: #aaa; |
|||
} |
|||
</style> |
@ -0,0 +1,136 @@ |
|||
<template> |
|||
<!-- 热门插件 --> |
|||
<div class="flex flex-row justify-space-between items-center"> |
|||
<div class="font-bold"> |
|||
热门插件: |
|||
<el-button plain size="mini" v-for="(tag, tagIndex) in data.tags" :key="tagIndex" class="cursor-pointer">{{ tag }}</el-button> |
|||
</div> |
|||
<div class="flex-1"></div> |
|||
<div class="flex flex-row"> |
|||
<el-input disabled v-model="data.keywords" placeholder="请输入插件名或标签名搜索" class="search-input" /> |
|||
<el-button type="primary" size="small" class="w-60px h-40px" disabled>搜索</el-button> |
|||
<el-button type="primary" icon="el-icon-plus" size="small" class="h-40px" @click="openPage">创建插件</el-button> |
|||
</div> |
|||
</div> |
|||
<!-- 所属行业 --> |
|||
<div class="types"> |
|||
所属行业: |
|||
<div |
|||
class="type" |
|||
:class="industry.checked ? 'check' : ''" |
|||
v-for="(industry, industryIndex) in data.industryList" |
|||
:key="industryIndex" |
|||
@click="changeIndustryCheck(industryIndex)" |
|||
> |
|||
{{ industry.value }} |
|||
</div> |
|||
</div> |
|||
<div class="line"></div> |
|||
<div class="types"> |
|||
所属分类: |
|||
<div |
|||
class="type" |
|||
:class="sort.checked ? 'check' : ''" |
|||
v-for="(sort, sortIndex) in data.sortList" |
|||
:key="sortIndex" |
|||
@click="changeSortCheck(sortIndex)" |
|||
> |
|||
{{ sort.value }} |
|||
</div> |
|||
</div> |
|||
<div class="line"></div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup="true"> |
|||
import { reactive } from 'vue'; |
|||
import { useRouter } from 'vue-router'; |
|||
import { useStore } from 'vuex'; |
|||
|
|||
const router = useRouter(); |
|||
const store = useStore(); |
|||
|
|||
const data = reactive({ |
|||
tags: [], |
|||
// tags: ['交付物', '财务条', '签到打卡', '即时奖惩'], |
|||
keywords: '', |
|||
industryList: [ |
|||
// { |
|||
// value: '行业一', |
|||
// label: '行业一', |
|||
// checked: true, |
|||
// }, |
|||
// { |
|||
// value: '行业二', |
|||
// label: '行业二', |
|||
// checked: false, |
|||
// }, |
|||
// { |
|||
// value: '行业三', |
|||
// label: '行业三', |
|||
// checked: false, |
|||
// } |
|||
], |
|||
sortList: [ |
|||
// { |
|||
// value: '分类一', |
|||
// label: '分类一', |
|||
// checked: false, |
|||
// }, |
|||
// { |
|||
// value: '分类二', |
|||
// label: '分类二', |
|||
// checked: true, |
|||
// }, |
|||
// { |
|||
// value: '分类三', |
|||
// label: '分类三', |
|||
// checked: false, |
|||
// }, |
|||
], |
|||
}); |
|||
|
|||
function changeIndustryCheck(index) { |
|||
data.industryList[index].checked = !data.industryList[index].checked; |
|||
} |
|||
|
|||
function changeSortCheck(index) { |
|||
data.sortList[index].checked = !data.sortList[index].checked; |
|||
} |
|||
|
|||
function openPage() { |
|||
router.push({ name: 'desk-add-plugin' }); |
|||
store.commit('plugin/setLeftIndex', 2); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.search-input { |
|||
width: 27.3125rem; |
|||
} |
|||
|
|||
.types { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
align-items: center; |
|||
margin: 8px 0; |
|||
} |
|||
|
|||
.types .type { |
|||
height: 2rem; |
|||
line-height: 2rem; |
|||
cursor: pointer; |
|||
padding: 0 12px; |
|||
margin: 6px 20px; |
|||
} |
|||
|
|||
.types .check { |
|||
color: #fff; |
|||
background: #409eff; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
.line { |
|||
width: 100%; |
|||
border-bottom: 1px dashed #ebebeb; |
|||
} |
|||
</style> |
@ -1,14 +1,27 @@ |
|||
import { createStore } from 'vuex'; |
|||
import user from './user'; |
|||
import plugin from './plugin'; |
|||
|
|||
export default createStore({ |
|||
modules: { user }, |
|||
state: { menu: { show: true, collapse: false } }, |
|||
modules: { user, plugin }, |
|||
state: { |
|||
menu: { show: true, collapse: false }, |
|||
systemInfo: null, // 系统设备信息
|
|||
}, |
|||
getters: {}, |
|||
mutations: { |
|||
toggleCollapse(state) { |
|||
state.menu.collapse = !state.menu.collapse; |
|||
}, |
|||
|
|||
/** |
|||
* 设置系统信息的数据 |
|||
* @param {object} state |
|||
* @param {object | null} data 获取到的数据 |
|||
*/ |
|||
setSystemInfo(state, data) { |
|||
state.systemInfo = data; |
|||
}, |
|||
}, |
|||
actions: {}, |
|||
}); |
|||
|
@ -0,0 +1,26 @@ |
|||
export default { |
|||
namespaced: true, |
|||
state: { leftIndex: 3, businessInfo: {} }, |
|||
getters: {}, |
|||
mutations: { |
|||
/** |
|||
* 设置控制台左侧菜单栏 |
|||
* @param {*} state |
|||
* @param {number} data |
|||
*/ |
|||
setLeftIndex(state, data) { |
|||
state.leftIndex = data; |
|||
}, |
|||
|
|||
/** |
|||
* 设置当前查看的业务信息 |
|||
* @param {*} state |
|||
* @param {object|null} data |
|||
*/ |
|||
setBusinessInfo(state, data) { |
|||
state.businessInfo = data; |
|||
}, |
|||
}, |
|||
|
|||
actions: {}, |
|||
}; |
@ -0,0 +1,18 @@ |
|||
const time = { |
|||
dateFormat(value) { |
|||
if (value) { |
|||
const date = new Date(Number(value)); // 时间戳为秒:13位数
|
|||
// let date = new Date(value * 1000) // 时间戳为毫秒:10位数
|
|||
const year = date.getFullYear(); |
|||
const month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : date.getMonth() + 1; |
|||
const day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate(); |
|||
const hour = date.getHours() < 10 ? `0${date.getHours()}` : date.getHours(); |
|||
const minute = date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes(); |
|||
const second = date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds(); |
|||
return `${year}-${month}-${day} ${hour}:${minute}:${second}`; |
|||
} |
|||
return ''; |
|||
}, |
|||
}; |
|||
|
|||
export default time; |
@ -1,3 +1,34 @@ |
|||
<template> |
|||
index.vue |
|||
<el-container> |
|||
<el-header> |
|||
<div class="top"> |
|||
<Navbar /> |
|||
</div> |
|||
</el-header> |
|||
<el-main> |
|||
<div class="bg-white p-6"> |
|||
<router-view></router-view> |
|||
</div> |
|||
</el-main> |
|||
</el-container> |
|||
</template> |
|||
|
|||
<script> |
|||
export default {}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.el-header { |
|||
background: #00182e; |
|||
color: #fff; |
|||
} |
|||
.el-main { |
|||
padding: 1.6rem 12rem; |
|||
background: #f5f5f5; |
|||
} |
|||
|
|||
.top { |
|||
/* padding: 2rem 10rem; */ |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,140 @@ |
|||
<template> |
|||
<div class="box"> |
|||
<h1 class="text-lg font-semibold">配置业务</h1> |
|||
<el-form ref="formRef" :model="form" :rules="rules" label-width="150px" class="forms"> |
|||
<el-form-item prop="name"> |
|||
<template v-slot:label> |
|||
<el-tooltip class="box-item" effect="dark" content="输入帮助" placement="top-end"> |
|||
<div>业务名称:</div> |
|||
</el-tooltip> |
|||
</template> |
|||
<el-input v-model="form.name" placeholder="输入业务名称"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="行业:" prop="region"> |
|||
<el-select v-model="form.region" placeholder="请选择"> |
|||
<el-option value="教育"></el-option> |
|||
<el-option value="医疗"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="分类:" prop="sort"> |
|||
<el-select v-model="form.sort" multiple placeholder="请选择,可多选"> |
|||
<el-option value="康复"></el-option> |
|||
<el-option value="管理"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="标签:" prop="tags"> |
|||
<el-select v-model="form.tags" multiple filterable allow-create default-first-option placeholder="请选择标签"> |
|||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="详情:" prop="description"> |
|||
<el-input v-model="form.description" type="textarea" placeholder="请输入备注"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="是否公开:" prop="pub"> |
|||
<el-switch v-model="form.pub" class="mr-3"></el-switch> |
|||
</el-form-item> |
|||
<el-form-item label="是否启用:" prop="startUsing"> |
|||
<el-switch v-model="form.startUsing" class="mr-3"></el-switch> |
|||
</el-form-item> |
|||
<!-- <el-form-item label="是否开启debug模式:" prop="debug"> |
|||
<el-switch v-model="form.debug" class="mr-3"></el-switch> |
|||
</el-form-item> --> |
|||
<el-form-item> <el-switch v-model="form.debug" class="mr-3"></el-switch> 是否开启debug模式 </el-form-item> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="onSubmit()">发布</el-button> |
|||
<el-button @click="resetForm()">重置</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, reactive } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { saveBusiness } from '@/apis/business.js'; |
|||
|
|||
const formRef = ref(null); |
|||
const form = reactive({ |
|||
name: '', |
|||
region: '', |
|||
sort: '', |
|||
tags: '', |
|||
description: '', |
|||
pub: false, |
|||
startUsing: false, |
|||
debug: false, |
|||
}); |
|||
|
|||
const rules = { |
|||
name: [{ required: true, message: '输入业务名称', trigger: 'blur' }], |
|||
region: [{ required: true, message: '请选择行业', trigger: 'blur' }], |
|||
sort: [{ required: true, message: '请选择分类', trigger: 'blur' }], |
|||
}; |
|||
|
|||
/** |
|||
* 创建业务 |
|||
*/ |
|||
const onSubmit = () => { |
|||
try { |
|||
formRef.value.validate(async valid => { |
|||
if (valid) { |
|||
const params = {}; |
|||
params.param = form; |
|||
params.param.pub = form.pub ? 1 : 0; |
|||
params.param.startUsing = form.startUsing ? 1 : 0; |
|||
params.param.debug = form.debug ? 1 : 0; |
|||
await saveBusiness(params); |
|||
ElMessage.success('创建成功'); |
|||
resetForm(); |
|||
} else { |
|||
return false; |
|||
} |
|||
}); |
|||
} catch (error) { |
|||
ElMessage.error(error || '创建失败'); |
|||
console.log('error: ', error); |
|||
} |
|||
}; |
|||
|
|||
function resetForm() { |
|||
formRef.value.resetFields(); |
|||
} |
|||
const options = [ |
|||
{ |
|||
value: 'HTML', |
|||
label: 'HTML', |
|||
}, |
|||
{ |
|||
value: 'CSS', |
|||
label: 'CSS', |
|||
}, |
|||
{ |
|||
value: 'JavaScript', |
|||
label: 'JavaScript', |
|||
}, |
|||
]; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.el-form-item { |
|||
margin-top: 1rem; |
|||
} |
|||
.tags { |
|||
width: 100%; |
|||
} |
|||
.el-select { |
|||
width: 100%; |
|||
} |
|||
.box >>> .el-form-item__label { |
|||
display: flex; |
|||
flex-direction: row-reverse; |
|||
justify-content: end; |
|||
flex: 0 0 auto; |
|||
text-align: right; |
|||
font-size: var(--el-form-label-font-size); |
|||
color: var(--el-text-color-regular); |
|||
line-height: 40px; |
|||
padding: 0 12px 0 0; |
|||
box-sizing: border-box; |
|||
} |
|||
</style> |
@ -0,0 +1,350 @@ |
|||
<template> |
|||
<div class="box"> |
|||
<h1 class="text-lg font-semibold">上传插件</h1> |
|||
<el-form ref="formRef" :model="form" :rules="rules" label-width="150px" class="forms"> |
|||
<el-form-item label="插件id:" prop="id"> |
|||
<div v-if="form.id"> |
|||
{{ form.id }} |
|||
<i class="el-icon-document-copy cursor-pointer ml-2" @click="copy(form.id)"></i> |
|||
</div> |
|||
<el-button type="success" plain size="mini" @click="handelPluginId" v-else>点击生成插件id</el-button> |
|||
</el-form-item> |
|||
<el-form-item prop="name"> |
|||
<template v-slot:label> |
|||
<el-tooltip class="box-item" effect="dark" content="输入帮助" placement="top-end"> |
|||
<div>插件名称 ①:</div> |
|||
</el-tooltip> |
|||
</template> |
|||
<el-input v-model="form.name" placeholder="输入插件名称"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="版本:" prop="versions"> |
|||
<el-input v-model="form.versions" placeholder="请输入"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="简介:" prop="intro"> |
|||
<el-input v-model="form.intro" type="textarea" placeholder="请输入备注"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="行业:" prop="region"> |
|||
<el-select v-model="form.region" placeholder="请选择"> |
|||
<el-option value="教育"></el-option> |
|||
<el-option value="医疗"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="分类:" prop="sort"> |
|||
<el-select v-model="form.sort" multiple placeholder="请选择,可多选"> |
|||
<el-option value="康复"></el-option> |
|||
<el-option value="管理"></el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="标签:" prop="tags"> |
|||
<el-select v-model="form.tags" multiple filterable allow-create default-first-option placeholder="请选择标签"> |
|||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"> </el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
<el-form-item label="HTML:" prop="html"> |
|||
<el-input v-model="form.html" type="textarea" placeholder="请输入HTML代码片段"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="JS:" prop="js"> |
|||
<el-input v-model="form.js" type="textarea" placeholder="请输入JS代码片段"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="CSS:" prop="css"> |
|||
<el-input v-model="form.css" type="textarea" placeholder="请输入CSS代码片段"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="配置文件:" prop="config"> |
|||
<el-input v-model="form.config" type="textarea" placeholder="请输入配置文件"></el-input> |
|||
</el-form-item> |
|||
<el-form-item label="上传预览图:" prop="preview"> |
|||
<el-upload |
|||
class="avatar-uploader" |
|||
:action="`${apiUrl}/filedeal/file/upload/single`" |
|||
:show-file-list="false" |
|||
:on-success="handleAvatarSuccess" |
|||
:before-upload="beforeAvatarUpload" |
|||
> |
|||
<img v-if="form.preview" :src="form.preview" class="avatar" /> |
|||
<i v-else class="el-icon-plus avatar-uploader-icon"></i> |
|||
</el-upload> |
|||
</el-form-item> |
|||
<el-form-item prop="carousel"> |
|||
<template v-slot:label> |
|||
<el-tooltip class="box-item" effect="dark" content="输入帮助" placement="top-end"> |
|||
<div>上传轮播图 ①:</div> |
|||
</el-tooltip> |
|||
</template> |
|||
<el-upload |
|||
class="upload-dialog" |
|||
name="files" |
|||
:action="`${apiUrl}/filedeal/file/upload/multiple`" |
|||
list-type="picture-card" |
|||
:on-success="handleBannerSuccess" |
|||
:on-remove="handleRemove" |
|||
ref="bannerUpload" |
|||
> |
|||
<i class="el-icon-plus"></i> |
|||
</el-upload> |
|||
<el-dialog :visible.sync="form.dialogVisible"> |
|||
<img width="100%" :src="form.banner" alt="" v-if="form.dialogVisible" /> |
|||
</el-dialog> |
|||
</el-form-item> |
|||
<el-form-item label="README:" prop="description"> |
|||
<el-input v-model="form.description" type="textarea" placeholder="请输入markdown详细介绍信息"></el-input> |
|||
</el-form-item> |
|||
<!-- <el-form-item> <el-switch v-model="form.delivery" class="mr-3"></el-switch> 是否压缩代码 </el-form-item> --> |
|||
<el-form-item> |
|||
<el-button type="primary" @click="onSubmit()">发布</el-button> |
|||
<el-button @click="resetForm()">重置</el-button> |
|||
|
|||
<el-button type="success" @click="visible = !visible">{{ !visible ? '预览' : '关闭预览' }}</el-button> |
|||
<div class="plugin-box" v-if="visible"> |
|||
<div class="plugin w-full h-full overflow-y-scroll"> |
|||
<Plugin :plugin="form" /> |
|||
</div> |
|||
</div> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import useClipboard from 'vue-clipboard3'; |
|||
import { ref, reactive } from 'vue'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { randomId, savePlugin } from '@/apis/plugin'; |
|||
|
|||
const { toClipboard } = useClipboard(); |
|||
|
|||
const apiUrl = import.meta.env.VITE_API_URL_NEW; |
|||
|
|||
const formRef = ref(null); |
|||
const bannerUpload = ref(null); |
|||
const visible = ref(false); |
|||
const form = reactive({ |
|||
id: '', |
|||
name: '', |
|||
versions: 'V1.0.0', |
|||
intro: '', |
|||
region: '', |
|||
sort: '', |
|||
tags: '', |
|||
html: '', |
|||
js: '', |
|||
css: '', |
|||
config: '', |
|||
delivery: '', |
|||
preview: '', |
|||
carousel: [], |
|||
dialogVisible: false, |
|||
description: '', |
|||
banner: '', |
|||
}); |
|||
|
|||
const rules = { |
|||
id: [{ required: true, message: '请先生成插件id', trigger: 'blur' }], |
|||
name: [{ required: true, message: '请输入插件名称', trigger: 'blur' }], |
|||
versions: [{ required: true, message: '请输入版本号', trigger: 'blur' }], |
|||
// region: [{ required: true, message: '请选择行业', trigger: 'blur' }], |
|||
// sort: [{ required: true, message: '请选择分类', trigger: 'blur' }], |
|||
// tags: [{ required: true, message: '请选择标签', trigger: 'blur' }], |
|||
preview: [{ required: true, message: '请上传预览图', trigger: 'blur' }], |
|||
carousel: [{ required: true, message: '请上传轮播图', trigger: 'blur' }], |
|||
}; |
|||
|
|||
const options = [ |
|||
{ |
|||
value: 'HTML', |
|||
label: 'HTML', |
|||
}, |
|||
{ |
|||
value: 'CSS', |
|||
label: 'CSS', |
|||
}, |
|||
{ |
|||
value: 'JavaScript', |
|||
label: 'JavaScript', |
|||
}, |
|||
]; |
|||
|
|||
/** |
|||
* 获取插件id |
|||
*/ |
|||
async function handelPluginId() { |
|||
try { |
|||
const res = await randomId(); |
|||
form.id = res; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
handelPluginId(); |
|||
|
|||
// 复制 |
|||
async function copy(Msg) { |
|||
try { |
|||
// 复制 |
|||
await toClipboard(Msg); |
|||
ElMessage.success('插件id复制成功'); |
|||
} catch (e) { |
|||
// 复制失败 |
|||
console.error(e); |
|||
ElMessage.error('插件id复制失败'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 创建插件 |
|||
* @param {object} params |
|||
*/ |
|||
function onSubmit() { |
|||
try { |
|||
formRef.value.validate(async valid => { |
|||
if (valid) { |
|||
console.log('submit!'); |
|||
const params = {}; |
|||
params.param = form; |
|||
await savePlugin(params); |
|||
ElMessage.success('插件创建成功'); |
|||
resetForm(); |
|||
bannerUpload.value.clearFiles(); |
|||
} else { |
|||
console.log('error submit!!'); |
|||
return false; |
|||
} |
|||
}); |
|||
} catch (error) { |
|||
ElMessage.error(error || '插件创建失败'); |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 上传预览图 |
|||
* @param {*} res |
|||
* @param {*} file |
|||
*/ |
|||
function handleAvatarSuccess(res) { |
|||
if (res.data && res.data.visitUrl) { |
|||
form.preview = res.data.visitUrl; |
|||
} |
|||
} |
|||
|
|||
function beforeAvatarUpload(file) { |
|||
// const isJPG = file.type === 'image/jpeg'; |
|||
const isLt2M = file.size / 1024 / 1024 < 2; |
|||
|
|||
// if (!isJPG) { |
|||
// ElMessage.error('上传头像图片只能是 JPG 格式!'); |
|||
// } |
|||
if (!isLt2M) { |
|||
ElMessage.error('上传头像图片大小不能超过 2MB!'); |
|||
} |
|||
return isLt2M; |
|||
} |
|||
|
|||
// 删除轮播图 |
|||
function handleRemove(res) { |
|||
if (res.response.data && res.response.data.length) { |
|||
const url = res.response.data[0].visitUrl; |
|||
const index = form.carousel.findIndex(item => item === url); |
|||
form.carousel.splice(index, 1); |
|||
} |
|||
} |
|||
|
|||
// 上传轮播图 |
|||
function handleBannerSuccess(res) { |
|||
if (res.data && res.data.length) { |
|||
form.dialogVisible = true; |
|||
form.banner = res.data[0].visitUrl; |
|||
res.data.forEach(item => { |
|||
if (item && item.id) { |
|||
form.carousel.push(item.visitUrl); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
// 重置 |
|||
function resetForm() { |
|||
formRef.value.resetFields(); |
|||
handelPluginId(); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.box { |
|||
/* padding-left: 5%; */ |
|||
} |
|||
.el-form-item { |
|||
margin-top: 1rem; |
|||
} |
|||
.tags { |
|||
width: 100%; |
|||
} |
|||
.el-select { |
|||
width: 100%; |
|||
} |
|||
.box >>> .el-form-item__label { |
|||
display: flex; |
|||
flex-direction: row-reverse; |
|||
justify-content: end; |
|||
flex: 0 0 auto; |
|||
text-align: right; |
|||
font-size: var(--el-form-label-font-size); |
|||
color: var(--el-text-color-regular); |
|||
line-height: 40px; |
|||
padding: 0 12px 0 0; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.avatar-uploader >>> .el-upload { |
|||
border: 1px dashed #d9d9d9; |
|||
border-radius: 6px; |
|||
cursor: pointer; |
|||
position: relative; |
|||
overflow: hidden; |
|||
} |
|||
.avatar-uploader >>> .el-upload:hover { |
|||
border-color: #409eff; |
|||
} |
|||
.avatar-uploader-icon { |
|||
font-size: 28px; |
|||
color: #8c939d; |
|||
width: 104px; |
|||
height: 104px; |
|||
line-height: 104px; |
|||
text-align: center; |
|||
background: #fafafa; |
|||
} |
|||
.avatar { |
|||
width: 104px; |
|||
height: 104px; |
|||
display: block; |
|||
} |
|||
|
|||
.upload-dialog >>> .el-upload--picture-card { |
|||
width: 104px; |
|||
height: 104px; |
|||
line-height: 104px; |
|||
background: #fafafa; |
|||
} |
|||
|
|||
.upload-dialog >>> .el-upload-list--picture-card .el-upload-list__item { |
|||
width: 104px; |
|||
height: 104px; |
|||
} |
|||
|
|||
.plugin-box { |
|||
position: fixed; |
|||
right: 14rem; |
|||
background: url(../../assets/iPhone13.png) no-repeat; |
|||
background-size: contain; |
|||
width: 19.375rem; |
|||
height: 39.2419rem; |
|||
top: calc(50vh - 289.93512px + 1.8rem); |
|||
padding: 2.8rem 1.2rem 2rem; |
|||
z-index: 99; |
|||
} |
|||
|
|||
.plugin::-webkit-scrollbar { |
|||
display: none; |
|||
} |
|||
</style> |
@ -0,0 +1,194 @@ |
|||
<template> |
|||
<breadcrumb :path="data.path" /> |
|||
|
|||
<div class="pt-12"> |
|||
<h1 class="text-lg font-semibold">业务名称</h1> |
|||
<div class="flex flex-col" v-if="data.info && data.info.id"> |
|||
<div class="mt-3"> |
|||
APPID: {{ data.info.appId }} |
|||
<i class="el-icon-document-copy cursor-pointer ml-2" @click="copy(data.info.appId)"></i> |
|||
</div> |
|||
<div class="mt-3">APPSecret: {{ data.info.secret }}</div> |
|||
<div class="mt-3">简介: {{ data.info.description }}</div> |
|||
<div class="flex flex-row mt-3"> |
|||
<div class="text-sm mr-20" v-if="data.info.tags && data.info.tags.length"> |
|||
<el-tag v-for="item in data.info.tags" :type="item.btnType" class="mr-3" :key="item.name">{{ item.name }}</el-tag> |
|||
</div> |
|||
<div>行业: {{ data.info.appId }}</div> |
|||
</div> |
|||
<div class="flex flex-row mt-3"> |
|||
<div class="mr-20">创建时间: {{ time.dateFormat(data.info.createTime) }}</div> |
|||
<div>最新更新时间: {{ time.dateFormat(data.info.createTime) }}</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="flex flex-col py-12"> |
|||
<div class="flex flex-nowrap justify-between"> |
|||
<h1 class="text-lg font-semibold">已绑定插件</h1> |
|||
<el-popover placement="bottom" title="请选择插件" :width="240" trigger="click"> |
|||
<div class="radio-box"> |
|||
<Relevance |
|||
:businessLists="data.pluginLists" |
|||
:businessId="data.info.id" |
|||
:isLastPage="data.isLastPage" |
|||
@changePageNum="changePageNum" |
|||
@query="queryPluginOfBusiness" |
|||
/> |
|||
</div> |
|||
<template #reference> |
|||
<el-button type="primary" @click="handleQueryPlugin">添加插件</el-button> |
|||
</template> |
|||
</el-popover> |
|||
</div> |
|||
<listPlugin :lists="data.lists" :showConfig="true" :businessId="data.businessId" @queryPluginOfBusiness="queryPluginOfBusiness" /> |
|||
<Pagination |
|||
:currentPage="data.currentPage" |
|||
:pageSize="data.pageSize" |
|||
:total="data.total" |
|||
@handleSizeChange="handleSizeChange" |
|||
@handleCurrentChange="handleCurrentChange" |
|||
/> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import useClipboard from 'vue-clipboard3'; |
|||
import { reactive } from 'vue'; |
|||
import { useRouter } from 'vue-router'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import time from 'utils/time'; |
|||
import { queryPluginByBusiness, queryIdBusiness } from '@/apis/business.js'; |
|||
import { queryPlugins } from '@/apis/plugin.js'; |
|||
|
|||
const router = useRouter(); |
|||
const { toClipboard } = useClipboard(); |
|||
|
|||
const data = reactive({ |
|||
path: [ |
|||
{ title: '控制台', name: 'plugin-shop' }, |
|||
{ title: '我的业务', name: 'desk-business-list' }, |
|||
{ title: '业务详情', name: 'desk-add-business' }, |
|||
], |
|||
lists: [], |
|||
currentPage: 1, |
|||
pageSize: 10, |
|||
total: 0, |
|||
info: {}, |
|||
pluginLists: [], |
|||
isLastPage: false, |
|||
pageNum: 1, |
|||
businessId: '', |
|||
}); |
|||
|
|||
function handleSizeChange(val) { |
|||
data.pageSize = val; |
|||
queryPluginOfBusiness(); |
|||
} |
|||
|
|||
function handleCurrentChange(val) { |
|||
data.currentPage = val; |
|||
queryPluginOfBusiness(); |
|||
} |
|||
|
|||
// 复制 |
|||
async function copy(Msg) { |
|||
try { |
|||
// 复制 |
|||
await toClipboard(Msg); |
|||
ElMessage.success('复制成功'); |
|||
} catch (e) { |
|||
// 复制失败 |
|||
console.error(e); |
|||
ElMessage.error('复制失败'); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 通过id查询业务信息 |
|||
* @param {string} businessId 业务信息对应的id |
|||
*/ |
|||
async function handleQueryIdBusiness(businessId) { |
|||
try { |
|||
const params = { param: { businessId } }; |
|||
const res = await queryIdBusiness(params); |
|||
data.info = res; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 查询业务下关联的插件 |
|||
* @param {string} businessId 业务信息对应的id |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function queryPluginOfBusiness() { |
|||
try { |
|||
const { currentPage, pageSize, businessId } = data; |
|||
const params = { |
|||
param: { |
|||
businessId, |
|||
pageNum: currentPage, |
|||
pageSize, |
|||
}, |
|||
}; |
|||
const res = await queryPluginByBusiness(params); |
|||
data.lists = res.list; |
|||
data.currentPage = res.pageNum - 0; |
|||
data.pageSize = res.pageSize - 0; |
|||
data.total = res.total - 0; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
const routeValue = router.currentRoute.value; |
|||
const id = routeValue && routeValue.query && routeValue.query.id ? routeValue.query.id : ''; |
|||
data.businessId = id; |
|||
queryPluginOfBusiness(id); |
|||
handleQueryIdBusiness(id); |
|||
|
|||
function changePageNum() { |
|||
data.pageNum++; |
|||
handleQueryPlugin(); |
|||
} |
|||
|
|||
/** |
|||
* 查询插件列表 |
|||
* @param {number} depth 查询深度 0则只查名称,1则查询全部 |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function handleQueryPlugin() { |
|||
try { |
|||
const { pageNum } = data; |
|||
if (pageNum === 1) { |
|||
data.pluginLists = []; |
|||
} |
|||
const params = { |
|||
param: { |
|||
depth: 0, |
|||
name: '', |
|||
pageNum, |
|||
pageSize: 10, |
|||
}, |
|||
}; |
|||
const res = await queryPlugins(params); |
|||
if (res.list.length) { |
|||
res.list.forEach(item => { |
|||
data.pluginLists.push(item); |
|||
}); |
|||
} |
|||
data.pageNum = res.pageNum - 0; |
|||
data.isLastPage = res.isLastPage; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style></style> |
@ -0,0 +1,79 @@ |
|||
<template> |
|||
<div class="flex flex-col"> |
|||
<listSearchBar /> |
|||
<div class="py-6"> |
|||
<el-button type="primary" icon="el-icon-plus" @click="openPage">创建业务</el-button> |
|||
</div> |
|||
<listTable :lists="data.lists" @handleQueryBusiness="handleQueryBusiness" /> |
|||
<Pagination |
|||
:currentPage="data.currentPage" |
|||
:pageSize="data.pageSize" |
|||
:total="data.total" |
|||
@handleSizeChange="handleSizeChange" |
|||
@handleCurrentChange="handleCurrentChange" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from 'vue-router'; |
|||
import { useStore } from 'vuex'; |
|||
import { reactive } from 'vue'; |
|||
import { queryBusiness } from '@/apis/business.js'; |
|||
|
|||
const router = useRouter(); |
|||
const store = useStore(); |
|||
|
|||
const data = reactive({ |
|||
lists: [], |
|||
currentPage: 1, |
|||
pageSize: 10, |
|||
total: 0, |
|||
}); |
|||
|
|||
function openPage() { |
|||
router.push({ name: 'desk-add-business' }); |
|||
store.commit('plugin/setLeftIndex', 1); |
|||
} |
|||
|
|||
function handleSizeChange(val) { |
|||
data.pageSize = val; |
|||
handleQueryBusiness(); |
|||
} |
|||
|
|||
function handleCurrentChange(val) { |
|||
data.currentPage = val; |
|||
handleQueryBusiness(); |
|||
} |
|||
|
|||
/** |
|||
* 查询插件列表 |
|||
* @param {number} depth 查询深度 0则只查名称,1则查询全部 |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function handleQueryBusiness() { |
|||
try { |
|||
const { currentPage, pageSize } = data; |
|||
const params = { |
|||
param: { |
|||
depth: 1, |
|||
name: '', |
|||
pageNum: currentPage, |
|||
pageSize, |
|||
}, |
|||
}; |
|||
const res = await queryBusiness(params); |
|||
data.lists = res.list; |
|||
data.currentPage = res.pageNum - 0; |
|||
data.pageSize = res.pageSize - 0; |
|||
data.total = res.total - 0; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
handleQueryBusiness(); |
|||
</script> |
|||
|
|||
<style></style> |
@ -0,0 +1,14 @@ |
|||
<template> |
|||
<!-- <div class="flex flex-row"> --> |
|||
<el-container> |
|||
<el-aside width="208px"> |
|||
<leftMenu /> |
|||
</el-aside> |
|||
<el-main> |
|||
<router-view></router-view> |
|||
</el-main> |
|||
</el-container> |
|||
<!-- </div> --> |
|||
</template> |
|||
|
|||
<script setup></script> |
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<div class="flex flex-col"> |
|||
<listSearchBar /> |
|||
<div class="py-6"> |
|||
<el-button type="primary" icon="el-icon-plus" @click="openPage">创建插件</el-button> |
|||
</div> |
|||
<PluginListTable :lists="data.lists" @handleQueryPlugins="handleQueryPlugins" /> |
|||
<Pagination |
|||
:currentPage="data.currentPage" |
|||
:pageSize="data.pageSize" |
|||
:total="data.total" |
|||
@handleSizeChange="handleSizeChange" |
|||
@handleCurrentChange="handleCurrentChange" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from 'vue-router'; |
|||
import { useStore } from 'vuex'; |
|||
import { reactive } from 'vue'; |
|||
import { queryPlugins } from '@/apis/plugin.js'; |
|||
|
|||
const router = useRouter(); |
|||
const store = useStore(); |
|||
|
|||
const data = reactive({ |
|||
lists: [], |
|||
currentPage: 1, |
|||
pageSize: 10, |
|||
total: 0, |
|||
}); |
|||
|
|||
function openPage() { |
|||
router.push({ name: 'desk-add-plugin' }); |
|||
store.commit('plugin/setLeftIndex', 2); |
|||
} |
|||
|
|||
function handleSizeChange(val) { |
|||
data.pageSize = val; |
|||
handleQueryPlugins(); |
|||
} |
|||
|
|||
function handleCurrentChange(val) { |
|||
data.currentPage = val; |
|||
handleQueryPlugins(); |
|||
} |
|||
|
|||
/** |
|||
* 查询插件列表 |
|||
* @param {number} depth 查询深度 0则只查名称,1则查询全部 |
|||
* @param {number} mine 查询全部插件还是自己的插件 0全部 1自己 |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function handleQueryPlugins() { |
|||
try { |
|||
const { currentPage, pageSize } = data; |
|||
const params = { |
|||
param: { |
|||
depth: 1, |
|||
mine: 1, |
|||
name: '', |
|||
pageNum: currentPage, |
|||
pageSize, |
|||
}, |
|||
}; |
|||
const res = await queryPlugins(params); |
|||
data.lists = res.list; |
|||
data.currentPage = res.pageNum - 0; |
|||
data.pageSize = res.pageSize - 0; |
|||
data.total = res.total - 0; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
handleQueryPlugins(); |
|||
</script> |
|||
|
|||
<style></style> |
@ -0,0 +1,67 @@ |
|||
<template> |
|||
<searchBar /> |
|||
<listPlugin :lists="data.lists" /> |
|||
<Pagination |
|||
:currentPage="data.currentPage" |
|||
:pageSize="data.pageSize" |
|||
:total="data.total" |
|||
@handleSizeChange="handleSizeChange" |
|||
@handleCurrentChange="handleCurrentChange" |
|||
/> |
|||
</template> |
|||
|
|||
<script lang="ts" setup="true"> |
|||
import { reactive } from 'vue'; |
|||
import { queryPlugins } from '@/apis/plugin.js'; |
|||
|
|||
const data = reactive({ |
|||
lists: [], |
|||
currentPage: 1, |
|||
pageSize: 10, |
|||
total: 0, |
|||
}); |
|||
|
|||
function handleSizeChange(val) { |
|||
data.pageSize = val; |
|||
handleQueryPlugins(); |
|||
} |
|||
|
|||
function handleCurrentChange(val) { |
|||
data.currentPage = val; |
|||
handleQueryPlugins(); |
|||
} |
|||
|
|||
/** |
|||
* 查询插件列表 |
|||
* @param {number} depth 查询深度 0则只查名称,1则查询全部 |
|||
* @param {number} mine 查询全部插件还是自己的插件 0全部 1自己 |
|||
* @param {number} name 插件名称,为空则不实用该条件 |
|||
* @param {number} pageNum 第几页 |
|||
* @param {number} pageSize 每页几条信息 |
|||
*/ |
|||
async function handleQueryPlugins() { |
|||
try { |
|||
const { currentPage, pageSize } = data; |
|||
const params = { |
|||
param: { |
|||
depth: 1, |
|||
mine: 0, |
|||
name: '', |
|||
pageNum: currentPage, |
|||
pageSize, |
|||
}, |
|||
}; |
|||
const res = await queryPlugins(params); |
|||
data.lists = res.list; |
|||
data.currentPage = res.pageNum - 0; |
|||
data.pageSize = res.pageSize - 0; |
|||
data.total = res.total - 0; |
|||
} catch (error) { |
|||
console.error('error: ', error); |
|||
} |
|||
} |
|||
|
|||
handleQueryPlugins(); |
|||
</script> |
|||
|
|||
<style scoped></style> |
Loading…
Reference in new issue