From 58db52cea8dc3c5cb547f3234b8b9e05a175969e Mon Sep 17 00:00:00 2001 From: xingyuv <xingyu4j@vip.qq.com> Date: Sat, 18 Mar 2023 21:47:59 +0800 Subject: [PATCH] feat(view): base view init --- src/views/{sys => base}/about/index.vue | 0 .../{sys => base}/exception/Exception.vue | 0 src/views/{sys => base}/exception/index.ts | 0 src/views/{sys => base}/iframe/FrameBlank.vue | 0 src/views/{sys => base}/iframe/index.vue | 0 src/views/{sys => base}/lock/LockPage.vue | 0 src/views/{sys => base}/lock/index.vue | 0 src/views/{sys => base}/lock/useNow.ts | 0 .../login/ForgetPasswordForm.vue | 0 src/views/{sys => base}/login/Login.vue | 0 src/views/{sys => base}/login/LoginForm.vue | 0 .../{sys => base}/login/LoginFormTitle.vue | 0 src/views/{sys => base}/login/MobileForm.vue | 0 src/views/{sys => base}/login/QrCodeForm.vue | 0 .../{sys => base}/login/RegisterForm.vue | 0 .../login/SessionTimeoutLogin.vue | 0 src/views/{sys => base}/login/useLogin.ts | 0 src/views/base/profile/AccountBind.vue | 64 ++++++ src/views/base/profile/BaseSetting.vue | 80 ++++++++ src/views/base/profile/MsgNotify.vue | 34 ++++ src/views/base/profile/PasswordModel.vue | 43 ++++ src/views/base/profile/SecureSetting.vue | 55 +++++ src/views/base/profile/data.ts | 189 ++++++++++++++++++ src/views/base/profile/index.vue | 40 ++++ src/views/{sys => base}/redirect/index.vue | 0 .../workbench/components/WorkbenchHeader.vue | 4 +- src/views/sys/error-log/DetailModal.vue | 26 --- src/views/sys/error-log/data.tsx | 67 ------- src/views/sys/error-log/index.vue | 97 --------- 29 files changed, 507 insertions(+), 192 deletions(-) rename src/views/{sys => base}/about/index.vue (100%) rename src/views/{sys => base}/exception/Exception.vue (100%) rename src/views/{sys => base}/exception/index.ts (100%) rename src/views/{sys => base}/iframe/FrameBlank.vue (100%) rename src/views/{sys => base}/iframe/index.vue (100%) rename src/views/{sys => base}/lock/LockPage.vue (100%) rename src/views/{sys => base}/lock/index.vue (100%) rename src/views/{sys => base}/lock/useNow.ts (100%) rename src/views/{sys => base}/login/ForgetPasswordForm.vue (100%) rename src/views/{sys => base}/login/Login.vue (100%) rename src/views/{sys => base}/login/LoginForm.vue (100%) rename src/views/{sys => base}/login/LoginFormTitle.vue (100%) rename src/views/{sys => base}/login/MobileForm.vue (100%) rename src/views/{sys => base}/login/QrCodeForm.vue (100%) rename src/views/{sys => base}/login/RegisterForm.vue (100%) rename src/views/{sys => base}/login/SessionTimeoutLogin.vue (100%) rename src/views/{sys => base}/login/useLogin.ts (100%) create mode 100644 src/views/base/profile/AccountBind.vue create mode 100644 src/views/base/profile/BaseSetting.vue create mode 100644 src/views/base/profile/MsgNotify.vue create mode 100644 src/views/base/profile/PasswordModel.vue create mode 100644 src/views/base/profile/SecureSetting.vue create mode 100644 src/views/base/profile/data.ts create mode 100644 src/views/base/profile/index.vue rename src/views/{sys => base}/redirect/index.vue (100%) delete mode 100644 src/views/sys/error-log/DetailModal.vue delete mode 100644 src/views/sys/error-log/data.tsx delete mode 100644 src/views/sys/error-log/index.vue diff --git a/src/views/sys/about/index.vue b/src/views/base/about/index.vue similarity index 100% rename from src/views/sys/about/index.vue rename to src/views/base/about/index.vue diff --git a/src/views/sys/exception/Exception.vue b/src/views/base/exception/Exception.vue similarity index 100% rename from src/views/sys/exception/Exception.vue rename to src/views/base/exception/Exception.vue diff --git a/src/views/sys/exception/index.ts b/src/views/base/exception/index.ts similarity index 100% rename from src/views/sys/exception/index.ts rename to src/views/base/exception/index.ts diff --git a/src/views/sys/iframe/FrameBlank.vue b/src/views/base/iframe/FrameBlank.vue similarity index 100% rename from src/views/sys/iframe/FrameBlank.vue rename to src/views/base/iframe/FrameBlank.vue diff --git a/src/views/sys/iframe/index.vue b/src/views/base/iframe/index.vue similarity index 100% rename from src/views/sys/iframe/index.vue rename to src/views/base/iframe/index.vue diff --git a/src/views/sys/lock/LockPage.vue b/src/views/base/lock/LockPage.vue similarity index 100% rename from src/views/sys/lock/LockPage.vue rename to src/views/base/lock/LockPage.vue diff --git a/src/views/sys/lock/index.vue b/src/views/base/lock/index.vue similarity index 100% rename from src/views/sys/lock/index.vue rename to src/views/base/lock/index.vue diff --git a/src/views/sys/lock/useNow.ts b/src/views/base/lock/useNow.ts similarity index 100% rename from src/views/sys/lock/useNow.ts rename to src/views/base/lock/useNow.ts diff --git a/src/views/sys/login/ForgetPasswordForm.vue b/src/views/base/login/ForgetPasswordForm.vue similarity index 100% rename from src/views/sys/login/ForgetPasswordForm.vue rename to src/views/base/login/ForgetPasswordForm.vue diff --git a/src/views/sys/login/Login.vue b/src/views/base/login/Login.vue similarity index 100% rename from src/views/sys/login/Login.vue rename to src/views/base/login/Login.vue diff --git a/src/views/sys/login/LoginForm.vue b/src/views/base/login/LoginForm.vue similarity index 100% rename from src/views/sys/login/LoginForm.vue rename to src/views/base/login/LoginForm.vue diff --git a/src/views/sys/login/LoginFormTitle.vue b/src/views/base/login/LoginFormTitle.vue similarity index 100% rename from src/views/sys/login/LoginFormTitle.vue rename to src/views/base/login/LoginFormTitle.vue diff --git a/src/views/sys/login/MobileForm.vue b/src/views/base/login/MobileForm.vue similarity index 100% rename from src/views/sys/login/MobileForm.vue rename to src/views/base/login/MobileForm.vue diff --git a/src/views/sys/login/QrCodeForm.vue b/src/views/base/login/QrCodeForm.vue similarity index 100% rename from src/views/sys/login/QrCodeForm.vue rename to src/views/base/login/QrCodeForm.vue diff --git a/src/views/sys/login/RegisterForm.vue b/src/views/base/login/RegisterForm.vue similarity index 100% rename from src/views/sys/login/RegisterForm.vue rename to src/views/base/login/RegisterForm.vue diff --git a/src/views/sys/login/SessionTimeoutLogin.vue b/src/views/base/login/SessionTimeoutLogin.vue similarity index 100% rename from src/views/sys/login/SessionTimeoutLogin.vue rename to src/views/base/login/SessionTimeoutLogin.vue diff --git a/src/views/sys/login/useLogin.ts b/src/views/base/login/useLogin.ts similarity index 100% rename from src/views/sys/login/useLogin.ts rename to src/views/base/login/useLogin.ts diff --git a/src/views/base/profile/AccountBind.vue b/src/views/base/profile/AccountBind.vue new file mode 100644 index 0000000..e0cdf78 --- /dev/null +++ b/src/views/base/profile/AccountBind.vue @@ -0,0 +1,64 @@ +<template> + <CollapseContainer title="账号绑定" :canExpan="false"> + <List> + <template v-for="item in accountBindList" :key="item.key"> + <ListItem> + <ListItemMeta> + <template #avatar> + <Icon v-if="item.avatar" class="avatar" :icon="item.avatar" :color="item.color" /> + </template> + <template #title> + {{ item.title }} + <a-button type="link" size="small" v-if="item.extra" class="extra"> + {{ item.extra }} + </a-button> + </template> + <template #description> + <div>{{ item.description }}</div> + </template> + </ListItemMeta> + </ListItem> + </template> + </List> + </CollapseContainer> +</template> +<script setup lang="ts"> +import { List } from 'ant-design-vue' +import { CollapseContainer } from '@/components/Container/index' +import { accountBindList } from './data' +import { getUserProfileApi } from '@/api/base/profile' +import { onMounted } from 'vue' + +const ListItem = List.Item +const ListItemMeta = List.Item.Meta + +async function init() { + const userInfo = await getUserProfileApi() + // TODO + for (const i in accountBindList) { + if (userInfo.socialUsers) { + for (const j in userInfo.socialUsers) { + if (accountBindList[i].key === userInfo.socialUsers[j].type) { + accountBindList[i].title = '已綁定' + break + } + } + } + } +} +onMounted(async () => { + await init() +}) +</script> +<style lang="less" scoped> +.avatar { + font-size: 40px !important; +} + +.extra { + float: right; + margin-top: 10px; + margin-right: 30px; + cursor: pointer; +} +</style> diff --git a/src/views/base/profile/BaseSetting.vue b/src/views/base/profile/BaseSetting.vue new file mode 100644 index 0000000..e08a128 --- /dev/null +++ b/src/views/base/profile/BaseSetting.vue @@ -0,0 +1,80 @@ +<template> + <CollapseContainer title="基本设置" :canExpan="false"> + <Row :gutter="24"> + <Col :span="14"> + <BasicForm @register="register" /> + </Col> + <Col :span="10"> + <div class="change-avatar"> + <div class="mb-2">头像</div> + <CropperAvatar + :value="avatar" + btnText="更换头像" + :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" + @change="updateAvatar" + width="150" + /> + </div> + </Col> + </Row> + <Button type="primary" @click="handleSubmit"> 更新基本信息 </Button> + </CollapseContainer> +</template> +<script setup lang="ts"> +import { Button, Row, Col } from 'ant-design-vue' +import { computed, onMounted } from 'vue' +import { BasicForm, useForm } from '@/components/Form/index' +import { CollapseContainer } from '@/components/Container' +import { CropperAvatar } from '@/components/Cropper' +import { useMessage } from '@/hooks/web/useMessage' +import headerImg from '@/assets/images/header.jpg' +import { baseSetschemas } from './data' +import { useUserStore } from '@/store/modules/user' +import { getUserProfileApi, updateUserProfileApi, uploadAvatarApi } from '@/api/base/profile' + +const { createMessage } = useMessage() +const userStore = useUserStore() + +const [register, { setFieldsValue, validate }] = useForm({ + labelWidth: 120, + schemas: baseSetschemas, + showActionButtonGroup: false +}) + +onMounted(async () => { + const data = await getUserProfileApi() + setFieldsValue(data) +}) + +const avatar = computed(() => { + const { avatar } = userStore.getUserInfo.user + return avatar || headerImg +}) + +async function updateAvatar({ src, data }) { + await uploadAvatarApi({ avatarFile: data }) + const userinfo = userStore.getUserInfo + userinfo.user.avatar = src + userStore.setUserInfo(userinfo) + console.log('data', data) +} + +async function handleSubmit() { + try { + const values = await validate() + await updateUserProfileApi(values) + } finally { + createMessage.success('更新成功!') + } +} +</script> + +<style lang="less" scoped> +.change-avatar { + img { + display: block; + margin-bottom: 15px; + border-radius: 50%; + } +} +</style> diff --git a/src/views/base/profile/MsgNotify.vue b/src/views/base/profile/MsgNotify.vue new file mode 100644 index 0000000..8979a13 --- /dev/null +++ b/src/views/base/profile/MsgNotify.vue @@ -0,0 +1,34 @@ +<template> + <CollapseContainer title="新消息通知" :canExpan="false"> + <List> + <template v-for="item in msgNotifyList" :key="item.key"> + <ListItem> + <ListItemMeta> + <template #title> + {{ item.title }} + <Switch class="extra" checked-children="开" un-checked-children="关" default-checked /> + </template> + <template #description> + <div>{{ item.description }}</div> + </template> + </ListItemMeta> + </ListItem> + </template> + </List> + </CollapseContainer> +</template> +<script setup lang="ts"> +import { List, Switch } from 'ant-design-vue' +import { CollapseContainer } from '@/components/Container/index' +import { msgNotifyList } from './data' + +const ListItem = List.Item +const ListItemMeta = List.Item.Meta +</script> +<style lang="less" scoped> +.extra { + float: right; + margin-top: 10px; + margin-right: 30px; +} +</style> diff --git a/src/views/base/profile/PasswordModel.vue b/src/views/base/profile/PasswordModel.vue new file mode 100644 index 0000000..1ff14ea --- /dev/null +++ b/src/views/base/profile/PasswordModel.vue @@ -0,0 +1,43 @@ +<template> + <BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit"> + <BasicForm @register="registerForm" /> + </BasicModal> +</template> +<script lang="ts" setup name="PasswordModel"> +import { ref } from 'vue' +import { BasicModal, useModalInner } from '@/components/Modal' +import { BasicForm, useForm } from '@/components/Form' +import { passwordSchema } from './data' +import { updateUserPwdApi } from '@/api/base/profile' + +const emit = defineEmits(['success', 'register']) + +const title = ref('修改密码') + +const [registerForm, { resetFields, validate }] = useForm({ + labelWidth: 100, + baseColProps: { span: 24 }, + schemas: passwordSchema, + showActionButtonGroup: false, + actionColOptions: { + span: 23 + } +}) + +const [registerModal, { setModalProps, closeModal }] = useModalInner(() => { + resetFields() + setModalProps({ confirmLoading: false }) +}) + +async function handleSubmit() { + try { + const values = await validate() + await updateUserPwdApi(values.oldPassword, values.newPassword) + setModalProps({ confirmLoading: true }) + closeModal() + emit('success') + } finally { + setModalProps({ confirmLoading: false }) + } +} +</script> diff --git a/src/views/base/profile/SecureSetting.vue b/src/views/base/profile/SecureSetting.vue new file mode 100644 index 0000000..74c4a78 --- /dev/null +++ b/src/views/base/profile/SecureSetting.vue @@ -0,0 +1,55 @@ +<template> + <CollapseContainer title="安全设置" :canExpan="false"> + <List> + <template v-for="item in secureSettingList" :key="item.key"> + <ListItem> + <ListItemMeta> + <template #title> + {{ item.title }} + <div class="extra" v-if="item.extra"> + <a-button type="link" @click="handleEdit(item.title)">{{ item.extra }}</a-button> + </div> + </template> + <template #description> + <div>{{ item.description }}</div> + </template> + </ListItemMeta> + </ListItem> + </template> + </List> + </CollapseContainer> + <PasswordModel @register="registerModal" @success="handleSuccess" /> +</template> +<script setup lang="ts"> +import { List } from 'ant-design-vue' +import { CollapseContainer } from '@/components/Container/index' +import { secureSettingList } from './data' +import { useModal } from '@/components/Modal' +import { useMessage } from '@/hooks/web/useMessage' +import PasswordModel from './PasswordModel.vue' + +const ListItem = List.Item +const ListItemMeta = List.Item.Meta + +const { createMessage } = useMessage() +const [registerModal, { openModal }] = useModal() + +function handleEdit(title: string) { + if (title == '账户密码') { + openModal(true, {}) + } +} +function handleSuccess() { + createMessage.success('更新成功!') +} +</script> +<style lang="less" scoped> +.extra { + float: right; + margin-top: 10px; + margin-right: 30px; + font-weight: normal; + color: #1890ff; + cursor: pointer; +} +</style> diff --git a/src/views/base/profile/data.ts b/src/views/base/profile/data.ts new file mode 100644 index 0000000..406d84e --- /dev/null +++ b/src/views/base/profile/data.ts @@ -0,0 +1,189 @@ +import { FormSchema } from '@/components/Form/index' +import { useI18n } from '@/hooks/web/useI18n' + +const { t } = useI18n() + +export interface ListItem { + key: string + title: string + description: string + extra?: string + avatar?: string + color?: string +} + +// tab的list +export const settingList = [ + { + key: '1', + name: '基本设置', + component: 'BaseSetting' + }, + { + key: '2', + name: '安全设置', + component: 'SecureSetting' + }, + { + key: '3', + name: '账号绑定', + component: 'AccountBind' + }, + { + key: '4', + name: '新消息通知', + component: 'MsgNotify' + } +] + +// 基础设置 form +export const baseSetschemas: FormSchema[] = [ + { + field: 'nickname', + component: 'Input', + label: t('profile.user.nickname'), + colProps: { span: 18 } + }, + { + field: 'mobile', + component: 'Input', + label: t('profile.user.mobile'), + colProps: { span: 18 } + }, + { + field: 'email', + component: 'Input', + label: t('profile.user.email'), + colProps: { span: 18 } + }, + { + field: 'sex', + component: 'RadioGroup', + componentProps: { + options: [ + { label: '男', value: 1 }, + { label: '女', value: 2 } + ] + }, + label: t('profile.user.sex'), + colProps: { span: 18 } + } +] + +// 安全设置 list +export const secureSettingList: ListItem[] = [ + { + key: '1', + title: '账户密码', + description: '当前密码强度::强', + extra: '修改' + }, + { + key: '2', + title: '密保手机', + description: '已绑定手机::138****8293', + extra: '修改' + }, + { + key: '3', + title: '密保问题', + description: '未设置密保问题,密保问题可有效保护账户安全', + extra: '修改' + }, + { + key: '4', + title: '备用邮箱', + description: '已绑定邮箱::ant***sign.com', + extra: '修改' + }, + { + key: '5', + title: 'MFA 设备', + description: '未绑定 MFA 设备,绑定后,可以进行二次确认', + extra: '修改' + } +] + +// 账号绑定 list +export const accountBindList: ListItem[] = [ + { + key: '20', + title: '钉钉', + description: '当前未绑定钉钉账号', + extra: '绑定', + avatar: 'ri:dingding-fill', + color: '#2eabff' + }, + { + key: '30', + title: '企业微信', + description: '当前未绑定企业微信', + extra: '绑定', + avatar: 'ri:wechat-line', + color: '#2eabff' + } +] + +// 新消息通知 list +export const msgNotifyList: ListItem[] = [ + { + key: '1', + title: '账户密码', + description: '其他用户的消息将以站内信的形式通知' + }, + { + key: '2', + title: '系统消息', + description: '系统消息将以站内信的形式通知' + }, + { + key: '3', + title: '待办任务', + description: '待办任务将以站内信的形式通知' + } +] + +export const passwordSchema: FormSchema[] = [ + { + field: 'oldPassword', + label: '当前密码', + component: 'InputPassword', + required: true + }, + { + field: 'newPassword', + label: '新密码', + component: 'StrengthMeter', + componentProps: { + placeholder: '新密码' + }, + rules: [ + { + required: true, + message: '请输入新密码' + } + ] + }, + { + field: 'confirmPassword', + label: '确认密码', + component: 'InputPassword', + + dynamicRules: ({ values }) => { + return [ + { + required: true, + validator: (_, value) => { + if (!value) { + return Promise.reject('密码不能为空') + } + if (value !== values.newPassword) { + return Promise.reject('两次输入的密码不一致!') + } + return Promise.resolve() + } + } + ] + } + } +] diff --git a/src/views/base/profile/index.vue b/src/views/base/profile/index.vue new file mode 100644 index 0000000..b8d8c35 --- /dev/null +++ b/src/views/base/profile/index.vue @@ -0,0 +1,40 @@ +<template> + <ScrollContainer> + <div ref="wrapperRef" class="account-setting"> + <Tabs tab-position="left" :tabBarStyle="tabBarStyle"> + <template v-for="item in settingList" :key="item.key"> + <TabPane :tab="item.name"> + <BaseSetting v-if="item.component == 'BaseSetting'" /> + <SecureSetting v-if="item.component == 'SecureSetting'" /> + <AccountBind v-if="item.component == 'AccountBind'" /> + <MsgNotify v-if="item.component == 'MsgNotify'" /> + </TabPane> + </template> + </Tabs> + </div> + </ScrollContainer> +</template> +<script setup lang="ts"> +import { Tabs, TabPane } from 'ant-design-vue' +import { ScrollContainer } from '@/components/Container/index' +import { settingList } from './data' +import BaseSetting from './BaseSetting.vue' +import SecureSetting from './SecureSetting.vue' +import AccountBind from './AccountBind.vue' +import MsgNotify from './MsgNotify.vue' +const tabBarStyle = { width: '220px' } +</script> +<style lang="less"> +.account-setting { + margin: 12px; + background-color: @component-background; + + .base-title { + padding-left: 0; + } + + .ant-tabs-tab-active { + background-color: @item-active-bg; + } +} +</style> diff --git a/src/views/sys/redirect/index.vue b/src/views/base/redirect/index.vue similarity index 100% rename from src/views/sys/redirect/index.vue rename to src/views/base/redirect/index.vue diff --git a/src/views/dashboard/workbench/components/WorkbenchHeader.vue b/src/views/dashboard/workbench/components/WorkbenchHeader.vue index 5fe095e..1c41b6a 100644 --- a/src/views/dashboard/workbench/components/WorkbenchHeader.vue +++ b/src/views/dashboard/workbench/components/WorkbenchHeader.vue @@ -1,8 +1,8 @@ <template> <div class="lg:flex"> - <Avatar :src="userinfo.avatar || headerImg" :size="72" class="!mx-auto !block" /> + <Avatar :src="userinfo.user.avatar || headerImg" :size="72" class="!mx-auto !block" /> <div class="md:ml-6 flex flex-col justify-center md:mt-0 mt-2"> - <h1 class="md:text-lg text-md">早安, {{ userinfo.realName }}, 开始您一天的工作吧!</h1> + <h1 class="md:text-lg text-md">早安, {{ userinfo.user.nickname }}, 开始您一天的工作吧!</h1> <span class="text-secondary"> 今日晴,20℃ - 32℃! </span> </div> <div class="flex flex-1 justify-end md:mt-0 mt-4"> diff --git a/src/views/sys/error-log/DetailModal.vue b/src/views/sys/error-log/DetailModal.vue deleted file mode 100644 index 48159e0..0000000 --- a/src/views/sys/error-log/DetailModal.vue +++ /dev/null @@ -1,26 +0,0 @@ -<template> - <BasicModal :width="800" :title="t('sys.errorLog.tableActionDesc')" v-bind="$attrs"> - <Description :data="info" @register="register" /> - </BasicModal> -</template> -<script lang="ts" setup> -import type { ErrorLogInfo } from '@/types/store' -import { BasicModal } from '@/components/Modal' -import { Description, useDescription } from '@/components/Description' -import { useI18n } from '@/hooks/web/useI18n' -import { getDescSchema } from './data' - -defineProps({ - info: { - type: Object as PropType<ErrorLogInfo>, - default: null - } -}) - -const { t } = useI18n() - -const [register] = useDescription({ - column: 2, - schema: getDescSchema()! -}) -</script> diff --git a/src/views/sys/error-log/data.tsx b/src/views/sys/error-log/data.tsx deleted file mode 100644 index ab3a5cc..0000000 --- a/src/views/sys/error-log/data.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Tag } from 'ant-design-vue' -import { BasicColumn } from '@/components/Table' -import { ErrorTypeEnum } from '@/enums/exceptionEnum' -import { useI18n } from '@/hooks/web/useI18n' - -const { t } = useI18n() - -export function getColumns(): BasicColumn[] { - return [ - { - dataIndex: 'type', - title: t('sys.errorLog.tableColumnType'), - width: 80, - customRender: ({ text }) => { - const color = - text === ErrorTypeEnum.VUE - ? 'green' - : text === ErrorTypeEnum.RESOURCE - ? 'cyan' - : text === ErrorTypeEnum.PROMISE - ? 'blue' - : ErrorTypeEnum.AJAX - ? 'red' - : 'purple' - return <Tag color={color}>{() => text}</Tag> - } - }, - { - dataIndex: 'url', - title: 'URL', - width: 200 - }, - { - dataIndex: 'time', - title: t('sys.errorLog.tableColumnDate'), - width: 160 - }, - { - dataIndex: 'file', - title: t('sys.errorLog.tableColumnFile'), - width: 200 - }, - { - dataIndex: 'name', - title: 'Name', - width: 200 - }, - { - dataIndex: 'message', - title: t('sys.errorLog.tableColumnMsg'), - width: 300 - }, - { - dataIndex: 'stack', - title: t('sys.errorLog.tableColumnStackMsg') - } - ] -} - -export function getDescSchema(): any { - return getColumns().map((column) => { - return { - field: column.dataIndex!, - label: column.title - } - }) -} diff --git a/src/views/sys/error-log/index.vue b/src/views/sys/error-log/index.vue deleted file mode 100644 index ae14517..0000000 --- a/src/views/sys/error-log/index.vue +++ /dev/null @@ -1,97 +0,0 @@ -<template> - <div class="p-4"> - <template v-for="src in imgList" :key="src"> - <img :src="src" v-show="false" alt="" /> - </template> - <DetailModal :info="rowInfo" @register="registerModal" /> - <BasicTable @register="register" class="error-handle-table"> - <template #toolbar> - <a-button @click="fireVueError" type="primary"> - {{ t('sys.errorLog.fireVueError') }} - </a-button> - <a-button @click="fireResourceError" type="primary"> - {{ t('sys.errorLog.fireResourceError') }} - </a-button> - <a-button @click="fireAjaxError" type="primary"> - {{ t('sys.errorLog.fireAjaxError') }} - </a-button> - </template> - <template #bodyCell="{ column, record }"> - <template v-if="column.key === 'action'"> - <TableAction - :actions="[ - { - label: t('sys.errorLog.tableActionDesc'), - onClick: handleDetail.bind(null, record) - } - ]" - /> - </template> - </template> - </BasicTable> - </div> -</template> - -<script lang="ts" setup> -import type { ErrorLogInfo } from '@/types/store' -import { watch, ref, nextTick } from 'vue' -import DetailModal from './DetailModal.vue' -import { BasicTable, useTable, TableAction } from '@/components/Table' -import { useModal } from '@/components/Modal' -import { useMessage } from '@/hooks/web/useMessage' -import { useI18n } from '@/hooks/web/useI18n' -import { useErrorLogStore } from '@/store/modules/errorLog' -import { fireErrorApi } from '@/api/demo/error' -import { getColumns } from './data' -import { cloneDeep } from 'lodash-es' - -const rowInfo = ref<ErrorLogInfo>() -const imgList = ref<string[]>([]) - -const { t } = useI18n() -const errorLogStore = useErrorLogStore() -const [register, { setTableData }] = useTable({ - title: t('sys.errorLog.tableTitle'), - columns: getColumns(), - actionColumn: { - width: 80, - title: 'Action', - dataIndex: 'action' - // slots: { customRender: 'action' }, - } -}) -const [registerModal, { openModal }] = useModal() - -watch( - () => errorLogStore.getErrorLogInfoList, - (list) => { - nextTick(() => { - setTableData(cloneDeep(list)) - }) - }, - { - immediate: true - } -) -const { createMessage } = useMessage() -if (import.meta.env.DEV) { - createMessage.info(t('sys.errorLog.enableMessage')) -} -// 查看详情 -function handleDetail(row: ErrorLogInfo) { - rowInfo.value = row - openModal(true) -} - -function fireVueError() { - throw new Error('fire vue error!') -} - -function fireResourceError() { - imgList.value.push(`${new Date().getTime()}.png`) -} - -async function fireAjaxError() { - await fireErrorApi() -} -</script>