日常 bugfix 更新

This commit is contained in:
Ah jung
2021-07-13 10:01:31 +08:00
parent b1c730dde8
commit 18597fabd3
10 changed files with 235 additions and 191 deletions

View File

@@ -2,77 +2,91 @@
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="renderer" content="webkit"/>
<meta
name="viewport"
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
/>
<link rel="icon" href="/favicon.ico"/>
<title><%= title %></title> <title><%= title %></title>
</head> </head>
<body> <body>
<div id="app"> <div id="app">
<style> <style>
.app-loading-main{ .app-loading-main {
display: flex; display: flex;
width: 100%; width: 100%;
height: 100%; height: 100%;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
flex-direction: column; flex-direction: column;
background-color: #f4f7f9; background-color: #f4f7f9;
position: relative; position: relative;
}
.app-loading {
position: relative;
-webkit-transform: translateY(-15px);
-ms-transform: translateY(-15px);
transform: translateY(-15px);
}
.app-loading > div {
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
position: absolute;
top: 0px;
left: 0px;
border-radius: 100%;
}
.app-loading > div:first-child {
background: #2d8cf0;
height: 16px;
width: 16px;
top: 9px;
left: 9px;
-webkit-animation: scale 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
animation: scale 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
}
.app-loading > div:last-child {
position: absolute;
border: 2px solid #2d8cf0;
width: 30px;
height: 30px;
background: transparent;
border: 2px solid;
border-color: #2d8cf0 transparent #2d8cf0 transparent;
-webkit-animation: rotate 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
animation: rotate 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
-webkit-animation-duration: 1s;
animation-duration: 1s;
}
@keyframes rotate {
0% {
-webkit-transform: rotate(0deg) scale(1);
transform: rotate(0deg) scale(1);
} }
.app-loading { 50% {
position: relative; -webkit-transform: rotate(180deg) scale(0.6);
-webkit-transform: translateY(-15px); transform: rotate(180deg) scale(0.6);
-ms-transform: translateY(-15px);
transform: translateY(-15px);
} }
.app-loading > div { 100% {
-webkit-animation-fill-mode: both; -webkit-transform: rotate(360deg) scale(1);
animation-fill-mode: both; transform: rotate(360deg) scale(1);
position: absolute;
top: 0px;
left: 0px;
border-radius: 100%; }
.app-loading > div:first-child {
background: #2d8cf0;
height: 16px;
width: 16px;
top: 9px;
left: 9px;
-webkit-animation: scale 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
animation: scale 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
} }
.app-loading > div:last-child { }
position: absolute; </style>
border: 2px solid #2d8cf0; <div class="app-loading-main">
width: 30px; <div class="app-loading">
height: 30px; <div></div>
background: transparent; <div></div>
border: 2px solid;
border-color: #2d8cf0 transparent #2d8cf0 transparent;
-webkit-animation: rotate 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
animation: rotate 1s 0s cubic-bezier(.09, .57, .49, .9) infinite;
-webkit-animation-duration: 1s;
animation-duration: 1s;
}
@keyframes rotate {
0% {
-webkit-transform: rotate(0deg) scale(1);
transform: rotate(0deg) scale(1); }
50% {
-webkit-transform: rotate(180deg) scale(0.6);
transform: rotate(180deg) scale(0.6); }
100% {
-webkit-transform: rotate(360deg) scale(1);
transform: rotate(360deg) scale(1); }
}
</style>
<div class="app-loading-main">
<div class="app-loading">
<div></div>
<div></div>
</div>
</div> </div>
</div> </div>
<script type="module" src="/src/main.ts"></script> </div>
<script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

View File

@@ -12,7 +12,7 @@
</NConfigProvider> </NConfigProvider>
<transition v-if="isLock && $route.name != 'login'" name="slide-up"> <transition v-if="isLock && $route.name != 'login'" name="slide-up">
<lockScreen/> <LockScreen/>
</transition> </transition>
</template> </template>

View File

@@ -267,7 +267,6 @@ export default defineComponent({
justify-content: flex-start; justify-content: flex-start;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
color: rgba(0, 0, 0, .85);
} }
} }
@@ -280,9 +279,8 @@ export default defineComponent({
height: 18px; height: 18px;
margin-left: 12px; margin-left: 12px;
font-size: 16px; font-size: 16px;
color: rgba(0, 0, 0, .75);
cursor: pointer; cursor: pointer;
color:var(--text-color);
:hover { :hover {
color: #1890ff; color: #1890ff;
} }

View File

@@ -18,42 +18,41 @@
</div> </div>
</template> </template>
<div class="table-toolbar-inner"> <div class="table-toolbar-inner">
<Draggable v-model="columnsList" animation="300" item-key="key" @end="draggableEnd"> <n-checkbox-group v-model:value="checkList" @update:value="onChange">
<template #item="{element, index}"> <Draggable v-model="columnsList" animation="300" item-key="key" @end="draggableEnd">
<div class="table-toolbar-inner-checkbox"> <template #item="{element, index}">
<span class="drag-icon"> <div class="table-toolbar-inner-checkbox" :class="{'table-toolbar-inner-checkbox-dark':getDarkTheme === true}">
<n-icon size="18"> <span class="drag-icon">
<DragOutlined/> <n-icon size="18">
</n-icon> <DragOutlined/>
</span> </n-icon>
<n-checkbox-group v-model:value="checkList" @update:value="onChange"> </span>
<n-checkbox :value="element.key" :label="element.title"/> <n-checkbox :value="element.key" :label="element.title"/>
</n-checkbox-group> <div class="fixed-item">
<div class="fixed-item"> <n-tooltip trigger="hover" placement="bottom">
<n-tooltip trigger="hover" placement="bottom"> <template #trigger>
<template #trigger> <n-icon size="18" :color="element.fixed === 'left' ? '#2080f0':undefined"
<n-icon size="18" :color="element.fixed === 'left' ? '#2080f0':undefined" class="transform -rotate-90 cursor-pointer" @click="fixedColumn(element,'left')">
class="transform -rotate-90 cursor-pointer" @click="fixedColumn(index,'left')"> <VerticalAlignTopOutlined/>
<VerticalAlignTopOutlined/> </n-icon>
</n-icon> </template>
</template> <span>固定到左侧</span>
<span>固定到左侧</span> </n-tooltip>
</n-tooltip> <n-divider vertical/>
<n-divider vertical/> <n-tooltip trigger="hover" placement="bottom">
<n-tooltip trigger="hover" placement="bottom"> <template #trigger>
<template #trigger> <n-icon size="18" :color="element.fixed === 'right' ? '#2080f0':undefined"
<n-icon size="18" :color="element.fixed === 'right' ? '#2080f0':undefined" class="transform rotate-90 cursor-pointer" @click="fixedColumn(element,'right')">
class="transform rotate-90 cursor-pointer" @click="fixedColumn(index,'right')"> <VerticalAlignTopOutlined/>
<VerticalAlignTopOutlined/> </n-icon>
</n-icon> </template>
</template> <span>固定到右侧</span>
<span>固定到右侧</span> </n-tooltip>
</n-tooltip> </div>
</div> </div>
</div> </template>
</template> </Draggable>
</Draggable> </n-checkbox-group>
</div> </div>
</n-popover> </n-popover>
</div> </div>
@@ -67,6 +66,7 @@ import { ref, defineComponent, reactive, unref, toRaw, computed, toRefs, watchEf
import { useTableContext } from '../../hooks/useTableContext'; import { useTableContext } from '../../hooks/useTableContext';
import { ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, VerticalAlignTopOutlined } from '@vicons/antd' import { ReloadOutlined, ColumnHeightOutlined, SettingOutlined, DragOutlined, VerticalAlignTopOutlined } from '@vicons/antd'
import Draggable from 'vuedraggable/src/vuedraggable' import Draggable from 'vuedraggable/src/vuedraggable'
import { useDesignSetting } from "@/hooks/setting/useDesignSetting";
interface Options { interface Options {
title: string; title: string;
@@ -81,8 +81,11 @@ export default defineComponent({
VerticalAlignTopOutlined VerticalAlignTopOutlined
}, },
setup(props, { emit }) { setup(props, { emit }) {
const { getDarkTheme } = useDesignSetting()
const table = useTableContext(); const table = useTableContext();
const columnsList = ref<Options[]>([]); const columnsList = ref<Options[]>([]);
const cacheColumnsList = ref<Options[]>([]);
const state = reactive({ const state = reactive({
selection: false, selection: false,
checkAll: true, checkAll: true,
@@ -108,6 +111,7 @@ export default defineComponent({
state.checkList = checkList state.checkList = checkList
state.defaultCheckList = checkList state.defaultCheckList = checkList
columnsList.value = columns columnsList.value = columns
cacheColumnsList.value = columns
} }
//切换 //切换
@@ -125,18 +129,26 @@ export default defineComponent({
//获取 //获取
function getColumns() { function getColumns() {
const newArr = [] let newRet = []
table.getColumns().forEach(item => { table.getColumns().forEach(item => {
newArr.push({ ...item }) newRet.push({...item })
}) })
return newArr return newRet
} }
//重置 //重置
function resetColumns() { function resetColumns() {
state.checkList = [...state.defaultCheckList] state.checkList = [...state.defaultCheckList]
state.checkAll = true; state.checkAll = true;
setColumns(table.getCacheColumns(true)); let cacheColumnsKeys:any[] = table.getCacheColumns()
let newColumns = cacheColumnsKeys.map(item => {
return {
...item,
fixed:undefined
}
})
setColumns(newColumns);
columnsList.value = newColumns
} }
//全选 //全选
@@ -154,6 +166,8 @@ export default defineComponent({
//拖拽排序 //拖拽排序
function draggableEnd(e) { function draggableEnd(e) {
const newColumns = toRaw(unref(columnsList)) const newColumns = toRaw(unref(columnsList))
console.log(newColumns);
columnsList.value = newColumns
setColumns(newColumns); setColumns(newColumns);
} }
@@ -170,19 +184,26 @@ export default defineComponent({
} }
//固定 //固定
function fixedColumn(index, fixed) { function fixedColumn(item, fixed) {
let columnList = getColumns(); console.log('item',item)
let columnInfo = columnList[index] if (!state.checkList.includes(item.key)) return;
const isFixed = columnInfo.fixed === fixed ? undefined : fixed let columns = getColumns();
columnInfo.fixed = isFixed const isFixed = item.fixed === fixed ? undefined : fixed
columnsList.value = columnList let index = columns.findIndex(res => res.key === item.key)
table.setCacheColumnsField(columnInfo.key, { fixed: isFixed }) console.log('index',index)
setColumns(columnList); if(index !== -1){
columns[index].fixed = isFixed;
}
table.setCacheColumnsField(item.key, { fixed: isFixed })
columnsList.value[index].fixed = isFixed
console.log('columnsList',columnsList.value)
setColumns(columns);
} }
return { return {
...toRefs(state), ...toRefs(state),
columnsList, columnsList,
getDarkTheme,
onChange, onChange,
onCheckAll, onCheckAll,
onSelection, onSelection,
@@ -197,12 +218,15 @@ export default defineComponent({
<style lang="less"> <style lang="less">
.table-toolbar { .table-toolbar {
&-inner-popover-title{
padding: 3px 0;
}
&-right { &-right {
&-icon { &-icon {
height: 18px; height: 18px;
margin-left: 12px; margin-left: 12px;
font-size: 16px; font-size: 16px;
color: rgba(0, 0, 0, .75); color:var(--text-color);
cursor: pointer; cursor: pointer;
:hover { :hover {
@@ -216,18 +240,15 @@ export default defineComponent({
&-checkbox { &-checkbox {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 8px 0; padding: 10px 14px;
&:hover { &:hover {
background: #e6f7ff; background: #e6f7ff;
} }
.drag-icon { .drag-icon {
display: inline-flex; display: inline-flex;
margin-right: 8px; margin-right: 8px;
cursor: move; cursor: move;
} }
.fixed-item { .fixed-item {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -243,5 +264,15 @@ export default defineComponent({
} }
} }
} }
&-checkbox-dark{
&:hover {
background: hsla(0, 0%, 100%, .08);
}
}
}
.toolbar-popover{
.n-popover__content{
padding: 0;
}
} }
</style> </style>

View File

@@ -22,10 +22,11 @@ export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
() => unref(propsRef).columns, () => unref(propsRef).columns,
(columns) => { (columns) => {
columnsRef.value = columns; columnsRef.value = columns;
cacheColumns = columns?.filter((item) => !item.flag) ?? []; cacheColumns = columns;
} }
); );
//设置 //设置
function setColumns(columnList: string[]) { function setColumns(columnList: string[]) {
const columns: any[] = cloneDeep(columnList); const columns: any[] = cloneDeep(columnList);
@@ -36,7 +37,6 @@ export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
return; return;
} }
const cacheKeys = cacheColumns.map((item) => item.key); const cacheKeys = cacheColumns.map((item) => item.key);
//针对拖拽排序 //针对拖拽排序
if (!isString(columns[0])) { if (!isString(columns[0])) {
columnsRef.value = columns; columnsRef.value = columns;
@@ -60,9 +60,9 @@ export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
//获取 //获取
function getColumns() { function getColumns() {
const columns = toRaw(unref(propsRef).columns); let columns = toRaw(unref(getColumnsRef));
return columns.map(item => { return columns.map(item => {
return { title: item.title, key: item.key, fixed: item.fixed || undefined } return { ...item, title: item.title, key: item.key, fixed: item.fixed || undefined }
}) })
} }

View File

@@ -1,8 +1,8 @@
import { ref, ComputedRef, unref, computed, onMounted, onBeforeMount, watchEffect, watch } from 'vue'; import { ref, ComputedRef, unref, computed, onMounted, watchEffect, watch } from 'vue';
import type { BasicTableProps } from '../types/table'; import type { BasicTableProps } from '../types/table';
import type { PaginationProps } from '../types/pagination'; import type { PaginationProps } from '../types/pagination';
import { isFunction, isBoolean } from '@/utils/is'; import { isBoolean } from '@/utils/is';
import { DEFAULTPAGESIZE, APISETTING, PAGESIZES } from '../const'; import { APISETTING } from '../const';
export function useDataSource( export function useDataSource(
propsRef: ComputedRef<BasicTableProps>, propsRef: ComputedRef<BasicTableProps>,
@@ -10,12 +10,11 @@ export function useDataSource(
getPaginationInfo, getPaginationInfo,
setPagination, setPagination,
setLoading, setLoading,
tableData, tableData
getSelection
}, },
emit: EmitType emit
) { ) {
const dataSourceRef = ref<Recordable[]>([]); const dataSourceRef = ref([]);
watchEffect(() => { watchEffect(() => {
tableData.value = unref(dataSourceRef); tableData.value = unref(dataSourceRef);
@@ -33,7 +32,7 @@ export function useDataSource(
); );
const getRowKey = computed(() => { const getRowKey = computed(() => {
const { rowKey } = unref(propsRef); const { rowKey }:any = unref(propsRef);
return rowKey ? rowKey : () => { return rowKey ? rowKey : () => {
return 'key' return 'key'
}; };
@@ -44,25 +43,6 @@ export function useDataSource(
if (!dataSource || dataSource.length === 0) { if (!dataSource || dataSource.length === 0) {
return unref(dataSourceRef); return unref(dataSourceRef);
} }
// if (unref(getAutoCreateKey)) {
// const firstItem = dataSource[0];
// const lastItem = dataSource[dataSource.length - 1];
//
// if (firstItem && lastItem) {
// if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
// const data = cloneDeep(unref(dataSourceRef));
// data.forEach((item) => {
// if (!item[ROW_KEY]) {
// item[ROW_KEY] = buildUUID();
// }
// if (item.children && item.children.length) {
// setTableKey(item.children);
// }
// });
// dataSourceRef.value = data;
// }
// }
// }
return unref(dataSourceRef); return unref(dataSourceRef);
}); });
@@ -77,7 +57,7 @@ export function useDataSource(
const totalField = APISETTING.totalField const totalField = APISETTING.totalField
const listField = APISETTING.listField const listField = APISETTING.listField
let pageParams: Recordable = {}; let pageParams = {};
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps; const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) { if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
@@ -95,7 +75,7 @@ export function useDataSource(
const resultTotal = res[totalField] || 0 const resultTotal = res[totalField] || 0
const currentPage = res[pageField] const currentPage = res[pageField]
// 假如数据变少导致总页数变少并小于当前选中页码通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行 // 如果数据异常,需获取正确的页码再次执行
if (resultTotal) { if (resultTotal) {
const currentTotalPage = Math.ceil(resultTotal / pageSize); const currentTotalPage = Math.ceil(resultTotal / pageSize);
if (page > currentTotalPage) { if (page > currentTotalPage) {
@@ -138,19 +118,15 @@ export function useDataSource(
}, 16) }, 16)
}); });
// onBeforeMount(()=> { function setTableData(values) {
// fetch()
// })
function setTableData<T = Recordable>(values: T[]) {
dataSourceRef.value = values; dataSourceRef.value = values;
} }
function getDataSource<T = Recordable>() { function getDataSource() :any[] {
return getDataSourceRef.value as T[]; return getDataSourceRef.value;
} }
async function reload(opt?: FetchParams) { async function reload(opt?) {
await fetch(opt); await fetch(opt);
} }

View File

@@ -23,7 +23,6 @@ export const basicProps = {
type: [Array] as PropType<BasicColumn[]>, type: [Array] as PropType<BasicColumn[]>,
default: () => [], default: () => [],
required: true, required: true,
}, },
request: { request: {
type: Function as PropType<(...arg: any[]) => Promise<any>>, type: Function as PropType<(...arg: any[]) => Promise<any>>,

View File

@@ -0,0 +1,22 @@
import type {
TableBaseColumn,
} from 'naive-ui/lib/data-table/src/interface';
export interface BasicColumn extends TableBaseColumn {
}
export interface TableActionType {
reload: (opt) => Promise<void>;
emit?: any;
getColumns: (opt) => BasicColumn[];
setColumns: (columns: BasicColumn[] | string[]) => void;
}
export interface BasicTableProps<T = any> {
title?: string,
dataSource: Function,
columns: any[],
pagination: object,
showPagination: boolean
}

View File

@@ -1,5 +1,5 @@
<template> <template>
<n-drawer v-model:show="isDrawer" :width="width" :placement="placement"> <n-drawer v-model:show="isDrawer" :width="width" :placement="placement" :native-scrollbar="false">
<n-drawer-content :title="title"> <n-drawer-content :title="title">
<div class="drawer"> <div class="drawer">
<n-divider title-placement="center">主题</n-divider> <n-divider title-placement="center">主题</n-divider>

View File

@@ -2,41 +2,39 @@
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"module": "esnext", "module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node", "moduleResolution": "node",
"skipLibCheck": true, "strict": true,
"esModuleInterop": true, "forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"sourceMap": true,
"pretty": true,
"resolveJsonModule": true,
"allowJs": true,
"checkJs": true,
"suppressImplicitAnyIndexErrors": true,
"strictPropertyInitialization": false,
"downlevelIteration": true,
"noUnusedLocals": false,
"noImplicitAny": false,
"noImplicitThis": true,
"removeComments": false,
"strictFunctionTypes": false, "strictFunctionTypes": false,
"jsx": "preserve",
"baseUrl": ".", "baseUrl": ".",
"types": ["vite/client", "node"], "allowJs": true,
"typeRoots": ["./node_modules/@types/", "./types"], "sourceMap": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"experimentalDecorators": true,
"lib": [
"dom",
"esnext"
],
"types": [
"vite/client",
"jest"
],
"typeRoots": [
"./node_modules/@types/",
"./types"
],
"noImplicitAny": false,
"skipLibCheck": true,
"paths": { "paths": {
"@/*": [ "@/*": [
"src/*" "src/*"
] ]
}, }
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}, },
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
@@ -44,9 +42,15 @@
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue", "src/**/*.vue",
"types/**/*.d.ts", "types/**/*.d.ts",
"types/**/*.ts" "types/**/*.ts",
"build/**/*.ts",
"build/**/*.d.ts",
"mock/**/*.ts",
"vite.config.ts"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules",
"dist",
"**/*.js"
] ]
} }