96 UI optimization (#122)
* fix(home): 🐛 解决多次切换路由后页面卡顿的问题 #96 卸载路由时清除requestAnimationFrame * feat: ✨ 文件存储使用Blob格式 * style: 💄 修改部分类型any为具体类型 * feat: ✨ 界面设置中模块使用瀑布流布局 #96 * fix: 🐛 md文档更换文件夹解决控制台警告 * style: 💄 switch按钮改回使用daisyui组件 * refactor: ♻️ 所有人员列表提取tableColumn * style: 💄 奖项列表中的图片类型修复
This commit is contained in:
@@ -42,7 +42,7 @@ async function uploadFile(fileData: IFileData | null) {
|
||||
function submitUpload() {
|
||||
if (jsonFileData.value) {
|
||||
// 把文件转化为json数据
|
||||
const jsonData = jsonFileData.value.dataUrl
|
||||
const jsonData = jsonFileData.value.data
|
||||
console.log('jsonData', jsonData)
|
||||
props.importAllConfigData(jsonData)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
<script setup lang='ts'>
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import GridWaterfall from '@/components/Waterfall/index.vue'
|
||||
import { DataSetting, LayoutSetting, PatternSetting, TextSetting, ThemeSetting } from './parts'
|
||||
|
||||
import { useViewModel } from './useViewModel'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { resetData, topTitleValue, languageValue, textSizeValue, currentFontValue, currentTitleFontValue, titleFontSyncGlobalValue, languageList, formErr, formData, cardSizeValue, isShowPrizeListValue, isShowAvatarValue, resetPersonLayout, isRowCountChange, themeValue, backgroundImageValue, cardColorValue, luckyCardColorValue, textColorValue, patternColorValue, imageList, rowCount, cardColor, patternColor, patternList, clearPattern, resetPattern, exportAllConfigData, importAllConfigData } = useViewModel()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="w-4/5 flex flex-col gap-4">
|
||||
<h2>{{ t('viewTitle.globalSetting') }}</h2>
|
||||
|
||||
<div class="flex flex-wrap h-auto w-full gap-6">
|
||||
<!-- <div class="flex flex-wrap h-auto w-full gap-6"> -->
|
||||
<GridWaterfall>
|
||||
<!-- 数据操作 -->
|
||||
<DataSetting :reset-data="resetData" :export-all-config-data="exportAllConfigData" :import-all-config-data="importAllConfigData" />
|
||||
<!-- 文本设置(主标题、语言、文字大小) -->
|
||||
@@ -55,7 +54,8 @@ const { resetData, topTitleValue, languageValue, textSizeValue, currentFontValue
|
||||
:clear-pattern="clearPattern"
|
||||
:reset-pattern="resetPattern"
|
||||
/>
|
||||
</div>
|
||||
</GridWaterfall>
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -17,32 +17,32 @@ const uploadVisible = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">
|
||||
{{ t('dialog.titleTip') }}
|
||||
</h3>
|
||||
<p class="py-4">
|
||||
{{ t('dialog.dialogResetAllData') }}
|
||||
</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="resetDataDialogRef.close()">
|
||||
{{ t(`button.cancel`) }}
|
||||
</button>
|
||||
<button class="btn" @click="resetData">
|
||||
{{ t('button.confirm') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
<UploadJsonModal v-model:visible="uploadVisible" :import-all-config-data="importAllConfigData" />
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
数据操作
|
||||
</legend>
|
||||
<dialog id="my_modal_1" ref="resetDataDialogRef" class="border-none modal">
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">
|
||||
{{ t('dialog.titleTip') }}
|
||||
</h3>
|
||||
<p class="py-4">
|
||||
{{ t('dialog.dialogResetAllData') }}
|
||||
</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex gap-3">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn" @click="resetDataDialogRef.close()">
|
||||
{{ t(`button.cancel`) }}
|
||||
</button>
|
||||
<button class="btn" @click="resetData">
|
||||
{{ t('button.confirm') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
<UploadJsonModal v-model:visible="uploadVisible" :import-all-config-data="importAllConfigData" />
|
||||
<label class="flex flex-row items-center form-control">
|
||||
<div class="">
|
||||
<div class="label flex flex-col justify-start items-start">
|
||||
|
||||
@@ -16,7 +16,7 @@ const isShowAvatarValue = defineModel<boolean>('isShowAvatarValue', { required:
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
布局设置
|
||||
</legend>
|
||||
|
||||
@@ -15,7 +15,7 @@ const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
图案设置
|
||||
</legend>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang='ts'>
|
||||
import type { IImage } from '@/types/storeType'
|
||||
import { reactive } from 'vue'
|
||||
import { ColorPicker } from 'vue3-colorpicker'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -7,7 +8,7 @@ import { daisyuiThemes } from '@/constant/theme'
|
||||
import 'vue3-colorpicker/style.css'
|
||||
|
||||
interface Props {
|
||||
imageList: Array<{ name: string, url: string, id: string }>
|
||||
imageList: Array<IImage>
|
||||
}
|
||||
defineProps<Props>()
|
||||
const themeList = reactive(daisyuiThemes)
|
||||
@@ -23,7 +24,7 @@ const patternColorValue = defineModel<string>('patternColorValue')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<fieldset class="p-4 border text-setting fieldset bg-base-200 border-base-300 rounded-box w-xs pb-10">
|
||||
<legend class="fieldset-legend">
|
||||
主题设置
|
||||
</legend>
|
||||
|
||||
@@ -48,7 +48,7 @@ async function uploadFile(fileData: IFileData | null) {
|
||||
async function getImageDbStore() {
|
||||
const keys = await imageDbStore.keys()
|
||||
if (keys.length > 0) {
|
||||
imageDbStore.iterate((value: { fileName: string, dataUrl: string }, key: string) => {
|
||||
imageDbStore.iterate((value: { fileName: string, data: Blob }, key: string) => {
|
||||
globalConfig.addImage({
|
||||
id: key,
|
||||
name: value.fileName,
|
||||
@@ -59,10 +59,10 @@ async function getImageDbStore() {
|
||||
}
|
||||
function submitUpload() {
|
||||
if (imageData.value) {
|
||||
const { dataUrl, fileName } = imageData.value
|
||||
const { data, fileName } = imageData.value
|
||||
const uniqueId = uuidv4()
|
||||
imageDbStore.setItem(uniqueId, {
|
||||
dataUrl,
|
||||
data,
|
||||
fileName,
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
@@ -52,7 +52,7 @@ async function uploadFile(fileData: IFileData | null) {
|
||||
async function getAudioDbStore() {
|
||||
const keys = await audioDbStore.keys()
|
||||
if (keys.length > 0) {
|
||||
audioDbStore.iterate((value: { fileName: string, dataUrl: string }, key: string) => {
|
||||
audioDbStore.iterate((value: { fileName: string, data: Blob }, key: string) => {
|
||||
globalConfig.addMusic({
|
||||
id: key,
|
||||
name: value.fileName,
|
||||
@@ -63,10 +63,10 @@ async function getAudioDbStore() {
|
||||
}
|
||||
function submitUpload() {
|
||||
if (audioData.value) {
|
||||
const { dataUrl, fileName } = audioData.value
|
||||
const { data, fileName } = audioData.value
|
||||
const uniqueId = uuidv4()
|
||||
audioDbStore.setItem(uniqueId, {
|
||||
dataUrl,
|
||||
data,
|
||||
fileName,
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
53
src/views/Config/Person/PersonAll/columns.ts
Normal file
53
src/views/Config/Person/PersonAll/columns.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { IPersonConfig } from '@/types/storeType'
|
||||
import i18n from '@/locales/i18n'
|
||||
|
||||
interface IColumnsProps {
|
||||
handleDeletePerson: (row: IPersonConfig) => void
|
||||
}
|
||||
export function tableColumns(props: IColumnsProps) {
|
||||
return [
|
||||
{
|
||||
label: i18n.global.t('data.number'),
|
||||
props: 'uid',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.name'),
|
||||
props: 'name',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.department'),
|
||||
props: 'department',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.avatar'),
|
||||
props: 'avatar',
|
||||
formatValue(row: any) {
|
||||
return row.avatar ? `<img src="${row.avatar}" alt="avatar" style="width: 50px; height: 50px;"/>` : '-'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.identity'),
|
||||
props: 'identity',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.isWin'),
|
||||
props: 'isWin',
|
||||
formatValue(row: IPersonConfig) {
|
||||
return row.isWin ? i18n.global.t('data.yes') : i18n.global.t('data.no')
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.operation'),
|
||||
actions: [
|
||||
{
|
||||
label: i18n.global.t('data.delete'),
|
||||
type: 'btn-error',
|
||||
onClick: (row: IPersonConfig) => {
|
||||
props.handleDeletePerson(row)
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import { useViewModel } from './useViewModel'
|
||||
const resetDataDialogRef = ref()
|
||||
const delAllDataDialogRef = ref()
|
||||
const exportInputFileRef = ref()
|
||||
const { resetData, deleteAll, handleFileChange, exportData, alreadyPersonList, allPersonList, tableColumns } = useViewModel({ exportInputFileRef })
|
||||
const { resetData, deleteAll, handleFileChange, exportData, alreadyPersonList, allPersonList, tableColumnList } = useViewModel({ exportInputFileRef })
|
||||
const { t } = useI18n()
|
||||
const limitType = '.xlsx,.xls'
|
||||
</script>
|
||||
@@ -70,7 +70,7 @@ const limitType = '.xlsx,.xls'
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<DaiysuiTable :table-columns="tableColumns" :data="allPersonList" />
|
||||
<DaiysuiTable :table-columns="tableColumnList" :data="allPersonList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { loadingKey } from '@/components/Loading'
|
||||
import i18n from '@/locales/i18n'
|
||||
import useStore from '@/store'
|
||||
import { readFileBinary, readLocalFileAsArraybuffer } from '@/utils/file'
|
||||
import { tableColumns } from './columns'
|
||||
import ImportExcelWorker from './importExcel.worker?worker'
|
||||
|
||||
export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<HTMLInputElement> }) {
|
||||
@@ -15,52 +16,7 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<H
|
||||
const loading = inject(loadingKey)
|
||||
const personConfig = useStore().personConfig
|
||||
const { getAllPersonList: allPersonList, getAlreadyPersonList: alreadyPersonList } = storeToRefs(personConfig)
|
||||
const tableColumns = [
|
||||
{
|
||||
label: i18n.global.t('data.number'),
|
||||
props: 'uid',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.name'),
|
||||
props: 'name',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.department'),
|
||||
props: 'department',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.avatar'),
|
||||
props: 'avatar',
|
||||
formatValue(row: any) {
|
||||
return row.avatar ? `<img src="${row.avatar}" alt="avatar" style="width: 50px; height: 50px;"/>` : '-'
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.identity'),
|
||||
props: 'identity',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.isWin'),
|
||||
props: 'isWin',
|
||||
formatValue(row: IPersonConfig) {
|
||||
return row.isWin ? i18n.global.t('data.yes') : i18n.global.t('data.no')
|
||||
},
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('data.operation'),
|
||||
actions: [
|
||||
{
|
||||
label: i18n.global.t('data.delete'),
|
||||
type: 'btn-error',
|
||||
onClick: (row: IPersonConfig) => {
|
||||
delPersonItem(row)
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const tableColumnList = tableColumns({ handleDeletePerson: delPersonItem })
|
||||
async function getExcelTemplateContent() {
|
||||
const locale = i18n.global.locale.value
|
||||
if (locale === 'zhCn') {
|
||||
@@ -171,6 +127,6 @@ export function useViewModel({ exportInputFileRef }: { exportInputFileRef: Ref<H
|
||||
exportData,
|
||||
alreadyPersonList,
|
||||
allPersonList,
|
||||
tableColumns,
|
||||
tableColumnList,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ const { alreadyPersonList, alreadyPersonDetail, isDetail, tableColumnsList, tabl
|
||||
<label class="label flex items-center gap-2">
|
||||
<p class="label-text">{{ t('table.detail') }}:</p>
|
||||
<div class="flex items-center">
|
||||
<Switch v-model="isDetail" class="cursor-pointer" />
|
||||
<!-- <Switch v-model="isDetail" class="cursor-pointer" /> -->
|
||||
<input v-model="isDetail" type="checkbox" :checked="isDetail" class="toggle toggle-primary">
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script setup lang='ts'>
|
||||
import markdownit from 'markdown-it'
|
||||
import { onMounted, ref, watch } from 'vue'
|
||||
import readmeEn from '@/../public/readme-en.md?raw'
|
||||
import readmeZh from '@/../public/readme-zhCn.md?raw'
|
||||
import readmeEn from '@/assets/md/readme-en.md?raw'
|
||||
import readmeZh from '@/assets/md/readme-zhCn.md?raw'
|
||||
import i18n from '@/locales/i18n'
|
||||
|
||||
const md = markdownit()
|
||||
|
||||
Reference in New Issue
Block a user