feat: 修改应用商店 应用列表

This commit is contained in:
zhengkunwang223 2023-01-12 15:12:01 +08:00 committed by zhengkunwang223
parent 3dda250b4d
commit 2ed62864b8
7 changed files with 202 additions and 172 deletions

View File

@ -3,79 +3,81 @@
// Read more: https://github.com/vuejs/vue-next/pull/3399
declare module 'vue' {
export interface GlobalComponents {
403: typeof import('./src/components/error-message/403.vue')['default'];
404: typeof import('./src/components/error-message/404.vue')['default'];
500: typeof import('./src/components/error-message/500.vue')['default'];
AppLayout: typeof import('./src/components/app-layout/index.vue')['default'];
AppStatus: typeof import('./src/components/app-status/index.vue')['default'];
BackButton: typeof import('./src/components/back-button/index.vue')['default'];
BreadCrumbs: typeof import('./src/components/bread-crumbs/index.vue')['default'];
BreadCrumbsItem: typeof import('./src/components/bread-crumbs/bread-crumbs-item.vue')['default'];
Codemirror: typeof import('./src/components/codemirror-dialog/codemirror.vue')['default'];
ComplexTable: typeof import('./src/components/complex-table/index.vue')['default'];
ConfirmDialog: typeof import('./src/components/confirm-dialog/index.vue')['default'];
ContainerLog: typeof import('./src/components/container-log/index.vue')['default'];
DrawerHeader: typeof import('./src/components/drawer-header/index.vue')['default'];
ElAlert: typeof import('element-plus/es')['ElAlert'];
ElAside: typeof import('element-plus/es')['ElAside'];
ElButton: typeof import('element-plus/es')['ElButton'];
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'];
ElCard: typeof import('element-plus/es')['ElCard'];
ElCheckbox: typeof import('element-plus/es')['ElCheckbox'];
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'];
ElCol: typeof import('element-plus/es')['ElCol'];
ElCollapse: typeof import('element-plus/es')['ElCollapse'];
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'];
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'];
ElContainer: typeof import('element-plus/es')['ElContainer'];
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'];
ElDivider: typeof import('element-plus/es')['ElDivider'];
ElDrawer: typeof import('element-plus/es')['ElDrawer'];
ElFooter: typeof import('element-plus/es')['ElFooter'];
ElForm: typeof import('element-plus/es')['ElForm'];
ElFormItem: typeof import('element-plus/es')['ElFormItem'];
ElHeader: typeof import('element-plus/es')['ElHeader'];
ElIcon: typeof import('element-plus/es')['ElIcon'];
ElImage: typeof import('element-plus/es')['ElImage'];
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'];
ElMenu: typeof import('element-plus/es')['ElMenu'];
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'];
ElOption: typeof import('element-plus/es')['ElOption'];
ElPageHeader: typeof import('element-plus/es')['ElPageHeader'];
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'];
ElRow: typeof import('element-plus/es')['ElRow'];
ElScrollbar: typeof import('element-plus/es')['ElScrollbar'];
ElSelect: typeof import('element-plus/es')['ElSelect'];
ElSubMenu: typeof import('element-plus/es')['ElSubMenu'];
ElSwitch: typeof import('element-plus/es')['ElSwitch'];
ElTable: typeof import('element-plus/es')['ElTable'];
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'];
ElTabPane: typeof import('element-plus/es')['ElTabPane'];
ElTabs: typeof import('element-plus/es')['ElTabs'];
ElTag: typeof import('element-plus/es')['ElTag'];
ElUpload: typeof import('element-plus/es')['ElUpload'];
FileList: typeof import('./src/components/file-list/index.vue')['default'];
FileRole: typeof import('./src/components/file-role/index.vue')['default'];
Footer: typeof import('./src/components/app-layout/footer/index.vue')['default'];
Loading: typeof import('element-plus/es')['ElLoadingDirective'];
Logo: typeof import('./src/components/app-layout/menu/components/Logo.vue')['default'];
Menu: typeof import('./src/components/app-layout/menu/index.vue')['default'];
RouterButton: typeof import('./src/components/router-button/index.vue')['default'];
Status: typeof import('./src/components/status/index.vue')['default'];
SubItem: typeof import('./src/components/app-layout/menu/components/sub-item.vue')['default'];
SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default'];
}
export interface GlobalComponents {
403: typeof import('./src/components/error-message/403.vue')['default']
404: typeof import('./src/components/error-message/404.vue')['default']
500: typeof import('./src/components/error-message/500.vue')['default']
AppLayout: typeof import('./src/components/app-layout/index.vue')['default']
AppStatus: typeof import('./src/components/app-status/index.vue')['default']
BackButton: typeof import('./src/components/back-button/index.vue')['default']
BreadCrumbs: typeof import('./src/components/bread-crumbs/index.vue')['default']
BreadCrumbsItem: typeof import('./src/components/bread-crumbs/bread-crumbs-item.vue')['default']
Codemirror: typeof import('./src/components/codemirror-dialog/codemirror.vue')['default']
ComplexTable: typeof import('./src/components/complex-table/index.vue')['default']
ConfirmDialog: typeof import('./src/components/confirm-dialog/index.vue')['default']
ContainerLog: typeof import('./src/components/container-log/index.vue')['default']
DrawerHeader: typeof import('./src/components/drawer-header/index.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert']
ElAside: typeof import('element-plus/es')['ElAside']
ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import('element-plus/es')['ElButton']
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'];
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElContainer: typeof import('element-plus/es')['ElContainer']
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']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElDraw: typeof import('element-plus/es')['ElDraw']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElFooter: typeof import('element-plus/es')['ElFooter']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
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']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPageHeader: typeof import('element-plus/es')['ElPageHeader']
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']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElUpload: typeof import('element-plus/es')['ElUpload']
FileList: typeof import('./src/components/file-list/index.vue')['default']
FileRole: typeof import('./src/components/file-role/index.vue')['default']
Footer: typeof import('./src/components/app-layout/footer/index.vue')['default']
Loading: typeof import('element-plus/es')['ElLoadingDirective']
Logo: typeof import('./src/components/app-layout/menu/components/Logo.vue')['default']
Menu: typeof import('./src/components/app-layout/menu/index.vue')['default']
RouterButton: typeof import('./src/components/router-button/index.vue')['default']
Status: typeof import('./src/components/status/index.vue')['default']
SubItem: typeof import('./src/components/app-layout/menu/components/sub-item.vue')['default']
SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default']
}
}
export {};
export { }

View File

@ -854,6 +854,7 @@ export default {
noService: '{0}',
toInstall: '去安装',
param: '参数配置',
syncAppList: '更新应用列表',
},
website: {
website: '网站',

View File

@ -35,8 +35,13 @@
<span v-else>
{{ title }}
<el-divider v-if="slots.buttons" direction="vertical" />
<slot v-if="slots.buttons" name="buttons"></slot>
<span v-if="slots.buttons">
<el-divider direction="vertical" />
<slot name="buttons"></slot>
</span>
<span style="float: right">
<slot v-if="slots.rightButton" name="rightButton"></slot>
</span>
</span>
</slot>
</div>

View File

@ -1,89 +1,84 @@
<template>
<div>
<el-card v-loading="loading" v-if="!showDetail">
<LayoutContent v-loading="loading" v-if="!showDetail" :title="$t('website.website')">
<template #toolbar>
<el-row :gutter="5">
<el-col :span="2">
<el-button @click="sync" type="primary" :plain="true">{{ $t('app.sync') }}</el-button>
<el-col :span="20">
<div>
<el-button @click="changeTag('all')" type="primary" :plain="activeTag !== 'all'">
{{ $t('app.all') }}
</el-button>
<div v-for="item in tags" :key="item.key" style="display: inline">
<el-button
class="tag-button"
@click="changeTag(item.key)"
type="primary"
:plain="activeTag !== item.key"
>
{{ item.name }}
</el-button>
</div>
</div>
</el-col>
<el-col :span="22">
<el-col :span="4">
<div style="float: right">
<el-input
style="display: inline; margin-right: 5px"
class="table-button"
v-model="req.name"
clearable
@clear="searchByName('')"
suffix-icon="Search"
@keyup.enter="searchByName(req.name)"
@blur="searchByName(req.name)"
:placeholder="$t('commons.button.search')"
></el-input>
<el-button
style="display: inline; margin-right: 5px"
v-model="req.name"
@click="searchByName(req.name)"
>
{{ $t('app.search') }}
</el-button>
</div>
</el-col>
</el-row>
<br />
<el-row>
<el-button
style="margin-right: 5px"
@click="changeTag('all')"
type="primary"
:plain="activeTag !== 'all'"
>
{{ $t('app.all') }}
</el-button>
<div style="margin-right: 5px" :span="1" v-for="item in tags" :key="item.key">
<el-button @click="changeTag(item.key)" type="primary" :plain="activeTag !== item.key">
{{ item.name }}
</el-button>
</div>
</el-row>
</template>
<template #rightButton>
<el-button @click="sync" type="text" :plain="true">{{ $t('app.syncAppList') }}</el-button>
</template>
<template #main>
<div class="divider"></div>
<el-row :gutter="5">
<el-col v-for="(app, index) in apps" :key="index" :span="6">
<div @click="getAppDetail(app.id)">
<el-card :body-style="{ padding: '0px' }" class="a-card">
<el-row :gutter="24">
<el-col :span="8">
<div class="icon">
<el-image class="image" :src="'data:image/png;base64,' + app.icon"></el-image>
<el-col v-for="(app, index) in apps" :key="index" :span="8">
<div class="a-card">
<el-row :gutter="24">
<el-col :span="5">
<div class="icon">
<el-avatar shape="square" :size="60" :src="'data:image/png;base64,' + app.icon" />
</div>
</el-col>
<el-col :span="19">
<div class="a-detail">
<div class="d-name">
<span class="name">{{ app.name }}</span>
<el-button class="h-button" round @click="getAppDetail(app.id)">安装</el-button>
</div>
</el-col>
<el-col :span="16">
<div class="a-detail">
<div class="d-name">
<span style="font-weight: 500; font-size: 16px">
{{ app.name }}
</span>
</div>
<div class="d-description">
<span>
{{ app.shortDesc }}
</span>
</div>
<div class="d-tag" style="margin-top: 5px">
<el-tag
v-for="(tag, ind) in app.tags"
:key="ind"
round
:colr="getColor(ind)"
>
{{ tag.name }}
</el-tag>
</div>
<div class="d-description">
<span class="description">
{{ app.shortDesc }}
</span>
</div>
</el-col>
</el-row>
</el-card>
<div class="d-tag" style="margin-top: 5px">
<el-tag v-for="(tag, ind) in app.tags" :key="ind" :colr="getColor(ind)">
{{ tag.name }}
</el-tag>
</div>
<div class="divider"></div>
</div>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</el-card>
<Detail v-if="showDetail" :id="appId"></Detail>
</div>
</template>
</LayoutContent>
<Detail v-if="showDetail" :id="appId"></Detail>
</template>
<script lang="ts" setup>
import LayoutContent from '@/layout/layout-content.vue';
import { App } from '@/api/interface/app';
import { onMounted, reactive, ref } from 'vue';
import { SearchApp, SyncApp } from '@/api/modules/app';
@ -159,14 +154,15 @@ onMounted(() => {
}
.a-card {
height: 100px;
height: 120px;
margin-top: 10px;
cursor: pointer;
padding: 5px;
.icon {
margin-left: 10px;
width: 80px;
height: 100%;
height: 80%;
padding: 5px;
display: flex;
align-items: center;
@ -185,24 +181,46 @@ onMounted(() => {
.d-name {
height: 20%;
.name {
font-weight: 500;
font-size: 16px;
color: #1f2329;
}
.h-button {
float: right;
}
}
.d-description {
margin-top: 5px;
margin-top: 10px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
.description {
font-size: 14px;
color: #646a73;
}
}
}
}
.a-card:hover {
transform: scale(1.1);
background-color: rgba(0, 94, 235, 0.03);
}
.table-button {
display: inline;
margin-right: 5px;
}
.tag-button {
margin-left: 10px;
}
.divider {
margin-top: 5px;
border: 0;
border-top: 1px solid #ccc;
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<el-card>
<LayoutContent :header="$t('app.detail')" :back-name="'App'" :v-loading="loadingDetail">
<LayoutContent :title="$t('app.detail')" :reload="true" :v-loading="loadingDetail">
<template #main>
<div class="brief">
<el-row :gutter="20">
<el-col :span="4">
@ -63,9 +63,9 @@
<div class="detail" v-loading="loadingDetail">
<v-md-preview :text="appDetail.readme"></v-md-preview>
</div>
<Install ref="installRef"></Install>
</LayoutContent>
</el-card>
</template>
</LayoutContent>
<Install ref="installRef"></Install>
</template>
<script lang="ts" setup>

View File

@ -1,24 +1,27 @@
<template>
<el-dialog
v-model="open"
:title="$t('app.install')"
:close-on-click-modal="false"
width="40%"
:before-close="handleClose"
>
<el-form
ref="paramForm"
label-position="left"
:model="form"
label-width="150px"
:rules="rules"
:validate-on-rule-change="false"
>
<el-form-item :label="$t('app.name')" prop="NAME">
<el-input v-model.trim="form['NAME']"></el-input>
</el-form-item>
<Params v-model:form="form" v-model:params="installData.params" v-model:rules="rules"></Params>
</el-form>
<el-drawer v-model="open" :title="$t('app.install')" size="50%" :before-close="handleClose" :show-close="false">
<template #header>
<Header :header="$t('app.install')" :back="handleClose" />
</template>
<el-row>
<el-col :span="22" :offset="1">
<el-form
ref="paramForm"
label-position="top"
:model="form"
label-width="150px"
:rules="rules"
:validate-on-rule-change="false"
>
<el-form-item :label="$t('app.name')" prop="NAME">
<el-input v-model.trim="form['NAME']"></el-input>
</el-form-item>
<Params v-model:form="form" v-model:params="installData.params" v-model:rules="rules"></Params>
</el-form>
</el-col>
</el-row>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
@ -27,7 +30,7 @@
</el-button>
</span>
</template>
</el-dialog>
</el-drawer>
</template>
<script lang="ts" setup name="appInstall">
@ -38,6 +41,8 @@ import { FormInstance, FormRules } from 'element-plus';
import { reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import Params from '../params/index.vue';
import Header from '@/components/drawer-header/index.vue';
const router = useRouter();
interface InstallRrops {

View File

@ -1,7 +1,6 @@
<template>
<div>
<RouterButton :buttons="buttons" />
<br />
<LayoutContent>
<router-view></router-view>
</LayoutContent>