Merge remote-tracking branch 'yudao/dev' into dev
commit
f697dfb266
|
|
@ -22,7 +22,7 @@ const md = new MarkdownIt({
|
||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
const copyHtml = `<div id="copy" data-copy='${str}' style="position: absolute; right: 10px; top: 5px; color: #fff;cursor: pointer;">复制</div>`;
|
const copyHtml = `<div id="copy" data-copy='${str}' style="position: absolute; right: 10px; top: 5px; color: #fff;cursor: pointer;">复制</div>`;
|
||||||
return `<pre style="position: relative;">${copyHtml}<code class="hljs">${hljs.highlight(lang, str, true).value}</code></pre>`;
|
return `<pre style="position: relative;">${copyHtml}<code class="hljs">${hljs.highlight(str, { language: lang, ignoreIllegals: true }).value}</code></pre>`;
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
return ``;
|
return ``;
|
||||||
|
|
|
||||||
|
|
@ -60,39 +60,14 @@ function isIfShow(action: ActionItem): boolean {
|
||||||
|
|
||||||
/** 处理按钮 actions */
|
/** 处理按钮 actions */
|
||||||
const getActions = computed(() => {
|
const getActions = computed(() => {
|
||||||
return (props.actions || [])
|
return (props.actions || []).filter((action: ActionItem) => isIfShow(action));
|
||||||
.filter((action: ActionItem) => isIfShow(action))
|
|
||||||
.map((action: ActionItem) => {
|
|
||||||
const { popConfirm } = action;
|
|
||||||
return {
|
|
||||||
type: action.type || 'link',
|
|
||||||
...action,
|
|
||||||
...popConfirm,
|
|
||||||
onConfirm: popConfirm?.confirm,
|
|
||||||
onCancel: popConfirm?.cancel,
|
|
||||||
enable: !!popConfirm,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 处理下拉菜单 actions */
|
/** 处理下拉菜单 actions */
|
||||||
const getDropdownList = computed(() => {
|
const getDropdownList = computed(() => {
|
||||||
return (props.dropDownActions || [])
|
return (props.dropDownActions || []).filter((action: ActionItem) =>
|
||||||
.filter((action: ActionItem) => isIfShow(action))
|
isIfShow(action),
|
||||||
.map((action: ActionItem, index: number) => {
|
);
|
||||||
const { label, popConfirm } = action;
|
|
||||||
const processedAction = { ...action };
|
|
||||||
delete processedAction.icon;
|
|
||||||
return {
|
|
||||||
...processedAction,
|
|
||||||
...popConfirm,
|
|
||||||
onConfirm: popConfirm?.confirm,
|
|
||||||
onCancel: popConfirm?.cancel,
|
|
||||||
text: label,
|
|
||||||
divider:
|
|
||||||
index < props.dropDownActions.length - 1 ? props.divider : false,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Space 组件的 size */
|
/** Space 组件的 size */
|
||||||
|
|
@ -103,18 +78,27 @@ const spaceSize = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
/** 获取 PopConfirm 属性 */
|
/** 获取 PopConfirm 属性 */
|
||||||
function getPopConfirmProps(attrs: PopConfirm) {
|
function getPopConfirmProps(popConfirm: PopConfirm) {
|
||||||
const originAttrs: any = { ...attrs };
|
if (!popConfirm) return {};
|
||||||
delete originAttrs.icon;
|
|
||||||
if (attrs.confirm && isFunction(attrs.confirm)) {
|
const attrs: Record<string, any> = {};
|
||||||
originAttrs.onConfirm = attrs.confirm;
|
|
||||||
delete originAttrs.confirm;
|
// 复制基本属性,排除函数
|
||||||
|
Object.keys(popConfirm).forEach((key) => {
|
||||||
|
if (key !== 'confirm' && key !== 'cancel' && key !== 'icon') {
|
||||||
|
attrs[key] = popConfirm[key as keyof PopConfirm];
|
||||||
}
|
}
|
||||||
if (attrs.cancel && isFunction(attrs.cancel)) {
|
});
|
||||||
originAttrs.onCancel = attrs.cancel;
|
|
||||||
delete originAttrs.cancel;
|
// 单独处理事件函数
|
||||||
|
if (popConfirm.confirm && isFunction(popConfirm.confirm)) {
|
||||||
|
attrs.onConfirm = popConfirm.confirm;
|
||||||
}
|
}
|
||||||
return originAttrs;
|
if (popConfirm.cancel && isFunction(popConfirm.cancel)) {
|
||||||
|
attrs.onCancel = popConfirm.cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取 Button 属性 */
|
/** 获取 Button 属性 */
|
||||||
|
|
@ -146,6 +130,13 @@ function handleMenuClick(e: any) {
|
||||||
function getActionKey(action: ActionItem, index: number) {
|
function getActionKey(action: ActionItem, index: number) {
|
||||||
return `${action.label || ''}-${action.type || ''}-${index}`;
|
return `${action.label || ''}-${action.type || ''}-${index}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 处理按钮点击 */
|
||||||
|
function handleButtonClick(action: ActionItem) {
|
||||||
|
if (action.onClick && isFunction(action.onClick)) {
|
||||||
|
action.onClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -172,7 +163,10 @@ function getActionKey(action: ActionItem, index: number) {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
<Tooltip v-else v-bind="getTooltipProps(action.tooltip)">
|
<Tooltip v-else v-bind="getTooltipProps(action.tooltip)">
|
||||||
<Button v-bind="getButtonProps(action)" @click="action.onClick">
|
<Button
|
||||||
|
v-bind="getButtonProps(action)"
|
||||||
|
@click="handleButtonClick(action)"
|
||||||
|
>
|
||||||
<template v-if="action.icon" #icon>
|
<template v-if="action.icon" #icon>
|
||||||
<IconifyIcon :icon="action.icon" />
|
<IconifyIcon :icon="action.icon" />
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -184,7 +178,7 @@ function getActionKey(action: ActionItem, index: number) {
|
||||||
|
|
||||||
<Dropdown v-if="getDropdownList.length > 0" :trigger="['hover']">
|
<Dropdown v-if="getDropdownList.length > 0" :trigger="['hover']">
|
||||||
<slot name="more">
|
<slot name="more">
|
||||||
<Button :type="getDropdownList[0]?.type">
|
<Button type="link">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
{{ $t('page.action.more') }}
|
{{ $t('page.action.more') }}
|
||||||
<IconifyIcon icon="lucide:ellipsis-vertical" />
|
<IconifyIcon icon="lucide:ellipsis-vertical" />
|
||||||
|
|
@ -213,7 +207,7 @@ function getActionKey(action: ActionItem, index: number) {
|
||||||
>
|
>
|
||||||
<IconifyIcon v-if="action.icon" :icon="action.icon" />
|
<IconifyIcon v-if="action.icon" :icon="action.icon" />
|
||||||
<span :class="action.icon ? 'ml-1' : ''">
|
<span :class="action.icon ? 'ml-1' : ''">
|
||||||
{{ action.text }}
|
{{ action.label }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
||||||
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkCaptcha,
|
checkCaptcha,
|
||||||
|
|
@ -124,12 +125,6 @@ async function handleVerifySuccess({ captchaVerification }: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** tricky: 配合 login.vue 中,redirectUri 需要对参数进行 encode,需要在回调后进行decode */
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 组件挂载时获取租户信息 */
|
/** 组件挂载时获取租户信息 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchTenantList();
|
await fetchTenantList();
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ async function handelUpload({
|
||||||
所属岗位
|
所属岗位
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
{{ profile.posts.map((post) => post.name).join(',') }}
|
{{ profile.posts && profile.posts.length > 0 ? profile.posts.map(post => post.name).join(',') : '-' }}
|
||||||
</DescriptionsItem>
|
</DescriptionsItem>
|
||||||
<DescriptionsItem>
|
<DescriptionsItem>
|
||||||
<template #label>
|
<template #label>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { computed, onMounted, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { confirm } from '@vben/common-ui';
|
import { confirm } from '@vben/common-ui';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Card, Image, message } from 'ant-design-vue';
|
import { Button, Card, Image, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
|
@ -149,13 +150,6 @@ async function bindSocial() {
|
||||||
window.history.replaceState({}, '', location.pathname);
|
window.history.replaceState({}, '', location.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @芋艿:后续搞到 util 里;
|
|
||||||
// 双层 encode 需要在回调后进行 decode
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
bindSocial();
|
bindSocial();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,12 @@ import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
import { z } from '#/adapter/form';
|
||||||
import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils';
|
import {
|
||||||
|
CommonStatusEnum,
|
||||||
|
DICT_TYPE,
|
||||||
|
getDictOptions,
|
||||||
|
getRangePickerDefaultProps,
|
||||||
|
} from '#/utils';
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
|
|
@ -97,7 +102,15 @@ export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// TODO 创建时间 等通用方法完善后加
|
{
|
||||||
|
fieldName: 'createTime',
|
||||||
|
label: '创建时间',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Recordable } from '@vben/types';
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
import type { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
import type { SystemRoleApi } from '#/api/system/role';
|
import type { SystemRoleApi } from '#/api/system/role';
|
||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
@ -21,7 +21,7 @@ import { useAssignMenuFormSchema } from '../data';
|
||||||
|
|
||||||
const emit = defineEmits(['success']);
|
const emit = defineEmits(['success']);
|
||||||
|
|
||||||
const menuTree = ref<SystemDeptApi.Dept[]>([]); // 菜单树
|
const menuTree = ref<SystemMenuApi.Menu[]>([]); // 菜单树
|
||||||
const menuLoading = ref(false); // 加载菜单列表
|
const menuLoading = ref(false); // 加载菜单列表
|
||||||
const isAllSelected = ref(false); // 全选状态
|
const isAllSelected = ref(false); // 全选状态
|
||||||
const isExpanded = ref(false); // 展开状态
|
const isExpanded = ref(false); // 展开状态
|
||||||
|
|
@ -90,7 +90,7 @@ async function loadMenuTree() {
|
||||||
menuLoading.value = true;
|
menuLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const data = await getMenuList();
|
const data = await getMenuList();
|
||||||
menuTree.value = handleTree(data) as SystemDeptApi.Dept[];
|
menuTree.value = handleTree(data) as SystemMenuApi.Menu[];
|
||||||
} finally {
|
} finally {
|
||||||
menuLoading.value = false;
|
menuLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { SystemDeptApi } from '#/api/system/dept';
|
import type { SystemMenuApi } from '#/api/system/menu';
|
||||||
import type { SystemTenantPackageApi } from '#/api/system/tenant-package';
|
import type { SystemTenantPackageApi } from '#/api/system/tenant-package';
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
|
@ -27,7 +27,7 @@ const getTitle = computed(() => {
|
||||||
? $t('ui.actionTitle.edit', ['套餐'])
|
? $t('ui.actionTitle.edit', ['套餐'])
|
||||||
: $t('ui.actionTitle.create', ['套餐']);
|
: $t('ui.actionTitle.create', ['套餐']);
|
||||||
});
|
});
|
||||||
const menuTree = ref<SystemDeptApi.Dept[]>([]); // 菜单树
|
const menuTree = ref<SystemMenuApi.Menu[]>([]); // 菜单树
|
||||||
const menuLoading = ref(false); // 加载菜单列表
|
const menuLoading = ref(false); // 加载菜单列表
|
||||||
const isAllSelected = ref(false); // 全选状态
|
const isAllSelected = ref(false); // 全选状态
|
||||||
const isExpanded = ref(false); // 展开状态
|
const isExpanded = ref(false); // 展开状态
|
||||||
|
|
@ -95,7 +95,7 @@ async function loadMenuTree() {
|
||||||
menuLoading.value = true;
|
menuLoading.value = true;
|
||||||
try {
|
try {
|
||||||
const data = await getMenuList();
|
const data = await getMenuList();
|
||||||
menuTree.value = handleTree(data) as SystemDeptApi.Dept[];
|
menuTree.value = handleTree(data) as SystemMenuApi.Menu[];
|
||||||
} finally {
|
} finally {
|
||||||
menuLoading.value = false;
|
menuLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,6 @@ function getAllNodeIds(nodes: any[], ids: number[] = []): number[] {
|
||||||
<Modal :title="getTitle" class="w-2/5">
|
<Modal :title="getTitle" class="w-2/5">
|
||||||
<Form class="mx-6">
|
<Form class="mx-6">
|
||||||
<template #menuIds="slotProps">
|
<template #menuIds="slotProps">
|
||||||
<!-- TODO @芋艿:可优化,使用 antd 的 tree?原因是,更原生 -->
|
|
||||||
<VbenTree
|
<VbenTree
|
||||||
class="max-h-96 overflow-y-auto"
|
class="max-h-96 overflow-y-auto"
|
||||||
:loading="menuLoading"
|
:loading="menuLoading"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
||||||
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkCaptcha,
|
checkCaptcha,
|
||||||
|
|
@ -124,12 +125,6 @@ async function handleVerifySuccess({ captchaVerification }: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** tricky: 配合 login.vue 中,redirectUri 需要对参数进行 encode,需要在回调后进行decode */
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 组件挂载时获取租户信息 */
|
/** 组件挂载时获取租户信息 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchTenantList();
|
await fetchTenantList();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { computed, onMounted, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { confirm } from '@vben/common-ui';
|
import { confirm } from '@vben/common-ui';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import { ElButton, ElCard, ElImage, ElMessage } from 'element-plus';
|
import { ElButton, ElCard, ElImage, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
|
@ -149,13 +150,6 @@ async function bindSocial() {
|
||||||
window.history.replaceState({}, '', location.pathname);
|
window.history.replaceState({}, '', location.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @芋艿:后续搞到 util 里;
|
|
||||||
// 双层 encode 需要在回调后进行 decode
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
bindSocial();
|
bindSocial();
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { AuthenticationLogin, Verification, z } from '@vben/common-ui';
|
||||||
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
import { isCaptchaEnable, isTenantEnable } from '@vben/hooks';
|
||||||
import { $t } from '@vben/locales';
|
import { $t } from '@vben/locales';
|
||||||
import { useAccessStore } from '@vben/stores';
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkCaptcha,
|
checkCaptcha,
|
||||||
|
|
@ -124,12 +125,6 @@ async function handleVerifySuccess({ captchaVerification }: any) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** tricky: 配合 login.vue 中,redirectUri 需要对参数进行 encode,需要在回调后进行decode */
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 组件挂载时获取租户信息 */
|
/** 组件挂载时获取租户信息 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await fetchTenantList();
|
await fetchTenantList();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { computed, onMounted, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { confirm } from '@vben/common-ui';
|
import { confirm } from '@vben/common-ui';
|
||||||
|
import { getUrlValue } from '@vben/utils';
|
||||||
|
|
||||||
import { NButton, NCard, NImage } from 'naive-ui';
|
import { NButton, NCard, NImage } from 'naive-ui';
|
||||||
|
|
||||||
|
|
@ -150,13 +151,6 @@ async function bindSocial() {
|
||||||
window.history.replaceState({}, '', location.pathname);
|
window.history.replaceState({}, '', location.pathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @芋艿:后续搞到 util 里;
|
|
||||||
// 双层 encode 需要在回调后进行 decode
|
|
||||||
function getUrlValue(key: string): string {
|
|
||||||
const url = new URL(decodeURIComponent(location.href));
|
|
||||||
return url.searchParams.get(key) ?? '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
bindSocial();
|
bindSocial();
|
||||||
|
|
@ -201,7 +195,7 @@ onMounted(() => {
|
||||||
<NButton
|
<NButton
|
||||||
:disabled="!!item.socialUser"
|
:disabled="!!item.socialUser"
|
||||||
size="small"
|
size="small"
|
||||||
type="link"
|
text
|
||||||
@click="onBind(item)"
|
@click="onBind(item)"
|
||||||
>
|
>
|
||||||
{{ item.socialUser ? '已绑定' : '绑定' }}
|
{{ item.socialUser ? '已绑定' : '绑定' }}
|
||||||
|
|
|
||||||
|
|
@ -42,3 +42,13 @@ export function getNestedValue<T>(obj: T, path: string): any {
|
||||||
|
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 URL 参数值
|
||||||
|
* @param key - 参数键
|
||||||
|
* @returns 参数值,或者未找到时返回空字符串
|
||||||
|
*/
|
||||||
|
export function getUrlValue(key: string): string {
|
||||||
|
const url = new URL(decodeURIComponent(location.href));
|
||||||
|
return url.searchParams.get(key) ?? '';
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue