feat[preview]: 适配签名组件
- 适配签名组件 PreviewSign
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, useTemplateRef, toRefs } from 'vue';
|
||||
const props = defineProps<{
|
||||
element: any;
|
||||
active: boolean;
|
||||
index: number;
|
||||
}>();
|
||||
|
||||
const { element, active } = toRefs(props);
|
||||
import { computed, onMounted, ref, useTemplateRef } from 'vue';
|
||||
import CommonApi from '@/api/common.js';
|
||||
// question 属性
|
||||
const element = defineModel<question>('element', { default: {} });
|
||||
// 属性框是否激活
|
||||
const active = defineModel<boolean>('active', { default: false });
|
||||
// 题目索引
|
||||
const index = defineModel<number>('index', { default: 0 });
|
||||
// 答案
|
||||
const answer = defineModel<string>('answer', { default: '' });
|
||||
// 错误信息
|
||||
const errorMessage = defineModel<string>('errorMessage', { default: '' });
|
||||
|
||||
const signatureCanvas = useTemplateRef('signatureCanvas');
|
||||
|
||||
@@ -54,10 +58,7 @@ const togglePen = () => {
|
||||
isEraser.value = !isEraser.value;
|
||||
setPenStyle();
|
||||
};
|
||||
const errorMessage = defineModel('errorMessage', {
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (!signatureCanvas.value) return;
|
||||
// 将 canvas 宽度和窗口的宽度保持一致
|
||||
@@ -146,10 +147,24 @@ const clearCanvas = () => {
|
||||
|
||||
/**
|
||||
* 保存画布
|
||||
* @param type {'dataUrl' | 'blob'} 保存类型
|
||||
* @return {string | Blob | undefined | null}
|
||||
*/
|
||||
const saveCanvas = () => {
|
||||
const saveCanvas = (type: 'dataUrl' | 'blob'): string | Blob | undefined | null => {
|
||||
let img: string | Blob | undefined | null = undefined;
|
||||
if (!ctx || !signatureCanvas.value) return;
|
||||
return signatureCanvas.value.toDataURL('image/png');
|
||||
if (type === 'blob') {
|
||||
signatureCanvas.value.toBlob(
|
||||
(blob) => {
|
||||
img = blob;
|
||||
},
|
||||
'image/png',
|
||||
{ quality: 0.9 }
|
||||
);
|
||||
return img;
|
||||
}
|
||||
|
||||
if (type === 'dataUrl') return signatureCanvas.value.toDataURL('image/png');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -168,10 +183,19 @@ const emit = defineEmits(['update:element']);
|
||||
const emitValue = () => {
|
||||
emit('update:element', element.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
async function handleUploadImg() {
|
||||
const file = new File([saveCanvas('blob')!], 'sign.png', { type: 'image/png' });
|
||||
const { url } = await CommonApi.cosUpload(file);
|
||||
// 传递答案
|
||||
answer.value = url;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <van-cell>-->
|
||||
<van-field
|
||||
:label="element.stem"
|
||||
:required="element.config.is_required === 1"
|
||||
@@ -211,13 +235,12 @@ const emitValue = () => {
|
||||
:class="isEraser ? 'mobilefont-huabi' : 'mobilefont-rubber'"
|
||||
@click="togglePen"
|
||||
></span>
|
||||
<span class="icon mobilefont mobilefont-shangchuan" @click="saveCanvas"></span>
|
||||
<span class="icon mobilefont mobilefont-shangchuan" @click="handleUploadImg"></span>
|
||||
</div>
|
||||
<div v-else class="sign-tips">请在空白区域书写您的签名</div>
|
||||
</div>
|
||||
</template>
|
||||
</van-field>
|
||||
<!-- </van-cell>-->
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -323,14 +323,15 @@
|
||||
<!-- v-model:answer="question.answer"-->
|
||||
<!-- isMobile-->
|
||||
<!-- />-->
|
||||
<!-- <!– 签名题 –>-->
|
||||
<!-- <q-sign-->
|
||||
<!-- v-else-if="question.question_type === 22"-->
|
||||
<!-- :config="question.config"-->
|
||||
<!-- :question="question"-->
|
||||
<!-- v-model:answer="question.answer"-->
|
||||
<!-- isMobile-->
|
||||
<!-- />-->
|
||||
<!-- 签名题 -->
|
||||
<preview-sign
|
||||
v-else-if="question.question_type === 22"
|
||||
:config="question.config"
|
||||
:question="question"
|
||||
v-model:answer="question.answer"
|
||||
:answerIndex="getQuestionIndex(questionsData.questions, question)"
|
||||
@change-answer="onRelation($event, question)"
|
||||
/>
|
||||
<!-- <!– 知情同意书 –>-->
|
||||
<!-- <q-consent-->
|
||||
<!-- v-else-if="question.question_type === 23"-->
|
||||
@@ -540,6 +541,7 @@ import { getQuestionIndex } from '@/utils/utils.js';
|
||||
import icon from '@/assets/img/create-right-back.png';
|
||||
import PreviewCheckbox from '@/views/Survey/views/Preview/components/questions/PreviewCheckbox.vue';
|
||||
import PreviewRate from '@/views/Survey/views/Preview/components/questions/PreviewRate.vue';
|
||||
import PreviewSign from '@/views/Survey/views/Preview/components/questions/PreviewSign.vue';
|
||||
const isPreview = defineModel('isPreview', {
|
||||
type: Boolean,
|
||||
default: true
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import SignQuestion from '@/views/Design/components/Questions/SignQuestion.vue';
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const question = defineModel<question>('question', { default: {} });
|
||||
const answer = defineModel<{ value: string }>('answer', { default: undefined });
|
||||
const answerValue = ref<string>('');
|
||||
const answerIndex = defineModel<number>('answerIndex', { default: 0 });
|
||||
// emit
|
||||
const emit = defineEmits(['changeAnswer']);
|
||||
|
||||
// 如果 answer 不为空,需要解析答案
|
||||
answer.value?.value && parseAnswer();
|
||||
|
||||
/**
|
||||
* 监听答案,如果答案变动,重新生成答案,然后提交
|
||||
*/
|
||||
watch(answerValue, (newValue) => {
|
||||
emit('changeAnswer', { value: newValue });
|
||||
});
|
||||
/**
|
||||
* 解析答案
|
||||
* answer 格式
|
||||
* {
|
||||
* value: 'url'
|
||||
* }
|
||||
*/
|
||||
function parseAnswer() {
|
||||
answerValue.value = answer.value.value;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<sign-question
|
||||
:element="question"
|
||||
:active="false"
|
||||
:index="answerIndex"
|
||||
v-model:answer="answerValue"
|
||||
:error-message="question.error"
|
||||
/>
|
||||
</template>
|
||||
<style scoped lang="scss"></style>
|
||||
Reference in New Issue
Block a user