Vendored
-3
@@ -45,9 +45,6 @@ spec:
|
|||||||
- name: "volume-m2"
|
- name: "volume-m2"
|
||||||
hostPath:
|
hostPath:
|
||||||
path: "/root/.m2/repository"
|
path: "/root/.m2/repository"
|
||||||
- name: "maven-config"
|
|
||||||
configMap:
|
|
||||||
name: maven-config
|
|
||||||
- name: "volume-docker"
|
- name: "volume-docker"
|
||||||
hostPath:
|
hostPath:
|
||||||
path: "/var/run/docker.sock"
|
path: "/var/run/docker.sock"
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
## Vue 3 + Typescript + Vite + pinia + vue-router
|
## 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.
|
before create project, you should install node to promit npm and node command is standy.
|
||||||
npm -v
|
npm -v
|
||||||
node -v<br />
|
node -v<br />
|
||||||
|
|
||||||
// 在想要创建的工程路径下执行以下命令,3到6秒就可以结束
|
// 在想要创建的工程路径下执行以下命令,3到6秒就可以结束
|
||||||
npm init vite@latest
|
npm init vite@latest
|
||||||
// 1.填写 g-home
|
// 1.填写 violin-home
|
||||||
// 2.选择vue
|
// 2.选择vue
|
||||||
// 3.vue.ts
|
// 3.vue.ts
|
||||||
|
|
||||||
cd g-home
|
cd violin-home
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
## vue-router
|
## vue-router
|
||||||
@@ -33,19 +33,19 @@
|
|||||||
// to enter the home page:
|
// to enter the home page:
|
||||||
localhost:3000/home?tenantId=XXX&account=YYY&token=ABCDEFG
|
localhost:3000/home?tenantId=XXX&account=YYY&token=ABCDEFG
|
||||||
|
|
||||||
## 环境配置
|
## profiles
|
||||||
添加了.env.development ebv.test .env.production 文件
|
添加了.env.development ebv.test .env.production 文件
|
||||||
development:
|
development:
|
||||||
开发环境,使用mock,不需要后台联动
|
开发环境,使用mock,不需要后台联动
|
||||||
test:
|
test:
|
||||||
测试环境需要 后台java程序支持,同时需要百度第三方认证。
|
测试环境需要 后台java程序支持,同时需要百度第三方认证。
|
||||||
prod:
|
prod:
|
||||||
生产环境通过 jenkins cicd进行发布配置。
|
生产环境通过 jenkins 做ci 持续集成 argocd 做cd 持续发布。
|
||||||
|
|
||||||
# 云服务器
|
# prod server
|
||||||
nginx as a veb server, i use the official image to build this app image.
|
nginx as a web server, i use the official image to build this app image.
|
||||||
|
|
||||||
## 发布
|
## publish
|
||||||
- npm run build 生成dist 文件夹
|
- 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[]
|
] 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[]
|
] 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": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^1.1.4",
|
"@element-plus/icons-vue": "^1.1.4",
|
||||||
"@types/node": "^17.0.23",
|
"@types/node": "^17.0.23",
|
||||||
"axios": "^0.26.1",
|
|
||||||
"aplayer": "^1.10.1",
|
"aplayer": "^1.10.1",
|
||||||
|
"axios": "^0.26.1",
|
||||||
"clipboard": "^2.0.10",
|
"clipboard": "^2.0.10",
|
||||||
"copy-to-clipboard": "^3.3.1",
|
"copy-to-clipboard": "^3.3.1",
|
||||||
"echarts": "^5.3.2",
|
"echarts": "^5.3.2",
|
||||||
@@ -24,9 +24,14 @@
|
|||||||
"lodash-unified": "^1.0.2",
|
"lodash-unified": "^1.0.2",
|
||||||
"md-editor-v3": "^1.11.6",
|
"md-editor-v3": "^1.11.6",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
"node-sass": "^8.0.0",
|
||||||
"pinia": "^2.0.13",
|
"pinia": "^2.0.13",
|
||||||
"qs": "^6.10.3",
|
"qs": "^6.10.3",
|
||||||
|
"sass": "^1.57.1",
|
||||||
|
"sass-loader": "^13.2.0",
|
||||||
"save": "^2.4.0",
|
"save": "^2.4.0",
|
||||||
|
"scss": "^0.2.4",
|
||||||
|
"style-loader": "^3.3.1",
|
||||||
"type-fest": "^2.12.2",
|
"type-fest": "^2.12.2",
|
||||||
"vue": "^3.2.25",
|
"vue": "^3.2.25",
|
||||||
"vue-router": "^4.0.14",
|
"vue-router": "^4.0.14",
|
||||||
@@ -40,10 +45,10 @@
|
|||||||
"@vitejs/plugin-vue": "^2.3.0",
|
"@vitejs/plugin-vue": "^2.3.0",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
|
"v-contextmenu": "^3.0.0",
|
||||||
"vite": "^2.9.13",
|
"vite": "^2.9.13",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"v-contextmenu": "^3.0.0",
|
|
||||||
"vue-tsc": "^0.29.8"
|
"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 {
|
export {
|
||||||
search_bookmark,
|
search_bookmark,
|
||||||
put_bookmark,
|
put_bookmark,
|
||||||
delete_bookmark,
|
delete_bookmark,
|
||||||
delete_bookmarks,
|
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>
|
<template>
|
||||||
<div class="4444">
|
<div>
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-aside width="150px">
|
<el-aside width="180px">
|
||||||
<SideBar></SideBar>
|
<SideBar></SideBar>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-header
|
<el-header>
|
||||||
style="border-bottom-style:solid; border-bottom-width: 0.5px; border-bottom-color:rgba(151, 151, 151, 0.3);">
|
|
||||||
<NavBar></NavBar>
|
<NavBar></NavBar>
|
||||||
</el-header>
|
</el-header>
|
||||||
<el-main>
|
<el-main>
|
||||||
@@ -20,7 +19,6 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-avatar @click="openGithub" src="https://github.githubassets.com/favicons/favicon.svg" />
|
<el-avatar @click="openGithub" src="https://github.githubassets.com/favicons/favicon.svg" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-footer>
|
</el-footer>
|
||||||
</el-container>
|
</el-container>
|
||||||
</el-container>
|
</el-container>
|
||||||
@@ -31,6 +29,32 @@
|
|||||||
import MainApp from '../layout/MainApp.vue'
|
import MainApp from '../layout/MainApp.vue'
|
||||||
import NavBar from "../layout/NavBar.vue"
|
import NavBar from "../layout/NavBar.vue"
|
||||||
import SideBar from "../layout/SideBar.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 = () => {
|
const openGithub = () => {
|
||||||
let href = 'https://github.com/simple321vip'
|
let href = 'https://github.com/simple321vip'
|
||||||
@@ -42,48 +66,32 @@ const openSiteQuery = () => {
|
|||||||
window.open(href, '_blank')
|
window.open(href, '_blank')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AUTO INVOKE FUNCTION
|
||||||
|
*/
|
||||||
|
iniPage()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* .el-header,
|
.el-header {
|
||||||
.el-footer {
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 0.5px;
|
||||||
color: rgb(51, 51, 51);
|
border-bottom-color: rgba(151, 151, 151, 0.3);
|
||||||
text-align: center;
|
|
||||||
line-height: 60px;
|
|
||||||
} */
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
.el-aside {
|
|
||||||
background-color: #e9eef3;
|
|
||||||
color: #333;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 200px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-main {
|
.el-main {
|
||||||
background-color: #e9eef3;
|
padding: 16px;
|
||||||
color: #333;
|
overflow: hidden;
|
||||||
/* line-height: 450px; */
|
|
||||||
/* vertical-align: top;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body > .el-container {
|
.el-aside {
|
||||||
margin-bottom: 40px;
|
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 {
|
.el-footer {
|
||||||
|
margin-top: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="section-main" style="height:100%;">
|
<section class="section-main" v-loading="usesSttingsStore.isLoading" element-loading-text="页面加载中……"
|
||||||
<router-view />
|
element-loading-background="rgba(0, 0, 0, 0.1)">
|
||||||
|
<router-view v-if="usesSttingsStore.isRouterAlive" />
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
|
import { settingsStore } from "@/store/modules/settings"
|
||||||
|
const usesSttingsStore = settingsStore()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.section-main {
|
||||||
|
height: 100%;
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,88 +1,96 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nav-main">
|
<el-row class="pd-0">
|
||||||
<div style="width: 800px;">
|
<el-col :xs="2" :lg="1" :md="1" :sm="1" :xl="1" style="z-index:100">
|
||||||
<div>
|
<!-- <div class="menu-total" @click="totalCollapse">
|
||||||
当前时间:{{ time }}
|
<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>
|
</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>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu class="dropdown-group">
|
||||||
<el-dropdown-item>profile</el-dropdown-item>
|
<el-dropdown-item>
|
||||||
<el-dropdown-item @click="dialogVisible = true">退出</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>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog v-model="dialogVisible" title="提示" width="30%">
|
</el-col>
|
||||||
<span>确认你的登出操作么?</span>
|
</el-row>
|
||||||
<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>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import $moment from "moment";
|
import CustomPic from "@/components/customPic/index.vue";
|
||||||
import { reactive, ref } from "vue";
|
import { tenantStore } from '@/store/modules/tenant'
|
||||||
import router from '../../router'
|
import { settingsStore } from '@/store/modules/settings'
|
||||||
import { tenantStore } from '../../store/tenant'
|
|
||||||
import { logout } from '../../api/user'
|
|
||||||
// obtain user infomation
|
|
||||||
const tenant = tenantStore()
|
|
||||||
tenant.reflush()
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
|
|
||||||
// show time
|
// -- IMPORT --
|
||||||
let time = ref<String>($moment().format("YYYY年MM月DD日 HH:mm:ss"));
|
const useTenantStore = tenantStore()
|
||||||
setInterval(() => {
|
const useSettingsStore = settingsStore()
|
||||||
time.value = $moment().format("YYYY年MM月DD日 HH:mm:ss");
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// login logout function
|
// -- REACTIVE OBJECT --
|
||||||
const doLogin = () => {
|
|
||||||
router.push({
|
// -- REF OBJECT --
|
||||||
path: '/login'
|
|
||||||
})
|
// -- EVENT DEFINITION
|
||||||
}
|
const toPerson = () => {
|
||||||
const doLogout = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
logout(tenant.id).catch(() => { console.log(1) }).finally(() => {
|
|
||||||
tenant.logout()
|
|
||||||
router.push({
|
|
||||||
path: '/login'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useTenantStore.reflush()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style lang="scss" scoped>
|
||||||
.open_side {
|
.right-box {
|
||||||
background: url("../../assets/logo.png") center no-repeat;
|
padding-top: 16px;
|
||||||
background-size: cover;
|
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;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
/* background-color: bisque; */
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,27 +1,113 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-menu router class="side_Style" :style="{ height: sideHeight }">
|
<el-menu router class="el-menu-vertical" :style="{ height: sideHeight }" :background-color="theme.background"
|
||||||
<el-menu-item v-for="(route, index) in current_routes" v-bind:key="index" v-bind:index="route.path"
|
:active-text-color="theme?.background">
|
||||||
v-bind:title="route.meta?.name">{{ route.meta?.name }}</el-menu-item>
|
|
||||||
|
<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>
|
</el-menu>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { RouteRecordRaw } from "vue-router";
|
import { onBeforeMount, ref } from 'vue'
|
||||||
// import { store } from "../../store/index";
|
import router from "@/router/index"
|
||||||
import router from "../../router/index";
|
import { settingsStore } from "@/store/modules/settings"
|
||||||
import { onBeforeMount, ref } from 'vue';
|
import { Theme } from "@/entity/index";
|
||||||
let current_routes = router.options.routes[0].children;
|
|
||||||
|
|
||||||
|
// -- IMPORT --
|
||||||
|
const useSettingsStore = settingsStore()
|
||||||
|
|
||||||
|
// -- REACTIVE OBJECT --
|
||||||
|
|
||||||
|
// -- REF OBJECT --
|
||||||
let sideHeight = ref("")
|
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(() => {
|
onBeforeMount(() => {
|
||||||
sideHeight.value = window.innerHeight + 'px'
|
sideHeight.value = window.innerHeight + 'px'
|
||||||
})
|
})
|
||||||
|
const activeBackground = ref(theme.value.activeBackground)
|
||||||
|
onclick()
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style lang="scss" scoped>
|
||||||
.side_Style {
|
.side_Style {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
@@ -30,6 +116,15 @@ onBeforeMount(() => {
|
|||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gva-menu-item {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-menu-item.is-active {
|
||||||
|
color: v-bind(activeBackground);
|
||||||
|
background: v-bind(activeBackground);
|
||||||
|
}
|
||||||
|
|
||||||
/* .el-menu-item {
|
/* .el-menu-item {
|
||||||
background-color: #01dfd7;
|
background-color: #01dfd7;
|
||||||
} */
|
} */
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
import { tenantStore } from '../../store/tenant'
|
import { tenantStore } from '../../store/modules/tenant'
|
||||||
import router from '../../router'
|
import router from '../../router'
|
||||||
import baiduCloudImage from "../../assets/baiducloud.png"
|
import baiduCloudImage from "../../assets/baiducloud.png"
|
||||||
import { config, scan } from '../../const/config'
|
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
|
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 ruleFormRef = ref<FormInstance>()
|
||||||
const loginForm = reactive({
|
const loginForm = reactive({
|
||||||
@@ -66,19 +66,19 @@ const dologin = (form: any) => {
|
|||||||
|
|
||||||
if (!form)
|
if (!form)
|
||||||
return
|
return
|
||||||
form.validate((valid: any) => {
|
// form.validate((valid: any) => {
|
||||||
if (valid) {
|
// if (valid) {
|
||||||
tenant.login(loginForm.user_id, loginForm.password).then(res => {
|
// useTenantStore.login(loginForm.user_id, loginForm.password).then(res => {
|
||||||
console.log(1)
|
// console.log(1)
|
||||||
router.push({
|
// router.push({
|
||||||
path: '/home'
|
// path: '/home'
|
||||||
})
|
// })
|
||||||
})
|
// })
|
||||||
|
|
||||||
} else {
|
// } else {
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
const style = reactive({} as any)
|
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 router from '../router'
|
||||||
import { setToken, setTenant } from '../utils/auth'
|
import { setToken, setTenant } from '../utils/auth'
|
||||||
|
|
||||||
@@ -41,7 +43,27 @@ const scan_method: any = {
|
|||||||
production: (qrcode: string) => {
|
production: (qrcode: string) => {
|
||||||
window.location.href = qrcode
|
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")
|
setToken("token")
|
||||||
setTenant(
|
setTenant(
|
||||||
{
|
{
|
||||||
|
|||||||
+24
-2
@@ -1,6 +1,28 @@
|
|||||||
type Tenant = {
|
type Tenant = {
|
||||||
id: string,
|
tenant_id: string,
|
||||||
account: 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 App from './App.vue'
|
||||||
import ElementPlus from "element-plus";
|
import ElementPlus from "element-plus";
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
|
import { store } from './store'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { createPinia } from 'pinia'
|
import '@/permission'
|
||||||
const store = createPinia()
|
|
||||||
|
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
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 contentmenu from 'v-contextmenu'
|
||||||
import 'v-contextmenu/dist/themes/default.css'
|
import 'v-contextmenu/dist/themes/default.css'
|
||||||
app.use(contentmenu)
|
|
||||||
|
|
||||||
import { setupMock } from '../mock'
|
import { setupMock } from '../mock'
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
if (process.env.NODE_ENV === 'development') {
|
||||||
setupMock()
|
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(router)
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus)
|
||||||
app.use(store)
|
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')
|
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'
|
import { createRouter, createMemoryHistory, RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
@@ -14,103 +15,103 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/blog',
|
path: '/blog',
|
||||||
component: () => import('../view/blog/index.vue'),
|
component: resolve => (require('@/view/blog/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '博客'
|
name: '博客'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/bookmark',
|
path: '/bookmark',
|
||||||
component: () => import('../view/bookmark/index.vue'),
|
component: resolve => (require('@/view/bookmark/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '书签'
|
name: '书签'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/school',
|
path: '/onenote',
|
||||||
component: () => import('../view/school/index.vue'),
|
component: resolve => (require('@/view/onenote/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '学习'
|
name: 'onenote'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/thinking',
|
path: '/calendar',
|
||||||
component: () => import('../view/thinking/index.vue'),
|
component: resolve => (require('@/view/calendar/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '感悟人生'
|
name: '日历'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/cloud',
|
path: '/cloud',
|
||||||
component: () => import('../view/cloud/index.vue'),
|
component: resolve => (require('@/view/cloud/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '个人云盘'
|
name: '个人云盘'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/market',
|
path: '/market',
|
||||||
component: () => import('../view/recommend/index.vue'),
|
component: resolve => (require('@/view/recommend/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '市场行情'
|
name: '市场行情'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/capital',
|
path: '/capital',
|
||||||
component: () => import('../view/capital/index.vue'),
|
component: resolve => (require('@/view/capital/index.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '资金管理'
|
name: '资金管理'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// path: '/trader',
|
|
||||||
// component: () => import('../view/trader/index.vue'),
|
|
||||||
// meta: {
|
|
||||||
// name: 'trader'
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
path: '/strategy',
|
path: '/strategy',
|
||||||
component: () => import('../view/trader/cta_strategy_file.vue'),
|
component: resolve => (require('@/view/trader/cta_strategy_file.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: '策略模板'
|
name: '策略模板'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/strategy_instance',
|
path: '/strategy_instance',
|
||||||
component: () => import('../view/trader/cta_strategy.vue'),
|
component: resolve => (require('@/view/trader/cta_strategy.vue'), resolve),
|
||||||
meta: {
|
meta: {
|
||||||
name: 'CTA策略'
|
name: 'CTA策略'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/settings',
|
||||||
|
component: resolve => (require('@/view/settings/index.vue'), resolve),
|
||||||
|
meta: {
|
||||||
|
name: '设置'
|
||||||
|
}
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/feedback",
|
path: "/feedback",
|
||||||
component: () => import('../view/blog/mdview.vue')
|
component: resolve => (require('@/view/blog/mdview.vue'), resolve),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/BlogEditer",
|
path: "/BlogEditer",
|
||||||
component: () => import('../view/blog/createBlog.vue')
|
component: resolve => (require('@/view/blog/createBlog.vue'), resolve),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/BlogViewer",
|
path: "/BlogViewer",
|
||||||
component: () => import('../view/blog/mdview.vue')
|
component: resolve => (require('@/view/blog/mdview.vue'), resolve),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
component: () => import('../components/login/login.vue')
|
component: () => import('@/components/login/login.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/illustration",
|
path: "/illustration",
|
||||||
component: () => import('../components/illustration/index.vue')
|
component: resolve => (require('../components/illustration/login.vue'), resolve)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/register",
|
path: "/register",
|
||||||
component: () => import('../components/login/register.vue')
|
component: resolve => (require('../components/login/register.vue'), resolve)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/sorryPage",
|
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 { createPinia } from "pinia"
|
||||||
import { authorize } from '../api/user'
|
|
||||||
import { getToken, setToken, resetToken, setTenant, getTenant } from '../utils/auth'
|
|
||||||
import { Tenant } from '../entity/index'
|
|
||||||
|
|
||||||
|
const store = createPinia()
|
||||||
|
|
||||||
interface Record {
|
export { store }
|
||||||
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))
|
|
||||||
}
|
|
||||||
@@ -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) + "%"
|
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>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 { delete_bookmark_type, post_bookmark_type, get_bookmark_type } from '../../api/bookmark_type'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
const formLabelWidth = '140px'
|
const formLabelWidth = '140px'
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue'
|
||||||
import { put_bookmark_type } from '../../api/bookmark_type'
|
import { put_bookmark_type } from '../../api/bookmark_type'
|
||||||
|
|
||||||
const bookmark_type_name = ref<String>('')
|
const bookmark_type_name = ref<String>('')
|
||||||
|
|||||||
@@ -3,12 +3,8 @@
|
|||||||
<el-form :model="dialog_form">
|
<el-form :model="dialog_form">
|
||||||
<el-form-item label="分类" :label-width="formLabelWidth">
|
<el-form-item label="分类" :label-width="formLabelWidth">
|
||||||
<el-select v-model="dialog_form.bk_type_id" placeholder>
|
<el-select v-model="dialog_form.bk_type_id" placeholder>
|
||||||
<el-option
|
<el-option v-for="(item) in types" :key="item.bk_type_id" :value="item.bk_type_id"
|
||||||
v-for="(item) in types"
|
:label="item.bk_type_name" />
|
||||||
:key="item.bk_type_id"
|
|
||||||
:value="item.bk_type_id"
|
|
||||||
:label="item.bk_type_name"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-form-item label="备注" :label-width="formLabelWidth">
|
<el-form-item label="备注" :label-width="formLabelWidth">
|
||||||
<el-input v-model="dialog_form.comment" autocomplete="off" />
|
<el-input v-model="dialog_form.comment" autocomplete="off" />
|
||||||
@@ -28,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue'
|
||||||
import { update_bookmark, put_bookmark } from '../../api/bookmark'
|
import { update_bookmark, put_bookmark } from '../../api/bookmark'
|
||||||
import type { FormInstance } from 'element-plus'
|
import type { FormInstance } from 'element-plus'
|
||||||
const formLabelWidth = '140px'
|
const formLabelWidth = '140px'
|
||||||
@@ -69,15 +65,19 @@ const submit = () => {
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>.el-button--text {
|
<style scoped>
|
||||||
|
.el-button--text {
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-select {
|
.el-select {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input {
|
.el-input {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-footer button:first-child {
|
.dialog-footer button:first-child {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -14,12 +14,12 @@
|
|||||||
<div class="tag_list">
|
<div class="tag_list">
|
||||||
<el-tag class="ml-2 click-icon" :type="item.clicked ? 'danger' : 'info'" v-for="(item) in bookmark_types"
|
<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>
|
@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="handleAddType" v-show="useTenantStore.tenant.account">增加</el-button>
|
||||||
<el-button type="primary" @click="handleManageType" v-show="Tenant.account">自定义</el-button>
|
<el-button type="primary" @click="handleManageType" v-show="useTenantStore.tenant.account">自定义</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="create_dialog">
|
<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>
|
</div>
|
||||||
|
|
||||||
<el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%">
|
<el-table ref="multipleTableRef" :data="tableData" @selection-change="handleSelectionChange" style="width: 100%">
|
||||||
@@ -39,9 +39,10 @@
|
|||||||
<CopyDocument />
|
<CopyDocument />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<el-button class="click-icon" size="small" @click="handleEdit(scope.$index, scope.row)"
|
<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>
|
||||||
<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>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -72,34 +73,33 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref, h } from 'vue'
|
||||||
import { search_bookmark, delete_bookmark } from '../../api/bookmark'
|
import type { ElTable } from 'element-plus'
|
||||||
import { get_bookmark_type } from '../../api/bookmark_type'
|
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 bookmark_dialog from './dialog.vue'
|
||||||
import bookmarkType_dialog from './Typedialog.vue'
|
import bookmarkType_dialog from './Typedialog.vue'
|
||||||
import createType_dialog from './createTypedialog.vue'
|
import createType_dialog from './createTypedialog.vue'
|
||||||
import delete_dialog from '../../components/operate/deleteDialog.vue'
|
import delete_dialog from '../../components/operate/deleteDialog.vue'
|
||||||
import type { ElTable } from 'element-plus'
|
import { tenantStore } from '../../store/modules/tenant'
|
||||||
import { CopyDocument } from "@element-plus/icons-vue";
|
import { search_bookmark, delete_bookmark } from '../../api/bookmark'
|
||||||
import { ElNotification } from 'element-plus'
|
import { get_bookmark_type } from '../../api/bookmark_type'
|
||||||
import copy from 'copy-to-clipboard';
|
|
||||||
import { h } from 'vue'
|
|
||||||
import { tenantStore } from '../../store/tenant'
|
|
||||||
// obtain user infomation
|
// obtain user infomation
|
||||||
const Tenant = tenantStore()
|
const useTenantStore = tenantStore()
|
||||||
|
|
||||||
// 定义书签格式
|
// 定义书签格式
|
||||||
type Bookmark = {
|
type Bookmark = {
|
||||||
bk_id: string,
|
bk_id: string,
|
||||||
bk_type_id: number,
|
bk_type_id: number,
|
||||||
bk_type_name: String,
|
bk_type_name: string,
|
||||||
comment: String,
|
comment: string,
|
||||||
url: String
|
url: string
|
||||||
}
|
}
|
||||||
// 定义 表单格式
|
// 定义 表单格式
|
||||||
type Searchform = {
|
type Searchform = {
|
||||||
bk_type_ids: number[],
|
bk_type_ids: number[],
|
||||||
comment: String
|
comment: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 操作code
|
// 操作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-collapse-item title="手动下单" name="2">
|
||||||
|
|
||||||
<el-select v-model="vt_symbol" placeholder="select a vt_symbol" @change="select_contract">
|
<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>
|
</el-select>
|
||||||
<div style="height: 10px;"></div>
|
<div style="height: 10px;"></div>
|
||||||
<el-row>
|
<el-row>
|
||||||
@@ -134,14 +134,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import { ElMessage, TabsPaneContext } from 'element-plus'
|
import { ElMessage, TabsPaneContext } from 'element-plus'
|
||||||
import { reactive, ref, h, onMounted, onUnmounted } from 'vue'
|
import { reactive, ref, h, onMounted, onUnmounted } from 'vue'
|
||||||
import { get_accounts, send_order, get_tick } from '../../api/capital'
|
import { get_accounts, send_order, get_tick } from '../../api/capital'
|
||||||
import { strategyStore } from '../../store/strategy'
|
import { strategyStore } from '../../store/modules/strategy'
|
||||||
|
|
||||||
// -- IMPORT --
|
// -- IMPORT --
|
||||||
const store = strategyStore()
|
const useStrategyStore = strategyStore()
|
||||||
|
|
||||||
// -- INTERFACE OR TYPE DEFINITION --
|
// -- INTERFACE OR TYPE DEFINITION --
|
||||||
interface AccountData {
|
interface AccountData {
|
||||||
@@ -272,7 +271,7 @@ const on_order = () => {
|
|||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
|
|
||||||
store.select_subscribe_vt_symbols()
|
useStrategyStore.select_subscribe_vt_symbols()
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
clearInterval(timer.value)
|
clearInterval(timer.value)
|
||||||
timer.value = window.setInterval(on_query_accounts(), 3000);
|
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>
|
<template>
|
||||||
<div class="about" ref="bookmarks" id="bookmarks" :style="{
|
<div class="page">
|
||||||
width: '600px',
|
<div class="gva-card-box">
|
||||||
height: '400px'
|
<div class="gva-card gva-top-card">
|
||||||
}"></div>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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>
|
</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>
|
</style>
|
||||||
@@ -5,14 +5,14 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<el-select v-model="exchange" placeholder="select a exchange">
|
<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-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1">
|
<el-col :span="1">
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4">
|
<el-col :span="4">
|
||||||
<el-select v-model="vt_symbol" placeholder="select a vt_symbol">
|
<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-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="1">
|
<el-col :span="1">
|
||||||
@@ -56,15 +56,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, h, onMounted, onUnmounted, reactive, getCurrentInstance } from 'vue'
|
import { ref, h, onMounted, onUnmounted, reactive, getCurrentInstance } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { get_ticks, subscribe, concel_subscribe } from '../../api/capital'
|
import * as echarts from 'echarts'
|
||||||
import { strategyStore } from '../../store/strategy'
|
|
||||||
import { Contextmenu, ContextmenuItem } from "v-contextmenu"
|
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 { toPercent } from '../../utils/number'
|
||||||
|
|
||||||
import * as echarts from 'echarts'
|
|
||||||
// -- IMPORT --
|
// -- IMPORT --
|
||||||
const currentInstance = getCurrentInstance()
|
const currentInstance = getCurrentInstance()
|
||||||
const store = strategyStore()
|
const useStrategyStore = strategyStore()
|
||||||
|
|
||||||
// -- INTERFACE OR TYPE DEFINITION --
|
// -- INTERFACE OR TYPE DEFINITION --
|
||||||
interface TickData {
|
interface TickData {
|
||||||
@@ -104,7 +105,7 @@ const on_subscribe = () => {
|
|||||||
h('i', { style: 'color: green' }, "行情订阅成功"),
|
h('i', { style: 'color: green' }, "行情订阅成功"),
|
||||||
]),
|
]),
|
||||||
})
|
})
|
||||||
store.select_subscribe_vt_symbols()
|
useStrategyStore.select_subscribe_vt_symbols()
|
||||||
on_ticks()
|
on_ticks()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
@@ -189,7 +190,7 @@ const on_ticks = () => {
|
|||||||
window.clearInterval(timer.value)
|
window.clearInterval(timer.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
store.select_subscribe_vt_symbols()
|
useStrategyStore.select_subscribe_vt_symbols()
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: h('p', null, [
|
message: h('p', null, [
|
||||||
@@ -198,7 +199,7 @@ const on_ticks = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
store.select_vt_symbols()
|
useStrategyStore.select_vt_symbols()
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: h('p', null, [
|
message: h('p', null, [
|
||||||
@@ -207,7 +208,7 @@ const on_ticks = () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
store.select_exchanges()
|
useStrategyStore.select_exchanges()
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: h('p', null, [
|
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>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 create_strategy_dialog from './dialog.vue'
|
||||||
|
import { strategyStore } from '../../store/modules/strategy'
|
||||||
import {
|
import {
|
||||||
get_strategies,
|
get_strategies,
|
||||||
init_strategy,
|
init_strategy,
|
||||||
@@ -72,9 +74,6 @@ import {
|
|||||||
get_strategy_status,
|
get_strategy_status,
|
||||||
get_strategy_load_files,
|
get_strategy_load_files,
|
||||||
} from '../../api/cta_strategy'
|
} from '../../api/cta_strategy'
|
||||||
import { h } from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { strategyStore } from '../../store/strategy'
|
|
||||||
|
|
||||||
type Strategy = {
|
type Strategy = {
|
||||||
strategy_name: string,
|
strategy_name: string,
|
||||||
@@ -84,7 +83,7 @@ type Strategy = {
|
|||||||
status: number,
|
status: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = strategyStore()
|
const useStrategyStore = strategyStore()
|
||||||
let createStrategyDialogVisible = ref(false)
|
let createStrategyDialogVisible = ref(false)
|
||||||
const strategy_list = reactive<Strategy[]>([])
|
const strategy_list = reactive<Strategy[]>([])
|
||||||
const dialogRef = ref()
|
const dialogRef = ref()
|
||||||
@@ -133,7 +132,7 @@ const on_status = (row: any) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
on_list()
|
on_list()
|
||||||
get_strategy_load_files().then(res => {
|
get_strategy_load_files().then(res => {
|
||||||
store.$patch({ class_names: res.data.class_names })
|
useStrategyStore.strategy.class_names = res.data.class_names
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
ElMessage({
|
ElMessage({
|
||||||
message: h('p', null, [
|
message: h('p', null, [
|
||||||
|
|||||||
@@ -66,17 +66,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 {
|
import {
|
||||||
get_strategy_files,
|
get_strategy_files,
|
||||||
load_strategy_file,
|
load_strategy_file,
|
||||||
unload_strategy_file,
|
unload_strategy_file,
|
||||||
remove_strategy_file
|
remove_strategy_file
|
||||||
} from '../../api/cta_strategy'
|
} 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 OR TYPE DEFINITION --
|
||||||
interface StrategyFile {
|
interface StrategyFile {
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="vt_symbol" prop="vt_symbol">
|
<el-form-item label="vt_symbol" prop="vt_symbol">
|
||||||
<el-select v-model="ruleForm.vt_symbol" placeholder="select a 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-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="class_name" prop="class_name">
|
<el-form-item label="class_name" prop="class_name">
|
||||||
<el-select v-model="ruleForm.class_name" placeholder="select a 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-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="setting:">
|
<el-form-item label="setting:">
|
||||||
@@ -47,9 +47,9 @@ import type { FormInstance, FormRules } from 'element-plus'
|
|||||||
import { create_strategy } from '../../api/cta_strategy'
|
import { create_strategy } from '../../api/cta_strategy'
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
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 formSize = ref('default')
|
||||||
const ruleFormRef = ref<FormInstance>()
|
const ruleFormRef = ref<FormInstance>()
|
||||||
|
|||||||
@@ -6,10 +6,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue';
|
import { onMounted, ref, reactive } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { EChartsOption } from 'echarts';
|
import { EChartsOption } from 'echarts'
|
||||||
import { onMounted, ref } from 'vue'
|
|
||||||
import { generateOHLC, option } from '../../service/trader'
|
import { generateOHLC, option } from '../../service/trader'
|
||||||
import { get_stock_data } from '../../api/trader'
|
import { get_stock_data } from '../../api/trader'
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
|||||||
+21
-2
@@ -1,7 +1,8 @@
|
|||||||
import { defineConfig, loadEnv } from 'vite'
|
import { defineConfig, loadEnv } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
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 { viteMockServe } from 'vite-plugin-mock'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
|
||||||
// https://vitejs.cn/guide/env-and-mode.html#env-files
|
// https://vitejs.cn/guide/env-and-mode.html#env-files
|
||||||
export default defineConfig(({ mode }) => {
|
export default defineConfig(({ mode }) => {
|
||||||
@@ -16,6 +17,24 @@ export default defineConfig(({ mode }) => {
|
|||||||
localEnabled: true,
|
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