瀏覽代碼

feat: 简易版本

kailong321200875 1 年之前
父節點
當前提交
255843d4c0
共有 60 個文件被更改,包括 0 次插入7839 次删除
  1. 0 3
      src/components/CountTo/index.ts
  2. 0 180
      src/components/CountTo/src/CountTo.vue
  3. 0 3
      src/components/Echart/index.ts
  4. 0 113
      src/components/Echart/src/Echart.vue
  5. 0 3
      src/components/Highlight/index.ts
  6. 0 65
      src/components/Highlight/src/Highlight.vue
  7. 0 33
      src/components/ImageViewer/index.ts
  8. 0 34
      src/components/ImageViewer/src/ImageViewer.vue
  9. 0 9
      src/components/ImageViewer/src/types/index.ts
  10. 0 5
      src/components/Infotip/index.ts
  11. 0 53
      src/components/Infotip/src/Infotip.vue
  12. 0 4
      src/components/Infotip/src/types/index.ts
  13. 0 5
      src/components/Qrcode/index.ts
  14. 0 252
      src/components/Qrcode/src/Qrcode.vue
  15. 0 9
      src/components/Qrcode/src/types/index.ts
  16. 0 10
      src/directives/index.ts
  17. 0 47
      src/directives/permission/hasPermi.ts
  18. 0 5
      src/main.ts
  19. 0 420
      src/router/index.ts
  20. 0 91
      src/views/Authorization/Role.vue
  21. 0 355
      src/views/Authorization/User.vue
  22. 0 20
      src/views/Authorization/components/Detail.vue
  23. 0 62
      src/views/Authorization/components/Write.vue
  24. 0 100
      src/views/Components/CountTo.vue
  25. 0 190
      src/views/Components/Descriptions.vue
  26. 0 131
      src/views/Components/Dialog.vue
  27. 0 36
      src/views/Components/Echart.vue
  28. 0 32
      src/views/Components/Editor/Editor.vue
  29. 0 1825
      src/views/Components/Form/DefaultForm.vue
  30. 0 316
      src/views/Components/Form/UseFormDemo.vue
  31. 0 20
      src/views/Components/Highlight.vue
  32. 0 62
      src/views/Components/Icon.vue
  33. 0 30
      src/views/Components/ImageViewer.vue
  34. 0 33
      src/views/Components/Infotip.vue
  35. 0 21
      src/views/Components/InputPassword.vue
  36. 0 108
      src/views/Components/Qrcode.vue
  37. 0 272
      src/views/Components/Search.vue
  38. 0 104
      src/views/Components/Table/DefaultTable.vue
  39. 0 82
      src/views/Components/Table/TableImagePreview.vue
  40. 0 116
      src/views/Components/Table/TreeTable.vue
  41. 0 275
      src/views/Components/Table/UseTableDemo.vue
  42. 0 127
      src/views/Dashboard/Analysis.vue
  43. 0 293
      src/views/Dashboard/Workplace.vue
  44. 0 200
      src/views/Dashboard/components/PanelGroup.vue
  45. 0 309
      src/views/Dashboard/echarts-data.ts
  46. 0 17
      src/views/Error/403.vue
  47. 0 17
      src/views/Error/404.vue
  48. 0 17
      src/views/Error/500.vue
  49. 0 324
      src/views/Example/Dialog/ExampleDialog.vue
  50. 0 20
      src/views/Example/Dialog/components/Detail.vue
  51. 0 63
      src/views/Example/Dialog/components/Write.vue
  52. 0 53
      src/views/Example/Page/ExampleAdd.vue
  53. 0 38
      src/views/Example/Page/ExampleDetail.vue
  54. 0 67
      src/views/Example/Page/ExampleEdit.vue
  55. 0 262
      src/views/Example/Page/ExamplePage.vue
  56. 0 69
      src/views/Example/Page/components/Detail.vue
  57. 0 154
      src/views/Example/Page/components/Write.vue
  58. 0 20
      src/views/Guide/Guide.vue
  59. 0 223
      src/views/hooks/useCrudSchemas.vue
  60. 0 32
      src/views/hooks/useWatermark.vue

+ 0 - 3
src/components/CountTo/index.ts

@@ -1,3 +0,0 @@
-import CountTo from './src/CountTo.vue'
-
-export { CountTo }

+ 0 - 180
src/components/CountTo/src/CountTo.vue

@@ -1,180 +0,0 @@
-<script setup lang="ts">
-import { reactive, computed, watch, onMounted, unref, toRef, PropType } from 'vue'
-import { isNumber } from '@/utils/is'
-import { propTypes } from '@/utils/propTypes'
-import { useDesign } from '@/hooks/web/useDesign'
-
-const { getPrefixCls } = useDesign()
-
-const prefixCls = getPrefixCls('count-to')
-
-const props = defineProps({
-  startVal: propTypes.number.def(0),
-  endVal: propTypes.number.def(2021),
-  duration: propTypes.number.def(3000),
-  autoplay: propTypes.bool.def(true),
-  decimals: propTypes.number.validate((value: number) => value >= 0).def(0),
-  decimal: propTypes.string.def('.'),
-  separator: propTypes.string.def(','),
-  prefix: propTypes.string.def(''),
-  suffix: propTypes.string.def(''),
-  useEasing: propTypes.bool.def(true),
-  easingFn: {
-    type: Function as PropType<(t: number, b: number, c: number, d: number) => number>,
-    default(t: number, b: number, c: number, d: number) {
-      return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
-    }
-  }
-})
-
-const emit = defineEmits(['mounted', 'callback'])
-
-const formatNumber = (num: number | string) => {
-  const { decimals, decimal, separator, suffix, prefix } = props
-  num = Number(num).toFixed(decimals)
-  num += ''
-  const x = num.split('.')
-  let x1 = x[0]
-  const x2 = x.length > 1 ? decimal + x[1] : ''
-  const rgx = /(\d+)(\d{3})/
-  if (separator && !isNumber(separator)) {
-    while (rgx.test(x1)) {
-      x1 = x1.replace(rgx, '$1' + separator + '$2')
-    }
-  }
-  return prefix + x1 + x2 + suffix
-}
-
-const state = reactive<{
-  localStartVal: number
-  printVal: number | null
-  displayValue: string
-  paused: boolean
-  localDuration: number | null
-  startTime: number | null
-  timestamp: number | null
-  rAF: any
-  remaining: number | null
-}>({
-  localStartVal: props.startVal,
-  displayValue: formatNumber(props.startVal),
-  printVal: null,
-  paused: false,
-  localDuration: props.duration,
-  startTime: null,
-  timestamp: null,
-  remaining: null,
-  rAF: null
-})
-
-const displayValue = toRef(state, 'displayValue')
-
-onMounted(() => {
-  if (props.autoplay) {
-    start()
-  }
-  emit('mounted')
-})
-
-const getCountDown = computed(() => {
-  return props.startVal > props.endVal
-})
-
-watch([() => props.startVal, () => props.endVal], () => {
-  if (props.autoplay) {
-    start()
-  }
-})
-
-const start = () => {
-  const { startVal, duration } = props
-  state.localStartVal = startVal
-  state.startTime = null
-  state.localDuration = duration
-  state.paused = false
-  state.rAF = requestAnimationFrame(count)
-}
-
-const pauseResume = () => {
-  if (state.paused) {
-    resume()
-    state.paused = false
-  } else {
-    pause()
-    state.paused = true
-  }
-}
-
-const pause = () => {
-  cancelAnimationFrame(state.rAF)
-}
-
-const resume = () => {
-  state.startTime = null
-  state.localDuration = +(state.remaining as number)
-  state.localStartVal = +(state.printVal as number)
-  requestAnimationFrame(count)
-}
-
-const reset = () => {
-  state.startTime = null
-  cancelAnimationFrame(state.rAF)
-  state.displayValue = formatNumber(props.startVal)
-}
-
-const count = (timestamp: number) => {
-  const { useEasing, easingFn, endVal } = props
-  if (!state.startTime) state.startTime = timestamp
-  state.timestamp = timestamp
-  const progress = timestamp - state.startTime
-  state.remaining = (state.localDuration as number) - progress
-  if (useEasing) {
-    if (unref(getCountDown)) {
-      state.printVal =
-        state.localStartVal -
-        easingFn(progress, 0, state.localStartVal - endVal, state.localDuration as number)
-    } else {
-      state.printVal = easingFn(
-        progress,
-        state.localStartVal,
-        endVal - state.localStartVal,
-        state.localDuration as number
-      )
-    }
-  } else {
-    if (unref(getCountDown)) {
-      state.printVal =
-        state.localStartVal -
-        (state.localStartVal - endVal) * (progress / (state.localDuration as number))
-    } else {
-      state.printVal =
-        state.localStartVal +
-        (endVal - state.localStartVal) * (progress / (state.localDuration as number))
-    }
-  }
-  if (unref(getCountDown)) {
-    state.printVal = state.printVal < endVal ? endVal : state.printVal
-  } else {
-    state.printVal = state.printVal > endVal ? endVal : state.printVal
-  }
-  state.displayValue = formatNumber(state.printVal!)
-  if (progress < (state.localDuration as number)) {
-    state.rAF = requestAnimationFrame(count)
-  } else {
-    emit('callback')
-  }
-}
-
-defineExpose({
-  pauseResume,
-  reset,
-  start,
-  pause
-})
-</script>
-
-<template>
-  <span :class="prefixCls">
-    {{ displayValue }}
-  </span>
-</template>

+ 0 - 3
src/components/Echart/index.ts

@@ -1,3 +0,0 @@
-import Echart from './src/Echart.vue'
-
-export { Echart }

+ 0 - 113
src/components/Echart/src/Echart.vue

@@ -1,113 +0,0 @@
-<script setup lang="ts">
-import type { EChartsOption } from 'echarts'
-import echarts from '@/plugins/echarts'
-import { debounce } from 'lodash-es'
-import 'echarts-wordcloud'
-import { propTypes } from '@/utils/propTypes'
-import { computed, PropType, ref, unref, watch, onMounted, onBeforeUnmount, onActivated } from 'vue'
-import { useAppStore } from '@/store/modules/app'
-import { isString } from '@/utils/is'
-import { useDesign } from '@/hooks/web/useDesign'
-
-const { getPrefixCls, variables } = useDesign()
-
-const prefixCls = getPrefixCls('echart')
-
-const appStore = useAppStore()
-
-const props = defineProps({
-  options: {
-    type: Object as PropType<EChartsOption>,
-    required: true
-  },
-  width: propTypes.oneOfType([Number, String]).def(''),
-  height: propTypes.oneOfType([Number, String]).def('500px')
-})
-
-const isDark = computed(() => appStore.getIsDark)
-
-const theme = computed(() => {
-  const echartTheme: boolean | string = unref(isDark) ? true : 'auto'
-
-  return echartTheme
-})
-
-const options = computed(() => {
-  return Object.assign(props.options, {
-    darkMode: unref(theme)
-  })
-})
-
-const elRef = ref<ElRef>()
-
-let echartRef: Nullable<echarts.ECharts> = null
-
-const contentEl = ref<Element>()
-
-const styles = computed(() => {
-  const width = isString(props.width) ? props.width : `${props.width}px`
-  const height = isString(props.height) ? props.height : `${props.height}px`
-
-  return {
-    width,
-    height
-  }
-})
-
-const initChart = () => {
-  if (unref(elRef) && props.options) {
-    echartRef = echarts.init(unref(elRef) as HTMLElement)
-    echartRef?.setOption(unref(options))
-  }
-}
-
-watch(
-  () => options.value,
-  (options) => {
-    if (echartRef) {
-      echartRef?.setOption(options)
-    }
-  },
-  {
-    deep: true
-  }
-)
-
-const resizeHandler = debounce(() => {
-  if (echartRef) {
-    echartRef.resize()
-  }
-}, 100)
-
-const contentResizeHandler = async (e: TransitionEvent) => {
-  if (e.propertyName === 'width') {
-    resizeHandler()
-  }
-}
-
-onMounted(() => {
-  initChart()
-
-  window.addEventListener('resize', resizeHandler)
-
-  contentEl.value = document.getElementsByClassName(`${variables.namespace}-layout-content`)[0]
-  unref(contentEl) &&
-    (unref(contentEl) as Element).addEventListener('transitionend', contentResizeHandler)
-})
-
-onBeforeUnmount(() => {
-  window.removeEventListener('resize', resizeHandler)
-  unref(contentEl) &&
-    (unref(contentEl) as Element).removeEventListener('transitionend', contentResizeHandler)
-})
-
-onActivated(() => {
-  if (echartRef) {
-    echartRef.resize()
-  }
-})
-</script>
-
-<template>
-  <div ref="elRef" :class="[$attrs.class, prefixCls]" :style="styles"></div>
-</template>

+ 0 - 3
src/components/Highlight/index.ts

@@ -1,3 +0,0 @@
-import Highlight from './src/Highlight.vue'
-
-export { Highlight }

+ 0 - 65
src/components/Highlight/src/Highlight.vue

@@ -1,65 +0,0 @@
-<script lang="tsx">
-import { defineComponent, PropType, computed, h, unref } from 'vue'
-import { propTypes } from '@/utils/propTypes'
-
-export default defineComponent({
-  name: 'Highlight',
-  props: {
-    tag: propTypes.string.def('span'),
-    keys: {
-      type: Array as PropType<string[]>,
-      default: () => []
-    },
-    color: propTypes.string.def('var(--el-color-primary)')
-  },
-  emits: ['click'],
-  setup(props, { emit, slots }) {
-    const keyNodes = computed(() => {
-      return props.keys.map((key) => {
-        return h(
-          'span',
-          {
-            onClick: () => {
-              emit('click', key)
-            },
-            style: {
-              color: props.color,
-              cursor: 'pointer'
-            }
-          },
-          key
-        )
-      })
-    })
-
-    const parseText = (text: string) => {
-      props.keys.forEach((key, index) => {
-        const regexp = new RegExp(key, 'g')
-        text = text.replace(regexp, `{{${index}}}`)
-      })
-      return text.split(/{{|}}/)
-    }
-
-    const renderText = () => {
-      if (!slots?.default) return null
-      const node = slots?.default()[0].children
-
-      if (!node) {
-        return slots?.default()[0]
-      }
-
-      const textArray = parseText(node as string)
-      const regexp = /^[0-9]*$/
-      const nodes = textArray.map((t) => {
-        if (regexp.test(t)) {
-          return unref(keyNodes)[t] || t
-        }
-        return t
-      })
-      return h(props.tag, nodes)
-    }
-
-    return () => renderText()
-  }
-})
-</script>

+ 0 - 33
src/components/ImageViewer/index.ts

@@ -1,33 +0,0 @@
-import ImageViewer from './src/ImageViewer.vue'
-import { isClient } from '@/utils/is'
-import { createVNode, render, VNode } from 'vue'
-import { ImageViewerProps } from './src/types'
-
-let instance: Nullable<VNode> = null
-
-export function createImageViewer(options: ImageViewerProps) {
-  if (!isClient) return
-  const {
-    urlList,
-    initialIndex = 0,
-    infinite = true,
-    hideOnClickModal = false,
-    teleported = false,
-    zIndex = 2000,
-    show = true
-  } = options
-
-  const propsData: Partial<ImageViewerProps> = {}
-  const container = document.createElement('div')
-  propsData.urlList = urlList
-  propsData.initialIndex = initialIndex
-  propsData.infinite = infinite
-  propsData.hideOnClickModal = hideOnClickModal
-  propsData.teleported = teleported
-  propsData.zIndex = zIndex
-  propsData.show = show
-
-  document.body.appendChild(container)
-  instance = createVNode(ImageViewer, propsData)
-  render(instance, container)
-}

+ 0 - 34
src/components/ImageViewer/src/ImageViewer.vue

@@ -1,34 +0,0 @@
-<script setup lang="ts">
-import { ElImageViewer } from 'element-plus'
-import { computed, ref, PropType } from 'vue'
-import { propTypes } from '@/utils/propTypes'
-
-const props = defineProps({
-  urlList: {
-    type: Array as PropType<string[]>,
-    default: (): string[] => []
-  },
-  zIndex: propTypes.number.def(200),
-  initialIndex: propTypes.number.def(0),
-  infinite: propTypes.bool.def(true),
-  hideOnClickModal: propTypes.bool.def(false),
-  teleported: propTypes.bool.def(false),
-  show: propTypes.bool.def(false)
-})
-
-const getBindValue = computed(() => {
-  const propsData: Recordable = { ...props }
-  delete propsData.show
-  return propsData
-})
-
-const show = ref(props.show)
-
-const close = () => {
-  show.value = false
-}
-</script>
-
-<template>
-  <ElImageViewer v-if="show" v-bind="getBindValue" @close="close" />
-</template>

+ 0 - 9
src/components/ImageViewer/src/types/index.ts

@@ -1,9 +0,0 @@
-export interface ImageViewerProps {
-  urlList?: string[]
-  zIndex?: number
-  initialIndex?: number
-  infinite?: boolean
-  hideOnClickModal?: boolean
-  teleported?: boolean
-  show?: boolean
-}

+ 0 - 5
src/components/Infotip/index.ts

@@ -1,5 +0,0 @@
-import Infotip from './src/Infotip.vue'
-
-export type { InfoTipSchema } from './src/types'
-
-export { Infotip }

+ 0 - 53
src/components/Infotip/src/Infotip.vue

@@ -1,53 +0,0 @@
-<script setup lang="ts">
-import { PropType } from 'vue'
-import { Highlight } from '@/components/Highlight'
-import { useDesign } from '@/hooks/web/useDesign'
-import { propTypes } from '@/utils/propTypes'
-import { InfoTipSchema } from './types'
-
-const { getPrefixCls } = useDesign()
-
-const prefixCls = getPrefixCls('infotip')
-
-defineProps({
-  title: propTypes.string.def(''),
-  schema: {
-    type: Array as PropType<Array<string | InfoTipSchema>>,
-    required: true,
-    default: () => []
-  },
-  showIndex: propTypes.bool.def(true),
-  highlightColor: propTypes.string.def('var(--el-color-primary)')
-})
-
-const emit = defineEmits(['click'])
-
-const keyClick = (key: string) => {
-  emit('click', key)
-}
-</script>
-
-<template>
-  <div
-    :class="[
-      prefixCls,
-      'p-20px mb-20px border-1px border-solid border-[var(--el-color-primary)] bg-[var(--el-color-primary-light-9)]'
-    ]"
-  >
-    <div v-if="title" :class="[`${prefixCls}__header`, 'flex items-center']">
-      <Icon icon="bi:exclamation-circle-fill" :size="22" color="var(--el-color-primary)" />
-      <span :class="[`${prefixCls}__title`, 'pl-5px text-16px font-bold']">{{ title }}</span>
-    </div>
-    <div :class="`${prefixCls}__content`">
-      <p v-for="(item, $index) in schema" :key="$index" class="text-14px mt-15px">
-        <Highlight
-          :keys="typeof item === 'string' ? [] : item.keys"
-          :color="highlightColor"
-          @click="keyClick"
-        >
-          {{ showIndex ? `${$index + 1}、` : '' }}{{ typeof item === 'string' ? item : item.label }}
-        </Highlight>
-      </p>
-    </div>
-  </div>
-</template>

+ 0 - 4
src/components/Infotip/src/types/index.ts

@@ -1,4 +0,0 @@
-export interface InfoTipSchema {
-  label: string
-  keys?: string[]
-}

+ 0 - 5
src/components/Qrcode/index.ts

@@ -1,5 +0,0 @@
-import Qrcode from './src/Qrcode.vue'
-
-export type { QrcodeLogo } from './src/types'
-
-export { Qrcode }

+ 0 - 252
src/components/Qrcode/src/Qrcode.vue

@@ -1,252 +0,0 @@
-<script setup lang="ts">
-import { PropType, nextTick, ref, watch, computed, unref } from 'vue'
-import QRCode from 'qrcode'
-import { QRCodeRenderersOptions } from 'qrcode'
-import { cloneDeep } from 'lodash-es'
-import { propTypes } from '@/utils/propTypes'
-import { useDesign } from '@/hooks/web/useDesign'
-import { isString } from '@/utils/is'
-import { QrcodeLogo } from '@/components/Qrcode'
-
-const props = defineProps({
-  // img 或者 canvas,img不支持logo嵌套
-  tag: propTypes.string.validate((v: string) => ['canvas', 'img'].includes(v)).def('canvas'),
-  // 二维码内容
-  text: {
-    type: [String, Array] as PropType<string | Recordable[]>,
-    default: null
-  },
-  // qrcode.js配置项
-  options: {
-    type: Object as PropType<QRCodeRenderersOptions>,
-    default: () => ({})
-  },
-  // 宽度
-  width: propTypes.number.def(200),
-  // logo
-  logo: {
-    type: [String, Object] as PropType<Partial<QrcodeLogo> | string>,
-    default: ''
-  },
-  // 是否过期
-  disabled: propTypes.bool.def(false),
-  // 过期提示内容
-  disabledText: propTypes.string.def('')
-})
-
-const emit = defineEmits(['done', 'click', 'disabled-click'])
-
-const { getPrefixCls } = useDesign()
-
-const prefixCls = getPrefixCls('qrcode')
-
-const { toCanvas, toDataURL } = QRCode
-
-const loading = ref(true)
-
-const wrapRef = ref<Nullable<HTMLCanvasElement | HTMLImageElement>>(null)
-
-const renderText = computed(() => String(props.text))
-
-const wrapStyle = computed(() => {
-  return {
-    width: props.width + 'px',
-    height: props.width + 'px'
-  }
-})
-
-const initQrcode = async () => {
-  await nextTick()
-  const options = cloneDeep(props.options || {})
-  if (props.tag === 'canvas') {
-    // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率
-    options.errorCorrectionLevel =
-      options.errorCorrectionLevel || getErrorCorrectionLevel(unref(renderText))
-    const _width: number = await getOriginWidth(unref(renderText), options)
-    options.scale = props.width === 0 ? undefined : (props.width / _width) * 4
-    const canvasRef = (await toCanvas(
-      unref(wrapRef) as HTMLCanvasElement,
-      unref(renderText),
-      options
-    )) as unknown as HTMLCanvasElement
-    if (props.logo) {
-      const url = await createLogoCode(canvasRef)
-      emit('done', url)
-      loading.value = false
-    } else {
-      emit('done', canvasRef.toDataURL())
-      loading.value = false
-    }
-  } else {
-    const url = await toDataURL(renderText.value, {
-      errorCorrectionLevel: 'H',
-      width: props.width,
-      ...options
-    })
-    ;(unref(wrapRef) as HTMLImageElement).src = url
-    emit('done', url)
-    loading.value = false
-  }
-}
-
-watch(
-  () => renderText.value,
-  (val) => {
-    if (!val) return
-    initQrcode()
-  },
-  {
-    deep: true,
-    immediate: true
-  }
-)
-
-const createLogoCode = (canvasRef: HTMLCanvasElement) => {
-  const canvasWidth = canvasRef.width
-  const logoOptions: QrcodeLogo = Object.assign(
-    {
-      logoSize: 0.15,
-      bgColor: '#ffffff',
-      borderSize: 0.05,
-      crossOrigin: 'anonymous',
-      borderRadius: 8,
-      logoRadius: 0
-    },
-    isString(props.logo) ? {} : props.logo
-  )
-  const {
-    logoSize = 0.15,
-    bgColor = '#ffffff',
-    borderSize = 0.05,
-    crossOrigin = 'anonymous',
-    borderRadius = 8,
-    logoRadius = 0
-  } = logoOptions
-  const logoSrc = isString(props.logo) ? props.logo : props.logo.src
-  const logoWidth = canvasWidth * logoSize
-  const logoXY = (canvasWidth * (1 - logoSize)) / 2
-  const logoBgWidth = canvasWidth * (logoSize + borderSize)
-  const logoBgXY = (canvasWidth * (1 - logoSize - borderSize)) / 2
-
-  const ctx = canvasRef.getContext('2d')
-  if (!ctx) return
-
-  // logo 底色
-  canvasRoundRect(ctx)(logoBgXY, logoBgXY, logoBgWidth, logoBgWidth, borderRadius)
-  ctx.fillStyle = bgColor
-  ctx.fill()
-
-  // logo
-  const image = new Image()
-  if (crossOrigin || logoRadius) {
-    image.setAttribute('crossOrigin', crossOrigin)
-  }
-  ;(image as any).src = logoSrc
-
-  // 使用image绘制可以避免某些跨域情况
-  const drawLogoWithImage = (image: HTMLImageElement) => {
-    ctx.drawImage(image, logoXY, logoXY, logoWidth, logoWidth)
-  }
-
-  // 使用canvas绘制以获得更多的功能
-  const drawLogoWithCanvas = (image: HTMLImageElement) => {
-    const canvasImage = document.createElement('canvas')
-    canvasImage.width = logoXY + logoWidth
-    canvasImage.height = logoXY + logoWidth
-    const imageCanvas = canvasImage.getContext('2d')
-    if (!imageCanvas || !ctx) return
-    imageCanvas.drawImage(image, logoXY, logoXY, logoWidth, logoWidth)
-
-    canvasRoundRect(ctx)(logoXY, logoXY, logoWidth, logoWidth, logoRadius)
-    if (!ctx) return
-    const fillStyle = ctx.createPattern(canvasImage, 'no-repeat')
-    if (fillStyle) {
-      ctx.fillStyle = fillStyle
-      ctx.fill()
-    }
-  }
-
-  // 将 logo绘制到 canvas上
-  return new Promise((resolve: any) => {
-    image.onload = () => {
-      logoRadius ? drawLogoWithCanvas(image) : drawLogoWithImage(image)
-      resolve(canvasRef.toDataURL())
-    }
-  })
-}
-
-// 得到原QrCode的大小,以便缩放得到正确的QrCode大小
-const getOriginWidth = async (content: string, options: QRCodeRenderersOptions) => {
-  const _canvas = document.createElement('canvas')
-  await toCanvas(_canvas, content, options)
-  return _canvas.width
-}
-
-// 对于内容少的QrCode,增大容错率
-const getErrorCorrectionLevel = (content: string) => {
-  if (content.length > 36) {
-    return 'M'
-  } else if (content.length > 16) {
-    return 'Q'
-  } else {
-    return 'H'
-  }
-}
-
-// copy来的方法,用于绘制圆角
-const canvasRoundRect = (ctx: CanvasRenderingContext2D) => {
-  return (x: number, y: number, w: number, h: number, r: number) => {
-    const minSize = Math.min(w, h)
-    if (r > minSize / 2) {
-      r = minSize / 2
-    }
-    ctx.beginPath()
-    ctx.moveTo(x + r, y)
-    ctx.arcTo(x + w, y, x + w, y + h, r)
-    ctx.arcTo(x + w, y + h, x, y + h, r)
-    ctx.arcTo(x, y + h, x, y, r)
-    ctx.arcTo(x, y, x + w, y, r)
-    ctx.closePath()
-    return ctx
-  }
-}
-
-const clickCode = () => {
-  emit('click')
-}
-
-const disabledClick = () => {
-  emit('disabled-click')
-}
-</script>
-
-<template>
-  <div v-loading="loading" :class="[prefixCls, 'relative inline-block']" :style="wrapStyle">
-    <component :is="tag" ref="wrapRef" @click="clickCode" />
-    <div
-      v-if="disabled"
-      :class="`${prefixCls}--disabled`"
-      class="absolute top-0 left-0 flex w-full h-full items-center justify-center"
-      @click="disabledClick"
-    >
-      <div class="absolute top-[50%] left-[50%] font-bold">
-        <Icon icon="ep:refresh-right" :size="30" color="var(--el-color-primary)" />
-        <div>{{ disabledText }}</div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<style lang="less" scoped>
-@prefix-cls: ~'@{namespace}-qrcode';
-
-.@{prefix-cls} {
-  &--disabled {
-    background: rgba(255, 255, 255, 0.95);
-
-    & > div {
-      transform: translate(-50%, -50%);
-    }
-  }
-}
-</style>

+ 0 - 9
src/components/Qrcode/src/types/index.ts

@@ -1,9 +0,0 @@
-export interface QrcodeLogo {
-  src?: string
-  logoSize?: number
-  bgColor?: string
-  borderSize?: number
-  crossOrigin?: string
-  borderRadius?: number
-  logoRadius?: number
-}

+ 0 - 10
src/directives/index.ts

@@ -1,10 +0,0 @@
-import type { App } from 'vue'
-import { setupPermissionDirective } from './permission/hasPermi'
-
-/**
- * 导出指令:v-xxx
- * @methods hasPermi 按钮权限,用法: v-hasPermi
- */
-export const setupPermission = (app: App<Element>) => {
-  setupPermissionDirective(app)
-}

+ 0 - 47
src/directives/permission/hasPermi.ts

@@ -1,47 +0,0 @@
-import type { App, Directive, DirectiveBinding } from 'vue'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useStorage } from '@/hooks/web/useStorage'
-import { intersection } from 'lodash-es'
-import { isArray } from '@/utils/is'
-import { useAppStoreWithOut } from '@/store/modules/app'
-
-const { t } = useI18n()
-const { getStorage } = useStorage()
-const appStore = useAppStoreWithOut()
-
-// 全部权限
-const all_permission = ['*.*.*']
-const hasPermission = (value: string | string[]): boolean => {
-  const permissions = getStorage(appStore.getUserInfo).permissions as string[]
-  if (!value) {
-    throw new Error(t('permission.hasPermission'))
-  }
-  if (!isArray(value)) {
-    return permissions?.includes(value as string)
-  }
-  if (all_permission[0] === permissions[0]) {
-    return true
-  }
-  return (intersection(value, permissions) as string[]).length > 0
-}
-function hasPermi(el: Element, binding: DirectiveBinding) {
-  const value = binding.value
-
-  const flag = hasPermission(value)
-  if (!flag) {
-    el.parentNode?.removeChild(el)
-  }
-}
-const mounted = (el: Element, binding: DirectiveBinding<any>) => {
-  hasPermi(el, binding)
-}
-
-const permiDirective: Directive = {
-  mounted
-}
-
-export const setupPermissionDirective = (app: App<Element>) => {
-  app.directive('hasPermi', permiDirective)
-}
-
-export default permiDirective

+ 0 - 5
src/main.ts

@@ -25,9 +25,6 @@ import '@/plugins/animate.css'
 // 路由
 import { setupRouter } from './router'
 
-// 权限
-import { setupPermission } from './directives'
-
 import { createApp } from 'vue'
 
 import App from './App.vue'
@@ -48,8 +45,6 @@ const setupAll = async () => {
 
   setupRouter(app)
 
-  setupPermission(app)
-
   app.mount('#app')
 }
 

+ 0 - 420
src/router/index.ts

@@ -56,292 +56,6 @@ export const constantRouterMap: AppRouteRecordRaw[] = [
 ]
 
 export const asyncRouterMap: AppRouteRecordRaw[] = [
-  {
-    path: '/dashboard',
-    component: Layout,
-    redirect: '/dashboard/analysis',
-    name: 'Dashboard',
-    meta: {
-      title: t('router.dashboard'),
-      icon: 'ant-design:dashboard-filled',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: 'analysis',
-        component: () => import('@/views/Dashboard/Analysis.vue'),
-        name: 'Analysis',
-        meta: {
-          title: t('router.analysis'),
-          noCache: true,
-          affix: true
-        }
-      },
-      {
-        path: 'workplace',
-        component: () => import('@/views/Dashboard/Workplace.vue'),
-        name: 'Workplace',
-        meta: {
-          title: t('router.workplace'),
-          noCache: true
-        }
-      }
-    ]
-  },
-  {
-    path: '/external-link',
-    component: Layout,
-    meta: {},
-    name: 'ExternalLink',
-    children: [
-      {
-        path: 'https://element-plus-admin-doc.cn/',
-        name: 'DocumentLink',
-        meta: {
-          title: t('router.document'),
-          icon: 'clarity:document-solid'
-        }
-      }
-    ]
-  },
-  {
-    path: '/guide',
-    component: Layout,
-    name: 'Guide',
-    meta: {},
-    children: [
-      {
-        path: 'index',
-        component: () => import('@/views/Guide/Guide.vue'),
-        name: 'GuideDemo',
-        meta: {
-          title: t('router.guide'),
-          icon: 'cib:telegram-plane'
-        }
-      }
-    ]
-  },
-  {
-    path: '/components',
-    component: Layout,
-    name: 'ComponentsDemo',
-    meta: {
-      title: t('router.component'),
-      icon: 'bx:bxs-component',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: 'form',
-        component: getParentLayout(),
-        redirect: '/components/form/default-form',
-        name: 'Form',
-        meta: {
-          title: t('router.form'),
-          alwaysShow: true
-        },
-        children: [
-          {
-            path: 'default-form',
-            component: () => import('@/views/Components/Form/DefaultForm.vue'),
-            name: 'DefaultForm',
-            meta: {
-              title: t('router.defaultForm')
-            }
-          },
-          {
-            path: 'use-form',
-            component: () => import('@/views/Components/Form/UseFormDemo.vue'),
-            name: 'UseForm',
-            meta: {
-              title: 'UseForm'
-            }
-          }
-        ]
-      },
-      {
-        path: 'table',
-        component: getParentLayout(),
-        redirect: '/components/table/default-table',
-        name: 'TableDemo',
-        meta: {
-          title: t('router.table'),
-          alwaysShow: true
-        },
-        children: [
-          {
-            path: 'default-table',
-            component: () => import('@/views/Components/Table/DefaultTable.vue'),
-            name: 'DefaultTable',
-            meta: {
-              title: t('router.defaultTable')
-            }
-          },
-          {
-            path: 'use-table',
-            component: () => import('@/views/Components/Table/UseTableDemo.vue'),
-            name: 'UseTable',
-            meta: {
-              title: 'UseTable'
-            }
-          },
-          {
-            path: 'tree-table',
-            component: () => import('@/views/Components/Table/TreeTable.vue'),
-            name: 'TreeTable',
-            meta: {
-              title: t('router.treeTable')
-            }
-          },
-          {
-            path: 'table-image-preview',
-            component: () => import('@/views/Components/Table/TableImagePreview.vue'),
-            name: 'TableImagePreview',
-            meta: {
-              title: t('router.PicturePreview')
-            }
-          }
-        ]
-      },
-      {
-        path: 'editor-demo',
-        component: getParentLayout(),
-        redirect: '/components/editor-demo/editor',
-        name: 'EditorDemo',
-        meta: {
-          title: t('router.editor'),
-          alwaysShow: true
-        },
-        children: [
-          {
-            path: 'editor',
-            component: () => import('@/views/Components/Editor/Editor.vue'),
-            name: 'Editor',
-            meta: {
-              title: t('router.richText')
-            }
-          }
-        ]
-      },
-      {
-        path: 'search',
-        component: () => import('@/views/Components/Search.vue'),
-        name: 'Search',
-        meta: {
-          title: t('router.search')
-        }
-      },
-      {
-        path: 'descriptions',
-        component: () => import('@/views/Components/Descriptions.vue'),
-        name: 'Descriptions',
-        meta: {
-          title: t('router.descriptions')
-        }
-      },
-      {
-        path: 'image-viewer',
-        component: () => import('@/views/Components/ImageViewer.vue'),
-        name: 'ImageViewer',
-        meta: {
-          title: t('router.imageViewer')
-        }
-      },
-      {
-        path: 'dialog',
-        component: () => import('@/views/Components/Dialog.vue'),
-        name: 'Dialog',
-        meta: {
-          title: t('router.dialog')
-        }
-      },
-      {
-        path: 'icon',
-        component: () => import('@/views/Components/Icon.vue'),
-        name: 'Icon',
-        meta: {
-          title: t('router.icon')
-        }
-      },
-      {
-        path: 'echart',
-        component: () => import('@/views/Components/Echart.vue'),
-        name: 'Echart',
-        meta: {
-          title: t('router.echart')
-        }
-      },
-      {
-        path: 'count-to',
-        component: () => import('@/views/Components/CountTo.vue'),
-        name: 'CountTo',
-        meta: {
-          title: t('router.countTo')
-        }
-      },
-      {
-        path: 'qrcode',
-        component: () => import('@/views/Components/Qrcode.vue'),
-        name: 'Qrcode',
-        meta: {
-          title: t('router.qrcode')
-        }
-      },
-      {
-        path: 'highlight',
-        component: () => import('@/views/Components/Highlight.vue'),
-        name: 'Highlight',
-        meta: {
-          title: t('router.highlight')
-        }
-      },
-      {
-        path: 'infotip',
-        component: () => import('@/views/Components/Infotip.vue'),
-        name: 'Infotip',
-        meta: {
-          title: t('router.infotip')
-        }
-      },
-      {
-        path: 'input-password',
-        component: () => import('@/views/Components/InputPassword.vue'),
-        name: 'InputPassword',
-        meta: {
-          title: t('router.inputPassword')
-        }
-      }
-    ]
-  },
-  {
-    path: '/hooks',
-    component: Layout,
-    redirect: '/hooks/useWatermark',
-    name: 'Hooks',
-    meta: {
-      title: 'hooks',
-      icon: 'ic:outline-webhook',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: 'useWatermark',
-        component: () => import('@/views/hooks/useWatermark.vue'),
-        name: 'UseWatermark',
-        meta: {
-          title: 'useWatermark'
-        }
-      }
-      // {
-      //   path: 'useCrudSchemas',
-      //   component: () => import('@/views/hooks/useCrudSchemas.vue'),
-      //   name: 'UseCrudSchemas',
-      //   meta: {
-      //     title: 'useCrudSchemas'
-      //   }
-      // }
-    ]
-  },
   {
     path: '/level',
     component: Layout,
@@ -400,140 +114,6 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
         }
       }
     ]
-  },
-  {
-    path: '/example',
-    component: Layout,
-    redirect: '/example/example-dialog',
-    name: 'Example',
-    meta: {
-      title: t('router.example'),
-      icon: 'ep:management',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: 'example-dialog',
-        component: () => import('@/views/Example/Dialog/ExampleDialog.vue'),
-        name: 'ExampleDialog',
-        meta: {
-          title: t('router.exampleDialog')
-        }
-      },
-      {
-        path: 'example-page',
-        component: () => import('@/views/Example/Page/ExamplePage.vue'),
-        name: 'ExamplePage',
-        meta: {
-          title: t('router.examplePage')
-        }
-      },
-      {
-        path: 'example-add',
-        component: () => import('@/views/Example/Page/ExampleAdd.vue'),
-        name: 'ExampleAdd',
-        meta: {
-          title: t('router.exampleAdd'),
-          noTagsView: true,
-          noCache: true,
-          hidden: true,
-          canTo: true,
-          activeMenu: '/example/example-page'
-        }
-      },
-      {
-        path: 'example-edit',
-        component: () => import('@/views/Example/Page/ExampleEdit.vue'),
-        name: 'ExampleEdit',
-        meta: {
-          title: t('router.exampleEdit'),
-          noTagsView: true,
-          noCache: true,
-          hidden: true,
-          canTo: true,
-          activeMenu: '/example/example-page'
-        }
-      },
-      {
-        path: 'example-detail',
-        component: () => import('@/views/Example/Page/ExampleDetail.vue'),
-        name: 'ExampleDetail',
-        meta: {
-          title: t('router.exampleDetail'),
-          noTagsView: true,
-          noCache: true,
-          hidden: true,
-          canTo: true,
-          activeMenu: '/example/example-page'
-        }
-      }
-    ]
-  },
-  {
-    path: '/error',
-    component: Layout,
-    redirect: '/error/404',
-    name: 'Error',
-    meta: {
-      title: t('router.errorPage'),
-      icon: 'ci:error',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: '404-demo',
-        component: () => import('@/views/Error/404.vue'),
-        name: '404Demo',
-        meta: {
-          title: '404'
-        }
-      },
-      {
-        path: '403-demo',
-        component: () => import('@/views/Error/403.vue'),
-        name: '403Demo',
-        meta: {
-          title: '403'
-        }
-      },
-      {
-        path: '500-demo',
-        component: () => import('@/views/Error/500.vue'),
-        name: '500Demo',
-        meta: {
-          title: '500'
-        }
-      }
-    ]
-  },
-  {
-    path: '/authorization',
-    component: Layout,
-    redirect: '/authorization/user',
-    name: 'Authorization',
-    meta: {
-      title: t('router.authorization'),
-      icon: 'eos-icons:role-binding',
-      alwaysShow: true
-    },
-    children: [
-      {
-        path: 'user',
-        component: () => import('@/views/Authorization/User.vue'),
-        name: 'User',
-        meta: {
-          title: t('router.user')
-        }
-      },
-      {
-        path: 'role',
-        component: () => import('@/views/Authorization/Role.vue'),
-        name: 'Role',
-        meta: {
-          title: t('router.role')
-        }
-      }
-    ]
   }
 ]
 

+ 0 - 91
src/views/Authorization/Role.vue

@@ -1,91 +0,0 @@
-<script setup lang="ts">
-// import { ContentWrap } from '@/components/ContentWrap'
-// import { useI18n } from '@/hooks/web/useI18n'
-// import { Table } from '@/components/Table'
-// import { getUserListApi } from '@/api/login'
-// import { UserType } from '@/api/login/types'
-// import { ref, h } from 'vue'
-// import { ElButton } from 'element-plus'
-// import { TableColumn, TableSlotDefault } from '@/types/table'
-
-// interface Params {
-//   pageIndex?: number
-//   pageSize?: number
-// }
-
-// const { t } = useI18n()
-
-// const columns: TableColumn[] = [
-//   {
-//     field: 'index',
-//     label: t('userDemo.index'),
-//     type: 'index'
-//   },
-//   {
-//     field: 'username',
-//     label: t('userDemo.username')
-//   },
-//   {
-//     field: 'password',
-//     label: t('userDemo.password')
-//   },
-//   {
-//     field: 'role',
-//     label: t('userDemo.role')
-//   },
-//   {
-//     field: 'remark',
-//     label: t('userDemo.remark'),
-//     formatter: (row: UserType) => {
-//       return h(
-//         'span',
-//         row.username === 'admin' ? t('userDemo.remarkMessage1') : t('userDemo.remarkMessage2')
-//       )
-//     }
-//   },
-//   {
-//     field: 'action',
-//     label: t('userDemo.action')
-//   }
-// ]
-
-// const loading = ref(true)
-
-// let tableDataList = ref<UserType[]>([])
-
-// const getTableList = async (params?: Params) => {
-//   const res = await getUserListApi({
-//     params: params || {
-//       pageIndex: 1,
-//       pageSize: 10
-//     }
-//   })
-//   // .catch(() => {})
-//   // .finally(() => {
-//   //   loading.value = false
-//   // })
-//   if (res) {
-//     tableDataList.value = res.data.list
-//     loading.value = false
-//   }
-// }
-
-// getTableList()
-
-// const actionFn = (data: TableSlotDefault) => {
-//   console.log(data)
-// }
-</script>
-
-<template>
-  <div>role</div>
-  <!-- <ContentWrap :title="t('userDemo.title')" :message="t('userDemo.message')">
-    <Table :columns="columns" :data="tableDataList" :loading="loading" :selection="false">
-      <template #action="data">
-        <ElButton type="primary" @click="actionFn(data as TableSlotDefault)">
-          {{ t('tableDemo.action') }}
-        </ElButton>
-      </template>
-    </Table>
-  </ContentWrap> -->
-</template>

+ 0 - 355
src/views/Authorization/User.vue

@@ -1,355 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Table } from '@/components/Table'
-import { ref, unref, nextTick, watch, reactive } from 'vue'
-import { ElButton, ElTree, ElInput, ElDivider } from 'element-plus'
-import { getDepartmentApi, getUserByIdApi, saveUserApi, deleteUserByIdApi } from '@/api/department'
-import type { DepartmentItem, DepartmentUserItem } from '@/api/department/types'
-import { useTable } from '@/hooks/web/useTable'
-import { Search } from '@/components/Search'
-import Write from './components/Write.vue'
-import Detail from './components/Detail.vue'
-import { Dialog } from '@/components/Dialog'
-import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
-
-const { t } = useI18n()
-
-const { tableRegister, tableState, tableMethods } = useTable({
-  fetchDataApi: async () => {
-    const { pageSize, currentPage } = tableState
-    const res = await getUserByIdApi({
-      id: unref(currentNodeKey),
-      pageIndex: unref(currentPage),
-      pageSize: unref(pageSize),
-      ...unref(searchParams)
-    })
-    return {
-      list: res.data.list || [],
-      total: res.data.total || 0
-    }
-  },
-  fetchDelApi: async () => {
-    const res = await deleteUserByIdApi(unref(ids))
-    return !!res
-  }
-})
-const { total, loading, dataList, pageSize, currentPage } = tableState
-const { getList, getElTableExpose, delList } = tableMethods
-
-const crudSchemas = reactive<CrudSchema[]>([
-  {
-    field: 'selection',
-    search: {
-      hidden: true
-    },
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      type: 'selection'
-    }
-  },
-  {
-    field: 'index',
-    label: t('userDemo.index'),
-    form: {
-      hidden: true
-    },
-    search: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      type: 'index'
-    }
-  },
-  {
-    field: 'username',
-    label: t('userDemo.username')
-  },
-  {
-    field: 'account',
-    label: t('userDemo.account')
-  },
-  {
-    field: 'department.id',
-    label: t('userDemo.department'),
-    detail: {
-      slots: {
-        default: (data: DepartmentUserItem) => {
-          return <>{data.department.departmentName}</>
-        }
-      }
-    },
-    search: {
-      hidden: true
-    },
-    form: {
-      component: 'TreeSelect',
-      componentProps: {
-        nodeKey: 'id',
-        props: {
-          label: 'departmentName'
-        }
-      },
-      optionApi: async () => {
-        const res = await getDepartmentApi()
-        return res.data.list
-      }
-    },
-    table: {
-      type: 'index'
-    }
-  },
-  {
-    field: 'role',
-    label: t('userDemo.role'),
-    search: {
-      hidden: true
-    }
-  },
-  {
-    field: 'email',
-    label: t('userDemo.email'),
-    form: {
-      component: 'Input'
-    },
-    search: {
-      hidden: true
-    }
-  },
-  {
-    field: 'createTime',
-    label: t('userDemo.createTime'),
-    form: {
-      component: 'Input'
-    },
-    search: {
-      hidden: true
-    }
-  },
-  {
-    field: 'action',
-    label: t('userDemo.action'),
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    search: {
-      hidden: true
-    },
-    table: {
-      width: 240,
-      slots: {
-        default: (data: any) => {
-          const row = data[0].row as DepartmentUserItem
-          return (
-            <>
-              <ElButton type="primary" onClick={() => action(row, 'edit')}>
-                {t('exampleDemo.edit')}
-              </ElButton>
-              <ElButton type="success" onClick={() => action(row, 'detail')}>
-                {t('exampleDemo.detail')}
-              </ElButton>
-              <ElButton type="danger" onClick={() => delData(row)}>
-                {t('exampleDemo.del')}
-              </ElButton>
-            </>
-          )
-        }
-      }
-    }
-  }
-])
-
-const { allSchemas } = useCrudSchemas(crudSchemas)
-
-const searchParams = ref({})
-const setSearchParams = (params: any) => {
-  currentPage.value = 1
-  searchParams.value = params
-  getList()
-}
-
-const treeEl = ref<typeof ElTree>()
-
-const currentNodeKey = ref('')
-const departmentList = ref<DepartmentItem[]>([])
-const fetchDepartment = async () => {
-  const res = await getDepartmentApi()
-  departmentList.value = res.data.list
-  currentNodeKey.value =
-    (res.data.list[0] && res.data.list[0]?.children && res.data.list[0].children[0].id) || ''
-  await nextTick()
-  unref(treeEl)?.setCurrentKey(currentNodeKey.value)
-}
-fetchDepartment()
-
-const currentDepartment = ref('')
-watch(
-  () => currentDepartment.value,
-  (val) => {
-    unref(treeEl)!.filter(val)
-  }
-)
-
-const currentChange = (data: DepartmentItem) => {
-  if (data.children) return
-  currentNodeKey.value = data.id
-  currentPage.value = 1
-  getList()
-}
-
-const filterNode = (value: string, data: DepartmentItem) => {
-  if (!value) return true
-  return data.departmentName.includes(value)
-}
-
-const dialogVisible = ref(false)
-const dialogTitle = ref('')
-
-const currentRow = ref<DepartmentUserItem>()
-const actionType = ref('')
-
-const AddAction = () => {
-  dialogTitle.value = t('exampleDemo.add')
-  currentRow.value = undefined
-  dialogVisible.value = true
-  actionType.value = ''
-}
-
-const delLoading = ref(false)
-const ids = ref<string[]>([])
-
-const delData = async (row?: DepartmentUserItem) => {
-  const elTableExpose = await getElTableExpose()
-  ids.value = row
-    ? [row.id]
-    : elTableExpose?.getSelectionRows().map((v: DepartmentUserItem) => v.id) || []
-  delLoading.value = true
-
-  await delList(unref(ids).length).finally(() => {
-    delLoading.value = false
-  })
-}
-
-const action = (row: DepartmentUserItem, type: string) => {
-  dialogTitle.value = t(type === 'edit' ? 'exampleDemo.edit' : 'exampleDemo.detail')
-  actionType.value = type
-  currentRow.value = { ...row, department: unref(treeEl)?.getCurrentNode() || {} }
-  dialogVisible.value = true
-}
-
-const writeRef = ref<ComponentRef<typeof Write>>()
-
-const saveLoading = ref(false)
-
-const save = async () => {
-  const write = unref(writeRef)
-  const formData = await write?.submit()
-  if (formData) {
-    saveLoading.value = true
-    try {
-      const res = await saveUserApi(formData)
-      if (res) {
-        currentPage.value = 1
-        getList()
-      }
-    } catch (error) {
-      console.log(error)
-    } finally {
-      saveLoading.value = false
-      dialogVisible.value = false
-    }
-  }
-}
-</script>
-
-<template>
-  <div class="flex w-100% h-100%">
-    <ContentWrap class="flex-1">
-      <div class="flex justify-center items-center">
-        <div class="flex-1">{{ t('userDemo.departmentList') }}</div>
-        <ElInput
-          v-model="currentDepartment"
-          class="flex-[2]"
-          :placeholder="t('userDemo.searchDepartment')"
-          clearable
-        />
-      </div>
-      <ElDivider />
-      <ElTree
-        ref="treeEl"
-        :data="departmentList"
-        default-expand-all
-        node-key="id"
-        :current-node-key="currentNodeKey"
-        :props="{
-          label: 'departmentName'
-        }"
-        :filter-node-method="filterNode"
-        @current-change="currentChange"
-      />
-    </ContentWrap>
-    <ContentWrap class="flex-[3] ml-20px">
-      <Search
-        :schema="allSchemas.searchSchema"
-        @reset="setSearchParams"
-        @search="setSearchParams"
-      />
-
-      <div class="mb-10px">
-        <ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
-        <ElButton :loading="delLoading" type="danger" @click="delData()">
-          {{ t('exampleDemo.del') }}
-        </ElButton>
-      </div>
-      <Table
-        v-model:current-page="currentPage"
-        v-model:page-size="pageSize"
-        :columns="allSchemas.tableColumns"
-        :data="dataList"
-        :loading="loading"
-        @register="tableRegister"
-        :pagination="{
-          total
-        }"
-      />
-    </ContentWrap>
-
-    <Dialog v-model="dialogVisible" :title="dialogTitle">
-      <Write
-        v-if="actionType !== 'detail'"
-        ref="writeRef"
-        :form-schema="allSchemas.formSchema"
-        :current-row="currentRow"
-      />
-
-      <Detail
-        v-if="actionType === 'detail'"
-        :detail-schema="allSchemas.detailSchema"
-        :current-row="currentRow"
-      />
-
-      <template #footer>
-        <ElButton
-          v-if="actionType !== 'detail'"
-          type="primary"
-          :loading="saveLoading"
-          @click="save"
-        >
-          {{ t('exampleDemo.save') }}
-        </ElButton>
-        <ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
-      </template>
-    </Dialog>
-  </div>
-</template>

+ 0 - 20
src/views/Authorization/components/Detail.vue

@@ -1,20 +0,0 @@
-<script setup lang="ts">
-import { PropType } from 'vue'
-import { DepartmentUserItem } from '@/api/department/types'
-import { Descriptions, DescriptionsSchema } from '@/components/Descriptions'
-
-defineProps({
-  currentRow: {
-    type: Object as PropType<DepartmentUserItem>,
-    default: () => undefined
-  },
-  detailSchema: {
-    type: Array as PropType<DescriptionsSchema[]>,
-    default: () => []
-  }
-})
-</script>
-
-<template>
-  <Descriptions :schema="detailSchema" :data="currentRow || {}" />
-</template>

+ 0 - 62
src/views/Authorization/components/Write.vue

@@ -1,62 +0,0 @@
-<script setup lang="ts">
-import { Form, FormSchema } from '@/components/Form'
-import { useForm } from '@/hooks/web/useForm'
-import { PropType, reactive, watch } from 'vue'
-import { DepartmentUserItem } from '@/api/department/types'
-import { useValidator } from '@/hooks/web/useValidator'
-
-const { required } = useValidator()
-
-const props = defineProps({
-  currentRow: {
-    type: Object as PropType<DepartmentUserItem>,
-    default: () => undefined
-  },
-  formSchema: {
-    type: Array as PropType<FormSchema[]>,
-    default: () => []
-  }
-})
-
-const rules = reactive({
-  username: [required()],
-  account: [required()],
-  role: [required()],
-  email: [required()],
-  createTime: [required()]
-})
-
-const { formRegister, formMethods } = useForm()
-const { setValues, getFormData, getElFormExpose } = formMethods
-
-const submit = async () => {
-  const elForm = await getElFormExpose()
-  const valid = await elForm?.validate().catch((err) => {
-    console.log(err)
-  })
-  if (valid) {
-    const formData = getFormData()
-    return formData
-  }
-}
-
-watch(
-  () => props.currentRow,
-  (currentRow) => {
-    if (!currentRow) return
-    setValues(currentRow)
-  },
-  {
-    deep: true,
-    immediate: true
-  }
-)
-
-defineExpose({
-  submit
-})
-</script>
-
-<template>
-  <Form :rules="rules" @register="formRegister" :schema="formSchema" />
-</template>

+ 0 - 100
src/views/Components/CountTo.vue

@@ -1,100 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { CountTo } from '@/components/CountTo'
-import { ElRow, ElCol, ElInputNumber, ElInput, ElButton } from 'element-plus'
-import { ref, unref } from 'vue'
-
-const { t } = useI18n()
-
-const countRef = ref<ComponentRef<typeof CountTo>>()
-
-const startVal = ref(0)
-
-const endVal = ref(1314512)
-
-const duration = ref(3000)
-
-const decimals = ref(0)
-
-const separator = ref(',')
-
-const prefix = ref('¥ ')
-
-const suffix = ref(' rmb')
-
-const autoplay = ref(false)
-
-const start = () => {
-  unref(countRef)?.start()
-}
-
-const pauseResume = () => {
-  unref(countRef)?.pauseResume()
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('countToDemo.countTo')" :message="t('countToDemo.countToDes')">
-    <div class="text-center mb-40px">
-      <CountTo
-        ref="countRef"
-        :start-val="startVal"
-        :end-val="endVal"
-        :duration="duration"
-        :decimals="decimals"
-        :separator="separator"
-        :prefix="prefix"
-        :suffix="suffix"
-        :autoplay="autoplay"
-        class="text-30px font-bold text-[var(--el-color-primary)]"
-      />
-    </div>
-    <ElRow :gutter="20" justify="space-between">
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.startVal') }}:</span>
-          <ElInputNumber v-model="startVal" :min="0" />
-        </div>
-      </ElCol>
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.endVal') }}:</span>
-          <ElInputNumber v-model="endVal" :min="1" />
-        </div>
-      </ElCol>
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.duration') }}:</span>
-          <ElInputNumber v-model="duration" :min="1000" />
-        </div>
-      </ElCol>
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.separator') }}:</span>
-          <ElInput v-model="separator" />
-        </div>
-      </ElCol>
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.prefix') }}:</span>
-          <ElInput v-model="prefix" />
-        </div>
-      </ElCol>
-      <ElCol :xl="8" :lg="8" :md="12" :sm="24" :xs="24">
-        <div class="flex mb-20px items-center">
-          <span class="min-w-90px text-right">{{ t('countToDemo.suffix') }}:</span>
-          <ElInput v-model="suffix" />
-        </div>
-      </ElCol>
-      <ElCol :span="24">
-        <div class="text-center">
-          <ElButton type="primary" @click="start">{{ t('countToDemo.start') }}</ElButton>
-          <ElButton @click="pauseResume">
-            {{ t('countToDemo.pause') }}/{{ t('countToDemo.resume') }}
-          </ElButton>
-        </div>
-      </ElCol>
-    </ElRow>
-  </ContentWrap>
-</template>

+ 0 - 190
src/views/Components/Descriptions.vue

@@ -1,190 +0,0 @@
-<script setup lang="tsx">
-import { Descriptions } from '@/components/Descriptions'
-import { useI18n } from '@/hooks/web/useI18n'
-import { reactive } from 'vue'
-import { Form } from '@/components/Form'
-import { ElFormItem, ElInput, ElButton } from 'element-plus'
-import { useValidator } from '@/hooks/web/useValidator'
-import { useForm } from '@/hooks/web/useForm'
-import { DescriptionsSchema } from '@/components/Descriptions'
-
-const { required } = useValidator()
-
-const { t } = useI18n()
-
-const data = reactive({
-  username: 'chenkl',
-  nickName: '梦似花落。',
-  age: 26,
-  phone: '13655971xxxx',
-  email: '502431556@qq.com',
-  addr: '这是一个很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的地址',
-  sex: '男',
-  certy: '3505831994xxxxxxxx'
-})
-
-const schema = reactive<DescriptionsSchema[]>([
-  {
-    field: 'username',
-    label: t('descriptionsDemo.username')
-  },
-  {
-    field: 'nickName',
-    label: t('descriptionsDemo.nickName')
-  },
-  {
-    field: 'phone',
-    label: t('descriptionsDemo.phone')
-  },
-  {
-    field: 'email',
-    label: t('descriptionsDemo.email')
-  },
-  {
-    field: 'addr',
-    label: t('descriptionsDemo.addr')
-  }
-])
-
-const schema2 = reactive<DescriptionsSchema[]>([
-  {
-    field: 'username',
-    label: t('descriptionsDemo.username'),
-    slots: {
-      label: (row) => {
-        return <span class="is-required--item">{row.label}</span>
-      },
-      default: () => {
-        return (
-          <ElFormItem prop="username">
-            <ElInput v-model={form.username} />
-          </ElFormItem>
-        )
-      }
-    }
-  },
-  {
-    field: 'nickName',
-    label: t('descriptionsDemo.nickName'),
-    slots: {
-      label: (row) => {
-        return <span class="is-required--item">{row.label}</span>
-      },
-      default: () => {
-        return (
-          <ElFormItem prop="nickName">
-            <ElInput v-model={form.nickName} />
-          </ElFormItem>
-        )
-      }
-    }
-  },
-  {
-    field: 'phone',
-    label: t('descriptionsDemo.phone'),
-    slots: {
-      label: (row) => {
-        return <span class="is-required--item">{row.label}</span>
-      },
-      default: () => {
-        return (
-          <ElFormItem prop="phone">
-            <ElInput v-model={form.phone} />
-          </ElFormItem>
-        )
-      }
-    }
-  },
-  {
-    field: 'email',
-    label: t('descriptionsDemo.email'),
-    slots: {
-      label: (row) => {
-        return <span class="is-required--item">{row.label}</span>
-      },
-      default: () => {
-        return (
-          <ElFormItem prop="email">
-            <ElInput v-model={form.email} />
-          </ElFormItem>
-        )
-      }
-    }
-  },
-  {
-    field: 'addr',
-    label: t('descriptionsDemo.addr'),
-    slots: {
-      label: (row) => {
-        return <span class="is-required--item">{row.label}</span>
-      },
-      default: () => {
-        return (
-          <ElFormItem prop="addr">
-            <ElInput v-model={form.addr} />
-          </ElFormItem>
-        )
-      }
-    }
-  }
-])
-
-const form = reactive({
-  username: '',
-  nickName: '',
-  phone: '',
-  email: '',
-  addr: ''
-})
-
-const rules = reactive({
-  username: [required()],
-  nickName: [required()],
-  phone: [required()],
-  email: [required()],
-  addr: [required()]
-})
-
-const { formRegister, formMethods } = useForm()
-const { getElFormExpose } = formMethods
-
-const formValidation = async () => {
-  const elFormExpose = await getElFormExpose()
-  elFormExpose?.validate((isValid) => {
-    console.log(isValid)
-  })
-}
-</script>
-
-<template>
-  <Descriptions
-    :title="t('descriptionsDemo.descriptions')"
-    :message="t('descriptionsDemo.descriptionsDes')"
-    :data="data"
-    :schema="schema"
-  />
-
-  <Form is-custom :model="form" :rules="rules" @register="formRegister">
-    <Descriptions
-      :title="t('descriptionsDemo.form')"
-      :data="data"
-      :schema="schema2"
-      class="mt-20px"
-    />
-    <div class="text-center mt-10px">
-      <ElButton @click="formValidation"> {{ t('formDemo.formValidation') }} </ElButton>
-    </div>
-  </Form>
-</template>
-
-<style lang="less" scoped>
-:deep(.is-required--item) {
-  position: relative;
-
-  &::before {
-    margin-right: 4px;
-    color: var(--el-color-danger);
-    content: '*';
-  }
-}
-</style>

+ 0 - 131
src/views/Components/Dialog.vue

@@ -1,131 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { Dialog } from '@/components/Dialog'
-import { ElButton } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ref, reactive } from 'vue'
-import { Form, FormSchema } from '@/components/Form'
-import { useValidator } from '@/hooks/web/useValidator'
-import { getDictOneApi } from '@/api/common'
-import { useForm } from '@/hooks/web/useForm'
-
-const { required } = useValidator()
-
-const { t } = useI18n()
-
-const dialogVisible = ref(false)
-
-const dialogVisible2 = ref(false)
-
-const { formRegister, formMethods } = useForm()
-const { getElFormExpose } = formMethods
-
-const schema = reactive<FormSchema[]>([
-  {
-    field: 'field1',
-    label: t('formDemo.input'),
-    component: 'Input',
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'field2',
-    label: t('formDemo.select'),
-    component: 'Select',
-    // componentProps: {
-    //   options: []
-    // },
-    optionApi: async () => {
-      const res = await getDictOneApi()
-      return res.data
-    }
-  },
-  {
-    field: 'field3',
-    label: t('formDemo.radio'),
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field4',
-    label: t('formDemo.checkbox'),
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field5',
-    component: 'DatePicker',
-    label: t('formDemo.datePicker'),
-    componentProps: {
-      type: 'date'
-    }
-  },
-  {
-    field: 'field6',
-    component: 'TimeSelect',
-    label: t('formDemo.timeSelect')
-  }
-])
-
-const formSubmit = async () => {
-  const elFormExpose = await getElFormExpose()
-  elFormExpose?.validate((valid) => {
-    if (valid) {
-      console.log('submit success')
-    } else {
-      console.log('submit fail')
-    }
-  })
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('dialogDemo.dialog')" :message="t('dialogDemo.dialogDes')">
-    <ElButton type="primary" @click="dialogVisible = !dialogVisible">
-      {{ t('dialogDemo.open') }}
-    </ElButton>
-
-    <ElButton type="primary" @click="dialogVisible2 = !dialogVisible2">
-      {{ t('dialogDemo.combineWithForm') }}
-    </ElButton>
-
-    <Dialog v-model="dialogVisible" :title="t('dialogDemo.dialog')">
-      <div v-for="v in 10000" :key="v">{{ v }}</div>
-      <template #footer>
-        <ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
-      </template>
-    </Dialog>
-
-    <Dialog v-model="dialogVisible2" :title="t('dialogDemo.dialog')">
-      <Form :schema="schema" @register="formRegister" />
-      <template #footer>
-        <ElButton type="primary" @click="formSubmit">{{ t('dialogDemo.submit') }}</ElButton>
-        <ElButton @click="dialogVisible2 = false">{{ t('dialogDemo.close') }}</ElButton>
-      </template>
-    </Dialog>
-  </ContentWrap>
-</template>

+ 0 - 36
src/views/Components/Echart.vue

@@ -1,36 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { pieOptions, barOptions, lineOptions, wordOptions } from '@/views/Dashboard/echarts-data'
-import { Echart } from '@/components/Echart'
-import { ElRow, ElCol, ElCard } from 'element-plus'
-
-const { t } = useI18n()
-</script>
-
-<template>
-  <ContentWrap :title="t('echartDemo.echart')" :message="t('echartDemo.echartDes')">
-    <ElRow :gutter="20" justify="space-between">
-      <ElCol :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-20px">
-          <Echart :options="pieOptions" :height="300" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-20px">
-          <Echart :options="barOptions" :height="300" />
-        </ElCard>
-      </ElCol>
-      <ElCol :span="24">
-        <ElCard shadow="hover" class="mb-20px">
-          <Echart :options="lineOptions" :height="350" />
-        </ElCard>
-      </ElCol>
-      <ElCol :span="24">
-        <ElCard shadow="hover" class="mb-20px">
-          <Echart :options="wordOptions as any" :height="300" />
-        </ElCard>
-      </ElCol>
-    </ElRow>
-  </ContentWrap>
-</template>

+ 0 - 32
src/views/Components/Editor/Editor.vue

@@ -1,32 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { Editor, EditorExpose } from '@/components/Editor'
-import { useI18n } from '@/hooks/web/useI18n'
-import { IDomEditor } from '@wangeditor/editor'
-import { ref, onMounted, unref } from 'vue'
-
-const { t } = useI18n()
-
-const change = (editor: IDomEditor) => {
-  console.log(editor.getHtml())
-}
-
-const editorRef = ref<typeof Editor & EditorExpose>()
-
-const defaultHtml = ref('')
-
-onMounted(async () => {
-  const editor = await unref(editorRef)?.getEditorRef()
-  console.log(editor)
-})
-
-setTimeout(() => {
-  defaultHtml.value = '<p>hello <strong>world</strong></p>'
-}, 3000)
-</script>
-
-<template>
-  <ContentWrap :title="t('richText.richText')" :message="t('richText.richTextDes')">
-    <Editor v-model="defaultHtml" ref="editorRef" @change="change" />
-  </ContentWrap>
-</template>

+ 0 - 1825
src/views/Components/Form/DefaultForm.vue

@@ -1,1825 +0,0 @@
-<script setup lang="tsx">
-import { Form } from '@/components/Form'
-import { reactive, ref, onMounted, computed } from 'vue'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ContentWrap } from '@/components/ContentWrap'
-import { useAppStore } from '@/store/modules/app'
-import { SelectOption, RadioOption, CheckboxOption, FormSchema } from '@/components/Form'
-import {
-  ElOption,
-  ElOptionGroup,
-  ElButton,
-  ElRadio,
-  ElRadioButton,
-  ElCheckbox,
-  ElCheckboxButton,
-  ElInput,
-  ElMessage,
-  ElMessageBox,
-  ElIcon
-} from 'element-plus'
-import { getDictOneApi } from '@/api/common'
-import { Icon } from '@/components/Icon'
-
-const appStore = useAppStore()
-
-const { t } = useI18n()
-
-const isMobile = computed(() => appStore.getMobile)
-
-const restaurants = ref<Recordable[]>([])
-const querySearch = (queryString: string, cb: Fn) => {
-  const results = queryString
-    ? restaurants.value.filter(createFilter(queryString))
-    : restaurants.value
-  // call callback function to return suggestions
-  cb(results)
-}
-let timeout: NodeJS.Timeout
-const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
-  const results = queryString
-    ? restaurants.value.filter(createFilter(queryString))
-    : restaurants.value
-
-  clearTimeout(timeout)
-  timeout = setTimeout(() => {
-    cb(results)
-  }, 3000 * Math.random())
-}
-const createFilter = (queryString: string) => {
-  return (restaurant: Recordable) => {
-    return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
-  }
-}
-const loadAll = () => {
-  return [
-    { value: 'vue', link: 'https://github.com/vuejs/vue' },
-    { value: 'element', link: 'https://github.com/ElemeFE/element' },
-    { value: 'cooking', link: 'https://github.com/ElemeFE/cooking' },
-    { value: 'mint-ui', link: 'https://github.com/ElemeFE/mint-ui' },
-    { value: 'vuex', link: 'https://github.com/vuejs/vuex' },
-    { value: 'vue-router', link: 'https://github.com/vuejs/vue-router' },
-    { value: 'babel', link: 'https://github.com/babel/babel' }
-  ]
-}
-const handleSelect = (item: Recordable) => {
-  console.log(item)
-}
-onMounted(() => {
-  restaurants.value = loadAll()
-})
-
-const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
-const options = ref(
-  Array.from({ length: 1000 }).map((_, idx) => ({
-    value: `Option ${idx + 1}`,
-    label: `${initials[idx % 10]}${idx}`
-  }))
-)
-const options2 = ref(
-  Array.from({ length: 10 }).map((_, idx) => {
-    const label = idx + 1
-    return {
-      value: `Group ${label}`,
-      label: `Group ${label}`,
-      options: Array.from({ length: 10 }).map((_, idx) => ({
-        value: `Option ${idx + 1 + 10 * label}`,
-        label: `${initials[idx % 10]}${idx + 1 + 10 * label}`
-      }))
-    }
-  })
-)
-
-const options3 = [
-  {
-    value: 'guide',
-    label: 'Guide',
-    children: [
-      {
-        value: 'disciplines',
-        label: 'Disciplines',
-        children: [
-          {
-            value: 'consistency',
-            label: 'Consistency'
-          },
-          {
-            value: 'feedback',
-            label: 'Feedback'
-          },
-          {
-            value: 'efficiency',
-            label: 'Efficiency'
-          },
-          {
-            value: 'controllability',
-            label: 'Controllability'
-          }
-        ]
-      },
-      {
-        value: 'navigation',
-        label: 'Navigation',
-        children: [
-          {
-            value: 'side nav',
-            label: 'Side Navigation'
-          },
-          {
-            value: 'top nav',
-            label: 'Top Navigation'
-          }
-        ]
-      }
-    ]
-  },
-  {
-    value: 'component',
-    label: 'Component',
-    children: [
-      {
-        value: 'basic',
-        label: 'Basic',
-        children: [
-          {
-            value: 'layout',
-            label: 'Layout'
-          },
-          {
-            value: 'color',
-            label: 'Color'
-          },
-          {
-            value: 'typography',
-            label: 'Typography'
-          },
-          {
-            value: 'icon',
-            label: 'Icon'
-          },
-          {
-            value: 'button',
-            label: 'Button'
-          }
-        ]
-      },
-      {
-        value: 'form',
-        label: 'Form',
-        children: [
-          {
-            value: 'radio',
-            label: 'Radio'
-          },
-          {
-            value: 'checkbox',
-            label: 'Checkbox'
-          },
-          {
-            value: 'input',
-            label: 'Input'
-          },
-          {
-            value: 'input-number',
-            label: 'InputNumber'
-          },
-          {
-            value: 'select',
-            label: 'Select'
-          },
-          {
-            value: 'cascader',
-            label: 'Cascader'
-          },
-          {
-            value: 'switch',
-            label: 'Switch'
-          },
-          {
-            value: 'slider',
-            label: 'Slider'
-          },
-          {
-            value: 'time-picker',
-            label: 'TimePicker'
-          },
-          {
-            value: 'date-picker',
-            label: 'DatePicker'
-          },
-          {
-            value: 'datetime-picker',
-            label: 'DateTimePicker'
-          },
-          {
-            value: 'upload',
-            label: 'Upload'
-          },
-          {
-            value: 'rate',
-            label: 'Rate'
-          },
-          {
-            value: 'form',
-            label: 'Form'
-          }
-        ]
-      },
-      {
-        value: 'data',
-        label: 'Data',
-        children: [
-          {
-            value: 'table',
-            label: 'Table'
-          },
-          {
-            value: 'tag',
-            label: 'Tag'
-          },
-          {
-            value: 'progress',
-            label: 'Progress'
-          },
-          {
-            value: 'tree',
-            label: 'Tree'
-          },
-          {
-            value: 'pagination',
-            label: 'Pagination'
-          },
-          {
-            value: 'badge',
-            label: 'Badge'
-          }
-        ]
-      },
-      {
-        value: 'notice',
-        label: 'Notice',
-        children: [
-          {
-            value: 'alert',
-            label: 'Alert'
-          },
-          {
-            value: 'loading',
-            label: 'Loading'
-          },
-          {
-            value: 'message',
-            label: 'Message'
-          },
-          {
-            value: 'message-box',
-            label: 'MessageBox'
-          },
-          {
-            value: 'notification',
-            label: 'Notification'
-          }
-        ]
-      },
-      {
-        value: 'navigation',
-        label: 'Navigation',
-        children: [
-          {
-            value: 'menu',
-            label: 'Menu'
-          },
-          {
-            value: 'tabs',
-            label: 'Tabs'
-          },
-          {
-            value: 'breadcrumb',
-            label: 'Breadcrumb'
-          },
-          {
-            value: 'dropdown',
-            label: 'Dropdown'
-          },
-          {
-            value: 'steps',
-            label: 'Steps'
-          }
-        ]
-      },
-      {
-        value: 'others',
-        label: 'Others',
-        children: [
-          {
-            value: 'dialog',
-            label: 'Dialog'
-          },
-          {
-            value: 'tooltip',
-            label: 'Tooltip'
-          },
-          {
-            value: 'popover',
-            label: 'Popover'
-          },
-          {
-            value: 'card',
-            label: 'Card'
-          },
-          {
-            value: 'carousel',
-            label: 'Carousel'
-          },
-          {
-            value: 'collapse',
-            label: 'Collapse'
-          }
-        ]
-      }
-    ]
-  }
-]
-
-const generateData = () => {
-  const data: {
-    value: number
-    desc: string
-    disabled: boolean
-  }[] = []
-  for (let i = 1; i <= 15; i++) {
-    data.push({
-      value: i,
-      desc: `Option ${i}`,
-      disabled: i % 4 === 0
-    })
-  }
-  return data
-}
-
-const holidays = [
-  '2021-10-01',
-  '2021-10-02',
-  '2021-10-03',
-  '2021-10-04',
-  '2021-10-05',
-  '2021-10-06',
-  '2021-10-07'
-]
-
-const isHoliday = ({ dayjs }) => {
-  return holidays.includes(dayjs.format('YYYY-MM-DD'))
-}
-
-const treeSelectData = [
-  {
-    value: '1',
-    label: 'Level one 1',
-    children: [
-      {
-        value: '1-1',
-        label: 'Level two 1-1',
-        children: [
-          {
-            value: '1-1-1',
-            label: 'Level three 1-1-1'
-          }
-        ]
-      }
-    ]
-  },
-  {
-    value: '2',
-    label: 'Level one 2',
-    children: [
-      {
-        value: '2-1',
-        label: 'Level two 2-1',
-        children: [
-          {
-            value: '2-1-1',
-            label: 'Level three 2-1-1'
-          }
-        ]
-      },
-      {
-        value: '2-2',
-        label: 'Level two 2-2',
-        children: [
-          {
-            value: '2-2-1',
-            label: 'Level three 2-2-1'
-          }
-        ]
-      }
-    ]
-  },
-  {
-    value: '3',
-    label: 'Level one 3',
-    children: [
-      {
-        value: '3-1',
-        label: 'Level two 3-1',
-        children: [
-          {
-            value: '3-1-1',
-            label: 'Level three 3-1-1'
-          }
-        ]
-      },
-      {
-        value: '3-2',
-        label: 'Level two 3-2',
-        children: [
-          {
-            value: '3-2-1',
-            label: 'Level three 3-2-1'
-          }
-        ]
-      }
-    ]
-  }
-]
-
-let id = 0
-
-const imageUrl = ref('')
-
-const schema = reactive<FormSchema[]>([
-  {
-    field: 'field1',
-    label: t('formDemo.input'),
-    component: 'Divider'
-  },
-  {
-    field: 'field2',
-    label: t('formDemo.default'),
-    component: 'Input',
-    componentProps: {
-      formatter: (value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','),
-      parser: (value) => value.replace(/\$\s?|(,*)/g, '')
-    }
-  },
-  {
-    field: 'field3',
-    label: `${t('formDemo.icon')}1`,
-    component: 'Input',
-    componentProps: {
-      suffixIcon: <Icon icon="ep:calendar" />,
-      prefixIcon: <Icon icon="ep:share" />
-    }
-  },
-  {
-    field: 'field4',
-    label: `${t('formDemo.icon')}2`,
-    component: 'Input',
-    componentProps: {
-      slots: {
-        suffix: () => {
-          return <Icon icon="ep:share" />
-        },
-        prefix: () => <Icon icon="ep:calendar" />
-      }
-    }
-  },
-  {
-    field: 'field5',
-    label: t('formDemo.mixed'),
-    component: 'Input',
-    componentProps: {
-      slots: {
-        prepend: () => <Icon icon="ep:calendar" />,
-        append: () => <Icon icon="ep:share" />
-      }
-    }
-  },
-  {
-    field: 'input-field7',
-    label: t('formDemo.password'),
-    component: 'Input',
-    componentProps: {
-      showPassword: true
-    }
-  },
-  {
-    field: 'field6',
-    label: t('formDemo.textarea'),
-    component: 'Input',
-    componentProps: {
-      type: 'textarea',
-      rows: 2
-    }
-  },
-  {
-    field: 'field7',
-    label: t('formDemo.autocomplete'),
-    component: 'Divider'
-  },
-  {
-    field: 'field8',
-    label: t('formDemo.default'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearch,
-      on: {
-        select: handleSelect
-      }
-    }
-  },
-  {
-    field: 'field9',
-    label: t('formDemo.slot'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearch,
-      on: {
-        select: handleSelect
-      },
-      slots: {
-        default: ({ item }) => {
-          return (
-            <>
-              <div class="value">{item?.value}</div>
-              <span class="link">{item?.link}</span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'autocomplete-field10',
-    label: t('formDemo.remoteSearch'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearchAsync,
-      on: {
-        select: handleSelect
-      }
-    }
-  },
-  {
-    field: 'field10',
-    component: 'Divider',
-    label: t('formDemo.inputNumber')
-  },
-  {
-    field: 'field11',
-    label: t('formDemo.default'),
-    component: 'InputNumber',
-    value: 0
-  },
-  {
-    field: 'field12',
-    label: t('formDemo.position'),
-    component: 'InputNumber',
-    componentProps: {
-      controlsPosition: 'right'
-    },
-    value: 10
-  },
-  {
-    field: 'field13',
-    label: t('formDemo.select'),
-    component: 'Divider'
-  },
-  {
-    field: 'field14',
-    label: t('formDemo.default'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          disabled: true,
-          label: 'option1',
-          value: '1'
-        },
-        {
-          label: 'option2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field15',
-    label: t('formDemo.slot'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'option1',
-          value: '1'
-        },
-        {
-          label: 'option2',
-          value: '2'
-        }
-      ],
-      slots: {
-        default: (options: SelectOption[]) => {
-          if (options.length) {
-            return options?.map((v) => {
-              return <ElOption key={v.value} label={v.label} value={v.value} />
-            })
-          } else {
-            return null
-          }
-        },
-        prefix: () => <Icon icon="ep:calendar" />
-      }
-    }
-  },
-  {
-    field: 'select-field18',
-    label: t('formDemo.optionSlot'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          value: 'Beijing',
-          label: 'Beijing'
-        },
-        {
-          value: 'Shanghai',
-          label: 'Shanghai'
-        },
-        {
-          value: 'Nanjing',
-          label: 'Nanjing'
-        },
-        {
-          value: 'Chengdu',
-          label: 'Chengdu'
-        },
-        {
-          value: 'Shenzhen',
-          label: 'Shenzhen'
-        },
-        {
-          value: 'Guangzhou',
-          label: 'Guangzhou'
-        }
-      ],
-      slots: {
-        optionDefault: (option: SelectOption) => {
-          return (
-            <>
-              <span style="float: left">{option.label}</span>
-              <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px;">
-                {option.value}
-              </span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field16',
-    label: t('formDemo.selectGroup'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'option1',
-          options: [
-            {
-              disabled: true,
-              label: 'option1-1',
-              value: '1-1'
-            },
-            {
-              label: 'option1-2',
-              value: '1-2'
-            }
-          ]
-        },
-        {
-          label: 'option2',
-          options: [
-            {
-              label: 'option2-1',
-              value: '2-1'
-            },
-            {
-              label: 'option2-2',
-              value: '2-2'
-            }
-          ]
-        }
-      ]
-    }
-  },
-  {
-    field: 'field17',
-    label: `${t('formDemo.selectGroup')} ${t('formDemo.slot')}`,
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'option1',
-          options: [
-            {
-              label: 'option1-1',
-              value: '1-1'
-            },
-            {
-              label: 'option1-2',
-              value: '1-2'
-            }
-          ]
-        },
-        {
-          label: 'option2',
-          options: [
-            {
-              label: 'option2-1',
-              value: '2-1'
-            },
-            {
-              label: 'option2-2',
-              value: '2-2'
-            }
-          ]
-        }
-      ],
-      slots: {
-        optionGroupDefault: (option: SelectOption) => {
-          return (
-            <ElOptionGroup key={option.label} label={`${option.label} ${option.label}`}>
-              {option?.options?.map((v) => {
-                return <ElOption key={v.value} label={v.label} value={v.value} />
-              })}
-            </ElOptionGroup>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field18',
-    label: `${t('formDemo.selectV2')}`,
-    component: 'Divider'
-  },
-  {
-    field: 'field19',
-    label: t('formDemo.default'),
-    component: 'SelectV2',
-    componentProps: {
-      value: undefined,
-      options: options.value
-    }
-  },
-  {
-    field: 'field20',
-    label: t('formDemo.slot'),
-    component: 'SelectV2',
-    componentProps: {
-      options: options.value,
-      slots: {
-        default: (option: SelectOption) => {
-          return (
-            <>
-              <span style="margin-right: 8px">{option?.label}</span>
-              <span style="color: var(--el-text-color-secondary); font-size: 13px">
-                {option?.value}
-              </span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field21',
-    label: t('formDemo.selectGroup'),
-    component: 'SelectV2',
-    componentProps: {
-      options: options2.value
-    }
-  },
-  {
-    field: 'field22',
-    label: `${t('formDemo.selectGroup')} ${t('formDemo.slot')}`,
-    component: 'SelectV2',
-    componentProps: {
-      options: options2.value,
-      slots: {
-        default: (option: SelectOption) => {
-          return (
-            <>
-              <span style="margin-right: 8px">{option?.label}</span>
-              <span style="color: var(--el-text-color-secondary); font-size: 13px">
-                {option?.value}
-              </span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field23',
-    label: t('formDemo.cascader'),
-    component: 'Divider'
-  },
-  {
-    field: 'field24',
-    label: t('formDemo.default'),
-    component: 'Cascader',
-    componentProps: {
-      options: options3,
-      props: {
-        multiple: true
-      }
-    }
-  },
-  {
-    field: 'field25',
-    label: t('formDemo.slot'),
-    component: 'Cascader',
-    componentProps: {
-      options: options3,
-      slots: {
-        default: ({ data, node }) => {
-          return (
-            <>
-              <span>{data.label}</span>
-              {!node.isLeaf ? <span> ({data.children.length}) </span> : null}
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field26',
-    label: t('formDemo.switch'),
-    component: 'Divider'
-  },
-  {
-    field: 'field27',
-    label: t('formDemo.default'),
-    component: 'Switch',
-    value: false
-  },
-  {
-    field: 'field28',
-    label: t('formDemo.icon'),
-    component: 'Switch',
-    value: false,
-    componentProps: {
-      activeIcon: <Icon icon="ep:check" />,
-      inactiveIcon: <Icon icon="ep:close" />
-    }
-  },
-  {
-    field: 'field29',
-    label: t('formDemo.rate'),
-    component: 'Divider'
-  },
-  {
-    field: 'field30',
-    label: t('formDemo.default'),
-    component: 'Rate',
-    value: 0
-  },
-  {
-    field: 'field31',
-    label: t('formDemo.icon'),
-    component: 'Rate',
-    value: null,
-    componentProps: {
-      voidIcon: <Icon icon="ep:chat-round" />,
-      icons: [
-        <Icon icon="ep:chat-round" />,
-        <Icon icon="ep:chat-line-round" />,
-        <Icon icon="ep:chat-dot-round" />
-      ]
-    }
-  },
-  {
-    field: 'field32',
-    label: t('formDemo.colorPicker'),
-    component: 'Divider'
-  },
-  {
-    field: 'field33',
-    label: t('formDemo.default'),
-    component: 'ColorPicker'
-  },
-  {
-    field: 'field34',
-    label: t('formDemo.transfer'),
-    component: 'Divider'
-  },
-  {
-    field: 'field35',
-    label: t('formDemo.default'),
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc'
-      },
-      data: generateData()
-    },
-    value: [],
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field36',
-    label: t('formDemo.slot'),
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc'
-      },
-      filterable: true,
-      leftDefaultChecked: [2, 3],
-      rightDefaultChecked: [1],
-      titles: ['Source', 'Target'],
-      buttonTexts: ['To Left', 'To Right'],
-      format: {
-        noChecked: '${total}',
-        hasChecked: '${checked}/${total}'
-      },
-      data: generateData(),
-      slots: {
-        default: ({ option }) => {
-          return (
-            <span>
-              {option.value} - {option.desc}
-            </span>
-          )
-        },
-        leftFooter: () => {
-          return (
-            <ElButton class="transfer-footer" size="small">
-              Operation
-            </ElButton>
-          )
-        },
-        rightFooter: () => {
-          return (
-            <ElButton class="transfer-footer" size="small">
-              Operation
-            </ElButton>
-          )
-        }
-      }
-    },
-    value: [1],
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field37',
-    label: `${t('formDemo.render')}`,
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc',
-        disabled: 'disabled'
-      },
-      leftDefaultChecked: [2, 3],
-      rightDefaultChecked: [1],
-      data: generateData(),
-      renderContent: (h, option) => {
-        return h('span', null, `${option.value} - ${option.desc}`)
-      }
-    },
-    value: [1],
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field38',
-    label: t('formDemo.radio'),
-    component: 'Divider'
-  },
-  {
-    field: 'field39-2',
-    label: t('formDemo.radioGroup'),
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          // disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field39-3',
-    label: `${t('formDemo.radioGroup')} ${t('formDemo.slot')}`,
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          // disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ],
-      slots: {
-        default: (options: RadioOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElRadio label={v.value}>
-                {v.label}({v.value})
-              </ElRadio>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field40',
-    label: t('formDemo.button'),
-    component: 'RadioButton',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field40-1',
-    label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
-    component: 'RadioButton',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ],
-      slots: {
-        default: (options: RadioOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElRadioButton label={v.value}>
-                {v.label}({v.value})
-              </ElRadioButton>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field41',
-    label: t('formDemo.checkbox'),
-    component: 'Divider'
-  },
-  {
-    field: 'field42-2',
-    label: t('formDemo.checkboxGroup'),
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field42-3',
-    label: `${t('formDemo.checkboxGroup')} ${t('formDemo.slot')}`,
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ],
-      slots: {
-        default: (options: CheckboxOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElCheckbox label={v.value}>
-                {v.label}({v.value})
-              </ElCheckbox>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field43',
-    label: t('formDemo.button'),
-    component: 'CheckboxButton',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '23'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field43-1',
-    label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
-    component: 'CheckboxButton',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '23'
-        }
-      ],
-      slots: {
-        default: (options: CheckboxOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElCheckboxButton label={v.value}>
-                {v.label}({v.value})
-              </ElCheckboxButton>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field44',
-    component: 'Divider',
-    label: t('formDemo.slider')
-  },
-  {
-    field: 'field45',
-    component: 'Slider',
-    label: t('formDemo.default'),
-    value: 0
-  },
-  {
-    field: 'field46',
-    component: 'Divider',
-    label: t('formDemo.datePicker')
-  },
-  {
-    field: 'field47',
-    component: 'DatePicker',
-    label: t('formDemo.default'),
-    componentProps: {
-      type: 'date'
-    }
-  },
-  {
-    field: 'field48',
-    component: 'DatePicker',
-    label: t('formDemo.shortcuts'),
-    componentProps: {
-      type: 'date',
-      disabledDate: (time: Date) => {
-        return time.getTime() > Date.now()
-      },
-      shortcuts: [
-        {
-          text: t('formDemo.today'),
-          value: new Date()
-        },
-        {
-          text: t('formDemo.yesterday'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24)
-            return date
-          }
-        },
-        {
-          text: t('formDemo.aWeekAgo'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-            return date
-          }
-        }
-      ]
-    }
-  },
-  {
-    field: 'field47-1',
-    component: 'DatePicker',
-    label: t('formDemo.slot'),
-    value: '2021-10-29',
-    componentProps: {
-      type: 'date',
-      slots: {
-        default: (cell: any) => {
-          return (
-            <div class={{ cell: true, current: cell.isCurrent }}>
-              <span class="text">{cell.text}</span>
-              {isHoliday(cell) ? <span class="holiday" /> : null}
-            </div>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field49',
-    component: 'DatePicker',
-    label: t('formDemo.week'),
-    componentProps: {
-      type: 'week',
-      format: `[${t('formDemo.week')}]`
-    }
-  },
-  {
-    field: 'field50',
-    component: 'DatePicker',
-    label: t('formDemo.year'),
-    componentProps: {
-      type: 'year'
-    }
-  },
-  {
-    field: 'field51',
-    component: 'DatePicker',
-    label: t('formDemo.month'),
-    componentProps: {
-      type: 'month'
-    }
-  },
-  {
-    field: 'field52',
-    component: 'DatePicker',
-    label: t('formDemo.dates'),
-    componentProps: {
-      type: 'dates'
-    }
-  },
-  {
-    field: 'field53',
-    component: 'DatePicker',
-    label: t('formDemo.daterange'),
-    componentProps: {
-      type: 'daterange'
-    }
-  },
-  {
-    field: 'field54',
-    component: 'DatePicker',
-    label: t('formDemo.monthrange'),
-    componentProps: {
-      type: 'monthrange'
-    }
-  },
-  {
-    field: 'field56',
-    component: 'Divider',
-    label: t('formDemo.dateTimePicker')
-  },
-  {
-    field: 'field57',
-    component: 'DatePicker',
-    label: t('formDemo.default'),
-    componentProps: {
-      type: 'datetime'
-    }
-  },
-  {
-    field: 'field58',
-    component: 'DatePicker',
-    label: t('formDemo.shortcuts'),
-    componentProps: {
-      type: 'datetime',
-      shortcuts: [
-        {
-          text: t('formDemo.today'),
-          value: new Date()
-        },
-        {
-          text: t('formDemo.yesterday'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24)
-            return date
-          }
-        },
-        {
-          text: t('formDemo.aWeekAgo'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-            return date
-          }
-        }
-      ]
-    }
-  },
-  {
-    field: 'field59',
-    component: 'DatePicker',
-    label: t('formDemo.dateTimerange'),
-    componentProps: {
-      type: 'datetimerange'
-    }
-  },
-  {
-    field: 'field60',
-    component: 'Divider',
-    label: t('formDemo.timePicker')
-  },
-  {
-    field: 'field61',
-    component: 'TimePicker',
-    label: t('formDemo.default')
-  },
-  {
-    field: 'field62',
-    component: 'Divider',
-    label: t('formDemo.timeSelect')
-  },
-  {
-    field: 'field63',
-    component: 'TimeSelect',
-    label: t('formDemo.default')
-  },
-  {
-    field: 'field64',
-    component: 'Divider',
-    label: t('formDemo.richText')
-  },
-  {
-    field: 'field65',
-    component: 'Editor',
-    value: 'hello world',
-    label: t('formDemo.default'),
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field66',
-    component: 'Divider',
-    label: t('formDemo.inputPassword')
-  },
-  {
-    field: 'field67',
-    component: 'InputPassword',
-    label: t('formDemo.default'),
-    componentProps: {
-      strength: true
-    }
-  },
-  {
-    field: 'field68',
-    component: 'Divider',
-    label: `${t('formDemo.form')} ${t('formDemo.slot')}`
-  },
-  {
-    field: 'field69',
-    component: 'Input',
-    label: `label`,
-    formItemProps: {
-      slots: {
-        label: ({ label }) => {
-          return (
-            <div class="custom-label">
-              <span class="label-text">custom {label}</span>
-            </div>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field69-1',
-    component: 'Input',
-    label: `custom formItem`,
-    formItemProps: {
-      slots: {
-        default: (formModel: any) => {
-          return <ElInput v-model={formModel['field69-1']} />
-        }
-      }
-    }
-  },
-  {
-    field: 'field70',
-    component: 'Divider',
-    label: `${t('formDemo.remoteLoading')}`
-  },
-  {
-    field: 'field71',
-    label: `${t('formDemo.select')}`,
-    component: 'Select',
-    componentProps: {
-      options: []
-    },
-    // 远程加载option
-    optionApi: async () => {
-      const res = await getDictOneApi()
-      return res.data
-    }
-  },
-  {
-    field: 'field72',
-    label: `${t('formDemo.selectV2')}`,
-    component: 'SelectV2',
-    componentProps: {
-      options: []
-    },
-    // 远程加载option
-    optionApi: async () => {
-      const res = await getDictOneApi()
-      return res.data
-    }
-  },
-  {
-    field: 'field73',
-    label: `${t('formDemo.checkboxGroup')}`,
-    component: 'CheckboxGroup',
-    componentProps: {
-      options: []
-    },
-    // 远程加载option
-    optionApi: async () => {
-      const res = await getDictOneApi()
-      return res.data
-    }
-  },
-  {
-    field: 'field74',
-    label: `${t('formDemo.radioGroup')}`,
-    component: 'RadioGroup',
-    componentProps: {
-      options: []
-    },
-    // 远程加载option
-    optionApi: async () => {
-      const res = await getDictOneApi()
-      return res.data
-    }
-  },
-  {
-    field: 'field82',
-    label: `${t('formDemo.treeSelect')}`,
-    component: 'TreeSelect',
-    // 远程加载option
-    optionApi: () => {
-      return treeSelectData
-    }
-  },
-  {
-    field: 'field75',
-    component: 'Divider',
-    label: `${t('formDemo.treeSelect')}`
-  },
-  {
-    field: 'field76',
-    component: 'TreeSelect',
-    label: `${t('formDemo.default')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field76',
-    component: 'TreeSelect',
-    label: `${t('formDemo.showCheckbox')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      showCheckbox: true,
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field77',
-    component: 'TreeSelect',
-    label: `${t('formDemo.selectAnyLevel')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      showCheckbox: true,
-      checkStrictly: true,
-      checkOnClickNode: true,
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field78',
-    component: 'TreeSelect',
-    label: `${t('formDemo.multiple')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      multiple: true,
-      showCheckbox: true,
-      checkStrictly: true,
-      checkOnClickNode: true,
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field79',
-    component: 'TreeSelect',
-    label: `${t('formDemo.filterable')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      multiple: true,
-      filterable: true,
-      showCheckbox: true,
-      checkStrictly: true,
-      checkOnClickNode: true,
-      filterNodeMethod: (value, data) => data.label.includes(value),
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field80',
-    component: 'TreeSelect',
-    label: `${t('formDemo.customContent')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      multiple: true,
-      filterable: true,
-      showCheckbox: true,
-      checkStrictly: true,
-      checkOnClickNode: true,
-      filterNodeMethod: (value, data) => data.label.includes(value),
-      slots: {
-        default: ({ data: { label } }) => {
-          return (
-            <>
-              {label}
-              <span style="color: gray">(suffix)</span>
-            </>
-          )
-        }
-      },
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field81',
-    component: 'TreeSelect',
-    label: `${t('formDemo.lazyLoad')}`,
-    componentProps: {
-      renderAfterExpand: false,
-      lazy: true,
-      load: (node, resolve) => {
-        if (node.isLeaf) return resolve([])
-
-        setTimeout(() => {
-          resolve([
-            {
-              value: ++id,
-              label: `lazy load node${id}`
-            },
-            {
-              value: ++id,
-              label: `lazy load node${id}`,
-              isLeaf: true
-            }
-          ])
-        }, 400)
-      },
-      multiple: true,
-      filterable: true,
-      showCheckbox: true,
-      checkStrictly: true,
-      checkOnClickNode: true,
-      filterNodeMethod: (value, data) => data.label.includes(value),
-      slots: {
-        default: ({ data: { label } }) => {
-          return (
-            <>
-              {label}
-              <span style="color: gray">(suffix)</span>
-            </>
-          )
-        }
-      },
-      data: treeSelectData
-    }
-  },
-  {
-    field: 'field82',
-    component: 'Divider',
-    label: `${t('formDemo.upload')}`
-  },
-  {
-    field: 'field83',
-    component: 'Upload',
-    label: `${t('formDemo.default')}`,
-    componentProps: {
-      limit: 3,
-      action: 'https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15',
-      fileList: [
-        {
-          name: 'element-plus-logo.svg',
-          url: 'https://element-plus.org/images/element-plus-logo.svg'
-        },
-        {
-          name: 'element-plus-logo2.svg',
-          url: 'https://element-plus.org/images/element-plus-logo.svg'
-        }
-      ],
-      multiple: true,
-      onPreview: (uploadFile) => {
-        console.log(uploadFile)
-      },
-      onRemove: (file) => {
-        console.log(file)
-      },
-      beforeRemove: (uploadFile) => {
-        return ElMessageBox.confirm(`Cancel the transfer of ${uploadFile.name} ?`).then(
-          () => true,
-          () => false
-        )
-      },
-      onExceed: (files, uploadFiles) => {
-        ElMessage.warning(
-          `The limit is 3, you selected ${files.length} files this time, add up to ${
-            files.length + uploadFiles.length
-          } totally`
-        )
-      },
-      slots: {
-        default: () => <ElButton type="primary">Click to upload</ElButton>,
-        tip: () => <div class="el-upload__tip">jpg/png files with a size less than 500KB.</div>
-      }
-    }
-  },
-  {
-    field: 'field84',
-    component: 'Upload',
-    label: `${t('formDemo.userAvatar')}`,
-    componentProps: {
-      action: 'https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15',
-      showFileList: false,
-      onSuccess: (_response, uploadFile) => {
-        imageUrl.value = URL.createObjectURL(uploadFile.raw!)
-      },
-      beforeUpload: (rawFile) => {
-        if (rawFile.type !== 'image/jpeg') {
-          ElMessage.error('Avatar picture must be JPG format!')
-          return false
-        } else if (rawFile.size / 1024 / 1024 > 2) {
-          ElMessage.error('Avatar picture size can not exceed 2MB!')
-          return false
-        }
-        return true
-      },
-      slots: {
-        default: () => (
-          <>
-            {imageUrl.value ? <img src={imageUrl.value} class="avatar" /> : null}
-            {!imageUrl.value ? (
-              <ElIcon class="avatar-uploader-icon" size="large">
-                add
-              </ElIcon>
-            ) : null}
-          </>
-        )
-      }
-    }
-  }
-])
-</script>
-
-<template>
-  <ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')">
-    <Form :schema="schema" label-width="auto" :label-position="isMobile ? 'top' : 'right'" />
-  </ContentWrap>
-</template>
-
-<style lang="less">
-.cell {
-  height: 30px;
-  padding: 3px 0;
-  box-sizing: border-box;
-
-  .text {
-    position: absolute;
-    left: 50%;
-    display: block;
-    width: 24px;
-    height: 24px;
-    margin: 0 auto;
-    line-height: 24px;
-    border-radius: 50%;
-    transform: translateX(-50%);
-  }
-
-  &.current {
-    .text {
-      color: #fff;
-      background: #626aef;
-    }
-  }
-
-  .holiday {
-    position: absolute;
-    bottom: 0;
-    left: 50%;
-    width: 6px;
-    height: 6px;
-    background: var(--el-color-danger);
-    border-radius: 50%;
-    transform: translateX(-50%);
-  }
-}
-
-.transfer-footer {
-  padding: 6px 5px;
-  margin-left: 15px;
-}
-
-.el-upload {
-  position: relative;
-  overflow: hidden;
-  cursor: pointer;
-  border: 1px dashed var(--el-border-color);
-  border-radius: 6px;
-  transition: var(--el-transition-duration-fast);
-}
-
-.el-upload:hover {
-  border-color: var(--el-color-primary);
-}
-
-.el-icon.avatar-uploader-icon {
-  width: 178px;
-  height: 178px;
-  font-size: 28px;
-  color: #8c939d;
-  text-align: center;
-}
-</style>

+ 0 - 316
src/views/Components/Form/UseFormDemo.vue

@@ -1,316 +0,0 @@
-<script setup lang="ts">
-import { Form, FormSchema } from '@/components/Form'
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useForm } from '@/hooks/web/useForm'
-import { reactive, unref, ref } from 'vue'
-import { ElButton, ElInput, FormItemProp, ComponentSize } from 'element-plus'
-import { useValidator } from '@/hooks/web/useValidator'
-import { getDictOneApi } from '@/api/common'
-
-const { required } = useValidator()
-
-const { t } = useI18n()
-
-const schema = reactive<FormSchema[]>([
-  {
-    field: 'field1',
-    label: t('formDemo.input'),
-    component: 'Input',
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'field2',
-    label: t('formDemo.select'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'option1',
-          value: '1'
-        },
-        {
-          label: 'option2',
-          value: '2'
-        }
-      ]
-    },
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'field3',
-    label: t('formDemo.radio'),
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field4',
-    label: t('formDemo.checkbox'),
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field5',
-    component: 'DatePicker',
-    label: t('formDemo.datePicker'),
-    componentProps: {
-      type: 'date'
-    }
-  },
-  {
-    field: 'field6',
-    component: 'TimeSelect',
-    label: t('formDemo.timeSelect')
-  }
-])
-
-const { formRegister, formMethods } = useForm()
-const {
-  setProps,
-  delSchema,
-  addSchema,
-  setValues,
-  setSchema,
-  getComponentExpose,
-  getFormItemExpose,
-  getElFormExpose
-} = formMethods
-
-const changeLabelWidth = (width: number | string) => {
-  setProps({
-    labelWidth: width
-  })
-}
-
-const changeSize = (size: ComponentSize) => {
-  setProps({
-    size
-  })
-}
-
-const changeDisabled = (bool: boolean) => {
-  setProps({
-    disabled: bool
-  })
-}
-
-const changeSchema = (del: boolean) => {
-  if (del) {
-    delSchema('field2')
-  } else if (!del && schema[1].field !== 'field2') {
-    addSchema(
-      {
-        field: 'field2',
-        label: t('formDemo.select'),
-        component: 'Select',
-        componentProps: {
-          options: [
-            {
-              label: 'option1',
-              value: '1'
-            },
-            {
-              label: 'option2',
-              value: '2'
-            }
-          ]
-        }
-      },
-      1
-    )
-  }
-}
-
-const setValue = async (reset: boolean) => {
-  const elFormExpose = await getElFormExpose()
-  if (reset) {
-    elFormExpose?.resetFields()
-  } else {
-    setValues({
-      field1: 'field1',
-      field2: '2',
-      field3: '2',
-      field4: ['1', '3'],
-      field5: '2022-01-27',
-      field6: '17:00'
-    })
-  }
-}
-
-const index = ref(7)
-
-const setLabel = () => {
-  setSchema([
-    {
-      field: 'field2',
-      path: 'label',
-      value: `${t('formDemo.select')} ${index.value}`
-    },
-    {
-      field: 'field2',
-      path: 'componentProps.options',
-      value: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ]
-    }
-  ])
-  index.value++
-}
-
-const addItem = () => {
-  if (unref(index) % 2 === 0) {
-    addSchema({
-      field: `field${unref(index)}`,
-      label: `${t('formDemo.input')}${unref(index)}`,
-      component: 'Input'
-    })
-  } else {
-    addSchema(
-      {
-        field: `field${unref(index)}`,
-        label: `${t('formDemo.input')}${unref(index)}`,
-        component: 'Input'
-      },
-      unref(index)
-    )
-  }
-  index.value++
-}
-
-const formValidation = async () => {
-  const elFormExpose = await getElFormExpose()
-  elFormExpose?.validate((isValid) => {
-    console.log(isValid)
-  })
-}
-
-const verifyReset = async () => {
-  const elFormExpose = await getElFormExpose()
-  elFormExpose?.resetFields()
-}
-
-const getDictOne = async () => {
-  const res = await getDictOneApi()
-  if (res) {
-    setSchema([
-      {
-        field: 'field2',
-        path: 'componentProps.options',
-        value: res.data
-      }
-    ])
-  }
-}
-
-const inoutFocus = async () => {
-  const inputEl: ComponentRef<typeof ElInput> = await getComponentExpose('field1')
-  inputEl?.focus()
-}
-
-const inoutValidation = async () => {
-  const formItem = await getFormItemExpose('field1')
-  const inputEl: ComponentRef<typeof ElInput> = await getComponentExpose('field1')
-  inputEl?.focus()
-  formItem?.validate('focus', (val: boolean) => {
-    console.log(val)
-  })
-}
-
-const formValidate = (prop: FormItemProp, isValid: boolean, message: string) => {
-  console.log(prop, isValid, message)
-}
-</script>
-
-<template>
-  <ContentWrap :title="`UseForm ${t('formDemo.operate')}`" style="margin-bottom: 20px">
-    <ElButton @click="changeLabelWidth(150)">{{ t('formDemo.change') }} labelWidth</ElButton>
-    <ElButton @click="changeLabelWidth('auto')">{{ t('formDemo.restore') }} labelWidth</ElButton>
-
-    <ElButton @click="changeSize('large')">{{ t('formDemo.change') }} size</ElButton>
-    <ElButton @click="changeSize('default')">{{ t('formDemo.restore') }} size</ElButton>
-
-    <ElButton @click="changeDisabled(true)">{{ t('formDemo.disabled') }}</ElButton>
-    <ElButton @click="changeDisabled(false)">{{ t('formDemo.disablement') }}</ElButton>
-
-    <ElButton @click="changeSchema(true)">
-      {{ t('formDemo.delete') }} {{ t('formDemo.select') }}
-    </ElButton>
-    <ElButton @click="changeSchema(false)">
-      {{ t('formDemo.add') }} {{ t('formDemo.select') }}
-    </ElButton>
-
-    <ElButton @click="setValue(false)">{{ t('formDemo.setValue') }}</ElButton>
-    <ElButton @click="setValue(true)">{{ t('formDemo.resetValue') }}</ElButton>
-
-    <ElButton @click="setLabel">
-      {{ t('formDemo.set') }} {{ t('formDemo.select') }} label
-    </ElButton>
-
-    <ElButton @click="addItem"> {{ t('formDemo.add') }} {{ t('formDemo.subitem') }} </ElButton>
-
-    <ElButton @click="formValidation"> {{ t('formDemo.formValidation') }} </ElButton>
-    <ElButton @click="verifyReset"> {{ t('formDemo.verifyReset') }} </ElButton>
-
-    <ElButton @click="getDictOne">
-      {{ `${t('formDemo.select')} ${t('searchDemo.dynamicOptions')}` }}
-    </ElButton>
-
-    <ElButton @click="inoutFocus">
-      {{ `${t('formDemo.input')} ${t('formDemo.focus')}` }}
-    </ElButton>
-    <ElButton @click="inoutValidation">
-      {{ `${t('formDemo.input')} ${t('formDemo.formValidation')}` }}
-    </ElButton>
-  </ContentWrap>
-  <ContentWrap :title="`UseForm ${t('formDemo.example')}`">
-    <Form :schema="schema" @register="formRegister" @validate="formValidate" />
-  </ContentWrap>
-</template>
-
-<style lang="less" scoped>
-.el-button {
-  margin-top: 10px;
-}
-</style>

+ 0 - 20
src/views/Components/Highlight.vue

@@ -1,20 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Highlight } from '@/components/Highlight'
-import { ElMessage } from 'element-plus'
-
-const { t } = useI18n()
-
-const keyClick = (key: string) => {
-  ElMessage.info(key)
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('highlightDemo.highlight')">
-    <Highlight :keys="[t('highlightDemo.keys1'), t('highlightDemo.keys2')]" @click="keyClick">
-      {{ t('highlightDemo.message') }}
-    </Highlight>
-  </ContentWrap>
-</template>

+ 0 - 62
src/views/Components/Icon.vue

@@ -1,62 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Infotip } from '@/components/Infotip'
-import { ElButton } from 'element-plus'
-import { useIcon } from '@/hooks/web/useIcon'
-
-const { t } = useI18n()
-
-const keyClick = (key: string) => {
-  if (key === t('iconDemo.accessAddress')) {
-    window.open('https://iconify.design/')
-  }
-}
-
-const peoples = useIcon({ icon: 'svg-icon:peoples' })
-const money = useIcon({ icon: 'svg-icon:money' })
-const aim = useIcon({ icon: 'ep:aim' })
-const alarmClock = useIcon({ icon: 'ep:alarm-clock' })
-</script>
-
-<template>
-  <Infotip
-    :show-index="false"
-    :title="`${t('iconDemo.recommendedUse')}${t('iconDemo.iconify')}`"
-    :schema="[
-      {
-        label: t('iconDemo.recommendeDes'),
-        keys: ['Iconify']
-      },
-      {
-        label: t('iconDemo.accessAddress'),
-        keys: [t('iconDemo.accessAddress')]
-      }
-    ]"
-    @click="keyClick"
-  />
-  <ContentWrap :title="t('iconDemo.localIcon')">
-    <div class="flex justify-between">
-      <Icon icon="svg-icon:peoples" />
-      <Icon icon="svg-icon:money" />
-      <Icon icon="svg-icon:message" />
-      <Icon icon="svg-icon:shopping" />
-    </div>
-  </ContentWrap>
-  <ContentWrap :title="t('iconDemo.iconify')">
-    <div class="flex justify-between">
-      <Icon icon="ep:aim" />
-      <Icon icon="ep:alarm-clock" />
-      <Icon icon="ep:baseball" />
-      <Icon icon="ep:chat-line-round" />
-    </div>
-  </ContentWrap>
-  <ContentWrap title="useIcon">
-    <div class="flex justify-between">
-      <ElButton :icon="peoples">Button</ElButton>
-      <ElButton :icon="money">Button</ElButton>
-      <ElButton :icon="aim">Button</ElButton>
-      <ElButton :icon="alarmClock">Button</ElButton>
-    </div>
-  </ContentWrap>
-</template>

+ 0 - 30
src/views/Components/ImageViewer.vue

@@ -1,30 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { createImageViewer } from '@/components/ImageViewer'
-import { ElButton } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-
-const { t } = useI18n()
-
-const open = () => {
-  createImageViewer({
-    urlList: [
-      'https://images6.alphacoders.com/657/thumbbig-657194.webp',
-      'https://images3.alphacoders.com/677/thumbbig-677688.webp',
-      'https://images4.alphacoders.com/200/thumbbig-200966.webp',
-      'https://images5.alphacoders.com/657/thumbbig-657248.webp',
-      'https://images3.alphacoders.com/679/thumbbig-679917.webp',
-      'https://images3.alphacoders.com/737/thumbbig-73785.webp'
-    ]
-  })
-}
-</script>
-
-<template>
-  <ContentWrap
-    :title="t('imageViewerDemo.imageViewer')"
-    :message="t('imageViewerDemo.imageViewerDes')"
-  >
-    <ElButton type="primary" @click="open">{{ t('imageViewerDemo.open') }}</ElButton>
-  </ContentWrap>
-</template>

+ 0 - 33
src/views/Components/Infotip.vue

@@ -1,33 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Infotip } from '@/components/Infotip'
-
-const { t } = useI18n()
-
-const keyClick = (key: string) => {
-  if (key === t('iconDemo.accessAddress')) {
-    window.open('https://iconify.design/')
-  }
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('infotipDemo.infotip')" :message="t('infotipDemo.infotipDes')">
-    <Infotip
-      :show-index="false"
-      :title="`${t('iconDemo.recommendedUse')}${t('iconDemo.iconify')}`"
-      :schema="[
-        {
-          label: t('iconDemo.recommendeDes'),
-          keys: ['Iconify']
-        },
-        {
-          label: t('iconDemo.accessAddress'),
-          keys: [t('iconDemo.accessAddress')]
-        }
-      ]"
-      @click="keyClick"
-    />
-  </ContentWrap>
-</template>

+ 0 - 21
src/views/Components/InputPassword.vue

@@ -1,21 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { InputPassword } from '@/components/InputPassword'
-import { ref } from 'vue'
-
-const { t } = useI18n()
-
-const password = ref('')
-</script>
-
-<template>
-  <ContentWrap
-    :title="t('inputPasswordDemo.title')"
-    :message="t('inputPasswordDemo.inputPasswordDes')"
-  >
-    <InputPassword v-model="password" class="mb-20px" />
-    <InputPassword v-model="password" strength />
-    <InputPassword v-model="password" strength disabled class="mt-20px" />
-  </ContentWrap>
-</template>

+ 0 - 108
src/views/Components/Qrcode.vue

@@ -1,108 +0,0 @@
-<script setup lang="ts">
-import { Qrcode } from '@/components/Qrcode'
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { computed, ref, unref } from 'vue'
-import { useAppStore } from '@/store/modules/app'
-import { ElRow, ElCard, ElCol, ElMessage } from 'element-plus'
-// @ts-ignore
-import logoImg from '@/assets/imgs/logo.png'
-
-const appStore = useAppStore()
-
-const { t } = useI18n()
-
-const title = computed(() => appStore.getTitle)
-
-const asyncTitle = ref('')
-
-setTimeout(() => {
-  asyncTitle.value = unref(title)
-}, 3000)
-
-const codeClick = () => {
-  ElMessage.info(t('qrcodeDemo.click'))
-}
-
-const disabledClick = () => {
-  ElMessage.info(t('qrcodeDemo.invalid'))
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('qrcodeDemo.qrcode')" :message="t('qrcodeDemo.qrcodeDes')">
-    <ElRow :gutter="20" justify="space-between">
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.basicUsage') }}</div>
-          <Qrcode :text="title" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.imgTag') }}</div>
-          <Qrcode :text="title" tag="img" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.style') }}</div>
-          <Qrcode
-            :text="title"
-            :options="{
-              color: {
-                dark: '#55D187',
-                light: '#2d8cf0'
-              }
-            }"
-          />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.click') }}</div>
-          <Qrcode :text="title" @click="codeClick" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.asynchronousContent') }}</div>
-          <Qrcode :text="asyncTitle" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.invalid') }}</div>
-          <Qrcode :text="title" disabled @disabled-click="disabledClick" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.logoConfig') }}</div>
-          <Qrcode :text="title" :logo="logoImg" />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.logoStyle') }}</div>
-          <Qrcode
-            :text="title"
-            :logo="{
-              src: logoImg,
-              logoSize: 0.2,
-              borderSize: 0.05,
-              borderRadius: 50,
-              bgColor: 'blue'
-            }"
-          />
-        </ElCard>
-      </ElCol>
-      <ElCol :xl="6" :lg="6" :md="12" :sm="24" :xs="24">
-        <ElCard shadow="hover" class="mb-10px text-center">
-          <div class="font-bold">{{ t('qrcodeDemo.size') }}</div>
-          <Qrcode :text="title" :width="100" />
-        </ElCard>
-      </ElCol>
-    </ElRow>
-  </ContentWrap>
-</template>

+ 0 - 272
src/views/Components/Search.vue

@@ -1,272 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Search } from '@/components/Search'
-import { reactive, ref, unref } from 'vue'
-import { ElButton } from 'element-plus'
-import { getDictOneApi } from '@/api/common'
-import { FormSchema } from '@/components/Form'
-import { useSearch } from '@/hooks/web/useSearch'
-
-const { t } = useI18n()
-
-const { searchRegister, searchMethods } = useSearch()
-const { setSchema, setProps, setValues } = searchMethods
-
-const schema = reactive<FormSchema[]>([
-  {
-    field: 'field1',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field2',
-    label: t('formDemo.select'),
-    component: 'Select',
-    componentProps: {
-      options: [
-        {
-          label: 'option1',
-          value: '1'
-        },
-        {
-          label: 'option2',
-          value: '2'
-        }
-      ],
-      on: {
-        change: (value: string) => {
-          console.log(value)
-        }
-      }
-    }
-  },
-  {
-    field: 'field3',
-    label: t('formDemo.radio'),
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field5',
-    component: 'DatePicker',
-    label: t('formDemo.datePicker'),
-    componentProps: {
-      type: 'date'
-    }
-  },
-  {
-    field: 'field6',
-    component: 'TimeSelect',
-    label: t('formDemo.timeSelect')
-  },
-  {
-    field: 'field8',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field9',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field10',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field11',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field12',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field13',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field14',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field15',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field16',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field17',
-    label: t('formDemo.input'),
-    component: 'Input'
-  },
-  {
-    field: 'field18',
-    label: t('formDemo.input'),
-    component: 'Input'
-  }
-])
-
-const isGrid = ref(false)
-
-const changeGrid = (grid: boolean) => {
-  setProps({
-    isCol: grid
-  })
-  // isGrid.value = grid
-}
-
-const layout = ref('inline')
-
-const changeLayout = () => {
-  layout.value = unref(layout) === 'inline' ? 'bottom' : 'inline'
-}
-
-const buttonPosition = ref('left')
-
-const changePosition = (position: string) => {
-  layout.value = 'bottom'
-  buttonPosition.value = position
-}
-
-const getDictOne = async () => {
-  const res = await getDictOneApi()
-  if (res) {
-    setSchema([
-      {
-        field: 'field2',
-        path: 'componentProps.options',
-        value: res.data
-      }
-    ])
-  }
-}
-
-const handleSearch = (data: any) => {
-  console.log(data)
-}
-
-const delRadio = () => {
-  setSchema([
-    {
-      field: 'field3',
-      path: 'remove',
-      value: true
-    }
-  ])
-}
-
-const restoreRadio = () => {
-  setSchema([
-    {
-      field: 'field3',
-      path: 'remove',
-      value: false
-    }
-  ])
-}
-
-const setValue = () => {
-  setValues({
-    field1: 'Joy'
-  })
-}
-
-const searchLoading = ref(false)
-const changeSearchLoading = () => {
-  searchLoading.value = true
-  setTimeout(() => {
-    searchLoading.value = false
-  }, 2000)
-}
-
-const resetLoading = ref(false)
-const changeResetLoading = () => {
-  resetLoading.value = true
-  setTimeout(() => {
-    resetLoading.value = false
-  }, 2000)
-}
-</script>
-
-<template>
-  <ContentWrap
-    :title="`${t('searchDemo.search')} ${t('searchDemo.operate')}`"
-    style="margin-bottom: 20px"
-  >
-    <ElButton @click="changeGrid(true)">{{ t('searchDemo.grid') }}</ElButton>
-    <ElButton @click="changeGrid(false)">
-      {{ t('searchDemo.restore') }} {{ t('searchDemo.grid') }}
-    </ElButton>
-
-    <ElButton @click="changeLayout">
-      {{ t('searchDemo.button') }} {{ t('searchDemo.position') }}
-    </ElButton>
-
-    <ElButton @click="changePosition('left')">
-      {{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.left') }}
-    </ElButton>
-    <ElButton @click="changePosition('center')">
-      {{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.center') }}
-    </ElButton>
-    <ElButton @click="changePosition('right')">
-      {{ t('searchDemo.bottom') }} {{ t('searchDemo.position') }}-{{ t('searchDemo.right') }}
-    </ElButton>
-    <ElButton @click="getDictOne">
-      {{ t('formDemo.select') }} {{ t('searchDemo.dynamicOptions') }}
-    </ElButton>
-    <ElButton @click="delRadio">{{ t('searchDemo.deleteRadio') }}</ElButton>
-    <ElButton @click="restoreRadio">{{ t('searchDemo.restoreRadio') }}</ElButton>
-    <ElButton @click="setValue">{{ t('formDemo.setValue') }}</ElButton>
-
-    <ElButton @click="changeSearchLoading">
-      {{ t('searchDemo.search') }} {{ t('searchDemo.loading') }}
-    </ElButton>
-    <ElButton @click="changeResetLoading">
-      {{ t('searchDemo.reset') }} {{ t('searchDemo.loading') }}
-    </ElButton>
-  </ContentWrap>
-
-  <ContentWrap :title="t('searchDemo.search')" :message="t('searchDemo.searchDes')">
-    <Search
-      :schema="schema"
-      :is-col="isGrid"
-      :layout="layout"
-      :button-position="buttonPosition"
-      :search-loading="searchLoading"
-      :reset-loading="resetLoading"
-      show-expand
-      expand-field="field6"
-      @search="handleSearch"
-      @reset="handleSearch"
-      @register="searchRegister"
-    />
-  </ContentWrap>
-</template>
-
-<style lang="less" scoped>
-.el-button {
-  margin-top: 10px;
-}
-</style>

+ 0 - 104
src/views/Components/Table/DefaultTable.vue

@@ -1,104 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
-import { getTableListApi } from '@/api/table'
-import { TableData } from '@/api/table/types'
-import { ref, h } from 'vue'
-import { ElTag, ElButton } from 'element-plus'
-
-interface Params {
-  pageIndex?: number
-  pageSize?: number
-}
-
-const { t } = useI18n()
-
-const columns: TableColumn[] = [
-  {
-    field: 'title',
-    label: t('tableDemo.title')
-  },
-  {
-    field: 'author',
-    label: t('tableDemo.author')
-  },
-  {
-    field: 'display_time',
-    label: t('tableDemo.displayTime'),
-    sortable: true
-  },
-  {
-    field: 'importance',
-    label: t('tableDemo.importance'),
-    formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-      return h(
-        ElTag,
-        {
-          type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
-        },
-        () =>
-          cellValue === 1
-            ? t('tableDemo.important')
-            : cellValue === 2
-            ? t('tableDemo.good')
-            : t('tableDemo.commonly')
-      )
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('tableDemo.pageviews')
-  },
-  {
-    field: 'action',
-    label: t('tableDemo.action'),
-    slots: {
-      default: (data) => {
-        return (
-          <ElButton type="primary" onClick={() => actionFn(data)}>
-            {t('tableDemo.action')}
-          </ElButton>
-        )
-      }
-    }
-  }
-]
-
-const loading = ref(true)
-
-let tableDataList = ref<TableData[]>([])
-
-const getTableList = async (params?: Params) => {
-  const res = await getTableListApi(
-    params || {
-      pageIndex: 1,
-      pageSize: 10
-    }
-  )
-    .catch(() => {})
-    .finally(() => {
-      loading.value = false
-    })
-  if (res) {
-    tableDataList.value = res.data.list
-  }
-}
-
-getTableList()
-
-const actionFn = (data: TableSlotDefault) => {
-  console.log(data)
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('tableDemo.table')" :message="t('tableDemo.tableDes')">
-    <Table
-      :columns="columns"
-      :data="tableDataList"
-      :loading="loading"
-      :defaultSort="{ prop: 'display_time', order: 'descending' }"
-    />
-  </ContentWrap>
-</template>

+ 0 - 82
src/views/Components/Table/TableImagePreview.vue

@@ -1,82 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Table, TableColumn } from '@/components/Table'
-import { getTableListApi } from '@/api/table'
-import { TableData } from '@/api/table/types'
-import { ref } from 'vue'
-import { ElTag } from 'element-plus'
-
-interface Params {
-  pageIndex?: number
-  pageSize?: number
-}
-
-const { t } = useI18n()
-
-const columns: TableColumn[] = [
-  {
-    field: 'title',
-    label: t('tableDemo.title')
-  },
-  {
-    field: 'image_uri',
-    label: t('tableDemo.preview')
-  },
-  {
-    field: 'author',
-    label: t('tableDemo.author')
-  },
-  {
-    field: 'display_time',
-    label: t('tableDemo.displayTime')
-  },
-  {
-    field: 'importance',
-    label: t('tableDemo.importance'),
-    formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-      return (
-        <ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
-          {cellValue === 1
-            ? t('tableDemo.important')
-            : cellValue === 2
-            ? t('tableDemo.good')
-            : t('tableDemo.commonly')}
-        </ElTag>
-      )
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('tableDemo.pageviews')
-  }
-]
-
-const loading = ref(true)
-
-let tableDataList = ref<TableData[]>([])
-
-const getTableList = async (params?: Params) => {
-  const res = await getTableListApi(
-    params || {
-      pageIndex: 1,
-      pageSize: 10
-    }
-  )
-    .catch(() => {})
-    .finally(() => {
-      loading.value = false
-    })
-  if (res) {
-    tableDataList.value = res.data.list
-  }
-}
-
-getTableList()
-</script>
-
-<template>
-  <ContentWrap :title="t('router.PicturePreview')">
-    <Table :columns="columns" :data="tableDataList" :loading="loading" :preview="['image_uri']" />
-  </ContentWrap>
-</template>

+ 0 - 116
src/views/Components/Table/TreeTable.vue

@@ -1,116 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
-import { getTreeTableListApi } from '@/api/table'
-import { reactive, unref } from 'vue'
-import { ElTag, ElButton } from 'element-plus'
-import { useTable } from '@/hooks/web/useTable'
-
-const { tableRegister, tableState } = useTable({
-  fetchDataApi: async () => {
-    const { currentPage, pageSize } = tableState
-    const res = await getTreeTableListApi({
-      pageIndex: unref(currentPage),
-      pageSize: unref(pageSize)
-    })
-    return {
-      list: res.data.list,
-      total: res.data.total
-    }
-  }
-})
-const { loading, dataList, total, currentPage, pageSize } = tableState
-
-const { t } = useI18n()
-
-const columns = reactive<TableColumn[]>([
-  {
-    field: 'selection',
-    type: 'selection'
-  },
-  {
-    field: 'index',
-    label: t('tableDemo.index'),
-    type: 'index'
-  },
-  {
-    field: 'content',
-    label: t('tableDemo.header'),
-    children: [
-      {
-        field: 'title',
-        label: t('tableDemo.title')
-      },
-      {
-        field: 'author',
-        label: t('tableDemo.author')
-      },
-      {
-        field: 'display_time',
-        label: t('tableDemo.displayTime')
-      },
-      {
-        field: 'importance',
-        label: t('tableDemo.importance'),
-        formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-          return (
-            <ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
-              {cellValue === 1
-                ? t('tableDemo.important')
-                : cellValue === 2
-                ? t('tableDemo.good')
-                : t('tableDemo.commonly')}
-            </ElTag>
-          )
-        }
-      },
-      {
-        field: 'pageviews',
-        label: t('tableDemo.pageviews')
-      }
-    ]
-  },
-  {
-    field: 'action',
-    label: t('tableDemo.action'),
-    slots: {
-      default: (data) => {
-        return (
-          <ElButton type="primary" onClick={() => actionFn(data)}>
-            {t('tableDemo.action')}
-          </ElButton>
-        )
-      }
-    }
-  }
-])
-
-const actionFn = (data: TableSlotDefault) => {
-  console.log(data)
-}
-</script>
-
-<template>
-  <ContentWrap :title="`${t('router.treeTable')} ${t('tableDemo.example')}`">
-    <Table
-      v-model:pageSize="pageSize"
-      v-model:currentPage="currentPage"
-      :columns="columns"
-      :data="dataList"
-      row-key="id"
-      :loading="loading"
-      sortable
-      :pagination="{
-        total: total
-      }"
-      @register="tableRegister"
-    />
-  </ContentWrap>
-</template>
-
-<style lang="less" scoped>
-.el-button {
-  margin-top: 10px;
-}
-</style>

+ 0 - 275
src/views/Components/Table/UseTableDemo.vue

@@ -1,275 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
-import { getTableListApi } from '@/api/table'
-import { ref, reactive, unref } from 'vue'
-import { ElTag, ElButton } from 'element-plus'
-import { useTable } from '@/hooks/web/useTable'
-
-const { tableRegister, tableMethods, tableState } = useTable({
-  fetchDataApi: async () => {
-    const { currentPage, pageSize } = tableState
-    const res = await getTableListApi({
-      pageIndex: unref(currentPage),
-      pageSize: unref(pageSize)
-    })
-    return {
-      list: res.data.list,
-      total: res.data.total
-    }
-  }
-})
-const { loading, dataList, total, currentPage, pageSize } = tableState
-const { setProps, setColumn, getElTableExpose, addColumn, delColumn, refresh } = tableMethods
-
-const { t } = useI18n()
-
-const columns = reactive<TableColumn[]>([
-  {
-    field: 'expand',
-    type: 'expand',
-    slots: {
-      default: (data: TableSlotDefault[]) => {
-        const { row } = data[0]
-        return (
-          <div class="ml-30px">
-            <div>
-              {t('tableDemo.title')}:{row.title}
-            </div>
-            <div>
-              {t('tableDemo.author')}:{row.author}
-            </div>
-            <div>
-              {t('tableDemo.displayTime')}:{row.display_time}
-            </div>
-          </div>
-        )
-      }
-    }
-  },
-  {
-    field: 'selection',
-    type: 'selection'
-  },
-  {
-    field: 'index',
-    label: t('tableDemo.index'),
-    type: 'index'
-  },
-  {
-    field: 'content',
-    label: t('tableDemo.header'),
-    children: [
-      {
-        field: 'title',
-        label: t('tableDemo.title')
-      },
-      {
-        field: 'author',
-        label: t('tableDemo.author')
-      },
-      {
-        field: 'display_time',
-        label: t('tableDemo.displayTime')
-      },
-      {
-        field: 'importance',
-        label: t('tableDemo.importance'),
-        formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-          return (
-            <ElTag type={cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'}>
-              {cellValue === 1
-                ? t('tableDemo.important')
-                : cellValue === 2
-                ? t('tableDemo.good')
-                : t('tableDemo.commonly')}
-            </ElTag>
-          )
-        }
-      },
-      {
-        field: 'pageviews',
-        label: t('tableDemo.pageviews')
-      }
-    ]
-  },
-  {
-    field: 'action',
-    label: t('tableDemo.action'),
-    slots: {
-      default: (data) => {
-        return (
-          <ElButton type="primary" onClick={() => actionFn(data)}>
-            {t('tableDemo.action')}
-          </ElButton>
-        )
-      }
-    }
-  }
-])
-
-const actionFn = (data: TableSlotDefault) => {
-  console.log(data)
-}
-
-const canShowPagination = ref(true)
-const showPagination = (show: boolean) => {
-  canShowPagination.value = show
-}
-
-const reserveIndex = (custom: boolean) => {
-  setProps({
-    reserveIndex: custom
-  })
-}
-
-const showSelections = (show: boolean) => {
-  setColumn([
-    {
-      field: 'selection',
-      path: 'hidden',
-      value: !show
-    }
-  ])
-}
-
-const index = ref(1)
-
-const changeTitle = () => {
-  setColumn([
-    {
-      field: 'title',
-      path: 'label',
-      value: `${t('tableDemo.title')}${unref(index)}`
-    }
-  ])
-  index.value++
-}
-
-const showExpandedRows = (show: boolean) => {
-  setColumn([
-    {
-      field: 'expand',
-      path: 'hidden',
-      value: !show
-    }
-  ])
-}
-
-const selectAllNone = async () => {
-  const elTableRef = await getElTableExpose()
-  elTableRef?.toggleAllSelection()
-}
-
-const showAction = ref(true)
-const delOrAddAction = () => {
-  if (unref(showAction)) {
-    delColumn('action')
-    showAction.value = false
-  } else {
-    addColumn({
-      field: 'action',
-      label: t('tableDemo.action'),
-      slots: {
-        default: (data) => {
-          return (
-            <ElButton type="primary" onClick={() => actionFn(data)}>
-              {t('tableDemo.action')}
-            </ElButton>
-          )
-        }
-      }
-    })
-    showAction.value = true
-  }
-}
-
-const showStripe = ref(false)
-const showOrHiddenStripe = () => {
-  setProps({
-    stripe: !unref(showStripe)
-  })
-  showStripe.value = !unref(showStripe)
-}
-
-const height = ref<string | number>('auto')
-const fixedHeaderOrAuto = () => {
-  if (unref(height) === 'auto') {
-    setProps({
-      height: 300
-    })
-    height.value = 300
-  } else {
-    setProps({
-      height: 'auto'
-    })
-    height.value = 'auto'
-  }
-}
-
-const getSelections = async () => {
-  const elTableRef = await getElTableExpose()
-  const selections = elTableRef?.getSelectionRows()
-  console.log(selections)
-}
-</script>
-
-<template>
-  <ContentWrap :title="`UseTable ${t('tableDemo.operate')}`" style="margin-bottom: 20px">
-    <ElButton @click="showPagination(true)">
-      {{ t('tableDemo.show') }} {{ t('tableDemo.pagination') }}
-    </ElButton>
-    <ElButton @click="showPagination(false)">
-      {{ t('tableDemo.hidden') }} {{ t('tableDemo.pagination') }}
-    </ElButton>
-
-    <ElButton @click="reserveIndex(true)">{{ t('tableDemo.reserveIndex') }}</ElButton>
-    <ElButton @click="reserveIndex(false)">{{ t('tableDemo.restoreIndex') }}</ElButton>
-
-    <ElButton @click="showSelections(true)">{{ t('tableDemo.showSelections') }}</ElButton>
-    <ElButton @click="showSelections(false)">{{ t('tableDemo.hiddenSelections') }}</ElButton>
-
-    <ElButton @click="changeTitle">{{ t('tableDemo.changeTitle') }}</ElButton>
-
-    <ElButton @click="showExpandedRows(true)">{{ t('tableDemo.showExpandedRows') }}</ElButton>
-    <ElButton @click="showExpandedRows(false)">{{ t('tableDemo.hiddenExpandedRows') }}</ElButton>
-
-    <ElButton @click="selectAllNone">{{ t('tableDemo.selectAllNone') }}</ElButton>
-
-    <ElButton @click="delOrAddAction">{{ t('tableDemo.delOrAddAction') }}</ElButton>
-
-    <ElButton @click="showOrHiddenStripe">{{ t('tableDemo.showOrHiddenStripe') }}</ElButton>
-
-    <ElButton @click="fixedHeaderOrAuto">{{ t('tableDemo.fixedHeaderOrAuto') }}</ElButton>
-
-    <ElButton @click="getSelections">{{ t('tableDemo.getSelections') }}</ElButton>
-
-    <!-- <ElButton @click="showOrHiddenSortable">{{ t('tableDemo.showOrHiddenSortable') }}</ElButton> -->
-  </ContentWrap>
-  <ContentWrap :title="`UseTable ${t('tableDemo.example')}`">
-    <Table
-      v-model:pageSize="pageSize"
-      v-model:currentPage="currentPage"
-      showAction
-      :columns="columns"
-      :data="dataList"
-      :loading="loading"
-      :pagination="
-        canShowPagination
-          ? {
-              total: total
-            }
-          : undefined
-      "
-      @register="tableRegister"
-      @refresh="refresh"
-    />
-  </ContentWrap>
-</template>
-
-<style lang="less" scoped>
-.el-button {
-  margin-top: 10px;
-}
-</style>

+ 0 - 127
src/views/Dashboard/Analysis.vue

@@ -1,127 +0,0 @@
-<script setup lang="ts">
-import PanelGroup from './components/PanelGroup.vue'
-import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus'
-import { Echart } from '@/components/Echart'
-import { pieOptions, barOptions, lineOptions } from './echarts-data'
-import { ref, reactive } from 'vue'
-import {
-  getUserAccessSourceApi,
-  getWeeklyUserActivityApi,
-  getMonthlySalesApi
-} from '@/api/dashboard/analysis'
-import { set } from 'lodash-es'
-import { EChartsOption } from 'echarts'
-import { useI18n } from '@/hooks/web/useI18n'
-
-const { t } = useI18n()
-
-const loading = ref(true)
-
-const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
-
-// 用户来源
-const getUserAccessSource = async () => {
-  const res = await getUserAccessSourceApi().catch(() => {})
-  if (res) {
-    set(
-      pieOptionsData,
-      'legend.data',
-      res.data.map((v) => t(v.name))
-    )
-    pieOptionsData!.series![0].data = res.data.map((v) => {
-      return {
-        name: t(v.name),
-        value: v.value
-      }
-    })
-  }
-}
-
-const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
-
-// 周活跃量
-const getWeeklyUserActivity = async () => {
-  const res = await getWeeklyUserActivityApi().catch(() => {})
-  if (res) {
-    set(
-      barOptionsData,
-      'xAxis.data',
-      res.data.map((v) => t(v.name))
-    )
-    set(barOptionsData, 'series', [
-      {
-        name: t('analysis.activeQuantity'),
-        data: res.data.map((v) => v.value),
-        type: 'bar'
-      }
-    ])
-  }
-}
-
-const lineOptionsData = reactive<EChartsOption>(lineOptions) as EChartsOption
-
-// 每月销售总额
-const getMonthlySales = async () => {
-  const res = await getMonthlySalesApi().catch(() => {})
-  if (res) {
-    set(
-      lineOptionsData,
-      'xAxis.data',
-      res.data.map((v) => t(v.name))
-    )
-    set(lineOptionsData, 'series', [
-      {
-        name: t('analysis.estimate'),
-        smooth: true,
-        type: 'line',
-        data: res.data.map((v) => v.estimate),
-        animationDuration: 2800,
-        animationEasing: 'cubicInOut'
-      },
-      {
-        name: t('analysis.actual'),
-        smooth: true,
-        type: 'line',
-        itemStyle: {},
-        data: res.data.map((v) => v.actual),
-        animationDuration: 2800,
-        animationEasing: 'quadraticOut'
-      }
-    ])
-  }
-}
-
-const getAllApi = async () => {
-  await Promise.all([getUserAccessSource(), getWeeklyUserActivity(), getMonthlySales()])
-  loading.value = false
-}
-
-getAllApi()
-</script>
-
-<template>
-  <PanelGroup />
-  <ElRow :gutter="20" justify="space-between">
-    <ElCol :xl="10" :lg="10" :md="24" :sm="24" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated>
-          <Echart :options="pieOptionsData" :height="300" />
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-    <ElCol :xl="14" :lg="14" :md="24" :sm="24" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated>
-          <Echart :options="barOptionsData" :height="300" />
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-    <ElCol :span="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated :rows="4">
-          <Echart :options="lineOptionsData" :height="350" />
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-  </ElRow>
-</template>

+ 0 - 293
src/views/Dashboard/Workplace.vue

@@ -1,293 +0,0 @@
-<script setup lang="ts">
-import { useTimeAgo } from '@/hooks/web/useTimeAgo'
-import { ElRow, ElCol, ElSkeleton, ElCard, ElDivider, ElLink } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ref, reactive } from 'vue'
-import { CountTo } from '@/components/CountTo'
-import { formatTime } from '@/utils'
-import { Echart } from '@/components/Echart'
-import { EChartsOption } from 'echarts'
-import { radarOption } from './echarts-data'
-import { Highlight } from '@/components/Highlight'
-import {
-  getCountApi,
-  getProjectApi,
-  getDynamicApi,
-  getTeamApi,
-  getRadarApi
-} from '@/api/dashboard/workplace'
-import type { WorkplaceTotal, Project, Dynamic, Team } from '@/api/dashboard/workplace/types'
-import { set } from 'lodash-es'
-
-const loading = ref(true)
-
-// 获取统计数
-let totalSate = reactive<WorkplaceTotal>({
-  project: 0,
-  access: 0,
-  todo: 0
-})
-
-const getCount = async () => {
-  const res = await getCountApi().catch(() => {})
-  if (res) {
-    totalSate = Object.assign(totalSate, res.data)
-  }
-}
-
-let projects = reactive<Project[]>([])
-
-// 获取项目数
-const getProject = async () => {
-  const res = await getProjectApi().catch(() => {})
-  if (res) {
-    projects = Object.assign(projects, res.data)
-  }
-}
-
-// 获取动态
-let dynamics = reactive<Dynamic[]>([])
-
-const getDynamic = async () => {
-  const res = await getDynamicApi().catch(() => {})
-  if (res) {
-    dynamics = Object.assign(dynamics, res.data)
-  }
-}
-
-// 获取团队
-let team = reactive<Team[]>([])
-
-const getTeam = async () => {
-  const res = await getTeamApi().catch(() => {})
-  if (res) {
-    team = Object.assign(team, res.data)
-  }
-}
-
-// 获取指数
-let radarOptionData = reactive<EChartsOption>(radarOption) as EChartsOption
-
-const getRadar = async () => {
-  const res = await getRadarApi().catch(() => {})
-  if (res) {
-    set(
-      radarOptionData,
-      'radar.indicator',
-      res.data.map((v) => {
-        return {
-          name: t(v.name),
-          max: v.max
-        }
-      })
-    )
-    set(radarOptionData, 'series', [
-      {
-        name: `xxx${t('workplace.index')}`,
-        type: 'radar',
-        data: [
-          {
-            value: res.data.map((v) => v.personal),
-            name: t('workplace.personal')
-          },
-          {
-            value: res.data.map((v) => v.team),
-            name: t('workplace.team')
-          }
-        ]
-      }
-    ])
-  }
-}
-
-const getAllApi = async () => {
-  await Promise.all([getCount(), getProject(), getDynamic(), getTeam(), getRadar()])
-  loading.value = false
-}
-
-getAllApi()
-
-const { t } = useI18n()
-</script>
-
-<template>
-  <div>
-    <ElCard shadow="never">
-      <ElSkeleton :loading="loading" animated>
-        <ElRow :gutter="20" justify="space-between">
-          <ElCol :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex items-center">
-              <img
-                src="@/assets/imgs/avatar.jpg"
-                alt=""
-                class="w-70px h-70px rounded-[50%] mr-20px"
-              />
-              <div>
-                <div class="text-20px">
-                  {{ t('workplace.goodMorning') }},Archer,{{ t('workplace.happyDay') }}
-                </div>
-                <div class="mt-10px text-14px text-gray-500">
-                  {{ t('workplace.toady') }},20℃ - 32℃!
-                </div>
-              </div>
-            </div>
-          </ElCol>
-          <ElCol :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex h-70px items-center justify-end lt-sm:mt-20px">
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.project"
-                  :duration="2600"
-                />
-              </div>
-              <ElDivider direction="vertical" />
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.toDo') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.todo"
-                  :duration="2600"
-                />
-              </div>
-              <ElDivider direction="vertical" border-style="dashed" />
-              <div class="px-8px text-right">
-                <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.access') }}</div>
-                <CountTo
-                  class="text-20px"
-                  :start-val="0"
-                  :end-val="totalSate.access"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </ElCol>
-        </ElRow>
-      </ElSkeleton>
-    </ElCard>
-  </div>
-
-  <ElRow class="mt-20px" :gutter="20" justify="space-between">
-    <ElCol :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-20px">
-      <ElCard shadow="never">
-        <template #header>
-          <div class="flex justify-between">
-            <span>{{ t('workplace.project') }}</span>
-            <ElLink type="primary" :underline="false">{{ t('workplace.more') }}</ElLink>
-          </div>
-        </template>
-        <ElSkeleton :loading="loading" animated>
-          <ElRow>
-            <ElCol
-              v-for="(item, index) in projects"
-              :key="`card-${index}`"
-              :xl="8"
-              :lg="8"
-              :md="12"
-              :sm="24"
-              :xs="24"
-            >
-              <ElCard shadow="hover">
-                <div class="flex items-center">
-                  <Icon :icon="item.icon" :size="25" class="mr-10px" />
-                  <span class="text-16px">{{ item.name }}</span>
-                </div>
-                <div class="mt-15px text-14px text-gray-400">{{ t(item.message) }}</div>
-                <div class="mt-20px text-12px text-gray-400 flex justify-between">
-                  <span>{{ item.personal }}</span>
-                  <span>{{ formatTime(item.time, 'yyyy-MM-dd') }}</span>
-                </div>
-              </ElCard>
-            </ElCol>
-          </ElRow>
-        </ElSkeleton>
-      </ElCard>
-
-      <ElCard shadow="never" class="mt-20px">
-        <template #header>
-          <div class="flex justify-between">
-            <span>{{ t('workplace.dynamic') }}</span>
-            <ElLink type="primary" :underline="false">{{ t('workplace.more') }}</ElLink>
-          </div>
-        </template>
-        <ElSkeleton :loading="loading" animated>
-          <div v-for="(item, index) in dynamics" :key="`dynamics-${index}`">
-            <div class="flex items-center">
-              <img
-                src="@/assets/imgs/avatar.jpg"
-                alt=""
-                class="w-35px h-35px rounded-[50%] mr-20px"
-              />
-              <div>
-                <div class="text-14px">
-                  <Highlight :keys="item.keys.map((v) => t(v))">
-                    {{ t('workplace.pushCode') }}
-                  </Highlight>
-                </div>
-                <div class="mt-15px text-12px text-gray-400">
-                  {{ useTimeAgo(item.time) }}
-                </div>
-              </div>
-            </div>
-            <ElDivider />
-          </div>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-    <ElCol :xl="8" :lg="8" :md="24" :sm="24" :xs="24" class="mb-20px">
-      <ElCard shadow="never">
-        <template #header>
-          <span>{{ t('workplace.shortcutOperation') }}</span>
-        </template>
-        <ElSkeleton :loading="loading" animated>
-          <ElRow>
-            <ElCol
-              v-for="item in 9"
-              :key="`card-${item}`"
-              :xl="12"
-              :lg="12"
-              :md="12"
-              :sm="24"
-              :xs="24"
-              class="mb-10px"
-            >
-              <ElLink type="default" :underline="false">
-                {{ t('workplace.operation') }}{{ item }}
-              </ElLink>
-            </ElCol>
-          </ElRow>
-        </ElSkeleton>
-      </ElCard>
-
-      <ElCard shadow="never" class="mt-20px">
-        <template #header>
-          <span>xx{{ t('workplace.index') }}</span>
-        </template>
-        <ElSkeleton :loading="loading" animated>
-          <Echart :options="radarOptionData" :height="400" />
-        </ElSkeleton>
-      </ElCard>
-
-      <ElCard shadow="never" class="mt-20px">
-        <template #header>
-          <span>{{ t('workplace.team') }}</span>
-        </template>
-        <ElSkeleton :loading="loading" animated>
-          <ElRow>
-            <ElCol v-for="item in team" :key="`team-${item.name}`" :span="12" class="mb-20px">
-              <div class="flex items-center">
-                <Icon :icon="item.icon" class="mr-10px" />
-                <ElLink type="default" :underline="false">
-                  {{ item.name }}
-                </ElLink>
-              </div>
-            </ElCol>
-          </ElRow>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-  </ElRow>
-</template>

+ 0 - 200
src/views/Dashboard/components/PanelGroup.vue

@@ -1,200 +0,0 @@
-<script setup lang="ts">
-import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus'
-import { CountTo } from '@/components/CountTo'
-import { useDesign } from '@/hooks/web/useDesign'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ref, reactive } from 'vue'
-import { getCountApi } from '@/api/dashboard/analysis'
-import type { AnalysisTotalTypes } from '@/api/dashboard/analysis/types'
-
-const { t } = useI18n()
-
-const { getPrefixCls } = useDesign()
-
-const prefixCls = getPrefixCls('panel')
-
-const loading = ref(true)
-
-let totalState = reactive<AnalysisTotalTypes>({
-  users: 0,
-  messages: 0,
-  moneys: 0,
-  shoppings: 0
-})
-
-const getCount = async () => {
-  const res = await getCountApi()
-    .catch(() => {})
-    .finally(() => {
-      loading.value = false
-    })
-  totalState = Object.assign(totalState, res?.data || {})
-}
-
-getCount()
-</script>
-
-<template>
-  <ElRow :gutter="20" justify="space-between" :class="prefixCls">
-    <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated :rows="2">
-          <template #default>
-            <div :class="`${prefixCls}__item flex justify-between`">
-              <div>
-                <div
-                  :class="`${prefixCls}__item--icon ${prefixCls}__item--peoples p-16px inline-block rounded-6px`"
-                >
-                  <Icon icon="svg-icon:peoples" :size="40" />
-                </div>
-              </div>
-              <div class="flex flex-col justify-between">
-                <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
-                  t('analysis.newUser')
-                }}</div>
-                <CountTo
-                  class="text-20px font-700 text-right"
-                  :start-val="0"
-                  :end-val="102400"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </template>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-
-    <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated :rows="2">
-          <template #default>
-            <div :class="`${prefixCls}__item flex justify-between`">
-              <div>
-                <div
-                  :class="`${prefixCls}__item--icon ${prefixCls}__item--message p-16px inline-block rounded-6px`"
-                >
-                  <Icon icon="svg-icon:message" :size="40" />
-                </div>
-              </div>
-              <div class="flex flex-col justify-between">
-                <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
-                  t('analysis.unreadInformation')
-                }}</div>
-                <CountTo
-                  class="text-20px font-700 text-right"
-                  :start-val="0"
-                  :end-val="81212"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </template>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-
-    <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated :rows="2">
-          <template #default>
-            <div :class="`${prefixCls}__item flex justify-between`">
-              <div>
-                <div
-                  :class="`${prefixCls}__item--icon ${prefixCls}__item--money p-16px inline-block rounded-6px`"
-                >
-                  <Icon icon="svg-icon:money" :size="40" />
-                </div>
-              </div>
-              <div class="flex flex-col justify-between">
-                <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
-                  t('analysis.transactionAmount')
-                }}</div>
-                <CountTo
-                  class="text-20px font-700 text-right"
-                  :start-val="0"
-                  :end-val="9280"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </template>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-
-    <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
-      <ElCard shadow="hover" class="mb-20px">
-        <ElSkeleton :loading="loading" animated :rows="2">
-          <template #default>
-            <div :class="`${prefixCls}__item flex justify-between`">
-              <div>
-                <div
-                  :class="`${prefixCls}__item--icon ${prefixCls}__item--shopping p-16px inline-block rounded-6px`"
-                >
-                  <Icon icon="svg-icon:shopping" :size="40" />
-                </div>
-              </div>
-              <div class="flex flex-col justify-between">
-                <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
-                  t('analysis.totalShopping')
-                }}</div>
-                <CountTo
-                  class="text-20px font-700 text-right"
-                  :start-val="0"
-                  :end-val="13600"
-                  :duration="2600"
-                />
-              </div>
-            </div>
-          </template>
-        </ElSkeleton>
-      </ElCard>
-    </ElCol>
-  </ElRow>
-</template>
-
-<style lang="less" scoped>
-@prefix-cls: ~'@{namespace}-panel';
-
-.@{prefix-cls} {
-  &__item {
-    &--peoples {
-      color: #40c9c6;
-    }
-
-    &--message {
-      color: #36a3f7;
-    }
-
-    &--money {
-      color: #f4516c;
-    }
-
-    &--shopping {
-      color: #34bfa3;
-    }
-
-    &:hover {
-      :deep(.@{namespace}-icon) {
-        color: #fff !important;
-      }
-      .@{prefix-cls}__item--icon {
-        transition: all 0.38s ease-out;
-      }
-      .@{prefix-cls}__item--peoples {
-        background: #40c9c6;
-      }
-      .@{prefix-cls}__item--message {
-        background: #36a3f7;
-      }
-      .@{prefix-cls}__item--money {
-        background: #f4516c;
-      }
-      .@{prefix-cls}__item--shopping {
-        background: #34bfa3;
-      }
-    }
-  }
-}
-</style>

+ 0 - 309
src/views/Dashboard/echarts-data.ts

@@ -1,309 +0,0 @@
-import { EChartsOption } from 'echarts'
-import { useI18n } from '@/hooks/web/useI18n'
-
-const { t } = useI18n()
-
-export const lineOptions: EChartsOption = {
-  title: {
-    text: t('analysis.monthlySales'),
-    left: 'center'
-  },
-  xAxis: {
-    data: [
-      t('analysis.january'),
-      t('analysis.february'),
-      t('analysis.march'),
-      t('analysis.april'),
-      t('analysis.may'),
-      t('analysis.june'),
-      t('analysis.july'),
-      t('analysis.august'),
-      t('analysis.september'),
-      t('analysis.october'),
-      t('analysis.november'),
-      t('analysis.december')
-    ],
-    boundaryGap: false,
-    axisTick: {
-      show: false
-    }
-  },
-  grid: {
-    left: 20,
-    right: 20,
-    bottom: 20,
-    top: 80,
-    containLabel: true
-  },
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'cross'
-    },
-    padding: [5, 10]
-  },
-  yAxis: {
-    axisTick: {
-      show: false
-    }
-  },
-  legend: {
-    data: [t('analysis.estimate'), t('analysis.actual')],
-    top: 50
-  },
-  series: [
-    {
-      name: t('analysis.estimate'),
-      smooth: true,
-      type: 'line',
-      data: [100, 120, 161, 134, 105, 160, 165, 114, 163, 185, 118, 123],
-      animationDuration: 2800,
-      animationEasing: 'cubicInOut'
-    },
-    {
-      name: t('analysis.actual'),
-      smooth: true,
-      type: 'line',
-      itemStyle: {},
-      data: [120, 82, 91, 154, 162, 140, 145, 250, 134, 56, 99, 123],
-      animationDuration: 2800,
-      animationEasing: 'quadraticOut'
-    }
-  ]
-}
-
-export const pieOptions: EChartsOption = {
-  title: {
-    text: t('analysis.userAccessSource'),
-    left: 'center'
-  },
-  tooltip: {
-    trigger: 'item',
-    formatter: '{a} <br/>{b} : {c} ({d}%)'
-  },
-  legend: {
-    orient: 'vertical',
-    left: 'left',
-    data: [
-      t('analysis.directAccess'),
-      t('analysis.mailMarketing'),
-      t('analysis.allianceAdvertising'),
-      t('analysis.videoAdvertising'),
-      t('analysis.searchEngines')
-    ]
-  },
-  series: [
-    {
-      name: t('analysis.userAccessSource'),
-      type: 'pie',
-      radius: '55%',
-      center: ['50%', '60%'],
-      data: [
-        { value: 335, name: t('analysis.directAccess') },
-        { value: 310, name: t('analysis.mailMarketing') },
-        { value: 234, name: t('analysis.allianceAdvertising') },
-        { value: 135, name: t('analysis.videoAdvertising') },
-        { value: 1548, name: t('analysis.searchEngines') }
-      ]
-    }
-  ]
-}
-
-export const barOptions: EChartsOption = {
-  title: {
-    text: t('analysis.weeklyUserActivity'),
-    left: 'center'
-  },
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: 50,
-    right: 20,
-    bottom: 20
-  },
-  xAxis: {
-    type: 'category',
-    data: [
-      t('analysis.monday'),
-      t('analysis.tuesday'),
-      t('analysis.wednesday'),
-      t('analysis.thursday'),
-      t('analysis.friday'),
-      t('analysis.saturday'),
-      t('analysis.sunday')
-    ],
-    axisTick: {
-      alignWithLabel: true
-    }
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      name: t('analysis.activeQuantity'),
-      data: [13253, 34235, 26321, 12340, 24643, 1322, 1324],
-      type: 'bar'
-    }
-  ]
-}
-
-export const radarOption: EChartsOption = {
-  legend: {
-    data: [t('workplace.personal'), t('workplace.team')]
-  },
-  radar: {
-    // shape: 'circle',
-    indicator: [
-      { name: t('workplace.quote'), max: 65 },
-      { name: t('workplace.contribution'), max: 160 },
-      { name: t('workplace.hot'), max: 300 },
-      { name: t('workplace.yield'), max: 130 },
-      { name: t('workplace.follow'), max: 100 }
-    ]
-  },
-  series: [
-    {
-      name: `xxx${t('workplace.index')}`,
-      type: 'radar',
-      data: [
-        {
-          value: [42, 30, 20, 35, 80],
-          name: t('workplace.personal')
-        },
-        {
-          value: [50, 140, 290, 100, 90],
-          name: t('workplace.team')
-        }
-      ]
-    }
-  ]
-}
-
-export const wordOptions = {
-  series: [
-    {
-      type: 'wordCloud',
-      gridSize: 2,
-      sizeRange: [12, 50],
-      rotationRange: [-90, 90],
-      shape: 'pentagon',
-      width: 600,
-      height: 400,
-      drawOutOfBound: true,
-      textStyle: {
-        color: function () {
-          return (
-            'rgb(' +
-            [
-              Math.round(Math.random() * 160),
-              Math.round(Math.random() * 160),
-              Math.round(Math.random() * 160)
-            ].join(',') +
-            ')'
-          )
-        }
-      },
-      emphasis: {
-        textStyle: {
-          shadowBlur: 10,
-          shadowColor: '#333'
-        }
-      },
-      data: [
-        {
-          name: 'Sam S Club',
-          value: 10000,
-          textStyle: {
-            color: 'black'
-          },
-          emphasis: {
-            textStyle: {
-              color: 'red'
-            }
-          }
-        },
-        {
-          name: 'Macys',
-          value: 6181
-        },
-        {
-          name: 'Amy Schumer',
-          value: 4386
-        },
-        {
-          name: 'Jurassic World',
-          value: 4055
-        },
-        {
-          name: 'Charter Communications',
-          value: 2467
-        },
-        {
-          name: 'Chick Fil A',
-          value: 2244
-        },
-        {
-          name: 'Planet Fitness',
-          value: 1898
-        },
-        {
-          name: 'Pitch Perfect',
-          value: 1484
-        },
-        {
-          name: 'Express',
-          value: 1112
-        },
-        {
-          name: 'Home',
-          value: 965
-        },
-        {
-          name: 'Johnny Depp',
-          value: 847
-        },
-        {
-          name: 'Lena Dunham',
-          value: 582
-        },
-        {
-          name: 'Lewis Hamilton',
-          value: 555
-        },
-        {
-          name: 'KXAN',
-          value: 550
-        },
-        {
-          name: 'Mary Ellen Mark',
-          value: 462
-        },
-        {
-          name: 'Farrah Abraham',
-          value: 366
-        },
-        {
-          name: 'Rita Ora',
-          value: 360
-        },
-        {
-          name: 'Serena Williams',
-          value: 282
-        },
-        {
-          name: 'NCAA baseball tournament',
-          value: 273
-        },
-        {
-          name: 'Point Break',
-          value: 265
-        }
-      ]
-    }
-  ]
-}

+ 0 - 17
src/views/Error/403.vue

@@ -1,17 +0,0 @@
-<script setup lang="ts">
-import { Error } from '@/components/Error'
-import { usePermissionStore } from '@/store/modules/permission'
-import { useRouter } from 'vue-router'
-
-const { push } = useRouter()
-
-const permissionStore = usePermissionStore()
-
-const errorClick = () => {
-  push(permissionStore.addRouters[0]?.path as string)
-}
-</script>
-
-<template>
-  <Error type="403" @error-click="errorClick" />
-</template>

+ 0 - 17
src/views/Error/404.vue

@@ -1,17 +0,0 @@
-<script setup lang="ts">
-import { Error } from '@/components/Error'
-import { usePermissionStore } from '@/store/modules/permission'
-import { useRouter } from 'vue-router'
-
-const { push } = useRouter()
-
-const permissionStore = usePermissionStore()
-
-const errorClick = () => {
-  push(permissionStore.addRouters[0]?.path as string)
-}
-</script>
-
-<template>
-  <Error @error-click="errorClick" />
-</template>

+ 0 - 17
src/views/Error/500.vue

@@ -1,17 +0,0 @@
-<script setup lang="ts">
-import { Error } from '@/components/Error'
-import { usePermissionStore } from '@/store/modules/permission'
-import { useRouter } from 'vue-router'
-
-const { push } = useRouter()
-
-const permissionStore = usePermissionStore()
-
-const errorClick = () => {
-  push(permissionStore.addRouters[0]?.path as string)
-}
-</script>
-
-<template>
-  <Error type="500" @error-click="errorClick" />
-</template>

+ 0 - 324
src/views/Example/Dialog/ExampleDialog.vue

@@ -1,324 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { Search } from '@/components/Search'
-import { Dialog } from '@/components/Dialog'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ElButton, ElTag } from 'element-plus'
-import { Table, TableColumn } from '@/components/Table'
-import { getTableListApi, saveTableApi, delTableListApi } from '@/api/table'
-import { useTable } from '@/hooks/web/useTable'
-import { TableData } from '@/api/table/types'
-import { h, ref, unref, reactive } from 'vue'
-import Write from './components/Write.vue'
-import Detail from './components/Detail.vue'
-import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
-
-const ids = ref<string[]>([])
-
-const { tableRegister, tableState, tableMethods } = useTable({
-  fetchDataApi: async () => {
-    const { currentPage, pageSize } = tableState
-    const res = await getTableListApi({
-      pageIndex: unref(currentPage),
-      pageSize: unref(pageSize),
-      ...unref(searchParams)
-    })
-    return {
-      list: res.data.list,
-      total: res.data.total
-    }
-  },
-  fetchDelApi: async () => {
-    const res = await delTableListApi(unref(ids))
-    return !!res
-  }
-})
-const { loading, dataList, total, currentPage, pageSize } = tableState
-const { getList, getElTableExpose, delList } = tableMethods
-
-const searchParams = ref({})
-const setSearchParams = (params: any) => {
-  searchParams.value = params
-  getList()
-}
-
-const { t } = useI18n()
-
-const crudSchemas = reactive<CrudSchema[]>([
-  {
-    field: 'selection',
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      type: 'selection'
-    }
-  },
-  {
-    field: 'index',
-    label: t('tableDemo.index'),
-    type: 'index',
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    }
-  },
-  {
-    field: 'title',
-    label: t('tableDemo.title'),
-    search: {
-      component: 'Input'
-    },
-    form: {
-      component: 'Input',
-      colProps: {
-        span: 24
-      }
-    },
-    detail: {
-      span: 24
-    }
-  },
-  {
-    field: 'author',
-    label: t('tableDemo.author')
-  },
-  {
-    field: 'display_time',
-    label: t('tableDemo.displayTime'),
-    form: {
-      component: 'DatePicker',
-      componentProps: {
-        type: 'datetime',
-        valueFormat: 'YYYY-MM-DD HH:mm:ss'
-      }
-    }
-  },
-  {
-    field: 'importance',
-    label: t('tableDemo.importance'),
-    formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-      return h(
-        ElTag,
-        {
-          type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
-        },
-        () =>
-          cellValue === 1
-            ? t('tableDemo.important')
-            : cellValue === 2
-            ? t('tableDemo.good')
-            : t('tableDemo.commonly')
-      )
-    },
-    form: {
-      component: 'Select',
-      componentProps: {
-        style: {
-          width: '100%'
-        },
-        options: [
-          {
-            label: '重要',
-            value: 3
-          },
-          {
-            label: '良好',
-            value: 2
-          },
-          {
-            label: '一般',
-            value: 1
-          }
-        ]
-      }
-    },
-    detail: {
-      slots: {
-        default: (data: any) => {
-          return (
-            <ElTag
-              type={
-                data.importance === 1 ? 'success' : data.importance === 2 ? 'warning' : 'danger'
-              }
-            >
-              {data.importance === 1
-                ? t('tableDemo.important')
-                : data.importance === 2
-                ? t('tableDemo.good')
-                : t('tableDemo.commonly')}
-            </ElTag>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('tableDemo.pageviews'),
-    form: {
-      component: 'InputNumber',
-      value: 0
-    }
-  },
-  {
-    field: 'content',
-    label: t('exampleDemo.content'),
-    table: {
-      show: false
-    },
-    form: {
-      component: 'Editor',
-      colProps: {
-        span: 24
-      }
-    },
-    detail: {
-      span: 24,
-      slots: {
-        default: (data: any) => {
-          return <div innerHTML={data.content}></div>
-        }
-      }
-    }
-  },
-  {
-    field: 'action',
-    width: '260px',
-    label: t('tableDemo.action'),
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      slots: {
-        default: (data: any) => {
-          return (
-            <>
-              <ElButton type="primary" onClick={() => action(data[0].row, 'edit')}>
-                {t('exampleDemo.edit')}
-              </ElButton>
-              <ElButton type="success" onClick={() => action(data[0].row, 'detail')}>
-                {t('exampleDemo.detail')}
-              </ElButton>
-              <ElButton type="danger" onClick={() => delData(data[0].row)}>
-                {t('exampleDemo.del')}
-              </ElButton>
-            </>
-          )
-        }
-      }
-    }
-  }
-])
-
-// @ts-ignore
-const { allSchemas } = useCrudSchemas(crudSchemas)
-
-const dialogVisible = ref(false)
-const dialogTitle = ref('')
-
-const currentRow = ref<TableData | null>(null)
-const actionType = ref('')
-
-const AddAction = () => {
-  dialogTitle.value = t('exampleDemo.add')
-  currentRow.value = null
-  dialogVisible.value = true
-  actionType.value = ''
-}
-
-const delLoading = ref(false)
-
-const delData = async (row: TableData | null) => {
-  const elTableExpose = await getElTableExpose()
-  ids.value = row ? [row.id] : elTableExpose?.getSelectionRows().map((v: TableData) => v.id) || []
-  delLoading.value = true
-  await delList(unref(ids).length).finally(() => {
-    delLoading.value = false
-  })
-}
-
-const action = (row: TableData, type: string) => {
-  dialogTitle.value = t(type === 'edit' ? 'exampleDemo.edit' : 'exampleDemo.detail')
-  actionType.value = type
-  currentRow.value = row
-  dialogVisible.value = true
-}
-
-const writeRef = ref<ComponentRef<typeof Write>>()
-
-const saveLoading = ref(false)
-
-const save = async () => {
-  const write = unref(writeRef)
-  const formData = await write?.submit()
-  if (formData) {
-    saveLoading.value = true
-    const res = await saveTableApi(formData)
-      .catch(() => {})
-      .finally(() => {
-        saveLoading.value = false
-      })
-    if (res) {
-      dialogVisible.value = false
-      currentPage.value = 1
-      getList()
-    }
-  }
-}
-</script>
-
-<template>
-  <ContentWrap>
-    <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
-
-    <div class="mb-10px">
-      <ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
-      <ElButton :loading="delLoading" type="danger" @click="delData(null)">
-        {{ t('exampleDemo.del') }}
-      </ElButton>
-    </div>
-
-    <Table
-      v-model:pageSize="pageSize"
-      v-model:currentPage="currentPage"
-      :columns="allSchemas.tableColumns"
-      :data="dataList"
-      :loading="loading"
-      :pagination="{
-        total: total
-      }"
-      @register="tableRegister"
-    />
-  </ContentWrap>
-
-  <Dialog v-model="dialogVisible" :title="dialogTitle">
-    <Write
-      v-if="actionType !== 'detail'"
-      ref="writeRef"
-      :form-schema="allSchemas.formSchema"
-      :current-row="currentRow"
-    />
-
-    <Detail
-      v-if="actionType === 'detail'"
-      :detail-schema="allSchemas.detailSchema"
-      :current-row="currentRow"
-    />
-
-    <template #footer>
-      <ElButton v-if="actionType !== 'detail'" type="primary" :loading="saveLoading" @click="save">
-        {{ t('exampleDemo.save') }}
-      </ElButton>
-      <ElButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</ElButton>
-    </template>
-  </Dialog>
-</template>

+ 0 - 20
src/views/Example/Dialog/components/Detail.vue

@@ -1,20 +0,0 @@
-<script setup lang="ts">
-import { PropType } from 'vue'
-import type { TableData } from '@/api/table/types'
-import { Descriptions, DescriptionsSchema } from '@/components/Descriptions'
-
-defineProps({
-  currentRow: {
-    type: Object as PropType<Nullable<TableData>>,
-    default: () => null
-  },
-  detailSchema: {
-    type: Array as PropType<DescriptionsSchema[]>,
-    default: () => []
-  }
-})
-</script>
-
-<template>
-  <Descriptions :schema="detailSchema" :data="currentRow || {}" />
-</template>

+ 0 - 63
src/views/Example/Dialog/components/Write.vue

@@ -1,63 +0,0 @@
-<script setup lang="ts">
-import { Form, FormSchema } from '@/components/Form'
-import { useForm } from '@/hooks/web/useForm'
-import { PropType, reactive, watch } from 'vue'
-import { TableData } from '@/api/table/types'
-import { useValidator } from '@/hooks/web/useValidator'
-
-const { required } = useValidator()
-
-const props = defineProps({
-  currentRow: {
-    type: Object as PropType<Nullable<TableData>>,
-    default: () => null
-  },
-  formSchema: {
-    type: Array as PropType<FormSchema[]>,
-    default: () => []
-  }
-})
-
-const rules = reactive({
-  title: [required()],
-  author: [required()],
-  importance: [required()],
-  pageviews: [required()],
-  display_time: [required()],
-  content: [required()]
-})
-
-const { formRegister, formMethods } = useForm()
-const { setValues, getFormData, getElFormExpose } = formMethods
-
-const submit = async () => {
-  const elForm = await getElFormExpose()
-  const valid = await elForm?.validate().catch((err) => {
-    console.log(err)
-  })
-  if (valid) {
-    const formData = getFormData()
-    return formData
-  }
-}
-
-watch(
-  () => props.currentRow,
-  (currentRow) => {
-    if (!currentRow) return
-    setValues(currentRow)
-  },
-  {
-    deep: true,
-    immediate: true
-  }
-)
-
-defineExpose({
-  submit
-})
-</script>
-
-<template>
-  <Form :rules="rules" @register="formRegister" :schema="formSchema" />
-</template>

+ 0 - 53
src/views/Example/Page/ExampleAdd.vue

@@ -1,53 +0,0 @@
-<script setup lang="ts">
-import Write from './components/Write.vue'
-import { ContentDetailWrap } from '@/components/ContentDetailWrap'
-import { ref, unref } from 'vue'
-import { ElButton } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useRouter } from 'vue-router'
-import { saveTableApi } from '@/api/table'
-import { useEmitt } from '@/hooks/event/useEmitt'
-
-const { emitter } = useEmitt()
-
-const { push, go } = useRouter()
-
-const { t } = useI18n()
-
-const writeRef = ref<ComponentRef<typeof Write>>()
-
-const loading = ref(false)
-
-const save = async () => {
-  const write = unref(writeRef)
-  const formData = await write?.submit()
-  if (formData) {
-    loading.value = true
-    const res = await saveTableApi(formData)
-      .catch(() => {})
-      .finally(() => {
-        loading.value = false
-      })
-    if (res) {
-      emitter.emit('getList', 'add')
-      push('/example/example-page')
-    }
-  }
-}
-</script>
-
-<template>
-  <ContentDetailWrap :title="t('exampleDemo.add')" @back="push('/example/example-page')">
-    <Write ref="writeRef" />
-
-    <template #header>
-      <ElButton @click="go(-1)">
-        {{ t('common.back') }}
-      </ElButton>
-      <ElButton type="primary" :loading="loading" @click="save">
-        {{ t('exampleDemo.save') }}
-      </ElButton>
-    </template>
-  </ContentDetailWrap>
-</template>
-@/hooks/event/useEmitt

+ 0 - 38
src/views/Example/Page/ExampleDetail.vue

@@ -1,38 +0,0 @@
-<script setup lang="ts">
-import Detail from './components/Detail.vue'
-import { ContentDetailWrap } from '@/components/ContentDetailWrap'
-import { ref } from 'vue'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useRouter, useRoute } from 'vue-router'
-import { getTableDetApi } from '@/api/table'
-import { TableData } from '@/api/table/types'
-import { ElButton } from 'element-plus'
-
-const { push, go } = useRouter()
-
-const { query } = useRoute()
-
-const { t } = useI18n()
-
-const currentRow = ref<Nullable<TableData>>(null)
-
-const getTableDet = async () => {
-  const res = await getTableDetApi(query.id as string)
-  if (res) {
-    currentRow.value = res.data
-  }
-}
-
-getTableDet()
-</script>
-
-<template>
-  <ContentDetailWrap :title="t('exampleDemo.detail')" @back="push('/example/example-page')">
-    <template #header>
-      <ElButton @click="go(-1)">
-        {{ t('common.back') }}
-      </ElButton>
-    </template>
-    <Detail :current-row="currentRow" />
-  </ContentDetailWrap>
-</template>

+ 0 - 67
src/views/Example/Page/ExampleEdit.vue

@@ -1,67 +0,0 @@
-<script setup lang="ts">
-import Write from './components/Write.vue'
-import { ContentDetailWrap } from '@/components/ContentDetailWrap'
-import { ref, unref } from 'vue'
-import { ElButton } from 'element-plus'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useRouter, useRoute } from 'vue-router'
-import { saveTableApi, getTableDetApi } from '@/api/table'
-import { TableData } from '@/api/table/types'
-import { useEmitt } from '@/hooks/event/useEmitt'
-
-const { emitter } = useEmitt()
-
-const { push, go } = useRouter()
-
-const { query } = useRoute()
-
-const { t } = useI18n()
-
-const currentRow = ref<Nullable<TableData>>(null)
-
-const getTableDet = async () => {
-  const res = await getTableDetApi(query.id as string)
-  if (res) {
-    currentRow.value = res.data
-  }
-}
-
-getTableDet()
-
-const writeRef = ref<ComponentRef<typeof Write>>()
-
-const loading = ref(false)
-
-const save = async () => {
-  const write = unref(writeRef)
-  const formData = await write?.submit()
-  if (formData) {
-    loading.value = true
-    const res = await saveTableApi(formData)
-      .catch(() => {})
-      .finally(() => {
-        loading.value = false
-      })
-    if (res) {
-      emitter.emit('getList', 'editor')
-      push('/example/example-page')
-    }
-  }
-}
-</script>
-
-<template>
-  <ContentDetailWrap :title="t('exampleDemo.edit')" @back="push('/example/example-page')">
-    <Write ref="writeRef" :current-row="currentRow" />
-
-    <template #header>
-      <ElButton @click="go(-1)">
-        {{ t('common.back') }}
-      </ElButton>
-      <ElButton type="primary" :loading="loading" @click="save">
-        {{ t('exampleDemo.save') }}
-      </ElButton>
-    </template>
-  </ContentDetailWrap>
-</template>
-@/hooks/event/useEmitt

+ 0 - 262
src/views/Example/Page/ExamplePage.vue

@@ -1,262 +0,0 @@
-<script setup lang="tsx">
-import { ContentWrap } from '@/components/ContentWrap'
-import { Search } from '@/components/Search'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ElButton, ElTag } from 'element-plus'
-import { Table, TableColumn } from '@/components/Table'
-import { getTableListApi, delTableListApi } from '@/api/table'
-import { useTable } from '@/hooks/web/useTable'
-import { TableData } from '@/api/table/types'
-import { h, reactive, ref, unref } from 'vue'
-import { useRouter } from 'vue-router'
-import { useEmitt } from '@/hooks/event/useEmitt'
-import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
-
-defineOptions({
-  name: 'ExamplePage'
-})
-
-const { push } = useRouter()
-
-const ids = ref<string[]>([])
-
-const searchParams = ref({})
-const setSearchParams = (params: any) => {
-  searchParams.value = params
-  getList()
-}
-
-const { tableRegister, tableState, tableMethods } = useTable({
-  fetchDataApi: async () => {
-    const { currentPage, pageSize } = tableState
-    const res = await getTableListApi({
-      pageIndex: unref(currentPage),
-      pageSize: unref(pageSize),
-      ...unref(searchParams)
-    })
-    return {
-      list: res.data.list,
-      total: res.data.total
-    }
-  },
-  fetchDelApi: async () => {
-    const res = await delTableListApi(unref(ids))
-    return !!res
-  }
-})
-const { loading, dataList, total, currentPage, pageSize } = tableState
-const { getList, getElTableExpose, delList } = tableMethods
-
-getList()
-
-useEmitt({
-  name: 'getList',
-  callback: (type: string) => {
-    if (type === 'add') {
-      currentPage.value = 1
-    }
-    getList()
-  }
-})
-
-const { t } = useI18n()
-
-const crudSchemas = reactive<CrudSchema[]>([
-  {
-    field: 'selection',
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      type: 'selection'
-    }
-  },
-  {
-    field: 'index',
-    label: t('tableDemo.index'),
-    type: 'index',
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    }
-  },
-  {
-    field: 'title',
-    label: t('tableDemo.title'),
-    search: {
-      component: 'Input'
-    },
-    form: {
-      component: 'Input',
-      colProps: {
-        span: 24
-      }
-    },
-    detail: {
-      span: 24
-    }
-  },
-  {
-    field: 'author',
-    label: t('tableDemo.author')
-  },
-  {
-    field: 'display_time',
-    label: t('tableDemo.displayTime'),
-    form: {
-      component: 'DatePicker',
-      componentProps: {
-        type: 'datetime',
-        valueFormat: 'YYYY-MM-DD HH:mm:ss'
-      }
-    }
-  },
-  {
-    field: 'importance',
-    label: t('tableDemo.importance'),
-    formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-      return h(
-        ElTag,
-        {
-          type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
-        },
-        () =>
-          cellValue === 1
-            ? t('tableDemo.important')
-            : cellValue === 2
-            ? t('tableDemo.good')
-            : t('tableDemo.commonly')
-      )
-    },
-    form: {
-      component: 'Select',
-      componentProps: {
-        style: {
-          width: '100%'
-        },
-        options: [
-          {
-            label: '重要',
-            value: 3
-          },
-          {
-            label: '良好',
-            value: 2
-          },
-          {
-            label: '一般',
-            value: 1
-          }
-        ]
-      }
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('tableDemo.pageviews'),
-    form: {
-      component: 'InputNumber',
-      value: 0
-    }
-  },
-  {
-    field: 'content',
-    label: t('exampleDemo.content'),
-    table: {
-      hidden: true
-    },
-    form: {
-      component: 'Editor',
-      colProps: {
-        span: 24
-      }
-    },
-    detail: {
-      span: 24
-    }
-  },
-  {
-    field: 'action',
-    width: '260px',
-    label: t('tableDemo.action'),
-    form: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      slots: {
-        default: (data: any) => {
-          return (
-            <>
-              <ElButton type="primary" onClick={() => action(data[0].row, 'edit')}>
-                {t('exampleDemo.edit')}
-              </ElButton>
-              <ElButton type="success" onClick={() => action(data[0].row, 'detail')}>
-                {t('exampleDemo.detail')}
-              </ElButton>
-              <ElButton type="danger" onClick={() => delData(data[0].row)}>
-                {t('exampleDemo.del')}
-              </ElButton>
-            </>
-          )
-        }
-      }
-    }
-  }
-])
-
-// @ts-ignore
-const { allSchemas } = useCrudSchemas(crudSchemas)
-
-const AddAction = () => {
-  push('/example/example-add')
-}
-
-const delLoading = ref(false)
-
-const delData = async (row: TableData | null) => {
-  const elTableExpose = await getElTableExpose()
-  ids.value = row ? [row.id] : elTableExpose?.getSelectionRows().map((v: TableData) => v.id) || []
-  delLoading.value = true
-  await delList(unref(ids).length).finally(() => {
-    delLoading.value = false
-  })
-}
-
-const action = (row: TableData, type: string) => {
-  push(`/example/example-${type}?id=${row.id}`)
-}
-</script>
-
-<template>
-  <ContentWrap>
-    <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
-
-    <div class="mb-10px">
-      <ElButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</ElButton>
-      <ElButton :loading="delLoading" type="danger" @click="delData(null)">
-        {{ t('exampleDemo.del') }}
-      </ElButton>
-    </div>
-
-    <Table
-      v-model:pageSize="pageSize"
-      v-model:currentPage="currentPage"
-      :columns="allSchemas.tableColumns"
-      :data="dataList"
-      :loading="loading"
-      :pagination="{
-        total: total
-      }"
-      @register="tableRegister"
-    />
-  </ContentWrap>
-</template>
-@/hooks/event/useEmitt

+ 0 - 69
src/views/Example/Page/components/Detail.vue

@@ -1,69 +0,0 @@
-<script setup lang="tsx">
-import { PropType, reactive } from 'vue'
-import type { TableData } from '@/api/table/types'
-import { Descriptions, DescriptionsSchema } from '@/components/Descriptions'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ElTag } from 'element-plus'
-
-const { t } = useI18n()
-
-defineProps({
-  currentRow: {
-    type: Object as PropType<Nullable<TableData>>,
-    default: () => null
-  }
-})
-
-const schema = reactive<DescriptionsSchema[]>([
-  {
-    field: 'title',
-    label: t('exampleDemo.title'),
-    span: 24
-  },
-  {
-    field: 'author',
-    label: t('exampleDemo.author')
-  },
-  {
-    field: 'display_time',
-    label: t('exampleDemo.displayTime')
-  },
-  {
-    field: 'importance',
-    label: t('exampleDemo.importance'),
-    slots: {
-      default: (data: any) => {
-        return (
-          <ElTag
-            type={data.importance === 1 ? 'success' : data.importance === 2 ? 'warning' : 'danger'}
-          >
-            {data.importance === 1
-              ? t('tableDemo.important')
-              : data.importance === 2
-              ? t('tableDemo.good')
-              : t('tableDemo.commonly')}
-          </ElTag>
-        )
-      }
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('exampleDemo.pageviews')
-  },
-  {
-    field: 'content',
-    label: t('exampleDemo.content'),
-    span: 24,
-    slots: {
-      default: (data: any) => {
-        return <div innerHTML={data.content}></div>
-      }
-    }
-  }
-])
-</script>
-
-<template>
-  <Descriptions :schema="schema" :data="currentRow || {}" />
-</template>

+ 0 - 154
src/views/Example/Page/components/Write.vue

@@ -1,154 +0,0 @@
-<script setup lang="ts">
-import { Form, FormSchema } from '@/components/Form'
-import { useForm } from '@/hooks/web/useForm'
-import { PropType, reactive, watch } from 'vue'
-import { TableData } from '@/api/table/types'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useValidator } from '@/hooks/web/useValidator'
-import { IDomEditor } from '@wangeditor/editor'
-
-const { required } = useValidator()
-
-const props = defineProps({
-  currentRow: {
-    type: Object as PropType<Nullable<TableData>>,
-    default: () => null
-  }
-})
-
-const { t } = useI18n()
-
-const { formRegister, formMethods } = useForm()
-const { setValues, getFormData, getElFormExpose, setSchema } = formMethods
-
-const schema = reactive<FormSchema[]>([
-  {
-    field: 'title',
-    label: t('exampleDemo.title'),
-    component: 'Input',
-    formItemProps: {
-      rules: [required()]
-    },
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'author',
-    label: t('exampleDemo.author'),
-    component: 'Input',
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'display_time',
-    label: t('exampleDemo.displayTime'),
-    component: 'DatePicker',
-    componentProps: {
-      type: 'datetime',
-      valueFormat: 'YYYY-MM-DD HH:mm:ss'
-    },
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'importance',
-    label: t('exampleDemo.importance'),
-    component: 'Select',
-    formItemProps: {
-      rules: [required()]
-    },
-    componentProps: {
-      options: [
-        {
-          label: '重要',
-          value: 3
-        },
-        {
-          label: '良好',
-          value: 2
-        },
-        {
-          label: '一般',
-          value: 1
-        }
-      ]
-    }
-  },
-  {
-    field: 'pageviews',
-    label: t('exampleDemo.pageviews'),
-    component: 'InputNumber',
-    value: 0,
-    formItemProps: {
-      rules: [required()]
-    }
-  },
-  {
-    field: 'content',
-    component: 'Editor',
-    colProps: {
-      span: 24
-    },
-    componentProps: {
-      defaultHtml: '',
-      // @ts-ignore
-      onChange: (edit: IDomEditor) => {
-        setValues({
-          content: edit.getHtml()
-        })
-      }
-    },
-    label: t('exampleDemo.content')
-  }
-])
-
-const rules = reactive({
-  title: [required()],
-  author: [required()],
-  importance: [required()],
-  pageviews: [required()],
-  display_time: [required()],
-  content: [required()]
-})
-
-const submit = async () => {
-  const elForm = await getElFormExpose()
-  const valid = await elForm?.validate().catch((err) => {
-    console.log(err)
-  })
-  if (valid) {
-    const formData = getFormData()
-    return formData
-  }
-}
-
-watch(
-  () => props.currentRow,
-  (currentRow) => {
-    if (!currentRow) return
-    setValues(currentRow)
-    setSchema([
-      {
-        field: 'content',
-        path: 'componentProps.defaultHtml',
-        value: currentRow.content
-      }
-    ])
-  },
-  {
-    deep: true,
-    immediate: true
-  }
-)
-
-defineExpose({
-  submit
-})
-</script>
-
-<template>
-  <Form :rules="rules" @register="formRegister" :schema="schema" />
-</template>

+ 0 - 20
src/views/Guide/Guide.vue

@@ -1,20 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useIntro } from '@/hooks/web/useIntro'
-import { ElButton } from 'element-plus'
-
-const { t } = useI18n()
-
-const { introRef } = useIntro()
-
-const guideStart = () => {
-  introRef.start()
-}
-</script>
-
-<template>
-  <ContentWrap :title="t('guideDemo.guide')" :message="t('guideDemo.message')">
-    <ElButton type="primary" @click="guideStart">{{ t('guideDemo.start') }}</ElButton>
-  </ContentWrap>
-</template>

+ 0 - 223
src/views/hooks/useCrudSchemas.vue

@@ -1,223 +0,0 @@
-<script setup lang="ts">
-// import { ContentWrap } from '@/components/ContentWrap'
-// import { Search } from '@/components/Search'
-// import { useI18n } from '@/hooks/web/useI18n'
-// import { ElButton, ElTag } from 'element-plus'
-// import { Table } from '@/components/Table'
-// import { getTableListApi, delTableListApi } from '@/api/table'
-// import { useTable } from '@/hooks/web/useTable'
-// import { TableData } from '@/api/table/types'
-// import { h, ref, reactive } from 'vue'
-// import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
-// import { useDictStore } from '@/store/modules/dict'
-// import { getDictOneApi } from '@/api/common'
-// import { TableColumn } from '@/types/table'
-
-// const dictStore = useDictStore()
-
-// const { register, tableObject, methods } = useTable<TableData>({
-//   getListApi: getTableListApi,
-//   delListApi: delTableListApi,
-//   response: {
-//     list: 'list',
-//     total: 'total'
-//   }
-// })
-
-// const { getList, setSearchParams } = methods
-
-// getList()
-
-// const { t } = useI18n()
-
-// const crudSchemas = reactive<CrudSchema[]>([
-//   {
-//     field: 'index',
-//     label: t('tableDemo.index'),
-//     type: 'index',
-//     form: {
-//       show: false
-//     },
-//     detail: {
-//       show: false
-//     }
-//   },
-//   {
-//     field: 'title',
-//     label: t('tableDemo.title'),
-//     search: {
-//       show: true
-//     },
-//     form: {
-//       colProps: {
-//         span: 24
-//       }
-//     },
-//     detail: {
-//       span: 24
-//     }
-//   },
-//   {
-//     field: 'author',
-//     label: t('tableDemo.author')
-//   },
-//   {
-//     field: 'display_time',
-//     label: t('tableDemo.displayTime'),
-//     form: {
-//       component: 'DatePicker',
-//       componentProps: {
-//         type: 'datetime',
-//         valueFormat: 'YYYY-MM-DD HH:mm:ss'
-//       }
-//     }
-//   },
-//   {
-//     field: 'importance',
-//     label: t('tableDemo.importance'),
-//     formatter: (_: Recordable, __: TableColumn, cellValue: number) => {
-//       return h(
-//         ElTag,
-//         {
-//           type: cellValue === 1 ? 'success' : cellValue === 2 ? 'warning' : 'danger'
-//         },
-//         () =>
-//           cellValue === 1
-//             ? t('tableDemo.important')
-//             : cellValue === 2
-//             ? t('tableDemo.good')
-//             : t('tableDemo.commonly')
-//       )
-//     },
-//     search: {
-//       show: true,
-//       component: 'Select',
-//       componentProps: {
-//         options: dictStore.getDictObj.importance
-//       }
-//     },
-//     form: {
-//       component: 'Select',
-//       componentProps: {
-//         options: [
-//           {
-//             label: '重要',
-//             value: 3
-//           },
-//           {
-//             label: '良好',
-//             value: 2
-//           },
-//           {
-//             label: '一般',
-//             value: 1
-//           }
-//         ]
-//       }
-//     }
-//   },
-//   {
-//     field: 'importance2',
-//     label: `${t('tableDemo.importance')}2`,
-//     search: {
-//       show: true,
-//       component: 'Select',
-//       dictName: 'importance'
-//     }
-//   },
-//   {
-//     field: 'importance3',
-//     label: `${t('tableDemo.importance')}3`,
-//     search: {
-//       show: true,
-//       component: 'Select',
-//       api: async () => {
-//         const res = await getDictOneApi()
-//         return res.data
-//       }
-//     }
-//   },
-//   {
-//     field: 'pageviews',
-//     label: t('tableDemo.pageviews'),
-//     form: {
-//       component: 'InputNumber',
-//       value: 0
-//     }
-//   },
-//   {
-//     field: 'content',
-//     label: t('exampleDemo.content'),
-//     table: {
-//       show: false
-//     },
-//     form: {
-//       component: 'Editor',
-//       colProps: {
-//         span: 24
-//       }
-//     },
-//     detail: {
-//       span: 24
-//     }
-//   },
-//   {
-//     field: 'action',
-//     width: '260px',
-//     label: t('tableDemo.action'),
-//     form: {
-//       show: false
-//     },
-//     detail: {
-//       show: false
-//     }
-//   }
-// ])
-
-// const { allSchemas } = useCrudSchemas(crudSchemas)
-
-// const delLoading = ref(false)
-
-// const delData = async (row: TableData | null, multiple: boolean) => {
-//   tableObject.currentRow = row
-//   const { delList, getSelections } = methods
-//   const selections = await getSelections()
-//   delLoading.value = true
-//   await delList(
-//     multiple ? selections.map((v) => v.id) : [tableObject.currentRow?.id as string],
-//     multiple
-//   ).finally(() => {
-//     delLoading.value = false
-//   })
-// }
-</script>
-
-<template>
-  <ContentWrap>
-    <!-- <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
-
-    <div class="mb-10px">
-      <ElButton :loading="delLoading" type="danger" @click="delData(null, true)">
-        {{ t('exampleDemo.del') }}
-      </ElButton>
-    </div>
-
-    <Table
-      v-model:pageSize="tableObject.pageSize"
-      v-model:currentPage="tableObject.currentPage"
-      :columns="allSchemas.tableColumns"
-      :data="tableObject.tableList"
-      :loading="tableObject.loading"
-      :pagination="{
-        total: tableObject.total
-      }"
-      @register="register"
-    >
-      <template #action="{ row }">
-        <ElButton type="danger" @click="delData(row, false)">
-          {{ t('exampleDemo.del') }}
-        </ElButton>
-      </template>
-    </Table> -->
-  </ContentWrap>
-</template>

+ 0 - 32
src/views/hooks/useWatermark.vue

@@ -1,32 +0,0 @@
-<script setup lang="ts">
-import { ContentWrap } from '@/components/ContentWrap'
-import { useI18n } from '@/hooks/web/useI18n'
-import { ElButton } from 'element-plus'
-import { useWatermark } from '@/hooks/web/useWatermark'
-import { computed, onBeforeUnmount } from 'vue'
-import { useAppStore } from '@/store/modules/app'
-
-const appStore = useAppStore()
-
-const title = computed(() => appStore.getTitle)
-
-const { setWatermark, clear } = useWatermark()
-
-const { t } = useI18n()
-
-onBeforeUnmount(() => {
-  clear()
-})
-</script>
-
-<template>
-  <ContentWrap title="useWatermark">
-    <ElButton type="primary" @click="setWatermark(title)">
-      {{ t('watermarkDemo.createdWatermark') }}
-    </ElButton>
-    <ElButton type="danger" @click="clear">{{ t('watermarkDemo.clearWatermark') }}</ElButton>
-    <ElButton type="warning" @click="setWatermark(`New${title}`)">
-      {{ t('watermarkDemo.resetWatermark') }}
-    </ElButton>
-  </ContentWrap>
-</template>