review:“新增 iframe 和省市区选择器组件”

pull/854/MERGE
YunaiV 2026-02-08 14:37:55 +08:00
parent c119040307
commit c153ff93c7
4 changed files with 22 additions and 31 deletions

View File

@ -18,6 +18,7 @@
<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue'
import { getAreaTree } from '@/api/system/area'
// TODO @puhui999 handleTree
import { handleTree } from '@/utils/tree'
defineOptions({ name: 'AreaSelect' })
@ -34,7 +35,7 @@ interface AreaVO {
interface Props {
modelValue?: number[] | string[]
level?: 1 | 2 | 3 // 1- 2- 3-
level?: 1 | 2 | 3 // 1- 2- 3- TODO @puhui999
disabled?: boolean
placeholder?: string
clearable?: boolean
@ -45,7 +46,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
modelValue: undefined,
level: 3,
level: 3, // TODO @puhui999
disabled: false,
placeholder: '请选择省市区',
clearable: true,
@ -57,28 +58,23 @@ const emit = defineEmits<{
(e: 'update:modelValue', value: number[] | string[] | undefined): void
}>()
// Element Plus Cascader props
const cascaderProps = {
label: 'name',
value: 'id',
children: 'children',
checkStrictly: true, //
emitPath: true //
}
} // Element Plus Cascader props
//
const areaTree = ref<AreaVO[]>([])
//
const selectedValue = ref<number[] | undefined>()
//
const loading = ref(false)
const areaTree = ref<AreaVO[]>([]) //
const selectedValue = ref<number[] | undefined>() //
const loading = ref(false) //
//
/** 加载地区树形数据 */
async function loadAreaTree(): Promise<void> {
try {
loading.value = true
const data = await getAreaTree()
// level
areaTree.value = filterTreeByLevel(data || [], props.level)
} catch (error) {
@ -89,13 +85,13 @@ async function loadAreaTree(): Promise<void> {
}
}
//
/** 根据层级过滤树形数据 */
function filterTreeByLevel(tree: AreaVO[], maxLevel: number): AreaVO[] {
if (maxLevel <= 0) return []
if (maxLevel <= 0) {
return []
}
return tree.map((node) => {
const newNode = { ...node }
// children
if (maxLevel === 1) {
delete newNode.children
@ -103,25 +99,22 @@ function filterTreeByLevel(tree: AreaVO[], maxLevel: number): AreaVO[] {
//
newNode.children = filterTreeByLevel(node.children, maxLevel - 1)
}
return newNode
})
}
//
/** 处理选中值变化 */
function handleChange(value: number[] | undefined): void {
if (value === undefined || value === null) {
emit('update:modelValue', undefined)
return
}
emit('update:modelValue', value)
}
// modelValue
/** 同步 modelValue 到内部选中值 */
function syncSelectedValue(): void {
const newValue = props.modelValue
if (newValue === undefined || newValue === null) {
selectedValue.value = undefined
return
@ -135,10 +128,10 @@ function syncSelectedValue(): void {
}
}
// modelValue
/** 监听 modelValue 变化 */
watch(() => props.modelValue, syncSelectedValue, { immediate: true })
//
/** 组件挂载时加载数据 */
onMounted(async () => {
await loadAreaTree()
})

View File

@ -23,6 +23,7 @@
</template>
<script lang="ts" setup>
// TODO @AI
import { computed, ref, watch } from 'vue'
defineOptions({ name: 'IframeComponent' })
@ -50,19 +51,18 @@ const props = withDefaults(defineProps<Props>(), {
sandbox: ''
})
// TODO @puhui999
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
// URL使 url prop使 modelValue
const displayUrl = computed(() => props.url || props.modelValue || '')
//
const displayUrl = computed(() => props.url || props.modelValue || '') // URL使 url prop使 modelValue
const showPreview = computed(() => {
return displayUrl.value && isValidUrl(displayUrl.value)
})
}) //
// URL
// TODO @puhui999
/** URL 验证 */
function isValidUrl(url: string): boolean {
if (!url || url.trim() === '') return false
try {

View File

@ -7,7 +7,6 @@ import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils
export const useAreaSelectRule = () => {
const label = '省市区选择器'
const name = 'AreaSelect'
return {
icon: 'icon-location',
label,

View File

@ -7,7 +7,6 @@ import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils
export const useIframeRule = () => {
const label = '网页 iframe'
const name = 'IframeComponent'
return {
icon: 'icon-link',
label,