Pre Merge pull request !333 from puhui999/master-fix
commit
880225a892
|
|
@ -2,18 +2,17 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { handleTree } from '@vben/utils';
|
|
||||||
|
|
||||||
import { Cascader } from 'ant-design-vue';
|
import { Cascader } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getAreaTree } from '#/api/system/area';
|
import { getAreaTree } from '#/api/system/area';
|
||||||
|
import { AreaLevelEnum } from '@vben/constants';
|
||||||
|
|
||||||
defineOptions({ name: 'AreaSelect' });
|
defineOptions({ name: 'AreaSelect' });
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
modelValue: undefined,
|
modelValue: undefined,
|
||||||
value: undefined,
|
value: undefined,
|
||||||
level: 3,
|
level: AreaLevelEnum.DISTRICT,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
placeholder: '请选择省市区',
|
placeholder: '请选择省市区',
|
||||||
clearable: true,
|
clearable: true,
|
||||||
|
|
@ -41,7 +40,7 @@ interface AreaVO {
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue?: number[] | string[];
|
modelValue?: number[] | string[];
|
||||||
value?: number[] | string[];
|
value?: number[] | string[];
|
||||||
level?: 1 | 2 | 3; // 1-省 2-市 3-区
|
level?: typeof AreaLevelEnum[keyof typeof AreaLevelEnum];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
|
|
@ -121,15 +120,15 @@ function syncSelectedValue(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保是数组格式
|
// 确保是数组格式
|
||||||
if (Array.isArray(newValue)) {
|
selectedValue.value = Array.isArray(newValue)
|
||||||
selectedValue.value = newValue as number[];
|
? (newValue as number[])
|
||||||
} else {
|
: [newValue as number];
|
||||||
selectedValue.value = [newValue as number];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听 modelValue 和 value 变化
|
// 监听 modelValue 和 value 变化
|
||||||
watch(() => props.modelValue || props.value, syncSelectedValue, { immediate: true });
|
watch(() => props.modelValue || props.value, syncSelectedValue, {
|
||||||
|
immediate: true,
|
||||||
|
});
|
||||||
|
|
||||||
// 组件挂载时加载数据
|
// 组件挂载时加载数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<!-- 网页 iframe 组件 (Ant Design Vue 版本) -->
|
<!-- 网页 iframe 组件 (Ant Design Vue 版本) -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { isUrl } from '#/utils';
|
||||||
|
|
||||||
defineOptions({ name: 'IframeComponent' });
|
defineOptions({ name: 'IframeComponent' });
|
||||||
|
|
||||||
|
|
@ -16,11 +18,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
sandbox: '',
|
sandbox: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:modelValue', value: string): void;
|
|
||||||
(e: 'update:value', value: string): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 接受父组件参数
|
// 接受父组件参数
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue?: string;
|
modelValue?: string;
|
||||||
|
|
@ -36,23 +33,14 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示的 URL(优先使用 url prop,其次使用 value 或 modelValue)
|
// 显示的 URL(优先使用 url prop,其次使用 value 或 modelValue)
|
||||||
const displayUrl = computed(() => props.url || props.value || props.modelValue || '');
|
const displayUrl = computed(
|
||||||
|
() => props.url || props.value || props.modelValue || '',
|
||||||
|
);
|
||||||
|
|
||||||
// 是否显示预览
|
// 是否显示预览
|
||||||
const showPreview = computed(() => {
|
const showPreview = computed(() => {
|
||||||
return displayUrl.value && isValidUrl(displayUrl.value);
|
return displayUrl.value && isUrl(displayUrl.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// URL 验证
|
|
||||||
function isValidUrl(url: string): boolean {
|
|
||||||
if (!url || url.trim() === '') return false;
|
|
||||||
try {
|
|
||||||
const urlObj = new URL(url);
|
|
||||||
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -104,4 +92,3 @@ function isValidUrl(url: string): boolean {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { cloneDeep } from '@vben/utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
localeProps,
|
localeProps,
|
||||||
makeRequiredRule,
|
makeRequiredRule,
|
||||||
} from '#/components/form-create/helpers';
|
} from '#/components/form-create/helpers';
|
||||||
|
import { AreaLevelEnum } from '@vben/constants';
|
||||||
|
|
||||||
/** 省市区选择器规则 */
|
/** 省市区选择器规则 */
|
||||||
export function useAreaSelectRule() {
|
export function useAreaSelectRule() {
|
||||||
|
|
@ -31,11 +30,11 @@ export function useAreaSelectRule() {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'level',
|
field: 'level',
|
||||||
title: '选择层级',
|
title: '选择层级',
|
||||||
value: 3,
|
value: AreaLevelEnum.DISTRICT,
|
||||||
options: [
|
options: [
|
||||||
{ label: '省', value: 1 },
|
{ label: '省', value: AreaLevelEnum.PROVINCE },
|
||||||
{ label: '省/市', value: 2 },
|
{ label: '省/市', value: AreaLevelEnum.CITY },
|
||||||
{ label: '省/市/区', value: 3 },
|
{ label: '省/市/区', value: AreaLevelEnum.DISTRICT },
|
||||||
],
|
],
|
||||||
info: '限制可选择的地区层级',
|
info: '限制可选择的地区层级',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,16 @@ export const findIndex = <T = Recordable<any>>(
|
||||||
});
|
});
|
||||||
return index;
|
return index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL 验证
|
||||||
|
* @param path URL 路径
|
||||||
|
*/
|
||||||
|
export const isUrl = (path: string): boolean => {
|
||||||
|
// fix:修复hash路由无法跳转的问题
|
||||||
|
/* eslint-disable regexp/no-unused-capturing-group, regexp/no-super-linear-backtracking, regexp/no-useless-quantifier */
|
||||||
|
const reg =
|
||||||
|
/(((^https?:(?:\/\/)?)(?:[-:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%#/.\w-]*)?\??[-+=&%@.\w]*(?:#\w*)?)?)$/;
|
||||||
|
return reg.test(path);
|
||||||
|
/* eslint-enable regexp/no-unused-capturing-group, regexp/no-super-linear-backtracking, regexp/no-useless-quantifier */
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,16 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { handleTree } from '@vben/utils';
|
|
||||||
|
|
||||||
import { ElCascader } from 'element-plus';
|
import { ElCascader } from 'element-plus';
|
||||||
|
|
||||||
import { getAreaTree } from '#/api/system/area';
|
import { getAreaTree } from '#/api/system/area';
|
||||||
|
import { AreaLevelEnum } from '@vben/constants';
|
||||||
|
|
||||||
defineOptions({ name: 'AreaSelect' });
|
defineOptions({ name: 'AreaSelect' });
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
modelValue: undefined,
|
modelValue: undefined,
|
||||||
level: 3,
|
level: AreaLevelEnum.DISTRICT,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
placeholder: '请选择省市区',
|
placeholder: '请选择省市区',
|
||||||
clearable: true,
|
clearable: true,
|
||||||
|
|
@ -38,7 +37,7 @@ interface AreaVO {
|
||||||
// 接受父组件参数
|
// 接受父组件参数
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue?: number[] | string[];
|
modelValue?: number[] | string[];
|
||||||
level?: 1 | 2 | 3; // 1-省 2-市 3-区
|
level?: typeof AreaLevelEnum[keyof typeof AreaLevelEnum];
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
|
|
@ -118,11 +117,9 @@ function syncSelectedValue(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保是数组格式
|
// 确保是数组格式
|
||||||
if (Array.isArray(newValue)) {
|
selectedValue.value = Array.isArray(newValue)
|
||||||
selectedValue.value = newValue as number[];
|
? (newValue as number[])
|
||||||
} else {
|
: [newValue as number];
|
||||||
selectedValue.value = [newValue as number];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听 modelValue 变化
|
// 监听 modelValue 变化
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
<!-- 网页 iframe 组件 (Element Plus 版本) -->
|
<!-- 网页 iframe 组件 (Element Plus 版本) -->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import { isUrl } from '#/utils';
|
||||||
|
|
||||||
defineOptions({ name: 'IframeComponent' });
|
defineOptions({ name: 'IframeComponent' });
|
||||||
|
|
||||||
|
|
@ -15,10 +17,6 @@ const props = withDefaults(defineProps<Props>(), {
|
||||||
sandbox: '',
|
sandbox: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:modelValue', value: string): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 接受父组件参数
|
// 接受父组件参数
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue?: string;
|
modelValue?: string;
|
||||||
|
|
@ -37,19 +35,8 @@ const displayUrl = computed(() => props.url || props.modelValue || '');
|
||||||
|
|
||||||
// 是否显示预览
|
// 是否显示预览
|
||||||
const showPreview = computed(() => {
|
const showPreview = computed(() => {
|
||||||
return displayUrl.value && isValidUrl(displayUrl.value);
|
return displayUrl.value && isUrl(displayUrl.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// URL 验证
|
|
||||||
function isValidUrl(url: string): boolean {
|
|
||||||
if (!url || url.trim() === '') return false;
|
|
||||||
try {
|
|
||||||
const urlObj = new URL(url);
|
|
||||||
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { cloneDeep } from '@vben/utils';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
localeProps,
|
localeProps,
|
||||||
makeRequiredRule,
|
makeRequiredRule,
|
||||||
} from '#/components/form-create/helpers';
|
} from '#/components/form-create/helpers';
|
||||||
|
import { AreaLevelEnum } from '@vben/constants';
|
||||||
|
|
||||||
/** 省市区选择器规则 */
|
/** 省市区选择器规则 */
|
||||||
export function useAreaSelectRule() {
|
export function useAreaSelectRule() {
|
||||||
|
|
@ -31,11 +30,11 @@ export function useAreaSelectRule() {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
field: 'level',
|
field: 'level',
|
||||||
title: '选择层级',
|
title: '选择层级',
|
||||||
value: 3,
|
value: AreaLevelEnum.DISTRICT,
|
||||||
options: [
|
options: [
|
||||||
{ label: '省', value: 1 },
|
{ label: '省', value: AreaLevelEnum.PROVINCE },
|
||||||
{ label: '省/市', value: 2 },
|
{ label: '省/市', value: AreaLevelEnum.CITY },
|
||||||
{ label: '省/市/区', value: 3 },
|
{ label: '省/市/区', value: AreaLevelEnum.DISTRICT },
|
||||||
],
|
],
|
||||||
info: '限制可选择的地区层级',
|
info: '限制可选择的地区层级',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -28,3 +28,16 @@ export const findIndex = <T = Recordable<any>>(
|
||||||
});
|
});
|
||||||
return index;
|
return index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL 验证
|
||||||
|
* @param path URL 路径
|
||||||
|
*/
|
||||||
|
export const isUrl = (path: string): boolean => {
|
||||||
|
// fix:修复hash路由无法跳转的问题
|
||||||
|
/* eslint-disable regexp/no-unused-capturing-group, regexp/no-super-linear-backtracking, regexp/no-useless-quantifier */
|
||||||
|
const reg =
|
||||||
|
/(((^https?:(?:\/\/)?)(?:[-:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%#/.\w-]*)?\??[-+=&%@.\w]*(?:#\w*)?)?)$/;
|
||||||
|
return reg.test(path);
|
||||||
|
/* eslint-enable regexp/no-unused-capturing-group, regexp/no-super-linear-backtracking, regexp/no-useless-quantifier */
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -57,3 +57,12 @@ export const SystemUserSocialTypeEnum = {
|
||||||
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png',
|
img: 'https://s1.ax1x.com/2022/05/22/OzMrzn.png',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 地区选择器层级枚举
|
||||||
|
*/
|
||||||
|
export const AreaLevelEnum = {
|
||||||
|
PROVINCE: 1, // 省
|
||||||
|
CITY: 2, // 市
|
||||||
|
DISTRICT: 3, // 区
|
||||||
|
} as const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue