rainbro 3 days ago
parent
commit
be30d9bdb1
  1. 80
      src/components/GuipRadio.vue
  2. 120
      src/components/PreviewTab.vue
  3. 31
      src/views/elementGroups.vue

80
src/components/GuipRadio.vue

@ -1,13 +1,10 @@
<template>
<el-form-item :class="[{'column':column},'form-item']" :label="label" :prop="prop" :rules="rules" :required="required">
<el-form-item :class="[{ 'column': column }, 'form-item']" :label="label" :prop="prop" :rules="rules"
:required="required">
<el-radio-group v-model="selectedValue" v-bind="$attrs" @change="handleChange">
<el-radio
v-for="option in processedOptions"
:key="getValue(option)"
:label="getValue(option)"
:disabled="option.disabled"
>
{{ getLabel(option) }}
<el-radio v-for="(optionValue, optionKey) in normalizedOptions" :key="optionKey"
:label="getValue(optionValue)" :disabled="isDisabled(optionValue[valueKey])">
{{ getLabel(optionValue) }}
</el-radio>
</el-radio-group>
</el-form-item>
@ -18,17 +15,19 @@ export default {
name: 'MyRadioGroup',
props: {
//
column:{
type:String,
default:''
column: {
type: String,
default: ''
},
required:{
type:Boolean,
default:false
required: {
type: Boolean,
default: false
},
// [{ label: '', value: '', disabled: false }]
// :
// 1. : [{ label: '', value: '', disabled: false }]
// 2. : { key1: 'value1', key2: 'value2' }
options: {
type: Array,
type: [Array, Object],
required: true,
},
// 使 v-model
@ -64,19 +63,27 @@ export default {
formatter: {
type: Function,
default: null
},
// key
disabledKeys: {
type: Array,
default: () => []
}
},
computed: {
processedOptions() {
return this.options.map(option => {
if (this.formatter) {
return {
...option,
formattedLabel: this.formatter(option)
}
}
return option
})
//
normalizedOptions() {
//
if (Array.isArray(this.options)) {
return this.options;
} else if (typeof this.options === 'object' && this.options !== null) {
//
return Object.keys(this.options).map(key => ({
key,
value: this.options[key]
}));
}
return [];
}
},
data() {
@ -97,12 +104,27 @@ export default {
this.$emit('change', value); // change
},
getLabel(option) {
if (this.formatter) return option.formattedLabel || this.formatter(option)
return option[this.labelKey]
if (this.formatter) return this.formatter(option);
//
if (typeof option === 'object' && 'key' in option && 'value' in option) {
return option.value;
}
return option[this.labelKey] || option;
},
getValue(option) {
return option[this.valueKey]
//
if (typeof option === 'object' && 'key' in option && 'value' in option) {
return option.key;
}
return option[this.valueKey] || option;
},
//
isDisabled(key) {
return this.disabledKeys.includes(key);
}
},
};
</script>

120
src/components/PreviewTab.vue

@ -0,0 +1,120 @@
<template>
<div class="preview-container">
<div class="preview_top flex-between">
<b class="preview-title">实时预览</b>
<div class="toggle-container">
<div class="toggle-button" v-if="showPc" :class="{ active: activeView === 'desktop' }"
@click="switchView('desktop')">
电脑端
</div>
<div class="toggle-button" v-if="showMobile" :class="{ active: activeView === 'mobile' }"
@click="switchView('mobile')">
手机端
</div>
</div>
</div>
<div class="content-container">
<!-- 电脑端内容 -->
<div v-show="activeView === 'desktop'" class="desktop-view">
<slot name="desktop"></slot>
</div>
<!-- 手机端内容 -->
<div v-show="activeView === 'mobile'" class="mobile-view">
<slot name="mobile"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DevicePreview',
props:{
showMobile:{
type:Boolean,
default:true
},
showPc:{
type:Boolean,
default:true
},
},
data() {
return {
activeView: 'desktop' //
}
},
methods: {
switchView(view) {
this.activeView = view;
}
}
}
</script>
<style scoped>
.preview-container {
max-width: 800px;
min-width: 300px;
margin: 0 auto;
padding: 24px;
border-radius: 4px;
background: #FAFAFA;
}
.preview_top{
margin-bottom: 20px;
}
.preview-title {
text-align: center;
color: #1E2226;
}
.toggle-container {
display: flex;
height: 26px;
justify-content: center;
align-items: center;
padding: 3px 6px;
border-radius: 4px;
background: #F2F3F5;
}
.toggle-button {
padding: 1px 12px;
border-radius: 2px;
box-sizing: border-box;
cursor: pointer;
transition: all 0.3s ease;
}
.toggle-button.active {
color: #006AFF;
background: #FFFFFF;
}
.toggle-button.active:after {
/* content: '';
position: absolute;
bottom: -11px;
left: 0;
width: 100%;
height: 2px;
background-color: #1890ff; */
}
.content-container {
/* min-height: 300px;
padding: 20px;
border: 2px solid #ffd700;
border-radius: 4px;
background-color: #fff; */
}
.desktop-view,
.mobile-view {
width: 100%;
}
</style>

31
src/views/elementGroups.vue

@ -26,18 +26,33 @@
</template>
</PromptText>
<div class="ele-item">
<label for="">实时预览外层嵌套</label>
<!-- 默认 显示电脑端手机端 -->
<!-- :showMobile="false" :showPc="false" -->
<DevicePreview >
<template #desktop>
电脑端内容-内容自定义
</template>
<template #mobile>
内容自定义
手机端端内容-- 手机端端内容
</template>
</DevicePreview>
</div>
<!-- ele-item 为类名的这种div label h3 仅在此页面进行布局使用复制时无需复制此元素 -->
<el-form :model="form" :rules="rules" class="el-row demo-ruleForm" ref="formRef">
<div class="ele-item">
<label for="">单选框11</label>
<label for="">单选框(对象格式)</label>
<GuipRadio v-model="form.language" :options="languageOptions" label="选择语言" prop="language"
@change="radioChange" :rules="rules.language" />
</div>
<div class="ele-item">
<label for="">单选框11</label>
<GuipRadio v-model="form.language" :options="languageOptions" label="自定义属性" prop="language"
@change="radioChange" :rules="rules.language" label-key="name" :formatter="formatLabel"
<label for="">单选框2数组格式 + 自定义取值</label>
<GuipRadio v-model="form.language" :options="languageOptions1" label="自定义属性" prop="language"
@change="radioChange" :rules="rules.language" label-key="name" :disabledKeys="['1']"
value-key="id" />
</div>
<div class="ele-item">
@ -537,6 +552,7 @@ import HoverButton from '@/components/HoverButton.vue'
import GuipFormItem from '@/components/GuipFormItem.vue'
import SvgIcon from '@/components/SvgIcon.vue';
import PromptText from "@/components/PromptText.vue";
import DevicePreview from "@/components/PreviewTab.vue";
export default {
@ -555,6 +571,7 @@ export default {
HoverButton,
SvgIcon,
GuipFormItem,
DevicePreview,
CustomDropdown
},
data() {
@ -635,12 +652,16 @@ export default {
input2: '',
input3: '',
},
languageOptions: [
languageOptions1: [
{ label: 'JavaScript', value: 'js', selectedLabel: 'JavaScripthhhhhhhhhh',id:'1',name:'麻辣烫' },
{ label: 'Python', value: 'py', selectedLabel: 'JavaScripthhhhhhhhhh',id:'10',name:'易烊千玺' },
{ label: 'Java', value: 'java', disabled: true, selectedLabel: 'JavaScripthhhhhhhhhh',id:'11',name:'王鹤di' }, //
{ label: 'Go', value: 'go', selectedLabel: 'JavaScripthhhhhhhhhh',id:'12',name:'王俊凯' },
],
languageOptions:{
'20':'查重站',
'31':'AI站'
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }

Loading…
Cancel
Save