【kk-utils】Excel工具——excel-js

前言

kk-utils 是一款我自己基于这几年开发封装出来的前端工具库

excel-js

excel-jskk-utils里的工具之一(1.2.0版本开始支持),其作用是有多个针对导出导出的方法函数,是我在写项目时积累下来的,几乎可以覆盖日常所需

这个工具是基于GitHub上开源的exceljs的代码,基于此工具库的基础上进行二次封装适合我业务的功能

使用方法

安装

js 复制代码
npm install kk-utils-library -S
pnpm add kk-utils-library -S

可用方法

importExcel

导入Excel

js 复制代码
importExcel(File, [options])
  • File:要导入的Excel文件
  • options:配置项,可选,对象类型
    • allWorksheets:boolean,是否导入所有工作表,无论true还是false,返回的结果都是二维数组,默认为false
    • getValue:(cell) => string,获取单元格的文本值,默认为(cell) => cell.text
    • headerStartLine:number,表头开始行数,默认1开始
    • headerTotalLine:number,表头总行数,默认1
    • toJsonArray:boolean,是否转换成JSON格式,默认true
      • false:则返回的数据是[[key, key, key], [value, value, value], [value,value,value]]这种格式
      • true:则返回的数据是[{key, value}, {key, value}, {key, value}]这种格式
html 复制代码
<input type="file" id="file" accept=".xlsx" />
<button id="import">导入所选文件</button>

这是我要导入的Excel文件,第一行就是表头,总共一行表头,所以使用默认的headerStartLine和headerTotalLine就可以了,如果是多行表头或者开始不是第一行则自行调整或者传入对应参数

js 复制代码
import { importExcel } from 'kk-utils-library/excel-js';

const fileInput = document.getElementById('file');
const importButton = document.getElementById('import');
importButton.addEventListener('click', () => {
  const file = fileInput.files[0];
  if (!file) {
    alert('请选择文件');
    return;
  }
  importExcel(file, {
    headerStartLine: 1,
    headerTotalLine: 1
  }).then((data) => {
    console.log('data', data);
    // [
    //   [
    //     {
    //       操作类型: '新增',
    //       客户名称: '测试1',
    //       客户编码: 'TEST001',
    //       客户类型: '供应商',
    //       省: '辽宁省',
    //       市: '沈阳市',
    //       区: '辽中县'
    //     },
    //     {
    //       操作类型: '修改',
    //       客户名称: '测试2',
    //       客户编码: 'TEST002',
    //       客户类型: '客户',
    //       省: '山西省',
    //       市: '太原市',
    //       区: '晋源区'
    //     },
    //     {
    //       操作类型: '删除',
    //       客户名称: '测试3',
    //       客户编码: 'TEST003',
    //       客户类型: '客户与供应商',
    //       省: '吉林省',
    //       市: '长春市',
    //       区: '宽城区'
    //     },
    //     {
    //       操作类型: '不变',
    //       客户名称: '测试4',
    //       客户编码: 'TEST004',
    //       客户类型: '供应商',
    //       省: '湖南省',
    //       市: '长沙市',
    //       区: '雨花区'
    //     }
    //   ]
    // ];
  });
});

exportExcel

导出Excel

js 复制代码
exportExcel([options])
  • filename:导出的文件名,默认为excel
  • sheets:object[],要导出的工作表
    • sheetName:string,表名,默认为SheetJS[index + 1]
    • withDefaultStyle:boolean,携带默认样式,默认true,全局默认样式可通过setGlobalDefaultStyle()配置
    • adaptiveWidth:boolean,自适应列宽,默认true
    • adaptiveWidthOptions:object,自适应列宽配置项
      • minWidth:number,最小列宽,默认5
      • maxWidth:number,最大列宽,默认50
      • interstice:number,列宽额外空隙,默认5
      • ignoreLines:number[],计算列宽忽略的行,因为有些行会有合并单元格的操作,这样会导致合并行的列度最大并使用合并行的列宽作为整列的宽,所以可以传入合并行的行数来进行列宽计算忽略
    • processing:(worksheet) => void,对工作表对象做操作处理,这个是在自动列宽和默认样式之前执行的
    • extraProcessing:(worksheet) => void,对工作表对象做操作额外处理,这个是在自动列宽和默认样式之后执行的
  • processing:(workbook) => void,对Excel对象做操作处理
html 复制代码
<button id="export">导出测试文件</button>
js 复制代码
import { exportExcel } from 'kk-utils-library/excel-js';

const exportButton = document.getElementById('export');
exportButton.addEventListener('click', () => {
  const data = [
    ['姓名', '年龄', '性别'],
    ['张三', 18, '男'],
    ['李四', 19, '女'],
    ['王五', 20, '男']
  ];
  exportExcel({
    filename: 'test',
    sheets: [
      {
        processing: (worksheet) => {
          worksheet.addRows(data);
        },
        extraProcessing: (worksheet) => {
          _merge(worksheet.getRow(1), {
            fill: {
              type: 'pattern',
              pattern: 'solid',
              fgColor: {
                argb: 'FF99CCFF'
              }
            }
          });
          _merge(worksheet.getRow(2).getCell(2), {
            fill: {
              type: 'pattern',
              pattern: 'solid',
              fgColor: {
                argb: 'FFFF4949'
              }
            }
          });
        }
      }
    ]
  });
});

然后就可以看到下载了一份名为test.xlsx的文件,打开就是我们要的数据和效果了

coordinatesFromRange

从一个区间范围获取所有的坐标矩阵

js 复制代码
coordinatesFromRange(range)
  • range:[number, number, number, number]坐标点,四个参数分别代表开始行 开始列 结束行 结束列
js 复制代码
import { coordinatesFromRange } from 'kk-utils-library/excel-js';

const coordinatesResult = coordinatesFromRange([2, 3, 3, 4]);
console.log('coordinatesResult', coordinatesResult);
// [
//   [2, 3],
//   [2, 4],
//   [3, 3],
//   [3, 4]
// ];

isCoordinateInCoordinates

判断一个坐标点是否在坐标矩阵内

js 复制代码
isCoordinateInCoordinates(coordinate, coordinates)
  • coordinate:[number, number]坐标点
  • coordinates:坐标矩阵
js 复制代码
import { isCoordinateInCoordinates } from 'kk-utils-library/excel-js';

const isCoordinateInCoordinatesResult = isCoordinateInCoordinates(
  [2, 3],
  coordinatesResult
);
const isCoordinateInCoordinatesResult2 = isCoordinateInCoordinates(
  [12, 13],
  coordinatesResult
);
console.log('isCoordinateInCoordinatesResult', isCoordinateInCoordinatesResult);
// true
console.log('isCoordinateInCoordinatesResult2', isCoordinateInCoordinatesResult2);
// false

isCoordinateInRange

判断一个坐标点是否在坐标范围内

js 复制代码
isCoordinateInRange(coordinate, range)
  • coordinate:[number, number]坐标点
  • range:[number, number, number, number]坐标点,四个参数分别代表开始行 开始列 结束行 结束列
js 复制代码
import { isCoordinateInRange } from 'kk-utils-library/excel-js';

const isCoordinateInRangeResult = isCoordinateInRange(
  [2, 3],
  [2, 3, 5, 8]
);
const isCoordinateInRangeResult2 = isCoordinateInRange(
  [12, 13],
  [2, 3, 5, 8]
);
console.log('isCoordinateInRangeResult', isCoordinateInRangeResult);
// true
console.log('isCoordinateInRangeResult2', isCoordinateInRangeResult2);
// false

getHorizontalMerges

获取横向合并数据,此数据是专门给exceljs用的

js 复制代码
getHorizontalMerges(excelData)
  • excelData:二维数组
js 复制代码
import { 
    getHorizontalMerges,
    freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
    horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
    verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';

const horizontalMergeAndVerticalMergeTestData = [
  [11, 12, hm, hm, 15, 16, 17, 18, 19],
  [21, 22, 23, 24, 25, fm, fm, 28, 29],
  [31, 32, vm, 34, 35, fm, fm, 38, 39],
  [41, 42, vm, 44, vm, 46, hm, hm, hm],
  [51, 52, 53, 54, vm, 56, 57, 58, 59],
  [61, 62, vm, 64, vm, 66, 67, 68, 69],
  [71, 72, vm, 74, 75, 76, 77, 78, 79],
  [81, 82, vm, 84, 85, 86, 87, 88, 89],
  [91, 92, 93, 94, 95, 96, 97, 98, 99]
];

const horizontalMergesResult = getHorizontalMerges(
  horizontalMergeAndVerticalMergeTestData
);
console.log('horizontalMergesResult', horizontalMergesResult);
// [
//   [1, 2, 1, 4],
//   [4, 6, 4, 9]
// ];

getVerticalMerges

获取纵向合并数据,此数据是专门给exceljs用的

js 复制代码
getVerticalMerges(excelData)
  • excelData:二维数组
js 复制代码
import { 
    getVerticalMerges,
    freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
    horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
    verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';

const horizontalMergeAndVerticalMergeTestData = [
  [11, 12, hm, hm, 15, 16, 17, 18, 19],
  [21, 22, 23, 24, 25, fm, fm, 28, 29],
  [31, 32, vm, 34, 35, fm, fm, 38, 39],
  [41, 42, vm, 44, vm, 46, hm, hm, hm],
  [51, 52, 53, 54, vm, 56, 57, 58, 59],
  [61, 62, vm, 64, vm, 66, 67, 68, 69],
  [71, 72, vm, 74, 75, 76, 77, 78, 79],
  [81, 82, vm, 84, 85, 86, 87, 88, 89],
  [91, 92, 93, 94, 95, 96, 97, 98, 99]
];

const verticalMergesResult = getVerticalMerges(
  horizontalMergeAndVerticalMergeTestData
);
console.log('verticalMergesResult', verticalMergesResult);
// [
//   [2, 3, 4, 3],
//   [3, 5, 6, 5],
//   [5, 3, 8, 3]
// ];

getMatrixMerges

获取纵向和横向的合并数据,此数据是专门给exceljs用的

js 复制代码
getMatrixMerges(excelData)
  • excelData:二维数组
js 复制代码
import { 
    getMatrixMerges,
    freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
    horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
    verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';

const freeMergeTestData = [
  [11, 21, fm, fm, fm, 61, fm, fm, 91],
  [21, 22, fm, fm, fm, 26, 27, 28, 29],
  [31, 32, fm, fm, fm, 36, fm, fm, 39],
  [41, 42, 43, 44, 45, 46, fm, fm, 49],
  [51, 52, fm, fm, 55, 56, fm, fm, 59],
  [fm, 62, fm, fm, 65, 66, 67, 68, 69],
  [fm, 72, fm, fm, 75, 76, 77, 78, 79],
  [81, 82, fm, fm, 85, 86, 87, 88, 89],
  [91, 92, 93, 94, 95, 96, 97, 98, 99]
];

const matrixMergesResult = getMatrixMerges(freeMergeTestData);
console.log('matrixMergesResult', matrixMergesResult);
// [
//   [1, 2, 3, 5],
//   [1, 6, 1, 8],
//   [2, 6, 5, 8],
//   [4, 2, 8, 4],
//   [5, 1, 7, 1]
// ];

getMerges

获取合并数据,此数据是专门给exceljs用的 此方法涵盖了前面三种getMerge方法,会自动识别数据里的hm, vm, fm

js 复制代码
getMerges(excelData)
  • excelData:二维数组
js 复制代码
import { 
    getMerges,
    freeMerge as fm, // 代表自由合并 上下都合并,必须是正方形/长方形 起点为fm左上角单元格
    horizontalMerge as hm, // 代表横向合并 起点为hm前一个单元格
    verticalMerge as vm // 代表纵向合并 起点为vm上一个单元格
} from 'kk-utils-library/excel-js';

const horizontalMergeAndVerticalMergeTestData = [
  [11, 12, hm, hm, 15, 16, 17, 18, 19],
  [21, 22, 23, 24, 25, fm, fm, 28, 29],
  [31, 32, vm, 34, 35, fm, fm, 38, 39],
  [41, 42, vm, 44, vm, 46, hm, hm, hm],
  [51, 52, 53, 54, vm, 56, 57, 58, 59],
  [61, 62, vm, 64, vm, 66, 67, 68, 69],
  [71, 72, vm, 74, 75, 76, 77, 78, 79],
  [81, 82, vm, 84, 85, 86, 87, 88, 89],
  [91, 92, 93, 94, 95, 96, 97, 98, 99]
];

const mergesResult = getMerges(horizontalMergeAndVerticalMergeTestData);
console.log('mergesResult', mergesResult);
// [
//   [1, 2, 1, 4],
//   [4, 6, 4, 9],
//   [2, 3, 4, 3],
//   [3, 5, 6, 5],
//   [5, 3, 8, 3],
//   [1, 5, 3, 7]
// ];

getDefaultStyle

获取全局默认样式

js 复制代码
getDefaultStyle()
js 复制代码
import { getDefaultStyle } from 'kk-utils-library/excel-js';

const beforeStyle = getDefaultStyle();
console.log('beforeStyle', beforeStyle);
// {
//   font: {
//     size: 14
//   },
//   alignment: {
//     vertical: 'top',
//     wrapText: true
//   },
//   border: {
//     top: {
//       style: 'thin'
//     },
//     left: {
//       style: 'thin'
//     },
//     bottom: {
//       style: 'thin'
//     },
//     right: {
//       style: 'thin'
//     }
//   },
//   fill: {
//     type: 'pattern',
//     pattern: 'solid',
//     fgColor: {
//       argb: 'FF99CCFF'
//     }
//   }
// }

getDefaultStyle

获取全局默认样式

js 复制代码
getDefaultStyle()
js 复制代码
import { setGlobalDefaultStyle } from 'kk-utils-library/excel-js';

const afterStyle = setGlobalDefaultStyle({
  font: {
    size: 14
  },
  fill: {
    type: 'pattern',
    pattern: 'solid',
    fgColor: {
      argb: 'FF99CCFF'
    }
  }
});
const afterStyle = getDefaultStyle();
console.log('afterStyle', afterStyle);
// {
//   font: {
//     size: 14
//   },
//   alignment: {
//     vertical: 'top',
//     wrapText: true
//   },
//   border: {
//     top: {
//       style: 'thin'
//     },
//     left: {
//       style: 'thin'
//     },
//     bottom: {
//       style: 'thin'
//     },
//     right: {
//       style: 'thin'
//     }
//   },
//   fill: {
//     type: 'pattern',
//     pattern: 'solid',
//     fgColor: {
//       argb: 'FF99CCFF'
//     }
//   }
// }

setAdaptiveWidth

设置Excel的单元格自适应宽度,如果你自己使用exceljs则需要自己使用setAdaptiveWidth去处理,kk-utils里的导出默认是true了,可以自己传入调整参数,ExcelJs的参数需自己看文档

js 复制代码
setAdaptiveWidth(Worksheet, [options])
js 复制代码
import { setAdaptiveWidth } from 'kk-utils-library/excel-js';
import ExcelJS from 'exceljs';

const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('SheetJS');
worksheet.addRows([
  ['姓名', '简称', '年龄', '性别'],
  ['小明', '无', 18, '男'],
  ['古力那扎尔·拜合提亚尔', '古力娜扎', 16, '女'],
  [
    '巴勃罗·迭戈·荷瑟·山迪亚哥·弗朗西斯科·德·保拉·居安·尼波莫切诺·克瑞斯皮尼亚诺·德·罗斯·瑞米迪欧斯·西波瑞亚诺·德·拉·山迪西玛·特立尼达·玛利亚·帕里西奥·克里托·瑞兹·布拉斯科·毕加索',
    '毕加索',
    92,
    '男'
  ]
]);
console.log('before worksheet widths', _map(worksheet.columns, 'width'));
// [null, null, null, null];
setAdaptiveWidth(worksheet, {
  minWidth: 15,
  maxWidth: 50
});
console.log('after worksheet widths', _map(worksheet.columns, 'width'));
// [50, 17, 15, 15];

getDataHeader

获取最后渲染数据用的表头,因为表头我们可能需要合并,所以塞数据的时候原始表头不适用,需要使用列一一对应的表头才能更方便加入表体数据

js 复制代码
getDataHeader(excelData)
  • excelData:二维数组
js 复制代码
import { getDataHeader } from 'kk-utils-library/excel-js';

const dataHeader = getDataHeader([
  ['编码', '时间', '已批准', '已核销', '未核销', hm, '已支付', '待支付'],
  [vm, vm, vm, vm, '申请中', '未申请', vm, vm]
]);
console.log('dataHeader', dataHeader);
// [
//   '编码',
//   '时间',
//   '已批准',
//   '已核销',
//   '申请中',
//   '未申请',
//   '已支付',
//   '待支付'
// ];

getColumnLetterByNumber

根据列下标1开始获取对应的Excel字母列

js 复制代码
getColumnLetterByNumber(number)
js 复制代码
import { getColumnLetterByNumber } from 'kk-utils-library/excel-js';

const letter = getColumnLetterByNumber(5);
console.log('letter', letter);
// E

getDepthAndLength

获取树结构的深度和最长子级长度

js 复制代码
getDepthAndLength(tree, [options])
  • tree:树形数组
  • options:配置项,可选,对象类型,支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
js 复制代码
import { getDepthAndLength } from 'kk-utils-library/excel-js';

const getDepthAndLengthTree = [
  {
    key: 1,
    children: [
      {
      {
        key: 12,
        children: [
          {
            key: 122,
            children: [
              {
                key: 1221
              },
              {
                key: 1222,
                children: [
                  {
                    key: 12221
                  },
                  {
                    key: 12222
                  },
                  {
                    key: 12223
                  },
                  {
                    key: 12224
                  },
                  {
                    key: 12225
                  },
                  {
                    key: 12226
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
];
const getDepthAndLengthResult = getDepthAndLength(getDepthAndLengthTree);
console.log('getDepthAndLengthResult', getDepthAndLengthResult);
// { depth: 5, length: 6 }

getFillHorizontalMergeKeyMap

获取表头横向合并列所对应的合并长度

js 复制代码
getFillHorizontalMergeKeyMap(Tree, [options])
  • tree:树形数组
  • options:配置项,可选,对象类型,支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
js 复制代码
import { getFillHorizontalMergeKeyMap } from 'kk-utils-library/excel-js';

const treeHeader = [
  {
    prop: 'index',
    label: '序号'
  },
  {
    prop: 'budgetCycleItemName',
    label: '预算周期项名称'
  },
  {
    prop: 'expectedShipmentAmount',
    label: '预发货金额',
    children: [
      {
        prop: 'originalExpectedShipmentAmount',
        label: '调整前金额'
      },
      {
        prop: 'adjustedExpectedShipmentAmount',
        label: '调整的金额'
      },
      {
        prop: 'finalExpectedShipmentAmount',
        label: '调整后金额'
      }
    ]
  },
  {
    prop: 'budgetAmount',
    label: '预算金额',
    children: [
      {
        prop: 'originalBudgetAmount',
        label: '调整前金额'
      },
      {
        prop: 'adjustedBudgetAmount',
        label: '调整的金额'
      },
      {
        prop: 'finalBudgetAmount',
        label: '调整后金额'
      }
    ]
  }
];
const getFillHorizontalMergeKeyMapResult =
  getFillHorizontalMergeKeyMap(treeHeader);
console.log(
  'getFillHorizontalMergeKeyMapResult',
  getFillHorizontalMergeKeyMapResult
);
// {
//   index: 0,
//   budgetCycleItemName: 0,
//   expectedShipmentAmount: 2,
//   originalExpectedShipmentAmount: 0,
//   adjustedExpectedShipmentAmount: 0,
//   finalExpectedShipmentAmount: 0,
//   budgetAmount: 2,
//   originalBudgetAmount: 0,
//   adjustedBudgetAmount: 0,
//   finalBudgetAmount: 0
// }

tableHeaderToMultidimensionalArray

把树结构表头处理成Excel的表头

js 复制代码
tableHeaderToMultidimensionalArray(Tree, [options])
  • tree:树形数组
  • options:配置项,可选,对象类型,支持基础配置项
    • itemKey:指定节点key名,默认值为id
    • childrenKey:自定义子节点key名,默认值为children
    • labelKey: 自定义节点文本key名,默认值为label
js 复制代码
import { tableHeaderToMultidimensionalArray } from 'kk-utils-library/excel-js';

const treeHeader = [
  {
    prop: 'index',
    label: '序号'
  },
  {
    prop: 'budgetCycleItemName',
    label: '预算周期项名称'
  },
  {
    prop: 'expectedShipmentAmount',
    label: '预发货金额',
    children: [
      {
        prop: 'originalExpectedShipmentAmount',
        label: '调整前金额'
      },
      {
        prop: 'adjustedExpectedShipmentAmount',
        label: '调整的金额'
      },
      {
        prop: 'finalExpectedShipmentAmount',
        label: '调整后金额'
      }
    ]
  },
  {
    prop: 'budgetAmount',
    label: '预算金额',
    children: [
      {
        prop: 'originalBudgetAmount',
        label: '调整前金额'
      },
      {
        prop: 'adjustedBudgetAmount',
        label: '调整的金额'
      },
      {
        prop: 'finalBudgetAmount',
        label: '调整后金额'
      }
    ]
  }
];

const multidimensionalArray = tableHeaderToMultidimensionalArray(treeHeader);
console.log('multidimensionalArray', multidimensionalArray);
// [
//   [
//     '序号',
//     '预算周期项名称',
//     '预发货金额',
//     '-hm',
//     '-hm',
//     '预算金额',
//     '-hm',
//     '-hm'
//   ],
//   [
//     '-vm',
//     '-vm',
//     '调整前金额',
//     '调整的金额',
//     '调整后金额',
//     '调整前金额',
//     '调整的金额',
//     '调整后金额'
//   ]
// ];

conversionToJsonArray

把Excel数据转成数组对象格式

js 复制代码
conversionToJsonArray(ExcelData, [options])
  • excelData:二维数组
  • options:配置项,可选,对象类型
    • headerStartLine:number,表头开始行数,默认1开始
    • headerTotalLine:number,表头总行数,默认1
js 复制代码
import { conversionToJsonArray } from 'kk-utils-library/excel-js';

const arrayData = [
  ['操作类型', '客户名称', '客户编码', '省', '市', '区'],
  [
    '不变',
    '苏州秦曼商贸有限公司',
    '11605028',
    '苏北省(作废)',
    '苏州市',
    '吴中区'
  ],
  [
    '不变',
    '测试-嘉士柏河南省郑州------麻三定/麻坤丽',
    'JSB12001003',
    '河南省',
    '郑州市',
    '中原区'
  ]
];
const conversionToJsonArrayResult = conversionToJsonArray(arrayData);
console.log('conversionToJsonArrayResult', conversionToJsonArrayResult);
// [
//   {
//     操作类型: '不变',
//     客户名称: '苏州秦曼商贸有限公司',
//     客户编码: '11605028',
//     省: '苏北省(作废)',
//     市: '苏州市',
//     区: '吴中区'
//   },
//   {
//     操作类型: '不变',
//     客户名称: '测试-嘉士柏河南省郑州------麻三定/麻坤丽',
//     客户编码: 'JSB12001003',
//     省: '河南省',
//     市: '郑州市',
//     区: '中原区'
//   }
// ];
相关推荐
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅10 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊10 小时前
jwt介绍
前端
爱敲代码的小鱼10 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte11 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc