actorref(src): 重构组件以提高代码可维护性
- 更新了多个组件的属性定义和事件处理逻辑 - 优化了部分代码结构,提高了代码的可读性和可维护性 -调整了部分样式,提升了用户体验
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="flex contenteditable align-center space-between" :class="className">
|
||||
<p
|
||||
v-if="active"
|
||||
:id="'editor' + id"
|
||||
ref="editor"
|
||||
:contenteditable="active"
|
||||
@@ -8,6 +9,7 @@
|
||||
@focus="onFocus"
|
||||
v-html="modelValue"
|
||||
></p>
|
||||
<p v-else ref="editor" class="van-field contenteditable-content" v-html="modelValue"></p>
|
||||
<div class="right-icon ml10">
|
||||
<slot name="right-icon"></slot>
|
||||
</div>
|
||||
@@ -25,21 +27,20 @@ import { defineEmits, ref, onMounted, watch } from 'vue';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import CommonApi from '@/api/common.js';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
defineProps({
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const modelValue = defineModel('modelValue', {
|
||||
type: String,
|
||||
default: ''
|
||||
});
|
||||
const active = defineModel('active', {
|
||||
type: Boolean,
|
||||
default: false
|
||||
});
|
||||
const id = ref(uuidv4());
|
||||
|
||||
const editor = ref(null);
|
||||
@@ -47,10 +48,9 @@ const editorAction = ref(null);
|
||||
const emit = defineEmits(['update:modelValue', 'blur']);
|
||||
const save = (e) => {
|
||||
emit('update:modelValue', e.innerHTML);
|
||||
emit('blur', e.innerHTML);
|
||||
};
|
||||
|
||||
const savedRange = ref(null);
|
||||
|
||||
const functions = {
|
||||
boldModern: () => {
|
||||
document.execCommand('bold', true, null);
|
||||
@@ -103,16 +103,17 @@ const funEvent = (item) => {
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.active,
|
||||
() => active.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
// showAction.value = true;
|
||||
} else {
|
||||
if (!newVal) {
|
||||
save(editor.value);
|
||||
setTimeout(() => {
|
||||
showAction.value = false;
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true
|
||||
}
|
||||
);
|
||||
|
||||
@@ -162,7 +163,7 @@ onMounted(() => {
|
||||
if (!isEditor && !isActionBar) {
|
||||
showAction.value = false;
|
||||
save(editor.value);
|
||||
emit('blur', editor.value);
|
||||
// emit('blur', editor.value);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -192,7 +192,12 @@ const saveLogics = () => {
|
||||
};
|
||||
|
||||
// 当前题目
|
||||
const activeQuestion = ref(props.data);
|
||||
const activeQuestion = defineModel('data', {
|
||||
type: Object,
|
||||
default: () => {
|
||||
// 传递
|
||||
}
|
||||
});
|
||||
// 设置更新
|
||||
const show = ref(false);
|
||||
const questionShow = ref(false);
|
||||
@@ -251,7 +256,6 @@ watch(
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
|
||||
// 打开题目弹窗
|
||||
const openQuestionActionModel = () => {
|
||||
show.value = true;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
<van-stepper
|
||||
v-model="localConfig.min"
|
||||
button-size="22px"
|
||||
@blur="minChange"
|
||||
@change="minChange"
|
||||
@blur="minChange(localConfig.min)"
|
||||
/>
|
||||
</div>
|
||||
<div class="score">
|
||||
@@ -24,8 +24,8 @@
|
||||
v-model="localConfig.max"
|
||||
:max="maxLimit"
|
||||
button-size="22px"
|
||||
@blur="maxChange"
|
||||
@change="maxChange"
|
||||
@blur="maxChange(localConfig.max)"
|
||||
/>
|
||||
</div>
|
||||
<div class="score">
|
||||
@@ -35,7 +35,7 @@
|
||||
:min="0"
|
||||
button-size="22px"
|
||||
@blur="intervalChange"
|
||||
@change="intervalChange"
|
||||
@change="intervalChange(localConfig.score_interval)"
|
||||
/>
|
||||
</div>
|
||||
</van-cell-group>
|
||||
|
||||
@@ -40,17 +40,9 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import QuestionAction from '@/views/Design/components/ActionCompoents/QuestionAction.vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { basicQuesTypeList } from '@/utils/common.js';
|
||||
|
||||
const props = defineProps({
|
||||
element: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
// 此方法目前为空,未来可能扩展
|
||||
}
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 0
|
||||
@@ -86,14 +78,19 @@ const getQuestionType = (type) => {
|
||||
return typeName;
|
||||
};
|
||||
|
||||
const element = ref(props.element);
|
||||
const element = defineModel('element', {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
|
||||
// 选中题目后出现的操作
|
||||
const emit = defineEmits(['getChooseQuestionId', 'move', 'copy', 'setting', 'logics']);
|
||||
|
||||
// 选中题目
|
||||
const chooseItem = () => {
|
||||
emit('getChooseQuestionId', props.element, props.index);
|
||||
emit('getChooseQuestionId', element.value, props.index);
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -117,8 +117,7 @@ function handleMatrixRadioChange(row: number, col: number) {
|
||||
// emits('update:matrixAnswer', props.matrixAnswer);
|
||||
// emits('update:rowRecord', props.rowRecord);
|
||||
// };
|
||||
const emitValue = (val: unknown) => {
|
||||
console.log(val);
|
||||
const emitValue = () => {
|
||||
emit('update:element', element.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -49,14 +49,10 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, toRefs, watch } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
import RateCharacter from './RateCharacter.vue';
|
||||
|
||||
const props = defineProps({
|
||||
element: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
defineProps({
|
||||
active: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
@@ -72,18 +68,14 @@ const props = defineProps({
|
||||
const emit = defineEmits(['update:element']);
|
||||
|
||||
const chooseId = ref('');
|
||||
const { element } = toRefs(props);
|
||||
|
||||
const emitValue = (newVal) => {
|
||||
emit('update:element', newVal || element.value);
|
||||
const element = defineModel('element', {
|
||||
type: Object,
|
||||
required: true
|
||||
});
|
||||
const emitValue = () => {
|
||||
emit('update:element', element.value);
|
||||
};
|
||||
watch(
|
||||
element.value,
|
||||
(newVal) => {
|
||||
emitValue(newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const chooseOption = (item) => {
|
||||
chooseId.value = item.id;
|
||||
|
||||
@@ -46,13 +46,10 @@ const test = ref(1);
|
||||
setTimeout(() => {
|
||||
test.value = 2;
|
||||
}, 300);
|
||||
const props = defineProps({
|
||||
config: {
|
||||
const config = defineModel('config', {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
|
||||
const index = defineModel('index', {
|
||||
type: Number
|
||||
});
|
||||
@@ -94,26 +91,29 @@ watch(
|
||||
|
||||
// 监听 min、max 和 score_interval 的变化
|
||||
watch(
|
||||
() => [props.config.min, props.config.max, props.config.score_interval],
|
||||
() => [config.value.min, config.value.max, config.value.score_interval],
|
||||
(newValues) => {
|
||||
const [newMin, newMax, newScoreInterval] = newValues;
|
||||
renderScore(newMin, newMax, newScoreInterval);
|
||||
},
|
||||
{ immediate: true }
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
ul {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
//margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.rate_item {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
margin: 0 5px 0 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
//margin: 0 5px 0 0;
|
||||
border: 1px solid #979797;
|
||||
border-radius: 5px;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
import { ref, defineProps, onMounted } from 'vue';
|
||||
import { deleteTemplate } from '@/api/home/index.js';
|
||||
import { showDialog, showSuccessToast, showFailToast } from 'vant';
|
||||
import { useRouter } from 'vue-router';
|
||||
// import { useRouter } from 'vue-router';
|
||||
import png11 from '@/assets/img/home/11.png';
|
||||
import png13 from '@/assets/img/home/13.png';
|
||||
import png14 from '@/assets/img/home/14.png';
|
||||
@@ -61,7 +61,7 @@ import png17 from '@/assets/img/home/17.png';
|
||||
import png18 from '@/assets/img/home/18.png';
|
||||
import png31 from '@/assets/img/home/31.png';
|
||||
|
||||
const router = useRouter();
|
||||
// const router = useRouter();
|
||||
const { info } = defineProps({
|
||||
info: {
|
||||
type: Object,
|
||||
@@ -70,13 +70,14 @@ const { info } = defineProps({
|
||||
}
|
||||
});
|
||||
const userInfo = ref({ userName: '' });
|
||||
const toDetail = (item) => {
|
||||
router.push({
|
||||
path: '/create',
|
||||
query: {
|
||||
sn: item.sn
|
||||
}
|
||||
});
|
||||
const toDetail = () => {
|
||||
// return false
|
||||
// router.push({
|
||||
// path: '/create',
|
||||
// query: {
|
||||
// sn: item.sn
|
||||
// }
|
||||
// });
|
||||
};
|
||||
const deleteItem = (item) => {
|
||||
showDialog({
|
||||
@@ -84,7 +85,7 @@ const deleteItem = (item) => {
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#03B03C'
|
||||
})
|
||||
.then(async () => {
|
||||
.then(async() => {
|
||||
const res = await deleteTemplate(item.sn);
|
||||
if (res.data.code === 0) {
|
||||
showSuccessToast('删除成功');
|
||||
@@ -107,7 +108,8 @@ const setImg = (code) => {
|
||||
18: png18,
|
||||
31: png31
|
||||
};
|
||||
return imageMap[code] || png11; // 默认返回 png11 如果 code 不存在
|
||||
// 默认返回 png11 如果 code 不存在
|
||||
return imageMap[code] || png11;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -553,11 +553,13 @@ watch(
|
||||
|
||||
// 保存 目前没有任何逻辑可以执行所有保存
|
||||
const saveAs = () => {
|
||||
sync({ sn: route.query.sn }).then(() => {
|
||||
// 保存所有
|
||||
showConfirmDialog({
|
||||
message: '问卷保存成功',
|
||||
showCancelButton: false
|
||||
});
|
||||
});
|
||||
};
|
||||
// 投放
|
||||
const publishQuestion = () => {
|
||||
@@ -568,7 +570,7 @@ const previewQuestion = () => {
|
||||
router.push({ name: 'preview', query: { ...route.query } });
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(async() => {
|
||||
await getQuestionDetail();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1429,17 +1429,20 @@ function hasNConsecutiveNumbers(arr, n, onTrue, onFalse) {
|
||||
// eslint-disable
|
||||
// 跳转链接
|
||||
function toUrl(url) {
|
||||
// 创建一个新的变量来存储修改后的 URL
|
||||
let modifiedUrl = url;
|
||||
|
||||
// 判断是否小程序路径
|
||||
if (url[0] === '/') {
|
||||
if (modifiedUrl[0] === '/') {
|
||||
// 判断是否在小程序环境
|
||||
wx.miniProgram.getEnv(() => {
|
||||
wx.miniProgram.redirectTo({ url });
|
||||
wx.miniProgram.redirectTo({ url: modifiedUrl });
|
||||
});
|
||||
} else {
|
||||
if (url.indexOf('http://') === -1 && url.indexOf('https://') === -1) {
|
||||
url = `http://${url}`;
|
||||
if (modifiedUrl.indexOf('http://') === -1 && modifiedUrl.indexOf('https://') === -1) {
|
||||
modifiedUrl = `http://${modifiedUrl}`;
|
||||
}
|
||||
open(url);
|
||||
open(modifiedUrl);
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
@@ -121,8 +121,8 @@ function shareLink() {
|
||||
const params = {
|
||||
type: 'shareToWx',
|
||||
title:
|
||||
surveyTitle.value ||
|
||||
(publishInfo.value.download_url.title
|
||||
surveyTitle.value
|
||||
|| (publishInfo.value.download_url.title
|
||||
? publishInfo.value.download_url.title.replace(/_发布二维码\.[a-zA-Z]+$/, '')
|
||||
: ''),
|
||||
description: publishInfo.value.desc || '填写问卷',
|
||||
@@ -195,7 +195,7 @@ watch(status, (val) => {
|
||||
getCode();
|
||||
}
|
||||
});
|
||||
onMounted(async () => {
|
||||
onMounted(async() => {
|
||||
fetchInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user