用什么技术可以3天写出一个商城?

796 阅读5分钟

先上个预览地址

show.cool-admin.com/

账号:admin 密码:123456

1721442947571.jpg

Ai流程编排

通过拖放操作,可以实现利用AI技术来优化和自动化各种工作流程。

前端是基于 @vue-flow

a3dddfeb49914948a8f92915c8775267~tplv-73owjymdk6-watermark.png

Ai极速编码

来试试:show.cool-admin.com/helper/ai-c…

根据简要的描述生成完整的前后端代码,尊嘟假嘟??

image.png

7.14 支持 Java 版本,生成 MapperEntityService 实现/接口类Controller

有啥不一样??

路人甲:有一说一这种后台模版一抓一大把

路人乙:不就是UI组件套一套凑出来壳子的玩意

路人丙:代码结构肯定又是复制 vue-admin-template 那一套

...

虽然...,但是...,请跟着我往下看看

模块化开发

除了看得见的UI界面,背后的目录结构、代码设计都是几年来的总结和提炼。模块化开发也助于我们代码复用,降低耦合度。

src
  ├── cool 核心文件:权限、路由、模块插件的加载、Eps的生成
  ├── plugins
  │      ├── crud CRUD组件
  │      ├── editor 代码编辑器、符文布编辑器
  │      ├── upload 文件上传
  │      ├── excel 表格导入导出
  │      └── view 视图组件
  ├── modules
  │      ├── base 基础模块:用户、菜单、角色等
  │      ├── chat 聊天通讯模块
  │      ├── dict 字典模块
  │      ├── helper 快速开发辅助模块
  │      ├── space 文件管理模块
  │      ├── task 任务模块
  │      ├── theme 主题模块
  │      └── user 用户模块

使用的方式极为清爽

import { useBase } from '/$/base';
import { useDict } from '/$/dict';

const { user } = useBase();
const { dict } = useDict();

// 使用
user.token
user.info.nickName
dict.get('userTag');

Eps扩展

Eps是什么?这个大家想必很陌生。它是扫描服务端的 Api 和 Entity,自动在前端生成 service、dts 文件,提高开发效率。

以往的开发流程:

  • 后端创建表,写API接口;
  • 编写API接口文档;
  • 前端根据API接口文档,编写对应的调用接口的方法;
  • 前端使用到的地方调用接口;
  • 最后加上一堆恶心的 any;

这样的流程似乎有些冗余,我们在下面做了一些对比:

1. 在服务请求中

使用前:

// /api/user.ts
import { request } from "/@/utils"

export function userPage(data: any) {
    return request({ 
        url: "/admin/user/page",
        method: "POST",
        data
    })
}

export function userInfo() { ... };
export function userUpdate() { ... };
export function userAdd() { ... };
export function userDelete() { ... };
// user.vue
import { userInfo } from "/@/api/user.ts"

userInfo({ id: 1 }); // 获取用户详情

使用后:

image.png

自动同步生成 Service 对象,层级与请求路径一致。嗯... 都忘了 axios 怎么写了

2. 在类型描述中

使用前:

// 定义一个list
const list = ref([])

// 在页面中渲染,你猜这时候 item 是不是一个any
<ul>
    <li v-for="(item) in list">{{ item.nickName }}</li>
</ul>

// 那给他加个类型吧
interface User {
    nickName: string;
    avatarUrl: string;
    status: number;
    createTime: Date;
    ...
}

// 指定类型后有提示了
const list = ref<User[]>([])

使用后:

const list = ref<Eps.UserInfoEntity>([])

Eps.UserInfoEntity 根据后端 Entity 解析而来。那为什么不自己定义类型呢?

  • 后端有很多的 Entity,老板说给你的时间不多
  • 后端是 MidwayJs,还能蛮复制一下。那要是 JavaPython 咋办
  • 新需求要添加字段的时候,又要每个类型对一遍

Crud组件

做后台管理系统最离不开的就是表的增删改查,俗称CRUD。解决的方案也非常多:

  1. 最常见的是 Mixin 混入(这种方式灵活性不够)
  2. 封装一个<crud />然后文档写一堆的参数,是否要新增按钮、是否能删除、某列能不能搜索加上 n 多插槽的命名 table-after table-before header footer等等(相信使用的人也很累,满头问号??)
  3. 低代码平台,直接生成几百行代码。(谁用谁难受)
  4. 复制黏贴(直接起飞)

那我们的优势又是什么??以下是我们基础代码的示例:

<template>
	<cl-crud ref="Crud">
		<cl-row>
			<!-- 刷新按钮 -->
			<cl-refresh-btn />
			<!-- 新增按钮 -->
			<cl-add-btn />
			<!-- 删除按钮 -->
			<cl-multi-delete-btn />
			<!-- 筛选状态 -->
			<cl-filter label="状态">
				<cl-select prop="status" :options="options.status" />
			</cl-filter>
			<cl-flex1 />
			<!-- 关键字搜索 -->
			<cl-search-key placeholder="搜索名称、品牌" />
		</cl-row>

		<cl-row>
			<!-- 数据表格 -->
			<cl-table ref="Table">
				<template #column-specification="{ scope }"> 自定义规格展示 </template>
			</cl-table>
		</cl-row>

		<cl-row>
			<cl-flex1 />
			<!-- 分页控件 -->
			<cl-pagination />
		</cl-row>

		<!-- 新增、编辑 -->
		<cl-upsert ref="Upsert">
			<template #slot-specification="{ scope }"> 自定义规格输入 </template>
		</cl-upsert>
	</cl-crud>
</template>

<script lang="ts" name="goods-info" setup>
	import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
	import { useCool } from '/@/cool';

	const { service } = useCool();

	// 选择项
	const options = reactive({
		status: [
			{ label: '下架', value: 0, type: 'danger' },
			{ label: '上架', value: 1, type: 'success' }
		]
	});

	// 新增、编辑配置
	const Upsert = useUpsert({
		items: [
			{
				label: '名称',
				prop: 'name',
				component: { name: 'el-input', props: { clearable: true } },
				required: true
			},
			{
				label: '价格',
				prop: 'price',
				hook: 'number',
				component: { name: 'el-input-number' },
				required: true
			},
			{
				label: '库存',
				prop: 'stock',
				hook: 'number',
				component: { name: 'el-input-number' },
				required: true
			},
			{
				label: '品牌',
				prop: 'brand',
				component: { name: 'el-input', props: { clearable: true } },
				required: true
			},
			{
				label: '规格',
				prop: 'specification',
				component: {
					name: 'slot-specification'
				}
			},
			{
				label: '描述',
				prop: 'description',
				component: { name: 'el-input', props: { type: 'textarea', rows: 4 } }
			},
			{
				label: '图片',
				prop: 'images',
				component: { name: 'cl-upload', props: { multiple: true } }
			},
			{
				label: '状态',
				prop: 'status',
				component: {
					name: 'el-radio-group',
					options: options.status
				},
				value: 0,
				required: true
			},
			{
				label: '销量',
				prop: 'sales',
				hook: 'number',
				component: { name: 'el-input-number' },
				required: true
			}
		]
	});

	// 表格配置
	const Table = useTable({
		columns: [
			{ type: 'selection' },
			{ label: '名称', prop: 'name', minWidth: 140 },
			{ label: '价格', prop: 'price', minWidth: 140 },
			{ label: '库存', prop: 'stock', minWidth: 140 },
			{ label: '品牌', prop: 'brand', minWidth: 140 },
			{ label: '规格', prop: 'specification', minWidth: 140 },
			{ label: '描述', prop: 'description', showOverflowTooltip: true, minWidth: 200 },
			{
				label: '图片',
				prop: 'images',
				minWidth: 100,
				component: { name: 'cl-image', props: { size: 60 } }
			},
			{
				label: '状态',
				prop: 'status',
				component: {
					name: 'cl-switch'
				},
				minWidth: 120
			},
			{ label: '销量', prop: 'sales', minWidth: 140 },
			{
				label: '创建时间',
				prop: 'createTime',
				minWidth: 170,
				sortable: 'desc'
			},
			{ type: 'op', buttons: ['edit', 'delete'] }
		]
	});

	// CRUD配置
	const Crud = useCrud(
		{
			service: service.goods.info // 绑定某个 service,驱动整个CRUD
		},
		(app) => {
			app.refresh();
		}
	);

	// 刷新数据
	function refresh(params?: any) {
		Crud.value?.refresh(params);
	}
</script>

代码清晰易懂,也有很多人性化的设计(不一一举例):

  • 使用 useTable<Eps.GoodsInfoEntity> 后,items.prop 就能提示当前表有那些可选字段值
  • 继承 elm 的组件,如 cl-table 组件可直接使用 el-tableborder stripe row-class-name 等属性
  • 支持插件模式,如输入框自动聚焦插件、字段权限校验插件

更多示例请移步:show.cool-admin.com/demo/crud

最后

闺蜜喊ct了,后续叫大哥们把 MidwayJs Java 的一起补上,未完待续~~

另外 GoPython 的版本也在铁粉的帮助下显露端倪

贴个官网链接:cool-js.com/

再贴个Github链接:github.com/cool-team-o…

完全开源,好用点个 Star 撒~~