38 changed files with 0 additions and 4277 deletions
@ -1,2 +0,0 @@ |
|||||
VITE_PROXY=[["/api", "http://localhost:36789"]] |
|
||||
VITE_ADMIN_VERSION="v0.0.0-dev" |
|
||||
@ -1,68 +0,0 @@ |
|||||
module.exports = { |
|
||||
parser: "vue-eslint-parser", |
|
||||
"env": { |
|
||||
"browser": true, |
|
||||
"es2021": true |
|
||||
}, |
|
||||
"extends": [ |
|
||||
"plugin:@typescript-eslint/recommended", |
|
||||
"plugin:vue/vue3-recommended" |
|
||||
], |
|
||||
"parserOptions": { |
|
||||
"parser": "@typescript-eslint/parser", |
|
||||
"sourceType": "module", |
|
||||
ecmaFeature: { |
|
||||
jsx: true, |
|
||||
tsx: true |
|
||||
} |
|
||||
}, |
|
||||
"plugins": [ |
|
||||
"@typescript-eslint" |
|
||||
], |
|
||||
"rules": { |
|
||||
'vue/max-attributes-per-line': ['error', { |
|
||||
singleline: 10, |
|
||||
multiline: { |
|
||||
max: 1, |
|
||||
allowFirstLine: false |
|
||||
} |
|
||||
}], |
|
||||
'vue/singleline-html-element-content-newline': 'off', |
|
||||
'vue/multiline-html-element-content-newline': 'off', |
|
||||
'vue/html-indent': ['error', 4], |
|
||||
indent: ['error', 4], // 4行缩进
|
|
||||
'vue/script-indent': ['error', 4], |
|
||||
quotes: ['error', 'single'], // 单引号
|
|
||||
// 'vue/html-quotes': ['error', 'single'],
|
|
||||
semi: ['error', 'never'], // 禁止使用分号
|
|
||||
'space-infix-ops': ['error', { int32Hint: false }], // 要求操作符周围有空格
|
|
||||
'no-multi-spaces': 'error', // 禁止多个空格
|
|
||||
'no-whitespace-before-property': 'error', // 禁止在属性前使用空格
|
|
||||
'space-before-blocks': 'error', // 在块之前强制保持一致的间距
|
|
||||
'space-before-function-paren': ['error', 'never'], // 在“ function”定义打开括号之前强制不加空格
|
|
||||
'space-in-parens': ['error', 'never'], // 强制括号左右的不加空格
|
|
||||
'spaced-comment': ['error', 'always'], // 注释间隔
|
|
||||
'template-tag-spacing': ['error', 'always'], // 在模板标签及其文字之间需要空格
|
|
||||
'no-var': 'error', |
|
||||
'prefer-destructuring': ['error', { // 优先使用数组和对象解构
|
|
||||
array: true, |
|
||||
object: true |
|
||||
}, { |
|
||||
enforceForRenamedProperties: false |
|
||||
}], |
|
||||
'comma-dangle': ['error', 'never'], // 最后一个属性不允许有逗号
|
|
||||
'arrow-spacing': 'error', // 箭头函数空格
|
|
||||
'prefer-template': 'error', |
|
||||
'template-curly-spacing': 'error', |
|
||||
'quote-props': ['error', 'as-needed'], // 对象字面量属性名称使用引号
|
|
||||
'object-curly-spacing': ['error', 'always'], // 强制在花括号中使用一致的空格
|
|
||||
'no-unneeded-ternary': 'error', // 禁止可以表达为更简单结构的三元操作符
|
|
||||
'no-restricted-syntax': ['error', 'WithStatement', 'BinaryExpression[operator="in"]'], // 禁止with/in语句
|
|
||||
'no-lonely-if': 'error', // 禁止 if 语句作为唯一语句出现在 else 语句块中
|
|
||||
'newline-per-chained-call': ['error', { ignoreChainWithDepth: 2 }], // 要求方法链中每个调用都有一个换行符
|
|
||||
// 路径别名设置
|
|
||||
'no-submodule-imports': ['off', '/@'], |
|
||||
'no-implicit-dependencies': ['off', ['/@']], |
|
||||
'@typescript-eslint/no-explicit-any': 'off' // 类型可以使用any
|
|
||||
} |
|
||||
} |
|
||||
@ -1,24 +0,0 @@ |
|||||
# Logs |
|
||||
logs |
|
||||
*.log |
|
||||
npm-debug.log* |
|
||||
yarn-debug.log* |
|
||||
yarn-error.log* |
|
||||
pnpm-debug.log* |
|
||||
lerna-debug.log* |
|
||||
|
|
||||
node_modules |
|
||||
dist |
|
||||
dist-ssr |
|
||||
*.local |
|
||||
|
|
||||
# Editor directories and files |
|
||||
.vscode/* |
|
||||
!.vscode/extensions.json |
|
||||
.idea |
|
||||
.DS_Store |
|
||||
*.suo |
|
||||
*.ntvs* |
|
||||
*.njsproj |
|
||||
*.sln |
|
||||
*.sw? |
|
||||
@ -1 +0,0 @@ |
|||||
# DTM-Admin |
|
||||
@ -1,13 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="en"> |
|
||||
<head> |
|
||||
<meta charset="UTF-8" /> |
|
||||
<link rel="icon" href="/favicon.ico" /> |
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|
||||
<title>Vite App</title> |
|
||||
</head> |
|
||||
<body> |
|
||||
<div id="app"></div> |
|
||||
<script type="module" src="/src/main.ts"></script> |
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,39 +0,0 @@ |
|||||
{ |
|
||||
"name": "dtm-admin", |
|
||||
"private": true, |
|
||||
"version": "0.0.0", |
|
||||
"scripts": { |
|
||||
"dev": "vite", |
|
||||
"build": "vite build", |
|
||||
"preview": "vite preview" |
|
||||
}, |
|
||||
"dependencies": { |
|
||||
"ant-design-vue": "^3.1.1", |
|
||||
"vue": "^3.2.25", |
|
||||
"vue-request": "^1.2.4" |
|
||||
}, |
|
||||
"devDependencies": { |
|
||||
"@types/node": "^17.0.23", |
|
||||
"@types/nprogress": "^0.2.0", |
|
||||
"@typescript-eslint/eslint-plugin": "^5.18.0", |
|
||||
"@typescript-eslint/parser": "^5.18.0", |
|
||||
"@vitejs/plugin-vue": "^2.3.0", |
|
||||
"autoprefixer": "^10.4.4", |
|
||||
"axios": "^0.26.1", |
|
||||
"eslint": "^8.13.0", |
|
||||
"eslint-plugin-vue": "^8.6.0", |
|
||||
"nprogress": "^0.2.0", |
|
||||
"pinia": "^2.0.0-rc.10", |
|
||||
"postcss": "^8.4.12", |
|
||||
"postcss-import": "^14.1.0", |
|
||||
"postcss-nested": "^5.0.6", |
|
||||
"postcss-simple-vars": "^6.0.3", |
|
||||
"tailwindcss": "^3.0.24", |
|
||||
"typescript": "^4.5.4", |
|
||||
"unplugin-vue-components": "^0.19.3", |
|
||||
"vite": "^2.9.1", |
|
||||
"vite-plugin-svg-icons": "^1.1.0", |
|
||||
"vue-router": "^4.0.13", |
|
||||
"vue-tsc": "^0.29.8" |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +0,0 @@ |
|||||
module.exports = { |
|
||||
plugins: { |
|
||||
tailwindcss: {}, |
|
||||
autoprefixer: {}, |
|
||||
}, |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@ -1,6 +0,0 @@ |
|||||
<template> |
|
||||
<router-view /> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"></script> |
|
||||
|
|
||||
@ -1,22 +0,0 @@ |
|||||
import { AxiosResponse } from 'axios' |
|
||||
import request from '/@/utils/request' |
|
||||
|
|
||||
export interface IListAllTransactionsReq { |
|
||||
limit: number |
|
||||
position?: number |
|
||||
} |
|
||||
|
|
||||
export function listAllTransactions<T>(payload: IListAllTransactionsReq): Promise<AxiosResponse<T>> { |
|
||||
return request({ |
|
||||
url: '/api/dtmsvr/all', |
|
||||
method: 'get', |
|
||||
params: payload |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
export function getDtmVersion(): Promise<AxiosResponse<any>> { |
|
||||
return request({ |
|
||||
url: '/api/dtmsvr/version', |
|
||||
method: 'get', |
|
||||
}) |
|
||||
} |
|
||||
@ -1,3 +0,0 @@ |
|||||
/* @tailwind base; */ |
|
||||
@tailwind components; |
|
||||
@tailwind utilities; |
|
||||
@ -1,14 +0,0 @@ |
|||||
// generated by unplugin-vue-components
|
|
||||
// We suggest you to commit this file into source control
|
|
||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
|
||||
import '@vue/runtime-core' |
|
||||
|
|
||||
declare module '@vue/runtime-core' { |
|
||||
export interface GlobalComponents { |
|
||||
RouterLink: typeof import('vue-router')['RouterLink'] |
|
||||
RouterView: typeof import('vue-router')['RouterView'] |
|
||||
SvgIcon: typeof import('./components/SvgIcon/index.vue')['default'] |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export {} |
|
||||
@ -1,42 +0,0 @@ |
|||||
<template> |
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" /> |
|
||||
<svg v-else :class="svgClass" aria-hidden="true"> |
|
||||
<use :xlink:href="iconName" /> |
|
||||
</svg> |
|
||||
</template> |
|
||||
<script setup lang='ts'> |
|
||||
|
|
||||
const props = defineProps({ |
|
||||
iconClass: { |
|
||||
type: String, |
|
||||
required: true |
|
||||
}, |
|
||||
className: { |
|
||||
type: String, |
|
||||
default: '' |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const isExternal = /^(https?:|mailto:|tel:)/.test(props.iconClass) |
|
||||
const iconName = `#icon-${props.iconClass}` |
|
||||
const svgClass = props.className ? `svg-icon ${props.className}` : 'svg-icon ' |
|
||||
const styleExternalIcon = () => { |
|
||||
return { |
|
||||
mask: `url(${props.iconClass}) no-repeat 50% 50%`, |
|
||||
'-webkit-mask': `url(${props.iconClass}) no-repeat 50% 50%` |
|
||||
} |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="postcss" scoped> |
|
||||
.svg-icon { |
|
||||
vertical-align: -0.15em; |
|
||||
fill: currentColor; |
|
||||
overflow: hidden; |
|
||||
} |
|
||||
.svg-external-icon { |
|
||||
background-color: currentColor; |
|
||||
mask-size: cover !important; |
|
||||
display: inline-block; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1 +0,0 @@ |
|||||
# ICon Component |
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@ -1,78 +0,0 @@ |
|||||
<template> |
|
||||
<a-layout> |
|
||||
<a-layout-sider width="200" style="background: #fff"> |
|
||||
<Sidebar /> |
|
||||
</a-layout-sider> |
|
||||
<a-layout style="padding: 0 24px 24px"> |
|
||||
<div v-if="layout.dtmVersion && layout.dtmVersion != dashVer" style="color:#f00"> !!! admin version: {{dashVer}} != dtm version: {{layout.dtmVersion}}. </div> |
|
||||
<a-breadcrumb style="margin: 16px 0"> |
|
||||
<a-breadcrumb-item>{{ mainNav }}</a-breadcrumb-item> |
|
||||
<a-breadcrumb-item>{{ subNav }}</a-breadcrumb-item> |
|
||||
<a-breadcrumb-item>{{ page }}</a-breadcrumb-item> |
|
||||
</a-breadcrumb> |
|
||||
<a-layout-content |
|
||||
:style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }" |
|
||||
> |
|
||||
<Content /> |
|
||||
</a-layout-content> |
|
||||
</a-layout> |
|
||||
</a-layout> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang='ts'> |
|
||||
import Sidebar from './components/sidebar.vue' |
|
||||
import Content from './components/content.vue' |
|
||||
import { useRoute } from 'vue-router' |
|
||||
import { useLayoutStore } from '../store/modules/layout' |
|
||||
import { IMenubarList } from '../type/store/layout' |
|
||||
import { findCurrentMenubar } from '../utils/util' |
|
||||
import { computed, onMounted, ref } from 'vue' |
|
||||
import { getDtmVersion } from '../api/api_dtm' |
|
||||
|
|
||||
|
|
||||
const dashVer = import.meta.env.VITE_ADMIN_VERSION |
|
||||
const route = useRoute() |
|
||||
const layout = useLayoutStore() |
|
||||
|
|
||||
const mainNav = computed(() => { |
|
||||
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true) |
|
||||
return currentMenubar?.meta.title |
|
||||
}) |
|
||||
|
|
||||
const subNav = computed(() => { |
|
||||
let subNav = '' |
|
||||
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true) |
|
||||
currentMenubar.children?.forEach(v => { |
|
||||
if (route.path.indexOf(v.path) !== -1) { |
|
||||
subNav = v.meta.title |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
return subNav |
|
||||
}) |
|
||||
|
|
||||
const page = computed(() => { |
|
||||
let page = '' |
|
||||
const currentMenubar = findCurrentMenubar(layout.getMenubar.menuList, true) |
|
||||
currentMenubar.children?.forEach(v => { |
|
||||
v.children?.forEach(vv => { |
|
||||
if (route.path == vv.path) { |
|
||||
page = vv.meta.title |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
|
|
||||
return page |
|
||||
}) |
|
||||
|
|
||||
onMounted(() => { |
|
||||
layout.loadDtmVersion() |
|
||||
}) |
|
||||
|
|
||||
</script> |
|
||||
|
|
||||
<style lang="postcss" scoped> |
|
||||
.ant-layout.ant-layout-has-sider { |
|
||||
min-height: calc(100vh - 64px); |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,17 +0,0 @@ |
|||||
<template> |
|
||||
<router-view v-slot="{Component}"> |
|
||||
<transition name="fade-transform" mode="out-in"> |
|
||||
<keep-alive> |
|
||||
<component :is="Component" :key="key" /> |
|
||||
</keep-alive> |
|
||||
</transition> |
|
||||
</router-view> |
|
||||
</template> |
|
||||
<script setup lang='ts'> |
|
||||
import { computed } from 'vue' |
|
||||
import { useRoute } from 'vue-router' |
|
||||
|
|
||||
const route = useRoute() |
|
||||
|
|
||||
const key = computed(() => route.path) |
|
||||
</script> |
|
||||
@ -1,42 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<a-layout-header class="header flex"> |
|
||||
<div class="flex items-center logo h-16"> |
|
||||
<svg-icon style="width: 36px; height: 36px; margin-right: 84px;" icon-class="svg-logo" /> |
|
||||
<span class="text-gray-400 text-lg">DTM admin {{ version }}</span> |
|
||||
</div> |
|
||||
<a-menu |
|
||||
v-model:selectedKeys="activeMenu" |
|
||||
theme="dark" |
|
||||
mode="horizontal" |
|
||||
:style="{ lineHeight: '64px' }" |
|
||||
@select="onOpenChange" |
|
||||
> |
|
||||
<a-menu-item v-for="v in getMenubar.menuList" :key="v.path">{{ v.meta.title }}</a-menu-item> |
|
||||
</a-menu> |
|
||||
</a-layout-header> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script setup lang='ts'> |
|
||||
import { computed, ref } from 'vue'; |
|
||||
import { useRoute, useRouter } from 'vue-router'; |
|
||||
import { useLayoutStore } from '/@/store/modules/layout' |
|
||||
|
|
||||
const route = useRoute() |
|
||||
const router = useRouter() |
|
||||
const { getMenubar, getCurrentVersion } = useLayoutStore() |
|
||||
const firstRedirectPath = '/admin' |
|
||||
const version = import.meta.env.VITE_ADMIN_VERSION |
|
||||
|
|
||||
const activeMenu = ref([route.meta.activeMenu !== firstRedirectPath ? route.meta.activeMenu : '/']) |
|
||||
|
|
||||
const onOpenChange = (d:any) => { |
|
||||
router.push({ path: d.key }) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style scoped> |
|
||||
.logo { |
|
||||
margin-right: 20px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,57 +0,0 @@ |
|||||
<template> |
|
||||
<a-menu |
|
||||
v-model:selectedKeys="activeMenu" |
|
||||
v-model:openKeys="openKeys" |
|
||||
mode="inline" |
|
||||
:style="{ height: '100%', borderRight: 0 }" |
|
||||
@select="onOpenChange" |
|
||||
> |
|
||||
<a-sub-menu v-for="v in filterSubMenubarData" :key="v.path"> |
|
||||
<template #title> |
|
||||
<span> |
|
||||
{{ v.meta.title }} |
|
||||
</span> |
|
||||
</template> |
|
||||
<a-menu-item v-for="vv in v.children" :key="vv.path">{{ vv.meta.title }}</a-menu-item> |
|
||||
</a-sub-menu> |
|
||||
</a-menu> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang='ts'> |
|
||||
import { ref, computed } from 'vue' |
|
||||
import { useRoute, useRouter } from 'vue-router' |
|
||||
import { useLayoutStore } from '/@/store/modules/layout' |
|
||||
import { IMenubarList } from '/@/type/store/layout' |
|
||||
import { findCurrentMenubar } from '/@/utils/util' |
|
||||
|
|
||||
const route = useRoute() |
|
||||
const router = useRouter() |
|
||||
const { getMenubar } = useLayoutStore() |
|
||||
|
|
||||
const filterSubMenubarData = computed(() => { |
|
||||
return findCurrentMenubar(getMenubar.menuList) as IMenubarList[] |
|
||||
}) |
|
||||
|
|
||||
const activeMenu = computed({ |
|
||||
get: () => { |
|
||||
return [route.path] |
|
||||
}, |
|
||||
set: (val) => { |
|
||||
// do nothing, just for eliminate warn |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const openKeys = computed({ |
|
||||
get: () => { |
|
||||
const pos = route.path.lastIndexOf('/') |
|
||||
return [route.path.substring(0, pos)] |
|
||||
}, |
|
||||
set: (val) => { |
|
||||
// do onthing, just for eliminate warn |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const onOpenChange = (d:any) => { |
|
||||
router.push({ path: d.key }) |
|
||||
} |
|
||||
</script> |
|
||||
@ -1,12 +0,0 @@ |
|||||
<script setup lang="ts"> |
|
||||
import Header from './components/header.vue' |
|
||||
</script> |
|
||||
|
|
||||
<template> |
|
||||
<a-layout> |
|
||||
<a-layout-header class="header"> |
|
||||
<Header /> |
|
||||
</a-layout-header> |
|
||||
<router-view /> |
|
||||
</a-layout> |
|
||||
</template> |
|
||||
@ -1,13 +0,0 @@ |
|||||
import { createApp } from 'vue' |
|
||||
import App from './App.vue' |
|
||||
import router from '/@/router/index' |
|
||||
import { pinia } from '/@/store' |
|
||||
import '/@/permission' |
|
||||
|
|
||||
import '/@/assets/css/index.css' |
|
||||
import 'virtual:svg-icons-register' |
|
||||
|
|
||||
const app = createApp(App) |
|
||||
app.use(router) |
|
||||
app.use(pinia) |
|
||||
app.mount('#app') |
|
||||
@ -1,23 +0,0 @@ |
|||||
import router from '/@/router' |
|
||||
import { configure, start, done } from 'nprogress' |
|
||||
import { useLayoutStore } from './store/modules/layout' |
|
||||
|
|
||||
configure({ showSpinner: false }) |
|
||||
|
|
||||
const defaultRoutePath = '/' |
|
||||
|
|
||||
router.beforeEach((to) => { |
|
||||
start() |
|
||||
|
|
||||
const { getMenubar, concatAllowRoutes } = useLayoutStore() |
|
||||
|
|
||||
if (getMenubar.menuList.length === 0) { |
|
||||
concatAllowRoutes() |
|
||||
|
|
||||
return to.fullPath |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
router.afterEach(() => { |
|
||||
done() |
|
||||
}) |
|
||||
@ -1,18 +0,0 @@ |
|||||
const modules = import.meta.glob('../views/**/**.vue') |
|
||||
const components: IObject<() => Promise<typeof import('*.vue')>> = { |
|
||||
LayoutHeader: (() => import('/@/layout/index.vue')) as unknown as () => Promise<typeof import('*.vue')> |
|
||||
} |
|
||||
|
|
||||
Object.keys(modules).forEach(key => { |
|
||||
const nameMatch = key.match(/^\.\.\/views\/(.+)\.vue/) |
|
||||
if (!nameMatch) return |
|
||||
if (nameMatch[1].includes('_Components')) return |
|
||||
const indexMatch = nameMatch[1].match(/(.*)\/Index$/i) |
|
||||
let name = indexMatch ? indexMatch[1] : nameMatch[1]; |
|
||||
[name] = name.split('/').splice(-1) |
|
||||
components[name] = modules[key] as () => Promise<typeof import('*.vue')> |
|
||||
}) |
|
||||
|
|
||||
export { |
|
||||
components |
|
||||
} |
|
||||
@ -1,59 +0,0 @@ |
|||||
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' |
|
||||
import { IMenubarList } from '../type/store/layout'; |
|
||||
import { components } from './asyncRouter'; |
|
||||
|
|
||||
const Components: IObject<() => Promise<typeof import('*.vue')>> = Object.assign({}, components, { |
|
||||
LayoutHeader: (() => import('/@/layout/index.vue')) as unknown as () => Promise<typeof import('*.vue')>, |
|
||||
LayoutMain: (() => import('/@/layout/aside.vue')) as unknown as () => Promise<typeof import('*.vue')> |
|
||||
}) |
|
||||
|
|
||||
export const allowRouter: Array<IMenubarList> = [ |
|
||||
{ |
|
||||
name: 'Admin', |
|
||||
path: '/', |
|
||||
redirect: '/admin/global-transactions/all', |
|
||||
component: Components['LayoutHeader'], |
|
||||
meta: { title: 'Admin', activeMenu: '/admin' }, |
|
||||
children: [ |
|
||||
{ |
|
||||
name: 'Nodes', |
|
||||
path: '/admin/nodes', |
|
||||
component: Components['LayoutMain'], |
|
||||
meta: { title: 'Nodes' }, |
|
||||
children: [ |
|
||||
{ |
|
||||
name: 'LivingNodes', |
|
||||
path: '/admin/nodes/living', |
|
||||
component: Components['LivingNodes'], |
|
||||
meta: { title: 'Living Nodes' }, |
|
||||
} |
|
||||
] |
|
||||
}, { |
|
||||
name: 'GlobalTransactions', |
|
||||
path: '/admin/global-transactions', |
|
||||
component: Components['LayoutMain'], |
|
||||
meta: { title: 'Global Transactions' }, |
|
||||
children: [ |
|
||||
{ |
|
||||
name: 'AllTransactions', |
|
||||
path: '/admin/global-transactions/all', |
|
||||
component: Components['AllTransactions'], |
|
||||
meta: { title: 'All Transactions' }, |
|
||||
}, { |
|
||||
name: 'UnfinishedTransactions', |
|
||||
path: '/admin/global-transactions/unfinished', |
|
||||
component: Components['UnfinishedTransactions'], |
|
||||
meta: { title: 'Unfinished Transactions' }, |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
const router = createRouter({ |
|
||||
history: createWebHistory(), |
|
||||
routes: allowRouter as RouteRecordRaw[] |
|
||||
}) |
|
||||
|
|
||||
export default router |
|
||||
@ -1,2 +0,0 @@ |
|||||
import { createPinia } from 'pinia' |
|
||||
export const pinia = createPinia() |
|
||||
@ -1,38 +0,0 @@ |
|||||
import { defineStore } from 'pinia'; |
|
||||
import { allowRouter } from '/@/router'; |
|
||||
import { ILayout, IMenubar, IMenubarList, IStatus } from '/@/type/store/layout'; |
|
||||
import { getDtmVersion } from '/@/api/api_dtm'; |
|
||||
|
|
||||
export const useLayoutStore = defineStore({ |
|
||||
id: 'layout', |
|
||||
state: (): ILayout => ({ |
|
||||
menubar: { |
|
||||
menuList: [] |
|
||||
}, |
|
||||
status: { |
|
||||
isLoading: false |
|
||||
}, |
|
||||
dtmVersion: "", |
|
||||
}), |
|
||||
getters: { |
|
||||
getMenubar(): IMenubar { |
|
||||
return this.menubar |
|
||||
}, |
|
||||
getStatus(): IStatus { |
|
||||
return this.status |
|
||||
}, |
|
||||
}, |
|
||||
actions: { |
|
||||
setRoutes(data: Array<IMenubarList>): void { |
|
||||
this.menubar.menuList = data |
|
||||
}, |
|
||||
concatAllowRoutes(): void { |
|
||||
allowRouter.reverse().forEach(v => this.menubar.menuList.unshift(v)) |
|
||||
}, |
|
||||
async loadDtmVersion(): Promise<void> { |
|
||||
const { data: { version } } = await getDtmVersion() |
|
||||
this.dtmVersion = version |
|
||||
console.log("dtm version: ", this.dtmVersion) |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
@ -1,17 +0,0 @@ |
|||||
export { } |
|
||||
declare global { |
|
||||
interface IObject<T> { |
|
||||
[index: string]: T |
|
||||
} |
|
||||
interface ImportMetaEnv { |
|
||||
VITE_APP_TITLE: string |
|
||||
VITE_PORT: number |
|
||||
VITE_PROXY: string |
|
||||
VITE_ADMIN_VERSION: string |
|
||||
} |
|
||||
interface ITable<T = any> { |
|
||||
data: Array<T> |
|
||||
next_position: number, |
|
||||
size: number |
|
||||
} |
|
||||
} |
|
||||
@ -1,5 +0,0 @@ |
|||||
declare module '*.vue' { |
|
||||
import { defineComponent } from 'vue'; |
|
||||
const Component: ReturnType<typeof defineComponent> |
|
||||
export default Component |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
export interface IMenubar { |
|
||||
menuList: Array<IMenubarList> |
|
||||
} |
|
||||
|
|
||||
export interface ILayout { |
|
||||
menubar: IMenubar |
|
||||
status: IStatus |
|
||||
dtmVersion: string |
|
||||
} |
|
||||
|
|
||||
export interface IStatus { |
|
||||
isLoading: boolean |
|
||||
} |
|
||||
|
|
||||
export interface IMenubarList { |
|
||||
parentId?: number | string |
|
||||
id?: number | string |
|
||||
name: string |
|
||||
path: string |
|
||||
redirect?: string |
|
||||
meta: { |
|
||||
icon?: string |
|
||||
title: string |
|
||||
permission?: string[] |
|
||||
activeMenu?: string |
|
||||
hidden?: boolean |
|
||||
alwaysShow?: boolean |
|
||||
} |
|
||||
component: (() => Promise<typeof import('*.vue')>) | string |
|
||||
children?: Array<IMenubarList> |
|
||||
} |
|
||||
@ -1,8 +0,0 @@ |
|||||
import axios from 'axios' |
|
||||
|
|
||||
const request = axios.create({ |
|
||||
baseURL: import.meta.env.VITE_APP_API_BASE_URL as string | undefined, |
|
||||
timeout: 60000 |
|
||||
}) |
|
||||
|
|
||||
export default request |
|
||||
@ -1,23 +0,0 @@ |
|||||
import { useRoute } from 'vue-router'; |
|
||||
import { IMenubarList } from '../type/store/layout'; |
|
||||
|
|
||||
export const findCurrentMenubar = (menuList: IMenubarList[], root?:boolean) => { |
|
||||
const route = useRoute() |
|
||||
let arr:IMenubarList[] | IMenubarList = [] |
|
||||
for (let i = 0; i < menuList.length; i++) { |
|
||||
const v = menuList[i]; |
|
||||
const usePath = v.meta.activeMenu || v.redirect || v.path; |
|
||||
const pos = usePath.lastIndexOf('/') |
|
||||
const rootPath = pos == 0 ? usePath : usePath.substring(0, pos) |
|
||||
if (route.path.indexOf(rootPath) !== -1) { |
|
||||
if (!root) { |
|
||||
arr = v.children as IMenubarList[] |
|
||||
} else { |
|
||||
arr = v |
|
||||
} |
|
||||
break |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return arr |
|
||||
} |
|
||||
@ -1,133 +0,0 @@ |
|||||
<template> |
|
||||
<div> |
|
||||
<a-table :columns="columns" :data-source="dataSource" :loading="loading" :pagination="false"> |
|
||||
<template #bodyCell="{column, record}"> |
|
||||
<template v-if="column.key === 'status'"> |
|
||||
<span> |
|
||||
<a-tag :key="record.status" :color="record.status === 'succeed' ? 'green' : 'volcano'">{{ record.status.toUpperCase() }}</a-tag> |
|
||||
</span> |
|
||||
</template> |
|
||||
<template v-else-if="column.key === 'action'"> |
|
||||
<span> |
|
||||
<a class="mr-2 font-medium">Detail</a> |
|
||||
<a class="text-red-400 font-medium">Stop</a> |
|
||||
</span> |
|
||||
</template> |
|
||||
</template> |
|
||||
</a-table> |
|
||||
<div class="flex justify-center mt-2 text-lg pager" v-if="canPrev || canNext"> |
|
||||
<a-button type="text" :disabled="!canPrev" @click="handlePrevPage">Previous</a-button> |
|
||||
<a-button type="text" :disabled="!canNext" @click="handleNextPage">Next</a-button> |
|
||||
</div> |
|
||||
</div> |
|
||||
</template> |
|
||||
<script setup lang="ts"> |
|
||||
import { IListAllTransactions, listAllTransactions } from '/@/api/api_dtm' |
|
||||
import { ref, onMounted, reactive, computed } from 'vue-demi' |
|
||||
import { usePagination } from 'vue-request' |
|
||||
import { TableProps } from 'ant-design-vue/es/vc-table/Table' |
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: 'GID', |
|
||||
dataIndex: 'gid', |
|
||||
key: 'gid' |
|
||||
}, { |
|
||||
title: 'TransType', |
|
||||
dataIndex: 'trans_type', |
|
||||
key: 'trans_type' |
|
||||
}, { |
|
||||
title: 'Status', |
|
||||
dataIndex: 'status', |
|
||||
key: 'status' |
|
||||
}, { |
|
||||
title: 'Protocol', |
|
||||
dataIndex: 'protocol', |
|
||||
key: 'protocol' |
|
||||
}, { |
|
||||
title: 'CreateTime', |
|
||||
dataIndex: 'create_time', |
|
||||
key: 'create_time' |
|
||||
}, { |
|
||||
title: 'Action', |
|
||||
key: 'action' |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
const pager = ref([""]) |
|
||||
const currentState = ref(1) |
|
||||
|
|
||||
const canPrev = computed(() => { |
|
||||
if (currentState.value === 1) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
return true; |
|
||||
}) |
|
||||
|
|
||||
const canNext = computed(() => { |
|
||||
return data.value?.data.next_position !== "" |
|
||||
}) |
|
||||
|
|
||||
type Data = { |
|
||||
transactions: { |
|
||||
gid: string |
|
||||
trans_type: string |
|
||||
status: string |
|
||||
protocol: string |
|
||||
create_time: string |
|
||||
}[] |
|
||||
next_position: string |
|
||||
} |
|
||||
|
|
||||
const queryData = (params: IListAllTransactions) => { |
|
||||
return listAllTransactions<Data>(params) |
|
||||
} |
|
||||
|
|
||||
const { data, run, current, loading, pageSize } = usePagination(queryData, { |
|
||||
defaultParams: [ |
|
||||
{ |
|
||||
limit: 100, |
|
||||
} |
|
||||
], |
|
||||
pagination: { |
|
||||
pageSizeKey: 'limit' |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
const dataSource = computed(() => data.value?.data.transactions || []) |
|
||||
|
|
||||
const handlePrevPage = () => { |
|
||||
currentState.value -= 1; |
|
||||
const params = { |
|
||||
limit: 100 |
|
||||
} |
|
||||
if (pager.value[currentState.value - 1]) { |
|
||||
params.position = pager.value[currentState.value - 1] |
|
||||
} |
|
||||
run(params) |
|
||||
} |
|
||||
|
|
||||
const handleNextPage = () => { |
|
||||
currentState.value += 1; |
|
||||
if (currentState.value >= 2) { |
|
||||
pager.value[currentState.value - 1] = data.value?.data.next_position |
|
||||
} |
|
||||
|
|
||||
run({ |
|
||||
position: data.value?.data.next_position, |
|
||||
limit: 5 |
|
||||
}) |
|
||||
} |
|
||||
</script> |
|
||||
|
|
||||
<style lang="postcss" scoped> |
|
||||
::v-deep .ant-pagination-item { |
|
||||
display: none; |
|
||||
} |
|
||||
.pager .ant-btn-text { |
|
||||
font-weight: 500; |
|
||||
}1 |
|
||||
.pager .ant-btn { |
|
||||
padding: 6px; |
|
||||
} |
|
||||
</style> |
|
||||
@ -1,5 +0,0 @@ |
|||||
<template> |
|
||||
<h1>Coming Soon</h1> |
|
||||
</template> |
|
||||
<script setup lang="ts"> |
|
||||
</script> |
|
||||
@ -1,6 +0,0 @@ |
|||||
<template> |
|
||||
<h1>Coming Soon</h1> |
|
||||
</template> |
|
||||
|
|
||||
<script setup lang="ts"> |
|
||||
</script> |
|
||||
@ -1,7 +0,0 @@ |
|||||
module.exports = { |
|
||||
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], |
|
||||
theme: { |
|
||||
extend: {}, |
|
||||
}, |
|
||||
plugins: [], |
|
||||
} |
|
||||
@ -1,21 +0,0 @@ |
|||||
{ |
|
||||
"compilerOptions": { |
|
||||
"target": "esnext", |
|
||||
"useDefineForClassFields": true, |
|
||||
"module": "esnext", |
|
||||
"moduleResolution": "node", |
|
||||
"strict": true, |
|
||||
"jsx": "preserve", |
|
||||
"sourceMap": true, |
|
||||
"resolveJsonModule": true, |
|
||||
"esModuleInterop": true, |
|
||||
"baseUrl": ".", |
|
||||
"paths": { |
|
||||
"/@/*": ["src/*"], |
|
||||
}, |
|
||||
"lib": ["esnext", "dom"], |
|
||||
"types": ["vite/client", "node"] |
|
||||
}, |
|
||||
"include": ["**/*.ts", "**/*.d.ts", "**/*.tsx", "**/*.vue"], |
|
||||
"exclude": ["node_modules"] |
|
||||
} |
|
||||
@ -1,50 +0,0 @@ |
|||||
import { ConfigEnv, UserConfigExport } from 'vite'; |
|
||||
import path from 'path'; |
|
||||
import vue from '@vitejs/plugin-vue'; |
|
||||
import viteSvgIcons from 'vite-plugin-svg-icons'; |
|
||||
import Components from 'unplugin-vue-components/vite'; |
|
||||
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers' |
|
||||
|
|
||||
const setAlias = (alias: [string, string][]) => alias.map((v) => { |
|
||||
return { find: v[0], replacement: path.resolve(__dirname, v[1]) }; |
|
||||
}); |
|
||||
|
|
||||
export default ({ }: ConfigEnv): UserConfigExport => { |
|
||||
return { |
|
||||
resolve: { |
|
||||
alias: setAlias([['/@', 'src']]), |
|
||||
}, |
|
||||
plugins: [ |
|
||||
vue(), |
|
||||
viteSvgIcons({ |
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/icons')], |
|
||||
symbolId: 'icon-[dir]-[name]' |
|
||||
}), |
|
||||
Components({ |
|
||||
dts: 'src/components.d.ts', |
|
||||
resolvers: [ |
|
||||
AntDesignVueResolver() |
|
||||
] |
|
||||
}) |
|
||||
], |
|
||||
server: { |
|
||||
port: 5000, |
|
||||
base: 'admin', |
|
||||
proxy: { |
|
||||
'/api': { |
|
||||
target: 'http://localhost:36789', |
|
||||
}, |
|
||||
} |
|
||||
}, |
|
||||
css: { |
|
||||
postcss: { |
|
||||
plugins: [ |
|
||||
require('autoprefixer'), |
|
||||
require('tailwindcss'), |
|
||||
require('postcss-simple-vars'), |
|
||||
require('postcss-import') |
|
||||
] |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
}; |
|
||||
File diff suppressed because it is too large
Loading…
Reference in new issue