ref 精简组件

This commit is contained in:
bootx
2024-07-01 23:39:26 +08:00
parent d0f550b758
commit 5c578eb9a6
30 changed files with 31 additions and 1741 deletions

View File

@@ -7,7 +7,7 @@ VITE_PUBLIC_PATH = /
# Whether to enable gzip or brotli compression
# Optional: gzip | brotli | none
# If you need multiple forms, you can use `,` to separate
VITE_BUILD_COMPRESS = 'none'
VITE_BUILD_COMPRESS = 'gzip'
# Basic interface address SPA

View File

@@ -27,7 +27,6 @@
"CHANGELOG.md": true,
"examples": true,
"res": true,
"screenshots": true,
"yarn-error.log": true,
"**/.yarn": true
},
@@ -108,7 +107,6 @@
"antv",
"brotli",
"browserslist",
"codemirror",
"commitlint",
"cropperjs",
"echarts",

View File

@@ -82,15 +82,12 @@
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"echarts": "^5.5.0",
"exceljs": "^4.4.0",
"html2canvas": "^1.4.1",
"lodash-es": "^4.17.21",
"mockjs": "^1.1.0",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.2",
"pinia": "2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"print-js": "^1.6.0",
"qrcode": "^1.5.3",
"qs": "^6.12.1",
"resize-observer-polyfill": "^1.5.1",
@@ -105,9 +102,7 @@
"vue-types": "^5.1.1",
"vuedraggable": "^4.1.0",
"vxe-table": "^4.7.31",
"vxe-table-plugin-export-xlsx": "^4.0.2",
"xe-utils": "^3.5.25",
"xlsx": "^0.18.5"
"xe-utils": "^3.5.25"
},
"devDependencies": {
"@commitlint/cli": "^19.3.0",

578
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
import { withInstall } from '@/utils';
import impExcel from './src/ImportExcel.vue';
import expExcelModal from './src/ExportExcelModal.vue';
export const ImpExcel = withInstall(impExcel);
export const ExpExcelModal = withInstall(expExcelModal);
export * from './src/typing';
export { jsonToSheetXlsx, aoaToSheetXlsx } from './src/Export2Excel';

View File

@@ -1,148 +0,0 @@
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import type { JsonToSheet, AoAToSheet } from './typing';
import { AoaToMultipleSheet, JsonToMultipleSheet } from './typing';
const { utils, writeFile } = xlsx;
const DEF_FILE_NAME = 'excel-list.xlsx';
const DEF_SHEET_NAME = 'sheet';
/**
* @param data source data
* @param worksheet worksheet object
* @param min min width
*/
function setColumnWidth(data, worksheet, min = 3) {
const obj = {};
worksheet['!cols'] = [];
data.forEach((item) => {
Object.keys(item).forEach((key) => {
const cur = item[key];
const length = cur?.length ?? min;
obj[key] = Math.max(length, obj[key] ?? min);
});
});
Object.keys(obj).forEach((key) => {
worksheet['!cols'].push({
wch: obj[key],
});
});
}
export function jsonToSheetXlsx<T = any>({
data,
header,
filename = DEF_FILE_NAME,
sheetName = DEF_SHEET_NAME,
json2sheetOpts = {},
write2excelOpts = { bookType: 'xlsx' },
}: JsonToSheet<T>) {
const arrData = [...data];
if (header) {
arrData.unshift(header);
json2sheetOpts.skipHeader = true;
}
const worksheet = utils.json_to_sheet(arrData, json2sheetOpts);
setColumnWidth(arrData, worksheet);
/* add worksheet to workbook */
const workbook: WorkBook = {
SheetNames: [sheetName],
Sheets: {
[sheetName]: worksheet,
},
};
/* output format determined by filename */
writeFile(workbook, filename, write2excelOpts);
/* at this point, out.xlsb will have been downloaded */
}
export function aoaToSheetXlsx<T = any>({
data,
header,
filename = DEF_FILE_NAME,
write2excelOpts = { bookType: 'xlsx' },
}: AoAToSheet<T>) {
const arrData = [...data];
if (header) {
arrData.unshift(header);
}
const worksheet = utils.aoa_to_sheet(arrData);
/* add worksheet to workbook */
const workbook: WorkBook = {
SheetNames: [filename],
Sheets: {
[filename]: worksheet,
},
};
/* output format determined by filename */
writeFile(workbook, filename, write2excelOpts);
/* at this point, out.xlsb will have been downloaded */
}
/**
* json导出多Sheet的Xlsx
* @param sheetList 多sheet配置
* @param filename 文件名(包含后缀)
* @param write2excelOpts 文件配置
*/
export function jsonToMultipleSheetXlsx<T = any>({
sheetList,
filename = DEF_FILE_NAME,
write2excelOpts = { bookType: 'xlsx' },
}: JsonToMultipleSheet<T>) {
const workbook: WorkBook = {
SheetNames: [],
Sheets: {},
};
sheetList.forEach((p, index) => {
const arrData = [...p.data];
if (p.header) {
arrData.unshift(p.header);
p.json2sheetOpts = p.json2sheetOpts || {};
p.json2sheetOpts.skipHeader = true;
}
const worksheet = utils.json_to_sheet(arrData, p.json2sheetOpts);
setColumnWidth(arrData, worksheet);
p.sheetName = p.sheetName || `${DEF_SHEET_NAME}${index}`;
workbook.SheetNames.push(p.sheetName);
workbook.Sheets[p.sheetName] = worksheet;
});
writeFile(workbook, filename, write2excelOpts);
}
/**
* aoa导出多Sheet的Xlsx
* @param sheetList 多sheet配置
* @param filename 文件名(包含后缀)
* @param write2excelOpts 文件配置
*/
export function aoaToMultipleSheetXlsx<T = any>({
sheetList,
filename = DEF_FILE_NAME,
write2excelOpts = { bookType: 'xlsx' },
}: AoaToMultipleSheet<T>) {
const workbook: WorkBook = {
SheetNames: [],
Sheets: {},
};
sheetList.forEach((p, index) => {
const arrData = [...p.data];
if (p.header) {
arrData.unshift(p.header);
}
const worksheet = utils.aoa_to_sheet(arrData);
p.sheetName = p.sheetName || `${DEF_SHEET_NAME}${index}`;
workbook.SheetNames.push(p.sheetName);
workbook.Sheets[p.sheetName] = worksheet;
});
/* output format determined by filename */
writeFile(workbook, filename, write2excelOpts);
/* at this point, out.xlsb will have been downloaded */
}

View File

@@ -1,79 +0,0 @@
<template>
<BasicModal
v-bind="$attrs"
:title="t('component.excel.exportModalTitle')"
@ok="handleOk"
@register="registerModal"
>
<BasicForm
:labelWidth="100"
:schemas="schemas"
:showActionButtonGroup="false"
@register="registerForm"
/>
</BasicModal>
</template>
<script lang="ts" setup>
import type { ExportModalResult } from './typing';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, FormSchema, useForm } from '@/components/Form';
import { useI18n } from '@/hooks/web/useI18n';
const { t } = useI18n();
const schemas: FormSchema[] = [
{
field: 'filename',
component: 'Input',
label: t('component.excel.fileName'),
rules: [{ required: true }],
},
{
field: 'bookType',
component: 'Select',
label: t('component.excel.fileType'),
defaultValue: 'xlsx',
rules: [{ required: true }],
componentProps: {
options: [
{
label: 'xlsx',
value: 'xlsx',
key: 'xlsx',
},
{
label: 'html',
value: 'html',
key: 'html',
},
{
label: 'csv',
value: 'csv',
key: 'csv',
},
{
label: 'txt',
value: 'txt',
key: 'txt',
},
],
},
},
];
const emit = defineEmits(['success', 'register']);
const [registerForm, { validate }] = useForm();
const [registerModal, { closeModal }] = useModalInner();
const handleOk = async () => {
const res = await validate<ExportModalResult>();
const { filename, bookType } = res;
emit('success', {
filename: `${filename.split('.').shift()}.${bookType}`,
bookType,
});
closeModal();
};
</script>

View File

@@ -1,221 +0,0 @@
<template>
<div>
<input
ref="inputRef"
type="file"
v-show="false"
accept=".xlsx, .xls"
@change="handleInputClick"
/>
<div @click="handleUpload">
<slot></slot>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, unref } from 'vue';
import * as XLSX from 'xlsx';
import { dateUtil } from '@/utils/dateUtil';
import type { ExcelData } from './typing';
defineOptions({ name: 'ImportExcel' });
const props = defineProps({
// 日期时间格式。如果不提供或者提供空值将返回原始Date对象
dateFormat: {
type: String,
},
// 时区调整。实验性功能,仅为了解决读取日期时间值有偏差的问题。目前仅提供了+08:00时区的偏差修正值
// https://github.com/SheetJS/sheetjs/issues/1470#issuecomment-501108554
timeZone: {
type: Number,
default: 8,
},
// 是否直接返回选中文件
isReturnFile: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['success', 'error', 'cancel']);
const inputRef = ref<HTMLInputElement | null>(null);
const loadingRef = ref<Boolean>(false);
const cancelRef = ref<Boolean>(true);
function shapeWorkSheel(sheet: XLSX.WorkSheet, range: XLSX.Range) {
let str = ' ',
char = 65,
customWorkSheet = {
t: 's',
v: str,
r: '<t> </t><phoneticPr fontId="1" type="noConversion"/>',
h: str,
w: str,
};
if (!sheet || !sheet['!ref']) return [];
let c = 0,
r = 1;
while (c < range.e.c + 1) {
while (r < range.e.r + 1) {
if (!sheet[String.fromCharCode(char) + r]) {
sheet[String.fromCharCode(char) + r] = customWorkSheet;
}
r++;
}
r = 1;
str += ' ';
customWorkSheet = {
t: 's',
v: str,
r: '<t> </t><phoneticPr fontId="1" type="noConversion"/>',
h: str,
w: str,
};
c++;
char++;
}
}
/**
* @description: 第一行作为头部
*/
function getHeaderRow(sheet: XLSX.WorkSheet) {
if (!sheet || !sheet['!ref']) return [];
const headers: string[] = [];
// A3:B7=>{s:{c:0, r:2}, e:{c:1, r:6}}
const range: XLSX.Range = XLSX.utils.decode_range(sheet['!ref']);
shapeWorkSheel(sheet, range);
const R = range.s.r;
/* start in the first row */
for (let C = range.s.c; C <= range.e.c; ++C) {
/* walk every column in the range */
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })];
/* find the cell in the first row */
let hdr = 'UNKNOWN ' + C; // <-- replace with your desired default
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell);
headers.push(hdr);
}
return headers;
}
/**
* @description: 获得excel数据
*/
function getExcelData(workbook: XLSX.WorkBook) {
const excelData: ExcelData[] = [];
const { dateFormat, timeZone } = props;
for (const sheetName of workbook.SheetNames) {
const worksheet = workbook.Sheets[sheetName];
const header: string[] = getHeaderRow(worksheet);
let results = XLSX.utils.sheet_to_json(worksheet, {
raw: true,
dateNF: dateFormat, //Not worked
}) as object[];
results = results.map((row: object) => {
for (let field in row) {
if (row[field] instanceof Date) {
if (timeZone === 8) {
row[field].setSeconds(row[field].getSeconds() + 43);
}
if (dateFormat) {
row[field] = dateUtil(row[field]).format(dateFormat);
}
}
}
return row;
});
excelData.push({
header,
results,
meta: {
sheetName,
},
});
}
return excelData;
}
/**
* @description: 读取excel数据
*/
function readerData(rawFile: File) {
loadingRef.value = true;
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (e) => {
try {
const data = e.target && e.target.result;
const workbook = XLSX.read(data, { type: 'array', cellDates: true });
// console.log(workbook);
/* DO SOMETHING WITH workbook HERE */
const excelData = getExcelData(workbook);
emit('success', excelData);
resolve('');
} catch (error) {
reject(error);
emit('error');
} finally {
loadingRef.value = false;
}
};
reader.readAsArrayBuffer(rawFile);
});
}
async function upload(rawFile: File) {
const inputRefDom = unref(inputRef);
if (inputRefDom) {
// fix can't select the same excel
inputRefDom.value = '';
}
await readerData(rawFile);
}
/**
* @description: 触发选择文件管理器
*/
function handleInputClick(e: Event) {
const target = e && (e.target as HTMLInputElement);
const files = target?.files;
const rawFile = files && files[0]; // only setting files[0]
target.value = '';
if (!rawFile) return;
cancelRef.value = false;
if (props.isReturnFile) {
emit('success', rawFile);
return;
}
upload(rawFile);
}
/**
* @description 文件选择器关闭后,判断取消状态
*/
function handleFocusChange() {
const timeId = setInterval(() => {
if (cancelRef.value === true) {
emit('cancel');
}
clearInterval(timeId);
window.removeEventListener('focus', handleFocusChange);
}, 1000);
}
/**
* @description: 点击上传按钮
*/
function handleUpload() {
const inputRefDom = unref(inputRef);
if (inputRefDom) {
cancelRef.value = true;
inputRefDom.click();
window.addEventListener('focus', handleFocusChange);
}
}
</script>

View File

@@ -1,41 +0,0 @@
import type { JSON2SheetOpts, WritingOptions, BookType } from 'xlsx';
export interface ExcelData<T = any> {
header: string[];
results: T[];
meta: { sheetName: string };
}
export interface JsonToSheet<T = any> {
data: T[];
header?: T;
filename?: string;
sheetName?: string;
json2sheetOpts?: JSON2SheetOpts;
write2excelOpts?: WritingOptions;
}
export interface AoAToSheet<T = any> {
data: T[][];
header?: T[];
filename?: string;
sheetName?: string;
write2excelOpts?: WritingOptions;
}
export interface ExportModalResult {
filename: string;
bookType: BookType;
}
export interface JsonToMultipleSheet<T = any> {
sheetList: JsonToSheet<T>[];
filename?: string;
write2excelOpts?: WritingOptions;
}
export interface AoaToMultipleSheet<T = any> {
sheetList: AoAToSheet<T>[];
filename?: string;
write2excelOpts?: WritingOptions;
}

View File

@@ -290,8 +290,8 @@
const target = e ? e.target : null;
let value = target ? (isCheck ? target.checked : target.value) : e;
if(isFunction(valueFormat)){
value = valueFormat({...unref(getValues),value});
if (isFunction(valueFormat)) {
value = valueFormat({ ...unref(getValues), value });
}
props.setFormModel(field, value, props.schema);

View File

@@ -34,14 +34,10 @@ const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker'];
/**
* 上传组件
*/
export const uploadItemType: ComponentType[] = [
'Upload',
'ImageUpload'
];
export const uploadItemType: ComponentType[] = ['Upload', 'ImageUpload'];
function genType() {
return [...DATE_TYPE, 'RangePicker',"TimeRangePicker"];
return [...DATE_TYPE, 'RangePicker', 'TimeRangePicker'];
}
export function setComponentRuleType(

View File

@@ -25,12 +25,12 @@ interface UseFormActionContext {
schemaRef: Ref<FormSchema[]>;
handleFormValues: Fn;
}
/**
* @description: Is it upload
/**
* @description: Is it upload
*/
export function itemIsUploadComponent(key: keyof ComponentProps) {
return uploadItemType.includes(key);
}
export function itemIsUploadComponent(key: keyof ComponentProps) {
return uploadItemType.includes(key);
}
function tryConstructArray(field: string, values: Recordable = {}): any[] | undefined {
const pattern = /^\[(.+)\]$/;
if (pattern.test(field)) {
@@ -146,7 +146,7 @@ export function useFormEvents({
}
}
validKeys.push(key);
return
return;
}
// Adapt common component
if (hasKey) {

View File

@@ -59,6 +59,7 @@
import UploadPreviewModal from './components/UploadPreviewModal.vue';
import { BaseFileItem } from './types/typing';
import { buildUUID } from '@/utils/uuid';
defineOptions({ name: 'BasicUpload' });
const props = defineProps(uploadContainerProps);
@@ -86,9 +87,9 @@
return omit(value, 'onChange');
});
const isFirstRender = ref<boolean>(true)
const isFirstRender = ref<boolean>(true);
function getValue(valueKey="url") {
function getValue(valueKey = 'url') {
const list = (fileList.value || []).map((item: any) => {
return item[valueKey];
});
@@ -113,7 +114,7 @@
} else if (typeof v == 'string') {
values.push(v);
}
fileList.value = values.map((item,i) => {
fileList.value = values.map((item, i) => {
if (item && isString(item)) {
return {
uid: buildUUID(),
@@ -127,9 +128,9 @@
}) as any;
}
emit('update:value', values);
if(!isFirstRender.value){
if (!isFirstRender.value) {
emit('change', values);
isFirstRender.value = false
isFirstRender.value = false;
}
},
{
@@ -139,7 +140,7 @@
);
// 上传modal保存操作
function handleChange(urls: string[],valueKey:string) {
function handleChange(urls: string[], valueKey: string) {
fileList.value = [...unref(fileList), ...(genFileListByUrls(urls) || [])];
const values = getValue(valueKey);
emit('update:value', values);
@@ -147,7 +148,7 @@
}
// 预览modal保存操作
function handlePreviewChange(fileItems: string[],valueKey:string) {
function handlePreviewChange(fileItems: string[], valueKey: string) {
fileList.value = [...(fileItems || [])];
const values = getValue(valueKey);
emit('update:value', values);

View File

@@ -63,7 +63,7 @@
const fileList = ref<UploadProps['fileList']>([]);
const isLtMsg = ref<boolean>(true);
const isActMsg = ref<boolean>(true);
const isFirstRender = ref<boolean>(true)
const isFirstRender = ref<boolean>(true);
watch(
() => props.value,
@@ -95,9 +95,9 @@
}) as UploadProps['fileList'];
}
emit('update:value', value);
if(!isFirstRender.value){
if (!isFirstRender.value) {
emit('change', value);
isFirstRender.value = false
isFirstRender.value = false;
}
},
{

View File

@@ -23,6 +23,7 @@
import { BasicColumn } from '@/components/Table';
import { useMessage } from '@/hooks/web/useMessage';
import { buildUUID } from '@/utils/uuid';
const { createMessage } = useMessage();
const props = defineProps(previewProps);

View File

@@ -14,7 +14,7 @@ type SortableOptions = Merge<
// ...可扩展
}
>;
export type handleFnKey = "record" | "valueKey" | "uidKey"
export type handleFnKey = 'record' | 'valueKey' | 'uidKey';
export type previewColumnsFnType = {
handleRemove: (record: Record<handleFnKey, any>) => any;
handleAdd: (record: Record<handleFnKey, any>) => any;

View File

@@ -1,13 +1,7 @@
import { withInstall } from '@/utils';
import vxeBasicTable from './src/VxeBasicTable';
import { VxeUI } from 'vxe-table';
import VXETablePluginAntd from './src/components';
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx';
import ExcelJS from 'exceljs';
import './src/setting';
export const VxeBasicTable = withInstall(vxeBasicTable);
export * from 'vxe-table';
export * from './src/types';
VxeUI.use(VXETablePluginAntd).use(VXETablePluginExportXLSX, { ExcelJS });

View File

@@ -28,11 +28,6 @@
"cancelText": "Close",
"okText": "Confirm"
},
"excel": {
"exportModalTitle": "Export data",
"fileType": "File type",
"fileName": "File name"
},
"form": {
"putAway": "Put away",
"unfold": "Unfold",

View File

@@ -1,168 +0,0 @@
{
"charts": {
"baiduMap": "Baidu map",
"aMap": "A map",
"googleMap": "Google map",
"charts": "Chart",
"map": "Map",
"line": "Line",
"pie": "Pie"
},
"comp": {
"comp": "Component",
"basic": "Basic",
"transition": "Animation",
"countTo": "Count To",
"scroll": "Scroll",
"scrollBasic": "Basic",
"scrollAction": "Scroll Function",
"virtualScroll": "Virtual Scroll",
"tree": "Tree",
"treeBasic": "Basic",
"editTree": "Searchable/toolbar",
"actionTree": "Function operation",
"modal": "Modal",
"drawer": "Drawer",
"desc": "Desc",
"verify": "Verify",
"verifyDrag": "Drag ",
"verifyRotate": "Picture Restore",
"qrcode": "QR code",
"strength": "Password strength",
"upload": "Upload",
"loading": "Loading",
"time": "Relative Time",
"cropperImage": "Cropper Image",
"cardList": "Card List"
},
"excel": {
"excel": "Excel",
"customExport": "Select export format",
"jsonExport": "JSON data export",
"arrayExport": "Array data export",
"importExcel": "Import"
},
"feat": {
"feat": "Page Function",
"icon": "Icon",
"screenShot": "Screen Shot",
"tabs": "Tabs",
"tabDetail": "Tab Detail",
"sessionTimeout": "Session Timeout",
"print": "Print",
"contextMenu": "Context Menu",
"download": "Download",
"clickOutSide": "ClickOutSide",
"imgPreview": "Picture Preview",
"copy": "Clipboard",
"ellipsis": "EllipsisText",
"msg": "Message prompt",
"watermark": "Watermark",
"ripple": "Ripple",
"fullScreen": "Full Screen",
"errorLog": "Error Log",
"tab": "Tab with parameters",
"tab1": "Tab with parameter 1",
"tab2": "Tab with parameter 2",
"menu": "Menu with parameters",
"menu1": "Menu with parameters 1",
"menu2": "Menu with parameters 2",
"ws": "Websocket test",
"breadcrumb": "Breadcrumbs",
"breadcrumbFlat": "Flat Mode",
"breadcrumbFlatDetail": "Flat mode details",
"requestDemo": "Retry request demo",
"breadcrumbChildren": "Level mode",
"breadcrumbChildrenDetail": "Level mode detail"
},
"form": {
"form": "Form",
"basic": "Basic",
"useForm": "useForm",
"refForm": "RefForm",
"advancedForm": "Shrinkable",
"ruleForm": "Form validation",
"dynamicForm": "Dynamic",
"customerForm": "Custom",
"appendForm": "Append",
"tabsForm": "TabsForm"
},
"iframe": {
"frame": "External",
"antv": "antVue doc (embedded)",
"doc": "Project doc (embedded)",
"docExternal": "Project doc (external)"
},
"level": {
"level": "MultiMenu"
},
"page": {
"page": "Page",
"form": "Form",
"formBasic": "Basic Form",
"formStep": "Step Form",
"formHigh": "Advanced Form",
"desc": "Details",
"descBasic": "Basic Details",
"descHigh": "Advanced Details",
"result": "Result",
"resultSuccess": "Success",
"resultFail": "Failed",
"account": "Personal",
"accountCenter": "Personal Center",
"accountSetting": "Personal Settings",
"exception": "Exception",
"netWorkError": "Network Error",
"notData": "No data",
"list": "List page",
"listCard": "Card list",
"basic": "Basic list",
"listBasic": "Basic list",
"listSearch": "Search list"
},
"permission": {
"permission": "Permission",
"front": "front-end",
"frontPage": "Page",
"frontBtn": "Button",
"frontTestA": "Test page A",
"frontTestB": "Test page B",
"back": "background",
"backPage": "Page",
"backBtn": "Button"
},
"steps": {
"page": "Intro page"
},
"system": {
"moduleName": "System management",
"account": "Account management",
"vxeTableAccount": "Account management(VxeTable)",
"account_detail": "Account detail",
"password": "Change password",
"dept": "Department management",
"menu": "Menu management",
"role": "Role management"
},
"table": {
"table": "Table",
"basic": "Basic",
"treeTable": "Tree",
"fetchTable": "Remote loading",
"fixedColumn": "Fixed column",
"customerCell": "Custom column",
"formTable": "Open search",
"useTable": "UseTable",
"refTable": "RefTable",
"multipleHeader": "MultiLevel header",
"mergeHeader": "Merge cells",
"expandTable": "Expandable table",
"fixedHeight": "Fixed height",
"footerTable": "Footer",
"editCellTable": "Editable cell",
"editRowTable": "Editable row",
"authColumn": "Auth column",
"resizeParentHeightTable": "resizeParentHeightTable",
"vxeTable": "VxeTable"
}
}

View File

@@ -28,11 +28,6 @@
"cancelText": "关闭",
"okText": "确认"
},
"excel": {
"exportModalTitle": "导出数据",
"fileType": "文件类型",
"fileName": "文件名"
},
"form": {
"putAway": "收起",
"unfold": "展开",

View File

@@ -35,17 +35,9 @@
"cropperImage": "图片裁剪",
"cardList": "卡片列表"
},
"excel": {
"excel": "Excel",
"customExport": "选择导出格式",
"jsonExport": "JSON数据导出",
"arrayExport": "Array数据导出",
"importExcel": "导入"
},
"feat": {
"feat": "功能",
"icon": "图标",
"screenShot": "截图",
"sessionTimeout": "登录过期",
"tabs": "标签页操作",
"tabDetail": "标签详情页",

View File

@@ -23,14 +23,6 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.icon'),
},
},
{
path: 'screenshot',
name: 'Screenshot',
component: () => import('@/views/demo/feat/screenshot/index.vue'),
meta: {
title: t('routes.demo.feat.screenShot'),
},
},
{
path: 'ws',
name: 'WebSocket',
@@ -56,14 +48,6 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.sessionTimeout'),
},
},
{
path: 'print',
name: 'Print',
component: () => import('@/views/demo/feat/print/index.vue'),
meta: {
title: t('routes.demo.feat.print'),
},
},
{
path: 'tabs',
name: 'TabsDemo',
@@ -228,51 +212,6 @@ const feat: AppRouteModule = {
title: t('routes.demo.feat.errorLog'),
},
},
{
path: 'excel',
name: 'Excel',
redirect: '/feat/excel/customExport',
component: getParentLayout('Excel'),
meta: {
// icon: 'mdi:microsoft-excel',
title: t('routes.demo.excel.excel'),
},
children: [
{
path: 'customExport',
name: 'CustomExport',
component: () => import('@/views/demo/excel/CustomExport.vue'),
meta: {
title: t('routes.demo.excel.customExport'),
},
},
{
path: 'jsonExport',
name: 'JsonExport',
component: () => import('@/views/demo/excel/JsonExport.vue'),
meta: {
title: t('routes.demo.excel.jsonExport'),
},
},
{
path: 'arrayExport',
name: 'ArrayExport',
component: () => import('@/views/demo/excel/ArrayExport.vue'),
meta: {
title: t('routes.demo.excel.arrayExport'),
},
},
{
path: 'importExcel',
name: 'ImportExcel',
component: () => import('@/views/demo/excel/ImportExcel.vue'),
meta: {
title: t('routes.demo.excel.importExcel'),
},
},
],
},
{
path: 'testTab/:id',
name: 'TestTab',

View File

@@ -169,7 +169,7 @@ const setting: ProjectConfig = {
showBreadCrumbIcon: false,
// Use error-handler-plugin
useErrorHandle: false,
useErrorHandle: true,
// Whether to open back to top
useOpenBackTop: true,

View File

@@ -1,45 +0,0 @@
<template>
<PageWrapper title="导出示例" content="根据数组格式的数据进行导出">
<BasicTable title="基础表格" :columns="columns" :dataSource="data">
<template #toolbar>
<a-button @click="aoaToExcel"> 导出 </a-button>
<a-button @click="aoaToMultipleSheet" danger> 导出多Sheet </a-button>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { BasicTable } from '@/components/Table';
import { aoaToSheetXlsx } from '@/components/Excel';
import { arrHeader, arrData, columns, data } from './data';
import { PageWrapper } from '@/components/Page';
import { aoaToMultipleSheetXlsx } from '@/components/Excel/src/Export2Excel';
function aoaToExcel() {
// 保证data顺序与header一致
aoaToSheetXlsx({
data: arrData,
header: arrHeader,
filename: '二维数组方式导出excel.xlsx',
});
}
function aoaToMultipleSheet() {
// 保证data顺序与header一致
aoaToMultipleSheetXlsx({
sheetList: [
{
data: arrData,
header: arrHeader,
sheetName: 'Sheet1',
},
{
data: arrData,
header: arrHeader,
sheetName: 'Sheet2',
},
],
filename: '二维数组方式导出excel-多Sheet示例.xlsx',
});
}
</script>

View File

@@ -1,30 +0,0 @@
<template>
<PageWrapper title="导出示例" content="可以选择导出格式">
<BasicTable title="基础表格" :columns="columns" :dataSource="data">
<template #toolbar>
<a-button @click="openModal"> 导出 </a-button>
</template>
</BasicTable>
<ExpExcelModal @register="register" @success="defaultHeader" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { BasicTable } from '@/components/Table';
import { jsonToSheetXlsx, ExpExcelModal, ExportModalResult } from '@/components/Excel';
import { columns, data } from './data';
import { useModal } from '@/components/Modal';
import { PageWrapper } from '@/components/Page';
function defaultHeader({ filename, bookType }: ExportModalResult) {
// 默认Object.keys(data[0])作为header
jsonToSheetXlsx({
data,
filename,
write2excelOpts: {
bookType,
},
});
}
const [register, { openModal }] = useModal();
</script>

View File

@@ -1,46 +0,0 @@
<template>
<PageWrapper title="excel数据导入示例">
<ImpExcel @success="loadDataSuccess" dateFormat="YYYY-MM-DD">
<a-button class="m-3"> 导入Excel </a-button>
</ImpExcel>
<BasicTable
v-for="(table, index) in tableListRef"
:key="index"
:title="table.title"
:columns="table.columns"
:dataSource="table.dataSource"
/>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ImpExcel, ExcelData } from '@/components/Excel';
import { BasicTable, BasicColumn } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
const tableListRef = ref<
{
title: string;
columns?: any[];
dataSource?: any[];
}[]
>([]);
function loadDataSuccess(excelDataList: ExcelData[]) {
tableListRef.value = [];
console.log(excelDataList);
for (const excelData of excelDataList) {
const {
header,
results,
meta: { sheetName },
} = excelData;
const columns: BasicColumn[] = [];
for (const title of header) {
columns.push({ title, dataIndex: title });
}
tableListRef.value.push({ title: sheetName, dataSource: results, columns });
}
}
</script>

View File

@@ -1,76 +0,0 @@
<template>
<PageWrapper title="导出示例" content="根据JSON格式的数据进行导出">
<BasicTable title="基础表格" :columns="columns" :dataSource="data">
<template #toolbar>
<a-button @click="defaultHeader"> 导出默认头部 </a-button>
<a-button @click="customHeader"> 导出自定义头部 </a-button>
<a-button @click="handleMultipleSheet" danger> 导出多Sheet </a-button>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { BasicTable } from '@/components/Table';
import { jsonToSheetXlsx } from '@/components/Excel';
import { columns, data } from './data';
import { PageWrapper } from '@/components/Page';
import { jsonToMultipleSheetXlsx } from '@/components/Excel/src/Export2Excel';
function defaultHeader() {
// 默认Object.keys(data[0])作为header
jsonToSheetXlsx({
data,
filename: '使用key作为默认头部.xlsx',
});
}
function customHeader() {
jsonToSheetXlsx({
data,
header: {
id: 'ID',
name: '姓名',
age: '年龄',
no: '编号',
address: '地址',
beginTime: '开始时间',
endTime: '结束时间',
},
filename: '自定义头部.xlsx',
json2sheetOpts: {
// 指定顺序
header: ['name', 'id'],
},
});
}
function handleMultipleSheet() {
jsonToMultipleSheetXlsx({
sheetList: [
{
data,
sheetName: '使用key作为默认头部',
},
{
data,
header: {
id: 'ID',
name: '姓名',
age: '年龄',
no: '编号',
address: '地址',
beginTime: '开始时间',
endTime: '结束时间',
},
json2sheetOpts: {
// 指定顺序
header: ['name', 'id'],
},
sheetName: '自定义头部',
},
],
filename: '多Sheet导出示例.xlsx',
});
}
</script>

View File

@@ -1,59 +0,0 @@
import { BasicColumn } from '@/components/Table';
export const columns: BasicColumn[] = [
{
title: 'ID',
dataIndex: 'id',
width: 80,
},
{
title: '姓名',
dataIndex: 'name',
width: 120,
},
{
title: '年龄',
dataIndex: 'age',
width: 80,
},
{
title: '编号',
dataIndex: 'no',
width: 80,
},
{
title: '地址',
dataIndex: 'address',
},
{
title: '开始时间',
dataIndex: 'beginTime',
},
{
title: '结束时间',
dataIndex: 'endTime',
},
];
export const data: any[] = (() => {
const arr: any[] = [];
for (let index = 0; index < 40; index++) {
arr.push({
id: `${index}`,
name: `${index} John Brown`,
age: `${index + 10}`,
no: `${index}98678`,
address: 'New York No. 1 Lake ParkNew York No. 1 Lake Park',
beginTime: new Date().toLocaleString(),
endTime: new Date().toLocaleString(),
});
}
return arr;
})();
// ["ID", "姓名", "年龄", "编号", "地址", "开始时间", "结束时间"]
export const arrHeader = columns.map((column) => column.title);
// [["ID", "姓名", "年龄", "编号", "地址", "开始时间", "结束时间"],["0", "0 John Brown", "10", "098678"]]
export const arrData = data.map((item) => {
return Object.keys(item).map((key) => item[key]);
});

View File

@@ -1,40 +0,0 @@
<template>
<PageWrapper title="打印示例">
<CollapseContainer title="json打印表格">
<a-button type="primary" @click="jsonPrint">打印</a-button>
</CollapseContainer>
<a-button type="primary" class="mt-5" @click="imagePrint">Image Print</a-button>
</PageWrapper>
</template>
<script lang="ts" setup>
import { PageWrapper } from '@/components/Page';
import { CollapseContainer } from '@/components/Container';
import printJS from 'print-js';
defineOptions({ name: 'AppLogo' });
function jsonPrint() {
printJS({
printable: [
{ name: 'll', email: '123@gmail.com', phone: '123' },
{ name: 'qq', email: '456@gmail.com', phone: '456' },
],
properties: ['name', 'email', 'phone'],
type: 'json',
});
}
function imagePrint() {
printJS({
printable: [
'https://anncwb.github.io/anncwb/images/preview1.png',
'https://anncwb.github.io/anncwb/images/preview2.png',
],
type: 'image',
header: 'Multiple Images',
imageStyle: 'width:100%;',
});
}
</script>

View File

@@ -1,77 +0,0 @@
<template>
<PageWrapper title="截图示例">
<CollapseContainer title="截图操作">
<a-button type="primary" class="mr-2" @click="handleScreenshot">截取当前body</a-button>
<a-button type="primary" class="mr-2" :disabled="!showPicture" @click="handleDelScreenshot"
>删除截图</a-button
>
<a-button type="primary" class="mr-2" :disabled="!showPicture" @click="handlePrintScreenshot"
>打印截图</a-button
>
<a-button
type="primary"
class="mr-2"
:disabled="!showPicture"
@click="handleDownloadScreenshot"
>下载截图</a-button
>
</CollapseContainer>
<Card title="截图内容" class="mt-4">
<div ref="pictureRef" v-show="showPicture"></div>
</Card>
</PageWrapper>
</template>
<script lang="ts" setup>
import { PageWrapper } from '@/components/Page';
import html2canvas from 'html2canvas';
import { ref } from 'vue';
import { Card } from 'ant-design-vue';
import { CollapseContainer } from '@/components/Container';
import printJS from 'print-js';
import { downloadByBase64 } from '@/utils/file/download';
const pictureRef = ref();
const showPicture = ref<boolean>(false);
const canvasUrl = ref<string>('');
function handleScreenshot() {
if (showPicture.value) return;
html2canvas(document.body, {
backgroundColor: '#ffffff',
allowTaint: true, //开启跨域
useCORS: true,
scrollY: 0,
scrollX: 0,
})
.then(function (canvas) {
canvas.style.width = '100%';
canvas.style.height = '100%';
pictureRef.value.appendChild(canvas);
showPicture.value = true;
canvasUrl.value = canvas.toDataURL();
})
.catch((err) => {
console.log('绘制失败', err);
});
}
function handleDelScreenshot() {
pictureRef.value.innerHTML = '';
canvasUrl.value = '';
showPicture.value = false;
}
function handlePrintScreenshot() {
if (!canvasUrl.value) return;
printJS({
printable: canvasUrl.value,
type: 'image',
base64: true,
});
}
function handleDownloadScreenshot() {
downloadByBase64(canvasUrl.value, 'screen_shot.png');
}
</script>