Compare commits
11 Commits
57120c002a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| fe89520621 | |||
| de55ddbc48 | |||
| 78e2dbcd65 | |||
| 76ad4c7fa5 | |||
| 878b5f144c | |||
| c73a7b48fa | |||
| e615aefaee | |||
| dd9f966597 | |||
| 7c6c387a07 | |||
| bbf7a2a5d8 | |||
| 6c33113092 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -82,3 +82,4 @@ Icon
|
|||||||
Network Trash Folder
|
Network Trash Folder
|
||||||
Temporary Items
|
Temporary Items
|
||||||
.apdisk
|
.apdisk
|
||||||
|
*.db
|
||||||
|
|||||||
20
.idea/compiler.xml
generated
20
.idea/compiler.xml
generated
@@ -7,8 +7,28 @@
|
|||||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
<outputRelativeToContentRoot value="true" />
|
<outputRelativeToContentRoot value="true" />
|
||||||
|
</profile>
|
||||||
|
<profile name="Annotation profile for spring-boot-server-template" enabled="true">
|
||||||
|
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||||
|
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||||
|
<outputRelativeToContentRoot value="true" />
|
||||||
|
<option name="mapstruct.defaultComponentModel" value="spring" />
|
||||||
|
<option name="mapstruct.defaultInjectionStrategy" value="constructor" />
|
||||||
|
<processorPath useClasspath="false">
|
||||||
|
<entry name="$MAVEN_REPOSITORY$/org/mapstruct/mapstruct-processor/1.6.3/mapstruct-processor-1.6.3.jar" />
|
||||||
|
<entry name="$MAVEN_REPOSITORY$/org/mapstruct/mapstruct/1.6.3/mapstruct-1.6.3.jar" />
|
||||||
|
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/unknown/lombok-unknown.jar" />
|
||||||
|
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok-mapstruct-binding/0.2.0/lombok-mapstruct-binding-0.2.0.jar" />
|
||||||
|
</processorPath>
|
||||||
|
<module name="spring-boot-server-template" />
|
||||||
<module name="spring-boot-apijson-server" />
|
<module name="spring-boot-apijson-server" />
|
||||||
</profile>
|
</profile>
|
||||||
</annotationProcessing>
|
</annotationProcessing>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="JavacSettings">
|
||||||
|
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||||
|
<module name="spring-boot-apijson-server" options="-Amapstruct.defaultComponentModel=spring -Amapstruct.defaultInjectionStrategy=constructor" />
|
||||||
|
<module name="spring-boot-server-template" options="-Amapstruct.defaultComponentModel=spring -Amapstruct.defaultInjectionStrategy=constructor" />
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
12
.idea/dataSources.xml
generated
12
.idea/dataSources.xml
generated
@@ -26,5 +26,17 @@
|
|||||||
</jdbc-additional-properties>
|
</jdbc-additional-properties>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
|
<data-source source="LOCAL" name="database" uuid="894c61bb-b6fb-4153-94dc-97175dd7fd95">
|
||||||
|
<driver-ref>h2.unified</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.h2.Driver</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:h2:$PROJECT_DIR$/database</jdbc-url>
|
||||||
|
<jdbc-additional-properties>
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||||
|
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||||
|
</jdbc-additional-properties>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
15
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
15
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="NullableProblems" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" />
|
||||||
|
<option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" />
|
||||||
|
<option name="REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE" value="true" />
|
||||||
|
<option name="REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL" value="true" />
|
||||||
|
<option name="REPORT_NOT_ANNOTATED_GETTER" value="true" />
|
||||||
|
<option name="REPORT_NOT_ANNOTATED_SETTER_PARAMETER" value="true" />
|
||||||
|
<option name="REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS" value="true" />
|
||||||
|
<option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
10
.idea/jarRepositories.xml
generated
10
.idea/jarRepositories.xml
generated
@@ -11,6 +11,11 @@
|
|||||||
<option name="name" value="jitpack.io" />
|
<option name="name" value="jitpack.io" />
|
||||||
<option name="url" value="https://jitpack.io" />
|
<option name="url" value="https://jitpack.io" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="lanyuanxiaoyao-maven-central" />
|
||||||
|
<option name="name" value="lanyuanxiaoyao-maven-central" />
|
||||||
|
<option name="url" value="https://maven.lanyuanxiaoyao.com/central" />
|
||||||
|
</remote-repository>
|
||||||
<remote-repository>
|
<remote-repository>
|
||||||
<option name="id" value="central" />
|
<option name="id" value="central" />
|
||||||
<option name="name" value="central" />
|
<option name="name" value="central" />
|
||||||
@@ -26,5 +31,10 @@
|
|||||||
<option name="name" value="JBoss Community repository" />
|
<option name="name" value="JBoss Community repository" />
|
||||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="https://maven.lanyuanxiaoyao.com/central" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
2
.idea/modules.xml
generated
2
.idea/modules.xml
generated
@@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/spring-boot-apijson-server.iml" filepath="$PROJECT_DIR$/spring-boot-apijson-server.iml" />
|
<module fileurl="file://$PROJECT_DIR$/spring-boot-server-template.iml" filepath="$PROJECT_DIR$/spring-boot-server-template.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons-vue": "^7.0.1",
|
"@ant-design/icons-vue": "^7.0.1",
|
||||||
"ant-design-vue": "4.x",
|
"ant-design-vue": "4.x",
|
||||||
|
"licia": "^1.48.0",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "4"
|
"vue-router": "4"
|
||||||
},
|
},
|
||||||
|
|||||||
8
client/pnpm-lock.yaml
generated
8
client/pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
ant-design-vue:
|
ant-design-vue:
|
||||||
specifier: 4.x
|
specifier: 4.x
|
||||||
version: 4.2.6(vue@3.5.13)
|
version: 4.2.6(vue@3.5.13)
|
||||||
|
licia:
|
||||||
|
specifier: ^1.48.0
|
||||||
|
version: 1.48.0
|
||||||
vue:
|
vue:
|
||||||
specifier: ^3.5.13
|
specifier: ^3.5.13
|
||||||
version: 3.5.13
|
version: 3.5.13
|
||||||
@@ -681,6 +684,9 @@ packages:
|
|||||||
libphonenumber-js@1.12.5:
|
libphonenumber-js@1.12.5:
|
||||||
resolution: {integrity: sha512-DOjiaVjjSmap12ztyb4QgoFmUe/GbgnEXHu+R7iowk0lzDIjScvPAm8cK9RYTEobbRb0OPlwlZUGTTJPJg13Kw==}
|
resolution: {integrity: sha512-DOjiaVjjSmap12ztyb4QgoFmUe/GbgnEXHu+R7iowk0lzDIjScvPAm8cK9RYTEobbRb0OPlwlZUGTTJPJg13Kw==}
|
||||||
|
|
||||||
|
licia@1.48.0:
|
||||||
|
resolution: {integrity: sha512-bBWiT5CSdEtwuAHiYTJ74yItCjIFdHi4xiFk6BRDfKa+sdCpkUHp69YKb5udNOJlHDzFjNjcMgNZ/+wQIHrB8A==}
|
||||||
|
|
||||||
lodash-es@4.17.21:
|
lodash-es@4.17.21:
|
||||||
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||||
|
|
||||||
@@ -1489,6 +1495,8 @@ snapshots:
|
|||||||
|
|
||||||
libphonenumber-js@1.12.5: {}
|
libphonenumber-js@1.12.5: {}
|
||||||
|
|
||||||
|
licia@1.48.0: {}
|
||||||
|
|
||||||
lodash-es@4.17.21: {}
|
lodash-es@4.17.21: {}
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
lodash@4.17.21: {}
|
||||||
|
|||||||
19
client/src/components/Flow.vue
Normal file
19
client/src/components/Flow.vue
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<script setup>
|
||||||
|
import {ref} from "vue";
|
||||||
|
import {Button} from "ant-design-vue";
|
||||||
|
|
||||||
|
const message = ref('Vue Flow')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flow"></div>
|
||||||
|
<Button>{{ message}}</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.flow {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import {createApp} from 'vue'
|
import {createApp} from 'vue'
|
||||||
import {createMemoryHistory, createRouter, createWebHistory} from 'vue-router'
|
import {createRouter, createWebHistory} from 'vue-router'
|
||||||
import App from './App.vue'
|
import App from '@/App.vue'
|
||||||
import {Layout, Menu} from 'ant-design-vue'
|
import {Layout, Menu} from 'ant-design-vue'
|
||||||
import 'ant-design-vue/dist/reset.css'
|
import 'ant-design-vue/dist/reset.css'
|
||||||
|
|
||||||
@@ -14,23 +14,28 @@ createApp(App)
|
|||||||
{
|
{
|
||||||
name: 'home',
|
name: 'home',
|
||||||
path: '/home',
|
path: '/home',
|
||||||
component: () => import('./views/Home.vue'),
|
component: () => import('@/views/Home.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'management',
|
name: 'management',
|
||||||
path: '/management',
|
path: '/management',
|
||||||
component: () => import('./views/management/Index.vue'),
|
component: () => import('@/views/management/Index.vue'),
|
||||||
redirect: '/management/overview',
|
redirect: '/management/overview',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
name: 'overview',
|
name: 'overview',
|
||||||
path: 'overview',
|
path: 'overview',
|
||||||
component: () => import('./views/management/Overview.vue'),
|
component: () => import('@/views/management/Overview.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'organization',
|
||||||
|
path: 'organization',
|
||||||
|
component: () => import('@/views/management/Organization.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'setting',
|
name: 'setting',
|
||||||
path: 'setting',
|
path: 'setting',
|
||||||
component: () => import('./views/management/Setting.vue'),
|
component: () => import('@/views/management/Setting.vue'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,19 +1,54 @@
|
|||||||
|
import {isArr} from "licia";
|
||||||
|
|
||||||
const information = {
|
const information = {
|
||||||
debug: true,
|
debug: true,
|
||||||
baseUrl: 'http://localhost'
|
baseUrl: 'http://localhost:8080',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function amisRender(target, amisJson) {
|
export function amisRender(target, amisJson) {
|
||||||
let amisJsonObject = amisJson(information)
|
let amisJsonObject = amisJson(information)
|
||||||
if (information.debug) {
|
if (information.debug) {
|
||||||
console.log(amisJsonObject)
|
console.log(amisJsonObject)
|
||||||
|
}
|
||||||
|
amisRequire('amis/embed').embed(
|
||||||
|
target,
|
||||||
|
amisJsonObject,
|
||||||
|
information,
|
||||||
|
{
|
||||||
|
theme: 'antd',
|
||||||
|
enableAMISDebug: information.debug,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseEdges(edges) {
|
||||||
|
if (isArr(edges)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function amisElideGraphQLAdaptor(payload, response, api, context) {
|
||||||
|
// console.log(payload, response, api, context)
|
||||||
|
let result = []
|
||||||
|
console.log(payload)
|
||||||
|
if (payload.data) {
|
||||||
|
let items = payload.data[Object.keys(payload.data)[0]]['edges']
|
||||||
|
for (let item of items) {
|
||||||
|
result.push(item.node)
|
||||||
}
|
}
|
||||||
amisRequire('amis/embed').embed(
|
}
|
||||||
target,
|
return result
|
||||||
amisJsonObject,
|
}
|
||||||
information,
|
|
||||||
{
|
export function amisElideJsonapiAdaptor(payload, response, api, context) {
|
||||||
theme: 'antd'
|
let result = []
|
||||||
}
|
if (payload.data && isArr(payload.data)) {
|
||||||
)
|
for (let item of payload.data) {
|
||||||
}
|
result.push({
|
||||||
|
...item,
|
||||||
|
...item['attributes'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted} from 'vue'
|
import {createApp, onMounted} from 'vue'
|
||||||
import {amisRender} from '../utils.js'
|
import {amisRender} from '@/utils.js'
|
||||||
|
import Flow from "@/components/Flow.vue";
|
||||||
|
|
||||||
const toastMessage = () => {
|
const toastMessage = () => {
|
||||||
alert('click in vue')
|
alert('click in vue')
|
||||||
@@ -29,6 +30,12 @@ onMounted(() => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'custom',
|
||||||
|
onMount: (dom, value, onChange, props) => {
|
||||||
|
createApp(Flow).mount(dom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {ref, watch} from 'vue'
|
import {
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
} from 'vue'
|
||||||
import {useRoute} from 'vue-router'
|
import {useRoute} from 'vue-router'
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
@@ -13,13 +16,18 @@ const menus = [
|
|||||||
key: 'system',
|
key: 'system',
|
||||||
name: '系统管理',
|
name: '系统管理',
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
key: 'organization',
|
||||||
|
path: '/management/organization',
|
||||||
|
name: '组织架构',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'setting',
|
key: 'setting',
|
||||||
path: '/management/setting',
|
path: '/management/setting',
|
||||||
name: '设置',
|
name: '设置',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
const sideNavSelected = ref(['overview'])
|
const sideNavSelected = ref(['overview'])
|
||||||
const openKeys = ref([]) // 控制展开的子菜单
|
const openKeys = ref([]) // 控制展开的子菜单
|
||||||
@@ -65,19 +73,21 @@ watch(() => route.path, () => {
|
|||||||
v-model:openKeys="openKeys"
|
v-model:openKeys="openKeys"
|
||||||
mode="inline"
|
mode="inline"
|
||||||
>
|
>
|
||||||
<a-menu-item key="overview">
|
<div v-for="menu in menus" :key="menu.key">
|
||||||
<router-link to="/management/overview">概览</router-link>
|
<a-sub-menu v-if="menu.children" :key="menu.key">
|
||||||
</a-menu-item>
|
<template #title>
|
||||||
<a-sub-menu key="system">
|
|
||||||
<template #title>
|
|
||||||
<span>
|
<span>
|
||||||
系统管理
|
{{ menu.name }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<a-menu-item key="setting">
|
<a-menu-item v-for="submenu in menu.children" :key="submenu.key">
|
||||||
<router-link to="/management/setting">设置</router-link>
|
<router-link :to="submenu.path">{{ submenu.name }}</router-link>
|
||||||
|
</a-menu-item>
|
||||||
|
</a-sub-menu>
|
||||||
|
<a-menu-item v-else :key="menu.key">
|
||||||
|
<router-link :to="menu.path">{{ menu.name }}</router-link>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-sub-menu>
|
</div>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</a-layout-sider>
|
</a-layout-sider>
|
||||||
<div class="p-3 h-full w-full">
|
<div class="p-3 h-full w-full">
|
||||||
|
|||||||
121
client/src/views/management/Organization.vue
Normal file
121
client/src/views/management/Organization.vue
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<script setup>
|
||||||
|
import {onMounted} from 'vue'
|
||||||
|
import {amisElideJsonapiAdaptor, amisRender,} from '@/utils.js'
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
amisRender(
|
||||||
|
'#amis-organization',
|
||||||
|
information => {
|
||||||
|
return {
|
||||||
|
type: 'page',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'tpl',
|
||||||
|
tpl: '${baseUrl}1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'crud',
|
||||||
|
syncLocation: false,
|
||||||
|
headerToolbar: [
|
||||||
|
'reload',
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
icon: 'fa fa-plus',
|
||||||
|
label: '',
|
||||||
|
actionType: 'dialog',
|
||||||
|
dialog: {
|
||||||
|
title: '新增组织',
|
||||||
|
body: {
|
||||||
|
type: 'form',
|
||||||
|
api: {
|
||||||
|
method: 'post',
|
||||||
|
url: `${information.baseUrl}/organization/save`,
|
||||||
|
data: {
|
||||||
|
code: '${code|default:undefined}',
|
||||||
|
name: '${name|default:undefined}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'code',
|
||||||
|
label: '组织编号',
|
||||||
|
placeholder: '不填则自动生成',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'name',
|
||||||
|
label: '组织名称',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
api: {
|
||||||
|
method: 'get',
|
||||||
|
url: `${information.baseUrl}/jsonapi/organization`,
|
||||||
|
data: {
|
||||||
|
fields: {
|
||||||
|
organization: 'code,name'
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
size: '${perPage|default:undefined}',
|
||||||
|
number: '${page|default:undefined}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
adaptor: amisElideJsonapiAdaptor,
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
hidden: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 150,
|
||||||
|
name: 'code',
|
||||||
|
label: '组织编号',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: '组织名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
width: 100,
|
||||||
|
label: '操作',
|
||||||
|
type: 'operation',
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'action',
|
||||||
|
icon: 'fa fa-trash',
|
||||||
|
label: '删除',
|
||||||
|
level: 'danger',
|
||||||
|
size: 'xs',
|
||||||
|
actionType: 'ajax',
|
||||||
|
api: {
|
||||||
|
method: 'delete',
|
||||||
|
url: `${information.baseUrl}/jsonapi/organization/\${id}`,
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
success: '删除成功',
|
||||||
|
failed: '删除失败',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="amis-organization"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted} from 'vue'
|
import {onMounted} from 'vue'
|
||||||
import {amisRender} from '../../utils.js'
|
import {amisRender} from '@/utils.js'
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
amisRender(
|
amisRender(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted} from 'vue'
|
import {onMounted} from 'vue'
|
||||||
import {amisRender} from '../../utils.js'
|
import {amisRender} from '@/utils.js'
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
amisRender(
|
amisRender(
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import {defineConfig} from 'vite'
|
import {defineConfig} from 'vite'
|
||||||
import obfuscatorPlugin from "vite-plugin-javascript-obfuscator";
|
import obfuscatorPlugin from "vite-plugin-javascript-obfuscator";
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import {fileURLToPath, URL} from 'node:url'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'vue': 'vue/dist/vue.esm-bundler.js',
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
}
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
obfuscatorPlugin({
|
obfuscatorPlugin({
|
||||||
|
|||||||
61
pom.xml
61
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>com.lanyuanxiaoyao</groupId>
|
<groupId>com.lanyuanxiaoyao</groupId>
|
||||||
<artifactId>spring-boot-apijson-server</artifactId>
|
<artifactId>spring-boot-server-template</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@@ -16,13 +16,23 @@
|
|||||||
<spring-boot.version>3.4.0</spring-boot.version>
|
<spring-boot.version>3.4.0</spring-boot.version>
|
||||||
<spring-cloud.version>2024.0.0</spring-cloud.version>
|
<spring-cloud.version>2024.0.0</spring-cloud.version>
|
||||||
<hutool.version>5.8.32</hutool.version>
|
<hutool.version>5.8.32</hutool.version>
|
||||||
<elide.version>7.1.4</elide.version>
|
<mapstruct.version>1.6.3</mapstruct.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jetty</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -35,7 +45,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.yahoo.elide</groupId>
|
<groupId>com.yahoo.elide</groupId>
|
||||||
<artifactId>elide-spring-boot-starter</artifactId>
|
<artifactId>elide-spring-boot-starter</artifactId>
|
||||||
<version>${elide.version}</version>
|
<version>7.1.4</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.blinkfox</groupId>
|
||||||
|
<artifactId>fenix-spring-boot-starter</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -43,14 +58,23 @@
|
|||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>${hutool.version}</version>
|
<version>${hutool.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mysql</groupId>
|
<groupId>com.mysql</groupId>
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
@@ -76,6 +100,33 @@
|
|||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.12.1</version>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||||
|
<version>0.2.0</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-Amapstruct.defaultComponentModel=spring</arg>
|
||||||
|
<arg>-Amapstruct.defaultInjectionStrategy=constructor</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-build</artifactId>
|
<artifactId>spring-boot-build</artifactId>
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.lanyuanxiaoyao.server;
|
package com.lanyuanxiaoyao.server;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.EnableFenix;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
@@ -12,6 +16,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||||||
* @since 2025-03-03
|
* @since 2025-03-03
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@EnableFenix
|
||||||
|
@EnableConfigurationProperties
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class ServerApplication {
|
public class ServerApplication {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@@ -31,4 +37,10 @@ public class ServerApplication {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ApplicationRunner initialRunner() {
|
||||||
|
return args -> {
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250327
|
||||||
|
*/
|
||||||
|
public interface Constants {
|
||||||
|
String DATABASE_TABLE_PREFIX = "platform_";
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.configuration.database;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.time.Instant;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.hibernate.annotations.IdGeneratorType;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用雪花算法作为ID生成器
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2024-11-14
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SnowflakeId {
|
||||||
|
@IdGeneratorType(IdGenerator.class)
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Target({FIELD, METHOD})
|
||||||
|
public @interface Generator {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class IdGenerator implements IdentifierGenerator {
|
||||||
|
@Override
|
||||||
|
public Object generate(SharedSessionContractImplementor session, Object object) {
|
||||||
|
try {
|
||||||
|
return Snowflake.next();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Generate snowflake id failed", e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long nextId() {
|
||||||
|
return Snowflake.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String nextStrId() {
|
||||||
|
return String.valueOf(Snowflake.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Snowflake {
|
||||||
|
/**
|
||||||
|
* 起始的时间戳
|
||||||
|
*/
|
||||||
|
private final static long START_TIMESTAMP = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列号占用的位数
|
||||||
|
*/
|
||||||
|
private final static long SEQUENCE_BIT = 11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列号最大值
|
||||||
|
*/
|
||||||
|
private final static long MAX_SEQUENCE_BIT = ~(-1 << SEQUENCE_BIT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳值向左位移
|
||||||
|
*/
|
||||||
|
private final static long TIMESTAMP_OFFSET = SEQUENCE_BIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列号
|
||||||
|
*/
|
||||||
|
private static long sequence = 0;
|
||||||
|
/**
|
||||||
|
* 上一次时间戳
|
||||||
|
*/
|
||||||
|
private static long lastTimestamp = -1;
|
||||||
|
|
||||||
|
public static synchronized long next() {
|
||||||
|
long currentTimestamp = nowTimestamp();
|
||||||
|
if (currentTimestamp < lastTimestamp) {
|
||||||
|
throw new RuntimeException("Clock have moved backwards.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTimestamp == lastTimestamp) {
|
||||||
|
// 相同毫秒内, 序列号自增
|
||||||
|
sequence = (sequence + 1) & MAX_SEQUENCE_BIT;
|
||||||
|
// 同一毫秒的序列数已经达到最大
|
||||||
|
if (sequence == 0) {
|
||||||
|
currentTimestamp = nextTimestamp();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不同毫秒内, 序列号置为0
|
||||||
|
sequence = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastTimestamp = currentTimestamp;
|
||||||
|
return (currentTimestamp - START_TIMESTAMP) << TIMESTAMP_OFFSET | sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long nextTimestamp() {
|
||||||
|
long milli = nowTimestamp();
|
||||||
|
while (milli <= lastTimestamp) {
|
||||||
|
milli = nowTimestamp();
|
||||||
|
}
|
||||||
|
return milli;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long nowTimestamp() {
|
||||||
|
return Instant.now().toEpochMilli();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.controller;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.controller.base.AbstractController;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Organization;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.mapper.EntityMapper;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.mapper.OrganizationMapper;
|
||||||
|
import com.lanyuanxiaoyao.server.service.OrganizationService;
|
||||||
|
import com.lanyuanxiaoyao.server.service.base.AbstractService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("organization")
|
||||||
|
public class OrganizationController extends AbstractController<Organization, Long, Organization.SaveVO> {
|
||||||
|
private final OrganizationService organizationService;
|
||||||
|
private final OrganizationMapper organizationMapper;
|
||||||
|
|
||||||
|
public OrganizationController(OrganizationService organizationService, OrganizationMapper organizationMapper) {
|
||||||
|
this.organizationService = organizationService;
|
||||||
|
this.organizationMapper = organizationMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractService<Organization, Long> getService() {
|
||||||
|
return organizationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityMapper<Organization, Organization.SaveVO> getEntityMapper() {
|
||||||
|
return organizationMapper;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.controller.base;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.entity.mapper.EntityMapper;
|
||||||
|
import com.lanyuanxiaoyao.server.service.base.AbstractService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
public abstract class AbstractController<ENTITY, ID, SAVE_VO> {
|
||||||
|
public abstract AbstractService<ENTITY, ID> getService();
|
||||||
|
|
||||||
|
public abstract EntityMapper<ENTITY, SAVE_VO> getEntityMapper();
|
||||||
|
|
||||||
|
@GetMapping("/get/{id}")
|
||||||
|
public ENTITY get(@PathVariable("id") ID id) {
|
||||||
|
return getService().get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
public ID save(@RequestBody SAVE_VO entity) {
|
||||||
|
return getService().save(getEntityMapper().fromVO(entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.controller.base;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理错误信息
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @date 2024-01-02
|
||||||
|
*/
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class ErrorController {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ErrorController.class);
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
@ExceptionHandler(Throwable.class)
|
||||||
|
public String errorHandler(Throwable throwable) {
|
||||||
|
logger.error("Error", throwable);
|
||||||
|
return throwable.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.entity;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.configuration.Constants;
|
||||||
|
import com.lanyuanxiaoyao.server.configuration.database.SnowflakeId;
|
||||||
|
import com.yahoo.elide.annotation.Include;
|
||||||
|
import jakarta.persistence.ConstraintMode;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.ForeignKey;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组织
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250327
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = Constants.DATABASE_TABLE_PREFIX + "department")
|
||||||
|
@Include
|
||||||
|
public class Department {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "snowflakeId")
|
||||||
|
@GenericGenerator(name = "snowflakeId", type = SnowflakeId.IdGenerator.class)
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Organization organization;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Department parent;
|
||||||
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
|
||||||
|
@ToString.Exclude
|
||||||
|
private Set<Department> children;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public static class SaveVO {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private Long organizationId;
|
||||||
|
private Long parentId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.server.entity;
|
|
||||||
|
|
||||||
import com.yahoo.elide.annotation.LifeCycleHookBinding;
|
|
||||||
import com.yahoo.elide.core.lifecycle.LifeCycleHook;
|
|
||||||
import com.yahoo.elide.core.security.ChangeSpec;
|
|
||||||
import com.yahoo.elide.core.security.RequestScope;
|
|
||||||
import java.util.Optional;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @version 20250304
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class LogicDeletedHook implements LifeCycleHook<User> {
|
|
||||||
@Override
|
|
||||||
public void execute(LifeCycleHookBinding.Operation operation, LifeCycleHookBinding.TransactionPhase phase, User user, RequestScope scope, Optional<ChangeSpec> changes) {
|
|
||||||
log.info("Operation: {}, Phase: {}, User: {}, Scope: {}, Changes: {}", operation, phase, user, scope, changes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.entity;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.configuration.Constants;
|
||||||
|
import com.lanyuanxiaoyao.server.configuration.database.SnowflakeId;
|
||||||
|
import com.yahoo.elide.annotation.Include;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组织
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250327
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Entity
|
||||||
|
@Table(name = Constants.DATABASE_TABLE_PREFIX + "organization")
|
||||||
|
@Include
|
||||||
|
public class Organization {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "snowflakeId")
|
||||||
|
@GenericGenerator(name = "snowflakeId", type = SnowflakeId.IdGenerator.class)
|
||||||
|
private Long id;
|
||||||
|
@Column(unique = true, nullable = false)
|
||||||
|
private String code;
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.LAZY, mappedBy = "organization")
|
||||||
|
@ToString.Exclude
|
||||||
|
private Set<Department> departments;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public static final class SaveVO {
|
||||||
|
private Long id;
|
||||||
|
private String code;
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.server.entity;
|
|
||||||
|
|
||||||
import com.yahoo.elide.annotation.Include;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.OneToMany;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @version 20250304
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@DynamicUpdate
|
|
||||||
@Include
|
|
||||||
public class School {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.UUID)
|
|
||||||
private String id;
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String name;
|
|
||||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "school")
|
|
||||||
@ToString.Exclude
|
|
||||||
private List<User> users;
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.lanyuanxiaoyao.server.entity;
|
|
||||||
|
|
||||||
import com.yahoo.elide.annotation.Include;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.ConstraintMode;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.ForeignKey;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.ToString;
|
|
||||||
import org.hibernate.annotations.DynamicUpdate;
|
|
||||||
import org.hibernate.annotations.SoftDelete;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author lanyuanxiaoyao
|
|
||||||
* @version 20250304
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@ToString
|
|
||||||
@Entity
|
|
||||||
@DynamicUpdate
|
|
||||||
@Include
|
|
||||||
@SoftDelete
|
|
||||||
public class User {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.UUID)
|
|
||||||
private String id;
|
|
||||||
@Column(unique = true, nullable = false)
|
|
||||||
private String username;
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String password;
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
|
||||||
@ToString.Exclude
|
|
||||||
private School school;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.entity.mapper;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Department;
|
||||||
|
import com.lanyuanxiaoyao.server.service.DepartmentService;
|
||||||
|
import com.lanyuanxiaoyao.server.service.OrganizationService;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门bean转换
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250327
|
||||||
|
*/
|
||||||
|
@Mapper(
|
||||||
|
uses = {
|
||||||
|
OrganizationService.class,
|
||||||
|
DepartmentService.class,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public interface DepartmentMapper extends EntityMapper<Department, Department.SaveVO> {
|
||||||
|
@Mapping(target = "organization", source = "organizationId")
|
||||||
|
@Mapping(target = "parent", source = "parentId")
|
||||||
|
@Override
|
||||||
|
Department fromVO(Department.SaveVO saveVO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.entity.mapper;
|
||||||
|
|
||||||
|
public interface EntityMapper<SE, CE> {
|
||||||
|
SE fromVO(CE creationVO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.entity.mapper;
|
||||||
|
|
||||||
|
import com.lanyuanxiaoyao.server.configuration.database.SnowflakeId;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Organization;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组织bean转换
|
||||||
|
*
|
||||||
|
* @author lanyuanxiaoyao
|
||||||
|
* @version 20250327
|
||||||
|
*/
|
||||||
|
@Mapper(
|
||||||
|
imports = {
|
||||||
|
SnowflakeId.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public interface OrganizationMapper extends EntityMapper<Organization, Organization.SaveVO> {
|
||||||
|
@Mapping(target = "code", defaultExpression = "java(SnowflakeId.nextStrId())")
|
||||||
|
@Override
|
||||||
|
Organization fromVO(Organization.SaveVO creationVO);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.repository;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
|
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Department;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface DepartmentRepository extends FenixJpaRepository<Department, Long>, FenixJpaSpecificationExecutor<Department> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.repository;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
|
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Organization;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface OrganizationRepository extends FenixJpaRepository<Organization, Long>, FenixJpaSpecificationExecutor<Organization> {
|
||||||
|
@Override
|
||||||
|
Organization getReferenceById(Long aLong);
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.service;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Department;
|
||||||
|
import com.lanyuanxiaoyao.server.repository.DepartmentRepository;
|
||||||
|
import com.lanyuanxiaoyao.server.service.base.AbstractService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DepartmentService extends AbstractService<Department, Long> {
|
||||||
|
private final DepartmentRepository departmentRepository;
|
||||||
|
|
||||||
|
public DepartmentService(DepartmentRepository departmentRepository) {
|
||||||
|
this.departmentRepository = departmentRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FenixJpaRepository<Department, Long> getRepository() {
|
||||||
|
return departmentRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getId(Department department) {
|
||||||
|
return department.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.service;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
|
import com.lanyuanxiaoyao.server.entity.Organization;
|
||||||
|
import com.lanyuanxiaoyao.server.repository.OrganizationRepository;
|
||||||
|
import com.lanyuanxiaoyao.server.service.base.AbstractService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class OrganizationService extends AbstractService<Organization, Long> {
|
||||||
|
private final OrganizationRepository organizationRepository;
|
||||||
|
|
||||||
|
public OrganizationService(OrganizationRepository organizationRepository) {
|
||||||
|
this.organizationRepository = organizationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FenixJpaRepository<Organization, Long> getRepository() {
|
||||||
|
return organizationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getId(Organization organization) {
|
||||||
|
return organization.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.lanyuanxiaoyao.server.service.base;
|
||||||
|
|
||||||
|
import com.blinkfox.fenix.jpa.FenixJpaRepository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
public abstract class AbstractService<ENTITY, ID> {
|
||||||
|
public abstract FenixJpaRepository<ENTITY, ID> getRepository();
|
||||||
|
|
||||||
|
public abstract ID getId(ENTITY entity);
|
||||||
|
|
||||||
|
public ENTITY get(ID id) {
|
||||||
|
return getRepository().getReferenceById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public ID save(ENTITY entity) {
|
||||||
|
ENTITY saved = getRepository().saveOrUpdateByNotNullProperties(entity);
|
||||||
|
return getId(saved);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:mysql://localhost:3307/main?useSSL=false&allowPublicKeyRetrieval=true
|
url: jdbc:h2:file:./database;DB_CLOSE_ON_EXIT=FALSE
|
||||||
username: test
|
username: test
|
||||||
password: test
|
password: test
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: org.h2.Driver
|
||||||
jpa:
|
jpa:
|
||||||
show-sql: true
|
show-sql: true
|
||||||
generate-ddl: true
|
generate-ddl: true
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 10MB
|
||||||
|
max-request-size: 20MB
|
||||||
|
jackson:
|
||||||
|
date-format: 'yyyy-MM-dd HH:mm:ss'
|
||||||
elide:
|
elide:
|
||||||
json-api:
|
json-api:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -22,4 +28,6 @@ logging:
|
|||||||
datastores:
|
datastores:
|
||||||
jpql:
|
jpql:
|
||||||
query:
|
query:
|
||||||
DefaultQueryLogger: debug
|
DefaultQueryLogger: debug
|
||||||
|
fenix:
|
||||||
|
print-banner: false
|
||||||
20
src/test/resources/organization.http
Normal file
20
src/test/resources/organization.http
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
### Create
|
||||||
|
POST http://localhost:8080/jsonapi/organization
|
||||||
|
Content-Type: application/vnd.api+json
|
||||||
|
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"type": "organization",
|
||||||
|
"attributes": {
|
||||||
|
"organizationName": "苹果公司"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
### Create
|
||||||
|
POST http://localhost:8080/graphql
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"query": "mutation {organization(op: UPSERT, data: {organizationName: \"苹果\"}) {edges {node {organizationId organizationName}}}}"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user