123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- <template>
- <scoring-panel-container
- v-model="modalVisible"
- draggable
- title="键盘给分"
- modal-class="no-mask"
- :width="useVW(550)"
- :modal="false"
- @close="onToggleClick"
- >
- <div class="scoring-panel-box" :class="getClass('modal-box')">
- <template v-for="(question, index) in questionList" :key="question.mainNumber + question.subNumber">
- <scoring-panel-item
- v-model:score="scoreValues[index]"
- :active="activeIndex === index"
- :modal="dialogMode"
- :toggle-modal="props.toggleModal && index === 0"
- :question="question"
- @enter="() => onEnter(index)"
- @focused="() => onFocused(index)"
- @toggle-click="onToggleClick"
- ></scoring-panel-item>
- </template>
- </div>
- <template #footer>
- <el-button type="primary" class="full-w m-t-base" :disabled="!allowSubmit" @click="onSubmit">确定</el-button>
- </template>
- </scoring-panel-container>
- </template>
- <script setup lang="ts" name="ScoringPanel">
- import { watch, withDefaults, ref, defineComponent, useSlots, computed } from 'vue'
- import { ElButton } from 'element-plus'
- import BaseDialog from '@/components/element/BaseDialog.vue'
- import ScoringPanelItem from './ScoringPanelItem.vue'
- import useVModel from '@/hooks/useVModel'
- import useVW from '@/hooks/useVW'
- import useFetch from '@/hooks/useFetch'
- const props = withDefaults(
- defineProps<{
- /** 弹窗模式? */
- modal?: boolean
- /** 是否可以切换显示模式 */
- toggleModal?: boolean
- /** 显示隐藏 */
- visible?: boolean
- /** 分值 */
- score: (number | string)[]
- mainNumber?: number | null
- }>(),
- { modal: false, toggleModal: true, score: () => [], mainNumber: null }
- )
- const emits = defineEmits(['submit', 'update:score', 'update:visible'])
- const dialogMode = ref<boolean>(props.modal)
- const LessRenderComponent = defineComponent({
- name: 'LessRender',
- inheritAttrs: false,
- props: {
- modelValue: {
- type: Boolean,
- default: false,
- },
- },
- render() {
- return this.modelValue ? useSlots()?.default?.() : null
- },
- })
- const ScoringPanelContainer = computed(() => {
- return dialogMode.value ? BaseDialog : LessRenderComponent
- })
- const modalVisible = useVModel(props, 'visible')
- watch(modalVisible, () => {
- if (!modalVisible.value) {
- activeIndex.value = 0
- }
- })
- const getClass = (val: string, callback?: string) => {
- return dialogMode.value ? val : callback || ''
- }
- const scoreValues = useVModel(props, 'score')
- const activeIndex = ref<number>(0)
- const { fetch: getQuestionStruct, reset: resetQuestionStruct, result: questionStruct } = useFetch('getQuestionStruct')
- watch(
- () => props.mainNumber,
- () => {
- /** reset scores */
- scoreValues.value = []
- /** auto show */
- modalVisible.value = !!props.mainNumber
- if (props.mainNumber) {
- resetQuestionStruct()
- getQuestionStruct({ mainNumber: props.mainNumber })
- }
- },
- { immediate: true }
- )
- const questionList = computed(() => {
- if (!questionStruct.value) {
- return []
- }
- const { mainNumber, mainTitle, questionList = [] } = questionStruct.value
- return questionList.map((q) => ({ ...q, mainNumber, mainTitle }))
- })
- const allowSubmit = computed(() => {
- return questionList.value?.length && scoreValues.value?.length === questionList.value?.length
- })
- const onSubmit = () => {
- emits('submit', questionStruct.value)
- }
- const onEnter = (index: number) => {
- activeIndex.value = index + 1
- if (activeIndex.value >= questionList.value?.length) {
- onSubmit()
- }
- }
- const onFocused = (index: number) => {
- activeIndex.value = index
- }
- const onToggleClick = () => {
- dialogMode.value = props.toggleModal ? !dialogMode.value : dialogMode.value
- if (!props.toggleModal) {
- modalVisible.value = false
- }
- }
- </script>
- <style scoped lang="scss">
- .modal-box {
- max-height: 50vh;
- min-height: 8vw;
- }
- </style>
|