震惊,中石化将开源组件二次封装申请专利,这波操作你怎么看?
文章推荐:
AI 也救不了的前端坑,你遇到过吗?社区、AI、源码三重排查!
10000+ 个点位轻松展示,使用 Leaflet 实现地图海量标记点聚类
一. 前言
昨天看到了一篇关于 “中石化申请基于 vue 的文件上传组件二次封装方法和装置专利,解决文件上传功能开发繁琐问题” 的新闻。
今天特地在专利系统检索了一下,竟然是真的,令人不禁大跌眼镜!用的全是开源组件,最后还把它们变成了自己的专利!这波操作属实厉害啊!
难道以后要用这种方式上传文件,要交专利费了?哈哈....
说来好笑,有掘友指出有单词拼写错误,我又查看一下专利文件,竟然还真有拼写错误...
二. 了解一下
本专利是通过在 vue
页面中自定义 el-upload
组件和 el-progress
组件的使用,解决了文件上传功能开发步骤繁琐和第三方组件无法满足业务需求的问题,实现了简化开发、提高效率和灵活性的效果。
1. 摘要
本发明提供了一种基于 vue 的文件上传组件的二次封装方法和装置,解决了针对于文件上传功能的开发步骤繁琐,复杂,且上传功能的第三方组件无法完全满足业务需求的问题。
该基于 vue
的文件上传组件的二次封装方法包括:在 vue
页面中创建 el‑upload
组件和 el‑progress
组件;
基于所述 el‑upload
组件获取目标上传文件的大小,并判断所述目标上传文件的大小是否符合上传标准;若是,上传所述目标上传文件,并基于所述 el‑progress
组件获取上传进度;上传完成后,对上传的所述目标上传文件进行预处理并存储;
对存储的所述目标上传文件进行封装,并获得 vue
组件。
技术流程图:
二次封装装置模块:
2. 解决的技术问题
现有技术中文件上传功能的开发步骤繁琐复杂,第三方组件无法完全满足业务需求。
3. 采用的技术手段
通过在 vue 页面中引入 el-upload
组件和 el-progress
组件,自定义上传方法和进度条绑定,获取文件大小和上传进度,进行预处理和存储,并将其封装成可重复使用的 vue 组件。
4. 产生的技术功效
简化了文件上传功能的开发步骤,节省了开发时间和效率,避免了代码沉冗,降低了后期维护成本,并提高了文件上传功能的灵活性。
三. 实现一下
这种简单的上传文件+上传进度显示不是最基本的业务封装吗?相信这是每个前端开发工程师必备的基础技能。
1. el-upload + el-progress 组合
- el-upload 负责文件选择、上传。
- el-progress 负责展示上传进度。
2. 文件大小校验
- 使用 el-upload 的
before-upload
钩子,判断文件大小是否符合标准。
3. 上传进度获取
- 使用 el-upload 的
on-progress
钩子,实时更新进度条。
4. 上传完成后的预处理与存储
- 上传完成后,触发自定义钩子(如
beforeStore
、onStore
),进行预处理和存储。
5. 封装为 Vue 组件
- 通过 props、emits、插槽等方式,暴露灵活的接口,便于业务页面集成。
都懒得自己动手,让 Cursor
来实现一下。Cursor
还是一如既往的强大,基本上一次询问就能成功!我表示 Cursor
在手,天下我有!
UploaderWrapper
自定义组件:
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { ElButton, ElMessage, ElProgress, ElUpload } from 'element-plus';
interface UploadProps {
maxSize?: number; // MB
action: string;
accept?: string;
beforeStore?: (file: File) => Promise<File>;
onStore?: (file: File) => Promise<void>;
onError?: (error: Error) => void;
showFileList?: boolean;
multiple?: boolean;
limit?: number;
}
const props = withDefaults(defineProps<UploadProps>(), {
maxSize: 10,
accept: '*',
beforeStore: async (file: File) => file,
onStore: async () => {},
onError: () => {},
showFileList: true,
multiple: false,
limit: 1,
});
const emit = defineEmits<{
(e: 'uploadSuccess', file: File): void;
(e: 'uploadError', error: Error): void;
}>();
const uploadPercent = ref(0);
const uploading = ref(false);
const fileList = ref<any[]>([]);
const isUploading = computed(() => uploading.value);
function handleExceed(files: File[]) {
ElMessage.warning(`最多只能上传 ${props.limit} 个文件`);
}
function beforeUpload(file: File) {
const isLtMax = file.size / 1024 / 1024 < props.maxSize;
if (!isLtMax) {
ElMessage.error(`文件大小不能超过 ${props.maxSize}MB!`);
return false;
}
if (props.accept !== '*') {
const extension = file.name.split('.').pop()?.toLowerCase();
const acceptTypes = props.accept.split(',').map((type) => type.trim());
const isValidType = acceptTypes.some((type) => {
if (type.startsWith('.')) {
return `.${extension}` === type;
}
return file.type.startsWith(type);
});
if (!isValidType) {
ElMessage.error(`只能上传 ${props.accept} 格式的文件!`);
return false;
}
}
return true;
}
function handleProgress(event: any) {
uploading.value = true;
uploadPercent.value = Math.round(event.percent);
}
async function handleSuccess(response: any, file: any) {
try {
uploading.value = false;
uploadPercent.value = 100;
// 预处理
const processedFile = await props.beforeStore(file.raw);
// 存储
await props.onStore(processedFile);
ElMessage.success('上传并处理成功');
emit('uploadSuccess', processedFile);
} catch (error) {
handleError(error as Error);
}
}
function handleError(error: Error) {
uploading.value = false;
uploadPercent.value = 0;
ElMessage.error('上传失败');
props.onError(error);
emit('uploadError', error);
}
function handleRemove(file: any) {
const index = fileList.value.indexOf(file);
if (index !== -1) {
fileList.value.splice(index, 1);
}
}
</script>
<template>
<div class="file-uploader">
<ElUpload
:action="action"
:before-upload="beforeUpload"
:on-progress="handleProgress"
:on-success="handleSuccess"
:on-error="handleError"
:limit="limit"
:on-exceed="handleExceed"
:show-file-list="showFileList"
:multiple="multiple"
:accept="accept"
v-model:file-list="fileList"
:on-remove="handleRemove"
>
<template #trigger>
<ElButton type="primary"> 选择文件上传 </ElButton>
</template>
<template #tip>
<div class="el-upload__tip">
支持的文件类型: {{ accept }},单个文件不超过 {{ maxSize }}MB
</div>
</template>
</ElUpload>
<ElProgress
v-if="isUploading"
:percentage="uploadPercent"
:status="uploadPercent === 100 ? 'success' : ''"
class="mt-4"
/>
</div>
</template>
<style scoped>
.file-uploader {
width: 100%;
}
.el-upload__tip {
font-size: 12px;
color: #606266;
margin-top: 8px;
}
</style>
使用方式:
<script lang="ts" setup>
import { ElCard } from 'element-plus';
import UploaderWrapper from './UploaderWrapper.vue';
const beforeStore = async (file: File) => {
// 这里可以做预处理,比如图片压缩、格式转换等
return file;
};
const onStore = async (file: File) => {
// 这里可以做存储,比如保存到本地等
// 处理存储逻辑
};
</script>
<template>
<ElCard class="mb-5 w-80">
<template #header> 文件上传演示 </template>
<UploaderWrapper
action="/api/upload"
:max-size="5"
:before-store="beforeStore"
:on-store="onStore"
/>
</ElCard>
</template>
效果如下所示:
声明:“代码仅供演示,不要使用,以免有专利侵权风险,慎重!”
四. 思考一下
从开发者的角度来看,这个专利事件是否能给我们带来了一些值得思考影响和启示:
- 技术创新的边界问题
- 使用开源组件进行二次封装是否应该被授予专利?
- 是否对开源社区的发展可能产生负面影响?
- 对日常开发的影响
- 如果专利获得授权,其他公司使用类似的文件上传组件封装方案是否可能面临法律风险?
- 开发者是否需要寻找替代方案或支付专利费用?
- 对开源社区的影响
- 可能打击开发者对开源项目的贡献热情,自己辛苦开源项目为别人做了嫁衣?
- 是否会影响开源组件的使用和二次开发
- 可能导致更多公司效仿,将开源组件的二次封装申请专利,因为毕竟专利对公司的招投标挺大的
五. 后记
“中石化作为传统能源企业,都能积极拥抱前端技术,还将内部技术方案申请专利,体现了他们对知识产权的重视?”
那我们是不是要在技术创新和知识产权保护之间找到平衡点,既要保护创新,又不能阻碍技术的发展。
而作为开发者的我们呢?这么简单的封装都能申请专利成功的话,那么...,大家有什么想法,是不是现在强的可怕?哈哈...
专利来源于国家知识产权局
申请公布号:CN120122937A
来源:juejin.cn/post/7514858513442078754