Skip to content

Commit

Permalink
feat: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
vsdeeper committed Jul 28, 2024
1 parent 630ef03 commit 0610786
Show file tree
Hide file tree
Showing 26 changed files with 657 additions and 218 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const { defineConfig } = require('eslint-define-config')
module.exports = defineConfig({
root: true,
env: {
node: true
node: true,
browser: true
},
extends: ['eslint:recommended', 'plugin:prettier/recommended'],
parser: 'vue-eslint-parser',
Expand Down
1 change: 1 addition & 0 deletions packages/utils/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// 涉及第三方包引用的模块不在这里导出
export * from './file-download'
export * from './find-arrary-value-from-tree-data'
export * from './find-node-object-from-tree-data'
Expand Down
3 changes: 2 additions & 1 deletion packages/utils/core/xlsx-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import type { XLSX$Utils, WorkSheet } from 'xlsx-js-style'
export async function xlsxExport(
exportData: Record<string, any>[],
name?: string,
addStyleExc?: (xlsx: { utils: XLSX$Utils }, worksheet: WorkSheet) => void
// eslint-disable-next-line no-unused-vars
addStyleExc?: (XLSX: { utils: XLSX$Utils }, worksheet: WorkSheet) => void
) {
try {
const XLSX = await import('xlsx-js-style')
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions templates/vue-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@vswift/utils": "workspace:*",
"@vueuse/core": "^10.11.0",
"axios": "^1.7.2",
"crypto-js": "^4.2.0",
Expand All @@ -29,12 +28,13 @@
"pinia": "^2.1.7",
"radash": "^12.1.0",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
"vue-router": "^4.3.0",
"xlsx-js-style": "^1.2.0"
},
"devDependencies": {
"@iconify-json/ep": "^1.1.15",
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@iconify-json/ep": "^1.1.15",
"@rushstack/eslint-patch": "^1.8.0",
"@tsconfig/node20": "^20.1.4",
"@types/crypto-js": "^4.2.2",
Expand All @@ -49,9 +49,9 @@
"@vue/tsconfig": "^0.5.1",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.23.0",
"glob": "^10.3.12",
"husky": "^9.1.1",
"lint-staged": "^15.2.7",
"glob": "^10.3.12",
"npm-run-all2": "^6.1.2",
"prettier": "^3.2.5",
"sass": "^1.77.6",
Expand Down
5 changes: 5 additions & 0 deletions templates/vue-admin/src/components/vs-search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ export interface VsSearchOptionItem {
}
export type VsSearchOptions = VsSearchOptionItem[]
export type VsSearchInstance = InstanceType<typeof VsSearch>
export interface VsSearchProps {
options?: VsSearchOptions
labelWidth?: string | number
[key: string]: any
}
export { VsSearch }
7 changes: 2 additions & 5 deletions templates/vue-admin/src/components/vs-search/vs-search.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<script setup lang="ts">
import type { VsSearchOptions } from '.'
import type { VsSearchProps } from '.'
import { SComponent, type SComponentKey } from './components'
import { pascal } from 'radash'
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
defineProps<{
options?: VsSearchOptions
labelWidth?: string | number
}>()
defineProps<VsSearchProps>()
const emit = defineEmits<{
(e: 'inquire', val: Record<string, any>): void
Expand Down
33 changes: 32 additions & 1 deletion templates/vue-admin/src/components/vs-table/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { ButtonProps, PopconfirmProps, TableColumnCtx } from 'element-plus'
import type {
ButtonProps,
PaginationProps,
PopconfirmProps,
TableColumnCtx,
TableProps
} from 'element-plus'
import VsTable from './vs-table.vue'
import type { LoadingBinding } from 'element-plus/es/components/loading/src/directive.mjs'

export type VsTableInstance = InstanceType<typeof VsTable>
export interface VsTableColumnItem {
Expand All @@ -22,4 +29,28 @@ export interface VsRowOperateOptionItem extends VsTableOperateItem {
popconfirmTitle?: string
popconfirmProps?: Partial<PopconfirmProps>
}
export interface VsTableProps {
// 自定义属性
loading?: LoadingBinding
showIndex?: boolean
showSelection?: boolean
showPagination?: boolean
showRowOperate?: boolean
paginationAlign?: 'left' | 'right'
tableOperateAlign?: 'left' | 'right'
operateColumnWidth?: string | number
total?: number
data?: Record<string, any>[]
columns?: VsTableColumnItem[]
operateOptions?: VsTableOperateItem[]
rowOperateOptions?: VsRowOperateOptionItem[]
currentPage?: number
pageSize?: number

// 源属性
tableProps?: Partial<TableProps<Record<string, any>>>
operateColumnProps?: Partial<TableColumnCtx<any>>
paginationProps?: Partial<PaginationProps>
[key: string]: any
}
export { VsTable }
68 changes: 16 additions & 52 deletions templates/vue-admin/src/components/vs-table/vs-table.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,16 @@
<script setup lang="ts">
import type { VsRowOperateOptionItem, VsTableColumnItem, VsTableOperateItem } from '.'
import type { VsTableOperateItem, VsTableProps } from '.'
import TableColumn from './table-column.vue'
import { getSlots } from './util'
import type { LoadingBinding } from 'element-plus/es/components/loading/src/directive.mjs'
import type { PaginationProps, TableColumnCtx, TableInstance, TableProps } from 'element-plus'
const props = withDefaults(
defineProps<{
// 自定义属性
loading?: LoadingBinding
showIndex?: boolean
showSelection?: boolean
showPagination?: boolean
showRowOperate?: boolean
paginationAlign?: 'left' | 'right'
tableOperateAlign?: 'left' | 'right'
operateColumnWidth?: string | number
total?: number
tableData?: Record<string, any>[]
tableColumns?: VsTableColumnItem[]
rowOperateOptions?: VsRowOperateOptionItem[]
tableOperateOptions?: VsTableOperateItem[]
currentPage?: number
pageSize?: number
// 源属性
tableProps?: Partial<TableProps<Record<string, any>>>
operateColumnProps?: Partial<TableColumnCtx<any>>
paginationProps?: Partial<PaginationProps>
}>(),
{
loading: false,
showRowOperate: true,
showPagination: true,
paginationAlign: 'left',
tableOperateAlign: 'left'
}
)
import type { TableInstance } from 'element-plus'
const props = withDefaults(defineProps<VsTableProps>(), {
loading: false,
showRowOperate: true,
showPagination: true,
paginationAlign: 'left',
tableOperateAlign: 'left'
})
const emit = defineEmits<{
// 以下自定义 emit 事件
Expand Down Expand Up @@ -214,9 +188,9 @@ defineExpose({

<template>
<div v-loading="loading" class="vs-table">
<div v-if="tableOperateOptions?.length" :class="['table-operate', tableOperateAlign]">
<div v-if="operateOptions?.length" :class="['table-operate', tableOperateAlign]">
<template
v-for="(item, index) in tableOperateOptions"
v-for="(item, index) in operateOptions"
:key="`tableOperateItem${item.value}${index}`"
>
<el-button
Expand All @@ -229,13 +203,7 @@ defineExpose({
</el-button>
</template>
</div>
<el-table
v-if="tableColumns?.length"
ref="tableRef"
:data="tableData"
show-overflow-tooltip
v-bind="tableProps"
>
<el-table v-if="columns?.length" ref="tableRef" :data show-overflow-tooltip v-bind="tableProps">
<template #append="scope">
<slot name="append" v-bind="scope"></slot>
</template>
Expand All @@ -244,15 +212,11 @@ defineExpose({
</template>
<el-table-column v-if="showSelection" type="selection" fixed="left" width="55" />
<el-table-column v-if="showIndex" type="index" width="50" :index="(index) => index + 1" />
<TableColumn
v-for="(col, index) in tableColumns"
:key="`${col.label}${col.prop}${index}`"
:col
>
<template v-for="slot in getSlots(tableColumns)" #[slot]="scope">
<TableColumn v-for="(col, index) in columns" :key="`${col.label}${col.prop}${index}`" :col>
<template v-for="slot in getSlots(columns)" #[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
<template v-for="slot in getSlots(tableColumns).map((e) => `${e}-header`)" #[slot]="scope">
<template v-for="slot in getSlots(columns).map((e) => `${e}-header`)" #[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
</TableColumn>
Expand Down
113 changes: 113 additions & 0 deletions templates/vue-admin/src/components/vs-tree-select/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
type NodeKey = string | number

/**
* 根据子ID查询其所有父级元素,包含其本身
* @param targetId 要查询的目标id
* @param treeData 树形数据
* @param options 可选参数
* @param options.id id字段别名,默认id
* @param options.label label字段别名,默认label
* @param options.children children子节点别名,默认children
* @param options.returnType 返回所查找元素的类别,可选'ids'(默认)|'labels'|'nodes'
*/
export function findArraryValueFromTreeData(
targetId: NodeKey,
treeData: Record<string, any>[],
options?: {
id?: string
label?: string
children?: string
returnType?: 'ids' | 'labels' | 'nodes'
}
) {
try {
const { returnType = 'ids' } = options ?? {}
if (returnType === 'labels') return getLabels(targetId, toFlatten(treeData), options)
else if (returnType === 'ids') return getIds(targetId, toFlatten(treeData), options)
else return getNodes(targetId, toFlatten(treeData), options)
} catch (error) {
console.error('findArraryValuesFromTreeData: ', error)
}
}

/**
* 判断对象数组
* @param data
*/
export function isArraryObject(data: unknown) {
try {
if (Array.isArray(data)) {
if (data.length) return !!data[0] && data[0].constructor === Object
console.warn('data.length === 0, unable to judge.')
}
return false
} catch (error) {
console.error('isArraryObject ->', error)
}
}

/**
* 拍平树形数据
* @param treeData 树形数据
* @param options 可选参数
* @param options.id id字段别名,默认id
* @param options.children children子节点别名,默认children
* @param options.parentId 节点的父级id,函数内部自动添加,无需传入
*/
export function toFlatten(
treeData: Record<string, any>[],
options?: { id?: string; children?: string; parentId?: NodeKey }
): Record<string, any>[] {
try {
const { id = 'id', children = 'children', parentId } = options ?? {}
return treeData.reduce<Record<string, any>[]>((pre, cur) => {
return [
...pre,
typeof parentId === 'undefined' ? cur : { ...cur, parentId },
...(cur[children]?.length ? toFlatten(cur[children], { parentId: cur[id] }) : [])
]
}, [])
} catch (error) {
console.error('toFlatten: ', error)
return []
}
}

function getIds(targetId: NodeKey, flatData: Record<string, any>[], options?: { id?: string }) {
const { id = 'id' } = options ?? {}
let ids = [targetId]
let child = flatData.find((e) => e[id] === targetId)
while (child && typeof child.parentId !== 'undefined') {
ids = [child.parentId, ...ids]
child = flatData.find((e) => e[id] === child!.parentId)
}
return ids
}

function getLabels(
targetId: NodeKey,
flatData: Record<string, any>[],
options?: { id?: string; label?: string }
) {
const { id = 'id', label = 'label' } = options ?? {}
let child = flatData.find((e) => e[id] === targetId)
let labels: string[] = child && child[label] ? [child[label]] : []
while (child && typeof child.parentId !== 'undefined') {
const find = flatData.find((e) => e[id] === child!.parentId)
labels = [find![label], ...labels]
child = flatData.find((e) => e[id] === child!.parentId)
}
return labels
}

function getNodes(targetId: NodeKey, flatData: Record<string, any>[], options?: { id?: string }) {
const { id = 'id' } = options ?? {}
let child = flatData.find((e) => e[id] === targetId)
let nodes = child ? [child] : []
while (child && typeof child.parentId !== 'undefined') {
const find = flatData.find((e) => e[id] === child!.parentId)
nodes = [find!, ...nodes]
child = flatData.find((e) => e[id] === child!.parentId)
}
return nodes
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Close } from '@element-plus/icons-vue'
import type { TreeKey, TreeNodeData } from 'element-plus/es/components/tree-v2/src/types'
import { type InputInstance, ElTree as MyTree, ElTreeV2 as MyTreeV2 } from 'element-plus'
import type { VsTreeSelectProps, VsTreeSelectValue, VsTreeSelectValueItem } from '.'
import { findArraryValueFromTreeData, isArraryObject } from '@vswift/utils'
import { findArraryValueFromTreeData, isArraryObject } from './util'
const props = withDefaults(defineProps<VsTreeSelectProps>(), {
modelValue: undefined,
Expand Down
15 changes: 15 additions & 0 deletions templates/vue-admin/src/utils/count-down.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* 简易倒计时
* @param seconds 倒计时总秒数
* @param change 每秒变化时的回调
* @param done 倒计时完成时的回调
*/
export function countDown(seconds: number, change: (seconds: number) => void, done?: () => void) {
const timer = setInterval(() => {
if (seconds--) change(seconds)
else {
done && done()
clearInterval(timer)
}
}, 1000)
}
Loading

0 comments on commit 0610786

Please sign in to comment.