Vendored
-3
@@ -45,9 +45,6 @@ spec:
|
||||
- name: "volume-m2"
|
||||
hostPath:
|
||||
path: "/root/.m2/repository"
|
||||
- name: "maven-config"
|
||||
configMap:
|
||||
name: maven-config
|
||||
- name: "volume-docker"
|
||||
hostPath:
|
||||
path: "/var/run/docker.sock"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
## Vue 3 + Typescript + Vite + pinia + vue-router
|
||||
|
||||
## Create project document how to bulid a project
|
||||
## about creating project document how to bulid a project
|
||||
before create project, you should install node to promit npm and node command is standy.
|
||||
npm -v
|
||||
node -v<br />
|
||||
|
||||
// 在想要创建的工程路径下执行以下命令,3到6秒就可以结束
|
||||
npm init vite@latest
|
||||
// 1.填写 g-home
|
||||
// 1.填写 violin-home
|
||||
// 2.选择vue
|
||||
// 3.vue.ts
|
||||
|
||||
cd g-home
|
||||
cd violin-home
|
||||
npm install
|
||||
|
||||
## vue-router
|
||||
@@ -33,19 +33,19 @@
|
||||
// to enter the home page:
|
||||
localhost:3000/home?tenantId=XXX&account=YYY&token=ABCDEFG
|
||||
|
||||
## 环境配置
|
||||
## profiles
|
||||
添加了.env.development ebv.test .env.production 文件
|
||||
development:
|
||||
开发环境,使用mock,不需要后台联动
|
||||
test:
|
||||
测试环境需要 后台java程序支持,同时需要百度第三方认证。
|
||||
prod:
|
||||
生产环境通过 jenkins cicd进行发布配置。
|
||||
生产环境通过 jenkins 做ci 持续集成 argocd 做cd 持续发布。
|
||||
|
||||
# 云服务器
|
||||
nginx as a veb server, i use the official image to build this app image.
|
||||
# prod server
|
||||
nginx as a web server, i use the official image to build this app image.
|
||||
|
||||
## 发布
|
||||
## publish
|
||||
- npm run build 生成dist 文件夹
|
||||
|
||||
## 百度网盘开放平台
|
||||
|
||||
@@ -74,4 +74,13 @@ export default [
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
url: '/wiki/api/v1/reader/blogs/count',
|
||||
method: 'GET',
|
||||
response: () => {
|
||||
return {
|
||||
count: 101,
|
||||
}
|
||||
},
|
||||
},
|
||||
] as MockMethod[]
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { MockMethod } from 'vite-plugin-mock'
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/bookmark/api/v1/bookmark/count',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return {
|
||||
count: 53,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/bookmark/api/v1/bookmark',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return [
|
||||
{
|
||||
bk_id: '001',
|
||||
bk_type_id: '2',
|
||||
bk_type_name: '3',
|
||||
comment: '4',
|
||||
url: '5'
|
||||
},
|
||||
{
|
||||
bk_id: '002',
|
||||
bk_type_id: '2',
|
||||
bk_type_name: '3',
|
||||
comment: '4',
|
||||
url: '5'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/bookmark/api/v1/bookmark_type',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return [
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
] as MockMethod[]
|
||||
@@ -0,0 +1,30 @@
|
||||
import { MockMethod } from 'vite-plugin-mock'
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/calendar/api/v1/event',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return [
|
||||
{
|
||||
date: '2023-01-09',
|
||||
title: '春游',
|
||||
eventInfo: '春节不觉晓,处处闻啼鸟,夜来风雨声,花落知多少',
|
||||
},
|
||||
{
|
||||
date: '2023-01-30',
|
||||
title: '月底发工资',
|
||||
eventInfo: '发了工资少一半,还了信用卡再少一半,试问如何攒下钱,只有两个字:做梦',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/calendar/api/v1/event',
|
||||
method: 'put',
|
||||
response: () => {
|
||||
return {
|
||||
}
|
||||
}
|
||||
},
|
||||
] as MockMethod[]
|
||||
+102
@@ -130,5 +130,107 @@ export default [
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/trader/api/v1/accounts',
|
||||
method: 'get',
|
||||
response: ({ body, query }) => {
|
||||
return {
|
||||
accounts: [
|
||||
{
|
||||
gateway_name: 'cpt',
|
||||
account_id: '7788',
|
||||
balance: '7',
|
||||
frozen: '8',
|
||||
},
|
||||
{
|
||||
gateway_name: 'cpt',
|
||||
account_id: '778899',
|
||||
balance: '8',
|
||||
frozen: '9',
|
||||
}
|
||||
],
|
||||
positions: [
|
||||
{
|
||||
symbol: 'czce',
|
||||
exchange: 'RM301',
|
||||
direction: '1',
|
||||
volume: 222,
|
||||
price: 2500,
|
||||
frozen: 3,
|
||||
pnl: 2,
|
||||
yd_volume: 1,
|
||||
}
|
||||
],
|
||||
trades: [
|
||||
{
|
||||
symbol: 'string',
|
||||
exchange: 'string',
|
||||
direction: 'string',
|
||||
volume: 2,
|
||||
price: 4,
|
||||
orderid: 'string',
|
||||
tradeid: 'string',
|
||||
offset: 'string',
|
||||
}
|
||||
],
|
||||
orders: [{
|
||||
symbol: 'string',
|
||||
exchange: 'string',
|
||||
direction: 'string',
|
||||
volume: 6,
|
||||
price: 4,
|
||||
orderid: 'string',
|
||||
type: 'string',
|
||||
offset: 'string',
|
||||
traded: 7,
|
||||
status: 'string',
|
||||
// datetime :datetime
|
||||
reference: 'string',
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/trader/api/v1/strategy_file',
|
||||
method: 'get',
|
||||
response: ({ body, query }) => {
|
||||
return [
|
||||
{
|
||||
file_name: 'string',
|
||||
class_name: 'string',
|
||||
status: 'string',
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/trader/api/v1/strategies',
|
||||
method: 'get',
|
||||
response: ({ body, query }) => {
|
||||
return [
|
||||
{
|
||||
strategy_name: 'string',
|
||||
class_name: 'string',
|
||||
vt_symbol: 'string',
|
||||
setting: {},
|
||||
status: 1,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/trader/api/v1/strategy_file/load',
|
||||
method: 'get',
|
||||
response: ({ body, query }) => {
|
||||
return [
|
||||
{
|
||||
class_names: 'asdasdas'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
] as MockMethod[]
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { MockMethod } from 'vite-plugin-mock'
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/onenote/api/v1/one_note',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return [
|
||||
{
|
||||
section_id: 'x111',
|
||||
section_name: 'A',
|
||||
page_list: [
|
||||
{
|
||||
page_id: 'y111',
|
||||
section_id: 'x111',
|
||||
page_name: 'B',
|
||||
},
|
||||
{
|
||||
page_id: 'y222',
|
||||
section_id: 'x111',
|
||||
page_name: 'C',
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
] as MockMethod[]
|
||||
-56
@@ -1,56 +0,0 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location /write {
|
||||
alias /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location /home {
|
||||
alias /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location ~ /view {
|
||||
alias /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
Generated
+1555
-43
File diff suppressed because it is too large
Load Diff
+7
-2
@@ -12,8 +12,8 @@
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^1.1.4",
|
||||
"@types/node": "^17.0.23",
|
||||
"axios": "^0.26.1",
|
||||
"aplayer": "^1.10.1",
|
||||
"axios": "^0.26.1",
|
||||
"clipboard": "^2.0.10",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"echarts": "^5.3.2",
|
||||
@@ -24,9 +24,14 @@
|
||||
"lodash-unified": "^1.0.2",
|
||||
"md-editor-v3": "^1.11.6",
|
||||
"moment": "^2.29.4",
|
||||
"node-sass": "^8.0.0",
|
||||
"pinia": "^2.0.13",
|
||||
"qs": "^6.10.3",
|
||||
"sass": "^1.57.1",
|
||||
"sass-loader": "^13.2.0",
|
||||
"save": "^2.4.0",
|
||||
"scss": "^0.2.4",
|
||||
"style-loader": "^3.3.1",
|
||||
"type-fest": "^2.12.2",
|
||||
"vue": "^3.2.25",
|
||||
"vue-router": "^4.0.14",
|
||||
@@ -40,10 +45,10 @@
|
||||
"@vitejs/plugin-vue": "^2.3.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"typescript": "^4.5.4",
|
||||
"v-contextmenu": "^3.0.0",
|
||||
"vite": "^2.9.13",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"v-contextmenu": "^3.0.0",
|
||||
"vue-tsc": "^0.29.8"
|
||||
}
|
||||
}
|
||||
|
||||
+20
-1
@@ -92,5 +92,24 @@ const sortBlogs = (data: Object, btId: string) => {
|
||||
})
|
||||
}
|
||||
|
||||
const countBlogs = () => {
|
||||
return service({
|
||||
url: '/wiki/api/v1/reader/blogs/count',
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
})
|
||||
}
|
||||
|
||||
export { listAll, updateBtName, putBlogType, removeBlogType, sortBlogTypes, getContent, putBlog, updateContent, deleteContent, sortBlogs }
|
||||
export {
|
||||
listAll,
|
||||
updateBtName,
|
||||
putBlogType,
|
||||
removeBlogType,
|
||||
sortBlogTypes,
|
||||
getContent,
|
||||
putBlog,
|
||||
updateContent,
|
||||
deleteContent,
|
||||
sortBlogs,
|
||||
countBlogs
|
||||
}
|
||||
+9
-1
@@ -49,10 +49,18 @@ const delete_bookmarks = (params: Object) => {
|
||||
})
|
||||
}
|
||||
|
||||
const bookmarks_count = () => {
|
||||
return service({
|
||||
url: '/bookmark/api/v1/bookmark/count',
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
search_bookmark,
|
||||
put_bookmark,
|
||||
delete_bookmark,
|
||||
delete_bookmarks,
|
||||
update_bookmark
|
||||
update_bookmark,
|
||||
bookmarks_count
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { service } from '../utils/request'
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json;charsetset=UTF-8'
|
||||
}
|
||||
|
||||
const put_event = (data: Object) => {
|
||||
return service({
|
||||
url: '/calendar/api/v1/event',
|
||||
method: 'PUT',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
const get_event = () => {
|
||||
return service({
|
||||
url: '/calendar/api/v1/event',
|
||||
method: 'GET',
|
||||
headers: headers
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
get_event,
|
||||
put_event,
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<span class="headerAvatar">
|
||||
<template v-if="picType === 'avatar'">
|
||||
<el-avatar v-if="useTenantStore.tenant.headerImg" :size="30" :src="avatar" />
|
||||
<el-avatar v-else :size="30" :src="noAvatar" />
|
||||
</template>
|
||||
<template v-if="picType === 'img'">
|
||||
<img v-if="useTenantStore.tenant.headerImg" :src="avatar" class="avatar">
|
||||
<img v-else :src="noAvatar" class="avatar">
|
||||
</template>
|
||||
<template v-if="picType === 'file'">
|
||||
<img :src="file" class="file">
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { tenantStore } from '@/store/modules/tenant'
|
||||
import noAvatarPng from '@/assets/noBody.png'
|
||||
|
||||
const props = defineProps({
|
||||
picType: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'avatar'
|
||||
},
|
||||
picSrc: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const path = ref(import.meta.env.VITE_BASE_API + '/')
|
||||
const noAvatar = ref(noAvatarPng)
|
||||
const useTenantStore = tenantStore()
|
||||
const avatar = computed(() => {
|
||||
if (props.picSrc === '') {
|
||||
if (useTenantStore.tenant.headerImg !== '' && useTenantStore.tenant.headerImg.slice(0, 4) === 'http') {
|
||||
return useTenantStore.tenant.headerImg
|
||||
}
|
||||
return path.value + useTenantStore.tenant.headerImg
|
||||
} else {
|
||||
if (props.picSrc !== '' && props.picSrc.slice(0, 4) === 'http') {
|
||||
return props.picSrc
|
||||
}
|
||||
return path.value + props.picSrc
|
||||
}
|
||||
})
|
||||
const file = computed(() => {
|
||||
if (props.picSrc && props.picSrc.slice(0, 4) !== 'http') {
|
||||
return path.value + props.picSrc
|
||||
}
|
||||
return props.picSrc
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.headerAvatar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.file {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<div class="4444">
|
||||
<div>
|
||||
<el-container>
|
||||
<el-aside width="150px">
|
||||
<el-aside width="180px">
|
||||
<SideBar></SideBar>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header
|
||||
style="border-bottom-style:solid; border-bottom-width: 0.5px; border-bottom-color:rgba(151, 151, 151, 0.3);">
|
||||
<el-header>
|
||||
<NavBar></NavBar>
|
||||
</el-header>
|
||||
<el-main>
|
||||
@@ -20,7 +19,6 @@
|
||||
<div>
|
||||
<el-avatar @click="openGithub" src="https://github.githubassets.com/favicons/favicon.svg" />
|
||||
</div>
|
||||
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</el-container>
|
||||
@@ -31,6 +29,32 @@
|
||||
import MainApp from '../layout/MainApp.vue'
|
||||
import NavBar from "../layout/NavBar.vue"
|
||||
import SideBar from "../layout/SideBar.vue"
|
||||
import { settingsStore } from "@/store/modules/settings"
|
||||
|
||||
// -- IMPORT --
|
||||
const useSettingsStore = settingsStore()
|
||||
|
||||
// -- REACTIVE OBJECT --
|
||||
|
||||
// -- REF OBJECT --
|
||||
|
||||
// -- EVENT DEFINITION
|
||||
const iniPage = () => {
|
||||
const screenWidth = document.body.clientWidth
|
||||
if (screenWidth < 1000) {
|
||||
useSettingsStore.settings.isMobile = true
|
||||
// isSider.value = false
|
||||
// isCollaps.value = true
|
||||
} else if (screenWidth >= 1000 && screenWidth < 1200) {
|
||||
useSettingsStore.settings.isMobile = false
|
||||
// isSider.value = false
|
||||
// isCollaps.value = true
|
||||
} else {
|
||||
useSettingsStore.settings.isMobile = false
|
||||
// isSider.value = true
|
||||
// isCollaps.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const openGithub = () => {
|
||||
let href = 'https://github.com/simple321vip'
|
||||
@@ -42,48 +66,32 @@ const openSiteQuery = () => {
|
||||
window.open(href, '_blank')
|
||||
}
|
||||
|
||||
/**
|
||||
* AUTO INVOKE FUNCTION
|
||||
*/
|
||||
iniPage()
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* .el-header,
|
||||
.el-footer {
|
||||
|
||||
color: rgb(51, 51, 51);
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
} */
|
||||
/*
|
||||
|
||||
|
||||
.el-aside {
|
||||
background-color: #e9eef3;
|
||||
color: #333;
|
||||
text-align: left;
|
||||
line-height: 200px;
|
||||
.el-header {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 0.5px;
|
||||
border-bottom-color: rgba(151, 151, 151, 0.3);
|
||||
}
|
||||
|
||||
.el-main {
|
||||
background-color: #e9eef3;
|
||||
color: #333;
|
||||
/* line-height: 450px; */
|
||||
/* vertical-align: top;
|
||||
padding: 5px;
|
||||
padding: 16px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body > .el-container {
|
||||
margin-bottom: 40px;
|
||||
.el-aside {
|
||||
margin-left: -10px;
|
||||
background: #191a23;
|
||||
}
|
||||
|
||||
.el-container:nth-child(5) .el-aside,
|
||||
.el-container:nth-child(6) .el-aside {
|
||||
line-height: 260px;
|
||||
}
|
||||
|
||||
.el-container:nth-child(7) .el-aside {
|
||||
line-height: 320px;
|
||||
} */
|
||||
.el-footer {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
<template>
|
||||
<section class="section-main" style="height:100%;">
|
||||
<router-view />
|
||||
<section class="section-main" v-loading="usesSttingsStore.isLoading" element-loading-text="页面加载中……"
|
||||
element-loading-background="rgba(0, 0, 0, 0.1)">
|
||||
<router-view v-if="usesSttingsStore.isRouterAlive" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { settingsStore } from "@/store/modules/settings"
|
||||
const usesSttingsStore = settingsStore()
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.section-main {
|
||||
height: 100%;
|
||||
padding: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,88 +1,96 @@
|
||||
<template>
|
||||
<div class="nav-main">
|
||||
<div style="width: 800px;">
|
||||
<div>
|
||||
当前时间:{{ time }}
|
||||
<el-row class="pd-0">
|
||||
<el-col :xs="2" :lg="1" :md="1" :sm="1" :xl="1" style="z-index:100">
|
||||
<!-- <div class="menu-total" @click="totalCollapse">
|
||||
<div v-if="isCollapse" class="gvaIcon gvaIcon-arrow-double-right" />
|
||||
<div v-else class="gvaIcon gvaIcon-arrow-double-left" />
|
||||
</div> -->
|
||||
</el-col>
|
||||
<el-col :xs="10" :lg="14" :md="14" :sm="9" :xl="14" :pull="1">
|
||||
<!-- 修改为手机端不显示顶部标签 -->
|
||||
<!-- <el-breadcrumb v-show="!isMobile" class="breadcrumb">
|
||||
<el-breadcrumb-item
|
||||
v-for="item in matched.slice(1,matched.length)"
|
||||
:key="item.path"
|
||||
>{{ fmtTitle(item.meta.title,route) }}</el-breadcrumb-item>
|
||||
</el-breadcrumb> -->
|
||||
</el-col>
|
||||
<el-col :xs="12" :lg="9" :md="9" :sm="14" :xl="9">
|
||||
<div class="right-box">
|
||||
<el-dropdown>
|
||||
<div class="dp-flex justify-content-center align-items height-full width-full">
|
||||
<span class="header-avatar" style="cursor: pointer">
|
||||
<CustomPic />
|
||||
<span v-show="!useSettingsStore.isMobile" style="margin-left: 5px">{{
|
||||
useTenantStore.tenant.account
|
||||
}}</span>
|
||||
<el-icon>
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</span>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="dropdown-group">
|
||||
<el-dropdown-item>
|
||||
<span style="font-weight: 600;">
|
||||
当前角色:{{ useTenantStore.tenant.account }}
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<template v-if="useTenantStore.tenant.account">
|
||||
<!-- <el-dropdown-item v-for="item in userStore.userInfo.authorities.filter(i=>i.authorityId!==userStore.userInfo.authorityId)" :key="item.authorityId" @click="changeUserAuth(item.authorityId)">
|
||||
<span>
|
||||
切换为:{{ item.authorityName }}
|
||||
</span>
|
||||
</el-dropdown-item> -->
|
||||
</template>
|
||||
<el-dropdown-item icon="avatar" @click="toPerson">个人信息</el-dropdown-item>
|
||||
<el-dropdown-item icon="reading-lamp" @click="useTenantStore.logout">登 出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<div>
|
||||
期货交易时间 
|
||||
<el-icon color="yellow">
|
||||
<Sunrise />
|
||||
</el-icon>  9:00-11:30  
|
||||
<el-icon color="gold">
|
||||
<Sunny />
|
||||
</el-icon>  13:30-15:00  
|
||||
<el-icon color="blue">
|
||||
<Moon />
|
||||
</el-icon>  21:00-23:00
|
||||
</div>
|
||||
</div>
|
||||
<el-dropdown trigger="click" v-show="tenant.account">
|
||||
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>profile</el-dropdown-item>
|
||||
<el-dropdown-item @click="dialogVisible = true">退出</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<el-dialog v-model="dialogVisible" title="提示" width="30%">
|
||||
<span>确认你的登出操作么?</span>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="doLogout">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<span @click="doLogin" v-show="!tenant.account">登录</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import $moment from "moment";
|
||||
import { reactive, ref } from "vue";
|
||||
import router from '../../router'
|
||||
import { tenantStore } from '../../store/tenant'
|
||||
import { logout } from '../../api/user'
|
||||
// obtain user infomation
|
||||
const tenant = tenantStore()
|
||||
tenant.reflush()
|
||||
const dialogVisible = ref(false)
|
||||
import CustomPic from "@/components/customPic/index.vue";
|
||||
import { tenantStore } from '@/store/modules/tenant'
|
||||
import { settingsStore } from '@/store/modules/settings'
|
||||
|
||||
// show time
|
||||
let time = ref<String>($moment().format("YYYY年MM月DD日 HH:mm:ss"));
|
||||
setInterval(() => {
|
||||
time.value = $moment().format("YYYY年MM月DD日 HH:mm:ss");
|
||||
}, 1000);
|
||||
// -- IMPORT --
|
||||
const useTenantStore = tenantStore()
|
||||
const useSettingsStore = settingsStore()
|
||||
|
||||
// login logout function
|
||||
const doLogin = () => {
|
||||
router.push({
|
||||
path: '/login'
|
||||
})
|
||||
}
|
||||
const doLogout = () => {
|
||||
dialogVisible.value = false
|
||||
logout(tenant.id).catch(() => { console.log(1) }).finally(() => {
|
||||
tenant.logout()
|
||||
router.push({
|
||||
path: '/login'
|
||||
})
|
||||
})
|
||||
// -- REACTIVE OBJECT --
|
||||
|
||||
// -- REF OBJECT --
|
||||
|
||||
// -- EVENT DEFINITION
|
||||
const toPerson = () => {
|
||||
}
|
||||
|
||||
useTenantStore.reflush()
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.open_side {
|
||||
background: url("../../assets/logo.png") center no-repeat;
|
||||
background-size: cover;
|
||||
<style lang="scss" scoped>
|
||||
.right-box {
|
||||
padding-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-main {
|
||||
.header-avatar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* background-color: bisque; */
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,27 +1,113 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-menu router class="side_Style" :style="{ height: sideHeight }">
|
||||
<el-menu-item v-for="(route, index) in current_routes" v-bind:key="index" v-bind:index="route.path"
|
||||
v-bind:title="route.meta?.name">{{ route.meta?.name }}</el-menu-item>
|
||||
<el-menu router class="el-menu-vertical" :style="{ height: sideHeight }" :background-color="theme.background"
|
||||
:active-text-color="theme?.background">
|
||||
|
||||
<el-menu-item v-for="(route, index) in current_routes" :key="index" :index="route.path" :title="route.meta?.name"
|
||||
@click="onclick()">
|
||||
<template #title>
|
||||
<div class="gva-menu-item">
|
||||
<el-icon v-if="index == 0" :size="20">
|
||||
<Sunny />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 1" :size="20">
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 2" :size="20">
|
||||
<Star />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 3" :size="20">
|
||||
<Notebook />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 4" :size="20">
|
||||
<Calendar />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 5" :size="20">
|
||||
<MostlyCloudy />
|
||||
</el-icon>
|
||||
<el-icon v-if="index == 10" :size="20">
|
||||
<Setting />
|
||||
</el-icon>
|
||||
<span>{{ route.meta?.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
// import { store } from "../../store/index";
|
||||
import router from "../../router/index";
|
||||
import { onBeforeMount, ref } from 'vue';
|
||||
let current_routes = router.options.routes[0].children;
|
||||
import { onBeforeMount, ref } from 'vue'
|
||||
import router from "@/router/index"
|
||||
import { settingsStore } from "@/store/modules/settings"
|
||||
import { Theme } from "@/entity/index";
|
||||
|
||||
// -- IMPORT --
|
||||
const useSettingsStore = settingsStore()
|
||||
|
||||
// -- REACTIVE OBJECT --
|
||||
|
||||
// -- REF OBJECT --
|
||||
let sideHeight = ref("")
|
||||
|
||||
let current_routes = router.options.routes[0].children
|
||||
const theme = ref<Theme>({
|
||||
background: '#fff',
|
||||
activeBackground: '#4D70FF',
|
||||
activeText: '#fff',
|
||||
normalText: '#333',
|
||||
hoverBackground: 'rgba(64, 158, 255, 0.08)',
|
||||
hoverText: '#333'
|
||||
})
|
||||
|
||||
// -- EVENT DEFINITION
|
||||
const onclick = () => {
|
||||
activeBackground.value = '#4D70FF'
|
||||
}
|
||||
|
||||
const getTheme = () => {
|
||||
switch (useSettingsStore.sideMode) {
|
||||
// white color
|
||||
case '#fff':
|
||||
theme.value = {
|
||||
background: '#fff',
|
||||
activeBackground: '#4D70FF',
|
||||
activeText: '#fff',
|
||||
normalText: '#333',
|
||||
hoverBackground: 'rgba(64, 158, 255, 0.08)',
|
||||
hoverText: '#333',
|
||||
}
|
||||
break;
|
||||
|
||||
// black color
|
||||
case '#191a23':
|
||||
theme.value = {
|
||||
background: '#191a23',
|
||||
activeBackground: '#4D70FF',
|
||||
activeText: '#fff',
|
||||
normalText: '#fff',
|
||||
hoverBackground: 'rgba(64, 158, 255, 0.08)',
|
||||
hoverText: '#fff',
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AUTO INVOKE FUNCTION
|
||||
*/
|
||||
getTheme()
|
||||
|
||||
onBeforeMount(() => {
|
||||
sideHeight.value = window.innerHeight + 'px'
|
||||
})
|
||||
const activeBackground = ref(theme.value.activeBackground)
|
||||
onclick()
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss" scoped>
|
||||
.side_Style {
|
||||
width: 100px;
|
||||
}
|
||||
@@ -30,6 +116,15 @@ onBeforeMount(() => {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.gva-menu-item {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.el-menu-item.is-active {
|
||||
color: v-bind(activeBackground);
|
||||
background: v-bind(activeBackground);
|
||||
}
|
||||
|
||||
/* .el-menu-item {
|
||||
background-color: #01dfd7;
|
||||
} */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { tenantStore } from '../../store/tenant'
|
||||
import { tenantStore } from '../../store/modules/tenant'
|
||||
import router from '../../router'
|
||||
import baiduCloudImage from "../../assets/baiducloud.png"
|
||||
import { config, scan } from '../../const/config'
|
||||
@@ -34,7 +34,7 @@ import { config, scan } from '../../const/config'
|
||||
|
||||
let qrcode = config.BAIDU_CLOUD_URL + config.RESPONSE_TYPE + config.CLIENT_ID + config.REDIRECT_URI + config.SCOPE + config.DEVICE_ID + config.QR_CODE + config.DISPLAY
|
||||
|
||||
const tenant = tenantStore()
|
||||
const useTenantStore = tenantStore()
|
||||
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
const loginForm = reactive({
|
||||
@@ -66,19 +66,19 @@ const dologin = (form: any) => {
|
||||
|
||||
if (!form)
|
||||
return
|
||||
form.validate((valid: any) => {
|
||||
if (valid) {
|
||||
tenant.login(loginForm.user_id, loginForm.password).then(res => {
|
||||
console.log(1)
|
||||
router.push({
|
||||
path: '/home'
|
||||
})
|
||||
})
|
||||
// form.validate((valid: any) => {
|
||||
// if (valid) {
|
||||
// useTenantStore.login(loginForm.user_id, loginForm.password).then(res => {
|
||||
// console.log(1)
|
||||
// router.push({
|
||||
// path: '/home'
|
||||
// })
|
||||
// })
|
||||
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
// } else {
|
||||
// return false
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
const style = reactive({} as any)
|
||||
|
||||
+23
-1
@@ -1,3 +1,5 @@
|
||||
import { Tenant } from '@/entity';
|
||||
import { tenantStore } from '@/store/modules/tenant';
|
||||
import router from '../router'
|
||||
import { setToken, setTenant } from '../utils/auth'
|
||||
|
||||
@@ -41,7 +43,27 @@ const scan_method: any = {
|
||||
production: (qrcode: string) => {
|
||||
window.location.href = qrcode
|
||||
},
|
||||
development: () => {
|
||||
development: async () => {
|
||||
|
||||
const useTenantStore = tenantStore()
|
||||
const tenant: Tenant = {
|
||||
tenant_id: '7788',
|
||||
account: '小小的测试账户'
|
||||
}
|
||||
let token = 'ABCDEFG'
|
||||
|
||||
await useTenantStore.login(tenant, token).then(() => {
|
||||
const { href } = router.resolve({
|
||||
path: '/'
|
||||
})
|
||||
window.open(href, '_self')
|
||||
}).catch((error) => {
|
||||
const { href } = router.resolve({
|
||||
path: '/login'
|
||||
})
|
||||
window.open(href, '_self')
|
||||
})
|
||||
|
||||
setToken("token")
|
||||
setTenant(
|
||||
{
|
||||
|
||||
+24
-2
@@ -1,6 +1,28 @@
|
||||
type Tenant = {
|
||||
id: string,
|
||||
tenant_id: string,
|
||||
account: string
|
||||
}
|
||||
|
||||
export { Tenant }
|
||||
type Theme = {
|
||||
background: string,
|
||||
activeBackground: string,
|
||||
activeText: string,
|
||||
normalText: string,
|
||||
hoverBackground: string,
|
||||
hoverText: string,
|
||||
}
|
||||
|
||||
type DataTimeline = {
|
||||
from: string,
|
||||
title: string,
|
||||
showDayAndMonth: boolean,
|
||||
message: string,
|
||||
}
|
||||
|
||||
type Event = {
|
||||
event_date: string,
|
||||
title: string,
|
||||
event_info: string,
|
||||
}
|
||||
|
||||
export { Tenant, Theme, DataTimeline, Event }
|
||||
|
||||
+7
-117
@@ -2,137 +2,27 @@ import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import ElementPlus from "element-plus";
|
||||
import 'element-plus/dist/index.css'
|
||||
import { store } from './store'
|
||||
import router from './router'
|
||||
import { createPinia } from 'pinia'
|
||||
const store = createPinia()
|
||||
import '@/permission'
|
||||
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
|
||||
let app = createApp(App)
|
||||
|
||||
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
|
||||
import contentmenu from 'v-contextmenu'
|
||||
import 'v-contextmenu/dist/themes/default.css'
|
||||
app.use(contentmenu)
|
||||
|
||||
import { setupMock } from '../mock'
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
setupMock()
|
||||
}
|
||||
|
||||
let app = createApp(App)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
app.use(contentmenu)
|
||||
app.use(router)
|
||||
app.use(ElementPlus)
|
||||
app.use(store)
|
||||
import { getToken, getTenant, setToken, setTenant } from './utils/auth'
|
||||
import { Tenant } from './entity/index'
|
||||
import Cookies from 'js-cookie'
|
||||
import { tenantStore } from './store/tenant'
|
||||
const whiteList = ['/login', '/register', '/sorryPage']
|
||||
let url = window.location.href
|
||||
|
||||
async function checktoken(url: string) {
|
||||
|
||||
if (url.search("register") != -1) {
|
||||
let arr = url.split('?')
|
||||
let parameters = arr[1].split('&')
|
||||
let query_data: { [key: string]: any } = {}
|
||||
parameters.forEach(parameter => {
|
||||
let parameter_list = parameter.split("=")
|
||||
query_data[parameter_list[0]] = parameter_list[1]
|
||||
})
|
||||
router.push({
|
||||
path: '/register',
|
||||
query: query_data
|
||||
})
|
||||
return
|
||||
}
|
||||
if (url.search("/home/") != -1) {
|
||||
let arr = url.split('?')
|
||||
let parameters = arr[1].split('&')
|
||||
let query_data: { [key: string]: any } = {}
|
||||
parameters.forEach(parameter => {
|
||||
let parameter_list = parameter.split("=")
|
||||
query_data[parameter_list[0]] = parameter_list[1]
|
||||
})
|
||||
const tenant = {
|
||||
tenant_id: query_data.tenantId,
|
||||
account: query_data.account
|
||||
}
|
||||
const tenant_store = tenantStore()
|
||||
await tenant_store.login(tenant, query_data.token).then(() => {
|
||||
const { href } = router.resolve({
|
||||
path: '/'
|
||||
});
|
||||
window.open(href, '_self');
|
||||
}).catch((error) => {
|
||||
const { href } = router.resolve({
|
||||
path: '/login'
|
||||
});
|
||||
window.open(href, '_self');
|
||||
})
|
||||
}
|
||||
if (url.search("sorryPage") != -1) {
|
||||
router.push({
|
||||
path: '/sorryPage',
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
checktoken(url)
|
||||
|
||||
/**
|
||||
* ルーター監視
|
||||
* 1、トーケン取得
|
||||
* 2、トーケンなし場合はログイン画面に遷移
|
||||
* 3、トーケンあり場合:
|
||||
* 既にログイン場合はデフォルト / に遷移
|
||||
*
|
||||
*/
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log(from.path, to.path)
|
||||
|
||||
const token = getToken()
|
||||
|
||||
if (typeof token === 'string') {
|
||||
switch (to.path) {
|
||||
case '/login':
|
||||
next('/')
|
||||
break;
|
||||
case '/':
|
||||
const tenant = <Tenant>(JSON.parse(getTenant() as string))
|
||||
if (url.search("write") != -1) {
|
||||
next('/BlogEditer')
|
||||
} else if (url.search("view") != -1) {
|
||||
let bid = Cookies.get('bid')
|
||||
router.push({
|
||||
path: '/BlogViewer',
|
||||
query: { bid: bid }
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: '/home',
|
||||
query: tenant
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
next()
|
||||
} else {
|
||||
next('/login')
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import router from './router'
|
||||
import Cookies from 'js-cookie'
|
||||
import { getToken, getTenant } from './utils/auth'
|
||||
import { Tenant } from './entity/index'
|
||||
import { tenantStore } from './store/modules/tenant'
|
||||
|
||||
const whiteList = ['/login', '/register', '/sorryPage']
|
||||
let url = window.location.href
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
|
||||
const token = getToken()
|
||||
|
||||
if (typeof token === 'string') {
|
||||
switch (to.path) {
|
||||
case '/login':
|
||||
next('/')
|
||||
break;
|
||||
case '/':
|
||||
const tenant = <Tenant>(JSON.parse(getTenant() as string))
|
||||
if (url.search("write") != -1) {
|
||||
next('/BlogEditer')
|
||||
} else if (url.search("view") != -1) {
|
||||
let bid = Cookies.get('bid')
|
||||
router.push({
|
||||
path: '/BlogViewer',
|
||||
query: { bid: bid }
|
||||
})
|
||||
} else {
|
||||
router.push({
|
||||
path: '/home',
|
||||
query: tenant
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
next()
|
||||
}
|
||||
} else {
|
||||
if (url.search("register") != -1) {
|
||||
let arr = url.split('?')
|
||||
let parameters = arr[1].split('&')
|
||||
let query_data: { [key: string]: any } = {}
|
||||
parameters.forEach(parameter => {
|
||||
let parameter_list = parameter.split("=")
|
||||
query_data[parameter_list[0]] = parameter_list[1]
|
||||
})
|
||||
router.push({
|
||||
path: '/register',
|
||||
query: query_data
|
||||
})
|
||||
}
|
||||
if (url.search("/home/") != -1) {
|
||||
let arr = url.split('?')
|
||||
let parameters = arr[1].split('&')
|
||||
let query_data: { [key: string]: any } = {}
|
||||
parameters.forEach(parameter => {
|
||||
let parameter_list = parameter.split("=")
|
||||
query_data[parameter_list[0]] = parameter_list[1]
|
||||
})
|
||||
const tenant = {
|
||||
tenant_id: query_data.tenantId,
|
||||
account: query_data.account
|
||||
}
|
||||
const tenant_store = tenantStore()
|
||||
tenant_store.login(tenant, query_data.token).then(() => {
|
||||
const { href } = router.resolve({
|
||||
path: '/'
|
||||
});
|
||||
window.open(href, '_self');
|
||||
}).catch((error) => {
|
||||
const { href } = router.resolve({
|
||||
path: '/login'
|
||||
});
|
||||
window.open(href, '_self');
|
||||
})
|
||||
}
|
||||
if (url.search("sorryPage") != -1) {
|
||||
router.push({
|
||||
path: '/sorryPage',
|
||||
})
|
||||
}
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
next()
|
||||
} else {
|
||||
next('/login')
|
||||
}
|
||||
}
|
||||
})
|
||||
+28
-27
@@ -1,5 +1,6 @@
|
||||
import { createRouter, createMemoryHistory, RouteRecordRaw } from 'vue-router'
|
||||
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: "/",
|
||||
@@ -14,103 +15,103 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
{
|
||||
path: '/blog',
|
||||
component: () => import('../view/blog/index.vue'),
|
||||
component: resolve => (require('@/view/blog/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '博客'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/bookmark',
|
||||
component: () => import('../view/bookmark/index.vue'),
|
||||
component: resolve => (require('@/view/bookmark/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '书签'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/school',
|
||||
component: () => import('../view/school/index.vue'),
|
||||
path: '/onenote',
|
||||
component: resolve => (require('@/view/onenote/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '学习'
|
||||
name: 'onenote'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/thinking',
|
||||
component: () => import('../view/thinking/index.vue'),
|
||||
path: '/calendar',
|
||||
component: resolve => (require('@/view/calendar/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '感悟人生'
|
||||
name: '日历'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/cloud',
|
||||
component: () => import('../view/cloud/index.vue'),
|
||||
component: resolve => (require('@/view/cloud/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '个人云盘'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/market',
|
||||
component: () => import('../view/recommend/index.vue'),
|
||||
component: resolve => (require('@/view/recommend/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '市场行情'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/capital',
|
||||
component: () => import('../view/capital/index.vue'),
|
||||
component: resolve => (require('@/view/capital/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '资金管理'
|
||||
}
|
||||
},
|
||||
// {
|
||||
// path: '/trader',
|
||||
// component: () => import('../view/trader/index.vue'),
|
||||
// meta: {
|
||||
// name: 'trader'
|
||||
// }
|
||||
// },
|
||||
{
|
||||
path: '/strategy',
|
||||
component: () => import('../view/trader/cta_strategy_file.vue'),
|
||||
component: resolve => (require('@/view/trader/cta_strategy_file.vue'), resolve),
|
||||
meta: {
|
||||
name: '策略模板'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/strategy_instance',
|
||||
component: () => import('../view/trader/cta_strategy.vue'),
|
||||
component: resolve => (require('@/view/trader/cta_strategy.vue'), resolve),
|
||||
meta: {
|
||||
name: 'CTA策略'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
component: resolve => (require('@/view/settings/index.vue'), resolve),
|
||||
meta: {
|
||||
name: '设置'
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "/feedback",
|
||||
component: () => import('../view/blog/mdview.vue')
|
||||
component: resolve => (require('@/view/blog/mdview.vue'), resolve),
|
||||
},
|
||||
{
|
||||
path: "/BlogEditer",
|
||||
component: () => import('../view/blog/createBlog.vue')
|
||||
component: resolve => (require('@/view/blog/createBlog.vue'), resolve),
|
||||
},
|
||||
{
|
||||
path: "/BlogViewer",
|
||||
component: () => import('../view/blog/mdview.vue')
|
||||
component: resolve => (require('@/view/blog/mdview.vue'), resolve),
|
||||
},
|
||||
{
|
||||
path: "/login",
|
||||
component: () => import('../components/login/login.vue')
|
||||
component: () => import('@/components/login/login.vue')
|
||||
},
|
||||
{
|
||||
path: "/illustration",
|
||||
component: () => import('../components/illustration/index.vue')
|
||||
component: resolve => (require('../components/illustration/login.vue'), resolve)
|
||||
},
|
||||
{
|
||||
path: "/register",
|
||||
component: () => import('../components/login/register.vue')
|
||||
component: resolve => (require('../components/login/register.vue'), resolve)
|
||||
},
|
||||
{
|
||||
path: "/sorryPage",
|
||||
component: () => import('../components/login/sorry.vue')
|
||||
component: resolve => (require('../components/login/sorry.vue'), resolve)
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const service = axios.create()
|
||||
|
||||
const get_holiday = () => {
|
||||
return service({
|
||||
url: 'https://holidays-jp.github.io/api/v1/2023/date.json',
|
||||
method: 'GET'
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
get_holiday
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const service = axios.create()
|
||||
|
||||
export function Commits(page: number) {
|
||||
return service({
|
||||
url: 'https://api.github.com/repos/simple321vip/violin-home/commits?page=' + page,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function Members() {
|
||||
return service({
|
||||
url: 'https://api.github.com/orgs/FLIPPED-AURORA/members',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import axios from 'axios'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const weatherInfo = ref('对不起主人,我还没有获得天气信息,暂时无法显示哟。')
|
||||
const amapKey = '8e8baa8a7317586c29ec694895de6e0a'
|
||||
|
||||
export const useWeatherInfo = () => {
|
||||
ip()
|
||||
return weatherInfo
|
||||
}
|
||||
|
||||
export const ip = async () => {
|
||||
// key换成你自己的 https://console.amap.com/dev/index
|
||||
// if (amapKey === '') {
|
||||
if (amapKey.length == 1) {
|
||||
return false
|
||||
}
|
||||
const res = await axios.get('https://restapi.amap.com/v3/ip?key=' + amapKey)
|
||||
if (res.data.adcode) {
|
||||
getWeather(res.data.adcode)
|
||||
}
|
||||
}
|
||||
|
||||
const getWeather = async (code: string) => {
|
||||
const response = await axios.get('https://restapi.amap.com/v3/weather/weatherInfo?key=' + amapKey + '&extensions=base&city=' + code)
|
||||
if (response.data.status === '1') {
|
||||
const s = response.data.lives[0]
|
||||
weatherInfo.value = s.city + ' 天气:' + s.weather + ' 温度:' + s.temperature + '摄氏度 风向:' + s.winddirection + ' 风力:' + s.windpower + '级 空气湿度:' + s.humidity
|
||||
}
|
||||
}
|
||||
+3
-67
@@ -1,69 +1,5 @@
|
||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||
import { authorize } from '../api/user'
|
||||
import { getToken, setToken, resetToken, setTenant, getTenant } from '../utils/auth'
|
||||
import { Tenant } from '../entity/index'
|
||||
import { createPinia } from "pinia"
|
||||
|
||||
const store = createPinia()
|
||||
|
||||
interface Record {
|
||||
isFolder: boolean
|
||||
path: string
|
||||
records: Set<Record>
|
||||
}
|
||||
|
||||
/**
|
||||
* skeleton
|
||||
*
|
||||
*
|
||||
*/
|
||||
export const tenantStore = defineStore({
|
||||
id: 'cloud',
|
||||
state: () => ({
|
||||
cloud: new Set<Record>(),
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
logout() {
|
||||
this.$patch({
|
||||
})
|
||||
resetToken()
|
||||
// we could do other stuff like redirecting the user
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempt to login a user
|
||||
* @param {string} user_id
|
||||
* @param {string} user_password
|
||||
*/
|
||||
async login(tenant: any, token: string) {
|
||||
|
||||
try {
|
||||
await authorize({
|
||||
tenant_id: tenant.tenant_id, token: token
|
||||
})
|
||||
setToken(token)
|
||||
setTenant(tenant)
|
||||
} catch {
|
||||
Promise.resolve("authorize error")
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
async reflush() {
|
||||
if (getToken()) {
|
||||
const tenant = <Tenant>(JSON.parse(getTenant() as string))
|
||||
const token = <string>getToken()
|
||||
this.$patch({
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(tenantStore, import.meta.hot))
|
||||
}
|
||||
export { store }
|
||||
@@ -0,0 +1,29 @@
|
||||
import { acceptHMRUpdate, defineStore } from "pinia"
|
||||
import { computed, ref } from "vue"
|
||||
|
||||
export const settingsStore = defineStore('settings', () => {
|
||||
|
||||
const settings = ref({
|
||||
sideMode: '#191a23',
|
||||
isMobile: false,
|
||||
isRouterAlive: true,
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
const sideMode = computed(() => settings.value.sideMode)
|
||||
const isMobile = computed(() => settings.value.isMobile)
|
||||
const isRouterAlive = computed(() => settings.value.isRouterAlive)
|
||||
const isLoading = computed(() => settings.value.isLoading)
|
||||
|
||||
return {
|
||||
settings,
|
||||
sideMode,
|
||||
isMobile,
|
||||
isRouterAlive,
|
||||
isLoading,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(settingsStore, import.meta.hot))
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { acceptHMRUpdate, defineStore } from "pinia"
|
||||
import { reactive } from "vue"
|
||||
import { get_vt_symbols, get_exchanges, get_subscribe_vt_symbols } from '../../api/capital'
|
||||
|
||||
export const strategyStore = defineStore('strategy', () => {
|
||||
|
||||
const strategy = reactive({
|
||||
class_names: [],
|
||||
vt_symbols: new Map(),
|
||||
subscribe_vt_symbols: [],
|
||||
exchanges: []
|
||||
})
|
||||
|
||||
const select_exchanges = async () => {
|
||||
if (strategy.exchanges.length == 0) {
|
||||
get_exchanges().then(res => {
|
||||
strategy.exchanges = res.data.exchanges
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const select_vt_symbols = async () => {
|
||||
if (strategy.vt_symbols.size == 0) {
|
||||
get_vt_symbols().then(res => {
|
||||
let keys = Object.keys(res.data.vt_symbols)
|
||||
keys.forEach(key => {
|
||||
strategy.vt_symbols.set(key, res.data.vt_symbols[key])
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const select_subscribe_vt_symbols = async () => {
|
||||
if (strategy.subscribe_vt_symbols.length == 0) {
|
||||
get_subscribe_vt_symbols().then(res => {
|
||||
strategy.subscribe_vt_symbols = res.data.subscribe_vt_symbols
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
strategy,
|
||||
select_exchanges,
|
||||
select_vt_symbols,
|
||||
select_subscribe_vt_symbols
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(strategyStore, import.meta.hot))
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||
import { authorize } from '../../api/user'
|
||||
import { getToken, setToken, resetToken, setTenant, getTenant } from '../../utils/auth'
|
||||
import { Tenant } from '../../entity/index'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export const tenantStore = defineStore('tenant', () => {
|
||||
const tenant = ref({
|
||||
account: '',
|
||||
token: '',
|
||||
id: '',
|
||||
headerImg: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
|
||||
})
|
||||
|
||||
const login = async (tenant: Tenant, token: string) => {
|
||||
try {
|
||||
await authorize({
|
||||
tenant_id: tenant.tenant_id, token: token
|
||||
})
|
||||
setToken(token)
|
||||
setTenant(tenant)
|
||||
} catch {
|
||||
Promise.resolve("authorize error")
|
||||
}
|
||||
}
|
||||
|
||||
const logout = async () => {
|
||||
tenant.value.account = ''
|
||||
tenant.value.token = ''
|
||||
tenant.value.id = ''
|
||||
resetToken()
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
const reflush = async () => {
|
||||
if (getToken()) {
|
||||
const tenantStorage = <Tenant>(JSON.parse(getTenant() as string))
|
||||
const token = <string>getToken()
|
||||
tenant.value.account = tenantStorage.account
|
||||
tenant.value.token = token
|
||||
tenant.value.id = tenantStorage.tenant_id
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
tenant,
|
||||
login,
|
||||
logout,
|
||||
reflush
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(tenantStore, import.meta.hot))
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import { acceptHMRUpdate, defineStore } from "pinia"
|
||||
import { get_vt_symbols, get_exchanges, get_subscribe_vt_symbols } from '../api/capital'
|
||||
|
||||
export const strategyStore = defineStore({
|
||||
id: 'strategy',
|
||||
state: () => ({
|
||||
class_names: [],
|
||||
vt_symbols: new Map(),
|
||||
subscribe_vt_symbols: [],
|
||||
exchanges: []
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async select_exchanges() {
|
||||
if (this.exchanges.length == 0) {
|
||||
get_exchanges().then(res => {
|
||||
this.$patch({ exchanges: res.data.exchanges })
|
||||
})
|
||||
}
|
||||
},
|
||||
async select_vt_symbols() {
|
||||
if (this.vt_symbols.size == 0) {
|
||||
get_vt_symbols().then(res => {
|
||||
let keys = Object.keys(res.data.vt_symbols)
|
||||
keys.forEach(key => {
|
||||
this.vt_symbols.set(key, res.data.vt_symbols[key])
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
async select_subscribe_vt_symbols() {
|
||||
if (this.subscribe_vt_symbols.length == 0) {
|
||||
get_subscribe_vt_symbols().then(res => {
|
||||
this.$patch({ subscribe_vt_symbols: res.data.vt_symbols })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(strategyStore, import.meta.hot))
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||
import { authorize } from '../api/user'
|
||||
import { getToken, setToken, resetToken, setTenant, getTenant } from '../utils/auth'
|
||||
import { Tenant } from '../entity/index'
|
||||
|
||||
/**
|
||||
* Simulate a login
|
||||
* @param {string} a
|
||||
* @param {string} p
|
||||
*/
|
||||
// function apiLogin(a, p) {
|
||||
// if (a === 'ed' && p === 'ed') return Promise.resolve({ isAdmin: true })
|
||||
// if (p === 'ed') return Promise.resolve({ isAdmin: false })
|
||||
// return Promise.reject(new Error('invalid credentials'))
|
||||
// }
|
||||
|
||||
export const tenantStore = defineStore({
|
||||
id: 'tenant',
|
||||
state: () => ({
|
||||
account: '',
|
||||
token: '',
|
||||
id: ''
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
||||
},
|
||||
actions: {
|
||||
logout() {
|
||||
this.$patch({
|
||||
account: '',
|
||||
token: '',
|
||||
id: ''
|
||||
})
|
||||
resetToken()
|
||||
// we could do other stuff like redirecting the user
|
||||
},
|
||||
|
||||
/**
|
||||
* Attempt to login a tenant
|
||||
* @param {object} tenant
|
||||
* @param {string} token
|
||||
*/
|
||||
async login(tenant: any, token: string) {
|
||||
|
||||
try {
|
||||
await authorize({
|
||||
tenant_id: tenant.tenant_id, token: token
|
||||
})
|
||||
setToken(token)
|
||||
setTenant(tenant)
|
||||
} catch {
|
||||
Promise.resolve("authorize error")
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
async reflush() {
|
||||
if (getToken()) {
|
||||
const tenant = <Tenant>(JSON.parse(getTenant() as string))
|
||||
const token = <string>getToken()
|
||||
this.$patch({
|
||||
account: tenant.account,
|
||||
token: token,
|
||||
id: tenant.id
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if (import.meta.hot) {
|
||||
import.meta.hot.accept(acceptHMRUpdate(tenantStore, import.meta.hot))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
$color: red;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { addZero } from "./number"
|
||||
|
||||
// 对Date的扩展,将 Date 转化为指定格式的String
|
||||
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
|
||||
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
|
||||
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
|
||||
// (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
|
||||
// eslint-disable-next-line no-extend-native
|
||||
const format = (date: Date, fmt: string) => {
|
||||
var o = {
|
||||
'M+': date.getMonth() + 1, // 月份
|
||||
'd+': date.getDate(), // 日
|
||||
'h+': date.getHours(), // 小时
|
||||
'm+': date.getMinutes(), // 分
|
||||
's+': date.getSeconds(), // 秒
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
|
||||
'S': date.getMilliseconds() // 毫秒
|
||||
}
|
||||
if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) }
|
||||
for (var k in o) {
|
||||
// if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
|
||||
}
|
||||
return fmt
|
||||
}
|
||||
|
||||
const formatTimeToStr = (times: any, pattern: string) => {
|
||||
|
||||
if (!pattern) {
|
||||
pattern = 'yyyy-MM-dd hh:mm:ss'
|
||||
}
|
||||
let date = format(new Date(times), pattern)
|
||||
return date.toLocaleString()
|
||||
}
|
||||
|
||||
// 2023-01-03
|
||||
const toLocalDate = (date: Date) => {
|
||||
return date.getFullYear() + '-' + addZero(date.getMonth() + 1) + '-' + addZero(date.getDate())
|
||||
}
|
||||
|
||||
export {
|
||||
formatTimeToStr,
|
||||
toLocalDate,
|
||||
}
|
||||
+11
-1
@@ -2,4 +2,14 @@ const toPercent = (num: number) => {
|
||||
return (num * 100).toFixed(2) + "%"
|
||||
}
|
||||
|
||||
export { toPercent }
|
||||
const addZero = (num: number) => {
|
||||
if (num > 10) {
|
||||
return num
|
||||
}
|
||||
return '0' + num
|
||||
}
|
||||
|
||||
export {
|
||||
toPercent,
|
||||
addZero
|
||||
}
|
||||
@@ -53,7 +53,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { reactive, ref } from 'vue'
|
||||
import { delete_bookmark_type, post_bookmark_type, get_bookmark_type } from '../../api/bookmark_type'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
const formLabelWidth = '140px'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref } from 'vue'
|
||||
import { put_bookmark_type } from '../../api/bookmark_type'
|
||||
|
||||
const bookmark_type_name = ref<String>('')
|
||||
|
||||
@@ -3,12 +3,8 @@
|
||||
<el-form :model="dialog_form">
|
||||
<el-form-item label="分类" :label-width="formLabelWidth">
|
||||
<el-select v-model="dialog_form.bk_type_id" placeholder>
|
||||
<el-option
|
||||
v-for="(item) in types"
|
||||
:key="item.bk_type_id"
|
||||
:value="item.bk_type_id"
|
||||
:label="item.bk_type_name"
|
||||
/>
|
||||
<el-option v-for="(item) in types" :key="item.bk_type_id" :value="item.bk_type_id"
|
||||
:label="item.bk_type_name" />
|
||||
</el-select>
|
||||
<el-form-item label="备注" :label-width="formLabelWidth">
|
||||
<el-input v-model="dialog_form.comment" autocomplete="off" />
|
||||
@@ -28,7 +24,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from 'vue';
|
||||
import { reactive } from 'vue'
|
||||
import { update_bookmark, put_bookmark } from '../../api/bookmark'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
const formLabelWidth = '140px'
|
||||
@@ -69,15 +65,19 @@ const submit = () => {
|
||||
|
||||
|
||||
</script>
|
||||
<style scoped>.el-button--text {
|
||||
<style scoped>
|
||||
.el-button--text {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.dialog-footer button:first-child {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
+19
-19
@@ -14,12 +14,12 @@
|
||||
<div class="tag_list">
|
||||
<el-tag class="ml-2 click-icon" :type="item.clicked ? 'danger' : 'info'" v-for="(item) in bookmark_types"
|
||||
@click="handleTags(item)">{{ item.bk_type_name }}</el-tag>
|
||||
<el-button type="primary" @click="handleAddType" v-show="Tenant.account">增加</el-button>
|
||||
<el-button type="primary" @click="handleManageType" v-show="Tenant.account">自定义</el-button>
|
||||
<el-button type="primary" @click="handleAddType" v-show="useTenantStore.tenant.account">增加</el-button>
|
||||
<el-button type="primary" @click="handleManageType" v-show="useTenantStore.tenant.account">自定义</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
<div class="create_dialog">
|
||||
<el-button type="primary" @click="handleInsert" v-show="Tenant.account">新建</el-button>
|
||||
<el-button type="primary" @click="handleInsert" v-show="useTenantStore.tenant.account">新建</el-button>
|
||||
</div>
|
||||
|
||||
<el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%">
|
||||
@@ -39,9 +39,10 @@
|
||||
<CopyDocument />
|
||||
</el-icon>
|
||||
<el-button class="click-icon" size="small" @click="handleEdit(scope.$index, scope.row)"
|
||||
v-show="Tenant.account">编辑
|
||||
v-show="useTenantStore.tenant.account">编辑
|
||||
</el-button>
|
||||
<el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)" v-show="Tenant.account">
|
||||
<el-button size="small" type="danger" @click="handleDelete(scope.$index, scope.row)"
|
||||
v-show="useTenantStore.tenant.account">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -72,34 +73,33 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { search_bookmark, delete_bookmark } from '../../api/bookmark'
|
||||
import { get_bookmark_type } from '../../api/bookmark_type'
|
||||
import { reactive, ref, h } from 'vue'
|
||||
import type { ElTable } from 'element-plus'
|
||||
import { CopyDocument } from "@element-plus/icons-vue"
|
||||
import { ElNotification } from 'element-plus'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import bookmark_dialog from './dialog.vue'
|
||||
import bookmarkType_dialog from './Typedialog.vue'
|
||||
import createType_dialog from './createTypedialog.vue'
|
||||
import delete_dialog from '../../components/operate/deleteDialog.vue'
|
||||
import type { ElTable } from 'element-plus'
|
||||
import { CopyDocument } from "@element-plus/icons-vue";
|
||||
import { ElNotification } from 'element-plus'
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { h } from 'vue'
|
||||
import { tenantStore } from '../../store/tenant'
|
||||
import { tenantStore } from '../../store/modules/tenant'
|
||||
import { search_bookmark, delete_bookmark } from '../../api/bookmark'
|
||||
import { get_bookmark_type } from '../../api/bookmark_type'
|
||||
// obtain user infomation
|
||||
const Tenant = tenantStore()
|
||||
const useTenantStore = tenantStore()
|
||||
|
||||
// 定义书签格式
|
||||
type Bookmark = {
|
||||
bk_id: string,
|
||||
bk_type_id: number,
|
||||
bk_type_name: String,
|
||||
comment: String,
|
||||
url: String
|
||||
bk_type_name: string,
|
||||
comment: string,
|
||||
url: string
|
||||
}
|
||||
// 定义 表单格式
|
||||
type Searchform = {
|
||||
bk_type_ids: number[],
|
||||
comment: String
|
||||
comment: string
|
||||
}
|
||||
|
||||
// 操作code
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<el-calendar v-model="value" v-if="isComponentActive" v-loading="isComponentLoading"
|
||||
element-loading-text="主人,别着急我在努力加载中^_^">
|
||||
<template #dateCell="{ data }" lo>
|
||||
<div class="date-cell-holiday" v-if="Object.keys(holidays).includes(toLocalDate(data.date))">
|
||||
<span style="color: red;" @click="onclick(data.date)"> {{ data.date.getDate() }}</span><br>
|
||||
<span>{{ holidays[toLocalDate(data.date)] }}</span>
|
||||
</div>
|
||||
<div class="date-cell" v-else>
|
||||
<span style="color: red;" v-if="data.date.getDay() == 0 || data.date.getDay() == 6" @click="onclick(data.date)">
|
||||
{{
|
||||
data.date.getDate()
|
||||
}}</span>
|
||||
<span v-else @click="onclick(data.date)"> {{ data.date.getDate() }}</span>
|
||||
</div>
|
||||
<div class="date-cell-event" v-if="Object.keys(eventDataObject).includes(toLocalDate(data.date))">
|
||||
<span>{{ eventDataObject[toLocalDate(data.date)] }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-calendar>
|
||||
<span>待办事项</span>
|
||||
<el-table :data="eventDataList">
|
||||
<el-table-column property="event_date" label="Date" width="150" />
|
||||
<el-table-column property="title" label="title" width="200" />
|
||||
<el-table-column property="event_info" label="eventInfo" />
|
||||
</el-table>
|
||||
|
||||
<el-dialog v-model="dialogFormVisible" title="待办事项">
|
||||
<el-form :model="form">
|
||||
<el-form-item label="日期" :label-width="formLabelWidth">
|
||||
<span>{{ form.event_date }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="title" :label-width="formLabelWidth">
|
||||
<el-input v-model="form.title" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="eventInfo" :label-width="formLabelWidth">
|
||||
<el-input v-model="form.event_info" autocomplete="off" type="textarea" />
|
||||
</el-form-item>
|
||||
<el-form-item label="alert" :label-width="formLabelWidth">
|
||||
<el-checkbox-group v-model="checkedalerts" :min="0" :max="2">
|
||||
<el-checkbox v-for="city in alerts" :key="city" :label="city">{{
|
||||
city
|
||||
}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">Cancel</el-button>
|
||||
<el-button type="primary" @click="confirm">
|
||||
Confirm
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import { get_holiday } from '@/service/calendar'
|
||||
import { toLocalDate } from '@/utils/date'
|
||||
import { get_event, put_event } from "@/api/calendar"
|
||||
import { Event } from "@/entity/index"
|
||||
import { settingsStore } from "@/store/modules/settings";
|
||||
|
||||
|
||||
// -- IMPORT --
|
||||
const useSettingsStore = settingsStore()
|
||||
|
||||
// -- REACTIVE OBJECT --
|
||||
const holidays = reactive<any>({})
|
||||
|
||||
const eventDataList = reactive<Event[]>([])
|
||||
const eventDataObject = reactive<any>({})
|
||||
const form = reactive({
|
||||
event_date: '',
|
||||
title: '',
|
||||
event_info: '',
|
||||
})
|
||||
// -- REF OBJECT --
|
||||
const value = ref(new Date())
|
||||
const dialogFormVisible = ref(false)
|
||||
const formLabelWidth = '140px'
|
||||
const isComponentActive = ref(false)
|
||||
const isComponentLoading = ref(true)
|
||||
|
||||
const checkedalerts = ref([])
|
||||
const alerts = ['email', 'messageBox', '手机短信', '微信通知']
|
||||
|
||||
// -- EVENT DEFINITION
|
||||
const onclick = (date: Date) => {
|
||||
form.event_date = toLocalDate(date)
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
|
||||
const confirm = async () => {
|
||||
await put_event(form).then(() => {
|
||||
|
||||
})
|
||||
dialogFormVisible.value = false
|
||||
handleCommand('refresh')
|
||||
}
|
||||
|
||||
const handleCommand = (command: string) => {
|
||||
if (command === 'refresh') {
|
||||
useSettingsStore.settings.isLoading = true
|
||||
useSettingsStore.settings.isRouterAlive = false
|
||||
nextTick(() => {
|
||||
useSettingsStore.settings.isRouterAlive = true
|
||||
useSettingsStore.settings.isLoading = false
|
||||
})
|
||||
} else if (command === 'closeOther') {
|
||||
// useSettingsStore.closeOther()
|
||||
} else {
|
||||
// useSettingsStore.closeLeftOrRight(command)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AUTO INVOKE FUNCTION
|
||||
*/
|
||||
onMounted(async () => {
|
||||
await get_holiday().then((resp) => {
|
||||
Object.keys(resp.data).forEach(element => {
|
||||
holidays[element] = resp.data[element]
|
||||
})
|
||||
})
|
||||
await get_event().then((response) => {
|
||||
eventDataList.length = 0
|
||||
response.data.forEach((record: Event) => {
|
||||
eventDataList.push(record)
|
||||
eventDataObject[record.event_date] = record.title
|
||||
})
|
||||
})
|
||||
isComponentActive.value = true
|
||||
isComponentLoading.value = false
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.date-cell-holiday {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.date-cell-event {
|
||||
background: yellow;
|
||||
}
|
||||
</style>
|
||||
@@ -48,7 +48,7 @@
|
||||
<el-collapse-item title="手动下单" name="2">
|
||||
|
||||
<el-select v-model="vt_symbol" placeholder="select a vt_symbol" @change="select_contract">
|
||||
<el-option v-for="symbol in store.subscribe_vt_symbols" :value="symbol" />
|
||||
<el-option v-for="symbol in useStrategyStore.strategy.subscribe_vt_symbols" :value="symbol" />
|
||||
</el-select>
|
||||
<div style="height: 10px;"></div>
|
||||
<el-row>
|
||||
@@ -134,14 +134,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import { ElMessage, TabsPaneContext } from 'element-plus'
|
||||
import { reactive, ref, h, onMounted, onUnmounted } from 'vue'
|
||||
import { get_accounts, send_order, get_tick } from '../../api/capital'
|
||||
import { strategyStore } from '../../store/strategy'
|
||||
import { strategyStore } from '../../store/modules/strategy'
|
||||
|
||||
// -- IMPORT --
|
||||
const store = strategyStore()
|
||||
const useStrategyStore = strategyStore()
|
||||
|
||||
// -- INTERFACE OR TYPE DEFINITION --
|
||||
interface AccountData {
|
||||
@@ -272,7 +271,7 @@ const on_order = () => {
|
||||
*/
|
||||
(() => {
|
||||
|
||||
store.select_subscribe_vt_symbols()
|
||||
useStrategyStore.select_subscribe_vt_symbols()
|
||||
onMounted(() => {
|
||||
clearInterval(timer.value)
|
||||
timer.value = window.setInterval(on_query_accounts(), 3000);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<div class="dashboard-line-box">
|
||||
<div class="dashboard-line-title">
|
||||
访问趋势
|
||||
</div>
|
||||
<div ref="echart" class="dashboard-line" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import * as echarts from 'echarts'
|
||||
import { nextTick, onMounted, onUnmounted, ref, shallowRef } from 'vue'
|
||||
// import 'echarts/theme/macarons'
|
||||
|
||||
var dataAxis: Array<string> = []
|
||||
for (var i = 1; i < 13; i++) {
|
||||
dataAxis.push(`${i}月`)
|
||||
}
|
||||
var data = [
|
||||
220,
|
||||
182,
|
||||
191,
|
||||
234,
|
||||
290,
|
||||
330,
|
||||
310,
|
||||
123,
|
||||
442,
|
||||
321,
|
||||
90,
|
||||
149,
|
||||
]
|
||||
var yMax = 500
|
||||
var dataShadow = []
|
||||
|
||||
// eslint-disable-next-line no-redeclare
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
dataShadow.push(yMax)
|
||||
}
|
||||
|
||||
const chart = shallowRef()
|
||||
const echart = ref()
|
||||
const initChart = () => {
|
||||
chart.value = echarts.init(echart.value /* 'macarons' */)
|
||||
setOptions()
|
||||
}
|
||||
const setOptions = () => {
|
||||
chart.value.setOption({
|
||||
grid: {
|
||||
left: '40',
|
||||
right: '20',
|
||||
top: '40',
|
||||
bottom: '20',
|
||||
},
|
||||
xAxis: {
|
||||
data: dataAxis,
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
z: 10,
|
||||
},
|
||||
yAxis: {
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#999',
|
||||
},
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
},
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
barWidth: '40%',
|
||||
itemStyle: {
|
||||
borderRadius: [5, 5, 0, 0],
|
||||
color: '#188df0',
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
color: '#188df0',
|
||||
},
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
initChart()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (!chart.value) {
|
||||
return
|
||||
}
|
||||
chart.value.dispose()
|
||||
chart.value = null
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-line-box {
|
||||
.dashboard-line {
|
||||
background-color: #fff;
|
||||
height: 360px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dashboard-line-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="commit-table">
|
||||
<div class="commit-table-title">
|
||||
更新日志
|
||||
</div>
|
||||
<div class="log">
|
||||
<div v-for="(item, key) in dataTimeline" :key="key" class="log-item">
|
||||
<div class="flex-1 flex key-box">
|
||||
<span class="key" :class="key < 3 && 'top'">{{ key+ 1 }}</span>
|
||||
</div>
|
||||
<div class="flex-5 flex message">{{ item.message }}</div>
|
||||
<div class="flex-3 flex form">{{ item.from }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { Commits } from '@/service/github'
|
||||
import { formatTimeToStr } from '@/utils/date'
|
||||
import { DataTimeline } from "@/entity/index";
|
||||
|
||||
const loading = ref(true)
|
||||
const dataTimeline = reactive<DataTimeline[]>([])
|
||||
|
||||
const loadCommits = () => {
|
||||
Commits(0).then(({ data }) => {
|
||||
loading.value = false
|
||||
data.forEach((element: any, index: any) => {
|
||||
if (element.commit.message && index < 10) {
|
||||
dataTimeline.push({
|
||||
from: formatTimeToStr(element.commit.author.date, 'yyyy-MM-dd'),
|
||||
title: element.commit.author.name,
|
||||
showDayAndMonth: true,
|
||||
message: element.commit.message,
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
loadCommits()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.commit-table {
|
||||
background-color: #fff;
|
||||
height: 400px;
|
||||
|
||||
&-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.log {
|
||||
&-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 14px;
|
||||
|
||||
.key-box {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.key {
|
||||
&.top {
|
||||
background: #314659;
|
||||
color: #FFFFFF;
|
||||
;
|
||||
}
|
||||
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #F0F2F5;
|
||||
text-align: center;
|
||||
color:rgba($color: #000000, $alpha: 0.65)
|
||||
}
|
||||
|
||||
.message {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
|
||||
.form {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.flex {
|
||||
line-height: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.flex-2 {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.flex-3 {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
.flex-4 {
|
||||
flex: 4;
|
||||
}
|
||||
|
||||
.flex-5 {
|
||||
flex: 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +1,392 @@
|
||||
<template>
|
||||
<div class="about" ref="bookmarks" id="bookmarks" :style="{
|
||||
width: '600px',
|
||||
height: '400px'
|
||||
}"></div>
|
||||
<div class="page">
|
||||
<div class="gva-card-box">
|
||||
<div class="gva-card gva-top-card">
|
||||
<div class="gva-top-card-left">
|
||||
<div class="gva-top-card-left-title">我的主人,我们又见面了,我有什么能帮助你么^_^</div>
|
||||
<div class="gva-top-card-left-dot">{{ weatherInfo }}</div>
|
||||
<div class="gva-top-card-left-rows">
|
||||
<el-row>
|
||||
<el-col :span="8" :xs="24" :sm="8">
|
||||
<div class="flex-center">
|
||||
<el-icon class="dashboard-icon">
|
||||
<sort />
|
||||
</el-icon>
|
||||
wiki数量 ({{ statistics.wiki_count }})
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8" :xs="24" :sm="8">
|
||||
<div class="flex-center">
|
||||
<el-icon class="dashboard-icon">
|
||||
<avatar />
|
||||
</el-icon>
|
||||
bookmark数量 ({{ statistics.bookmark_count }})
|
||||
</div>
|
||||
</el-col>
|
||||
<!-- <el-col :span="8" :xs="24" :sm="8">
|
||||
<div class="flex-center">
|
||||
<el-icon class="dashboard-icon">
|
||||
<comment />
|
||||
</el-icon>
|
||||
好评率 (99%)
|
||||
</div>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="gva-top-card-left-item">
|
||||
<div>
|
||||
{{ time }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="gva-top-card-left-item">
|
||||
<div>
|
||||
期货交易时间 
|
||||
<el-icon color="yellow">
|
||||
<Sunrise />
|
||||
</el-icon>  9:00-11:30  
|
||||
<el-icon color="gold">
|
||||
<Sunny />
|
||||
</el-icon>  13:30-15:00  
|
||||
<el-icon color="blue">
|
||||
<Moon />
|
||||
</el-icon>  21:00-23:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<img src="../../assets/dashboard.png" class="gva-top-card-right">
|
||||
</div>
|
||||
</div>
|
||||
<div class="gva-card-box">
|
||||
<el-card class="gva-card quick-entrance">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>快捷入口</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row :gutter="20">
|
||||
<el-col v-for="(card, key) in toolCards" :key="key" :span="4" :xs="8" class="quick-entrance-items"
|
||||
@click="toTarget(card.name)">
|
||||
<div class="quick-entrance-item">
|
||||
<div class="quick-entrance-item-icon" :style="{ backgroundColor: card.bg }">
|
||||
<el-icon>
|
||||
<component :is="card.icon" :style="{ color: card.color }" />
|
||||
</el-icon>
|
||||
</div>
|
||||
<p>{{ card.label }}</p>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<!-- <div class="quick-entrance-title"></div> -->
|
||||
</div>
|
||||
<div class="gva-card-box">
|
||||
<div class="gva-card">
|
||||
<div class="card-header">
|
||||
<span>数据统计</span>
|
||||
</div>
|
||||
<div class="echart-box">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :sm="18">
|
||||
<echarts-line />
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="6">
|
||||
<dashboard-table />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import $moment from "moment"
|
||||
import EchartsLine from '@/view/dashboard/dashboardCharts/index.vue'
|
||||
import DashboardTable from '@/view/dashboard/dashboardTable/index.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useWeatherInfo } from '@/service/weather'
|
||||
import { countBlogs } from "@/api/blog"
|
||||
import { bookmarks_count } from "@/api/bookmark"
|
||||
|
||||
// -- IMPORT --
|
||||
const weatherInfo = useWeatherInfo()
|
||||
const router = useRouter()
|
||||
|
||||
// -- REACTIVE OBJECT --
|
||||
|
||||
// -- REF OBJECT --
|
||||
let time = ref<String>($moment().format("YYYY年MM月DD日 HH:mm:ss"));
|
||||
|
||||
const statistics = ref({
|
||||
wiki_count: 0,
|
||||
bookmark_count: 0,
|
||||
})
|
||||
|
||||
const toolCards = ref([
|
||||
{
|
||||
label: 'Jenkins',
|
||||
icon: 'camera',
|
||||
name: 'Jenkins',
|
||||
color: '#ff9c6e',
|
||||
bg: 'rgba(255, 156, 110,.3)'
|
||||
},
|
||||
{
|
||||
label: 'argo-cd',
|
||||
icon: 'monitor',
|
||||
name: 'argocd',
|
||||
color: '#69c0ff',
|
||||
bg: 'rgba(92, 219, 211,.3)'
|
||||
},
|
||||
{
|
||||
label: 'wiki',
|
||||
icon: 'document',
|
||||
name: 'wiki',
|
||||
color: '#b37feb',
|
||||
bg: 'rgba(185, 192, 255,.3)'
|
||||
},
|
||||
{
|
||||
label: '代码生成器',
|
||||
icon: 'cpu',
|
||||
name: 'autoCode',
|
||||
color: '#ffd666',
|
||||
bg: 'rgba(255, 214, 102,.3)'
|
||||
},
|
||||
{
|
||||
label: '表单生成器',
|
||||
icon: 'document-checked',
|
||||
name: 'formCreate',
|
||||
color: '#ff85c0',
|
||||
bg: 'rgba(255, 133, 192,.3)'
|
||||
},
|
||||
{
|
||||
label: '关于我们',
|
||||
icon: 'user',
|
||||
name: 'about',
|
||||
color: '#5cdbd3',
|
||||
bg: 'rgba(92, 219, 211,.3)'
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
// -- EVENT DEFINITION
|
||||
const toTarget = (name: string) => {
|
||||
// router.push({ name })
|
||||
switch (name) {
|
||||
case 'Jenkins':
|
||||
window.open('https://www.violin-home.cn/jenkins/', '_blank')
|
||||
break;
|
||||
case 'argocd':
|
||||
window.open('https://www.violin-home.cn/argo-cd/', '_blank')
|
||||
break;
|
||||
case 'wiki':
|
||||
window.open('https://www.violin-home.cn/docs#/guan/', '_blank')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AUTO INVOKE FUNCTION
|
||||
*/
|
||||
setInterval(() => {
|
||||
time.value = $moment().format("YYYY年MM月DD日 HH:mm:ss")
|
||||
}, 1000)
|
||||
|
||||
countBlogs().then((resp) => {
|
||||
const data = resp.data
|
||||
statistics.value.wiki_count = data.count
|
||||
})
|
||||
bookmarks_count().then((resp) => {
|
||||
const data = resp.data
|
||||
statistics.value.bookmark_count = data.count
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss" scoped>
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.page {
|
||||
background: #f0f2f5;
|
||||
padding: 0;
|
||||
|
||||
.gva-card-box {
|
||||
padding: 12px 16px;
|
||||
|
||||
&+.gva-card-box {
|
||||
padding-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.gva-card {
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
height: auto;
|
||||
padding: 26px 30px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 0 7px 1px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.gva-top-card {
|
||||
height: 260px;
|
||||
@include flex-center;
|
||||
justify-content: space-between;
|
||||
color: #777;
|
||||
|
||||
&-left {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&-title {
|
||||
font-size: 22px;
|
||||
color: #343844;
|
||||
}
|
||||
|
||||
&-dot {
|
||||
font-size: 16px;
|
||||
color: #6B7687;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
&-rows {
|
||||
// margin-top: 15px;
|
||||
margin-top: 18px;
|
||||
color: #6B7687;
|
||||
width: 600px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-item {
|
||||
+.gva-top-card-left-item {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
margin-top: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
height: 600px;
|
||||
width: 600px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-card__header) {
|
||||
padding: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.quick-entrance-title {
|
||||
height: 30px;
|
||||
font-size: 22px;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.quick-entrance-items {
|
||||
@include flex-center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
|
||||
.quick-entrance-item {
|
||||
padding: 16px 28px;
|
||||
margin-top: -16px;
|
||||
margin-bottom: -16px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0px 0px 7px 0px rgba(217, 217, 217, 0.55);
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
height: auto;
|
||||
text-align: center;
|
||||
|
||||
// align-items: center;
|
||||
&-icon {
|
||||
width: 50px;
|
||||
height: 50px !important;
|
||||
border-radius: 8px;
|
||||
@include flex-center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
|
||||
i {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.echart-box {
|
||||
padding: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-icon {
|
||||
font-size: 20px;
|
||||
color: rgb(85, 160, 248);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
@include flex-center;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
@include flex-center;
|
||||
}
|
||||
|
||||
//小屏幕不显示右侧,将登录框居中
|
||||
@media (max-width: 750px) {
|
||||
.gva-card {
|
||||
padding: 20px 10px !important;
|
||||
|
||||
.gva-top-card {
|
||||
height: auto;
|
||||
|
||||
&-left {
|
||||
&-title {
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
&-rows {
|
||||
margin-top: 15px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.gva-middle-card {
|
||||
&-item {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-icon {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -5,14 +5,14 @@
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<el-select v-model="exchange" placeholder="select a exchange">
|
||||
<el-option v-for="ex in store.exchanges" :value="ex" />
|
||||
<el-option v-for="ex in useStrategyStore.strategy.exchanges" :value="ex" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-select v-model="vt_symbol" placeholder="select a vt_symbol">
|
||||
<el-option v-for="symbol in store.vt_symbols.get(exchange)" :value="symbol" />
|
||||
<el-option v-for="symbol in useStrategyStore.strategy.vt_symbols.get(exchange)" :value="symbol" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
@@ -56,15 +56,16 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, h, onMounted, onUnmounted, reactive, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { get_ticks, subscribe, concel_subscribe } from '../../api/capital'
|
||||
import { strategyStore } from '../../store/strategy'
|
||||
import * as echarts from 'echarts'
|
||||
import { Contextmenu, ContextmenuItem } from "v-contextmenu"
|
||||
import { get_ticks, subscribe, concel_subscribe } from '../../api/capital'
|
||||
import { strategyStore } from '../../store/modules/strategy'
|
||||
import { toPercent } from '../../utils/number'
|
||||
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
// -- IMPORT --
|
||||
const currentInstance = getCurrentInstance()
|
||||
const store = strategyStore()
|
||||
const useStrategyStore = strategyStore()
|
||||
|
||||
// -- INTERFACE OR TYPE DEFINITION --
|
||||
interface TickData {
|
||||
@@ -104,7 +105,7 @@ const on_subscribe = () => {
|
||||
h('i', { style: 'color: green' }, "行情订阅成功"),
|
||||
]),
|
||||
})
|
||||
store.select_subscribe_vt_symbols()
|
||||
useStrategyStore.select_subscribe_vt_symbols()
|
||||
on_ticks()
|
||||
}).catch(error => {
|
||||
ElMessage({
|
||||
@@ -189,7 +190,7 @@ const on_ticks = () => {
|
||||
window.clearInterval(timer.value)
|
||||
})
|
||||
|
||||
store.select_subscribe_vt_symbols()
|
||||
useStrategyStore.select_subscribe_vt_symbols()
|
||||
.catch(error => {
|
||||
ElMessage({
|
||||
message: h('p', null, [
|
||||
@@ -198,7 +199,7 @@ const on_ticks = () => {
|
||||
})
|
||||
})
|
||||
|
||||
store.select_vt_symbols()
|
||||
useStrategyStore.select_vt_symbols()
|
||||
.catch((error) => {
|
||||
ElMessage({
|
||||
message: h('p', null, [
|
||||
@@ -207,7 +208,7 @@ const on_ticks = () => {
|
||||
})
|
||||
})
|
||||
|
||||
store.select_exchanges()
|
||||
useStrategyStore.select_exchanges()
|
||||
.catch((error) => {
|
||||
ElMessage({
|
||||
message: h('p', null, [
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<el-button text @click="open">Click to open the Message Box</el-button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import type { Action } from 'element-plus'
|
||||
|
||||
const open = () => {
|
||||
ElMessageBox.alert('This is a message', 'Title', {
|
||||
// if you want to disable its autofocus
|
||||
// autofocus: false,
|
||||
confirmButtonText: 'OK',
|
||||
callback: (action: Action) => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: `action: ${action}`,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
@@ -1,12 +0,0 @@
|
||||
<template>
|
||||
<div class="dashboard">感悟这个东西,暂时没有什么太多想法,以后会被删掉把</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.dashboard {
|
||||
background-color: beige;
|
||||
}
|
||||
</style>
|
||||
@@ -61,8 +61,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { onMounted, reactive, ref, h } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import create_strategy_dialog from './dialog.vue'
|
||||
import { strategyStore } from '../../store/modules/strategy'
|
||||
import {
|
||||
get_strategies,
|
||||
init_strategy,
|
||||
@@ -72,9 +74,6 @@ import {
|
||||
get_strategy_status,
|
||||
get_strategy_load_files,
|
||||
} from '../../api/cta_strategy'
|
||||
import { h } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { strategyStore } from '../../store/strategy'
|
||||
|
||||
type Strategy = {
|
||||
strategy_name: string,
|
||||
@@ -84,7 +83,7 @@ type Strategy = {
|
||||
status: number,
|
||||
}
|
||||
|
||||
const store = strategyStore()
|
||||
const useStrategyStore = strategyStore()
|
||||
let createStrategyDialogVisible = ref(false)
|
||||
const strategy_list = reactive<Strategy[]>([])
|
||||
const dialogRef = ref()
|
||||
@@ -133,7 +132,7 @@ const on_status = (row: any) => {
|
||||
onMounted(() => {
|
||||
on_list()
|
||||
get_strategy_load_files().then(res => {
|
||||
store.$patch({ class_names: res.data.class_names })
|
||||
useStrategyStore.strategy.class_names = res.data.class_names
|
||||
}).catch(error => {
|
||||
ElMessage({
|
||||
message: h('p', null, [
|
||||
|
||||
@@ -66,17 +66,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { reactive, ref, h } from 'vue'
|
||||
import { UploadInstance, UploadProps, UploadRawFile, genFileId, ElMessage, ElButton, ElIcon, ElTable, ElTableColumn, ElUpload } from 'element-plus'
|
||||
import {
|
||||
get_strategy_files,
|
||||
load_strategy_file,
|
||||
unload_strategy_file,
|
||||
remove_strategy_file
|
||||
} from '../../api/cta_strategy'
|
||||
import { genFileId } from 'element-plus'
|
||||
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
// -- INTERFACE OR TYPE DEFINITION --
|
||||
interface StrategyFile {
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="vt_symbol" prop="vt_symbol">
|
||||
<el-select v-model="ruleForm.vt_symbol" placeholder="select a vt_symbol">
|
||||
<el-option v-for="vt_symbol in store.subscribe_vt_symbols" :value="vt_symbol" />
|
||||
<el-option v-for="vt_symbol in useStrategyStore.strategy.subscribe_vt_symbols" :value="vt_symbol" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="class_name" prop="class_name">
|
||||
<el-select v-model="ruleForm.class_name" placeholder="select a class_name">
|
||||
<el-option v-for="name in store.class_names" :value="name" />
|
||||
<el-option v-for="name in useStrategyStore.strategy.class_names" :value="name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="setting:">
|
||||
@@ -47,9 +47,9 @@ import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { create_strategy } from '../../api/cta_strategy'
|
||||
import { h } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { strategyStore } from '../../store/strategy'
|
||||
import { strategyStore } from '../../store/modules/strategy'
|
||||
|
||||
const store = strategyStore()
|
||||
const useStrategyStore = strategyStore()
|
||||
|
||||
const formSize = ref('default')
|
||||
const ruleFormRef = ref<FormInstance>()
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from 'vue';
|
||||
import { onMounted, ref, reactive } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { EChartsOption } from 'echarts';
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { EChartsOption } from 'echarts'
|
||||
import { generateOHLC, option } from '../../service/trader'
|
||||
import { get_stock_data } from '../../api/trader'
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
"target": "esnext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "esnext",
|
||||
|
||||
+21
-2
@@ -1,7 +1,8 @@
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import viteCompression from 'vite-plugin-compression';
|
||||
import viteCompression from 'vite-plugin-compression'
|
||||
import { viteMockServe } from 'vite-plugin-mock'
|
||||
import { resolve } from 'path'
|
||||
|
||||
// https://vitejs.cn/guide/env-and-mode.html#env-files
|
||||
export default defineConfig(({ mode }) => {
|
||||
@@ -16,6 +17,24 @@ export default defineConfig(({ mode }) => {
|
||||
localEnabled: true,
|
||||
}),
|
||||
],
|
||||
base: env.VITE_RES_URL
|
||||
pluginOptions: {
|
||||
'style-resources-loader': {
|
||||
preProcessor: 'scss',
|
||||
patterns: []
|
||||
}
|
||||
},
|
||||
base: env.VITE_RES_URL,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
additionalData: `@import "@/style/mixin.scss";`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user