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>