mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-02 02:24:29 +00:00
feat 表格相关hooks调试, 新增查询器组件
This commit is contained in:
@@ -31,14 +31,14 @@ module.exports = {
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
0,
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
0,
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
|
82
src/components/Bootx/Query/BQuery.vue
Normal file
82
src/components/Bootx/Query/BQuery.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<a-form class="query" layout="inline">
|
||||
<a-row :gutter="gutter">
|
||||
<query-item
|
||||
:key="i"
|
||||
v-show="i < defaultItemCount || toggleSearchStatus"
|
||||
v-for="(field, i) in fields"
|
||||
:field="field"
|
||||
:md="defaultItemMd"
|
||||
:query-params="queryParams"
|
||||
/>
|
||||
<a-col :md="defaultItemMd" :sm="24">
|
||||
<a-space>
|
||||
<a-button type="primary" :disabled="disabledQuery" @click="query">查询</a-button>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</a-space>
|
||||
<a v-show="fields.length > defaultItemCount" @click="handleToggleSearch" style="margin-left: 8px">
|
||||
{{ toggleSearchStatus ? '收起' : '展开' }}
|
||||
<up-outlined v-if="toggleSearchStatus" />
|
||||
<down-outlined v-else />
|
||||
</a>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import QueryItem from './QueryItem.vue'
|
||||
import { ref } from 'vue'
|
||||
import { DownOutlined, UpOutlined } from '@ant-design/icons-vue'
|
||||
// 切换搜索条件展开状态
|
||||
let toggleSearchStatus = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
fields: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
},
|
||||
// 查询条件
|
||||
queryParams: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
// 默认展示几个
|
||||
defaultItemCount: { type: Number, default: 2 },
|
||||
|
||||
defaultItemMd: { type: Number, default: 6 },
|
||||
// 禁用查询
|
||||
disabledQuery: { type: Boolean, default: false },
|
||||
gutter: { type: Number, default: 10 },
|
||||
})
|
||||
const emits = defineEmits(['update:modelValue', 'query', 'reset'])
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function query() {
|
||||
emits('query')
|
||||
}
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function reset() {
|
||||
emits('reset')
|
||||
}
|
||||
/**
|
||||
* 切换搜索条件展开状态
|
||||
*/
|
||||
function handleToggleSearch() {
|
||||
toggleSearchStatus.value = !toggleSearchStatus.value
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
/deep/ .ant-form-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ant-row {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
89
src/components/Bootx/Query/QueryItem.vue
Normal file
89
src/components/Bootx/Query/QueryItem.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<a-col :md="field.md || md" :sm="24">
|
||||
<a-form-item :label="field.name">
|
||||
<!-- 文本输入 -->
|
||||
<a-input
|
||||
allowClear
|
||||
v-if="field.type === STRING"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
<!-- 数字输入 -->
|
||||
<a-input-number
|
||||
allowClear
|
||||
style="width: 100%"
|
||||
v-else-if="field.type === NUMBER"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
|
||||
:precision="field.precision ? field.precision : 0"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
<!-- 布尔 -->
|
||||
<a-radio-group v-else-if="field.type === BOOLEAN" v-model:value="queryParams[field.field]">
|
||||
<a-radio :value="true">是</a-radio>
|
||||
<a-radio :value="false">否</a-radio>
|
||||
</a-radio-group>
|
||||
<!-- 列表 -->
|
||||
<a-select
|
||||
allowClear
|
||||
v-else-if="field.type === LIST"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请选择查询值'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
:options="field.list"
|
||||
/>
|
||||
<!-- 日期 -->
|
||||
<a-date-picker
|
||||
allowClear
|
||||
v-else-if="field.type === DATE"
|
||||
style="width: 100%"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请选择日期'"
|
||||
:valueFormat="queryParams.format ? queryParams.format : 'yyyy-MM-DD'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
<!-- 时间 -->
|
||||
<a-time-picker
|
||||
allowClear
|
||||
v-else-if="field.type === TIME"
|
||||
style="width: 100%"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请选择时间'"
|
||||
:valueFormat="queryParams.format ? queryParams.format : 'HH:mm:ss'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
<!-- 日期时间 -->
|
||||
<a-date-picker
|
||||
allowClear
|
||||
showTime
|
||||
v-else-if="field.type === DATE_TIME"
|
||||
style="width: 100%"
|
||||
:placeholder="field.placeholder ? field.placeholder : '请选择日期时间'"
|
||||
:valueFormat="queryParams.format ? queryParams.format : 'yyyy-MM-DD HH:mm:ss'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
<!-- 默认文本输入 -->
|
||||
<a-input
|
||||
allowClear
|
||||
v-else
|
||||
:placeholder="field.placeholder ? field.placeholder : '请输入查询值'"
|
||||
v-model:value="queryParams[field.field]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { BOOLEAN, DATE, DATE_TIME, LIST, NUMBER, QueryField, STRING, TIME } from './SuperQueryCode'
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 查询字段属性
|
||||
field: QueryField
|
||||
// 查询条件
|
||||
queryParams: object
|
||||
// md 栅格占位
|
||||
md: number
|
||||
}>(),
|
||||
{
|
||||
md: 6,
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
20
src/components/Bootx/Query/SuperQueryCode.ts
Normal file
20
src/components/Bootx/Query/SuperQueryCode.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// 数字
|
||||
export const NUMBER = 'number'
|
||||
// 字符串
|
||||
export const STRING = 'string'
|
||||
// 布尔
|
||||
export const BOOLEAN = 'boolean'
|
||||
// 日期
|
||||
export const DATE = 'date'
|
||||
// 时间
|
||||
export const TIME = 'time'
|
||||
// 日期时间
|
||||
export const DATE_TIME = 'date_time'
|
||||
// 列表
|
||||
export const LIST = 'list'
|
||||
|
||||
export interface QueryField {
|
||||
type: string
|
||||
placeholder: string
|
||||
field: string
|
||||
}
|
@@ -9,10 +9,34 @@ import 'vxe-table/lib/style.css'
|
||||
*/
|
||||
export function useTable(app: App) {
|
||||
app.use(VXETable)
|
||||
|
||||
// 给 vue 实例挂载内部对象,例如:
|
||||
// app.config.globalProperties.$XModal = VXETable.modal
|
||||
// app.config.globalProperties.$XPrint = VXETable.print
|
||||
// app.config.globalProperties.$XSaveFile = VXETable.saveFile
|
||||
// app.config.globalProperties.$XReadFile = VXETable.readFile
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置
|
||||
*/
|
||||
VXETable.setup({
|
||||
// 表格配置
|
||||
table: {
|
||||
resizable: true,
|
||||
border: true,
|
||||
stripe: true,
|
||||
showOverflow: true,
|
||||
showHeaderOverflow: true,
|
||||
size: 'medium',
|
||||
tooltipConfig: {
|
||||
enterable: true,
|
||||
},
|
||||
},
|
||||
// 工具条配置
|
||||
toolbar: {
|
||||
size: null,
|
||||
custom: true,
|
||||
buttons: [],
|
||||
tools: [],
|
||||
},
|
||||
// 分页配置
|
||||
pager: {
|
||||
border: true,
|
||||
size: 'medium',
|
||||
},
|
||||
})
|
||||
|
@@ -1,7 +1,58 @@
|
||||
import type { App } from 'vue'
|
||||
import { Button } from './Button'
|
||||
import { Input, Layout } from 'ant-design-vue'
|
||||
import {
|
||||
Layout,
|
||||
Input,
|
||||
InputNumber,
|
||||
Empty,
|
||||
Select,
|
||||
Tree,
|
||||
TreeSelect,
|
||||
Card,
|
||||
Form,
|
||||
Row,
|
||||
Col,
|
||||
Modal,
|
||||
Dropdown,
|
||||
Radio,
|
||||
Steps,
|
||||
Spin,
|
||||
Menu,
|
||||
Drawer,
|
||||
Tooltip,
|
||||
Tag,
|
||||
Divider,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Descriptions,
|
||||
Space,
|
||||
} from 'ant-design-vue'
|
||||
|
||||
export function registerGlobComp(app: App) {
|
||||
app.use(Input).use(Button).use(Layout)
|
||||
app.use(Input)
|
||||
app.use(Button)
|
||||
app.use(Layout)
|
||||
app.use(InputNumber)
|
||||
app.use(Tag)
|
||||
app.use(Space)
|
||||
app.use(Modal)
|
||||
app.use(Drawer)
|
||||
app.use(Row)
|
||||
app.use(Col)
|
||||
app.use(Radio)
|
||||
app.use(Divider)
|
||||
app.use(DatePicker)
|
||||
app.use(TimePicker)
|
||||
app.use(Empty)
|
||||
app.use(Select)
|
||||
app.use(Tree)
|
||||
app.use(TreeSelect)
|
||||
app.use(Card)
|
||||
app.use(Menu)
|
||||
app.use(Tooltip)
|
||||
app.use(Descriptions)
|
||||
app.use(Steps)
|
||||
app.use(Form)
|
||||
app.use(Spin)
|
||||
app.use(Dropdown)
|
||||
}
|
||||
|
@@ -1,8 +1,80 @@
|
||||
import { PageParams } from '/#/web'
|
||||
import { TablePageModel } from '/#/web'
|
||||
import { reactive, toRefs } from 'vue'
|
||||
import { PageResult } from '/#/axios'
|
||||
|
||||
/**
|
||||
* 重置当前页数
|
||||
* 获取数据对象
|
||||
*/
|
||||
export function resetPage(pages: PageParams) {
|
||||
pages.current = 1
|
||||
export default function (queryPageCallback: CallableFunction) {
|
||||
// 数据内容
|
||||
const model = reactive({
|
||||
pages: {
|
||||
size: 10,
|
||||
current: 1,
|
||||
},
|
||||
queryParam: {},
|
||||
loading: false,
|
||||
batchOperateFlag: false,
|
||||
superQueryFlag: false,
|
||||
pagination: {},
|
||||
} as TablePageModel)
|
||||
|
||||
// 拆分
|
||||
const { loading, batchOperateFlag, superQueryFlag } = toRefs(model)
|
||||
// 不可以被重新赋值, 否则会失去绑定
|
||||
const { pages, pagination } = model
|
||||
// 普通查询
|
||||
function query() {
|
||||
model.superQueryFlag = false
|
||||
resetPage()
|
||||
queryPageCallback()
|
||||
}
|
||||
// 表格翻页或变动
|
||||
function handleTableChange({ currentPage, pageSize }) {
|
||||
pages.current = currentPage
|
||||
pages.size = pageSize
|
||||
queryPageCallback()
|
||||
}
|
||||
// 重置当前页数
|
||||
function resetPage() {
|
||||
pages.current = 1
|
||||
}
|
||||
// 分页查询返回结果处理
|
||||
function pageQueryResHandel(res: PageResult) {
|
||||
pagination.current = Number(res.current)
|
||||
pagination.size = Number(res.size)
|
||||
pagination.total = Number(res.total)
|
||||
pagination.records = res.records
|
||||
model.loading = false
|
||||
}
|
||||
// 重置查询
|
||||
function resetQuery() {
|
||||
resetQueryParams()
|
||||
queryPageCallback()
|
||||
}
|
||||
// 重置查询参数
|
||||
function resetQueryParams() {
|
||||
model.superQueryFlag = false
|
||||
model.queryParam = {}
|
||||
}
|
||||
// ok按钮
|
||||
function handleOk() {
|
||||
queryPageCallback()
|
||||
}
|
||||
|
||||
return {
|
||||
model,
|
||||
loading,
|
||||
pages,
|
||||
pagination,
|
||||
batchOperateFlag,
|
||||
superQueryFlag,
|
||||
query,
|
||||
resetPage,
|
||||
pageQueryResHandel,
|
||||
handleTableChange,
|
||||
resetQuery,
|
||||
resetQueryParams,
|
||||
handleOk,
|
||||
}
|
||||
}
|
||||
|
19
src/views/modules/system/client/ClientEdit.vue
Normal file
19
src/views/modules/system/client/ClientEdit.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<a-modal :visible="visible"> 123 </a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
const visible = ref(false)
|
||||
const i = ref(3)
|
||||
|
||||
const emits = defineEmits(['ok'])
|
||||
function edit() {
|
||||
console.log(123)
|
||||
}
|
||||
defineExpose({
|
||||
visible,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@@ -1,103 +1,85 @@
|
||||
<template>
|
||||
<div class="m-5 p-3 bg-white">
|
||||
<div class="table-page-search-wrapper">
|
||||
<a-form layout="inline">
|
||||
<a-row :gutter="10">
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="编码">
|
||||
<a-input v-model="queryParam.code" placeholder="请输入编码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-form-item label="名称">
|
||||
<a-input v-model="queryParam.name" placeholder="请输入名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :md="6" :sm="24">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="query">查询</a-button>
|
||||
<a-button @click="resetQuery">重置</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<div>
|
||||
<div class="m-3 p-3 pt-5 bg-white">
|
||||
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
|
||||
</div>
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<a-button type="primary" icon="plus" @click="add">新建</a-button>
|
||||
<a-button @click="getPage">查询</a-button>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table row-id="id" :data="pagination.records" :loading="loading">
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="code" title="编码" />
|
||||
<vxe-column field="name" title="名称" />
|
||||
<vxe-column field="captcha" title="系统内置">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.system" color="green">是</a-tag>
|
||||
<a-tag v-else color="red">否</a-tag>
|
||||
<div class="m-3 p-3 bg-white">
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="add">新建</a-button>
|
||||
<a-button @click="queryPage">查询</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="enable" title="启用状态">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.enable" color="green">启用</a-tag>
|
||||
<a-tag v-else color="red">停用</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="description" title="描述" />
|
||||
<vxe-column field="createTime" title="创建时间" />
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
</vxe-toolbar>
|
||||
<vxe-table row-id="id" :data="pagination.records" :loading="loading">
|
||||
<vxe-column type="seq" width="60" />
|
||||
<vxe-column field="code" title="编码" />
|
||||
<vxe-column field="name" title="名称" />
|
||||
<vxe-column field="captcha" title="系统内置">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.system" color="green">是</a-tag>
|
||||
<a-tag v-else color="red">否</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="enable" title="启用状态">
|
||||
<template #default="{ row }">
|
||||
<a-tag v-if="row.enable" color="green">启用</a-tag>
|
||||
<a-tag v-else color="red">停用</a-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column field="description" title="描述" />
|
||||
<vxe-column field="createTime" title="创建时间" />
|
||||
</vxe-table>
|
||||
<vxe-pager
|
||||
size="medium"
|
||||
:loading="loading"
|
||||
:current-page="pagination.current"
|
||||
:page-size="pagination.size"
|
||||
:total="pagination.total"
|
||||
@page-change="handleTableChange"
|
||||
/>
|
||||
<client-edit ref="clientEdit" @ok="queryPage" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, toRefs } from 'vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { page } from '/@/views/modules/system/client/Client.api'
|
||||
import { PageResult } from '/#/axios'
|
||||
// 初始化
|
||||
function init() {
|
||||
getPage()
|
||||
}
|
||||
import useTable from '/@/hooks/bootx/useTable'
|
||||
import ClientEdit from './ClientEdit.vue'
|
||||
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
|
||||
import { STRING } from '/@/components/Bootx/Query/SuperQueryCode'
|
||||
|
||||
// 使用hooks
|
||||
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTable(queryPage)
|
||||
const clientEdit = ref()
|
||||
|
||||
// 查询条件
|
||||
const fields = [
|
||||
{ field: 'code', type: STRING, name: '编码', placeholder: '请输入数据源编码' },
|
||||
{ field: 'name', type: STRING, name: '名称', placeholder: '请输入数据源名称' },
|
||||
]
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
queryPage()
|
||||
})
|
||||
|
||||
const pageParam = reactive({
|
||||
size: 10,
|
||||
current: 1,
|
||||
})
|
||||
const queryParam = reactive({})
|
||||
const model = reactive({
|
||||
loading: false,
|
||||
pagination: { size: 10, current: 1, total: 0, records: [] } as PageResult,
|
||||
})
|
||||
const { loading, pagination } = toRefs(model)
|
||||
// 分页
|
||||
function getPage() {
|
||||
// 分页查询
|
||||
function queryPage() {
|
||||
model.loading = true
|
||||
page({
|
||||
...queryParam,
|
||||
...pageParam,
|
||||
...model.queryParam,
|
||||
...pages,
|
||||
}).then(({ data }) => {
|
||||
model.pagination = data
|
||||
model.loading = false
|
||||
pageQueryResHandel(data)
|
||||
})
|
||||
}
|
||||
// 页面变动
|
||||
function handleTableChange({ currentPage, pageSize }) {
|
||||
pageParam.current = currentPage
|
||||
pageParam.size = pageSize
|
||||
init()
|
||||
// 新增
|
||||
function add() {
|
||||
clientEdit.value.visible = true
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style lang="less" scoped></style>
|
||||
|
@@ -1,15 +0,0 @@
|
||||
# Test Server
|
||||
|
||||
It is used to start the test interface service, which can test the upload, websocket, login and other interfaces.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
|
||||
cd ./test/server
|
||||
|
||||
pnpm install
|
||||
|
||||
pnpm run start
|
||||
|
||||
```
|
@@ -1,18 +0,0 @@
|
||||
import FileService from '../service/FileService'
|
||||
|
||||
class FileController {
|
||||
private service: FileService = new FileService()
|
||||
|
||||
upload = async (ctx) => {
|
||||
const files = ctx.request.files.file
|
||||
console.log(files)
|
||||
|
||||
if (files.length === undefined) {
|
||||
this.service.upload(ctx, files, false)
|
||||
} else {
|
||||
this.service.upload(ctx, files, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new FileController()
|
@@ -1,15 +0,0 @@
|
||||
import UserService from '../service/UserService'
|
||||
|
||||
class UserController {
|
||||
private service: UserService = new UserService()
|
||||
|
||||
login = async (ctx) => {
|
||||
ctx.body = await this.service.login()
|
||||
}
|
||||
|
||||
getUserInfoById = async (ctx) => {
|
||||
ctx.body = await this.service.getUserInfoById()
|
||||
}
|
||||
}
|
||||
|
||||
export default new UserController()
|
@@ -1,18 +0,0 @@
|
||||
const { name } = require('./package.json')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name,
|
||||
script: path.resolve(__dirname, './dist/index.js'),
|
||||
instances: require('os').cpus().length,
|
||||
autorestart: true,
|
||||
watch: true,
|
||||
env_production: {
|
||||
NODE_ENV: 'production',
|
||||
PORT: 8080,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
import Koa from 'koa'
|
||||
import path from 'path'
|
||||
import Router from 'koa-router'
|
||||
import body from 'koa-body'
|
||||
import cors from 'koa2-cors'
|
||||
import koaStatic from 'koa-static'
|
||||
import websockify from 'koa-websocket'
|
||||
import route from 'koa-route'
|
||||
|
||||
import AppRoutes from './routes'
|
||||
|
||||
const PORT = 3300
|
||||
|
||||
const app = websockify(new Koa())
|
||||
|
||||
app.ws.use(function (ctx, next) {
|
||||
ctx.websocket.send('connection succeeded!')
|
||||
return next(ctx)
|
||||
})
|
||||
|
||||
app.ws.use(
|
||||
route.all('/test', function (ctx) {
|
||||
// ctx.websocket.send('Hello World');
|
||||
ctx.websocket.on('message', function (message) {
|
||||
// do something with the message from client
|
||||
|
||||
if (message !== 'ping') {
|
||||
const data = JSON.stringify({
|
||||
id: Math.ceil(Math.random() * 1000),
|
||||
time: new Date().getTime(),
|
||||
res: `${message}`,
|
||||
})
|
||||
ctx.websocket.send(data)
|
||||
}
|
||||
console.log(message)
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const router = new Router()
|
||||
|
||||
// router
|
||||
AppRoutes.forEach((route) => router[route.method](route.path, route.action))
|
||||
|
||||
app.use(cors())
|
||||
app.use(
|
||||
body({
|
||||
encoding: 'gzip',
|
||||
multipart: true,
|
||||
formidable: {
|
||||
// uploadDir: path.join(__dirname, '/upload/'), // 设置文件上传目录
|
||||
keepExtensions: true,
|
||||
maxFieldsSize: 20 * 1024 * 1024,
|
||||
},
|
||||
}),
|
||||
)
|
||||
app.use(router.routes())
|
||||
app.use(router.allowedMethods())
|
||||
app.use(koaStatic(path.join(__dirname)))
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Application started successfully: http://localhost:${PORT}`)
|
||||
})
|
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"watch": ["src"],
|
||||
"ext": "ts",
|
||||
"exec": "ts-node -r tsconfig-paths/register index.ts",
|
||||
"events": {
|
||||
"restart": "clear"
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "server",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "nodemon",
|
||||
"build": "rimraf ./dist && tsup ./index.ts --dts --format cjs,esm ",
|
||||
"prod": "npx pm2 start ecosystem.config.js --env production",
|
||||
"restart": "pm2 restart ecosystem.config.js --env production",
|
||||
"stop": "npx pm2 stop ecosystem.config.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.0.1",
|
||||
"koa": "^2.13.4",
|
||||
"koa-body": "^4.2.0",
|
||||
"koa-bodyparser": "^4.3.0",
|
||||
"koa-route": "^3.2.0",
|
||||
"koa-router": "^10.1.1",
|
||||
"koa-static": "^5.0.0",
|
||||
"koa-websocket": "^6.0.0",
|
||||
"koa2-cors": "^2.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/koa-bodyparser": "^5.0.2",
|
||||
"@types/koa-router": "^7.4.4",
|
||||
"@types/node": "^17.0.21",
|
||||
"nodemon": "^2.0.15",
|
||||
"pm2": "^5.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.7.0",
|
||||
"tsconfig-paths": "^3.14.0",
|
||||
"tsup": "^5.12.1",
|
||||
"typescript": "^4.6.2"
|
||||
}
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
import UserController from './controller/UserController'
|
||||
import FileController from './controller/FileController'
|
||||
|
||||
export default [
|
||||
// user
|
||||
{
|
||||
path: '/login',
|
||||
method: 'post',
|
||||
action: UserController.login,
|
||||
},
|
||||
{
|
||||
path: '/getUserInfoById',
|
||||
method: 'get',
|
||||
action: UserController.getUserInfoById,
|
||||
},
|
||||
|
||||
// file
|
||||
{
|
||||
path: '/upload',
|
||||
method: 'post',
|
||||
action: FileController.upload,
|
||||
},
|
||||
]
|
@@ -1,54 +0,0 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const uploadUrl = 'http://localhost:3300/static/upload'
|
||||
const filePath = path.join(__dirname, '../static/upload/')
|
||||
|
||||
fs.ensureDir(filePath)
|
||||
export default class UserService {
|
||||
async upload(ctx, files, isMultiple) {
|
||||
let fileReader, fileResource, writeStream
|
||||
|
||||
const fileFunc = function (file) {
|
||||
fileReader = fs.createReadStream(file.path)
|
||||
fileResource = filePath + `/${file.name}`
|
||||
console.log(fileResource)
|
||||
|
||||
writeStream = fs.createWriteStream(fileResource)
|
||||
fileReader.pipe(writeStream)
|
||||
}
|
||||
|
||||
const returnFunc = function (flag) {
|
||||
if (flag) {
|
||||
let url = ''
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
url += uploadUrl + `/${files[i].name},`
|
||||
}
|
||||
url = url.replace(/,$/gi, '')
|
||||
ctx.body = {
|
||||
url: url,
|
||||
code: 0,
|
||||
message: 'upload Success!',
|
||||
}
|
||||
} else {
|
||||
ctx.body = {
|
||||
url: uploadUrl + `/${files.name}`,
|
||||
code: 0,
|
||||
message: 'upload Success!',
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(isMultiple, files.length)
|
||||
|
||||
if (isMultiple) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const f1 = files[i]
|
||||
fileFunc(f1)
|
||||
}
|
||||
} else {
|
||||
fileFunc(files)
|
||||
}
|
||||
fs.ensureDir(filePath)
|
||||
returnFunc(isMultiple)
|
||||
}
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
import { Result } from '../utils'
|
||||
|
||||
const fakeUserInfo = {
|
||||
userId: '1',
|
||||
username: 'vben',
|
||||
realName: 'Vben Admin',
|
||||
desc: 'manager',
|
||||
password: '123456',
|
||||
token: 'fakeToken1',
|
||||
roles: [
|
||||
{
|
||||
roleName: 'Super Admin',
|
||||
value: 'super',
|
||||
},
|
||||
],
|
||||
}
|
||||
export default class UserService {
|
||||
async login() {
|
||||
return Result.success(fakeUserInfo)
|
||||
}
|
||||
|
||||
async getUserInfoById() {
|
||||
return Result.success(fakeUserInfo)
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "es6",
|
||||
"sourceMap": false,
|
||||
"esModuleInterop": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./"
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
export class Result {
|
||||
static success(data: any) {
|
||||
return {
|
||||
code: 0,
|
||||
success: true,
|
||||
result: data,
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,8 @@
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"experimentalDecorators": true,
|
||||
"lib": ["dom", "esnext"],
|
||||
"noImplicitAny": false,
|
||||
|
24
types/web.d.ts
vendored
24
types/web.d.ts
vendored
@@ -1,3 +1,5 @@
|
||||
import { PageResult } from "/#/axios";
|
||||
|
||||
/**
|
||||
* 分页属性
|
||||
*/
|
||||
@@ -10,7 +12,27 @@ export interface Pagination {
|
||||
/**
|
||||
* 分页参数
|
||||
*/
|
||||
export interface PageParams {
|
||||
export interface PageParam {
|
||||
// 每页数量
|
||||
size: number
|
||||
// 当前页数
|
||||
current: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格分页对象
|
||||
*/
|
||||
export interface TablePageModel<T = any> {
|
||||
// 加载状态
|
||||
loading: boolean
|
||||
// 批量操作标识
|
||||
batchOperateFlag: boolean
|
||||
// 高级查询条件生效状态
|
||||
superQueryFlag: boolean
|
||||
// 分页参数
|
||||
pages: PageParam
|
||||
// 查询参数
|
||||
queryParam: object
|
||||
// 结果
|
||||
pagination: PageResult<T>
|
||||
}
|
||||
|
Reference in New Issue
Block a user