mirror of
https://github.com/rubickCenter/rubick
synced 2025-12-25 11:59:27 +08:00
init
This commit is contained in:
84
src/renderer/App.vue
Normal file
84
src/renderer/App.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<a-layout id="components-layout-demo-custom-trigger">
|
||||
<div class="rubick-select">
|
||||
<div class="tag-container" v-if="selected">
|
||||
<a-tag
|
||||
:key="selected.key"
|
||||
@close="closeTag"
|
||||
class="select-tag"
|
||||
color="green"
|
||||
closable
|
||||
>
|
||||
{{ selected.name }}
|
||||
</a-tag>
|
||||
</div>
|
||||
<a-input
|
||||
placeholder="Hi, Rubick"
|
||||
class="main-input"
|
||||
@change="onSearch"
|
||||
:value="searchValue"
|
||||
>
|
||||
<a-icon class="icon-tool" type="tool" slot="suffix" @click="() => {
|
||||
showMainUI();
|
||||
changePath({key: 'market'})
|
||||
}"/>
|
||||
}
|
||||
</a-input>
|
||||
<div class="options" v-show="options.length && !showMain">
|
||||
<a-list item-layout="horizontal" :data-source="options">
|
||||
<a-list-item @click="() => item.click($router)" class="op-item" slot="renderItem" slot-scope="item, index">
|
||||
<a-list-item-meta
|
||||
:description="item.desc"
|
||||
>
|
||||
<span slot="title" >{{ item.name }}</span>
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
<router-view></router-view>
|
||||
</a-layout>
|
||||
</template>
|
||||
<script>
|
||||
import {mapActions, mapMutations, mapState} from "vuex";
|
||||
import {ipcRenderer} from "electron";
|
||||
import {getWindowHeight} from "./assets/common/utils";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
...mapActions('main', ['onSearch', 'showMainUI']),
|
||||
...mapMutations('main', ['commonUpdate']),
|
||||
changePath({key}) {
|
||||
this.$router.push({path: `/home/${key}`});
|
||||
this.commonUpdate({
|
||||
current: [key]
|
||||
})
|
||||
},
|
||||
closeTag(v) {
|
||||
this.commonUpdate({
|
||||
selected: null,
|
||||
showMain: false,
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight([]),
|
||||
});
|
||||
this.$router.push({
|
||||
path: '/home',
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['showMain', 'current', 'options', 'selected', 'searchValue'])
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
0
src/renderer/assets/.gitkeep
Normal file
0
src/renderer/assets/.gitkeep
Normal file
4
src/renderer/assets/api/config.js
Normal file
4
src/renderer/assets/api/config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
development: 'http://localhost:7001',
|
||||
// development: 'http://kaer-server.qa.91jkys.com',
|
||||
};
|
||||
5
src/renderer/assets/api/index.js
Normal file
5
src/renderer/assets/api/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import plugin from './list/plugin';
|
||||
|
||||
export default {
|
||||
plugin
|
||||
}
|
||||
16
src/renderer/assets/api/list/plugin.js
Normal file
16
src/renderer/assets/api/list/plugin.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import instance from '../request';
|
||||
|
||||
export default {
|
||||
async add(params) {
|
||||
const result = await instance.post('/plugin/create', params);
|
||||
return result.data;
|
||||
},
|
||||
async update(params) {
|
||||
const result = await instance.post('/plugin/update', params);
|
||||
return result.data;
|
||||
},
|
||||
async query(params) {
|
||||
const result = await instance.get('/plugin/query', {params});
|
||||
return result.data;
|
||||
}
|
||||
}
|
||||
10
src/renderer/assets/api/request.js
Normal file
10
src/renderer/assets/api/request.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import axios from 'axios';
|
||||
import config from "./config";
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: config[process.env.NODE_ENV],
|
||||
timeout: 10000,
|
||||
withCredentials: true
|
||||
});
|
||||
|
||||
export default instance;
|
||||
9
src/renderer/assets/common/constans.js
Normal file
9
src/renderer/assets/common/constans.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const WINDOW_MAX_HEIGHT = 766;
|
||||
const WINDOW_MIN_HEIGHT = 60;
|
||||
const PRE_ITEM_HEIGHT = 60;
|
||||
|
||||
export {
|
||||
WINDOW_MAX_HEIGHT,
|
||||
WINDOW_MIN_HEIGHT,
|
||||
PRE_ITEM_HEIGHT,
|
||||
}
|
||||
94
src/renderer/assets/common/utils.js
Normal file
94
src/renderer/assets/common/utils.js
Normal file
@@ -0,0 +1,94 @@
|
||||
import {WINDOW_MAX_HEIGHT, WINDOW_MIN_HEIGHT, PRE_ITEM_HEIGHT} from './constans';
|
||||
import download from 'download-git-repo';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import process from 'child_process';
|
||||
import Store from 'electron-store';
|
||||
|
||||
const store = new Store();
|
||||
|
||||
function getWindowHeight(searchList) {
|
||||
if (!searchList) return WINDOW_MAX_HEIGHT;
|
||||
if (!searchList.length) return WINDOW_MIN_HEIGHT;
|
||||
return searchList.length * PRE_ITEM_HEIGHT + WINDOW_MIN_HEIGHT + 5 > WINDOW_MAX_HEIGHT ? WINDOW_MAX_HEIGHT : searchList.length * PRE_ITEM_HEIGHT + WINDOW_MIN_HEIGHT + 5;
|
||||
}
|
||||
|
||||
function searchKeyValues(lists, value){
|
||||
return lists.filter(item => item.indexOf(value) >= 0)
|
||||
}
|
||||
|
||||
function existOrNot(path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(path, async (err, stat) => {
|
||||
if (err) {
|
||||
resolve(false);
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function mkdirFolder(name) {
|
||||
return new Promise((resolve, reject) => {
|
||||
process.exec(`mkdir ${name}`, async function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
reject(false);
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function downloadFunc(downloadRepoUrl, name) {
|
||||
const plugin_path = path.join(__static, './plugins');
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (!(await existOrNot(plugin_path))) {
|
||||
await mkdirFolder(plugin_path);
|
||||
}
|
||||
// 基础模版所在目录,如果是初始化,则是模板名称,否则是项目名称
|
||||
const temp_dest = `${plugin_path}/${name}`;
|
||||
// 下载模板
|
||||
if (await existOrNot(temp_dest)) {
|
||||
await process.execSync(`rm -rf ${temp_dest}`);
|
||||
}
|
||||
|
||||
download(`github:clouDr-f2e/${name}`, temp_dest, function (err) {
|
||||
console.log(err ? 'Error' : 'Success')
|
||||
if (err) {
|
||||
console.log(err);
|
||||
reject('请求模板下载失败');
|
||||
} else {
|
||||
resolve('请求模板下载成功');
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
const sysFile = {
|
||||
savePlugins(plugins) {
|
||||
store.set('user-plugins', plugins);
|
||||
},
|
||||
getUserPlugins() {
|
||||
try {
|
||||
console.log(store.get('user-plugins').devPlugins)
|
||||
return store.get('user-plugins').devPlugins;
|
||||
} catch (e) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
getWindowHeight,
|
||||
searchKeyValues,
|
||||
downloadFunc,
|
||||
sysFile,
|
||||
}
|
||||
BIN
src/renderer/assets/logo.png
Normal file
BIN
src/renderer/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
23
src/renderer/main.js
Normal file
23
src/renderer/main.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import Antd from 'ant-design-vue';
|
||||
|
||||
import 'ant-design-vue/dist/antd.css';
|
||||
|
||||
if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
|
||||
Vue.http = Vue.prototype.$http = axios
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.use(Antd);
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
components: { App },
|
||||
router,
|
||||
store,
|
||||
template: '<App/>'
|
||||
}).$mount('#app')
|
||||
62
src/renderer/pages/index/index.vue
Normal file
62
src/renderer/pages/index/index.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-list item-layout="horizontal" :data-source="data">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index">
|
||||
<a-list-item-meta>
|
||||
<div class="desc" slot="description">
|
||||
Ant Design, a design language for background applications, is refined by Ant UED Team
|
||||
</div>
|
||||
<div slot="title">
|
||||
{{ item.title }}
|
||||
<a-tag color="green">标签</a-tag>
|
||||
</div>
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</a-list-item-meta>
|
||||
<div class="fava-btn">
|
||||
<a-icon type="star" /> 添加
|
||||
</div>
|
||||
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const data = [
|
||||
{
|
||||
title: 'Ant Design Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 4',
|
||||
},
|
||||
];
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
data,
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.fava-btn {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #f50;
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 400px;
|
||||
}
|
||||
</style>
|
||||
37
src/renderer/pages/plugins/index.vue
Normal file
37
src/renderer/pages/plugins/index.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<webview style="width: 100%;height: 100vh" id="webview" :src="path"></webview>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import {getlocalDataFile} from '../../../common/utils';
|
||||
import { remote } from 'electron';
|
||||
// import process from 'child_process';
|
||||
|
||||
export default {
|
||||
name: "index.vue",
|
||||
data() {
|
||||
return {
|
||||
path: `File://${this.$route.query.sourceFile}`,
|
||||
preload: path.join(process.cwd(), './api/index.js')
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(1111, this.$route.query)
|
||||
// const webview = document.querySelector('webview')
|
||||
// webview.addEventListener('dom-ready', () => {
|
||||
// webview.openDevTools()
|
||||
// })
|
||||
},
|
||||
beforeRouteUpdate() {
|
||||
this.path = `File://${this.$route.query.sourceFile}`
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
115
src/renderer/pages/search/index.vue
Normal file
115
src/renderer/pages/search/index.vue
Normal file
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-show="showMain">
|
||||
<a-menu :selectedKeys="current" mode="horizontal" @select="changePath">
|
||||
<a-menu-item key="market">
|
||||
<a-icon type="appstore"/>
|
||||
插件中心
|
||||
</a-menu-item>
|
||||
<a-menu-item key="favo">
|
||||
<a-icon type="heart"/>
|
||||
已安装
|
||||
</a-menu-item>
|
||||
<a-menu-item key="dev">
|
||||
<a-icon type="code"/>
|
||||
开发者
|
||||
</a-menu-item>
|
||||
<a-menu-item key="set">
|
||||
<a-icon type="setting"/>
|
||||
设置
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</div>
|
||||
<router-view v-show="showMain"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapActions, mapState, mapMutations} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "search",
|
||||
methods: {
|
||||
...mapActions('main', ['onSearch', 'showMainUI']),
|
||||
...mapMutations('main', ['commonUpdate']),
|
||||
changePath({key}) {
|
||||
this.$router.push({path: `/home/${key}`});
|
||||
this.commonUpdate({
|
||||
current: [key]
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['showMain', 'current', 'options', 'selected', 'searchValue'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.rubick-select {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
|
||||
.tag-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
|
||||
.select-tag {
|
||||
height: 36px;
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input:focus {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
top: 62px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
.op-item {
|
||||
padding: 0 10px;
|
||||
height: 60px;
|
||||
line-height: 50px;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-input {
|
||||
-webkit-app-region: drag;
|
||||
height: 60px !important;
|
||||
flex: 1;
|
||||
|
||||
.ant-select-selection, .ant-input, .ant-select-selection__rendered {
|
||||
height: 60px !important;
|
||||
font-size: 22px;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.icon-tool {
|
||||
font-size: 24px;
|
||||
background: #314659;
|
||||
color: #fff;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 100%;
|
||||
line-height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
125
src/renderer/pages/search/subpages/dev.vue
Normal file
125
src/renderer/pages/search/subpages/dev.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<div class="dev-container">
|
||||
<div class="dev-detail" v-if="devPlugins.length">
|
||||
<a-menu v-model="currentSelect" style="width: 256px; height: 100%" mode="vertical">
|
||||
<a-menu-item @click="currentSelect = [index]" v-for="(plugin, index) in devPlugins" :key="index">
|
||||
<div>{{ plugin.pluginName }}</div>
|
||||
<div>{{ plugin.description }}</div>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
<div class="plugin-detail">
|
||||
<div class="plugin-top">
|
||||
<div class="left">
|
||||
<div class="title">
|
||||
{{pluginDetail.pluginName}}
|
||||
<a-tag>{{pluginDetail.version}}</a-tag>
|
||||
</div>
|
||||
<div class="desc">
|
||||
开发者:{{`${pluginDetail.author || '未知'}`}}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{pluginDetail.description}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a-switch />
|
||||
</div>
|
||||
</div>
|
||||
<a-tabs default-active-key="1">
|
||||
<a-tab-pane key="1" tab="管理">
|
||||
<div class="desc-item">
|
||||
<div class="desc-title">
|
||||
<p>重新加载</p>
|
||||
<a-button type="link">重载</a-button>
|
||||
</div>
|
||||
<div class="desc-info">
|
||||
如果你修改了plugin.json文件需要重新加载以应用最近版本
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc-item">
|
||||
<div class="desc-title">
|
||||
<p>发布</p>
|
||||
<a-button type="link">发布</a-button>
|
||||
</div>
|
||||
<div class="desc-info">
|
||||
发布后用户可以通过插件中心下载,且享受最新的更新
|
||||
</div>
|
||||
</div>
|
||||
<div class="desc-item">
|
||||
<div class="desc-title">
|
||||
<p>删除</p>
|
||||
<a-button type="link">删除</a-button>
|
||||
</div>
|
||||
<div class="desc-info">
|
||||
删除这个插件不可以恢复
|
||||
</div>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="详情介绍">
|
||||
Content of Tab Pane 2
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentSelect: [0]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('main', ['devPlugins']),
|
||||
pluginDetail() {
|
||||
console.log(this.$store)
|
||||
return this.devPlugins[this.currentSelect]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.dev-container {
|
||||
height: calc(100vh - 110px);
|
||||
.dev-detail {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
height: 100%;
|
||||
}
|
||||
.plugin-detail {
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
.plugin-top {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
.title {
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.desc {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.desc-item {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 10px 0;
|
||||
.desc-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.desc-info {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
113
src/renderer/pages/search/subpages/market.vue
Normal file
113
src/renderer/pages/search/subpages/market.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div class="market">
|
||||
<a-carousel arrows>
|
||||
<div
|
||||
slot="prevArrow"
|
||||
slot-scope="props"
|
||||
class="custom-slick-arrow"
|
||||
style="left: 10px;zIndex: 1"
|
||||
>
|
||||
<a-icon type="left-circle" />
|
||||
</div>
|
||||
<div slot="nextArrow" slot-scope="props" class="custom-slick-arrow" style="right: 10px">
|
||||
<a-icon type="right-circle" />
|
||||
</div>
|
||||
<div><h3>1</h3></div>
|
||||
<div><h3>2</h3></div>
|
||||
<div><h3>3</h3></div>
|
||||
<div><h3>4</h3></div>
|
||||
</a-carousel>
|
||||
<a-divider></a-divider>
|
||||
<h2>插件</h2>
|
||||
<a-list item-layout="horizontal" style="width: 100%" :grid="{ gutter: 16, column: 2 }" :data-source="pluginList">
|
||||
<a-list-item slot="renderItem" slot-scope="item, index">
|
||||
<a-button :loading="loading[index]" type="link" slot="actions" @click="download(index, item)">
|
||||
<a-icon v-show="!loading[index]" style="font-size: 20px;" type="cloud-download" />
|
||||
</a-button>
|
||||
|
||||
|
||||
<a-list-item-meta
|
||||
:description="item.description"
|
||||
>
|
||||
<a slot="title" href="https://www.antdv.com/">{{ item.title }}</a>
|
||||
<a-avatar
|
||||
slot="avatar"
|
||||
src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"
|
||||
/>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../../../assets/api';
|
||||
import {mapActions} from 'vuex';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pluginList: [],
|
||||
loading: {},
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
const result = await api.plugin.query();
|
||||
this.pluginList = result.result;
|
||||
},
|
||||
|
||||
methods: {
|
||||
async download(index, item) {
|
||||
if (this.loading[index]) return;
|
||||
this.$set(this.loading, index, true);
|
||||
console.log(this.loading);
|
||||
await this.downloadPlugin(item);
|
||||
this.$set(this.loading, index, false);
|
||||
console.log(this.loading);
|
||||
|
||||
},
|
||||
...mapActions('main', ['downloadPlugin'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.market {
|
||||
height: calc(100vh - 110px);
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
.ant-carousel .slick-slide {
|
||||
text-align: center;
|
||||
height: 200px;
|
||||
line-height: 160px;
|
||||
background: #364d79;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ant-carousel .custom-slick-arrow {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
font-size: 25px;
|
||||
color: #fff;
|
||||
background-color: rgba(31, 45, 61, 0.11);
|
||||
opacity: 0.3;
|
||||
}
|
||||
.ant-carousel .custom-slick-arrow:before {
|
||||
display: none;
|
||||
}
|
||||
.ant-carousel .custom-slick-arrow:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.ant-carousel .slick-slide h3 {
|
||||
color: #fff;
|
||||
}
|
||||
.ant-list-item {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
35
src/renderer/router/index.js
Normal file
35
src/renderer/router/index.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Market from '../pages/search/subpages/market';
|
||||
import Dev from '../pages/search/subpages/dev';
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/home',
|
||||
name: 'search',
|
||||
component: require('@/pages/search/index.vue').default,
|
||||
children: [
|
||||
{
|
||||
path: 'market',
|
||||
component: Market
|
||||
},
|
||||
{
|
||||
path: 'dev',
|
||||
component: Dev
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/plugin',
|
||||
name: 'plugin',
|
||||
component: require('@/pages/plugins/index.vue').default
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/home'
|
||||
}
|
||||
]
|
||||
})
|
||||
10
src/renderer/store/index.js
Normal file
10
src/renderer/store/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import modules from './modules'
|
||||
|
||||
Vue.use(Vuex)
|
||||
export default new Vuex.Store({
|
||||
modules,
|
||||
strict: process.env.NODE_ENV !== 'production'
|
||||
})
|
||||
25
src/renderer/store/modules/dev.js
Normal file
25
src/renderer/store/modules/dev.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const state = {
|
||||
main: 0
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
DECREMENT_MAIN_COUNTER (state) {
|
||||
state.main--
|
||||
},
|
||||
INCREMENT_MAIN_COUNTER (state) {
|
||||
state.main++
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
someAsyncTask ({ commit }) {
|
||||
// do something async
|
||||
commit('INCREMENT_MAIN_COUNTER')
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
14
src/renderer/store/modules/index.js
Normal file
14
src/renderer/store/modules/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* The file enables `@/store/index.js` to import all vuex modules
|
||||
* in a one-shot manner. There should not be any reason to edit this file.
|
||||
*/
|
||||
|
||||
const files = require.context('.', false, /\.js$/)
|
||||
const modules = {}
|
||||
|
||||
files.keys().forEach(key => {
|
||||
if (key === './index.js') return
|
||||
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
|
||||
})
|
||||
|
||||
export default modules
|
||||
162
src/renderer/store/modules/main.js
Normal file
162
src/renderer/store/modules/main.js
Normal file
@@ -0,0 +1,162 @@
|
||||
import {clipboard, ipcRenderer} from "electron";
|
||||
import {getWindowHeight, searchKeyValues, downloadFunc, sysFile} from '../../assets/common/utils';
|
||||
|
||||
import fs from "fs";
|
||||
import path from 'path';
|
||||
|
||||
const state = {
|
||||
selected: null,
|
||||
options: [],
|
||||
showMain: false,
|
||||
current: ['market'],
|
||||
searchValue: '',
|
||||
devPlugins: sysFile.getUserPlugins() || [],
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
commonUpdate (state, payload) {
|
||||
Object.keys(payload).forEach((key) => {
|
||||
state[key] = payload[key];
|
||||
if (key === 'devPlugins') {
|
||||
sysFile.savePlugins(payload)
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
showMainUI ({ commit, state }, paylpad) {
|
||||
commit('commonUpdate', {
|
||||
showMain: true,
|
||||
selected: {
|
||||
key: 'market',
|
||||
name: '插件中心'
|
||||
}
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
},
|
||||
onSearch ({ commit }, paylpad) {
|
||||
const value = paylpad.target.value;
|
||||
const fileUrl = clipboard.read('public.file-url').replace('file://', '');
|
||||
commit('commonUpdate', {searchValue: value})
|
||||
// 复制文件
|
||||
if (fileUrl && value === 'plugin.json') {
|
||||
const config = JSON.parse(fs.readFileSync(fileUrl, 'utf-8'));
|
||||
|
||||
const pluginConfig = {
|
||||
...JSON.parse(fs.readFileSync(fileUrl, 'utf-8')),
|
||||
sourceFile: path.join(fileUrl, `../${config.main}`)
|
||||
};
|
||||
commit('commonUpdate', {
|
||||
selected: {
|
||||
key: 'plugin',
|
||||
name: 'plugin.json'
|
||||
},
|
||||
searchValue: '',
|
||||
devPlugins: [pluginConfig, ...state.devPlugins],
|
||||
options: [
|
||||
{
|
||||
name: '新建rubick开发插件',
|
||||
value: 'new-plugin',
|
||||
icon: 'plus-circle',
|
||||
desc: '新建rubick开发插件',
|
||||
click: (router) => {
|
||||
commit('commonUpdate', {
|
||||
showMain: true,
|
||||
selected: {
|
||||
key: 'plugin',
|
||||
name: '新建rubick开发插件'
|
||||
},
|
||||
current: ['dev'],
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
router.push('/home/dev')
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '复制路径',
|
||||
desc: '复制路径',
|
||||
value: 'copy-path',
|
||||
icon: 'plus-circle',
|
||||
click: () => {
|
||||
clipboard.writeText(fileUrl)
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
// 调整窗口大小
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(state.options),
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
let options = [];
|
||||
|
||||
// check 是否是插件
|
||||
state.devPlugins.forEach((plugin) => {
|
||||
const feature = plugin.features;
|
||||
feature.forEach(fe => {
|
||||
const cmds = searchKeyValues(fe.cmds, value);
|
||||
|
||||
options = [
|
||||
...options,
|
||||
...cmds.map((cmd) => ({
|
||||
name: cmd,
|
||||
value: 'plugin',
|
||||
icon: 'plus-circle',
|
||||
desc: fe.explain,
|
||||
click: (router) => {
|
||||
commit('commonUpdate', {
|
||||
selected: {
|
||||
key: cmd,
|
||||
name: cmd
|
||||
},
|
||||
searchValue: '',
|
||||
showMain: true,
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(),
|
||||
});
|
||||
router.push({
|
||||
path: '/plugin',
|
||||
query: plugin,
|
||||
})
|
||||
}
|
||||
}))
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
commit('commonUpdate', {
|
||||
options
|
||||
});
|
||||
ipcRenderer.send('changeWindowSize', {
|
||||
height: getWindowHeight(state.options),
|
||||
});
|
||||
},
|
||||
async downloadPlugin({commit}, payload) {
|
||||
await downloadFunc(payload.gitUrl, payload.name);
|
||||
const fileUrl = path.join(__static, `plugins/${payload.name}`);
|
||||
// 复制文件
|
||||
const config = JSON.parse(fs.readFileSync(`${fileUrl}/plugin.json`, 'utf-8'));
|
||||
const pluginConfig = {
|
||||
...config,
|
||||
sourceFile: `${fileUrl}/${config.main}`
|
||||
};
|
||||
commit('commonUpdate', {
|
||||
devPlugins: [pluginConfig, ...state.devPlugins],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
Reference in New Issue
Block a user