v3.0.6 抽离导出 xlsx 功能,完善一些小细节

This commit is contained in:
ray_wuhao 2023-01-15 21:29:44 +08:00
parent 012c135e19
commit 3d495c047c
13 changed files with 177 additions and 74 deletions

View File

@ -9,4 +9,6 @@ yarn.*
vite-env.*
.prettierrc.*
.eslintrc
visualizer.*
visualizer.*
visualizer.html
.env.*

View File

@ -105,6 +105,9 @@ module.exports = {
'no-var': 'error', // 禁用 `var`
'no-with': 2, // 禁用 `with`
'no-undef': 0,
'use-isnan': 2, // 强制使用 isNaN 判断 NaN
'no-multi-assign': 2, // 禁止连续声明变量
'prefer-arrow-callback': 2, // 强制使用箭头函数作为回调
'vue/multi-word-component-names': [
'off',
{

View File

@ -1,5 +1,10 @@
# `Ray Template`
## 提示
> 项目默认启用严格模式 `eslint`,但是由于 `vite-plugin-eslint` 插件优先级最高,所以如果出现自动导入类型错误提示,请优先解决其他问题。
> 建议开启 `vscode` 保存自动修复功能。
## 前言
> 该项目模板采用 `vue3.x` `vite3.2` `tsx` 进行开发,使用 `naive ui` 作为组件库。意在提供一个简洁、快速上手的模板。
@ -26,13 +31,13 @@
## 拉取依赖
```
```sh
# yarn
yarn
```
```
```sh
# npm
npm install
@ -40,13 +45,13 @@ npm install
## 启动项目
```
```sh
# yarn
yarn dev
```
```
```sh
# npm
npm run dev
@ -54,18 +59,32 @@ npm run dev
## 项目打包
```
```sh
# yarn
yarn build
```
```
```sh
# npm
npm run build
```
## 预览项目
```sh
# yarn
yarn preview
```
```sh
# npm
npm run preview
```
## 项目依赖
- [pinia](https://pinia.vuejs.org/) `全局状态管理器`
@ -79,6 +98,7 @@ npm run build
- [vite-plugin-svg-icons](https://github.com/vbenjs/vite-plugin-svg-icons/blob/main/README.zh_CN.md) `svg雪碧图`
- [echarts5](https://echarts.apache.org/examples/zh/index.html#chart-type-line) `可视化`
- [lodash-es](https://www.lodashjs.com/) `拓展方法`
- 还有一些后续补充的,懒得写了。。。自己看项目依赖页面
## 基础组件

View File

@ -9,8 +9,7 @@ import type { RequestHeaderOptions } from './type'
* @param instance axios instance
* @param options axios headers options
*
* @note
* `axios`
* @remark `axios`
*/
const appendRequestHeaders = (
instance: AxiosRequestConfig<unknown>,
@ -41,7 +40,12 @@ server.interceptors.request.use(
// TODO: 测试环境
}
appendRequestHeaders(request, [{ key: 'X-TOKEN', value: 'token' }]) // 自定义请求头
appendRequestHeaders(request, [
{
key: 'X-TOKEN',
value: 'token',
},
]) // 自定义请求头
return request
},

View File

@ -1,12 +0,0 @@
import type { ExportExcelHeader } from './type'
import type { DataTableColumns } from 'naive-ui'
export const setupExportHeader = (columns: ExportExcelHeader[]) => {
const header = columns.reduce((pre, curr) => {
pre[curr.key] = curr.title
return pre
}, {} as ExportExcelHeader)
return header
}

View File

@ -14,16 +14,15 @@ import { NDataTable, NCard, NDropdown, NDivider } from 'naive-ui'
import TableSetting from './components/TableSetting/index'
import TableAction from './components/TableAction/index'
import dayjs from 'dayjs'
import { utils, writeFileXLSX } from 'xlsx'
import { setupExportHeader } from './hook'
import props from './props'
import print from 'print-js'
import { uuid } from '@use-utils/hook'
import { exportFileToXLSX } from '@use-utils/xlsx'
import type { ActionOptions, ExportExcelHeader } from './type'
import type { ActionOptions } from './type'
import type { WritableComputedRef } from 'vue'
import type { DropdownOption } from 'naive-ui'
import type { ExportExcelHeader } from '@use-utils/xlsx'
const RayTable = defineComponent({
name: 'RayTable',
@ -119,35 +118,16 @@ const RayTable = defineComponent({
*
* `xlsx` , `file save`
*/
const handleExportPositive = () => {
const handleExportPositive = async () => {
if (props.data.length && props.columns.length) {
try {
const exportHeader = setupExportHeader(
await exportFileToXLSX(
props.data,
props.columns as ExportExcelHeader[],
) // 获取所有列(设置为 `excel` 表头)
const sheetData = utils.json_to_sheet(props.data) // 将所有数据转换为表格数据类型
const workBook = utils.book_new()
const filename = props.exportFilename
? props.exportFilename + '.xlsx'
: dayjs(new Date()).format('YYYY-MM-DD') + '导出表格的.xlsx'
utils.book_append_sheet(workBook, sheetData, 'Data')
const range = utils.decode_range(sheetData['!ref'] as string) // 获取所有单元格
/**
*
*
*
* ,
*/
for (let c = range.s.c; c <= range.e.c; c++) {
const header = utils.encode_col(c) + '1'
sheetData[header].v = exportHeader[sheetData[header].v]
}
writeFileXLSX(workBook, filename) // 输出表格
{
filename: props.exportFilename,
},
)
emit('exportSuccess')
} catch (e) {

View File

@ -68,5 +68,3 @@ export declare type VNodeChild = VNodeChildAtom | VNodeArrayChildren
export declare type TableColumnTitle =
| string
| ((column: DataTableBaseColumn) => VNodeChild)
export interface ExportExcelHeader extends DataTableBaseColumn {}

View File

@ -3,7 +3,7 @@
* @param key key
* @param value
*/
export const setCache = <T>(
export const setCache = <T = unknown>(
key: string,
value: T,
type: CacheType = 'sessionStorage',

View File

@ -9,7 +9,7 @@ import BASE64 from 'crypto-js/enc-base64'
* @param message
* @param key key
*
* HmacSHA256
* @remark HmacSHA256
*/
export const useHmacSHA256 = (
message: WordArray | string,
@ -26,7 +26,7 @@ export const useHmacSHA256 = (
*
* @param message
*
* SHA256
* @remark SHA256
*/
export const useSHA256 = (message: WordArray | string) => {
return new Promise((resolve) => {
@ -42,7 +42,7 @@ export const useSHA256 = (message: WordArray | string) => {
* @param key key
* @param cfg
*
* AES
* @remark AES
*/
export const useAESEncrypt = (
message: WordArray | string,
@ -62,7 +62,7 @@ export const useAESEncrypt = (
* @param key key
* @param cfg
*
* AES
* @remark AES
*/
export const useAESDecrypt = (
ciphertext: CipherParams | string,
@ -81,7 +81,7 @@ export const useAESDecrypt = (
* @param message
* @param cfg md5
*
* md5
* @remark md5
*/
export const useMD5 = (message: WordArray | string, cfg?: object) => {
return new Promise((resolve) => {
@ -95,7 +95,7 @@ export const useMD5 = (message: WordArray | string, cfg?: object) => {
*
* @param wordArray base64
*
* base64
* @remark base64
*/
export const useBase64Stringify = (wordArray: WordArray) => {
return new Promise((resolve) => {
@ -109,7 +109,7 @@ export const useBase64Stringify = (wordArray: WordArray) => {
*
* @param str base64
*
* base64
* @remark base64
*/
export const useBase64Parse = (str: string) => {
return new Promise((resolve) => {

View File

@ -30,7 +30,7 @@ export const getElementChildNodes = (
* @param event
* @param handler
*
* @handle
* @remark
*/
export const on = (
element: HTMLElement | Document | Window,
@ -49,7 +49,7 @@ export const on = (
* @param event
* @param handler
*
* @handle
* @remark
*/
export const off = (
element: HTMLElement | Document | Window,
@ -67,7 +67,7 @@ export const off = (
* @param element Target element dom
* @param className className: 'xxx xxx' | 'xxx'
*
* @handle className(: 'xxx xxx' | 'xxx')
* @remark className(: 'xxx xxx' | 'xxx')
*/
export const addClass = (element: HTMLElement, className: string) => {
if (element) {
@ -86,7 +86,7 @@ export const addClass = (element: HTMLElement, className: string) => {
* @param element Target element dom
* @param className className: 'xxx xxx' | 'xxx'
*
* @handle className(: 'xxx xxx' | 'xxx')
* @remark className(: 'xxx xxx' | 'xxx')
*/
export const removeClass = (element: HTMLElement, className: string) => {
if (element) {
@ -107,7 +107,7 @@ export const removeClass = (element: HTMLElement, className: string) => {
*
* @returns boolean
*
* @handle className(: 'xxx xxx' | 'xxx')
* @remark className(: 'xxx xxx' | 'xxx')
*/
export const hasClass = (element: HTMLElement, className: string) => {
const elementClassName = element.className

View File

@ -17,7 +17,7 @@ export const useDetermineEnv = () => {
export const useImagebufferToBase64 = (
data: ArrayBufferLike | ArrayLike<number>,
) => {
const _base64 =
const base64 =
'data:image/png;base64,' +
window.btoa(
new Uint8Array(data).reduce(
@ -26,7 +26,7 @@ export const useImagebufferToBase64 = (
),
)
return _base64
return base64
}
/**
@ -34,10 +34,13 @@ export const useImagebufferToBase64 = (
* @param value
* @param type
*/
export const validteValueType = <T>(value: T, type: ValidteValueType) => {
const _v = Object.prototype.toString.call(value)
export const validteValueType = <T = unknown>(
value: T,
type: ValidteValueType,
) => {
const valid = Object.prototype.toString.call(value)
return _v.includes(type)
return valid.includes(type)
}
/**
@ -61,9 +64,12 @@ export const uuid = (length = 16, radix?: number) => {
} else {
let r
arr[8] = arr[13] = arr[18] = arr[23] = '-'
arr[23] = '-'
arr[18] = arr[23]
arr[13] = arr[18]
arr[8] = arr[13]
arr[14] = '4'
for (i = 0; i < 36; i++) {
if (!arr[i]) {
r = 0 | (Math.random() * 16)

100
src/utils/xlsx.ts Normal file
View File

@ -0,0 +1,100 @@
/**
*
* @author Ray <https://github.com/XiaoDaiGua-Ray>
*
* @date 2023-01-15
*
* @workspace ray-template
*
* @remark
*/
import { utils, writeFileXLSX } from 'xlsx'
import dayjs from 'dayjs'
import type { DataTableBaseColumn } from 'naive-ui'
import type { Range, WorkSheet } from 'xlsx'
export interface ExportExcelHeader extends DataTableBaseColumn {}
export type RowData = Record<string, unknown>
export interface ExportXLSXConfig {
filename?: string
}
/**
*
* @param columns table columns
* @returns
*/
const setupSheetHeader = (columns: ExportExcelHeader[]) => {
const header = columns.reduce((pre, curr) => {
pre[curr.key] = curr.title
return pre
}, {} as ExportExcelHeader)
return header
}
/**
*
* @param range table range
* @param sheetData sheet data
* @param sheetHeader table header
*
* @remark
* @remark ,
*/
const transformSheetHeader = (
range: Range,
sheetData: WorkSheet,
sheetHeader: ExportExcelHeader,
) => {
for (let c = range.s.c; c <= range.e.c; c++) {
const header = utils.encode_col(c) + '1'
sheetData[header].v = sheetHeader[sheetData[header].v]
}
}
/**
*
* @param dataSource
* @param columns
* @param config xlsx
*
* @remark xlsx
* @remark , 使 dataSource
*/
export const exportFileToXLSX = async (
dataSource: RowData[],
columns?: ExportExcelHeader[],
config: ExportXLSXConfig = {},
) => {
await new Promise<void>((resolve, reject) => {
if (dataSource?.length) {
const sheetHeader = setupSheetHeader(columns ?? []) // 获取所有列(设置为 `excel` 表头)
const sheetData = utils.json_to_sheet(dataSource) // 将所有数据转换为表格数据类型
const workBook = utils.book_new()
const filename = config.filename
? config.filename + '.xlsx'
: dayjs().format('YYYY-MM-DD') + '导出表格.xlsx'
utils.book_append_sheet(workBook, sheetData, 'Data')
const range = utils.decode_range(sheetData['!ref'] as string) // 获取所有单元格
if (columns?.length) {
transformSheetHeader(range, sheetData, sheetHeader)
}
writeFileXLSX(workBook, filename) // 输出表格
resolve()
} else {
reject()
}
})
}

View File

@ -76,10 +76,12 @@ export default defineConfig(async ({ mode }) => {
}),
useSVGIcon(),
viteEslintPlugin({
lintOnStart: true, // 构建时自动检查
failOnWarning: true, // 如果含有警告则构建失败
failOnError: true, // 如果有错误则构建失败
cache: true, // 缓存, 减少构建时间
exclude: ['**/node_modules/**', 'vite-env.d.ts'],
include: ['src/**/*.ts', 'src/**/*.vue', 'src/**/*.tsx'],
}),
vitePluginImp({
libList: [