<template>
<tiny-dialog-box :visible="visible" title="新建应用" width="400px" append-to-body destroy-on-close @close="cancle">
<tiny-form
ref="editAppInfoRef"
label-position="left"
label-width="84px"
label-align
:model="formState"
:rules="validRules"
validate-type="text"
>
<tiny-form-item label="应用名称" prop="name">
<tiny-input v-model="formState.name" placeholder="请输入"></tiny-input>
</tiny-form-item>
<tiny-form-item label="应用描述" prop="description">
<tiny-input v-model="formState.description" type="textarea" placeholder="请输入此次发布的修改点"></tiny-input>
</tiny-form-item>
<tiny-form-item label="缩略图">
<div class="form-item-icon-wrapper">
<div class="form-item-icon-mask" v-if="isOpen"></div>
<svg-icon :name="formState.assetsUrl" class="form-item-icon" @click="handleOpen"></svg-icon>
<transition name="dropdown">
<div v-if="isOpen" class="dropdown-menu">
<div class="icon-list">
<template v-for="iconIndex in 15" :key="iconIndex">
<svg-icon
:name="'template-cover-' + iconIndex"
class="icon"
@click="handleSelectIcon('template-cover-' + iconIndex)"
></svg-icon>
</template>
</div>
</div>
</transition>
</div>
</tiny-form-item>
</tiny-form>
<template #footer>
<tiny-button type="primary" @click="confirm"> 确定 </tiny-button>
<tiny-button @click="cancle">取消</tiny-button>
</template>
</tiny-dialog-box>
</template>
<script lang="ts">
import { ref, reactive } from 'vue'
import {
Input as TinyInput,
Button as TinyButton,
DialogBox as TinyDialogBox,
Form as TinyForm,
FormItem as TinyFormItem
} from '@opentiny/vue'
export default {
components: {
TinyInput,
TinyButton,
TinyDialogBox,
TinyForm,
TinyFormItem
},
props: {
visible: {
type: Boolean,
default: false
},
template: {
type: Object,
default: () => ({})
}
},
emits: ['confirm'],
setup(props, { emit }) {
const editAppInfoRef = ref()
const formState = reactive({
name: '',
description: props.template.description || '',
sceneId: props.template.sceneId || null,
industryId: props.template.industryId || null,
assetsUrl: props.template.assetsUrl || 'template-cover-1',
framework: 'Vue'
})
const isOpen = ref(false)
const validRules = {
name: [
{ required: true, message: '应用名称必填', trigger: 'blur' },
{ max: 50, message: '长度不大于50', trigger: 'change' },
{
trigger: 'blur',
validator: (rule: any, value: string, callback: any) => {
if (!/^[\w\-_]+$/.test(value)) {
callback(new Error('应用名称只能包括英文、数字、中划线和下划线'))
} else {
callback()
}
}
},
{
trigger: 'blur',
validator: (rule: any, value: string, callback: any) => {
if (value === props.template.name) {
callback(new Error('应用名称不能与模板名称一致'))
} else {
callback()
}
}
}
],
description: [
{ max: 200, message: '长度不大于200', trigger: 'change' },
{
trigger: 'blur',
validator: (rule: any, value: string, callback: any) => {
if (!/^[\w\-_\u4e00-\u9fa5]*$/.test(value)) {
callback(new Error('描述只能包括中文、英文、数字、中划线和下划线'))
} else {
callback()
}
}
}
]
}
const setVisible = (visible: boolean) => emit('update:visible', visible)
const handleOpen = () => {
isOpen.value = true
}
const handleSelectIcon = (icon: string) => {
formState.assetsUrl = icon
isOpen.value = false
}
const cancle = () => {
isOpen.value = false
setVisible(false)
}
const confirm = () => {
editAppInfoRef.value.validate((valid: boolean) => {
if (valid) {
emit('confirm', {
...props.template,
...formState
})
setVisible(false)
}
})
}
return {
isOpen,
editAppInfoRef,
formState,
validRules,
setVisible,
handleOpen,
handleSelectIcon,
confirm,
cancle
}
}
}
</script>
<style lang="less" scoped>
.form-item-icon-wrapper {
position: relative;
.form-item-icon {
font-size: 40px;
cursor: pointer;
}
.form-item-icon-mask {
background-color: var(--te-template-mask-modal-bg-color);
transition: background-color, 0.2s, ease-in-out;
position: fixed;
width: 40px;
height: 40px;
border-radius: 8px;
}
.dropdown-menu {
position: absolute;
bottom: 100%;
left: 0;
padding: 16px;
margin-bottom: 5px;
width: 192px;
border-radius: 4px;
z-index: 1000;
overflow: hidden;
background: var(--te-template-common-bg-color);
box-shadow: 0 4px 16px 0 var(--te-base-box-shadow-rgba-3);
.icon-list {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 4px 0;
.icon {
font-size: 32px;
cursor: pointer;
}
}
}
}
</style>