Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
data-table
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Authored by
hookehuyr
2022-11-21 15:25:26 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
e89d449dd8b7de8bc11e57585f35a0494811e4a2
e89d449d
1 parent
77d90328
组件注释调整优化
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
154 additions
and
95 deletions
src/components/AreaPickerField/index.vue
src/components/CalendarField/index.vue
src/components/CheckboxField/index.vue
src/components/DatePickerField/index.vue
src/components/DateTimePickerField/index.vue
src/components/IdentityField/index.vue
src/components/ImageUploaderField/index.vue
src/components/PhoneField/index.vue
src/components/RadioField/index.vue
src/components/RatePickerField/index.vue
src/components/TextField/index.vue
src/components/TimePickerField/index.vue
src/hooks/useComponentType.js
src/components/AreaPickerField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-30 14:32:11
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-07 16:05:51
* @LastEditTime: 2022-
11-21 14:32:24
* @FilePath: /data-table/src/components/AreaPickerField/index.vue
* @Description:
文件描述
* @Description:
省市区选择控件
-->
<template>
<div class="area-picker-field">
<div class="label">{{ item.label }}<span v-if="item.required"> *</span></div>
<van-field v-model="item.value" is-link readonly :name="item.key" :required="item.required"
:placeholder="item.placeholder" :rules="item.rules" @click="showPicker = true" :border="false" />
<van-field name="address" v-model="item.address" placeholder="详细地址" :border="false" />
<van-field
v-model="item.value"
is-link
readonly
:name="item.key"
:required="item.required"
:placeholder="item.placeholder"
:rules="item.rules"
@click="showPicker = true"
:border="false"
/>
<van-field
name="address"
v-model="item.address"
placeholder="详细地址"
:border="false"
/>
<van-popup v-model:show="showPicker" position="bottom">
<van-area name="city_code" v-model="item.city_code" title="" :area-list="areaList" @confirm="onConfirm"
@cancel="showPicker = false" />
<van-area
name="city_code"
v-model="item.city_code"
title=""
:area-list="areaList"
@confirm="onConfirm"
@cancel="showPicker = false"
/>
</van-popup>
</div>
</template>
<script setup>
import { areaList } from
'@vant/area-data'
;
import { areaList } from
"@vant/area-data"
;
const props = defineProps({
item: Object
item: Object
,
});
const address = ref(
'')
const address = ref(
"");
const showPicker = ref(false);
const fieldValue = ref(
''
);
const fieldValue = ref(
""
);
const onConfirm = ({ selectedOptions }) => {
props.item.value = selectedOptions.map((option) => option.text).join(
'/'
);
props.item.value = selectedOptions.map((option) => option.text).join(
"/"
);
props.item.city_code = selectedOptions[2]?.value;
showPicker.value = false;
};
...
...
src/components/CalendarField/index.vue
View file @
e89d449
<!--
* @Date: 2022-09-14 11:00:01
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-14 14:24:41
* @LastEditTime: 2022-
11-21 14:38:06
* @FilePath: /data-table/src/components/CalendarField/index.vue
* @Description:
文件描述
* @Description:
日历选择控件
-->
<template>
<div class="calendar-page">
<div class="label">
{{ item.component_props.label
}}
<span v-if="item.component_props.required"> *</span>
{{ item.component_props.label
}}
<span v-if="item.component_props.required"> *</span>
</div>
<van-field
v-model="item.value"
...
...
src/components/CheckboxField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-30 11:34:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-11-
08 08:01:23
* @LastEditTime: 2022-11-
21 14:42:00
* @FilePath: /data-table/src/components/CheckboxField/index.vue
* @Description:
文件描述
* @Description:
多项选择控件
-->
<template>
<div class="checkbox-field-page">
<div class="label">
{{ item.label }}
<span v-if="item.component_props.required" style="color: red"> *</span>
<span v-if="item.component_props.max" style="color: gray"
>(最多可选数: {{ item.component_props.max }})</span
>
<span v-if="item.component_props.max" style="color: gray"
>
(最多可选数: {{ item.component_props.max }})
</span
>
</div>
<van-field :name="item.key" :rules="item.rules" :border="false">
<template #input>
...
...
src/components/DatePickerField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-31 11:45:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-07 13:52:57
* @LastEditTime: 2022-
11-21 14:43:16
* @FilePath: /data-table/src/components/DatePickerField/index.vue
* @Description: 日期选择组件
-->
<template>
<div class="date-picker-field">
<div class="label">
{{ item.component_props.label
}}
<span v-if="item.component_props.required"> *</span>
{{ item.component_props.label
}}
<span v-if="item.component_props.required"> *</span>
</div>
<van-field
v-model="item.value"
...
...
src/components/DateTimePickerField/index.vue
View file @
e89d449
<!--
* @Date: 2022-09-08 15:02:45
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-16 15:04:37
* @LastEditTime: 2022-
11-21 14:47:52
* @FilePath: /data-table/src/components/DateTimePickerField/index.vue
* @Description:
文件描述
* @Description:
日期时间选择器
-->
<template>
<div class="datetime-picker">
...
...
src/components/IdentityField/index.vue
View file @
e89d449
<!--
* @Date: 2022-09-14 14:44:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-14 14:55:53
* @LastEditTime: 2022-
11-21 14:49:52
* @FilePath: /data-table/src/components/IdentityField/index.vue
* @Description:
文件描述
* @Description:
身份证输入控件
-->
<template>
<div class="identity-page">
<div class="label">{{ item.component_props.label }}<span v-if="item.component_props.required"> *</span></div>
<van-field v-model="item.value" :name="item.name" :placeholder="item.component_props.placeholder"
:rules="rules" :required="item.component_props.required" readonly @touchstart.stop="show = true" :border="false">
<div class="label">
{{ item.component_props.label
}}<span v-if="item.component_props.required"> *</span>
</div>
<van-field
v-model="item.value"
:name="item.name"
:placeholder="item.component_props.placeholder"
:rules="rules"
:required="item.component_props.required"
readonly
@touchstart.stop="show = true"
:border="false"
>
</van-field>
<van-number-keyboard
v-model="item.value"
...
...
@@ -25,7 +36,7 @@
<script setup>
const props = defineProps({
item: Object
item: Object
,
});
const show = ref(false);
...
...
@@ -33,8 +44,9 @@ const show = ref(false);
// 校验函数返回 true 表示校验通过,false 表示不通过
// 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
const validator = (val) => {
if (!props.item.component_props.required) { // 非必填
return true
if (!props.item.component_props.required) {
// 非必填
return true;
} else {
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val);
}
...
...
@@ -42,12 +54,12 @@ const validator = (val) => {
// 错误提示文案
const validatorMessage = (val, rule) => {
if (!val) {
return
'身份证号码不能为空'
;
return
"身份证号码不能为空"
;
} else if (!/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(val)) {
return
'请输入正确身份证号码'
;
return
"请输入正确身份证号码"
;
}
}
const rules = [{ validator, message: validatorMessage }]
}
;
const rules = [{ validator, message: validatorMessage }]
;
const onInput = (value) => {};
const onDelete = () => {};
...
...
src/components/ImageUploaderField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-31 16:16:49
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-07 13:56:29
* @LastEditTime: 2022-
11-21 14:54:30
* @FilePath: /data-table/src/components/ImageUploaderField/index.vue
* @Description:
文件描述
* @Description:
图片上传控件
-->
<template>
<div class="image-uploader-field">
<div class="label">{{ item.label }}<span v-if="item.required"> *</span></div>
<div style="padding: 1rem;">
<van-uploader upload-icon="add" :before-read="beforeRead" :after-read="afterRead" v-model="fileList"
:multiple="item.component_props.multiple" />
<div style="padding: 1rem">
<van-uploader
upload-icon="add"
:before-read="beforeRead"
:after-read="afterRead"
v-model="fileList"
:multiple="item.component_props.multiple"
/>
</div>
<div class="type-text">上传格式:{{ type_text }}</div>
</div>
...
...
@@ -22,33 +27,37 @@
* @param name[String] 组件名称
* @param image_type[Array] 图片上传类型
* @param multiple[Boolean] 图片多选
*/
import { Toast } from
'vant'
;
import _ from
'lodash'
import { v4 as uuidv4 } from
'uuid'
;
import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from
'@/api/common'
*/
import { Toast } from
"vant"
;
import _ from
"lodash";
import { v4 as uuidv4 } from
"uuid"
;
import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from
"@/api/common";
const props = defineProps({
item: Object
})
item: Object
,
})
;
const type_text = computed(() => {
return props.item.component_props.image_type.join(
'/')
})
return props.item.component_props.image_type.join(
"/");
})
;
// 上传前置处理
const beforeRead = (file) => {
const image_types = _.map(props.item.component_props.image_type, item => `image/${item}`)
const image_types = _.map(
props.item.component_props.image_type,
(item) => `image/${item}`
);
let flag = true;
if (_.isArray(file)) { // 多张图片
const types = _.difference(_.uniq(_.map(file, item => item.type)), image_types); // 数组返回不能上传的类型
if (_.isArray(file)) {
// 多张图片
const types = _.difference(_.uniq(_.map(file, (item) => item.type)), image_types); // 数组返回不能上传的类型
if (types.length) {
flag = false;
Toast(
'请上传指定格式图片'
);
Toast(
"请上传指定格式图片"
);
}
} else {
if (!_.includes(image_types, file.type)) {
Toast(
'请上传指定格式图片'
);
Toast(
"请上传指定格式图片"
);
flag = false;
}
}
...
...
@@ -58,28 +67,41 @@ const beforeRead = (file) => {
const afterRead = async (file) => {
// 此时可以自行将文件上传至服务器
let affix = uuidv4();
let base64url = file.content.slice(file.content.indexOf(
',') + 1);
// 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA.......
let base64url = file.content.slice(file.content.indexOf(
",") + 1);
// 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA.......
// 获取七牛token
const { token, key, code } = await qiniuTokenAPI({ filename: `${affix}_image_upload`, file: base64url });
const { token, key, code } = await qiniuTokenAPI({
filename: `${affix}_image_upload`,
file: base64url,
});
if (code) {
const config = {
headers: {
'Content-Type': 'application/octet-stream'
,
'Authorization': 'UpToken ' + token,
// UpToken后必须有一个 ' '(空格)
}
}
"Content-Type": "application/octet-stream"
,
Authorization: "UpToken " + token,
// UpToken后必须有一个 ' '(空格)
}
,
}
;
// 上传七牛服务器
const { filekey, hash, image_info } = await qiniuUploadAPI('http://upload.qiniup.com/putb64/-1/key/' + key, base64url, config)
const { filekey, hash, image_info } = await qiniuUploadAPI(
"http://upload.qiniup.com/putb64/-1/key/" + key,
base64url,
config
);
if (filekey) {
// 保存图片
const { data } = await saveFileAPI({ filekey, hash, format: image_info.format, height: image_info.height, width: image_info.width });
const { data } = await saveFileAPI({
filekey,
hash,
format: image_info.format,
height: image_info.height,
width: image_info.width,
});
console.warn(data.src);
}
}
};
const fileList = ref([
{ url:
'https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg'
},
{ url:
"https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg"
},
// Uploader 根据文件后缀来判断是否为图片文件
// 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
// { url: 'https://cloud-image', isImage: true },
...
...
src/components/PhoneField/index.vue
View file @
e89d449
<!--
* @Date: 2022-09-02 10:46:03
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-11-
18 11:08:29
* @LastEditTime: 2022-11-
21 14:59:02
* @FilePath: /data-table/src/components/PhoneField/index.vue
* @Description:
文件描述
* @Description:
手机输入框
-->
<template>
<div class="phone-field-page">
...
...
src/components/RadioField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-30 11:34:19
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-16 17:40:39
* @LastEditTime: 2022-
11-21 15:15:51
* @FilePath: /data-table/src/components/RadioField/index.vue
* @Description:
文件描述
* @Description:
单项选择控件
-->
<template>
<div class="radio-field-page">
...
...
src/components/RatePickerField/index.vue
View file @
e89d449
<!--
* @Date: 2022-09-08 15:47:54
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-08 16:20:11
* @LastEditTime: 2022-
11-21 15:16:10
* @FilePath: /data-table/src/components/RatePickerField/index.vue
* @Description:
文件描述
* @Description:
评分选择控件
-->
<template>
<div class="rate-field">
...
...
src/components/TextField/index.vue
View file @
e89d449
...
...
@@ -7,31 +7,41 @@
-->
<template>
<div class="text-field-page">
<div class="label">{{ item.component_props.label }}<span v-if="item.component_props.required"> *</span></div>
<van-field v-model="item.value"
:name="item.name" :type="item.type" :placeholder="item.component_props.placeholder"
:rules="item.rules" :required="item.required"
:readonly="item.component_props.readonly" :disabled="item.component_props.disabled"
<div class="label">
{{ item.component_props.label
}}<span v-if="item.component_props.required"> *</span>
</div>
<van-field
v-model="item.value"
:name="item.name"
:type="item.type"
:placeholder="item.component_props.placeholder"
:rules="item.rules"
:required="item.required"
:readonly="item.component_props.readonly"
:disabled="item.component_props.disabled"
:input-align="item.component_props.align"
clearable :border="false" />
clearable
:border="false"
/>
</div>
</template>
<script setup>
const props = defineProps({
item: Object
})
item: Object
,
})
;
</script>
<style lang="less" scoped>
.text-field-page {
.label {
padding: 1rem 1rem 0 1rem;
font-size: 0.9rem;
font-weight: bold;
span {
color: red;
}
.text-field-page {
.label {
padding: 1rem 1rem 0 1rem;
font-size: 0.9rem;
font-weight: bold;
span {
color: red;
}
}
}
</style>
...
...
src/components/TimePickerField/index.vue
View file @
e89d449
<!--
* @Date: 2022-08-31 11:45:30
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-
09-08 10:06:4
6
* @LastEditTime: 2022-
11-21 15:21:5
6
* @FilePath: /data-table/src/components/TimePickerField/index.vue
* @Description:
日期
选择组件
* @Description:
时间
选择组件
-->
<template>
<div class="time-picker-field">
...
...
src/hooks/useComponentType.js
View file @
e89d449
...
...
@@ -57,11 +57,6 @@ export function createComponentType(data) {
item
.
autosize
=
true
;
item
.
component
=
TextareaField
;
}
// if (item.component_props.name === 'number') {
// item.type = 'number';
// item.name = item.key;
// item.component = TextField;
// }
if
(
item
.
component_props
.
name
===
'number'
)
{
item
.
name
=
item
.
key
;
item
.
component
=
NumberField
;
...
...
Please
register
or
login
to post a comment