低代码平台directus 实战半年-进阶篇

介绍

directus 支持extension扩展有多种方式

  • display: 前端vue页面二次开发展示,用于定制后台列表页面的显示,对应某个字段
  • interface: 前端vue页面二次开发展示,用于定制后台详情页面的显示,对应某个字段
  • operation: 在flow里面的框框,有输入和输出。可以做更细粒度的业务封装
  • endpoint: 后台express的一个路由RESTful服务
  • hook: 监听数据变化钩子函数
  • layout: 后台列表页面的整体布局(列表或瀑布流)
  • panel: 后台报表分析的模块图像/表格化显示
  • module: 后台系统左边大菜单模块,可以定制更丰富的模块内容

1. displays

displays:前端vue页面二次开发展示,用于定制后台列表页面的显示,对应某个字段

我们用官方自带脚手架定制一个后台的displays

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装

# 提示
Need to install the following packages:
  [email protected]
Ok to proceed? (y) y # 输入y
This utility will walk you through creating a Directus extension.
# 选择 display
? Choose the extension type 
  panel 
  hook 
  endpoint 
  operation 
  bundle 
  interface 
 ❯ display 
 
 # 定义名称
 Choose a name for the extension mytest
 # 选择语言
 ? Choose the language to use 
  javascript 
❯ typescript 


# 根据提示 我们进入进入项目运行调试或构建
To start developing, run:
        cd mytest
        npm run dev

and then to build for production, run:
        npm run build

生成的代码

为了方便调整 我们打开项目的热更新

js 复制代码
EXTENSIONS_AUTO_RELOAD=true
EXTENSIONS_PATH="./extensions"

启动服务,发现缺少index.js 因为自定义display打包路径是mytest/dist/index.js,而directus访问的路径是mytest/index.js

js 复制代码
[17:41:44.367] WARN: Couldn't bundle App extensions
[17:41:44.368] WARN: Could not resolve "./extensions/displays/mytest/index.js" from "virtual:entry"
    err: {
      "type": "Error",
      "message": "Could not resolve \"./extensions/displays/mytest/index.js\" from \"\u0000virtual:entry\"",

我们调整mytest的package.json输出路径

json 复制代码
	"directus:extension": {
		"type": "display",
		"path": "dist/index.js",
		"source": "src/index.ts",
		"host": "^10.1.14"
	}, 

"path": "dist/index.js",调整为 "path": "./index.js",

再次启动,已经提示正常加载组件

测试一把

进入city表,选择name编辑 在显示拦新增了custom选项

我们对比选中自定义的name显示区别。 其实就是把字段通过自定义组件显示

代码分析

src/display.vue

生成的是vue3代码

html 复制代码
<template>
	<div>Value: {{ value }}</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
	props: {
		value: {
			type: String,
			default: null,
		},
	},
});
</script>

src/index.ts

js 复制代码
import { defineDisplay } from '@directus/extensions-sdk';
import DisplayComponent from './display.vue';

export default defineDisplay({
	id: 'custom',
	name: 'Custom',
	icon: 'box',
	description: 'This is my custom display!',
	component: DisplayComponent,
	options: null, //这里可以外部传入自定义的逻辑处理显示的交互
	types: ['string'], //这里对应数据字段类型,只有匹配的类型才能选择该display
});

2. interfaces

interfaces: 前端vue页面二次开发展示,用于定制后台详情页面的显示,对应某个字段

和display相同操作,我们创建interface

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 interface 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/interfaces/mytest
 npm run dev

发现directus已经热加载最新interface插件

开始设置 在city -> name字段 接口栏发现 custom

对比详情页面差异

代码分析

src/interface.vue

生成的是vue3代码

html 复制代码
<template>
	<input :value="value" @input="handleChange($event.target.value)" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
	props: {
		value: {
			type: String,
			default: null,
		},
	},
	emits: ['input'],
	setup(props, { emit }) {
		return { handleChange };

		function handleChange(value: string): void {
			emit('input', value);
		}
	},
});
</script>

src/index.ts

js 复制代码
import { defineInterface } from '@directus/extensions-sdk';
import InterfaceComponent from './interface.vue';

export default defineInterface({
	id: 'custom',
	name: 'Custom',
	icon: 'box',
	description: 'This is my custom interface!',
	component: InterfaceComponent,
	options: null,//这里可以外部传入自定义的逻辑处理显示的交互
	types: ['string'],//这里对应数据字段类型,只有匹配的类型才能选择该display
}); 

3.operation

operation: 就是在flow里面的框框,有输入和输出。可以做更细粒度的业务封装

和上面相同操作,我们创建operation

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 operation 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/operation/mytest
 npm run dev

发现directus已经热加载最新operation插件

新建一个get请求的flow

创建一个operation,发现底部多了一个custom选项

选中并输入11111

访问get请求

http://127.0.0.1:8055/flows/trigger/ed2f22a8-ae4e-4ee8-9cbe-9b72a5195ba8

可以看到控制台输出 11111

代码分析

src/api.ts 运行时的代码

ts 复制代码
import { defineOperationApi } from '@directus/extensions-sdk';

type Options = {
	text: string;
};

export default defineOperationApi<Options>({
	id: 'custom',
	handler: ({ text }) => {
		console.log(text); //这里把接收的参数打印到控制台
	},
});

src/app.ts 用于定义operation的配置项

js 复制代码
import { defineOperationApp } from '@directus/extensions-sdk';

export default defineOperationApp({
	id: 'custom',
	name: 'Custom1',
	icon: 'box',
	description: 'This is my custom operation!', //描述信息
	overview: ({ text }) => [
		{
			label: 'Text',
			text: text,
		},
	],
	options: [ //定义了一个文本输入框展示方式
		{
			field: 'text',
			name: 'Text',
			type: 'string',
			meta: {
				width: 'full',
				interface: 'input',
			},
		},
	],
});

4.endpoint

endpoint: 后台express的一个路由服务

和上面相同操作,我们创建endpoint

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 endpoint 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/endpoint/mytest
 npm run dev

发现directus已经热加载最新endpoint插件

在地址栏访问 127.0.0.1:8055/mytest/

输出hello word!

代码分析

src/index.ts

js 复制代码
import { defineEndpoint } from '@directus/extensions-sdk';

export default defineEndpoint((router) => {
	router.get('/', (_req, res) => res.send('Hello, World!'));
});

可以看到写法其实就是一个express的服务,默认路由前缀是 mytest

5.hook

hook: 监听数据变化钩子函数

和上面相同操作,我们创建hook

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 hook 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/hook/mytest
 npm run dev

发现directus已经热加载最新hook插件

测试新增一条city数据

发现控制台打印

代码分析

src/index.ts

js 复制代码
import { defineHook } from '@directus/extensions-sdk';

export default defineHook(({ filter, action }) => {
	filter('items.create', () => {
		console.log('Creating Item!');
	});

	action('items.create', () => {
		console.log('Item created!');
	});
});

可以看到在数据发生变化的时候,监听了数据的创建过滤事件和动作事件

优化代码

我们把入参打印

js 复制代码
import { defineHook } from '@directus/extensions-sdk';

export default defineHook(({ filter, action }) => {
	filter('items.create', (args) => {
		console.log('Creating Item!',args);
	});

	action('items.create', (args) => {
		console.log('Item created!',args);
	});
});

新建一条rrrr数据

可以获取变化数据,如id 参数 进行具体的业务逻辑处理

6.panel

panel: 后台报表分析的模块图像/表格化显示

和上面相同操作,我们创建panel

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 panel 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/panel/mytest
 npm run dev

发现directus已经热加载最新panel插件

新建一个表盘

我们可以新增一个省份的列表对比

代码分析

src/panel.vue

html 复制代码
<template>
	<div class="text" :class="{ 'has-header': showHeader }">
		{{ text }}
	</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
	props: {
		showHeader: {
			type: Boolean,
			default: false,
		},
		text: {
			type: String,
			default: '',
		},
	},
});
</script>

<style scoped>
.text {
	padding: 12px;
}

.text.has-header {
	padding: 0 12px;
}
</style>

src/index.ts

js 复制代码
import { definePanel } from '@directus/extensions-sdk';
import PanelComponent from './panel.vue';

export default definePanel({
	id: 'custom',
	name: 'Custom',
	icon: 'box',
	description: 'This is my custom panel!',
	component: PanelComponent,
	options: [
		{
			field: 'text',
			name: 'Text',
			type: 'string',
			meta: {
				interface: 'input',
				width: 'full',
			},
		},
	],
	minWidth: 12,
	minHeight: 8,
});

7.layout

layout: 后台列表页面的整体布局(列表或瀑布流)

和上面相同操作,我们创建layout

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 layout 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/layout/mytest
 npm run dev

发现directus已经热加载最新layout插件

我们在列表页面可以选择自定义的布局效果

由于我们没有重写对应列表逻辑。所以显示了默认的文本提示内容

代码分析

src/layout.vue

html 复制代码
<template>
	<div>
		<p>Name: {{ name }}</p>
		<p>Collection: {{ collection }}</p>
	</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
	inheritAttrs: false,
	props: {
		collection: {
			type: String,
			required: true,
		},
		name: {
			type: String,
			required: true,
		},
	},
});
</script>

src/index.ts

js 复制代码
import { ref } from 'vue';
import { defineLayout } from '@directus/extensions-sdk';
import LayoutComponent from './layout.vue';

export default defineLayout({
	id: 'custom',
	name: 'Custom',
	icon: 'box',
	component: LayoutComponent,
	slots: {
		options: () => null,
		sidebar: () => null,
		actions: () => null,
	},
	setup() {
		const name = ref('Custom Layout');

		return { name };
	},
});

8.module

module: 后台系统左边大菜单模块,可以定制更丰富的模块内容

和上面相同操作,我们创建module

sh 复制代码
cd extensions/displays #进入扩展路径
npx create-directus-extension@latest # 执行扩展安装
选择 module 》 typescript    

修改配置 我们调整mytest的package.json输出路径

json 复制代码
    "directus:extension": {
            "type": "interface",
            "path": "./index.js",
            "source": "src/index.ts",
            "host": "^10.1.14"
    },

生成代码

测试一把

运行

js 复制代码
 cd ./extensions/module/mytest
 npm run dev

发现directus已经热加载最新module插件

进入设置页面可以发现设置模块里面多出来一个custom

勾选+保存

左侧菜单多出了对应的新菜单模块选项

相关推荐
阑梦清川1 小时前
关于Go语言的开发环境的搭建
开发语言·后端·golang
lyrhhhhhhhh2 小时前
Spring 模拟转账开发实战
java·后端·spring
tonngw2 小时前
【Mac 从 0 到 1 保姆级配置教程 12】- 安装配置万能的编辑器 VSCode 以及常用插件
git·vscode·后端·macos·开源·编辑器·github
noravinsc3 小时前
InforSuite RDS 与django结合
后端·python·django
Brookty4 小时前
【MySQL】基础知识
后端·学习·mysql
一只码代码的章鱼4 小时前
Spring 的 异常管理的相关注解@ControllerAdvice 和@ExceptionHandler
java·后端·spring
老友@4 小时前
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解
java·后端·spring·elasticsearch·operations
熬夜苦读学习5 小时前
Linux线程控制
linux·运维·服务器·开发语言·后端
bing_1586 小时前
Spring Boot 项目中什么时候会抛出 FeignException?
java·spring boot·后端
Java&Develop6 小时前
springboot + mysql8降低版本到 mysql5.7
java·spring boot·后端