hookehuyr

✨ feat(多行文本控件): 调整样式和组件属性

...@@ -35,6 +35,7 @@ declare module '@vue/runtime-core' { ...@@ -35,6 +35,7 @@ declare module '@vue/runtime-core' {
35 NutNoticebar: typeof import('@nutui/nutui-taro')['Noticebar'] 35 NutNoticebar: typeof import('@nutui/nutui-taro')['Noticebar']
36 NutSwiper: typeof import('@nutui/nutui-taro')['Swiper'] 36 NutSwiper: typeof import('@nutui/nutui-taro')['Swiper']
37 NutSwiperItem: typeof import('@nutui/nutui-taro')['SwiperItem'] 37 NutSwiperItem: typeof import('@nutui/nutui-taro')['SwiperItem']
38 + NutTextarea: typeof import('@nutui/nutui-taro')['Textarea']
38 PhoneField: typeof import('./src/components/PhoneField/index.vue')['default'] 39 PhoneField: typeof import('./src/components/PhoneField/index.vue')['default']
39 PickerField: typeof import('./src/components/PickerField/index.vue')['default'] 40 PickerField: typeof import('./src/components/PickerField/index.vue')['default']
40 RadioField: typeof import('./src/components/RadioField/index.vue')['default'] 41 RadioField: typeof import('./src/components/RadioField/index.vue')['default']
......
1 <!-- 1 <!--
2 * @Date: 2022-08-29 14:31:20 2 * @Date: 2022-08-29 14:31:20
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-03-22 09:13:58 4 + * @LastEditTime: 2023-04-03 14:07:03
5 - * @FilePath: /data-table/src/components/TextareaField/index.vue 5 + * @FilePath: /custom_form/src/components/TextareaField/index.vue
6 * @Description: 多行文本输入框 6 * @Description: 多行文本输入框
7 --> 7 -->
8 <template> 8 <template>
9 <div v-if="HideShow" class="textarea-field-page"> 9 <div v-if="HideShow" class="textarea-field-page">
10 <div class="label"> 10 <div class="label">
11 - <span v-if="item.component_props.required">&nbsp;*</span> 11 + <text v-if="item.component_props.required">&nbsp;*</text>
12 {{ item.component_props.label }} 12 {{ item.component_props.label }}
13 </div> 13 </div>
14 - <div 14 + <!-- <div
15 v-if="item.component_props.note" 15 v-if="item.component_props.note"
16 v-html="item.component_props.note" 16 v-html="item.component_props.note"
17 style="font-size: 0.9rem; margin-left: 1rem; color: gray; padding-bottom: 0.5rem; padding-top: 0.25rem; white-space: pre-wrap;" 17 style="font-size: 0.9rem; margin-left: 1rem; color: gray; padding-bottom: 0.5rem; padding-top: 0.25rem; white-space: pre-wrap;"
18 - /> 18 + /> -->
19 - <van-field 19 + <nut-textarea
20 - v-model="item.value" 20 + v-model="input_value"
21 - :name="item.name"
22 :type="item.type" 21 :type="item.type"
22 + :border="false"
23 :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入'" 23 :placeholder="item.component_props.placeholder ? item.component_props.placeholder : '请输入'"
24 - :rules="item.rules"
25 - :required="item.component_props.required"
26 :readonly="item.component_props.readonly" 24 :readonly="item.component_props.readonly"
27 - :rows="item.component_props.rows" 25 + :max-length="item.component_props.maxlength ? item.component_props.maxlength : null"
28 - autosize 26 + :limit-show="!!item.component_props.maxlength && !item.component_props.readonly"
29 - :maxlength="item.component_props.maxlength ? item.component_props.maxlength : null" 27 + :autosize="{ maxHeight: 200, minHeight: 100 }"
30 - :show-word-limit="item.component_props.maxlength" 28 + style="border: 1px solid #eaeaea; border-radius: 0.25rem; padding: 10px;"
31 /> 29 />
30 + <div
31 + v-if="show_error"
32 + style="padding: 5px 20px; color: red; font-size: 12px;"
33 + >
34 + {{ error_msg }}
35 + </div>
32 </div> 36 </div>
33 </template> 37 </template>
34 38
35 <script setup> 39 <script setup>
40 +import { ref, computed, watch, onMounted, reactive } from "vue";
41 +
36 const props = defineProps({ 42 const props = defineProps({
37 item: Object, 43 item: Object,
38 }); 44 });
...@@ -40,15 +46,56 @@ const props = defineProps({ ...@@ -40,15 +46,56 @@ const props = defineProps({
40 const HideShow = computed(() => { 46 const HideShow = computed(() => {
41 return !props.item.component_props.disabled 47 return !props.item.component_props.disabled
42 }) 48 })
49 +
50 +const emit = defineEmits(["active"]);
51 +const input_value = ref('');
52 +
53 +// 错误提示
54 +const show_error = ref(false);
55 +const error_msg = ref('');
56 +
57 +onMounted(() => {
58 + if (props.item.component_props.default) {
59 + input_value.value = props.item.component_props.default;
60 + }
61 +})
62 +
63 +watch(
64 + () => input_value.value,
65 + (newValue, oldValue) => {
66 + props.item.value = {
67 + key: "textarea",
68 + filed_name: props.item.key,
69 + value: newValue,
70 + };
71 + emit("active", props.item.value);
72 + },
73 + { immediate: true }
74 +);
75 +
76 +// 校验模块
77 +const validTextarea = () => {
78 + // 必填项
79 + if (props.item.component_props.required && !input_value.value) {
80 + show_error.value = true;
81 + error_msg.value = '必填项不能为空'
82 + } else {
83 + show_error.value = false;
84 + error_msg.value = ''
85 + }
86 + return !show_error.value;
87 +};
88 +
89 +defineExpose({ validTextarea });
43 </script> 90 </script>
44 91
45 -<style lang="less" scoped> 92 +<style lang="less">
46 .textarea-field-page { 93 .textarea-field-page {
47 .label { 94 .label {
48 - padding: 1rem 1rem 0 1rem; 95 + padding: 30px 30px 0 30px;
49 - font-size: 0.9rem; 96 + font-size: 26px;
50 font-weight: bold; 97 font-weight: bold;
51 - span { 98 + text {
52 color: red; 99 color: red;
53 } 100 }
54 } 101 }
...@@ -59,9 +106,22 @@ const HideShow = computed(() => { ...@@ -59,9 +106,22 @@ const HideShow = computed(() => {
59 // border-radius: 0.25rem; 106 // border-radius: 0.25rem;
60 // padding: 0.25rem 0.5rem; 107 // padding: 0.25rem 0.5rem;
61 // } 108 // }
62 -:deep(.van-cell__value) { 109 +// :deep(.van-cell__value) {
63 - border: 1px solid #eaeaea; 110 +// border: 1px solid #eaeaea;
64 - border-radius: 0.25rem; 111 +// border-radius: 0.25rem;
65 - padding: 0.25rem 0.5rem; 112 +// padding: 0.25rem 0.5rem;
113 +// }
114 +
115 +input {
116 + color: #000 !important;
117 +}
118 +.nut-textarea {
119 + padding-left: 35px;
120 + padding-right: 35px;
121 + white-space: pre-wrap;
122 +}
123 +.nut-textarea__limit {
124 + right: 50px;
125 + bottom: 30px;
66 } 126 }
67 </style> 127 </style>
......
1 import _ from '@/utils/lodash' 1 import _ from '@/utils/lodash'
2 import TextField from '@/components/TextField/index.vue' 2 import TextField from '@/components/TextField/index.vue'
3 -// import TextareaField from '@/components/TextareaField/index.vue' 3 +import TextareaField from '@/components/TextareaField/index.vue'
4 // import RadioField from '@/components/RadioField/index.vue' 4 // import RadioField from '@/components/RadioField/index.vue'
5 // import CheckboxField from '@/components/CheckboxField/index.vue' 5 // import CheckboxField from '@/components/CheckboxField/index.vue'
6 // import PickerField from '@/components/PickerField/index.vue' 6 // import PickerField from '@/components/PickerField/index.vue'
...@@ -75,13 +75,11 @@ export function createComponentType(data) { ...@@ -75,13 +75,11 @@ export function createComponentType(data) {
75 item.name = item.key 75 item.name = item.key
76 item.component = TextField 76 item.component = TextField
77 } 77 }
78 - // if (item.component_props.tag === 'textarea') { 78 + if (item.component_props.tag === 'textarea') {
79 - // item.type = 'textarea' 79 + item.type = 'textarea'
80 - // item.name = item.key 80 + item.name = item.key
81 - // // item.rows = 10; 81 + item.component = TextareaField
82 - // item.autosize = true 82 + }
83 - // item.component = TextareaField
84 - // }
85 // if (item.component_props.tag === 'number') { 83 // if (item.component_props.tag === 'number') {
86 // item.name = item.key 84 // item.name = item.key
87 // item.component = NumberField 85 // item.component = NumberField
......
1 <!-- 1 <!--
2 * @Date: 2023-03-24 09:19:27 2 * @Date: 2023-03-24 09:19:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2023-03-31 18:02:51 4 + * @LastEditTime: 2023-04-03 13:32:11
5 * @FilePath: /custom_form/src/pages/table/index.vue 5 * @FilePath: /custom_form/src/pages/table/index.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
...@@ -127,6 +127,7 @@ const formatData = (data) => { ...@@ -127,6 +127,7 @@ const formatData = (data) => {
127 // 处理没有绑定值的组件的赋值 127 // 处理没有绑定值的组件的赋值
128 // 省市区选择,图片上传,文件上传,电子签名,评分组件 128 // 省市区选择,图片上传,文件上传,电子签名,评分组件
129 const input = ref([]); 129 const input = ref([]);
130 +const textarea = ref([]);
130 const area_picker = ref([]); 131 const area_picker = ref([]);
131 const image_uploader = ref([]); 132 const image_uploader = ref([]);
132 const file_uploader = ref([]); 133 const file_uploader = ref([]);
...@@ -138,6 +139,9 @@ const setRefMap = (el, item) => { ...@@ -138,6 +139,9 @@ const setRefMap = (el, item) => {
138 if (item.component_props.tag === "input") { 139 if (item.component_props.tag === "input") {
139 input.value.push(el); 140 input.value.push(el);
140 } 141 }
142 + if (item.component_props.tag === "textarea") {
143 + textarea.value.push(el);
144 + }
141 if (item.component_props.tag === "area_picker") { 145 if (item.component_props.tag === "area_picker") {
142 area_picker.value.push(el); 146 area_picker.value.push(el);
143 } 147 }
...@@ -364,6 +368,9 @@ const onActive = (item) => { ...@@ -364,6 +368,9 @@ const onActive = (item) => {
364 if (item.key === "input") { 368 if (item.key === "input") {
365 postData.value[item.filed_name] = item.value; 369 postData.value[item.filed_name] = item.value;
366 } 370 }
371 + if (item.key === "textarea") {
372 + postData.value[item.filed_name] = item.value;
373 + }
367 if (item.key === "area_picker") { 374 if (item.key === "area_picker") {
368 postData.value[item.filed_name] = item.value; 375 postData.value[item.filed_name] = item.value;
369 } 376 }
...@@ -418,6 +425,18 @@ const validOther = () => { ...@@ -418,6 +425,18 @@ const validOther = () => {
418 } 425 }
419 }); 426 });
420 } 427 }
428 + if (textarea.value) {
429 + // 多行文本
430 + textarea.value.forEach((item, index) => {
431 + if (!textarea.value[index].validTextarea()) {
432 + valid = {
433 + status: textarea.value[index].validTextarea(),
434 + key: "textarea",
435 + };
436 + return false;
437 + }
438 + });
439 + }
421 if (area_picker.value) { 440 if (area_picker.value) {
422 // 省市区地址 441 // 省市区地址
423 area_picker.value.forEach((item, index) => { 442 area_picker.value.forEach((item, index) => {
......