feat: 皮肤设置2.0 (#426)
* fix: 修复windows上传文件路径反斜杠问题 * feat: 补全服务端skinConf定义 * feat: web端皮肤背景设置2.0 * feat: 删除console.log * feat: 皮肤设置内容结果增加背景设置以及应用皮肤设置方法抽离 --------- Co-authored-by: jiangchunfu <jiangchunfu@kaike.la> Co-authored-by: sudoooooo <zjbbabybaby@gmail.com>
This commit is contained in:
parent
4bc8fbc557
commit
4b8719ab9c
@ -135,6 +135,17 @@ export interface BaseConf {
|
|||||||
export interface SkinConf {
|
export interface SkinConf {
|
||||||
skinColor: string;
|
skinColor: string;
|
||||||
inputBgColor: string;
|
inputBgColor: string;
|
||||||
|
backgroundConf: {
|
||||||
|
color: string;
|
||||||
|
type: string;
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
contentConf: {
|
||||||
|
opacity: number;
|
||||||
|
};
|
||||||
|
themeConf: {
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BottomConf {
|
export interface BottomConf {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { join, dirname } from 'path';
|
import { join, dirname, sep } from 'path';
|
||||||
import fse from 'fs-extra';
|
import fse from 'fs-extra';
|
||||||
import { createWriteStream } from 'fs';
|
import { createWriteStream } from 'fs';
|
||||||
import { FileUploadHandler } from './uploadHandler.interface';
|
import { FileUploadHandler } from './uploadHandler.interface';
|
||||||
@ -23,7 +23,9 @@ export class LocalHandler implements FileUploadHandler {
|
|||||||
const filePath = join(
|
const filePath = join(
|
||||||
options?.pathPrefix ? options?.pathPrefix : '',
|
options?.pathPrefix ? options?.pathPrefix : '',
|
||||||
filename,
|
filename,
|
||||||
);
|
)
|
||||||
|
.split(sep)
|
||||||
|
.join('/');
|
||||||
const physicalPath = join(this.physicalRootPath, filePath);
|
const physicalPath = join(this.physicalRootPath, filePath);
|
||||||
await fse.mkdir(dirname(physicalPath), { recursive: true });
|
await fse.mkdir(dirname(physicalPath), { recursive: true });
|
||||||
const writeStream = createWriteStream(physicalPath);
|
const writeStream = createWriteStream(physicalPath);
|
||||||
|
@ -249,6 +249,8 @@ describe('DataStatisticController', () => {
|
|||||||
skinConf: {
|
skinConf: {
|
||||||
backgroundConf: {
|
backgroundConf: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
|
type: 'color',
|
||||||
|
image: '',
|
||||||
},
|
},
|
||||||
themeConf: {
|
themeConf: {
|
||||||
color: '#ffa600',
|
color: '#ffa600',
|
||||||
|
@ -44,6 +44,17 @@ export const mockSensitiveResponseSchema: ResponseSchema = {
|
|||||||
logoImageWidth: '60%',
|
logoImageWidth: '60%',
|
||||||
},
|
},
|
||||||
skinConf: {
|
skinConf: {
|
||||||
|
backgroundConf: {
|
||||||
|
color: '#fff',
|
||||||
|
type: 'color',
|
||||||
|
image: '',
|
||||||
|
},
|
||||||
|
themeConf: {
|
||||||
|
color: '#ffa600',
|
||||||
|
},
|
||||||
|
contentConf: {
|
||||||
|
opacity: 100,
|
||||||
|
},
|
||||||
skinColor: '#4a4c5b',
|
skinColor: '#4a4c5b',
|
||||||
inputBgColor: '#ffffff',
|
inputBgColor: '#ffffff',
|
||||||
},
|
},
|
||||||
@ -327,6 +338,17 @@ export const mockResponseSchema: ResponseSchema = {
|
|||||||
logoImageWidth: '60%',
|
logoImageWidth: '60%',
|
||||||
},
|
},
|
||||||
skinConf: {
|
skinConf: {
|
||||||
|
backgroundConf: {
|
||||||
|
color: '#fff',
|
||||||
|
type: 'color',
|
||||||
|
image: '',
|
||||||
|
},
|
||||||
|
themeConf: {
|
||||||
|
color: '#ffa600',
|
||||||
|
},
|
||||||
|
contentConf: {
|
||||||
|
opacity: 100,
|
||||||
|
},
|
||||||
skinColor: '#4a4c5b',
|
skinColor: '#4a4c5b',
|
||||||
inputBgColor: '#ffffff',
|
inputBgColor: '#ffffff',
|
||||||
},
|
},
|
||||||
|
@ -176,7 +176,21 @@ describe('SurveyController', () => {
|
|||||||
endTime: '2034-01-23 21:59:05',
|
endTime: '2034-01-23 21:59:05',
|
||||||
},
|
},
|
||||||
bottomConf: { logoImage: '/imgs/Logo.webp', logoImageWidth: '60%' },
|
bottomConf: { logoImage: '/imgs/Logo.webp', logoImageWidth: '60%' },
|
||||||
skinConf: { skinColor: '#4a4c5b', inputBgColor: '#ffffff' },
|
skinConf: {
|
||||||
|
skinColor: '#4a4c5b',
|
||||||
|
inputBgColor: '#ffffff',
|
||||||
|
backgroundConf: {
|
||||||
|
color: '#fff',
|
||||||
|
type: 'color',
|
||||||
|
image: '',
|
||||||
|
},
|
||||||
|
themeConf: {
|
||||||
|
color: '#ffa600',
|
||||||
|
},
|
||||||
|
contentConf: {
|
||||||
|
opacity: 100,
|
||||||
|
},
|
||||||
|
},
|
||||||
submitConf: {},
|
submitConf: {},
|
||||||
dataConf: {
|
dataConf: {
|
||||||
dataList: [],
|
dataList: [],
|
||||||
|
@ -50,7 +50,9 @@
|
|||||||
"skinColor": "#4a4c5b",
|
"skinColor": "#4a4c5b",
|
||||||
"inputBgColor": "#ffffff",
|
"inputBgColor": "#ffffff",
|
||||||
"backgroundConf": {
|
"backgroundConf": {
|
||||||
"color": "#ffffff"
|
"color": "#ffffff",
|
||||||
|
"type": "color",
|
||||||
|
"image": ""
|
||||||
},
|
},
|
||||||
"themeConf": {
|
"themeConf": {
|
||||||
"color": "#ffa600"
|
"color": "#ffa600"
|
||||||
|
@ -44,6 +44,17 @@ export const mockResponseSchema: ResponseSchema = {
|
|||||||
logoImageWidth: '60%',
|
logoImageWidth: '60%',
|
||||||
},
|
},
|
||||||
skinConf: {
|
skinConf: {
|
||||||
|
backgroundConf: {
|
||||||
|
color: '#fff',
|
||||||
|
type: 'color',
|
||||||
|
image: '',
|
||||||
|
},
|
||||||
|
themeConf: {
|
||||||
|
color: '#ffa600',
|
||||||
|
},
|
||||||
|
contentConf: {
|
||||||
|
opacity: 100,
|
||||||
|
},
|
||||||
skinColor: '#4a4c5b',
|
skinColor: '#4a4c5b',
|
||||||
inputBgColor: '#ffffff',
|
inputBgColor: '#ffffff',
|
||||||
},
|
},
|
||||||
|
BIN
web/public/imgs/icons/upload.png
Normal file
BIN
web/public/imgs/icons/upload.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 340 B |
21
web/src/common/utils/applySkinConfig.ts
Normal file
21
web/src/common/utils/applySkinConfig.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export default function (skinConfig: any) {
|
||||||
|
const root = document.documentElement
|
||||||
|
const { themeConf, backgroundConf, contentConf } = skinConfig
|
||||||
|
|
||||||
|
if (themeConf?.color) {
|
||||||
|
// 设置主题颜色
|
||||||
|
root.style.setProperty('--primary-color', themeConf?.color)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置背景
|
||||||
|
const { color, type, image } = backgroundConf || {}
|
||||||
|
root.style.setProperty(
|
||||||
|
'--primary-background',
|
||||||
|
type === 'image' ? `url(${image}) no-repeat center / cover` : color
|
||||||
|
)
|
||||||
|
|
||||||
|
if (contentConf?.opacity.toString()) {
|
||||||
|
// 设置全局透明度
|
||||||
|
root.style.setProperty('--opacity', `${contentConf.opacity / 100}`)
|
||||||
|
}
|
||||||
|
}
|
@ -14,22 +14,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted } from 'vue'
|
import { onMounted, watch } from 'vue'
|
||||||
import { useEditStore } from '@/management/stores/edit'
|
import { useEditStore } from '@/management/stores/edit'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/src/message.scss'
|
import 'element-plus/theme-chalk/src/message.scss'
|
||||||
|
import applySkinConfig from '@/common/utils/applySkinConfig'
|
||||||
|
|
||||||
import LeftMenu from '@/management/components/LeftMenu.vue'
|
import LeftMenu from '@/management/components/LeftMenu.vue'
|
||||||
import CommonTemplate from './components/CommonTemplate.vue'
|
import CommonTemplate from './components/CommonTemplate.vue'
|
||||||
import Navbar from './components/ModuleNavbar.vue'
|
import Navbar from './components/ModuleNavbar.vue'
|
||||||
|
|
||||||
const editStore = useEditStore()
|
const editStore = useEditStore()
|
||||||
const { init, setSurveyId } = editStore
|
const { init, setSurveyId, schema } = editStore
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => schema.skinConf,
|
||||||
|
(v) => {
|
||||||
|
applySkinConfig(v)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const surveyId = route.params.id as string
|
const surveyId = route.params.id as string
|
||||||
setSurveyId(surveyId)
|
setSurveyId(surveyId)
|
||||||
|
@ -30,12 +30,14 @@
|
|||||||
<i-ep-monitor />
|
<i-ep-monitor />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :class="`preview-panel ${previewTab == 1 ? 'phone' : 'pc'}`">
|
<div
|
||||||
|
:class="`preview-panel ${previewTab == 1 ? 'phone' : 'pc'}`"
|
||||||
|
>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="tips-wrapper">
|
<div class="tips-wrapper">
|
||||||
<i-ep-WarningFilled /> <span>用户预览模式,数据不保存!</span>
|
<i-ep-WarningFilled /> <span>用户预览模式,数据不保存!</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-loading="loading" element-loading-text="加载中..." style="height: 100%">
|
<div class="iframe-wrapper" v-loading="loading" element-loading-text="加载中...">
|
||||||
<iframe
|
<iframe
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
id="iframe-preview"
|
id="iframe-preview"
|
||||||
@ -125,12 +127,28 @@ const closedDialog = () => {
|
|||||||
&.pc {
|
&.pc {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: #f7f7f7;
|
|
||||||
box-shadow: 0px 2px 10px -2px rgba(82, 82, 102, 0.2);
|
box-shadow: 0px 2px 10px -2px rgba(82, 82, 102, 0.2);
|
||||||
height: 726px;
|
height: 726px;
|
||||||
|
background: var(--primary-background);
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.tips-wrapper {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe-wrapper {
|
||||||
width: 636px;
|
width: 636px;
|
||||||
height: 704px;
|
flex: 1;
|
||||||
|
margin-top: 20px;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.phone {
|
&.phone {
|
||||||
@ -148,6 +166,9 @@ const closedDialog = () => {
|
|||||||
padding-bottom: 14px;
|
padding-bottom: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
.iframe-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
iframe {
|
iframe {
|
||||||
border-radius: 0px 0px 20px 20px;
|
border-radius: 0px 0px 20px 20px;
|
||||||
@ -156,6 +177,7 @@ const closedDialog = () => {
|
|||||||
}
|
}
|
||||||
.tips-wrapper {
|
.tips-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: $primary-bg-color;
|
background: $primary-bg-color;
|
||||||
color: $primary-color;
|
color: $primary-color;
|
||||||
|
@ -39,7 +39,7 @@ const moduleConfig = toRef(schema, 'submitConf')
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #f6f7f9;
|
background: var(--primary-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-page-wrap {
|
.result-page-wrap {
|
||||||
@ -49,8 +49,6 @@ const moduleConfig = toRef(schema, 'submitConf')
|
|||||||
max-height: 812px;
|
max-height: 812px;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
padding: 0 0.3rem;
|
|
||||||
.result-page {
|
.result-page {
|
||||||
background: rgba(255, 255, 255, var(--opacity));
|
background: rgba(255, 255, 255, var(--opacity));
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -73,25 +73,6 @@ export default defineComponent({
|
|||||||
pageEditOne
|
pageEditOne
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
skinConf: {
|
|
||||||
handler(newVal) {
|
|
||||||
const { themeConf, backgroundConf, contentConf } = newVal
|
|
||||||
const root = document.documentElement
|
|
||||||
if (themeConf?.color) {
|
|
||||||
root.style.setProperty('--primary-color', themeConf?.color) // 设置主题颜色
|
|
||||||
}
|
|
||||||
if (backgroundConf?.color) {
|
|
||||||
root.style.setProperty('--primary-background-color', backgroundConf?.color) // 设置背景颜色
|
|
||||||
}
|
|
||||||
if (contentConf?.opacity.toString()) {
|
|
||||||
root.style.setProperty('--opacity', contentConf?.opacity / 100) // 设置全局透明度
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -103,7 +84,7 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #f6f7f9;
|
background: var(--primary-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-wrapper {
|
.pagination-wrapper {
|
||||||
@ -137,7 +118,6 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.box {
|
.box {
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.mask {
|
.mask {
|
||||||
@ -150,9 +130,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin: 0 0.3rem;
|
|
||||||
background: rgba(255, 255, 255, var(--opacity));
|
background: rgba(255, 255, 255, var(--opacity));
|
||||||
border-radius: 8px 8px 0 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,37 @@ export default [
|
|||||||
name: '背景',
|
name: '背景',
|
||||||
key: 'skinConf.backgroundConf',
|
key: 'skinConf.backgroundConf',
|
||||||
formConfigList: [
|
formConfigList: [
|
||||||
|
{
|
||||||
|
type: 'TabsSetter',
|
||||||
|
key: 'type',
|
||||||
|
tabList: [
|
||||||
|
{
|
||||||
|
label: '图片(<5M)',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '颜色',
|
||||||
|
value: 'color',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '背景图片',
|
||||||
|
type: 'UploadSingleFile',
|
||||||
|
accept: "image/*",
|
||||||
|
limitSize: 5,// 单位MB
|
||||||
|
key: 'image',
|
||||||
|
relyFunc: (data) => {
|
||||||
|
return data.type === 'image'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '背景颜色',
|
label: '背景颜色',
|
||||||
type: 'ColorPicker',
|
type: 'ColorPicker',
|
||||||
key: 'color'
|
key: 'color',
|
||||||
|
relyFunc: (data) => {
|
||||||
|
return data.type === 'color'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
65
web/src/materials/setters/widgets/TabsSetter.vue
Normal file
65
web/src/materials/setters/widgets/TabsSetter.vue
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tabs-setter">
|
||||||
|
<div class="tabs-header">
|
||||||
|
<div
|
||||||
|
v-for="item in tabList"
|
||||||
|
:class="['tabs-header__item', { active: props.formConfig.value === item.value }]"
|
||||||
|
:key="item.value"
|
||||||
|
@click="handleTabClick(item)"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
formConfig: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IEmit {
|
||||||
|
(ev: typeof FORM_CHANGE_EVENT_KEY, arg: { key: string; value: string }): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<IProps>()
|
||||||
|
const emit = defineEmits<IEmit>()
|
||||||
|
|
||||||
|
const tabList = computed(() => {
|
||||||
|
return props.formConfig?.tabList || []
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleTabClick(item: any) {
|
||||||
|
const key = props.formConfig.key
|
||||||
|
|
||||||
|
emit(FORM_CHANGE_EVENT_KEY, { key, value: item.value })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tabs-setter {
|
||||||
|
background: #f2f4f7;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
.tabs-header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
&__item {
|
||||||
|
flex: 1;
|
||||||
|
line-height: 24px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
100
web/src/materials/setters/widgets/UploadSingleFile.vue
Normal file
100
web/src/materials/setters/widgets/UploadSingleFile.vue
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<el-input size="small" v-model="inputValue">
|
||||||
|
<template #append>
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
class="upload-img"
|
||||||
|
action="/api/file/upload"
|
||||||
|
:accept="formConfig.accept"
|
||||||
|
:limit="1"
|
||||||
|
:show-file-list="false"
|
||||||
|
:data="{ channel: 'upload' }"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:headers="{
|
||||||
|
Authorization: `Bearer ${token}`
|
||||||
|
}"
|
||||||
|
:before-upload="beforeAvatarUpload"
|
||||||
|
:on-success="onSuccess"
|
||||||
|
>
|
||||||
|
<img src="/imgs/icons/upload.png" alt="上传图标" />
|
||||||
|
</el-upload>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import { ElMessage, genFileId } from 'element-plus'
|
||||||
|
import { get as _get } from 'lodash-es'
|
||||||
|
import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
|
||||||
|
import { useUserStore } from '@/management/stores/user'
|
||||||
|
|
||||||
|
const upload = ref<UploadInstance>()
|
||||||
|
|
||||||
|
import { FORM_CHANGE_EVENT_KEY } from '@/materials/setters/constant'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
formConfig: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IEmit {
|
||||||
|
(ev: typeof FORM_CHANGE_EVENT_KEY, arg: { key: string; value: string }): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<IProps>()
|
||||||
|
const emit = defineEmits<IEmit>()
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const token = _get(userStore, 'userInfo.token')
|
||||||
|
const inputValue = ref(props.formConfig.value)
|
||||||
|
|
||||||
|
watch(inputValue, (newValue) => {
|
||||||
|
emit(FORM_CHANGE_EVENT_KEY, { key: props.formConfig.key, value: newValue })
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.formConfig.value,
|
||||||
|
(newValue) => {
|
||||||
|
inputValue.value = newValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||||
|
upload.value!.clearFiles()
|
||||||
|
const file = files[0] as UploadRawFile
|
||||||
|
file.uid = genFileId()
|
||||||
|
upload.value!.handleStart(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSuccess(response: any) {
|
||||||
|
if (response?.data?.url) {
|
||||||
|
const key = props.formConfig.key
|
||||||
|
emit(FORM_CHANGE_EVENT_KEY, { key, value: response.data.url })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
|
||||||
|
const { limitSize } = props.formConfig
|
||||||
|
if (limitSize) {
|
||||||
|
if (rawFile.size / 1024 / 1024 > limitSize) {
|
||||||
|
ElMessage.error(`图片大小不得超过 ${limitSize}MB!`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.el-input-group__append) {
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.upload-img {
|
||||||
|
.el-upload {
|
||||||
|
width: 80px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -6,31 +6,12 @@ import { watch } from 'vue'
|
|||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
import { useSurveyStore } from './stores/survey'
|
import { useSurveyStore } from './stores/survey'
|
||||||
|
import applySkinConfig from '@/common/utils/applySkinConfig';
|
||||||
|
|
||||||
const { skinConf } = storeToRefs(useSurveyStore())
|
const { skinConf } = storeToRefs(useSurveyStore())
|
||||||
|
|
||||||
const updateSkinConfig = (value: any) => {
|
|
||||||
const root = document.documentElement
|
|
||||||
const { themeConf, backgroundConf, contentConf } = value
|
|
||||||
|
|
||||||
if (themeConf?.color) {
|
|
||||||
// 设置主题颜色
|
|
||||||
root.style.setProperty('--primary-color', themeConf?.color)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backgroundConf?.color) {
|
|
||||||
// 设置背景颜色
|
|
||||||
root.style.setProperty('--primary-background-color', backgroundConf?.color)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentConf?.opacity.toString()) {
|
|
||||||
// 设置全局透明度
|
|
||||||
root.style.setProperty('--opacity', `${parseInt(contentConf.opacity) / 100}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(skinConf, (value) => {
|
watch(skinConf, (value) => {
|
||||||
updateSkinConfig(value)
|
applySkinConfig(value)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -54,4 +35,15 @@ html {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 750px) {
|
||||||
|
body {
|
||||||
|
padding-top: 40px;
|
||||||
|
background: var(--primary-background);
|
||||||
|
}
|
||||||
|
#app {
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
box-shadow: var(--el-box-shadow);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -175,13 +175,11 @@ const handleSubmit = () => {
|
|||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background-color: var(--primary-background-color);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin: 0 0.3rem;
|
|
||||||
background: rgba(255, 255, 255, var(--opacity));
|
background: rgba(255, 255, 255, var(--opacity));
|
||||||
border-radius: 8px 8px 0 0;
|
border-radius: 8px 8px 0 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
Loading…
Reference in New Issue
Block a user