feat
This commit is contained in:
@@ -187,7 +187,7 @@ const densityList = [
|
||||
|
||||
// 计算需要插槽的列(只在 columns 变化时重新计算)
|
||||
const slotColumns = computed(() => {
|
||||
return props.columns.filter(col => col.slotName)
|
||||
return props.columns.filter((col) => col.slotName)
|
||||
})
|
||||
|
||||
const onPageChange = (current: number) => {
|
||||
@@ -259,7 +259,7 @@ const popupVisibleChange = (val: boolean) => {
|
||||
|
||||
// 初始化列配置
|
||||
const initColumns = () => {
|
||||
const cols = props.columns.map(item => ({
|
||||
const cols = props.columns.map((item) => ({
|
||||
...item,
|
||||
checked: true,
|
||||
}))
|
||||
|
||||
@@ -6,13 +6,7 @@ import { listenerRouteChange } from '@/utils/route-listener'
|
||||
import { compile, computed, defineComponent, h, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { RouteMeta } from 'vue-router'
|
||||
import {
|
||||
isNavigationFailure,
|
||||
NavigationFailureType,
|
||||
RouteRecordRaw,
|
||||
useRoute,
|
||||
useRouter,
|
||||
} from 'vue-router'
|
||||
import { isNavigationFailure, NavigationFailureType, RouteRecordRaw, useRoute, useRouter } from 'vue-router'
|
||||
import useMenuTree from './use-menu-tree'
|
||||
import { COMMON_ICONS } from '@/views/ops/pages/system-settings/menu-management/menuIcons'
|
||||
|
||||
@@ -107,7 +101,7 @@ export default defineComponent({
|
||||
// 获取图标组件 - 支持 Arco Design 图标和 @tabler/icons-vue
|
||||
const getIconComponent = (iconName: string) => {
|
||||
if (!iconName) return null
|
||||
|
||||
|
||||
// 检查是否是 Tabler 图标(不以 'icon-' 开头)
|
||||
if (!iconName.startsWith('icon-')) {
|
||||
const IconComponent = COMMON_ICONS[iconName]
|
||||
@@ -115,7 +109,7 @@ export default defineComponent({
|
||||
return () => h(IconComponent, { size: 18 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 回退到 Arco Design 图标
|
||||
return () => h(compile(`<${iconName}/>`))
|
||||
}
|
||||
|
||||
@@ -201,7 +201,6 @@ const setDropDownVisible = () => {
|
||||
triggerBtn.value.dispatchEvent(event)
|
||||
}
|
||||
const toggleDrawerMenu = inject('toggleDrawerMenu') as () => void
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
@@ -11,107 +11,102 @@
|
||||
>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<a-form-item :label="'新密码'" field="newPassword" :required="true">
|
||||
<a-input-password
|
||||
v-model="form.newPassword"
|
||||
:placeholder="'请输入新密码'"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input-password v-model="form.newPassword" :placeholder="'请输入新密码'" allow-clear />
|
||||
</a-form-item>
|
||||
|
||||
|
||||
<a-form-item :label="'确认密码'" field="confirmPassword" :required="true">
|
||||
<a-input-password
|
||||
v-model="form.confirmPassword"
|
||||
:placeholder="'请再次输入新密码'"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input-password v-model="form.confirmPassword" :placeholder="'请再次输入新密码'" allow-clear />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { resetUserPassword } from '@/api/module/user';
|
||||
import SafeStorage, { AppStorageKey } from '@/utils/safeStorage';
|
||||
import { ref, watch } from 'vue'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { resetUserPassword } from '@/api/module/user'
|
||||
import SafeStorage, { AppStorageKey } from '@/utils/safeStorage'
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
open: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:open', value: boolean): void;
|
||||
}>();
|
||||
(e: 'update:open', value: boolean): void
|
||||
}>()
|
||||
|
||||
const loading = ref(false);
|
||||
const visible = ref(props.open);
|
||||
const loading = ref(false)
|
||||
const visible = ref(props.open)
|
||||
|
||||
const form = ref({
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
});
|
||||
confirmPassword: '',
|
||||
})
|
||||
|
||||
// 监听 props.open 变化
|
||||
watch(() => props.open, (val) => {
|
||||
visible.value = val;
|
||||
});
|
||||
watch(
|
||||
() => props.open,
|
||||
(val) => {
|
||||
visible.value = val
|
||||
}
|
||||
)
|
||||
|
||||
// 监听 visible 变化,同步到父组件
|
||||
watch(visible, (val) => {
|
||||
emit('update:open', val);
|
||||
});
|
||||
emit('update:open', val)
|
||||
})
|
||||
|
||||
// 保存密码
|
||||
const handleSavePassword = async () => {
|
||||
// 表单验证
|
||||
if (!form.value.newPassword || !form.value.confirmPassword) {
|
||||
Message.error('请填写新密码和确认密码');
|
||||
return;
|
||||
Message.error('请填写新密码和确认密码')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (form.value.newPassword.length < 6) {
|
||||
Message.error('密码至少需要6个字符');
|
||||
return;
|
||||
Message.error('密码至少需要6个字符')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if (form.value.newPassword !== form.value.confirmPassword) {
|
||||
Message.error('两次输入的密码不一致');
|
||||
return;
|
||||
Message.error('两次输入的密码不一致')
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
// 从 SafeStorage 获取登录用户信息
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {};
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {}
|
||||
const res = await resetUserPassword({
|
||||
account: userInfo.account || '',
|
||||
code: '123456', // 暂时没校验,随便传
|
||||
password: form.value.newPassword,
|
||||
phone: userInfo.phone || '13800138000' // 暂时没校验,随便传
|
||||
});
|
||||
|
||||
phone: userInfo.phone || '13800138000', // 暂时没校验,随便传
|
||||
})
|
||||
|
||||
if (res.code === 0) {
|
||||
Message.success('密码修改成功');
|
||||
handleClose();
|
||||
Message.success('密码修改成功')
|
||||
handleClose()
|
||||
} else {
|
||||
Message.error(res.message || '密码修改失败');
|
||||
Message.error(res.message || '密码修改失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('修改密码失败:', error);
|
||||
Message.error('密码修改失败,请稍后重试');
|
||||
console.error('修改密码失败:', error)
|
||||
Message.error('密码修改失败,请稍后重试')
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
form.value = {
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
};
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
||||
confirmPassword: '',
|
||||
}
|
||||
visible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -11,111 +11,102 @@
|
||||
>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<a-form-item :label="'账号'" field="account">
|
||||
<a-input
|
||||
v-model="form.account"
|
||||
:placeholder="'账号'"
|
||||
disabled
|
||||
/>
|
||||
<a-input v-model="form.account" :placeholder="'账号'" disabled />
|
||||
</a-form-item>
|
||||
|
||||
|
||||
<a-form-item :label="'姓名'" field="name">
|
||||
<a-input
|
||||
v-model="form.name"
|
||||
:placeholder="'请输入姓名'"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input v-model="form.name" :placeholder="'请输入姓名'" allow-clear />
|
||||
</a-form-item>
|
||||
|
||||
|
||||
<a-form-item :label="'邮箱'" field="email">
|
||||
<a-input
|
||||
v-model="form.email"
|
||||
:placeholder="'请输入邮箱'"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input v-model="form.email" :placeholder="'请输入邮箱'" allow-clear />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { modifyUser } from '@/api/module/user';
|
||||
import SafeStorage, { AppStorageKey } from '@/utils/safeStorage';
|
||||
import { ref, watch } from 'vue'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import { modifyUser } from '@/api/module/user'
|
||||
import SafeStorage, { AppStorageKey } from '@/utils/safeStorage'
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
open: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:open', value: boolean): void;
|
||||
}>();
|
||||
(e: 'update:open', value: boolean): void
|
||||
}>()
|
||||
|
||||
const loading = ref(false);
|
||||
const visible = ref(props.open);
|
||||
const loading = ref(false)
|
||||
const visible = ref(props.open)
|
||||
|
||||
const form = ref({
|
||||
account: '',
|
||||
name: '',
|
||||
email: ''
|
||||
});
|
||||
email: '',
|
||||
})
|
||||
|
||||
// 监听 props.open 变化
|
||||
watch(() => props.open, (val) => {
|
||||
visible.value = val;
|
||||
if (val) {
|
||||
// 打开时从存储中获取用户信息
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {};
|
||||
form.value = {
|
||||
account: userInfo.account || '',
|
||||
name: userInfo.name || '',
|
||||
email: userInfo.email || ''
|
||||
};
|
||||
watch(
|
||||
() => props.open,
|
||||
(val) => {
|
||||
visible.value = val
|
||||
if (val) {
|
||||
// 打开时从存储中获取用户信息
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {}
|
||||
form.value = {
|
||||
account: userInfo.account || '',
|
||||
name: userInfo.name || '',
|
||||
email: userInfo.email || '',
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
)
|
||||
|
||||
// 监听 visible 变化,同步到父组件
|
||||
watch(visible, (val) => {
|
||||
emit('update:open', val);
|
||||
});
|
||||
emit('update:open', val)
|
||||
})
|
||||
|
||||
// 保存个人资料
|
||||
const handleSaveProfile = async () => {
|
||||
loading.value = true;
|
||||
|
||||
loading.value = true
|
||||
|
||||
try {
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {};
|
||||
const userInfo = SafeStorage.get(AppStorageKey.USER_INFO) || {}
|
||||
const updatedUserInfo = {
|
||||
...userInfo,
|
||||
...form.value,
|
||||
id: userInfo.user_id
|
||||
};
|
||||
|
||||
const res = await modifyUser(updatedUserInfo);
|
||||
|
||||
id: userInfo.user_id,
|
||||
}
|
||||
|
||||
const res = await modifyUser(updatedUserInfo)
|
||||
|
||||
if (res.code === 0) {
|
||||
Message.success('个人资料修改成功');
|
||||
SafeStorage.set(AppStorageKey.USER_INFO, updatedUserInfo);
|
||||
handleClose();
|
||||
Message.success('个人资料修改成功')
|
||||
SafeStorage.set(AppStorageKey.USER_INFO, updatedUserInfo)
|
||||
handleClose()
|
||||
} else {
|
||||
Message.error(res.message || '个人资料修改失败');
|
||||
Message.error(res.message || '个人资料修改失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('个人资料修改失败:', error);
|
||||
Message.error('个人资料修改失败,请稍后重试');
|
||||
console.error('个人资料修改失败:', error)
|
||||
Message.error('个人资料修改失败,请稍后重试')
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
form.value = {
|
||||
account: '',
|
||||
name: '',
|
||||
email: ''
|
||||
};
|
||||
visible.value = false;
|
||||
};
|
||||
</script>
|
||||
email: '',
|
||||
}
|
||||
visible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,22 +1,12 @@
|
||||
<template>
|
||||
<a-row>
|
||||
<a-col :flex="1">
|
||||
<a-form
|
||||
:model="localModel"
|
||||
:label-col-props="{ span: 6 }"
|
||||
:wrapper-col-props="{ span: 18 }"
|
||||
label-align="left"
|
||||
>
|
||||
<a-form :model="localModel" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }" label-align="left">
|
||||
<a-row :gutter="16">
|
||||
<a-col v-for="item in formItems" :key="item.field" :span="item.span || 8">
|
||||
<a-form-item :field="item.field" :label="item.label">
|
||||
<!-- 输入框 -->
|
||||
<a-input
|
||||
v-if="item.type === 'input'"
|
||||
v-model="localModel[item.field]"
|
||||
:placeholder="item.placeholder"
|
||||
allow-clear
|
||||
/>
|
||||
<a-input v-if="item.type === 'input'" v-model="localModel[item.field]" :placeholder="item.placeholder" allow-clear />
|
||||
<!-- 选择框 -->
|
||||
<a-select
|
||||
v-else-if="item.type === 'select'"
|
||||
@@ -29,11 +19,7 @@
|
||||
allow-clear
|
||||
/>
|
||||
<!-- 日期范围选择器 -->
|
||||
<a-range-picker
|
||||
v-else-if="item.type === 'dateRange'"
|
||||
v-model="localModel[item.field]"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<a-range-picker v-else-if="item.type === 'dateRange'" v-model="localModel[item.field]" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 自定义表单项插槽 -->
|
||||
@@ -100,7 +86,7 @@ const isUpdating = ref(false)
|
||||
|
||||
// 初始化本地模型
|
||||
const initLocalModel = () => {
|
||||
Object.keys(localModel).forEach(key => delete localModel[key])
|
||||
Object.keys(localModel).forEach((key) => delete localModel[key])
|
||||
Object.assign(localModel, props.modelValue)
|
||||
}
|
||||
|
||||
@@ -109,7 +95,7 @@ watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
if (isUpdating.value) return
|
||||
Object.keys(localModel).forEach(key => delete localModel[key])
|
||||
Object.keys(localModel).forEach((key) => delete localModel[key])
|
||||
Object.assign(localModel, val)
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
@@ -148,5 +134,4 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
</style>
|
||||
<style scoped lang="less"></style>
|
||||
|
||||
@@ -186,10 +186,9 @@ const emit = defineEmits<{
|
||||
(e: 'column-change', columns: TableColumnData[]): void
|
||||
}>()
|
||||
|
||||
|
||||
// 计算需要插槽的列(动态插槽透传)
|
||||
const slotColumns = computed(() => {
|
||||
return props.columns.filter(col => col.slotName)
|
||||
return props.columns.filter((col) => col.slotName)
|
||||
})
|
||||
|
||||
const handleFormModelUpdate = (value: Record<string, any>) => {
|
||||
|
||||
Reference in New Issue
Block a user