From 8e153577efe04fba7b0db8bee087cf1513e87b42 Mon Sep 17 00:00:00 2001 From: Linzp Date: Thu, 22 Jan 2026 11:34:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0markdown=E9=A2=84=E8=A7=88?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 37 +++ doc/api.md | 12 + doc/example.json | 19 ++ doc/markdown-preview.js | 17 ++ package.json | 7 +- ...72\344\276\213\346\217\217\350\277\260.md" | 1 + ...37\346\210\220\346\226\207\346\241\243.md" | 1 + ...20\350\257\255\350\250\200\345\214\205.md" | 1 + ...72\344\276\213\347\274\226\345\206\231.md" | 282 ++++++++++++++++++ src/components/FilePreview/MarkdownPreview.js | 58 ++++ src/components/FilePreview/index.js | 1 + src/components/FilePreview/style.module.scss | 55 ++++ src/components/FilePreview/typeFormat.js | 5 + src/index.js | 2 +- template-libs-example/public/mock/example.md | 124 ++++++++ 15 files changed, 618 insertions(+), 4 deletions(-) create mode 100644 doc/markdown-preview.js create mode 100644 "prompts/\345\221\275\345\220\215\347\244\272\344\276\213\347\274\226\345\206\231\347\244\272\344\276\213\346\217\217\350\277\260.md" create mode 100644 "prompts/\347\224\237\346\210\220\346\226\207\346\241\243.md" create mode 100644 "prompts/\347\224\237\346\210\220\350\257\255\350\250\200\345\214\205.md" create mode 100644 "prompts/\347\273\204\344\273\266\347\244\272\344\276\213\347\274\226\345\206\231.md" create mode 100644 src/components/FilePreview/MarkdownPreview.js create mode 100644 template-libs-example/public/mock/example.md diff --git a/README.md b/README.md index 3e705de..dd84e43 100644 --- a/README.md +++ b/README.md @@ -471,6 +471,31 @@ render(); ``` +- MarkdownPreview +- Markdown文件预览 +- _ReactFile(@kne/current-lib_react-file)[import * as _ReactFile from "@kne/react-file"],(@kne/current-lib_react-file/dist/index.css),remoteLoader(@kne/remote-loader) + +```jsx +const { MarkdownPreview } = _ReactFile; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +const BaseExample = createWithRemoteLoader({ + modules: ['components-core:InfoPage'] +})(({ remoteModules }) => { + const [InfoPage] = remoteModules; + return ( + + + + + + ); +}); + +render(); + +``` + ### API @@ -489,6 +514,18 @@ render(); | maxSize | number | - | 单个文件最大尺寸(字节) | | children | ReactNode | - | 自定义上传按钮内容 | +### MarkdownPreview + +Markdown文件预览组件,支持渲染Markdown格式的文档。 + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|------|------|-------|------| +| url | string | - | Markdown文件的URL地址 | +| className | string | - | 自定义容器类名 | +| maxWidth | string/number | - | 容器最大宽度 | + ### FilePreview 文件预览组件,支持多种文件格式的预览。 diff --git a/doc/api.md b/doc/api.md index a0ccf72..8e8d9d9 100644 --- a/doc/api.md +++ b/doc/api.md @@ -13,6 +13,18 @@ | maxSize | number | - | 单个文件最大尺寸(字节) | | children | ReactNode | - | 自定义上传按钮内容 | +### MarkdownPreview + +Markdown文件预览组件,支持渲染Markdown格式的文档。 + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|------|------|-------|------| +| url | string | - | Markdown文件的URL地址 | +| className | string | - | 自定义容器类名 | +| maxWidth | string/number | - | 容器最大宽度 | + ### FilePreview 文件预览组件,支持多种文件格式的预览。 diff --git a/doc/example.json b/doc/example.json index 51de018..6d7351e 100644 --- a/doc/example.json +++ b/doc/example.json @@ -157,6 +157,25 @@ "packageName": "@kne/remote-loader" } ] + }, + { + "title": "MarkdownPreview", + "description": "Markdown文件预览", + "code": "./markdown-preview.js", + "scope": [ + { + "name": "_ReactFile", + "packageName": "@kne/current-lib_react-file", + "importStatement": "import * as _ReactFile from \"@kne/react-file\"" + }, + { + "packageName": "@kne/current-lib_react-file/dist/index.css" + }, + { + "name": "remoteLoader", + "packageName": "@kne/remote-loader" + } + ] } ] } diff --git a/doc/markdown-preview.js b/doc/markdown-preview.js new file mode 100644 index 0000000..a20dd96 --- /dev/null +++ b/doc/markdown-preview.js @@ -0,0 +1,17 @@ +const { MarkdownPreview } = _ReactFile; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +const BaseExample = createWithRemoteLoader({ + modules: ['components-core:InfoPage'] +})(({ remoteModules }) => { + const [InfoPage] = remoteModules; + return ( + + + + + + ); +}); + +render(); diff --git a/package.json b/package.json index 589542c..add5dc0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kne/react-file", - "version": "0.1.30", + "version": "0.1.31", "description": "提供了文件上传,文件预览,文件批量管理等功能", "syntax": { "esmodules": true @@ -90,11 +90,12 @@ "@ant-design/icons": "^5.5.1", "@kne/button-group": "^0.1.3", "@kne/create-deferred": "^0.1.0", - "@kne/global-context": "^1.1.2", + "@kne/global-context": "^1.3.2", "@kne/iframe-resizer": "^0.1.3", + "@kne/markdown-components-render": "^0.1.8", "@kne/react-fetch": "^1.5.5", "@kne/react-file-type": "^1.0.7", - "@kne/react-intl": "^0.1.6", + "@kne/react-intl": "^0.1.12", "@kne/use-control-value": "^0.1.8", "@kne/use-ref-callback": "^0.1.2", "@kne/use-resize": "^0.1.1", diff --git "a/prompts/\345\221\275\345\220\215\347\244\272\344\276\213\347\274\226\345\206\231\347\244\272\344\276\213\346\217\217\350\277\260.md" "b/prompts/\345\221\275\345\220\215\347\244\272\344\276\213\347\274\226\345\206\231\347\244\272\344\276\213\346\217\217\350\277\260.md" new file mode 100644 index 0000000..96ca14b --- /dev/null +++ "b/prompts/\345\221\275\345\220\215\347\244\272\344\276\213\347\274\226\345\206\231\347\244\272\344\276\213\346\217\217\350\277\260.md" @@ -0,0 +1 @@ +根据doc/example.json中code引用的代码实现内容完善doc/example.json中的title和description字段 \ No newline at end of file diff --git "a/prompts/\347\224\237\346\210\220\346\226\207\346\241\243.md" "b/prompts/\347\224\237\346\210\220\346\226\207\346\241\243.md" new file mode 100644 index 0000000..99d1a29 --- /dev/null +++ "b/prompts/\347\224\237\346\210\220\346\226\207\346\241\243.md" @@ -0,0 +1 @@ +根据代码帮我完成项目概述输出到doc/summary.md,api文档输出到doc/api.md markdown不要使用h1,h2对应的标签,doc/summary.md不需要项目概述标题,不需要依赖项说明,可以适当描述一下项目的特点吸引用户使用,doc/api.md不需要API文档标题,使用h3及之后,api文档优先使用table格式,api部分不需要示例代码,请严格遵守格式要求 \ No newline at end of file diff --git "a/prompts/\347\224\237\346\210\220\350\257\255\350\250\200\345\214\205.md" "b/prompts/\347\224\237\346\210\220\350\257\255\350\250\200\345\214\205.md" new file mode 100644 index 0000000..1aafab8 --- /dev/null +++ "b/prompts/\347\224\237\346\210\220\350\257\255\350\250\200\345\214\205.md" @@ -0,0 +1 @@ +将代码中的中文文案抽取到src/locale/zh-CN.js中,输入一个locale对象,locale对象中为key和文案的键值对,然后再翻译到en-US.js中,不要修改原始文件的任何内容 \ No newline at end of file diff --git "a/prompts/\347\273\204\344\273\266\347\244\272\344\276\213\347\274\226\345\206\231.md" "b/prompts/\347\273\204\344\273\266\347\244\272\344\276\213\347\274\226\345\206\231.md" new file mode 100644 index 0000000..f6f8c3f --- /dev/null +++ "b/prompts/\347\273\204\344\273\266\347\244\272\344\276\213\347\274\226\345\206\231.md" @@ -0,0 +1,282 @@ +# 组件示例编写提示词 + +本提示词用于编写遵循特定目录结构规范的 React 项目组件示例。 + +## 1. 目录结构规范 + +### 项目目录布局 + +``` +{PROJECT_ROOT}/ +├── src/ # 源代码目录 +│ └── components/ # 组件源代码 +│ ├── ComponentA/ # 单个组件目录 +│ ├── ComponentB/ # 带子组件的目录 +│ │ ├── Sub1/ +│ │ ├── Sub2/ +│ │ └── index.js +│ └── ... +├── doc/ # 文档及示例目录(所有组件共用) +│ ├── example.json # 示例配置文件(核心) +│ ├── api.md # 组件API文档 +│ ├── summary.md # 组件简要描述 +│ ├── base.js # 基础示例代码 +│ ├── component-a.js # ComponentA示例 +│ ├── component-b.js # ComponentB主组件示例 +│ ├── component-b-sub1.js # ComponentB子组件Sub1示例 +│ ├── component-b-sub2.js # ComponentB子组件Sub2示例 +│ └── style.scss # 示例样式(可选) +└── package.json # 项目配置文件 +``` + +### 示例文件规则 + +**重要**:所有组件的示例文件都统一放在项目根目录的 `doc/` 中,而不是在每个组件目录下创建单独的 `doc/` 目录。 + +- 单个组件:使用组件名的小写短横线形式命名示例文件,如 `component-a.js` +- 带子组件的组件:主组件示例使用组件名,子组件示例使用组件名加子组件名,如 `component-b.js`、`component-b-sub1.js` + +### 项目配置变量 + +在编写示例时需要替换以下变量: + +| 变量名 | 说明 | 示例值 | +|--------|------|--------| +| `{PACKAGE_NAME}` | 从 package.json 的 name 字段获取 | `@kne/react-file` | +| `{PROJECT_NAME}` | 项目名称,用于 getPublicPath | `react-file` | +| `{LIB_NAME}` | 组件库名称,通常是驼峰形式 | `ReactFile` | + +## 2. example.json 配置结构 + +所有组件的示例配置统一在 `doc/example.json` 中管理: + +```json +{ + "isFull": true, + "list": [ + { + "title": "ComponentA", + "description": "组件A的描述", + "code": "./component-a.js", + "scope": [ + { + "name": "_{LIB_NAME}", + "packageName": "{PACKAGE_NAME}", + "importStatement": "import * as _{LIB_NAME} from \"{PACKAGE_NAME}\"" + }, + { + "packageName": "{PACKAGE_NAME}/dist/index.css" + }, + { + "name": "antd", + "packageName": "antd" + }, + { + "name": "remoteLoader", + "packageName": "@kne/remote-loader" + } + ] + }, + { + "title": "ComponentB", + "description": "组件B主组件", + "code": "./component-b.js", + "scope": [] + }, + { + "title": "ComponentB-Sub1", + "description": "组件B子组件Sub1", + "code": "./component-b-sub1.js", + "scope": [] + } + ] +} +``` + +## 3. 示例代码规范 + +### 导入方式 + +- 使用 `scope` 中声明的变量名:`const { FilePreview } = _{LIB_NAME};` +- 工具包引用:`const { createWithRemoteLoader, getPublicPath } = remoteLoader;` + +### 标准示例模板(需要 PureGlobal 模拟数据) + +```javascript +const { YourComponent } = _{LIB_NAME}; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +const BaseExample = createWithRemoteLoader({ + modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage'] +})(({ remoteModules }) => { + const [PureGlobal, InfoPage] = remoteModules; + return ( + { + return { data: { code: 0, data: api.loader() } }; + }, + apis: { + file: { + staticUrl: getPublicPath('{PROJECT_NAME}') || window.PUBLIC_URL, + getUrl: { + loader: async ({ params }) => { + // 模拟数据 + return 'mock-url'; + } + } + } + } + }}> + + + + + + + ); +}); + +render(); +``` + +### 简化示例模板(无需远程加载) + +```javascript +const { YourComponent } = _{LIB_NAME}; +const { Flex, Switch } = antd; +const { useState } = React; + +const BaseExample = () => { + const [state, setState] = useState(false); + return ( + + + + ); +}; + +render(); +``` + +## 4. scope 依赖声明规则 + +| 场景 | name | packageName | importStatement(可选) | +|------|------|-------------|------------------------| +| 项目组件 | `_{LIB_NAME}` | `{PACKAGE_NAME}` | `import * as _{LIB_NAME} from "{PACKAGE_NAME}"` | +| 样式文件 | - | `{PACKAGE_NAME}/dist/index.css` | - | +| 远程加载器 | `remoteLoader` | `@kne/remote-loader` | - | +| Antd组件 | `antd` | `antd` | - | +| React原生 | `React` | - | -(无需声明) | + +## 5. API文档编写 + +`doc/api.md` 中包含所有组件的API文档,使用表格格式: + +```markdown +### 组件名称 + +组件描述 + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|------|------|-------|------| +| propName | string | - | 属性描述 | +``` + +## 6. 数据模拟 + +在示例中使用 PureGlobal 的 preset 模拟数据: + +```javascript +apis: { + file: { + staticUrl: getPublicPath('{PROJECT_NAME}') || window.PUBLIC_URL, + getUrl: { + loader: async ({ params }) => { + // 根据 params 返回对应的 mock 数据 + const urlMap = { + 1: '/mock/example.png', + 2: '/mock/example.pdf' + }; + return new Promise(resolve => { + setTimeout(() => { + resolve(urlMap[params.id]); + }, 500); + }); + } + } + } +} +``` + +## 7. 组件导出规范 + +在组件的主入口 `index.js` 中,需要导出所有子组件: + +```javascript +export { default } from './MainComponent'; +export { default as SubComponent1 } from './SubComponent1'; +export { default as SubComponent2 } from './SubComponent2'; +``` + +在示例中通过解构引用: + +```javascript +const { MainComponent, SubComponent1, SubComponent2 } = _{LIB_NAME}; +``` + +## 8. 使用说明 + +### 创建新组件示例步骤 + +1. 在 `src/components/` 下创建或编辑组件 +2. 在 `doc/example.json` 中添加示例配置 +3. 在 `doc/` 目录下创建对应的 `.js` 示例文件 +4. 在 `doc/api.md` 中添加组件API文档(如果是新组件) +5. 在组件的 `index.js` 中确保正确导出 + +### 变量替换示例 + +假设项目 `package.json` 中配置为: + +```json +{ + "name": "@your-org/your-project" +} +``` + +则变量值为: + +- `{PACKAGE_NAME}` → `@your-org/your-project` +- `{PROJECT_NAME}` → `your-project` +- `{LIB_NAME}` → `YourProject` + +实际使用时需要替换为: + +```json +{ + "name": "_YourProject", + "packageName": "@your-org/your-project", + "importStatement": "import * as _YourProject from \"@your-org/your-project\"" +} +``` + +```javascript +const { YourComponent } = _YourProject; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +// ... +staticUrl: getPublicPath('your-project') || window.PUBLIC_URL, +``` + +## 9. 项目参考 + +本项目的示例文件位于 `doc/` 目录: + +- `doc/example.json` - 所有组件的示例配置 +- `doc/api.md` - 所有组件的API文档 +- `doc/preview.js` - FilePreview 组件示例(包含多种预览类型) +- `doc/file-list.js` - FileList 组件示例 +- `doc/download.js` - Download 组件示例 +- `doc/markdown-preview.js` - MarkdownPreview 组件示例 diff --git a/src/components/FilePreview/MarkdownPreview.js b/src/components/FilePreview/MarkdownPreview.js new file mode 100644 index 0000000..c604f16 --- /dev/null +++ b/src/components/FilePreview/MarkdownPreview.js @@ -0,0 +1,58 @@ +import React, { useState, useEffect } from 'react'; +import { getAjax } from '@kne/react-fetch'; +import style from './style.module.scss'; +import { Spin } from 'antd'; +import classnames from 'classnames'; +import { createWithIntlProvider, useIntl } from '@kne/react-intl'; +import MarkdownRender from '@kne/markdown-components-render'; +import zhCn from '../../locale/zh-CN'; + +const MarkdownPreview = createWithIntlProvider( + 'zh-CN', + zhCn, + 'react-file' +)(({ url, className, maxWidth, ...props }) => { + const { formatMessage } = useIntl(); + const [text, setText] = useState(''); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + useEffect(() => { + const ajax = getAjax(); + ajax({ url, method: 'GET' }).then( + ({ data }) => { + setText(data); + setLoading(false); + }, + () => { + setLoading(false); + setError(true); + } + ); + }, [url]); + + return ( +
+ {loading ? ( +
+ +
+ ) : null} +
+ {error ? ( +
{formatMessage({ id: 'fileLoadedError' })}
+ ) : ( +
+ {text} +
+ )} +
+
+ ); +}); + +export default MarkdownPreview; diff --git a/src/components/FilePreview/index.js b/src/components/FilePreview/index.js index ec54f87..d2e64f1 100644 --- a/src/components/FilePreview/index.js +++ b/src/components/FilePreview/index.js @@ -8,4 +8,5 @@ export { default as OfficePreview } from './OfficePreview'; export { default as OSSFilePreview } from './OSSFilePreview'; export { default as AudioPreview } from './AudioPreview'; export { default as VideoPreview } from './VideoPreview'; +export { default as MarkdownPreview } from './MarkdownPreview'; export { default as typeFormat, typeComponentMapping } from './typeFormat'; diff --git a/src/components/FilePreview/style.module.scss b/src/components/FilePreview/style.module.scss index b1c3833..e55043b 100644 --- a/src/components/FilePreview/style.module.scss +++ b/src/components/FilePreview/style.module.scss @@ -109,6 +109,61 @@ text-align: left; } +.md-inner { + background: #ffffff; + padding: 20px; + + table { + width: 100%; + margin: 8px 0 16px; + empty-cells: show; + border: 1px solid #ebedf0; + border-collapse: collapse; + border-spacing: 0; + + th { + color: #5c6b77; + font-weight: 500; + white-space: nowrap; + background: rgba(0, 0, 0, 0.02); + } + + th, + td { + padding: 16px 24px; + text-align: left; + border: 1px solid #ebedf0; + } + + td:first-child { + color: #595959; + font-weight: 600; + } + + td:nth-child(3) { + color: #c41d7f; + } + } + + pre { + background: #f2f4f5; + word-wrap: break-word; + white-space: pre-wrap; + padding: 0.2em 0.4em; + font-size: 0.9em; + border: 1px solid #eee; + border-radius: 3px; + } + + code { + background: #f2f4f5; + } + + p { + margin: 0; + } +} + .image-inner { background: #ffffff; display: block; diff --git a/src/components/FilePreview/typeFormat.js b/src/components/FilePreview/typeFormat.js index 6e84a6c..a1f4c33 100644 --- a/src/components/FilePreview/typeFormat.js +++ b/src/components/FilePreview/typeFormat.js @@ -6,6 +6,7 @@ import UnknownPreview from './UnknownPreview'; import ImagePreview from './ImagePreview'; import AudioPreview from './AudioPreview'; import VideoPreview from './VideoPreview'; +import MarkdownPreview from './MarkdownPreview'; const typeFormat = url => { const path = (url || '').split('?')[0]; @@ -13,6 +14,9 @@ const typeFormat = url => { if (/.txt$/.test(_path)) { return 'txt'; } + if (/.md$/.test(_path)) { + return 'markdown'; + } if (/.pdf$/.test(_path)) { return 'pdf'; } @@ -38,6 +42,7 @@ export default typeFormat; export const typeComponentMapping = { txt: TextPreview, + markdown: MarkdownPreview, pdf: PdfPreview, image: ImagePreview, html: HtmlPreview, diff --git a/src/index.js b/src/index.js index d5afbe8..d71e1c7 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ export { default } from './components/File'; export { default as Download, useDownload, download, downloadBlobFile } from './components/Download'; -export { default as FilePreview, HtmlPreview, PdfPreview, TextPreview, ImagePreview, UnknownPreview, OfficePreview, OSSFilePreview, AudioPreview, VideoPreview } from './components/FilePreview'; +export { default as FilePreview, HtmlPreview, PdfPreview, TextPreview, MarkdownPreview, ImagePreview, UnknownPreview, OfficePreview, OSSFilePreview, AudioPreview, VideoPreview } from './components/FilePreview'; export { default as FileButton, useFileModalProps, useFileModal, FileModal } from './components/FileButton'; export { default as Image } from './components/Image'; export { default as PrintButton } from './components/PrintButton'; diff --git a/template-libs-example/public/mock/example.md b/template-libs-example/public/mock/example.md new file mode 100644 index 0000000..c4c4b6f --- /dev/null +++ b/template-libs-example/public/mock/example.md @@ -0,0 +1,124 @@ +# 候选人X + +女 | 29岁 ![](/api/v1/static/file-id/8cc2381e-56fe-42d5-8f4b-eafb1f33b73a) +15221260000 ![](/api/v1/static/file-id/99032a4a-3cf9-4c1b-a521-797ecb365cfa) xxx@sina.com + +5年工作经验 | 前端开发工程师 | 期望薪资: 19-22K | 期望城市: 上海 + +## 个人优势 + +熟练使用 Vue 框架,拥有独立开发 PC 项目的能力 + +熟练微信公众号h5项目开发,如直播h5/抽奖h5 + +熟练使用 uniapp 开发微信小程序,如云课表,熟悉开发过钉钉小程序 + +熟练使用 DataV+Echarts 开发可视化大屏项目 + +熟练 Es6, `Vux, Less, Sass` 在项目中的使用 + +掌握 Element, ant-design, Vant, uView 框架的使用 + +掌握 HTML 5和 CSS 3新特性及动画 + +熟悉了解webpack 等前端自动化构建工具 + +掌握vue-cli 脚手架搭建项目及其后期配置 + +熟悉Vue3 搭建并开发项目 + +熟悉百度/高德地图 api 运用定位/画线/标记 + +掌握 html2canvas 绘制海报/截图以及腾讯云视频的接入 + +掌握微信 (JsApi) 支付/支付宝支付 + +熟悉摄像头/胸卡/床卡/手表等硬件接入 + +熟悉jeecboot及可视化大屏等低代码平台 + +## 工作经历 + +上海学威教育科技有限公司 前端开发工程师 + +2022.08-2023.02 + +### 内容: + +参与项目的原型讨论与前期规划,完成前端框架的搭建/难点分析与技术研发工作 + +还原 UI 设计稿的交互实现以及与后端人员进行接口的对接 + +封装通用组件/公共方法,持续优化前端交互体验加快页面响应速度 + +负责的项目板块: + +负责云课表小程序项目清单管理/推广/直播相关页/邀请海报页/我的等功能板块的开发及后期的版本迭代功能的开发及维护 + +负责h5项目会员卡/专栏/体验课/研修班从商品页到购买到学习/试听等一系列流程的开发;此外还包括活动推广/清单管理/海报邀请等板块的开发及版本迭代 + +后管项目的维护及日常更新 + +### 内容: + +参与需求评审,与项目经理,产品经理,后端等开发人员等进行项目细节的讨论 + +负责 PC 系统/小程序/大屏项目的开发及需求更新维护 + +通用组件封装,提升开发效率和质量 + +根据项目业务需求,优化底层框架整体架构,完善项目方案 + +前端代码的发版留存,日常维护更新 + +配合市场部实时解决一些临时性问题 + +参与制定代码规范、前端开发流程等规范性文件 + +## 专业技能 + +熟练使用 Vue框架,拥有独立开发项目的能力 + +熟练微信小程序的开发,熟悉开发过钉钉小程序 + +熟练使用DataV+Echarts开发可视化大屏项目 + +掌握 Element, ant-design,Vant,uView 框架的使用 + +熟练微信公众号授权h5项目开发,如直播h5/抽奖h5 + +熟练 Es6,Vux,Less,Sass 在项目中的使用 + +掌握百度/高德地图api运用定位/画线 + +熟悉Vue3搭建并开发项目 + +掌握 HTML5和 CSS3新特性 + +熟悉了解webpack等前端自动化构建工具 + +掌握 html2canvas 绘制海报以及腾讯云视频的接入 + +掌握 Navicat,Git,SVN,FTP工具使用 + +掌握PS等图像处理软件进行快速切图,修改 + +掌握微信(JsApi)支付/支付宝支付 + +熟悉摄像头/胸卡/床卡/手表等硬件接入 + +熟悉jecboot及可视化大屏等低代码平台 + +## 资格证书 + +大学英语四级 计算机二级 h3c网络工程师 + +![](/api/v1/static/file-id/15435424-30a0-457e-a32c-60e68207ae67) + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|---------------|-----------|-----|----------| +| onBeforePrint | function | - | 打印前的回调函数 | +| onAfterPrint | function | - | 打印后的回调函数 | +| children | ReactNode | - | 按钮内容 | \ No newline at end of file