hlq-cli 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/README.md +18 -0
- package/bin/index.js +16 -0
- package/lib/aesCreate.js +11 -0
- package/lib/axiosCreate.js +11 -0
- package/lib/create.js +172 -0
- package/lib/echartCreate.js +12 -0
- package/lib/jwtDecodeCreate.js +16 -0
- package/lib/rsaCreate.js +11 -0
- package/lib/stateCreate.js +34 -0
- package/lib/websocketCreate.js +16 -0
- package/package.json +21 -0
- package/templates/.env +1 -0
- package/templates/.env.dev +2 -0
- package/templates/.env.pro +2 -0
- package/templates/index.html +15 -0
- package/templates/package-lock.json +4058 -0
- package/templates/package.json +31 -0
- package/templates/public/config.js +1 -0
- package/templates/public/font/iconfont.css +579 -0
- package/templates/public/font/iconfont.js +1 -0
- package/templates/public/font/iconfont.ttf +0 -0
- package/templates/public/font/iconfont.woff +0 -0
- package/templates/public/font/iconfont.woff2 +0 -0
- package/templates/src/App.vue +35 -0
- package/templates/src/components/chart/barChart.vue +103 -0
- package/templates/src/components/chart/color.ts +43 -0
- package/templates/src/components/chart/lineChart.vue +114 -0
- package/templates/src/components/chart/mapChart.vue +135 -0
- package/templates/src/components/chart/mixedChart.vue +148 -0
- package/templates/src/components/chart/pieChart.vue +104 -0
- package/templates/src/components/chart/radarChart.vue +112 -0
- package/templates/src/components/chart/scatterChart.vue +144 -0
- package/templates/src/components/chart/sunburstChart.vue +183 -0
- package/templates/src/components/descript/index.vue +45 -0
- package/templates/src/components/dialog/index.vue +54 -0
- package/templates/src/components/drawer/index.vue +53 -0
- package/templates/src/components/form/component/cascader.vue +65 -0
- package/templates/src/components/form/component/checkbox.vue +31 -0
- package/templates/src/components/form/component/datePicker.vue +39 -0
- package/templates/src/components/form/component/dateRange.vue +36 -0
- package/templates/src/components/form/component/datetimePicker.vue +25 -0
- package/templates/src/components/form/component/fileUpload.vue +80 -0
- package/templates/src/components/form/component/formFun.ts +132 -0
- package/templates/src/components/form/component/imageUpload.vue +92 -0
- package/templates/src/components/form/component/input.vue +41 -0
- package/templates/src/components/form/component/location.vue +79 -0
- package/templates/src/components/form/component/radio.vue +31 -0
- package/templates/src/components/form/component/select.vue +66 -0
- package/templates/src/components/form/component/textarea.vue +26 -0
- package/templates/src/components/form/component/timePicker.vue +28 -0
- package/templates/src/components/form/component/upload.ts +20 -0
- package/templates/src/components/form/formInterface.ts +115 -0
- package/templates/src/components/form/index.vue +193 -0
- package/templates/src/components/form/item.vue +323 -0
- package/templates/src/components/groupForm/index.vue +91 -0
- package/templates/src/components/icon/index.vue +29 -0
- package/templates/src/components/layout/header.vue +238 -0
- package/templates/src/components/layout/index.vue +167 -0
- package/templates/src/components/layout/menu.vue +130 -0
- package/templates/src/components/layout/sideBarItem.vue +49 -0
- package/templates/src/components/searchBox/height.ts +9 -0
- package/templates/src/components/searchBox/index.vue +265 -0
- package/templates/src/components/table/index.vue +371 -0
- package/templates/src/components/table/table.ts +23 -0
- package/templates/src/components/tree/index.vue +222 -0
- package/templates/src/components/tree/lazyTree.vue +136 -0
- package/templates/src/data.d.ts +4 -0
- package/templates/src/main.ts +18 -0
- package/templates/src/router/index.ts +60 -0
- package/templates/src/store/menuInterface.ts +10 -0
- package/templates/src/store/permission.ts +59 -0
- package/templates/src/store/user.ts +24 -0
- package/templates/src/utils/alioss/index.ts +0 -0
- package/templates/src/utils/axios/http.ts +99 -0
- package/templates/src/utils/axios/index.ts +112 -0
- package/templates/src/utils/axios/service.ts +8 -0
- package/templates/src/utils/crypto/index.ts +28 -0
- package/templates/src/utils/rsa/index.ts +18 -0
- package/templates/src/utils/token/index.ts +6 -0
- package/templates/src/utils/tree/index.ts +74 -0
- package/templates/src/utils/websocket/index.ts +136 -0
- package/templates/src/views/login/index.vue +248 -0
- package/templates/src/views/templete/table.vue +122 -0
- package/templates/src/views/templete/tableConfig.ts +153 -0
- package/templates/tsconfig.app.json +19 -0
- package/templates/tsconfig.json +7 -0
- package/templates/tsconfig.node.json +23 -0
- package/templates/vite.config.ts +34 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-date-picker
|
|
3
|
+
clearable
|
|
4
|
+
v-model="formData[config.key]"
|
|
5
|
+
:type="dateTypeMap.get(config.type)"
|
|
6
|
+
:placeholder="config.placeholder || '请选择' + config.label"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:format="config.format || 'YYYY-MM-DD'"
|
|
9
|
+
:value-format="config.valueFormat || 'YYYY-MM-DD HH:mm:ss'"
|
|
10
|
+
:disabled-date="config.disabledDate"
|
|
11
|
+
style="width: 100%"
|
|
12
|
+
@change="change"
|
|
13
|
+
/>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
interface Props {
|
|
17
|
+
config: FormDateConfig
|
|
18
|
+
data?: Data
|
|
19
|
+
formData: Data
|
|
20
|
+
disabled: boolean
|
|
21
|
+
state: any
|
|
22
|
+
}
|
|
23
|
+
const props = defineProps<Props>()
|
|
24
|
+
|
|
25
|
+
const dateTypeMap = new Map([
|
|
26
|
+
['date', 'datePicker'],
|
|
27
|
+
['dates', 'datesPicker'],
|
|
28
|
+
['week', 'weekPicker'],
|
|
29
|
+
['year', 'yearPicker'],
|
|
30
|
+
['years', 'yearsPicker'],
|
|
31
|
+
['month', 'monthPicker'],
|
|
32
|
+
['months', 'monthsPicker'],
|
|
33
|
+
])
|
|
34
|
+
const emits = defineEmits(['change'])
|
|
35
|
+
const change = (val: any) => {
|
|
36
|
+
emits('change', val)
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-date-picker
|
|
3
|
+
clearable
|
|
4
|
+
v-model="formData[config.key]"
|
|
5
|
+
:type="dateRangeMap.get(config.type)"
|
|
6
|
+
:start-placeholder="config.startPlaceholder || '开始日期'"
|
|
7
|
+
:end-placeholder="config.endPlaceholder || '结束日期'"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
:format="config.format || 'YYYY-MM-DD'"
|
|
10
|
+
:value-format="config.valueFormat || 'YYYY-MM-DD'"
|
|
11
|
+
style="width: 100%"
|
|
12
|
+
@change="change"
|
|
13
|
+
/>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
interface Props {
|
|
17
|
+
config: FormDateRangeConfig
|
|
18
|
+
data?: Data
|
|
19
|
+
formData: Data
|
|
20
|
+
disabled: boolean
|
|
21
|
+
state: any
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const props = defineProps<Props>()
|
|
25
|
+
const dateRangeMap = new Map([
|
|
26
|
+
['dateRange', 'daterange'],
|
|
27
|
+
['monthRange', 'monthrange'],
|
|
28
|
+
['yearRange', 'yearrange'],
|
|
29
|
+
['dateRange', 'datetimerange'],
|
|
30
|
+
])
|
|
31
|
+
const emits = defineEmits(['change'])
|
|
32
|
+
const change = (val: any) => {
|
|
33
|
+
emits('change', val)
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-date-picker
|
|
3
|
+
clearable
|
|
4
|
+
v-model="formData[config.key]"
|
|
5
|
+
:type="dateTypeMap.get(config.type)"
|
|
6
|
+
:placeholder="config.placeholder || '请选择' + config.label"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:format="config.format || 'YYYY-MM-DD'"
|
|
9
|
+
:value-format="config.valueFormat || 'YYYY-MM-DD HH:mm:ss'"
|
|
10
|
+
:disabled-date="config.disabledDate"
|
|
11
|
+
style="width: 100%"
|
|
12
|
+
@change="change"
|
|
13
|
+
/>
|
|
14
|
+
</template>
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
interface Props {
|
|
17
|
+
config: FormDateConfig
|
|
18
|
+
data?: Data
|
|
19
|
+
formData: Data
|
|
20
|
+
disabled: boolean
|
|
21
|
+
state: any
|
|
22
|
+
}
|
|
23
|
+
const props = defineProps<Props>()
|
|
24
|
+
</script>
|
|
25
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-upload
|
|
3
|
+
v-model:file-list="state.fileList"
|
|
4
|
+
action="#"
|
|
5
|
+
:before-upload="beforeUpload"
|
|
6
|
+
multiple
|
|
7
|
+
:limit="config.limit || 10"
|
|
8
|
+
:accept="config.fileType || ''"
|
|
9
|
+
:on-preview="handleFileDownload"
|
|
10
|
+
:on-exceed="handleExceed"
|
|
11
|
+
:on-success="handleSuccess"
|
|
12
|
+
:on-remove="handleRemove"
|
|
13
|
+
:http-request="httpRequest"
|
|
14
|
+
:show-file-list="true"
|
|
15
|
+
list-type="text"
|
|
16
|
+
style="width: 100%"
|
|
17
|
+
:disabled="disabled"
|
|
18
|
+
@change="change"
|
|
19
|
+
>
|
|
20
|
+
<el-button
|
|
21
|
+
type="default"
|
|
22
|
+
:disabled="disabled || state.fileList.length >= (config.limit || 10)"
|
|
23
|
+
>
|
|
24
|
+
点击选取文件上传
|
|
25
|
+
</el-button>
|
|
26
|
+
<template #tip v-if="config.tip">
|
|
27
|
+
<div class="el-upload__tip">
|
|
28
|
+
{{ config.tip }}
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
</el-upload>
|
|
32
|
+
</template>
|
|
33
|
+
<script lang="ts" setup>
|
|
34
|
+
import { upload } from './upload'
|
|
35
|
+
|
|
36
|
+
interface Props {
|
|
37
|
+
config: FormUploadConfig
|
|
38
|
+
data?: Data
|
|
39
|
+
formData: Data
|
|
40
|
+
disabled: boolean
|
|
41
|
+
state: any
|
|
42
|
+
}
|
|
43
|
+
const props = defineProps<Props>()
|
|
44
|
+
const {
|
|
45
|
+
handleFileDownload,
|
|
46
|
+
beforeUpload,
|
|
47
|
+
handleExceed,
|
|
48
|
+
handleSuccess,
|
|
49
|
+
handleRemove,
|
|
50
|
+
httpRequest,
|
|
51
|
+
} = upload(props, props.state)
|
|
52
|
+
const emits = defineEmits(['change'])
|
|
53
|
+
const change = (val: any) => {
|
|
54
|
+
emits('change', val)
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
<style lang="scss" scoped>
|
|
58
|
+
.uploadTip {
|
|
59
|
+
margin-top: 6px;
|
|
60
|
+
font-size: 12px;
|
|
61
|
+
color: #909399;
|
|
62
|
+
line-height: 1.4;
|
|
63
|
+
}
|
|
64
|
+
.hideUploadBtn :deep(.el-upload--picture-card),
|
|
65
|
+
.hideUploadBtn :deep(.el-upload.el-upload--text) {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
/* button 文本列表:文件名可点击下载 */
|
|
69
|
+
.formImageUploadWrap :deep(.el-upload-list--text .el-upload-list__item-name) {
|
|
70
|
+
color: #409eff;
|
|
71
|
+
cursor: pointer;
|
|
72
|
+
&:hover {
|
|
73
|
+
color: #66b1ff;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/* 隐藏「按 Delete 键可删除」提示,保留叉号删除 */
|
|
77
|
+
.formImageUploadWrap :deep(.el-icon--close-tip) {
|
|
78
|
+
display: none !important;
|
|
79
|
+
}
|
|
80
|
+
</style>
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// 常用公式方法处理器
|
|
2
|
+
type ProcessorFn = (...args: any[]) => any
|
|
3
|
+
type ProcessorMap = {
|
|
4
|
+
[key: string]: ProcessorFn
|
|
5
|
+
abs: (val: any) => number
|
|
6
|
+
trim: (val: any) => string
|
|
7
|
+
concat: (str: string | undefined, ...args: any[]) => string
|
|
8
|
+
upper: (val: any) => string
|
|
9
|
+
lower: (val: any) => string
|
|
10
|
+
round: (val: any, precision?: number) => string
|
|
11
|
+
substr: (val: any, start: any, len: undefined) => string
|
|
12
|
+
replace: (val: any, search: string | RegExp, replacement: string) => string
|
|
13
|
+
split: (
|
|
14
|
+
val: any,
|
|
15
|
+
sep: { [Symbol.split](string: string, limit?: number): string[] },
|
|
16
|
+
) => string[]
|
|
17
|
+
join: (arr: any[], sep: string | undefined) => string
|
|
18
|
+
length: (val: any) => number
|
|
19
|
+
parseInt: (val: string, radix?: number) => number
|
|
20
|
+
parseFloat: (val: string) => number
|
|
21
|
+
}
|
|
22
|
+
const processors: ProcessorMap = {
|
|
23
|
+
// 取绝对值
|
|
24
|
+
abs: (val: any) => Math.abs(Number(val)),
|
|
25
|
+
// 去除字符串首尾空格
|
|
26
|
+
trim: (val: any) => String(val).trim(),
|
|
27
|
+
// 用指定分隔符拼接参数
|
|
28
|
+
concat: (str: string | undefined, ...args: any[]) => {
|
|
29
|
+
return args.join(str)
|
|
30
|
+
},
|
|
31
|
+
// 转大写
|
|
32
|
+
upper: (val: any) => String(val).toUpperCase(),
|
|
33
|
+
// 转小写
|
|
34
|
+
lower: (val: any) => String(val).toLowerCase(),
|
|
35
|
+
// 四舍五入到指定小数位
|
|
36
|
+
round: (val: any, precision = 0) => Number(val).toFixed(Number(precision)),
|
|
37
|
+
// 字符串截取
|
|
38
|
+
substr: (val: any, start: any, len: undefined) =>
|
|
39
|
+
String(val).slice(
|
|
40
|
+
Number(start),
|
|
41
|
+
len !== undefined ? Number(start) + Number(len) : undefined,
|
|
42
|
+
),
|
|
43
|
+
// 替换字符串
|
|
44
|
+
replace: (val: any, search: string | RegExp, replacement: string) =>
|
|
45
|
+
String(val).replace(new RegExp(search, 'g'), replacement),
|
|
46
|
+
// 分割字符串
|
|
47
|
+
split: (
|
|
48
|
+
val: any,
|
|
49
|
+
sep: { [Symbol.split](string: string, limit?: number): string[] },
|
|
50
|
+
) => String(val).split(sep),
|
|
51
|
+
// 数组/字符串拼接
|
|
52
|
+
join: (arr: any[], sep: string | undefined) =>
|
|
53
|
+
Array.isArray(arr) ? arr.join(sep) : String(arr).split(',').join(sep),
|
|
54
|
+
// 获取长度
|
|
55
|
+
length: (val: any) => String(val).length,
|
|
56
|
+
// 字符串转整数
|
|
57
|
+
parseInt: (val: string, radix = 10) => parseInt(val, Number(radix)),
|
|
58
|
+
// 字符串转浮点数
|
|
59
|
+
parseFloat: (val: string) => parseFloat(val),
|
|
60
|
+
}
|
|
61
|
+
const getDataValue = (arg: string, data: any) => {
|
|
62
|
+
// 如果 arg 是 ${_xxx_} 形式且 xxx 中没有 .
|
|
63
|
+
if (/^\$\{_(\w+)_\}$/.test(arg)) {
|
|
64
|
+
const key = arg.match(/^\$\{_(\w+)_\}$/)?.[1]
|
|
65
|
+
if (key && data && typeof data === 'object' && key in data) {
|
|
66
|
+
return data[key]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
arg = arg.replace(/\$\{(_\w+(\.\w+)*_)\}/g, (_, key) => `${key}`)
|
|
70
|
+
// 判断 arg 中是否有 _任意字串.任意_
|
|
71
|
+
if (/_(\w+(\.\w+)*)_/.test(arg)) {
|
|
72
|
+
const argReplaced = arg.replace(
|
|
73
|
+
/_(\w+(\.\w+)*)_/g,
|
|
74
|
+
(_: any, key: string) => {
|
|
75
|
+
// 支持多级属性访问
|
|
76
|
+
const value = key
|
|
77
|
+
.split('.')
|
|
78
|
+
.reduce((acc: { [x: string]: any }, cur: string | number) => {
|
|
79
|
+
console.warn('匹配数值:', acc, cur)
|
|
80
|
+
if (acc?.[cur] === undefined) {
|
|
81
|
+
console.error('匹配数值为空请查看配置信息:', key)
|
|
82
|
+
return ''
|
|
83
|
+
}
|
|
84
|
+
return acc?.[cur]
|
|
85
|
+
}, data)
|
|
86
|
+
return String(value)
|
|
87
|
+
},
|
|
88
|
+
)
|
|
89
|
+
return getDataValue(argReplaced, data)
|
|
90
|
+
} else {
|
|
91
|
+
return arg
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ${_userData.id_}
|
|
95
|
+
export const proessParams = (valueStr: string, data: Data) => {
|
|
96
|
+
let value = getDataValue(valueStr, data) // 递归解析参数
|
|
97
|
+
if (typeof value !== 'string') {
|
|
98
|
+
return value
|
|
99
|
+
}
|
|
100
|
+
const match = value.match(/(\w+)\((.*?)\)/) // 匹配 "func(arg)"
|
|
101
|
+
if (match) {
|
|
102
|
+
const [str, func, arg] = match
|
|
103
|
+
value = value.replace(str, processors[func]?.(...arg.split(',')))
|
|
104
|
+
proessParams(value, data)
|
|
105
|
+
} else {
|
|
106
|
+
return value
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export const proessObjParams = (valueStr: Data, data: Data) => {
|
|
110
|
+
for (const key in valueStr) {
|
|
111
|
+
if (typeof valueStr[key] === 'string') {
|
|
112
|
+
valueStr[key] = proessParams(valueStr[key], data)
|
|
113
|
+
} else if (typeof valueStr[key] === 'object') {
|
|
114
|
+
valueStr[key] = proessObjParams(valueStr[key], data)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return valueStr
|
|
118
|
+
}
|
|
119
|
+
export const proessAnyParams = (valueStr: any, data: Data) => {
|
|
120
|
+
let value
|
|
121
|
+
if (typeof valueStr === 'string') {
|
|
122
|
+
value = proessParams(valueStr, data)
|
|
123
|
+
} else if (typeof valueStr === 'object') {
|
|
124
|
+
value = proessObjParams(valueStr, data)
|
|
125
|
+
} else {
|
|
126
|
+
value = valueStr
|
|
127
|
+
}
|
|
128
|
+
if (typeof value === 'string') {
|
|
129
|
+
value = JSON.parse(value)
|
|
130
|
+
}
|
|
131
|
+
return value
|
|
132
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="formImageUploadWrap"
|
|
4
|
+
:class="{ hideUploadBtn: state.fileList.length >= (config.limit || 10) }"
|
|
5
|
+
>
|
|
6
|
+
<!-- picture-card:原卡片图床上传 -->
|
|
7
|
+
<el-upload
|
|
8
|
+
v-model:file-list="state.fileList"
|
|
9
|
+
action="#"
|
|
10
|
+
:before-upload="beforeUpload"
|
|
11
|
+
list-type="picture-card"
|
|
12
|
+
multiple
|
|
13
|
+
:limit="config.limit || 10"
|
|
14
|
+
:on-preview="handleFileDownload"
|
|
15
|
+
:on-exceed="handleExceed"
|
|
16
|
+
:on-success="handleSuccess"
|
|
17
|
+
:on-remove="handleRemove"
|
|
18
|
+
:http-request="httpRequest"
|
|
19
|
+
drag
|
|
20
|
+
accept="image/*"
|
|
21
|
+
style="width: 100%"
|
|
22
|
+
:disabled="disabled"
|
|
23
|
+
@change="change"
|
|
24
|
+
>
|
|
25
|
+
<div
|
|
26
|
+
class="imageBox"
|
|
27
|
+
:style="{
|
|
28
|
+
cursor:
|
|
29
|
+
state.fileList.length >= (config.limit || 10) ? 'not-allowed' : '',
|
|
30
|
+
}"
|
|
31
|
+
>
|
|
32
|
+
<el-icon>
|
|
33
|
+
<Plus />
|
|
34
|
+
</el-icon>
|
|
35
|
+
</div>
|
|
36
|
+
</el-upload>
|
|
37
|
+
|
|
38
|
+
<div v-if="config.tip" class="uploadTip">{{ config.tip }}</div>
|
|
39
|
+
|
|
40
|
+
<el-dialog
|
|
41
|
+
v-model="state.dialogVisible"
|
|
42
|
+
style="display: flex; justify-content: center; align-items: center"
|
|
43
|
+
>
|
|
44
|
+
<img w-full :src="state.dialogImageUrl" />
|
|
45
|
+
</el-dialog>
|
|
46
|
+
</div>
|
|
47
|
+
</template>
|
|
48
|
+
<script lang="ts" setup>
|
|
49
|
+
import { Plus } from '@element-plus/icons-vue'
|
|
50
|
+
import { computed } from 'vue'
|
|
51
|
+
import { upload } from './upload'
|
|
52
|
+
|
|
53
|
+
interface Props {
|
|
54
|
+
config: FormUploadConfig
|
|
55
|
+
data?: Data
|
|
56
|
+
formData: Data
|
|
57
|
+
disabled: boolean
|
|
58
|
+
state: any
|
|
59
|
+
}
|
|
60
|
+
const props = defineProps<Props>()
|
|
61
|
+
|
|
62
|
+
const imageAccept = computed(() => {
|
|
63
|
+
const ft = props.config.fileType
|
|
64
|
+
if (!ft || ft === '*') return 'image/*'
|
|
65
|
+
return ft
|
|
66
|
+
.split(',')
|
|
67
|
+
.map((s) => `.${s.trim().toLowerCase()}`)
|
|
68
|
+
.join(',')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const {
|
|
72
|
+
handleFileDownload,
|
|
73
|
+
beforeUpload,
|
|
74
|
+
handleExceed,
|
|
75
|
+
handleSuccess,
|
|
76
|
+
handleRemove,
|
|
77
|
+
httpRequest,
|
|
78
|
+
} = upload(props, props.state)
|
|
79
|
+
const emits = defineEmits(['change'])
|
|
80
|
+
const change = (val: any) => {
|
|
81
|
+
emits('change', val)
|
|
82
|
+
}
|
|
83
|
+
</script>
|
|
84
|
+
<style lang="scss" scoped>
|
|
85
|
+
:deep() {
|
|
86
|
+
.el-upload-dragger {
|
|
87
|
+
display: flex;
|
|
88
|
+
justify-content: center !important;
|
|
89
|
+
align-items: center !important;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-input
|
|
3
|
+
clearable
|
|
4
|
+
v-model="formData[config.key]"
|
|
5
|
+
:placeholder="disabled ? '' : config.placeholder || '请输入' + config.label"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
:parser="parser"
|
|
8
|
+
:formatter="parser"
|
|
9
|
+
:show-password="config.type === 'password'"
|
|
10
|
+
:autocomplete="config.type === 'password' ? 'new-password' : 'on'"
|
|
11
|
+
@keyup.enter="enter"
|
|
12
|
+
style="width: 100%"
|
|
13
|
+
@change="change"
|
|
14
|
+
></el-input>
|
|
15
|
+
</template>
|
|
16
|
+
<script lang="ts" setup>
|
|
17
|
+
interface Props {
|
|
18
|
+
config: FormInputConfig
|
|
19
|
+
data?: Data
|
|
20
|
+
formData: Data
|
|
21
|
+
disabled: boolean
|
|
22
|
+
state: any
|
|
23
|
+
}
|
|
24
|
+
const props = defineProps<Props>()
|
|
25
|
+
// 输入框格式化
|
|
26
|
+
const parser = (value: string) => {
|
|
27
|
+
if (props.config.type === 'number') {
|
|
28
|
+
return value.replace(/[^0-9.-]/g, '')
|
|
29
|
+
} else {
|
|
30
|
+
return value
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const emits = defineEmits(['enter', 'change'])
|
|
34
|
+
const enter = () => {
|
|
35
|
+
emits('enter')
|
|
36
|
+
}
|
|
37
|
+
const change = (val: any) => {
|
|
38
|
+
emits('change', val)
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div style="display: flex; gap: 16px" class="w100">
|
|
3
|
+
<el-input
|
|
4
|
+
clearable
|
|
5
|
+
v-model="formData[config.keys[0]]"
|
|
6
|
+
:placeholder="disabled ? '' : '请输入' + config.labels[0]"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
style="width: 100%"
|
|
9
|
+
></el-input>
|
|
10
|
+
<el-input
|
|
11
|
+
clearable
|
|
12
|
+
v-model="formData[config.keys[1]]"
|
|
13
|
+
:placeholder="disabled ? '' : '请输入' + config.labels[1]"
|
|
14
|
+
:disabled="disabled"
|
|
15
|
+
style="width: 100%"
|
|
16
|
+
></el-input>
|
|
17
|
+
<el-button type="primary" @click="open">查询坐标</el-button>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<Dialog
|
|
21
|
+
ref="dialogRef"
|
|
22
|
+
v-model:modelValue="state.visible"
|
|
23
|
+
title="请在地图确认对应的位置后,在当前坐标点如下区域点击复制按钮,再关闭弹窗"
|
|
24
|
+
width="99%"
|
|
25
|
+
:footerShow="false"
|
|
26
|
+
>
|
|
27
|
+
<div style="height: 60vh">
|
|
28
|
+
<!-- <div>请在地图确认对应的位置后,在当前坐标点如下区域点击复制按钮,再关闭弹窗</div> -->
|
|
29
|
+
<iframe
|
|
30
|
+
src="https://api.map.baidu.com/lbsapi/getpoint/index.html"
|
|
31
|
+
frameborder="0"
|
|
32
|
+
style="width: 100%; height: 100%"
|
|
33
|
+
allow="accelerometer 'self'"
|
|
34
|
+
></iframe>
|
|
35
|
+
</div>
|
|
36
|
+
</Dialog>
|
|
37
|
+
</template>
|
|
38
|
+
<script lang="ts" setup>
|
|
39
|
+
import Dialog from "@/components/dialog/index.vue";
|
|
40
|
+
import { reactive, watch } from "vue";
|
|
41
|
+
interface Props {
|
|
42
|
+
config?: FormLocationConfig;
|
|
43
|
+
data?: Data;
|
|
44
|
+
formData: Data;
|
|
45
|
+
disabled: boolean;
|
|
46
|
+
state: any;
|
|
47
|
+
}
|
|
48
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
49
|
+
config: () => {
|
|
50
|
+
return {
|
|
51
|
+
type: "location",
|
|
52
|
+
label: "位置",
|
|
53
|
+
key: "location",
|
|
54
|
+
labels: ["经度", "纬度"],
|
|
55
|
+
keys: ["longitude", "latitude"],
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
const state = reactive({
|
|
60
|
+
visible: false,
|
|
61
|
+
});
|
|
62
|
+
const open = () => {
|
|
63
|
+
state.visible = true;
|
|
64
|
+
};
|
|
65
|
+
watch(
|
|
66
|
+
() => state.visible,
|
|
67
|
+
async () => {
|
|
68
|
+
if (!state.visible) {
|
|
69
|
+
let val = await navigator.clipboard.readText();
|
|
70
|
+
|
|
71
|
+
if (/^-?\d+(\.\d+)?,\-?\d+(\.\d+)?$/.test(val)) {
|
|
72
|
+
props.formData[props.config.keys[0]] = val.split(",")[0];
|
|
73
|
+
props.formData[props.config.keys[1]] = val.split(",")[1];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
</script>
|
|
79
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-radio-group
|
|
3
|
+
v-model="formData[config.key]"
|
|
4
|
+
style="width: 100%"
|
|
5
|
+
@change="change"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
>
|
|
8
|
+
<el-radio
|
|
9
|
+
v-for="item in config.options"
|
|
10
|
+
:key="item.value"
|
|
11
|
+
:value="item.value"
|
|
12
|
+
>
|
|
13
|
+
{{ item.label }}
|
|
14
|
+
</el-radio>
|
|
15
|
+
</el-radio-group>
|
|
16
|
+
</template>
|
|
17
|
+
<script lang="ts" setup>
|
|
18
|
+
interface Props {
|
|
19
|
+
config: FormCheckBoxConfig
|
|
20
|
+
data?: Data
|
|
21
|
+
formData: Data
|
|
22
|
+
disabled: boolean
|
|
23
|
+
state: any
|
|
24
|
+
}
|
|
25
|
+
const props = defineProps<Props>()
|
|
26
|
+
const emits = defineEmits(['change'])
|
|
27
|
+
const change = (val: any) => {
|
|
28
|
+
emits('change', val)
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-select-v2
|
|
3
|
+
clearable
|
|
4
|
+
ref="cascaderRef"
|
|
5
|
+
v-model="formData[config.key]"
|
|
6
|
+
:placeholder="config.placeholder || '请选择' + config.label"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
style="width: 100%"
|
|
9
|
+
:props="props.state.cascaderProp"
|
|
10
|
+
:multiple="config.isMore"
|
|
11
|
+
:options="showList"
|
|
12
|
+
filterable
|
|
13
|
+
:filter-method="filterselectMethod"
|
|
14
|
+
@keyup.enter="selectenter"
|
|
15
|
+
@change="change"
|
|
16
|
+
>
|
|
17
|
+
</el-select-v2>
|
|
18
|
+
</template>
|
|
19
|
+
<script lang="ts" setup>
|
|
20
|
+
import { debounce } from 'lodash'
|
|
21
|
+
import { reactive, ref, watch } from 'vue'
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
config: FormSelectConfig
|
|
25
|
+
data?: Data
|
|
26
|
+
formData: Data
|
|
27
|
+
disabled: boolean
|
|
28
|
+
state: any
|
|
29
|
+
}
|
|
30
|
+
const props = defineProps<Props>()
|
|
31
|
+
const cascaderRef = ref()
|
|
32
|
+
const showList = ref<Data[]>(props.config.options || [])
|
|
33
|
+
const filterselectMethod = (keyword: string) => {
|
|
34
|
+
// 正常过滤逻辑
|
|
35
|
+
showList.value = (
|
|
36
|
+
props.config.options && props.config.options.length
|
|
37
|
+
? props.config.options
|
|
38
|
+
: props.state.options
|
|
39
|
+
).filter((item: any) => {
|
|
40
|
+
return item[props.state.cascaderProp.label || 'label'].indexOf(keyword) > -1
|
|
41
|
+
})
|
|
42
|
+
if (keyword) {
|
|
43
|
+
selectdebounce()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const selectdebounce = debounce(() => {
|
|
47
|
+
if (showList.value.length > 0) {
|
|
48
|
+
props.formData[props.config.key] =
|
|
49
|
+
showList.value[0][props.state.cascaderProp.value || 'value']
|
|
50
|
+
}
|
|
51
|
+
}, 1000)
|
|
52
|
+
const selectenter = () => {
|
|
53
|
+
cascaderRef.value.blur()
|
|
54
|
+
}
|
|
55
|
+
const emits = defineEmits(['change'])
|
|
56
|
+
const change = (val: any) => {
|
|
57
|
+
emits('change', val)
|
|
58
|
+
}
|
|
59
|
+
watch(
|
|
60
|
+
() => props.state.options,
|
|
61
|
+
(val) => {
|
|
62
|
+
showList.value = val
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
</script>
|
|
66
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-input
|
|
3
|
+
clearable
|
|
4
|
+
type="textarea"
|
|
5
|
+
v-model="formData[config.key]"
|
|
6
|
+
:placeholder="disabled ? '' : config.placeholder || '请输入' + config.label"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
style="width: 100%"
|
|
9
|
+
@change="change"
|
|
10
|
+
></el-input>
|
|
11
|
+
</template>
|
|
12
|
+
<script lang="ts" setup>
|
|
13
|
+
interface Props {
|
|
14
|
+
config: FormInputConfig;
|
|
15
|
+
data?: Data;
|
|
16
|
+
formData: Data;
|
|
17
|
+
disabled: boolean;
|
|
18
|
+
state: any;
|
|
19
|
+
}
|
|
20
|
+
const props = defineProps<Props>();
|
|
21
|
+
const emits = defineEmits(["change"]);
|
|
22
|
+
const change = (val: any) => {
|
|
23
|
+
emits("change", val);
|
|
24
|
+
};
|
|
25
|
+
</script>
|
|
26
|
+
<style lang="scss" scoped></style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-time-picker
|
|
3
|
+
clearable
|
|
4
|
+
v-model="formData[config.key]"
|
|
5
|
+
:placeholder="config.placeholder || '请选择' + config.label"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
:format="config.format"
|
|
8
|
+
:value-format="config.valueFormat"
|
|
9
|
+
style="width: 100%"
|
|
10
|
+
@change="change"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
<script lang="ts" setup>
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
config: FormDateConfig;
|
|
17
|
+
data?: Data;
|
|
18
|
+
formData: Data;
|
|
19
|
+
disabled: boolean;
|
|
20
|
+
state: any;
|
|
21
|
+
}
|
|
22
|
+
const props = defineProps<Props>();
|
|
23
|
+
const emits = defineEmits(["change"]);
|
|
24
|
+
const change = (val: any) => {
|
|
25
|
+
emits("change", val);
|
|
26
|
+
};
|
|
27
|
+
</script>
|
|
28
|
+
<style lang="scss" scoped></style>
|