refactor(样式): 优化输入框样式和矩阵文本组件

- 调整了 main.scss 和 public.scss 中的样式
-重构了 MatrixText 组件,支持数字和文本输入
- 优化了 Completion 组件的默认值设置
- 修改了验证逻辑,允许空值作为有效答案
This commit is contained in:
陈昱达
2025-05-28 23:19:14 +08:00
parent f4f84e0b68
commit 966e56ad74
8 changed files with 206 additions and 95 deletions

View File

@@ -51,7 +51,7 @@ a,
top: 0; top: 0;
width: 100%; width: 100%;
// background-color: linear-gradient(to bottom, theme.$theme-color 200px, theme.$nav-color 300px); // background-color: linear-gradient(to bottom, theme.$theme-color 200px, theme.$nav-color 300px);
background: url("../img/home/nav.png") theme.$nav-color; background: url('../img/home/nav.png') theme.$nav-color;
color: #000; color: #000;
& .van-nav-bar__content { & .van-nav-bar__content {

View File

@@ -300,3 +300,12 @@ input {
background: linear-gradient(180deg, #e8fad7 0%, #ffffff 8%); background: linear-gradient(180deg, #e8fad7 0%, #ffffff 8%);
} }
//background: linear-gradient( 180deg, #E8FAD7 0%, #FFFFFF 100%); //background: linear-gradient( 180deg, #E8FAD7 0%, #FFFFFF 100%);
.el-input-number__decrease,
.el-input-number__increase {
display: none;
}
.el-input-number .el-input__wrapper,
.el-input-number.is-controls-right .el-input__wrapper {
padding: 0;
}

View File

@@ -58,7 +58,7 @@
import { toRefs, watch } from 'vue'; import { toRefs, watch } from 'vue';
import { ElInputNumber } from 'element-plus'; import { ElInputNumber } from 'element-plus';
import { showFailToast } from 'vant'; import { showFailToast } from 'vant';
const completionValue = defineModel('completionValue', { default: null, type: String }); const completionValue = defineModel('completionValue', { default: '', type: String });
const props = defineProps({ const props = defineProps({
isPreview: { isPreview: {
type: Boolean, type: Boolean,

View File

@@ -1,16 +1,40 @@
<template> <template>
<input <div>
type="text" <!-- <el-input-number-->
class="el-input" <!-- v-model="inputValueMTX"-->
style="width: 100%" <!-- style="width: 100%"-->
:placeholder="element.config.placeholder" <!-- v-if="element.config.text_type === 1"-->
:name="`R${rowIndex + 1}`" <!-- controls-position="right"-->
:value="getInputValue(rowIndex, colIndex)" <!-- @change="(e) => ev"-->
@change="handleMatrixTextChange(rowIndex, colIndex, $event)" <!-- :max="element.config.max"-->
/> <!-- @blur="changeValue(rowIndex, colIndex)"-->
<!-- ></el-input-number>-->
<!-- <el-input-number-->
<!-- v-model="inputValueMTX"-->
<!-- style="width: 100%"-->
<!-- v-else-if="element.config.text_type === 2"-->
<!-- controls-position="right"-->
<!-- @change="(e) => handleMatrixTextChange(rowIndex, colIndex, { target: { value: e } })"-->
<!-- :precision="element.config.decimal_few"-->
<!-- :max="element.config.max"-->
<!-- @blur="changeValue(rowIndex, colIndex)"-->
<!-- ></el-input-number>-->
<input
type="text"
class="el-input"
style="width: 100%"
:placeholder="element.config.placeholder"
:name="`R${rowIndex + 1}`"
:value="getInputValue(rowIndex, colIndex)"
@change="handleMatrixTextChange(rowIndex, colIndex, $event)"
/>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ElInputNumber } from 'element-plus';
import { ref } from 'vue';
import { showFailToast } from 'vant';
// 接受获取到的 col row 的索引参数 // 接受获取到的 col row 的索引参数
const rowIndex = defineModel('rowIndex', { required: true, default: 0 }); const rowIndex = defineModel('rowIndex', { required: true, default: 0 });
const colIndex = defineModel('colIndex', { required: true, default: 0 }); const colIndex = defineModel('colIndex', { required: true, default: 0 });
@@ -23,10 +47,12 @@ const element = defineModel<question>('element', {
} }
}); });
console.log(element); const inputValueMTX = ref('');
const emit = defineEmits(['update:matrixAnswer', 'update:rowRecord', 'update:element']); const emit = defineEmits(['update:matrixAnswer', 'update:rowRecord', 'update:element']);
function ev() {
console.log(1231);
}
function getInputValue(row: number, col: number) { function getInputValue(row: number, col: number) {
// console.log(`row: ${row}, col: ${col}`); // console.log(`row: ${row}, col: ${col}`);
// console.log(`rowRecord:`, rowRecord.value); // console.log(`rowRecord:`, rowRecord.value);
@@ -39,6 +65,7 @@ function handleMatrixTextChange(row: number, col: number, e: Event) {
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement;
const inputValue = target.value; const inputValue = target.value;
console.log(inputValue, 123);
// 获取 colIndexArray // 获取 colIndexArray
if (!rowRecord.value[row]) { if (!rowRecord.value[row]) {
// 如果没有对应的row创建一个 // 如果没有对应的row创建一个
@@ -50,6 +77,18 @@ function handleMatrixTextChange(row: number, col: number, e: Event) {
// console.log(`rowRecord:`, rowRecord.value); // console.log(`rowRecord:`, rowRecord.value);
} }
const changeValue = (rowIndex, colIndex) => {
if (
inputValueMTX.value < element.value.config.min &&
element.value.config.min &&
inputValueMTX.value
) {
inputValueMTX.value = null;
showFailToast('请输入大于' + element.value.config.min + '的数字');
handleMatrixTextChange(rowIndex, colIndex, { target: { value: '' } });
}
};
const emitValue = () => { const emitValue = () => {
emit('update:element', element.value); emit('update:element', element.value);
}; };
@@ -57,4 +96,15 @@ const emitValue = () => {
<style scoped lang="scss"> <style scoped lang="scss">
@import '@/assets/css/theme'; @import '@/assets/css/theme';
input[type='text'] {
width: 100%;
padding: 0 5px;
border: none;
border-radius: 4px;
outline: 1px solid #f4f4f4;
&:focus {
outline: 1px solid $theme-color;
}
}
</style> </style>

View File

@@ -651,8 +651,9 @@ async function answer(callback, callbackBeforePage) {
if ((questions.value.length || !questionsData.value.questions.length) && !props.isTemplate) { if ((questions.value.length || !questionsData.value.questions.length) && !props.isTemplate) {
// 表单验证(当前页) // 表单验证(当前页)
const errors = questions.value.filter((question) => { const errors = questions.value.filter((question) => {
const { config, answer, question_type: questionType, error } = question; const { config, question_type: questionType, error, answer } = question;
console.log(question.answer);
// let answer = question.answer.value ? question.answer.value : question.answer;
// console.log(answer, questionType, error); // console.log(answer, questionType, error);
// 单独 处理 图文 // 单独 处理 图文
if (questionType === 6) { if (questionType === 6) {
@@ -662,6 +663,15 @@ async function answer(callback, callbackBeforePage) {
let isError = false; let isError = false;
// 如果问题没有答案还有是必须填空的,就往下处理 // 如果问题没有答案还有是必须填空的,就往下处理
// 2025/4/1新增 如果有 error 内容, 同样视为有错误 // 2025/4/1新增 如果有 error 内容, 同样视为有错误
// if (config.is_required === 0) {
// if (!answer && !answer?.value) {
// return;
// }
// }
console.log(answer, ' isError = true;');
if (!answer || error) { if (!answer || error) {
isError = true; isError = true;
// 各个问题单独处理 // 各个问题单独处理
@@ -684,11 +694,11 @@ async function answer(callback, callbackBeforePage) {
// 分类题 // 分类题
question.error = translatedText.value.PleaseCategorizeAllOptions; question.error = translatedText.value.PleaseCategorizeAllOptions;
} else if (!question.error) { } else if (!question.error) {
console.log(question); console.log(question, 23);
if (question.config.is_required === 1) { if (config.is_required === 1) {
question.error = translatedText.value.ThisIsARequiredQuestion; question.error = translatedText.value.ThisIsARequiredQuestion;
} else { } else {
return; isError = false;
} }
} }
} else if ( } else if (
@@ -741,83 +751,108 @@ async function answer(callback, callbackBeforePage) {
isError = true; isError = true;
question.error = translatedText.value.PleaseUploadAtLeastOneFiles(config.min_number); question.error = translatedText.value.PleaseUploadAtLeastOneFiles(config.min_number);
} else if (answer && questionType === 4) { } else if (answer && questionType === 4) {
// 矩阵填空题
question.error = ''; question.error = '';
if (!answer.value && config.is_required === 0) {
if (question.config.is_required === 1 || answer.value) { isError = false;
switch (config.text_type) { return;
// 字母
case 3:
if (
!/^[a-zA-Z·~@#¥%…&*()—\-+={}|《》?:“”【】、;‘’,。`!$^()_<>?:",./;'\\[\]]+$/.test(
answer.value
)
) {
question.error = translatedText.value.PleaseEnterEnglishLetters;
}
break;
// 中文
case 4:
if (
!/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|[·~@#¥%…&*()—\-+={}|《》?:“”【】、;‘’,。`!$^()_<>?:",./;'\\[\]])+$/.test(
answer.value
)
) {
question.error = translatedText.value.PleaseEnterChineseWords;
}
break;
// 邮箱
case 5:
if (
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
answer.value
)
) {
question.error = translatedText.value.PleaseEnterACorrectEmail;
}
break;
// 手机号
case 6:
if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(answer.value)) {
question.error = translatedText.value.PleaseEnterACorrectPhone;
}
break;
// 身份证号
case 7:
if (
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
answer.value
)
) {
question.error = translatedText.value.PleaseEnterACorrectID;
}
break;
default:
break;
}
if (![5, 6, 7].includes(config.text_type)) {
if (
!question.error &&
answer.value.length < config.min &&
![1, 2].includes(config.text_type)
) {
question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min);
}
if (
!question.error &&
answer.value.length > config.max &&
![1, 2].includes(config.text_type)
) {
question.error = translatedText.value.PleaseEnterLessCharacters(config.max);
}
}
if (question.error) isError = true;
} }
if (answer.value === null) {
isError = true;
console.log(123123);
question.error = translatedText.value.ThisIsARequiredQuestion;
return;
}
// // 矩阵填空题
switch (config.text_type) {
// 字母
case 3:
if (
!/^[a-zA-Z·~@#¥%…&*()—\-+={}|《》?:“”【】、;‘’,。`!$^()_<>?:",./;'\\[\]]+$/.test(
answer.value
)
) {
isError = true;
question.error = translatedText.value.PleaseEnterEnglishLetters;
}
break;
// 中文
case 4:
if (
!/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|[·~@#¥%…&*()—\-+={}|《》?:“”【】、;‘’,。`!$^()_<>?:",./;'\\[\]])+$/.test(
answer.value
)
) {
isError = true;
question.error = translatedText.value.PleaseEnterChineseWords;
}
break;
// 邮箱
case 5:
if (
!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
answer.value
)
) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectEmail;
}
break;
// 手机号
case 6:
if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(answer.value)) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectPhone;
}
break;
// 身份证号
case 7:
if (
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
answer.value
)
) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectID;
}
break;
default:
break;
}
console.log(answer.value?.length, config.text_type, config.min);
// if (![5, 6, 7].includes(config.text_type)) {
if (
answer.value?.length < config.min &&
![1, 2, 5, 6, 7].includes(config.text_type) &&
config.min
) {
isError = true;
question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min);
return;
}
if (
answer.value?.length > config.max &&
![1, 2, 5, 6, 7].includes(config.text_type) &&
config.max
) {
isError = true;
question.error = translatedText.value.PleaseEnterLessCharacters(config.max);
return;
}
// }
if (question.error) isError = true;
} else if (answer && questionType === 8) { } else if (answer && questionType === 8) {
// 矩阵填空题 // 矩阵填空题
question.error = ''; question.error = '';
if (!answer && config.is_required === 0) {
isError = false;
return false;
}
Object.keys(answer).forEach((key) => { Object.keys(answer).forEach((key) => {
const value = answer[key]; const value = answer[key];
switch (config.text_type) { switch (config.text_type) {
// 字母 // 字母
case 3: case 3:
@@ -826,6 +861,7 @@ async function answer(callback, callbackBeforePage) {
value value
) )
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterEnglishLetters; question.error = translatedText.value.PleaseEnterEnglishLetters;
} }
break; break;
@@ -836,6 +872,7 @@ async function answer(callback, callbackBeforePage) {
value value
) )
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterChineseWords; question.error = translatedText.value.PleaseEnterChineseWords;
} }
break; break;
@@ -846,12 +883,14 @@ async function answer(callback, callbackBeforePage) {
value value
) )
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectEmail; question.error = translatedText.value.PleaseEnterACorrectEmail;
} }
break; break;
// 手机号 // 手机号
case 6: case 6:
if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value)) { if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value)) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectPhone; question.error = translatedText.value.PleaseEnterACorrectPhone;
} }
break; break;
@@ -862,6 +901,7 @@ async function answer(callback, callbackBeforePage) {
value value
) )
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterACorrectID; question.error = translatedText.value.PleaseEnterACorrectID;
} }
break; break;
@@ -873,16 +913,23 @@ async function answer(callback, callbackBeforePage) {
if ( if (
!question.error && !question.error &&
value.length < config.min && value.length < config.min &&
config.min &&
![1, 2].includes(config.text_type) ![1, 2].includes(config.text_type)
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min); question.error = translatedText.value.PleaseEnterMoreThanOneCharacters(config.min);
return false;
} }
if ( if (
!question.error && !question.error &&
value.length > config.max && value.length > config.max &&
config.max &&
![1, 2].includes(config.text_type) ![1, 2].includes(config.text_type)
) { ) {
isError = true;
question.error = translatedText.value.PleaseEnterLessCharacters(config.max); question.error = translatedText.value.PleaseEnterLessCharacters(config.max);
return false;
} }
} }
}); });

View File

@@ -34,18 +34,21 @@ const completionValue = ref<string>(answer.value?.value ?? '');
watch( watch(
() => completionValue.value, () => completionValue.value,
(value) => { (value) => {
console.log(value, 'update');
// 答案校验,生成最终答案 // 答案校验,生成最终答案
const { isError } = validateCompletion(question.value, question.value.config!, String(value)); const { isError } = validateCompletion(question.value, question.value.config!, String(value));
console.log(`isError, question`, isError, question.value); console.log(`isError, question`, isError, question.value);
if (isError) { // if (isError) {
// 有错误就不更新 // 有错误就不更新
question.value.answer = void 0; question.value.answer = void 0;
return; // return;
} // }
const res = generateAnswer(value); const res = generateAnswer(value);
answer.value = res; answer.value = res;
question.value!.answer = res; question.value!.answer = res;
// answer emit 提交失效 // answer emit 提交失效
// emit('changeAnswer', res); // emit('changeAnswer', res);
} }
@@ -56,6 +59,8 @@ watch(
* @param answer {string} * @param answer {string}
*/ */
function generateAnswer(answer: string) { function generateAnswer(answer: string) {
console.log(answer, 'asjd');
return { value: answer }; return { value: answer };
} }
</script> </script>

View File

@@ -22,7 +22,7 @@ export function validateMinLength(
// 如果包含相应的 text_type 也不处理1是整数2是小数 // 如果包含相应的 text_type 也不处理1是整数2是小数
if ([1, 2].includes(config.text_type)) return; if ([1, 2].includes(config.text_type)) return;
if (answer.length > Number(config.min)) return; if (answer.length >= Number(config.min)) return;
return { return {
isError: true, isError: true,
errorMessage: translatedText.PleaseEnterMoreCharacters(config.min) errorMessage: translatedText.PleaseEnterMoreCharacters(config.min)