Browse Source

文档逻辑

master
wangqi 6 months ago
parent
commit
57a3c229a2
  1. 1
      auto-imports.d.ts
  2. 3
      src/api/module/eam/device/document.ts
  3. 2
      src/assets/image/dashboard/file/document.svg
  4. 84
      src/assets/image/dashboard/file/document2.svg
  5. 38
      src/pages/fileDoc/components/markdownDrawer.vue
  6. 110
      src/pages/fileDoc/index.vue
  7. 31
      src/pages/fileDoc/utils.ts
  8. 34
      src/pages/layout.vue
  9. 6
      src/styles/var.css

1
auto-imports.d.ts vendored

@ -6,6 +6,7 @@
export {} export {}
declare global { declare global {
const EffectScope: typeof import('vue')['EffectScope'] const EffectScope: typeof import('vue')['EffectScope']
const ElLoading: typeof import('element-plus/es')['ElLoading']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp'] const createApp: typeof import('vue')['createApp']

3
src/api/module/eam/device/document.ts

@ -12,6 +12,8 @@ interface DocFileVO {
id: number id: number
name: string name: string
parentId: number parentId: number
isDraft?: 0 | 1
path: string
} }
export function createFolder(data: Omit<DocFileVO, 'id'>) { export function createFolder(data: Omit<DocFileVO, 'id'>) {
@ -64,7 +66,6 @@ export function deleteFile(params: { id: number }) {
interface MarkdownVO { interface MarkdownVO {
folderId: number folderId: number
content: string content: string
id: number
isDraft: 0 | 1 // 0: 文章 1: 草稿 isDraft: 0 | 1 // 0: 文章 1: 草稿
} }
export interface ContentType { export interface ContentType {

2
src/assets/image/dashboard/file/document.svg

@ -5,7 +5,7 @@
<style type="text/css"> <style type="text/css">
.st0{clip-path:url(#SVGID_1_);} .st0{clip-path:url(#SVGID_1_);}
.st1{clip-path:url(#SVGID_2_);} .st1{clip-path:url(#SVGID_2_);}
.st2{fill:#3A6ACC;} .st2{fill:#619925;}
.st3{opacity:0.4;} .st3{opacity:0.4;}
.st4{clip-path:url(#SVGID_3_);} .st4{clip-path:url(#SVGID_3_);}
.st5{fill:#FFFFFF;} .st5{fill:#FFFFFF;}

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

84
src/assets/image/dashboard/file/document2.svg

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_1_);}
.st1{clip-path:url(#SVGID_2_);}
.st2{fill:#909399;}
.st3{opacity:0.4;}
.st4{clip-path:url(#SVGID_3_);}
.st5{fill:#FFFFFF;}
</style>
<g>
<g>
<g>
<defs>
<rect id="SVGID_7_" x="96" y="96" width="832" height="832"/>
</defs>
<clipPath id="SVGID_1_">
<use xlink:href="#SVGID_7_" style="overflow:visible;"/>
</clipPath>
<g id="组_244" class="st0">
<g id="组_243" transform="translate(8 2)">
<g>
<g>
<g>
<defs>
<rect id="SVGID_9_" x="192" y="120" width="624" height="780"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_9_" style="overflow:visible;"/>
</clipPath>
<g id="组_242" class="st1">
<g id="路径_134">
<path class="st2" d="M270,120c-43,0.1-77.9,35-78,78v624c0.1,43,35,77.9,78,78h468c43-0.1,77.9-35,78-78V352.1L584,120
H270z"/>
</g>
<g id="组_241" transform="translate(30.15)" class="st3">
<g id="组_240">
<g>
<g>
<g>
<defs>
<rect id="SVGID_11_" x="553.8" y="120" width="232.1" height="232.1"/>
</defs>
<clipPath id="SVGID_3_">
<use xlink:href="#SVGID_11_" style="overflow:visible;"/>
</clipPath>
<g id="组_239" class="st4">
<g id="路径_135">
<path class="st5" d="M631.8,352.1h154L553.8,120v154.1C553.9,317.1,588.8,351.9,631.8,352.1"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="直线_87">
<path class="st5" d="M480.3,754.9h-156c-4.5,0-8.1-3.6-8.1-8.1s3.6-8.1,8.1-8.1h156c4.5,0,8.1,3.6,8.1,8.1
S484.8,754.9,480.3,754.9z"/>
</g>
<g id="直线_88">
<path class="st5" d="M558.3,676.5h-234c-4.5,0-8.1-3.6-8.1-8.1s3.6-8.1,8.1-8.1h234c4.5,0,8.1,3.6,8.1,8.1
S562.8,676.5,558.3,676.5z"/>
</g>
<g id="直线_89">
<path class="st5" d="M558.3,598.5h-234c-4.5,0-8.1-3.6-8.1-8.1s3.6-8.1,8.1-8.1h234c4.5,0,8.1,3.6,8.1,8.1
S562.8,598.5,558.3,598.5z"/>
</g>
<g id="直线_90">
<path class="st5" d="M558.3,520.5h-234c-4.5,0-8.1-3.6-8.1-8.1s3.6-8.1,8.1-8.1h234c4.5,0,8.1,3.6,8.1,8.1
C566.4,516.9,562.8,520.5,558.3,520.5z"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

38
src/pages/fileDoc/components/markdownDrawer.vue

@ -9,7 +9,7 @@
> >
<template #header> <template #header>
<div class="header"> <div class="header">
<span>{{ data.title }}</span> <span>{{ data.fileName }}</span>
<div> <div>
<EDFSButton innerText="保存为草稿" type="info" @click="onSave(1)" /> <EDFSButton innerText="保存为草稿" type="info" @click="onSave(1)" />
<EDFSButton innerText="发布文章" type="primary" @click="onSave(0)" /> <EDFSButton innerText="发布文章" type="primary" @click="onSave(0)" />
@ -29,8 +29,9 @@ import EDFSButton from '@/components/dashboard/Edfs-button/index.vue'
import Vditor from 'vditor' import Vditor from 'vditor'
import { type ContentType } from '@/api/module/eam/device/document' import { type ContentType } from '@/api/module/eam/device/document'
import 'vditor/dist/index.css' import 'vditor/dist/index.css'
import { vditorToolbar } from '../utils'
interface Props { interface Props {
data: ContentType data: ContentType & { fileName: string }
} }
const emits = defineEmits(['on-save']) const emits = defineEmits(['on-save'])
const props = withDefaults(defineProps<Props>(), {}) const props = withDefaults(defineProps<Props>(), {})
@ -65,34 +66,7 @@ function initEditor() {
pin: true, pin: true,
}, },
mode: 'wysiwyg', // "wysiwyg" | "sv" | "ir" // wysiwyg: sv: ir: mode: 'wysiwyg', // "wysiwyg" | "sv" | "ir" // wysiwyg: sv: ir:
toolbar: [ toolbar: vditorToolbar,
'edit-mode',
'headings',
'bold',
'italic',
'strike',
'emoji',
'line',
'quote',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'table',
'code',
'inline-code',
'insert-after',
'insert-before',
'link',
'both',
'outline',
'code-theme',
'export',
'undo',
'redo',
'fullscreen',
],
counter: { counter: {
enable: true, enable: true,
}, },
@ -105,10 +79,6 @@ function initEditor() {
}, },
after: () => { after: () => {
contentEditor.value?.setValue(props?.data?.content ?? '') contentEditor.value?.setValue(props?.data?.content ?? '')
console.log(contentEditor.value?.getValue()) //
setTimeout(() => {
console.log(contentEditor.value?.getValue()) //
}, 10000) //
}, },
}) })
} }

110
src/pages/fileDoc/index.vue

@ -18,7 +18,7 @@
@visibleChange="onVisibleChange" @visibleChange="onVisibleChange"
ref="contextMenuRef" ref="contextMenuRef"
> >
<div class="file-list" v-if="loading"> <div class="file-list">
<div v-for="item in dataList" :key="item.id" @click="onFileOpen(item)"> <div v-for="item in dataList" :key="item.id" @click="onFileOpen(item)">
<div class="item SourceClass" v-setItem="item"> <div class="item SourceClass" v-setItem="item">
<div class="file-header"> <div class="file-header">
@ -30,9 +30,15 @@
></Icon> ></Icon>
</div> </div>
<div class="file-icon"> <div class="file-icon">
<!-- {{ !!item.isEdit }} --> <img
:src="
<img :src="item.type === floeType.folder ? Folder : Document" /> item.type === floeType.folder
? Folder
: item.isDraft === 0
? Document
: Document2
"
/>
</div> </div>
<div class="file-name"> <div class="file-name">
<el-input <el-input
@ -103,20 +109,29 @@ import { ArrowRight } from '@element-plus/icons-vue'
import Folder from '@/assets/image/dashboard/file/folder.svg' import Folder from '@/assets/image/dashboard/file/folder.svg'
import Upload from '@/assets/image/dashboard/file/upload.svg' import Upload from '@/assets/image/dashboard/file/upload.svg'
import Document from '@/assets/image/dashboard/file/document.svg' import Document from '@/assets/image/dashboard/file/document.svg'
import Document2 from '@/assets/image/dashboard/file/document2.svg'
import { Icon } from '@/components/dashboard/Icon' import { Icon } from '@/components/dashboard/Icon'
import EdfsContextMenu from '@/components/dashboard/Edfs-context-menu/index.vue' import EdfsContextMenu from '@/components/dashboard/Edfs-context-menu/index.vue'
import markdownDrawer from './components/markdownDrawer.vue' import markdownDrawer from './components/markdownDrawer.vue'
const dropdownMenu = computed(() => { const dropdownMenu = computed(() => {
return menuTarget.value ? fileDropdownMenu : operationDropdownMenu return menuTarget.value
? fileDropdownMenu
: currentFolderId.value === 0
? operationDropdownMenu.filter(v => v.command === 'newFolder')
: operationDropdownMenu.filter(v => v.command === 'newMarkdown')
}) })
const message = useMessage() const message = useMessage()
const currentId = ref(0) const currentFolderId = ref(0)
watch(breadcrumbList.value, () => { watch(
currentId.value = breadcrumbList.value[breadcrumbList.value.length - 1].id () => breadcrumbList.value.length,
}) () => {
currentFolderId.value = breadcrumbList.value[breadcrumbList.value.length - 1].id
}
)
const dataList = ref<any>([]) const dataList = ref<any>([])
const loading = ref(false) const loading = ref(false)
@ -125,17 +140,14 @@ async function loadData(id: number = 0) {
const res = await getFileList({ const res = await getFileList({
parentId: id, parentId: id,
}) })
loading.value = false
if (isResError(res)) return if (isResError(res)) return
dataList.value = res.data.map((item: any) => ({ dataList.value = res.data
...item,
isEdit: false,
}))
loading.value = true
} }
async function onDelete(item: any) { async function onDelete(item: any) {
try { try {
let res let res: any
await message.delConfirm() await message.delConfirm()
switch (item.type) { switch (item.type) {
case floeType.folder: case floeType.folder:
@ -147,7 +159,7 @@ async function onDelete(item: any) {
} }
if (isResError(res)) return if (isResError(res)) return
message.success('删除成功') message.success('删除成功')
loadData(currentId.value) loadData(currentFolderId.value)
} catch (error) {} } catch (error) {}
} }
@ -158,7 +170,7 @@ function onFile(e: any) {
function onNewFolder() { function onNewFolder() {
const folder = { const folder = {
name: '新建文件夹', name: '未命名文件夹',
type: floeType.folder, type: floeType.folder,
isEdit: true, isEdit: true,
} }
@ -168,7 +180,7 @@ function onNewFolder() {
function onNewMarkdown() { function onNewMarkdown() {
const markdown = { const markdown = {
name: '新建文档', name: '未命名文档',
type: floeType.file, type: floeType.file,
isEdit: true, isEdit: true,
} }
@ -234,23 +246,26 @@ async function onSaveRename(item: any) {
if (!item.isEdit) return if (!item.isEdit) return
item.name = editFileName.value item.name = editFileName.value
await nextTick() await nextTick()
item.isEdit = false const find = findItem(item.id)
await nextTick() find.isEdit = false
await onSaveFile(item) await onSaveFile(item)
editFileName.value = '' editFileName.value = ''
} }
async function onRename(item: any) { async function onRename(item: any) {
if (!item) return if (!item) return
item.isEdit = true const find = findItem(item.id)
await nextTick() find.isEdit = true
editFileName.value = item.name editFileName.value = item.name
await nextTick() await nextTick()
editInputRefs.value[`editInputRef_${item.id}`].focus() editInputRefs.value[`editInputRef_${item.id}`].focus()
editInputRefs.value[`editInputRef_${item.id}`].select() editInputRefs.value[`editInputRef_${item.id}`].select()
} }
const findItem = (id: number) => dataList.value.find((v: any) => v.id === id)
async function onSaveFile(item: any) { async function onSaveFile(item: any) {
const isAdd = !item.id const isAdd = !item.id
loading.value = true
switch (item.type) { switch (item.type) {
case floeType.folder: case floeType.folder:
await saveFolder(isAdd, item) await saveFolder(isAdd, item)
@ -260,21 +275,30 @@ async function onSaveFile(item: any) {
break break
} }
loadData(currentId.value) loadData(currentFolderId.value)
}
function getPath() {
return currentFolderId.value === 0
? ''
: breadcrumbList.value[breadcrumbList.value.length - 1].path
} }
async function saveFolder(isAdd: boolean, item: any) { async function saveFolder(isAdd: boolean, item: any) {
getPath()
let res let res
if (isAdd) { if (isAdd) {
res = await createFolder({ res = await createFolder({
name: item.name, name: item.name,
parentId: currentId.value, parentId: currentFolderId.value,
path: getPath(),
}) })
} else { } else {
res = await updateFolder({ res = await updateFolder({
id: item.id, id: item.id,
name: item.name, name: item.name,
parentId: currentId.value, parentId: currentFolderId.value,
path: getPath(),
}) })
} }
if (isResError(res)) return if (isResError(res)) return
@ -284,34 +308,56 @@ async function saveFile(isAdd: boolean, item: any) {
if (isAdd) { if (isAdd) {
res = await createdFile({ res = await createdFile({
name: item.name + '.md', name: item.name + '.md',
parentId: currentId.value, parentId: currentFolderId.value,
isDraft: 1,
path: getPath(),
}) })
} else { } else {
res = await updateFile({ res = await updateFile({
id: item.id, id: item.id,
name: item.name, name: item.name,
parentId: currentId.value, parentId: currentFolderId.value,
path: getPath(),
}) })
} }
if (isResError(res)) return if (isResError(res)) return
} }
const fullscreenLoading = ref()
function openFullScreen() {
fullscreenLoading.value = ElLoading.service({
lock: true,
text: '数据加载中请稍等...',
target: document.querySelector('.firmware-management-wrap') as HTMLElement,
})
}
watch(loading, val => {
if (val) {
openFullScreen()
} else {
fullscreenLoading.value?.close()
}
})
// markdown // markdown
const curMarkdown = ref() as Ref<ContentType> const curMarkdown = ref() as Ref<ContentType & { fileName: string }>
const curMdId = ref()
const isShowMdDrawer = ref(false) const isShowMdDrawer = ref(false)
async function onOpenMarkdownDrawer(id: number) { async function onOpenMarkdownDrawer(id: number) {
curMdId.value = id
const res = await getMarkdown({ folderId: id }) const res = await getMarkdown({ folderId: id })
if (isResError(res)) return if (isResError(res)) return
curMarkdown.value = res?.data curMarkdown.value = Object.assign({}, res.data, { fileName: findItem(id).name })
isShowMdDrawer.value = true isShowMdDrawer.value = true
} }
async function onSaveMd(isDraft: 0 | 1, data: string) { async function onSaveMd(isDraft: 0 | 1, data: string) {
const res = await updateMarkdown({ const res = await updateMarkdown({
content: data, content: data,
folderId: currentId.value, folderId: curMdId.value,
id: curMarkdown.value?.id,
isDraft, isDraft,
}) })
@ -319,7 +365,7 @@ async function onSaveMd(isDraft: 0 | 1, data: string) {
message.success(isDraft === 1 ? '保存成功' : '发布成功') message.success(isDraft === 1 ? '保存成功' : '发布成功')
isShowMdDrawer.value = false isShowMdDrawer.value = false
curMarkdown.value = null as any curMarkdown.value = null as any
loadData(currentId.value) loadData(currentFolderId.value)
} }
onMounted(() => { onMounted(() => {
loadData() loadData()

31
src/pages/fileDoc/utils.ts

@ -10,10 +10,39 @@ export const breadcrumbList = ref([{ name: '全部文件', id: 0 }])
export const fileDropdownMenu = [ export const fileDropdownMenu = [
{ command: 'open', label: '打开', icon: '' }, { command: 'open', label: '打开', icon: '' },
{ command: 'rename', label: '重命名', icon: '' }, { command: 'rename', label: '重命名', icon: '' },
{ command: 'delete', label: '删除', icon: '' }, // { command: 'delete', label: '删除', icon: '' },
] ]
export const operationDropdownMenu = [ export const operationDropdownMenu = [
{ command: 'newFolder', label: '新建文件夹', icon: Folder }, { command: 'newFolder', label: '新建文件夹', icon: Folder },
// { command: 'upload', label: '上传', icon: Upload }, // { command: 'upload', label: '上传', icon: Upload },
{ command: 'newMarkdown', label: '新建文档', icon: Document }, { command: 'newMarkdown', label: '新建文档', icon: Document },
] ]
export const vditorToolbar = [
'edit-mode',
'headings',
'bold',
'italic',
'strike',
'emoji',
'line',
'quote',
'list',
'ordered-list',
'check',
'outdent',
'indent',
'table',
'code',
'inline-code',
'insert-after',
'insert-before',
'link',
'both',
'outline',
'code-theme',
'export',
'undo',
'redo',
'fullscreen',
]

34
src/pages/layout.vue

@ -69,7 +69,14 @@
{{ currentTime }} {{ currentTime }}
</div> </div>
<div class="right"> <div class="right">
<el-dropdown <el-switch
v-model="themeSwitch"
:active-action-icon="Moon"
:inactive-action-icon="Sunny"
style="--el-switch-on-color: #2C2C2C; --el-switch-off-color: #F2F2F2 "
@change="toggle"
/>
<!-- <el-dropdown
style="width: 100%; height: 100%" style="width: 100%; height: 100%"
@command="command => handleCommand(command)" @command="command => handleCommand(command)"
> >
@ -84,14 +91,13 @@
<el-dropdown-item command="logout">退出登录</el-dropdown-item> <el-dropdown-item command="logout">退出登录</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown> -->
</div> </div>
</el-header> </el-header>
<main class="layout-main"> <main class="layout-main">
<el-config-provider :locale="zhCn"> <el-config-provider :locale="zhCn">
<RouterView /> <RouterView />
</el-config-provider> </el-config-provider>
</main> </main>
</div> </div>
</div> </div>
@ -114,6 +120,7 @@ import { THEME_KEY, INIT_OPTIONS_KEY } from 'vue-echarts'
import { registerTheme } from 'echarts/core' import { registerTheme } from 'echarts/core'
const { theme, toggle } = useTheme() const { theme, toggle } = useTheme()
import { customDark, customLight } from '@/utils/dark' import { customDark, customLight } from '@/utils/dark'
import { useIcon } from '@/utils/useIcon'
registerTheme('dark', customDark) registerTheme('dark', customDark)
registerTheme('light', customLight) registerTheme('light', customLight)
provide(THEME_KEY, theme) provide(THEME_KEY, theme)
@ -121,6 +128,11 @@ provide(INIT_OPTIONS_KEY, {
devicePixelRatio: 2, devicePixelRatio: 2,
}) })
const Sunny = useIcon({icon: 'line-md:moon-filled-to-sunny-filled-loop-transition', color: '#2C2C2C'})
const Moon = useIcon({icon: 'line-md:sunny-filled-loop-to-moon-filled-transition', color: '#2C2C2C'})
const themeSwitch = ref(theme.value === 'dark')
const route = useRoute() const route = useRoute()
const breadcrumbItems = computed(() => { const breadcrumbItems = computed(() => {
@ -235,8 +247,6 @@ async function loginOut() {
push('/file/document') push('/file/document')
} catch {} } catch {}
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -245,10 +255,11 @@ $header-height: 48px;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
background: var(--bg);
.menu-box { .menu-box {
max-width: 216px; max-width: 216px;
height: 100%; height: calc(100% - 16px);
position: relative; position: relative;
transition: width 0.3s ease; transition: width 0.3s ease;
overflow: hidden; overflow: hidden;
@ -267,7 +278,7 @@ $header-height: 48px;
padding-left: 20px; padding-left: 20px;
column-gap: 6px; column-gap: 6px;
font-size: 16px; font-size: 16px;
color: #fff; color: var(--text-color);
font-weight: 400; font-weight: 400;
.logo-icon { .logo-icon {
@ -278,7 +289,7 @@ $header-height: 48px;
.logo-label { .logo-label {
font-size: 16px; font-size: 16px;
line-height: 22px; line-height: 22px;
font-weight: 400; font-weight: 500;
} }
.icon { .icon {
@ -297,21 +308,22 @@ $header-height: 48px;
background-color: var(--layout-menu-bg); background-color: var(--layout-menu-bg);
:deep(.el-menu-item:hover), :deep(.el-menu-item:hover),
:deep(.el-sub-menu__title:hover) { :deep(.el-sub-menu__title:hover) {
background: #272b35; background: var(--menu-hover-bg);
} }
:deep(.el-menu-item), :deep(.el-menu-item),
:deep(.el-sub-menu__title) { :deep(.el-sub-menu__title) {
font-family: Alibaba-PuHuiTi-R; font-family: Alibaba-PuHuiTi-R;
font-size: 14px; font-size: 14px;
color: #fff; color: var(--text-color);
line-height: 22px; line-height: 22px;
font-weight: 400; font-weight: 400;
height: 40px; height: 40px;
border-left: 3px solid transparent; border-left: 3px solid transparent;
} }
:deep(.el-menu-item.is-active) { :deep(.el-menu-item.is-active) {
background-color: #2c342c; background-color: var(--menu-active-bg);
color: #619925;
border-left: 3px solid #619925; border-left: 3px solid #619925;
} }
.mr-5px { .mr-5px {

6
src/styles/var.css

@ -3,6 +3,8 @@ html[data-theme='dark'] {
--text-color: #ffffff; --text-color: #ffffff;
--layout-header-bg: #1b1d23; --layout-header-bg: #1b1d23;
--layout-menu-bg: #1b1d23; --layout-menu-bg: #1b1d23;
--menu-active-bg: #2c342c;
--menu-hover-bg: #272b35;
--warp-bg: #212327; --warp-bg: #212327;
--table-header-bg: #3b3d40; --table-header-bg: #3b3d40;
--table-header-text-color: #cdcecf; --table-header-text-color: #cdcecf;
@ -25,7 +27,9 @@ html[data-theme='light'] {
--bg: #f1f2f6; --bg: #f1f2f6;
--text-color: #4d4d4d; --text-color: #4d4d4d;
--layout-header-bg: #ffffff; --layout-header-bg: #ffffff;
--layout-menu-bg: #1b1d23; --layout-menu-bg: #fff;
--menu-active-bg: #F5FCEE;
--menu-hover-bg: #f5f5f5;
--warp-bg: #ffffff; --warp-bg: #ffffff;
--table-header-bg: #e8e9ee; --table-header-bg: #e8e9ee;
--table-header-text-color: #030303; --table-header-text-color: #030303;

Loading…
Cancel
Save