@jzt-packages/components 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +68 -0
- package/src/JztBackTop/index.vue +255 -0
- package/src/JztButtonList/index.vue +88 -0
- package/src/JztChart/index.vue +95 -0
- package/src/JztCharts/index.vue +317 -0
- package/src/JztClassTabs/index.vue +156 -0
- package/src/JztDateSelect/dateSelect.vue +186 -0
- package/src/JztDateSelect/dateType.vue +54 -0
- package/src/JztDateSelect/index.ts +135 -0
- package/src/JztDateSelect/interface/index.ts +13 -0
- package/src/JztDialog/index.vue +249 -0
- package/src/JztEllipsisTooltip/index.vue +61 -0
- package/src/JztEmpty/index.vue +45 -0
- package/src/JztErrorPage/403.vue +30 -0
- package/src/JztErrorPage/404.vue +19 -0
- package/src/JztErrorPage/500.vue +18 -0
- package/src/JztErrorPage/assets/401.png +0 -0
- package/src/JztErrorPage/assets/403.png +0 -0
- package/src/JztErrorPage/assets/404.png +0 -0
- package/src/JztErrorPage/assets/500.png +0 -0
- package/src/JztErrorPage/index.scss +35 -0
- package/src/JztErrorPage/index.vue +35 -0
- package/src/JztFilePreview/components/pdfViewer.vue +221 -0
- package/src/JztFilePreview/hooks/useImageMethod.ts +256 -0
- package/src/JztFilePreview/index.scss +171 -0
- package/src/JztFilePreview/index.vue +68 -0
- package/src/JztFilePreview/interface/index.ts +18 -0
- package/src/JztFilePreview/previewFile.vue +371 -0
- package/src/JztFormGrid/README.md +520 -0
- package/src/JztFormGrid/components/formItem.vue +209 -0
- package/src/JztFormGrid/components/formItemValue.vue +384 -0
- package/src/JztFormGrid/components/showDetailForm.vue +172 -0
- package/src/JztFormGrid/index.scss +60 -0
- package/src/JztFormGrid/index.vue +513 -0
- package/src/JztFormGrid/interface/index.ts +106 -0
- package/src/JztGrid/components/GridItem.vue +68 -0
- package/src/JztGrid/index.vue +179 -0
- package/src/JztGrid/interface/index.ts +6 -0
- package/src/JztImportExcel/assets/delete.png +0 -0
- package/src/JztImportExcel/index.scss +46 -0
- package/src/JztImportExcel/index.vue +430 -0
- package/src/JztImportExcel/interface/index.ts +25 -0
- package/src/JztLabelTitle/index.vue +65 -0
- package/src/JztLeftRightMode/components/CollapseButton.vue +80 -0
- package/src/JztLeftRightMode/components/LeftCard.vue +203 -0
- package/src/JztLeftRightMode/components/LeftLayout.vue +173 -0
- package/src/JztLeftRightMode/components/RightHeader.vue +186 -0
- package/src/JztLeftRightMode/components/RightLayout.vue +235 -0
- package/src/JztLeftRightMode/components/RightTableHeader.vue +43 -0
- package/src/JztLeftRightMode/hooks/useCollapse.ts +17 -0
- package/src/JztLeftRightMode/hooks/useDefaultProps.ts +19 -0
- package/src/JztLeftRightMode/hooks/useLeftLayout.ts +201 -0
- package/src/JztLeftRightMode/hooks/useMode.ts +20 -0
- package/src/JztLeftRightMode/hooks/usePrevNext.ts +60 -0
- package/src/JztLeftRightMode/hooks/useRightLayout.ts +215 -0
- package/src/JztLeftRightMode/hooks/useSlots.ts +15 -0
- package/src/JztLeftRightMode/index.ts +3 -0
- package/src/JztLeftRightMode/index.vue +494 -0
- package/src/JztLeftRightMode/types/index.ts +457 -0
- package/src/JztLoading/fullScreen.ts +45 -0
- package/src/JztLoading/index.scss +67 -0
- package/src/JztLoading/index.vue +18 -0
- package/src/JztLogin/components/LoginFooter.vue +17 -0
- package/src/JztLogin/components/LoginForm.vue +99 -0
- package/src/JztLogin/hooks/useLogin.ts +186 -0
- package/src/JztLogin/index.scss +142 -0
- package/src/JztLogin/index.vue +31 -0
- package/src/JztLogin/interface/index.ts +47 -0
- package/src/JztNumericalRange/index.vue +81 -0
- package/src/JztPageCard/comm/datePicker.vue +151 -0
- package/src/JztPageCard/comm/details.vue +60 -0
- package/src/JztPageCard/comm/export.vue +24 -0
- package/src/JztPageCard/comm/tabs.vue +94 -0
- package/src/JztPageCard/comm/tooltip.vue +31 -0
- package/src/JztPageCard/index.vue +287 -0
- package/src/JztPagination/index.vue +70 -0
- package/src/JztProductInfo/components/imagePreview.vue +275 -0
- package/src/JztProductInfo/components/qxUnique.vue +101 -0
- package/src/JztProductInfo/components/records.vue +265 -0
- package/src/JztProductInfo/hooks/useParams.ts +143 -0
- package/src/JztProductInfo/hooks/useQxUnique.tsx +466 -0
- package/src/JztProductInfo/images/defaultProduct.png +0 -0
- package/src/JztProductInfo/index.ts +116 -0
- package/src/JztProductInfo/index.vue +108 -0
- package/src/JztProductInfo/interface/index.ts +15 -0
- package/src/JztQueryDetailTable/index.scss +100 -0
- package/src/JztQueryDetailTable/index.vue +400 -0
- package/src/JztQueryDetailTable/interface/index.ts +10 -0
- package/src/JztQueryTable/QueryTable /345/212/237/350/203/275.md" +1580 -0
- package/src/JztQueryTable/README.md +567 -0
- package/src/JztQueryTable/components/ColSetting.vue +67 -0
- package/src/JztQueryTable/components/ColumnsSetting.vue +404 -0
- package/src/JztQueryTable/components/ColumnsSetting1.vue +220 -0
- package/src/JztQueryTable/components/DeployToAccountLevelSetting.vue +351 -0
- package/src/JztQueryTable/components/Pagination.vue +54 -0
- package/src/JztQueryTable/components/TableColumn.vue +109 -0
- package/src/JztQueryTable/const.ts +1 -0
- package/src/JztQueryTable/hooks/useQueryTable.ts +194 -0
- package/src/JztQueryTable/hooks/useSelection.ts +47 -0
- package/src/JztQueryTable/hooks/useTableSetting.ts +197 -0
- package/src/JztQueryTable/hooks/useTemplate.ts +127 -0
- package/src/JztQueryTable/index.scss +91 -0
- package/src/JztQueryTable/index.vue +1445 -0
- package/src/JztQueryTable/interface/index.ts +185 -0
- package/src/JztRegionSelect/index.vue +134 -0
- package/src/JztSearchForm/components/SearchFormItem.vue +473 -0
- package/src/JztSearchForm/index.vue +530 -0
- package/src/JztSearchForm/interface/index.ts +100 -0
- package/src/JztSelectFilter/index.scss +63 -0
- package/src/JztSelectFilter/index.vue +110 -0
- package/src/JztSelectTable/index.vue +257 -0
- package/src/JztTable/index.scss +72 -0
- package/src/JztTable/index.vue +353 -0
- package/src/JztTable/interface/index.ts +1 -0
- package/src/JztTime/comm/agencySelect.vue +112 -0
- package/src/JztTime/comm/collapseRow.vue +132 -0
- package/src/JztTime/comm/dateSelect.vue +292 -0
- package/src/JztTime/comm/deptSelect.vue +193 -0
- package/src/JztTime/comm/typeSelect.vue +97 -0
- package/src/JztTime/index.ts +216 -0
- package/src/JztTime/index.vue +303 -0
- package/src/JztTime/interface/index.ts +23 -0
- package/src/JztTreeFilter/index.scss +44 -0
- package/src/JztTreeFilter/index.vue +177 -0
- package/src/JztUploadFile/interface/index.ts +21 -0
- package/src/JztUploadFile/multiple.scss +215 -0
- package/src/JztUploadFile/multiple.vue +318 -0
- package/src/JztUploadFile/single.scss +226 -0
- package/src/JztUploadFile/single.vue +274 -0
- package/src/JztUploadImg/Img.vue +294 -0
- package/src/JztUploadImg/Imgs.vue +411 -0
- package/src/JztUploadImg/index.scss +138 -0
- package/src/JztUploadImg/interface/index.ts +22 -0
- package/src/SelectIcon/index.scss +39 -0
- package/src/SelectIcon/index.vue +106 -0
- package/src/SvgIcon/index.vue +22 -0
- package/src/hooks/useAuthButtons.ts +58 -0
- package/src/hooks/useFormByUserType.ts +90 -0
- package/src/hooks/useTableEvents.ts +30 -0
- package/src/hooks/useUploadFileHook.ts +262 -0
- package/src/index.ts +91 -0
- package/src/typings/global.d.ts +101 -0
- package/src/utils/index.ts +107 -0
- package/src/utils/tree.ts +57 -0
- package/tsconfig.json +45 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg :style="iconStyle" aria-hidden="true">
|
|
3
|
+
<use :xlink:href="symbolId" />
|
|
4
|
+
</svg>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts" name="SvgIcon">
|
|
8
|
+
import { computed, CSSProperties } from 'vue'
|
|
9
|
+
|
|
10
|
+
interface SvgProps {
|
|
11
|
+
name: string // 图标的名称 ==> 必传
|
|
12
|
+
prefix?: string // 图标的前缀 ==> 非必传(默认为"icon")
|
|
13
|
+
iconStyle?: CSSProperties // 图标的样式 ==> 非必传
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const props = withDefaults(defineProps<SvgProps>(), {
|
|
17
|
+
prefix: 'icon',
|
|
18
|
+
iconStyle: () => ({ width: '20px', height: '20px' })
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { computed, ref } from 'vue'
|
|
2
|
+
// import { useAuthStore } from '@/stores/modules/auth'
|
|
3
|
+
import { localGet, isEmpty } from '@jzt-spd/utils'
|
|
4
|
+
const { authButtonList } = localGet('SPD-auth') || {}
|
|
5
|
+
const authList = ref<any[]>([])
|
|
6
|
+
authList.value = authButtonList
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 从当前页面 URL 的 hash 中提取 menuId
|
|
10
|
+
* */
|
|
11
|
+
const getMenuIdFromUrl = (): string | null => {
|
|
12
|
+
try {
|
|
13
|
+
const hash = window.location.hash || ''
|
|
14
|
+
const searchPart = hash.includes('?') ? hash.split('?')[1] : ''
|
|
15
|
+
const params = new URLSearchParams(searchPart)
|
|
16
|
+
return params.get('menuId')
|
|
17
|
+
} catch {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @description 页面按钮权限
|
|
24
|
+
* */
|
|
25
|
+
export const useAuthButtons = () => {
|
|
26
|
+
let authButtons = authList.value || []
|
|
27
|
+
const authData = localGet('SPD-auth') || {}
|
|
28
|
+
const authButtonList = authData.authButtonList
|
|
29
|
+
const activeAllMenu = authData.activeAllMenu
|
|
30
|
+
|
|
31
|
+
// 优先从 activeAllMenu 中按 URL 上的 menuId 查找当前页面的权限
|
|
32
|
+
const currentMenuId = getMenuIdFromUrl()
|
|
33
|
+
console.log('优先从 activeAllMenu 中按 URL 上的 menuId 查找当前页面的权限',currentMenuId,activeAllMenu);
|
|
34
|
+
|
|
35
|
+
if (currentMenuId && activeAllMenu && !isEmpty(activeAllMenu[currentMenuId]?.authBtns)) {
|
|
36
|
+
authButtons = activeAllMenu[currentMenuId].authBtns
|
|
37
|
+
console.log('存在!!!');
|
|
38
|
+
} else if (!isEmpty(authButtonList)) {
|
|
39
|
+
// 兼容:activeAllMenu 中没有数据时,走原来的逻辑
|
|
40
|
+
authButtons = authButtonList
|
|
41
|
+
}
|
|
42
|
+
const BUTTONS = computed(() => {
|
|
43
|
+
let currentPageAuthButton: { [key: string]: boolean } = {}
|
|
44
|
+
authButtons?.forEach(item => (currentPageAuthButton[item.operate] = true))
|
|
45
|
+
return currentPageAuthButton
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
BUTTONS
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 判断按钮是否有权限
|
|
54
|
+
export const hasPermission = (hasPerm: string | undefined) => {
|
|
55
|
+
const { BUTTONS } = useAuthButtons()
|
|
56
|
+
if (!hasPerm) return true
|
|
57
|
+
return !!BUTTONS.value[hasPerm]
|
|
58
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { computed, unref, ref } from 'vue'
|
|
2
|
+
// import { useUserStore } from '@/stores/modules/user'
|
|
3
|
+
// const userStore = useUserStore()
|
|
4
|
+
// 用户类型 0平台 1 供应商 2医院
|
|
5
|
+
const userType = ref(0); //computed(() => userStore.UserType)
|
|
6
|
+
/**
|
|
7
|
+
* @description 用户状态判断是否选中第一条
|
|
8
|
+
* */
|
|
9
|
+
export const useFormSetByUserType = (isSetFirstValue, prop) => {
|
|
10
|
+
// const isSetFirst = isSetFirstValue; // 设置第一个 // 为什么 且 非供应商呢 //&& prop !== 'supplierId'
|
|
11
|
+
// const isSetSupplierId = userType.value === 1 && prop === "supplierId"; // 供应商 且 供应商
|
|
12
|
+
// const isAgencyIdd = prop === "agencyId"; // 医疗机构(永远选择第一个)
|
|
13
|
+
// return isSetFirst || isSetSupplierId || isAgencyIdd;
|
|
14
|
+
// console.log(prop,isSetFirstValue);
|
|
15
|
+
|
|
16
|
+
return isSetFirstValue
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/* 获取枚举字典集合
|
|
20
|
+
* queryItem queryItem配置项
|
|
21
|
+
* enumMap 枚举字典集合
|
|
22
|
+
* searchParam 查询表单结合
|
|
23
|
+
* callBack 回调
|
|
24
|
+
*/
|
|
25
|
+
export const useSetEnumMap = async params => {
|
|
26
|
+
const { queryItem, enumMap, callBack, queryFrom, parentItem } = params
|
|
27
|
+
const { prop, isAwait, enum: enumValue, isSetFirstValue, fieldNames,isOnlySetValue } = queryItem
|
|
28
|
+
if (!enumValue) return
|
|
29
|
+
// 是否接口等待
|
|
30
|
+
|
|
31
|
+
if (isAwait && parentItem?.prop) {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
useSetCascaderEnumMap({
|
|
34
|
+
prevProp: parentItem.prop,
|
|
35
|
+
queryItem: queryItem,
|
|
36
|
+
enumMap: enumMap,
|
|
37
|
+
searchParam: queryFrom
|
|
38
|
+
})
|
|
39
|
+
},500)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isAwait) return
|
|
43
|
+
|
|
44
|
+
// 如果当前 enumMap 存在相同的值 return
|
|
45
|
+
if (enumMap.value.has(prop!) && (typeof enumValue === 'function' || enumMap.value.get(prop!) === enumValue)) return
|
|
46
|
+
// 当前 enum 为静态数据,则直接存储到 enumMap
|
|
47
|
+
let list = []
|
|
48
|
+
if (typeof enumValue !== 'function') {
|
|
49
|
+
enumMap.value.set(prop!, unref(enumValue!))
|
|
50
|
+
list =unref(enumValue!) || []
|
|
51
|
+
} else {
|
|
52
|
+
// 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
|
|
53
|
+
enumMap.value.set(prop!, [])
|
|
54
|
+
// 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
|
|
55
|
+
const res = await enumValue()
|
|
56
|
+
list = res?.result || []
|
|
57
|
+
enumMap.value.set(prop!, list)
|
|
58
|
+
}
|
|
59
|
+
if (useFormSetByUserType(isSetFirstValue, prop) || (isOnlySetValue && list?.length == 1)) {
|
|
60
|
+
callBack && callBack(prop, list[0], fieldNames, queryItem)
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/* cascade change 获取接口数据
|
|
64
|
+
* prevProp 联级上一层的prop
|
|
65
|
+
* queryItem queryItem配置项
|
|
66
|
+
* enumMap 枚举字典集合
|
|
67
|
+
* searchParam 查询表单结合
|
|
68
|
+
* callBack 回调
|
|
69
|
+
*/
|
|
70
|
+
export const useSetCascaderEnumMap = async (params) => {
|
|
71
|
+
const { prevProp, queryItem, enumMap, searchParam, callBack } = params;
|
|
72
|
+
const { prop, enum: enumValue, isSetFirstValue, fieldNames, isOnlySetValue } = queryItem;
|
|
73
|
+
if (!enumValue) return;
|
|
74
|
+
let list = []
|
|
75
|
+
// 如果当前 enumMap 存在相同的值 也不return 根据change实时获取
|
|
76
|
+
// 为了防止接口执行慢,而存储慢,导致重复请求,所以预先存储为[],接口返回后再二次存储
|
|
77
|
+
if (typeof enumValue !== "function") {
|
|
78
|
+
enumMap.value.set(prop!, unref(enumValue!));
|
|
79
|
+
list = unref(enumValue!) || []
|
|
80
|
+
} else {
|
|
81
|
+
enumMap.value.set(prop!, [])
|
|
82
|
+
// 当前 enum 为后台数据需要请求数据,则调用该请求接口,并存储到 enumMap
|
|
83
|
+
const res = await enumValue(searchParam[prevProp], searchParam);
|
|
84
|
+
list = res?.result || []
|
|
85
|
+
enumMap.value.set(prop!, list)
|
|
86
|
+
}
|
|
87
|
+
if (useFormSetByUserType(isSetFirstValue, prop) || (isOnlySetValue && list?.length == 1)) {
|
|
88
|
+
callBack && callBack(prop, list[0], fieldNames, queryItem)
|
|
89
|
+
}
|
|
90
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ElMessageBox } from 'element-plus'
|
|
2
|
+
const useButtonClickFn = (item: any, row: any) => {
|
|
3
|
+
let secondConfirm = ''
|
|
4
|
+
if (item.secondConfirm) {
|
|
5
|
+
secondConfirm = item.secondConfirm
|
|
6
|
+
} else if (item.id === 'delete') {
|
|
7
|
+
secondConfirm = `确定${item.text || '删除'}该条数据吗?`
|
|
8
|
+
}
|
|
9
|
+
if (secondConfirm) {
|
|
10
|
+
ElMessageBox.confirm(secondConfirm, '警告', {
|
|
11
|
+
confirmButtonText: '确定',
|
|
12
|
+
cancelButtonText: '取消',
|
|
13
|
+
type: 'warning'
|
|
14
|
+
})
|
|
15
|
+
.then(() => {
|
|
16
|
+
item.fun(row)
|
|
17
|
+
})
|
|
18
|
+
.catch(error => {
|
|
19
|
+
console.log(error)
|
|
20
|
+
})
|
|
21
|
+
} else {
|
|
22
|
+
item.fun(row)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const useTableEvents = () => {
|
|
27
|
+
return {
|
|
28
|
+
useButtonClickFn
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import type { UploadUserFile, UploadRequestOptions } from "element-plus";
|
|
2
|
+
import { debounce } from "lodash-es";
|
|
3
|
+
import { pdfCover } from "@jzt-spd/styles/assets";
|
|
4
|
+
import { isFullUrl, isPdfSuffix, localGetServer, getFileServiceDomains } from "@jzt-spd/utils";
|
|
5
|
+
import { ElNotification } from "element-plus";
|
|
6
|
+
|
|
7
|
+
interface UploadUserFileTypes extends UploadUserFile {
|
|
8
|
+
halfUrl: string;
|
|
9
|
+
isPdf: boolean;
|
|
10
|
+
}
|
|
11
|
+
// const serverObj = localGetServer();
|
|
12
|
+
// const baseDomain = serverObj.fileShowUrl;
|
|
13
|
+
// const baseDomain = getFileServiceDomains()
|
|
14
|
+
// 传入地址,处理成可显示的图片地址
|
|
15
|
+
const getFileShowList = (fileList: UploadUserFileTypes[]) => {
|
|
16
|
+
const baseDomain = getFileServiceDomains() as string
|
|
17
|
+
const _fileList = [] as UploadUserFileTypes[];
|
|
18
|
+
fileList.forEach((item) => {
|
|
19
|
+
if (typeof item === "string") {
|
|
20
|
+
const isPdf = isPdfSuffix(item);
|
|
21
|
+
const url = isFullUrl(item) ? item : baseDomain + item;
|
|
22
|
+
// 如果是pdf,使用pdf封面
|
|
23
|
+
_fileList.push({
|
|
24
|
+
isPdf: isPdf,
|
|
25
|
+
url: isPdf ? pdfCover : url,
|
|
26
|
+
halfUrl: item,
|
|
27
|
+
name: item,
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
const isPdf = isPdfSuffix(item.url);
|
|
31
|
+
const url = isFullUrl(item.url as string) ? item.url : baseDomain + item;
|
|
32
|
+
const items = getFileLists({
|
|
33
|
+
...item,
|
|
34
|
+
isPdf: isPdf,
|
|
35
|
+
url: isPdf ? pdfCover : url,
|
|
36
|
+
});
|
|
37
|
+
_fileList.push(items);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return _fileList;
|
|
41
|
+
};
|
|
42
|
+
// 获取图片地址
|
|
43
|
+
const getFileLists = (item) => {
|
|
44
|
+
return {
|
|
45
|
+
...item,
|
|
46
|
+
url: getFullUrl(item.url),
|
|
47
|
+
halfUrl: item.url,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// 是否是全地址及
|
|
52
|
+
const getFullUrl = (url) => {
|
|
53
|
+
const baseDomain = getFileServiceDomains()
|
|
54
|
+
return isFullUrl(url) ? url : baseDomain + url;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// 获取原始的半地址
|
|
58
|
+
const getHalfFileUrlList = (fileList: UploadUserFileTypes[]) => {
|
|
59
|
+
let halfUrls = fileList.map((item) => item.halfUrl);
|
|
60
|
+
return halfUrls;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @description 文件上传之前判断
|
|
65
|
+
* @param rawFile 选择的文件
|
|
66
|
+
* @param fileSize 选择的文件大小
|
|
67
|
+
* @param fileType 选择的类型后缀
|
|
68
|
+
* */
|
|
69
|
+
interface useUploadBeforeUpload {
|
|
70
|
+
rawFile: File;
|
|
71
|
+
fileSize: number;
|
|
72
|
+
fileType: File.FilePostfixType[];
|
|
73
|
+
}
|
|
74
|
+
const useBeforeUpload = (params: useUploadBeforeUpload) => {
|
|
75
|
+
const { rawFile, fileSize, fileType } = params;
|
|
76
|
+
const isImgSize = rawFile.size / 1024 / 1024 < fileSize;
|
|
77
|
+
//比对后缀
|
|
78
|
+
const postfix = rawFile.name.split(".");
|
|
79
|
+
const filePostfix = ("." +
|
|
80
|
+
postfix[postfix.length - 1]) as File.ImagePostfixType;
|
|
81
|
+
const newfilePostfix = filePostfix.toLowerCase() as File.FilePostfixType;
|
|
82
|
+
const isFileType = fileType.includes(newfilePostfix);
|
|
83
|
+
if (!isFileType) {
|
|
84
|
+
ElNotification({
|
|
85
|
+
title: "温馨提示",
|
|
86
|
+
message: `请上传${fileType.join(",")}格式的文件!`,
|
|
87
|
+
type: "warning",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (!isImgSize)
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
ElNotification({
|
|
93
|
+
title: "温馨提示",
|
|
94
|
+
message: `上传的文件大小不能超过 ${fileSize}M!`,
|
|
95
|
+
type: "warning",
|
|
96
|
+
});
|
|
97
|
+
}, 0);
|
|
98
|
+
return isFileType && isImgSize;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @description 图片上传成功
|
|
103
|
+
* @param response 上传响应结果
|
|
104
|
+
* @param uploadFile 上传的文件
|
|
105
|
+
* */
|
|
106
|
+
interface UploadSuccessParams {
|
|
107
|
+
response: { fileUrl: string } | undefined;
|
|
108
|
+
uploadFile: UploadUserFileTypes;
|
|
109
|
+
_fileList: UploadUserFileTypes[];
|
|
110
|
+
callback?: any;
|
|
111
|
+
formItemContext;
|
|
112
|
+
formContext;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const useUploadSuccess = (params: UploadSuccessParams) => {
|
|
116
|
+
const { response, uploadFile } = params;
|
|
117
|
+
if (!response) return;
|
|
118
|
+
uploadFile.halfUrl = response.fileUrl;
|
|
119
|
+
uploadFile.url = getFullUrl(response.fileUrl);
|
|
120
|
+
const isPdf = isPdfSuffix(response.fileUrl)
|
|
121
|
+
uploadFile.isPdf = isPdf
|
|
122
|
+
uploadFile.url = isPdf ? pdfCover : getFullUrl(response.fileUrl)
|
|
123
|
+
debounceToast(params);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const debounceToast = debounce((params: UploadSuccessParams) => {
|
|
127
|
+
const { formItemContext, formContext, callback, _fileList } = params;
|
|
128
|
+
const halfUrls = getHalfFileUrlList(_fileList);
|
|
129
|
+
callback && callback(halfUrls);
|
|
130
|
+
formItemContext?.prop &&
|
|
131
|
+
formContext?.validateField([formItemContext.prop as string]);
|
|
132
|
+
ElNotification({
|
|
133
|
+
title: "温馨提示",
|
|
134
|
+
message: "文件上传成功!",
|
|
135
|
+
type: "success",
|
|
136
|
+
});
|
|
137
|
+
}, 1000);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @description 删除图片
|
|
141
|
+
* @param _fileList 所以的文件列表
|
|
142
|
+
* @param file 删除的文件
|
|
143
|
+
* */
|
|
144
|
+
interface RemoveParams {
|
|
145
|
+
_fileList: UploadUserFileTypes[];
|
|
146
|
+
file: UploadUserFileTypes;
|
|
147
|
+
}
|
|
148
|
+
const useRemoveFilterList = (params: RemoveParams) => {
|
|
149
|
+
const { _fileList, file } = params;
|
|
150
|
+
const list = _fileList.filter((item) => item.halfUrl !== file.halfUrl);
|
|
151
|
+
// 获取原始的半地址
|
|
152
|
+
const halfUrls = getHalfFileUrlList(list);
|
|
153
|
+
return halfUrls;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
interface UploadParams {
|
|
157
|
+
isMergeUpload?: boolean // 是都合并请求,处理同时选择多张图片同时上传调多次接口的问题
|
|
158
|
+
fileName: string;
|
|
159
|
+
options: UploadRequestOptions;
|
|
160
|
+
api: any;
|
|
161
|
+
}
|
|
162
|
+
function createSyncThrottle(fn, delay = 1000) {
|
|
163
|
+
let isRunning = false // 是否正在执行任务
|
|
164
|
+
let timer = null // 节流定时器
|
|
165
|
+
let argsQueue = [] // 收集每一次调用的参数
|
|
166
|
+
|
|
167
|
+
// 串行执行任务
|
|
168
|
+
async function runTask() {
|
|
169
|
+
if (isRunning || argsQueue.length === 0) return
|
|
170
|
+
|
|
171
|
+
isRunning = true
|
|
172
|
+
// 拷贝当前收集的参数,避免执行中被新数据干扰
|
|
173
|
+
const currentArgsList = [...argsQueue]
|
|
174
|
+
// 清空,准备接收下一轮参数
|
|
175
|
+
argsQueue = []
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
// 把收集到的所有参数数组传给 funcA
|
|
179
|
+
await fn(currentArgsList)
|
|
180
|
+
} catch (err) {
|
|
181
|
+
console.error('funcA 执行异常:', err)
|
|
182
|
+
} finally {
|
|
183
|
+
isRunning = false
|
|
184
|
+
// 如果这期间又有新参数进来,自动触发下一轮
|
|
185
|
+
if (argsQueue.length > 0) {
|
|
186
|
+
timer = setTimeout(runTask, delay)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return function (...args) {
|
|
192
|
+
// 收集当前这一次调用的所有参数
|
|
193
|
+
argsQueue.push(args)
|
|
194
|
+
|
|
195
|
+
// 重置节流计时
|
|
196
|
+
if (timer) clearTimeout(timer)
|
|
197
|
+
timer = setTimeout(runTask, delay)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function funcA(argsList) {
|
|
201
|
+
console.log('开始执行,本次收集到的所有调用参数:', argsList)
|
|
202
|
+
if (argsList.length === 0) return
|
|
203
|
+
const uploadApi = argsList[0][2]
|
|
204
|
+
const fileName = argsList[0][0]
|
|
205
|
+
try {
|
|
206
|
+
let formData = new FormData()
|
|
207
|
+
argsList.forEach((item, index) => {
|
|
208
|
+
const { file } = item[1]
|
|
209
|
+
formData.append(fileName, file)
|
|
210
|
+
})
|
|
211
|
+
if (!uploadApi) return
|
|
212
|
+
const { result } = await uploadApi(formData)
|
|
213
|
+
const url = result
|
|
214
|
+
if (url) {
|
|
215
|
+
const urls = url.split(',')
|
|
216
|
+
urls.forEach((item, index) => {
|
|
217
|
+
const options = argsList[index][1]
|
|
218
|
+
options.onSuccess({ fileUrl: item })
|
|
219
|
+
})
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
const options = argsList[0][1]
|
|
223
|
+
console.log(error)
|
|
224
|
+
options.onError(error as any)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const safeFuncA = createSyncThrottle(funcA, 1000)
|
|
228
|
+
/**
|
|
229
|
+
* @description 图片上传
|
|
230
|
+
* @param params upload所有配置项
|
|
231
|
+
* */
|
|
232
|
+
const useHttpUploadHook = async (params: UploadParams) => {
|
|
233
|
+
const { fileName, options, api } = params;
|
|
234
|
+
if (params.isMergeUpload) {
|
|
235
|
+
safeFuncA(fileName, options, api)
|
|
236
|
+
return
|
|
237
|
+
}
|
|
238
|
+
let formData = new FormData();
|
|
239
|
+
formData.append(fileName, options.file);
|
|
240
|
+
try {
|
|
241
|
+
const uploadApi = api;
|
|
242
|
+
if (!uploadApi) return;
|
|
243
|
+
const { result } = await uploadApi(formData);
|
|
244
|
+
const url = result;
|
|
245
|
+
options.onSuccess({ fileUrl: url });
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.log(error);
|
|
248
|
+
options.onError(error as any);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export const useUploadFileHook = () => {
|
|
253
|
+
return {
|
|
254
|
+
useBeforeUpload,
|
|
255
|
+
getHalfFileUrlList,
|
|
256
|
+
useRemoveFilterList,
|
|
257
|
+
useUploadSuccess,
|
|
258
|
+
useHttpUploadHook,
|
|
259
|
+
getFileShowList,
|
|
260
|
+
getFullUrl,
|
|
261
|
+
};
|
|
262
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import JztBackTop from './JztBackTop/index.vue'
|
|
2
|
+
import JztButtonList from './JztButtonList/index.vue'
|
|
3
|
+
import JztChart from './JztChart/index.vue'
|
|
4
|
+
import JztCharts from './JztCharts/index.vue'
|
|
5
|
+
import JztClassTabs from './JztClassTabs/index.vue'
|
|
6
|
+
import JztDialog from './JztDialog/index.vue'
|
|
7
|
+
import JztEllipsisTooltip from './JztEllipsisTooltip/index.vue'
|
|
8
|
+
import JztEmpty from './JztEmpty/index.vue'
|
|
9
|
+
import JztErrorPage from './JztErrorPage/index.vue'
|
|
10
|
+
import JztFilePreview from './JztFilePreview/index.vue'
|
|
11
|
+
import JztFormGrid from './JztFormGrid/index.vue'
|
|
12
|
+
import JztGridItem from './JztGrid/components/GridItem.vue'
|
|
13
|
+
import JztGrid from './JztGrid/index.vue'
|
|
14
|
+
import JztImportExcel from './JztImportExcel/index.vue'
|
|
15
|
+
import JztLabelTitle from './JztLabelTitle/index.vue'
|
|
16
|
+
import JztRightMode from './JztLeftRightMode/components/RightLayout.vue'
|
|
17
|
+
import JztLeftRightMode from './JztLeftRightMode/index.vue'
|
|
18
|
+
import JztLogin from './JztLogin/index.vue'
|
|
19
|
+
import JztNumericalRange from './JztNumericalRange/index.vue'
|
|
20
|
+
import JztPageCard from './JztPageCard/index.vue'
|
|
21
|
+
import JztProductInfo from './JztProductInfo/index.vue'
|
|
22
|
+
import JztQueryDetailTable from './JztQueryDetailTable/index.vue'
|
|
23
|
+
import JztQueryTable from './JztQueryTable/index.vue'
|
|
24
|
+
import JztRegionSelect from './JztRegionSelect/index.vue'
|
|
25
|
+
import JztSearchFormItem from './JztSearchForm/components/SearchFormItem.vue'
|
|
26
|
+
import JztSearchForm from './JztSearchForm/index.vue'
|
|
27
|
+
import JztSelectFilter from './JztSelectFilter/index.vue'
|
|
28
|
+
import JztSelectTable from './JztSelectTable/index.vue'
|
|
29
|
+
import JztTable from './JztTable/index.vue'
|
|
30
|
+
import JztTime from './JztTime/index.vue'
|
|
31
|
+
import JztTreeFilter from './JztTreeFilter/index.vue'
|
|
32
|
+
import JztUploadMultipleFiles from './JztUploadFile/multiple.vue'
|
|
33
|
+
import JztUploadSingleFile from './JztUploadFile/single.vue'
|
|
34
|
+
import JztUploadImg from './JztUploadImg/Img.vue'
|
|
35
|
+
import JztUploadMultipleImgs from './JztUploadImg/Imgs.vue'
|
|
36
|
+
import JztSvgIcon from './SvgIcon/index.vue'
|
|
37
|
+
|
|
38
|
+
import { showFullScreenLoading, tryHideFullScreenLoading } from './JztLoading/fullScreen'
|
|
39
|
+
|
|
40
|
+
export type {
|
|
41
|
+
ColorType,
|
|
42
|
+
LeftLayoutInstance,
|
|
43
|
+
LeftLayoutProps,
|
|
44
|
+
LeftRightModeInstance,
|
|
45
|
+
Props as LeftRightModeProps,
|
|
46
|
+
RightLayoutInstance,
|
|
47
|
+
RightLayoutProps,
|
|
48
|
+
SearchProps
|
|
49
|
+
} from './JztLeftRightMode/types'
|
|
50
|
+
export { useJztProductInfo } from './JztProductInfo'
|
|
51
|
+
export type { ProTableProps as JztQueryTableProps } from './JztQueryTable/index.vue'
|
|
52
|
+
export {
|
|
53
|
+
JztBackTop,
|
|
54
|
+
JztButtonList,
|
|
55
|
+
JztChart,
|
|
56
|
+
JztCharts,
|
|
57
|
+
JztClassTabs,
|
|
58
|
+
JztDialog,
|
|
59
|
+
JztEllipsisTooltip,
|
|
60
|
+
JztEmpty,
|
|
61
|
+
JztErrorPage,
|
|
62
|
+
JztFilePreview,
|
|
63
|
+
JztFormGrid,
|
|
64
|
+
JztGrid,
|
|
65
|
+
JztGridItem,
|
|
66
|
+
JztImportExcel,
|
|
67
|
+
JztLabelTitle,
|
|
68
|
+
JztLeftRightMode,
|
|
69
|
+
JztLogin,
|
|
70
|
+
JztNumericalRange,
|
|
71
|
+
JztPageCard,
|
|
72
|
+
JztProductInfo,
|
|
73
|
+
JztQueryDetailTable,
|
|
74
|
+
JztQueryTable,
|
|
75
|
+
JztRegionSelect,
|
|
76
|
+
JztRightMode,
|
|
77
|
+
JztSearchForm,
|
|
78
|
+
JztSearchFormItem,
|
|
79
|
+
JztSelectFilter,
|
|
80
|
+
JztSelectTable,
|
|
81
|
+
JztSvgIcon,
|
|
82
|
+
JztTable,
|
|
83
|
+
JztTime,
|
|
84
|
+
JztTreeFilter,
|
|
85
|
+
JztUploadImg,
|
|
86
|
+
JztUploadMultipleFiles,
|
|
87
|
+
JztUploadMultipleImgs,
|
|
88
|
+
JztUploadSingleFile,
|
|
89
|
+
showFullScreenLoading,
|
|
90
|
+
tryHideFullScreenLoading
|
|
91
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* Menu */
|
|
2
|
+
declare namespace Menu {
|
|
3
|
+
interface MenuOptions {
|
|
4
|
+
path: string;
|
|
5
|
+
name: string;
|
|
6
|
+
component?: string | (() => Promise<unknown>);
|
|
7
|
+
redirect?: string;
|
|
8
|
+
meta: MetaProps;
|
|
9
|
+
children?: MenuOptions[];
|
|
10
|
+
id?: string;
|
|
11
|
+
level?: number;
|
|
12
|
+
menuType?: number;
|
|
13
|
+
parentId?: string;
|
|
14
|
+
parentName?: string;
|
|
15
|
+
sort?: number;
|
|
16
|
+
}
|
|
17
|
+
interface MetaProps {
|
|
18
|
+
icon: string;
|
|
19
|
+
title: string;
|
|
20
|
+
activeMenu?: string;
|
|
21
|
+
isLink?: string;
|
|
22
|
+
isHide: boolean;
|
|
23
|
+
isFull: boolean;
|
|
24
|
+
isAffix: boolean;
|
|
25
|
+
isKeepAlive: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface authButtonOptions {
|
|
28
|
+
id: string;
|
|
29
|
+
menuCod: string;
|
|
30
|
+
menuId: string;
|
|
31
|
+
menuName: string;
|
|
32
|
+
operate: string;
|
|
33
|
+
operateNam: string;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 分页响应参数
|
|
38
|
+
|
|
39
|
+
/* FileType */
|
|
40
|
+
declare namespace File {
|
|
41
|
+
type ImageMimeType =
|
|
42
|
+
| "image/apng"
|
|
43
|
+
| "image/bmp"
|
|
44
|
+
| "image/gif"
|
|
45
|
+
| "image/jpeg"
|
|
46
|
+
| "image/pjpeg"
|
|
47
|
+
| "image/png"
|
|
48
|
+
| "image/svg+xml"
|
|
49
|
+
| "image/tiff"
|
|
50
|
+
| "image/webp"
|
|
51
|
+
| "image/x-icon";
|
|
52
|
+
|
|
53
|
+
type ExcelMimeType =
|
|
54
|
+
| "application/vnd.ms-excel"
|
|
55
|
+
| "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
56
|
+
type FileMimeType =
|
|
57
|
+
| "image/jpeg"
|
|
58
|
+
| "image/pjpeg"
|
|
59
|
+
| "image/png"
|
|
60
|
+
| "image/webp"
|
|
61
|
+
| "image/x-icon"
|
|
62
|
+
| "application/pdf";
|
|
63
|
+
|
|
64
|
+
type FilePostfixType = ".jpeg" | ".png" | ".jpg" | ".pdf";
|
|
65
|
+
type ImagePostfixType = ".jpeg" | ".png" | ".jpg";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Vite */
|
|
69
|
+
declare type Recordable<T = any> = Record<string, T>;
|
|
70
|
+
|
|
71
|
+
declare interface ViteEnv {
|
|
72
|
+
VITE_USER_NODE_ENV: "development" | "production" | "test";
|
|
73
|
+
VITE_GLOB_APP_TITLE: string;
|
|
74
|
+
VITE_PORT: number;
|
|
75
|
+
VITE_OPEN: boolean;
|
|
76
|
+
VITE_REPORT: boolean;
|
|
77
|
+
VITE_ROUTER_MODE: "hash" | "history";
|
|
78
|
+
VITE_BUILD_COMPRESS: "gzip" | "brotli" | "gzip,brotli" | "none";
|
|
79
|
+
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE: boolean;
|
|
80
|
+
VITE_DROP_CONSOLE: boolean;
|
|
81
|
+
VITE_DEVTOOLS: boolean;
|
|
82
|
+
VITE_PUBLIC_PATH: string;
|
|
83
|
+
VITE_API_URL: string;
|
|
84
|
+
VITE_PROXY: [string, string][];
|
|
85
|
+
VITE_CODEINSPECTOR: boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface ImportMetaEnv extends ViteEnv {
|
|
89
|
+
__: unknown;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* __APP_INFO__ */
|
|
93
|
+
declare const __APP_INFO__: {
|
|
94
|
+
pkg: {
|
|
95
|
+
name: string;
|
|
96
|
+
version: string;
|
|
97
|
+
dependencies: Recordable<string>;
|
|
98
|
+
devDependencies: Recordable<string>;
|
|
99
|
+
};
|
|
100
|
+
lastBuildTime: string;
|
|
101
|
+
};
|