cool-admin之cl-upset自定义组件(1)

这是一个以前就写好的项目,但是后来增加了新需求

首先贴上原来组件的代码registry.vue

<template>
	<cl-crud ref="Crud">
		<el-row>
			<!-- 刷新按钮 -->
			<cl-refresh-btn />
			<!-- 新增按钮 -->
			<cl-add-btn />
			<!-- 删除按钮 -->
			<cl-multi-delete-btn />
			<cl-flex1 />
			<!-- 关键字搜索 -->
			<cl-search-key />
		</el-row>

		<el-row>
			<!-- 数据表格 -->
			<cl-table ref="Table">
				<template #column-flagImg="{ scope }">
					<div class="flex items-center justify-center">
						<el-image class="h-9 min-w-12" :src="scope.row.flagImg" fit="cover" />
					</div>
				</template>
			</cl-table>
		</el-row>

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

		<!-- 新增、编辑 -->
		<cl-upsert ref="Upsert" />
	</cl-crud>
</template>

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

const { service } = useCool();

// cl-upsert 配置
const Upsert = useUpsert({
	items: [
		{ label: "编码", prop: "mid", required: true, component: { name: "el-input" } },
		{ label: "国家名", prop: "eCountry", required: true, component: { name: "el-input" } },
		{ label: "中文名", prop: "cCountry", required: true, component: { name: "el-input" } },
		{ label: "缩写", prop: "abbreviate", component: { name: "el-input" } },
		{ label: "国旗", prop: "flagImg", component: { name: "cl-upload" } }
	]
});

// cl-table 配置
const Table = useTable({
	columns: [
		{ type: "selection" },
		{ label: "国旗", prop: "flagImg" },
		{ label: "编码", prop: "mid" },
		{ label: "国家名", prop: "eCountry" },
		{ label: "中文名", prop: "cCountry" },
		{ label: "缩写", prop: "abbreviate" },
		{ type: "op", buttons: ["edit", "delete"] }
	]
});

// cl-crud 配置
const Crud = useCrud(
	{
		service: service.ship.registry
	},
	(app) => {
		app.refresh();
	}
);
</script>

我就不具体解释代码了,看下面的代码块

// cl-upsert 配置
const Upsert = useUpsert({
	items: [
		{ label: "编码", prop: "mid", required: true, component: { name: "el-input" } },
		{ label: "国家名", prop: "eCountry", required: true, component: { name: "el-input" } },
		{ label: "中文名", prop: "cCountry", required: true, component: { name: "el-input" } },
		{ label: "缩写", prop: "abbreviate", component: { name: "el-input" } },
		{ label: "国旗", prop: "flagImg", component: { name: "cl-upload" } }
	]
});

最后的国旗这一块,以前使用的组件是cl-upload,是cool框架团队自己封装的element-plue组件,原型是el-upload,它存在数据库中字段的类型时varchar,长度32字节,是静态资源的访问地址url,现在要求存入base64转码后的字符串,这样的好处是,数据库迁移方便,只要复制ship_registry表的内容到其他的项目就可以直接使用,而不用拷贝静态资源,对这个项目的包的压力更小,坏处就是对于数据库的压力增大,因为存入base64转码后的字符串必然需要改变表的结构。

以前的表registry.ts

import { EntityModel } from '@midwayjs/orm';
import { BaseEntity } from '@cool-midway/core';
import { Column } from 'typeorm';

/**
 * 船队管理
 */
@EntityModel('ship_registry')
export class ShipRegistryEntity extends BaseEntity {
  @Column({ comment: '编码', type: 'bigint' })
  mid: number;

  @Column({ comment: '国家名' })
  eCountry: string;

  @Column({ comment: '国家名(中文)' })
  cCountry: string;

  @Column({ comment: '缩写' })
  abbreviate: string;

  @Column({ comment: '国旗', nullable: true})
  flagImg: string;
}

修改后的表:

import { EntityModel } from '@midwayjs/orm';
import { BaseEntity } from '@cool-midway/core';
import { Column } from 'typeorm';

/**
 * 船队管理
 */
@EntityModel('ship_registry')
export class ShipRegistryEntity extends BaseEntity {
  @Column({ comment: '编码', type: 'bigint' })
  mid: number;

  @Column({ comment: '国家名' })
  eCountry: string;

  @Column({ comment: '国家名(中文)' })
  cCountry: string;

  @Column({ comment: '缩写' })
  abbreviate: string;

  @Column({ comment: '国旗', nullable: true,type: "text"  })
  flagImg: string;
}

将flagImg字段的类型由varchar改为text,这样改原来存在表中的数据精度不会丢失,因为text长于varchar.

但是查询,插入的性能必然会受影响,本项目ship_registry表的查询,插入操作不是很频繁,所以影响不是很大,可以在接收范围内。

回到正题:以前使用的是cl-upload,我们不可能进cool框架内部改它的组件,所以唯一的解决办法只有自定义一个组件,替换掉cl-upload.

在component文件夹下新建一个upload-image.vue

<template>
	<!-- 缩略图显示-->
	<div class="img-show" v-if="imgUrl">
		<img :src="imgUrl" class="avatar" />
	</div>
	<!-- 图片上传 -->
	<el-upload
		v-else
		action="#"
		class="uploader-avatar"
		list-type="picture"
		:auto-upload="false"
		:show-file-list="false"
		:on-change="imgPreview"
	>
		<el-icon><Plus /></el-icon>
	</el-upload>
</template>
<script lang="ts" setup name="upload-image">
import { ref } from "vue";
import { Plus } from "@element-plus/icons-vue";

const emit = defineEmits(["update:modelValue"]);

const imgUrl = ref("");

const imgPreview = (file: any) => {
	const reader = new FileReader();
	reader.readAsDataURL(file.raw);
	reader.onload = () => {
		imgUrl.value = reader.result as any;
		console.log(imgUrl.value);
		// 触发自定义事件,并将 Base64 编码传递给父组件
		emit("update:modelValue", imgUrl.value);
	};
};
</script>

<style scoped>
.uploader-avatar >>> .el-upload {
	background-color: #fbfdff;
	border: 1px dashed #c0ccda;
	border-radius: 6px;
	box-sizing: border-box;
	width: 148px;
	height: 148px;
	cursor: pointer;
	line-height: 146px;
	vertical-align: top;
	overflow: hidden;
}
.img-show {
	position: relative;
	border: 1px solid #c0ccda;
	border-radius: 6px;
	box-sizing: border-box;
	width: 148px;
	height: 148px;
	cursor: pointer;
	overflow: hidden;
}

.uploader-avatar >>> i {
	font-size: 28px;
	color: #8c939d;
}
.avatar {
	width: 100%;
	height: 100%;
	object-fit: contain;
}
</style>

由于是添加只需要一张图片就可以了,所以使用el-upload自带的自定义缩略图是不行的,因为它会出现让你可以继续上传第二张图片的错误感觉

 所以要自己写div,展示将要上传的图片

<template>
	<!-- 缩略图显示-->
	<div class="img-show" v-if="imgUrl">
		<img :src="imgUrl" class="avatar" />
	</div>
	<!-- 图片上传 -->
	<el-upload
		v-else
		action="#"
		class="uploader-avatar"
		list-type="picture"
		:auto-upload="false"
		:show-file-list="false"
		:on-change="imgPreview"
	>
		<el-icon><Plus /></el-icon>
	</el-upload>
</template>

:auto-upload="false"表示不触发自动上传文件

 :show-file-list="false"表示不展示上传文件的列表

 :on-change="imgPreview"当el-upload组件有图片上传时触发的方法,使用@change也可以

<script lang="ts" setup name="upload-image">
import { ref } from "vue";
import { Plus } from "@element-plus/icons-vue";

const emit = defineEmits(["update:modelValue"]);

const imgUrl = ref("");

const imgPreview = (file: any) => {
	const reader = new FileReader();
	reader.readAsDataURL(file.raw);
	reader.onload = () => {
		imgUrl.value = reader.result as any;
		console.log(imgUrl.value);
		// 触发自定义事件,并将 Base64 编码传递给父组件
		emit("update:modelValue", imgUrl.value);
	};
};
</script>

name="upload-image"必须要写,因为等下我们要将组件暴露出去成为一个公共组件,不然父组件就无法获取到upload-image组件,import是不行的。

const emit = defineEmits(["update:modelValue"]);...emit("update:modelValue", imgUrl.value);也是固定写法,不然父组件就获取不到子组件的传值,这是cool框架规定的,具体可以在cool官网上查资料,我还是贴一下吧

 最后我们还要写一个配置文件暴露upload-image.vue组件

在component文件夹平级目录下创建config.ts文件

import { ModuleConfig } from "/@/cool";

export default (): ModuleConfig => {
	return {
		//注册到全局
		components: [() => import("./component/upload-image.vue")],
	};
};

为什么这样做可以将upload-image.vue变为公共组件,这是cool框架规定的,这个配置文件还可以配置静态路由(静态路由是什么,自己去看视频)进行模块加载时的一些操作等,这是我以前写的,可以参考一下

import { ModuleConfig } from "/@/cool";

export default ():ModuleConfig=>{
  return{
    views:[
      {
        path:'/test',
        meta:{
          label:'test',
          keepAlive:true //开启页面缓存
        },
        component:()=>import('./views/test.vue')
      }
    ],
    pages:[
      {
        path:'/test2',
        meta:{
          label:'test2',
           keepAlive:true //开启页面缓存
        },
        component:()=>import('./pages/test2.vue')
      }
    ],
    //模块加载时
      onLoad(){
        console.log('加载user模块')
      },
      //模块安装时
      install(app,options?){
        //这个时候可以使用app,例如注册组件,使用第三方插件等等
        //console.log(app)
        //注册到全局
        app.component('user-info',UserInfo)
      }
  }
}

接下里我们就可以改造registry.vue文件了

const Upsert = useUpsert({
	items: [
		{
			label: "编码",
			prop: "mid",
			required: true,
			component: { name: "el-input" },
		},
		{
			label: "国家名",
			prop: "eCountry",
			required: true,
			component: { name: "el-input" },
		},
		{
			label: "中文名",
			prop: "cCountry",
			required: true,
			component: { name: "el-input" },
		},
		{ label: "缩写", prop: "abbreviate", component: { name: "el-input" } },
		{
			label: "国旗",
			prop: "flagImg",
			component: {
				name: "upload-image",
			},
		},
	],
});

其它地方都不需要改动,我们就可以存入Base64格式的图片数据了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值