mirror of
https://github.com/jekip/naive-ui-admin.git
synced 2026-02-13 17:52:28 +08:00
fix Bug Features CHANGELOG.ms
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div
|
||||
:class="{ onLockLogin: showLogin }"
|
||||
class="lockscreen"
|
||||
@keyup="onLockLogin(true)"
|
||||
@mousedown.stop
|
||||
@contextmenu.prevent
|
||||
:class="{ onLockLogin: showLogin }"
|
||||
class="lockscreen"
|
||||
@keyup="onLockLogin(true)"
|
||||
@mousedown.stop
|
||||
@contextmenu.prevent
|
||||
>
|
||||
<template v-if="!showLogin">
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
</div>
|
||||
<!--充电-->
|
||||
<recharge
|
||||
:battery="battery"
|
||||
:battery-status="batteryStatus"
|
||||
:calc-discharging-time="calcDischargingTime"
|
||||
:battery="battery"
|
||||
:battery-status="batteryStatus"
|
||||
:calc-discharging-time="calcDischargingTime"
|
||||
></recharge>
|
||||
|
||||
<div class="local-time">
|
||||
@@ -47,10 +47,10 @@
|
||||
</n-avatar>
|
||||
<div class="username">{{ loginParams.username }}</div>
|
||||
<n-input
|
||||
type="password"
|
||||
autofocus
|
||||
v-model:value="loginParams.password"
|
||||
placeholder="请输入登录密码">
|
||||
type="password"
|
||||
autofocus
|
||||
v-model:value="loginParams.password"
|
||||
placeholder="请输入登录密码">
|
||||
<template #suffix>
|
||||
<n-icon @click="onLogin" style="cursor: pointer;">
|
||||
<LoadingOutlined v-if="loginLoading"/>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default as ProTable } from './src/ProTable.vue';
|
||||
@@ -1,95 +0,0 @@
|
||||
import { ref, Ref, ComputedRef, unref, computed, watch, toRaw } from 'vue';
|
||||
import type { BasicColumn, BasicTableProps } from '../types/table';
|
||||
import { isEqual, cloneDeep } from 'lodash-es';
|
||||
import { isArray, isString } from '@/utils/is';
|
||||
|
||||
export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
|
||||
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
|
||||
let cacheColumns = unref(propsRef).columns;
|
||||
|
||||
const getColumnsRef = computed(() => {
|
||||
const columns = cloneDeep(unref(columnsRef));
|
||||
return columns;
|
||||
})
|
||||
|
||||
const getPageColumns = computed(() => {
|
||||
const pageColumns = unref(getColumnsRef);
|
||||
const columns = cloneDeep(pageColumns);
|
||||
return columns
|
||||
})
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).columns,
|
||||
(columns) => {
|
||||
columnsRef.value = columns;
|
||||
cacheColumns = columns;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
//设置
|
||||
function setColumns(columnList: string[]) {
|
||||
const columns: any[] = cloneDeep(columnList);
|
||||
if (!isArray(columns)) return;
|
||||
|
||||
if (!columns.length) {
|
||||
columnsRef.value = [];
|
||||
return;
|
||||
}
|
||||
const cacheKeys = cacheColumns.map((item) => item.key);
|
||||
//针对拖拽排序
|
||||
if (!isString(columns[0])) {
|
||||
columnsRef.value = columns;
|
||||
} else {
|
||||
const newColumns: any[] = []
|
||||
cacheColumns.forEach(item => {
|
||||
if (columnList.includes(item.key)) {
|
||||
newColumns.push({ ...item })
|
||||
}
|
||||
})
|
||||
if (!isEqual(cacheKeys, columns)) {
|
||||
newColumns.sort((prev, next) => {
|
||||
return (
|
||||
cacheKeys.indexOf(prev.key) - cacheKeys.indexOf(next.key)
|
||||
);
|
||||
});
|
||||
}
|
||||
columnsRef.value = newColumns
|
||||
}
|
||||
}
|
||||
|
||||
//获取
|
||||
function getColumns() {
|
||||
let columns = toRaw(unref(getColumnsRef));
|
||||
return columns.map(item => {
|
||||
return { ...item, title: item.title, key: item.key, fixed: item.fixed || undefined }
|
||||
})
|
||||
}
|
||||
|
||||
//获取原始
|
||||
function getCacheColumns(isKey?: boolean): any[] {
|
||||
return isKey ? cacheColumns.map(item => item.key) : cacheColumns;
|
||||
}
|
||||
|
||||
//更新原始数据单个字段
|
||||
function setCacheColumnsField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
||||
if (!dataIndex || !value) {
|
||||
return;
|
||||
}
|
||||
cacheColumns.forEach((item) => {
|
||||
if (item.key === dataIndex) {
|
||||
Object.assign(item, value);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getColumnsRef,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getPageColumns
|
||||
};
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
import { ref, ComputedRef, unref, computed, onMounted, watchEffect, watch } from 'vue';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
import type { PaginationProps } from '../types/pagination';
|
||||
import { isBoolean } from '@/utils/is';
|
||||
import { APISETTING } from '../const';
|
||||
|
||||
export function useDataSource(
|
||||
propsRef: ComputedRef<BasicTableProps>,
|
||||
{
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
setLoading,
|
||||
tableData
|
||||
},
|
||||
emit
|
||||
) {
|
||||
const dataSourceRef = ref([]);
|
||||
|
||||
watchEffect(() => {
|
||||
tableData.value = unref(dataSourceRef);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).dataSource,
|
||||
() => {
|
||||
const { dataSource }: any = unref(propsRef);
|
||||
dataSource && (dataSourceRef.value = dataSource);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const getRowKey = computed(() => {
|
||||
const { rowKey }:any = unref(propsRef);
|
||||
return rowKey ? rowKey : () => {
|
||||
return 'key'
|
||||
};
|
||||
});
|
||||
|
||||
const getDataSourceRef = computed(() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
return unref(dataSourceRef);
|
||||
}
|
||||
return unref(dataSourceRef);
|
||||
});
|
||||
|
||||
async function fetch(opt?) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { request, pagination }: any = unref(propsRef);
|
||||
|
||||
//组装分页信息
|
||||
const pageField = APISETTING.pageField
|
||||
const sizeField = APISETTING.sizeField
|
||||
const totalField = APISETTING.totalField
|
||||
const listField = APISETTING.listField
|
||||
|
||||
let pageParams = {};
|
||||
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
|
||||
|
||||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
||||
pageParams = {};
|
||||
} else {
|
||||
pageParams[pageField] = (opt && opt[pageField]) || page;
|
||||
pageParams[sizeField] = pageSize;
|
||||
}
|
||||
|
||||
let params = {
|
||||
...pageParams,
|
||||
}
|
||||
const res = await request(params);
|
||||
|
||||
const resultTotal = res[totalField] || 0
|
||||
const currentPage = res[pageField]
|
||||
|
||||
// 如果数据异常,需获取正确的页码再次执行
|
||||
if (resultTotal) {
|
||||
const currentTotalPage = Math.ceil(resultTotal / pageSize);
|
||||
if (page > currentTotalPage) {
|
||||
setPagination({
|
||||
[pageField]: currentTotalPage,
|
||||
});
|
||||
fetch(opt);
|
||||
}
|
||||
}
|
||||
let resultInfo = res[listField] ? res[listField] : []
|
||||
dataSourceRef.value = resultInfo;
|
||||
setPagination({
|
||||
[pageField]: currentPage,
|
||||
[totalField]: resultTotal,
|
||||
});
|
||||
if (opt && opt[pageField]) {
|
||||
setPagination({
|
||||
[pageField]: opt[pageField] || 1,
|
||||
});
|
||||
}
|
||||
emit('fetch-success', {
|
||||
items: unref(resultInfo),
|
||||
resultTotal
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
emit('fetch-error', error);
|
||||
dataSourceRef.value = [];
|
||||
// setPagination({
|
||||
// pageCount: 0,
|
||||
// });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
fetch();
|
||||
}, 16)
|
||||
});
|
||||
|
||||
function setTableData(values) {
|
||||
dataSourceRef.value = values;
|
||||
}
|
||||
|
||||
function getDataSource() :any[] {
|
||||
return getDataSourceRef.value;
|
||||
}
|
||||
|
||||
async function reload(opt?) {
|
||||
await fetch(opt);
|
||||
}
|
||||
|
||||
return {
|
||||
fetch,
|
||||
getRowKey,
|
||||
getDataSourceRef,
|
||||
getDataSource,
|
||||
setTableData,
|
||||
reload
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { ref, ComputedRef, unref, computed, watch } from 'vue';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
|
||||
export function useLoading(props: ComputedRef<BasicTableProps>) {
|
||||
const loadingRef = ref(unref(props).loading);
|
||||
|
||||
watch(
|
||||
() => unref(props).loading,
|
||||
(loading) => {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
);
|
||||
|
||||
const getLoading = computed(() => unref(loadingRef));
|
||||
|
||||
function setLoading(loading: boolean) {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
|
||||
return { getLoading, setLoading };
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import type { PaginationProps } from '../types/pagination';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
import { computed, unref, ref, ComputedRef } from 'vue';
|
||||
|
||||
import { isBoolean } from '@/utils/is';
|
||||
import { DEFAULTPAGESIZE, PAGESIZES } from '../const';
|
||||
|
||||
export function usePagination(refProps: ComputedRef<BasicTableProps>) {
|
||||
const configRef = ref<PaginationProps>({});
|
||||
const show = ref(true);
|
||||
|
||||
const getPaginationInfo = computed((): PaginationProps | boolean => {
|
||||
const { pagination } = unref(refProps);
|
||||
if (!unref(show) || (isBoolean(pagination) && !pagination)) {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
pageSize: DEFAULTPAGESIZE,
|
||||
pageSizes: PAGESIZES,
|
||||
showSizePicker: true,
|
||||
showQuickJumper: true,
|
||||
...(isBoolean(pagination) ? {} : pagination),
|
||||
...unref(configRef),
|
||||
};
|
||||
});
|
||||
|
||||
function setPagination(info: Partial<PaginationProps>) {
|
||||
const paginationInfo = unref(getPaginationInfo);
|
||||
configRef.value = {
|
||||
...(!isBoolean(paginationInfo) ? paginationInfo : {}),
|
||||
...info,
|
||||
};
|
||||
}
|
||||
|
||||
function getPagination() {
|
||||
return unref(getPaginationInfo);
|
||||
}
|
||||
|
||||
function getShowPagination() {
|
||||
return unref(show);
|
||||
}
|
||||
|
||||
async function setShowPagination(flag: boolean) {
|
||||
show.value = flag;
|
||||
}
|
||||
|
||||
return { getPagination, getPaginationInfo, setShowPagination, getShowPagination, setPagination };
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import type { PropType } from 'vue'
|
||||
import { BasicColumn } from './types/table'
|
||||
|
||||
export const basicProps = {
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
titleTooltip: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
},
|
||||
tableData: {
|
||||
type: [Object],
|
||||
default: () => {
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
type: [Array] as PropType<BasicColumn[]>,
|
||||
default: () => [],
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
rowKey: {
|
||||
type: [String, Function] as PropType<string | ((record) => string)>,
|
||||
default: undefined,
|
||||
},
|
||||
pagination: {
|
||||
type: [Object, Boolean],
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
showPagination: {
|
||||
type: [String, Boolean],
|
||||
default: 'auto'
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import Pagination from 'naive-ui/lib/pagination';
|
||||
import { VNodeChild } from 'vue';
|
||||
|
||||
export interface PaginationProps {
|
||||
page?: number;
|
||||
pageCount?: number,
|
||||
pageSize?: number,
|
||||
pageSizes?: number[],
|
||||
showSizePicker?: boolean,
|
||||
showQuickJumper?: boolean,
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
ProTable 重封装组件说明
|
||||
BasicTable 重封装组件说明
|
||||
====
|
||||
|
||||
封装说明
|
||||
@@ -6,7 +6,7 @@ ProTable 重封装组件说明
|
||||
|
||||
> 基础的使用方式与 API 与 [官方版(data-table)](https://www.naiveui.com/zh-CN/os-theme/components/data-table#tree) 本一致,在其基础上,封装了加载数据的方法。
|
||||
>
|
||||
> 你无需在你是用表格的页面进行分页逻辑处理,仅需向 ProTable 组件传递绑定 `:api="Promise"` 对象即可
|
||||
> 你无需在你是用表格的页面进行分页逻辑处理,仅需向 BasicTable 组件传递绑定 `:api="Promise"` 对象即可
|
||||
>
|
||||
> 例子1
|
||||
----
|
||||
@@ -15,7 +15,7 @@ ProTable 重封装组件说明
|
||||
```vue
|
||||
|
||||
<template>
|
||||
<ProTable
|
||||
<BasicTable
|
||||
title="表格列表"
|
||||
:columns="columns"
|
||||
:api="loadDataTable"
|
||||
@@ -25,12 +25,12 @@ ProTable 重封装组件说明
|
||||
<template #toolbar>
|
||||
<n-button type="primary">添加会员</n-button>
|
||||
</template>
|
||||
</ProTable>
|
||||
</BasicTable>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
import { ProTable } from '@/components/ProTable'
|
||||
import { BasicTable } from '@/components/Table'
|
||||
import { getTableList } from '@/api/table/list'
|
||||
const columns = [
|
||||
{
|
||||
@@ -51,7 +51,7 @@ const columns = [
|
||||
},
|
||||
]
|
||||
export default defineComponent({
|
||||
components: { ProTable },
|
||||
components: { BasicTable },
|
||||
setup() {
|
||||
const loadDataTable = async (params) => {
|
||||
const data = await getTableList(params);
|
||||
@@ -68,7 +68,7 @@ export default defineComponent({
|
||||
|
||||
API
|
||||
----
|
||||
ProTable 在 NaiveUi 的 data-table 上进行了一层封装,支持了一些预设,并且封装了一些行为。这里只列出与 data-table 不同的 api。
|
||||
BasicTable 在 NaiveUi 的 data-table 上进行了一层封装,支持了一些预设,并且封装了一些行为。这里只列出与 data-table 不同的 api。
|
||||
|
||||
> request:Promise 参考上面例子写法
|
||||
> ref:可绑定ref 调用组件内部方法(data-table本身的方法和参数)
|
||||
1
src/components/Table/index.ts
Normal file
1
src/components/Table/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as BasicTable } from './src/Table.vue';
|
||||
@@ -58,10 +58,10 @@
|
||||
</div>
|
||||
<div class="s-table">
|
||||
<n-data-table
|
||||
v-bind="getBindValues"
|
||||
:pagination="pagination"
|
||||
@update:page="updatePage"
|
||||
@update:page-size="updatePageSize"
|
||||
v-bind="getBindValues"
|
||||
:pagination="pagination"
|
||||
@update:page="updatePage"
|
||||
@update:page-size="updatePageSize"
|
||||
>
|
||||
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
|
||||
<slot :name="item" v-bind="data"></slot>
|
||||
@@ -141,12 +141,12 @@ export default defineComponent({
|
||||
} = usePagination(getProps)
|
||||
|
||||
const { getDataSourceRef, getRowKey, getDataSource, setDataSource, reload } = useDataSource(
|
||||
getProps, {
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
tableData,
|
||||
setLoading
|
||||
}, emit
|
||||
getProps, {
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
tableData,
|
||||
setLoading
|
||||
}, emit
|
||||
)
|
||||
|
||||
const {
|
||||
@@ -281,7 +281,8 @@ export default defineComponent({
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
color:var(--text-color);
|
||||
color: var(--text-color);
|
||||
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
@@ -21,7 +21,8 @@
|
||||
<n-checkbox-group v-model:value="checkList" @update:value="onChange">
|
||||
<Draggable v-model="columnsList" animation="300" item-key="key" @end="draggableEnd">
|
||||
<template #item="{element, index}">
|
||||
<div class="table-toolbar-inner-checkbox" :class="{'table-toolbar-inner-checkbox-dark':getDarkTheme === true}">
|
||||
<div class="table-toolbar-inner-checkbox"
|
||||
:class="{'table-toolbar-inner-checkbox-dark':getDarkTheme === true}">
|
||||
<span class="drag-icon">
|
||||
<n-icon size="18">
|
||||
<DragOutlined/>
|
||||
@@ -33,7 +34,7 @@
|
||||
<template #trigger>
|
||||
<n-icon size="18" :color="element.fixed === 'left' ? '#2080f0':undefined"
|
||||
class="cursor-pointer" @click="fixedColumn(element,'left')">
|
||||
<VerticalRightOutlined />
|
||||
<VerticalRightOutlined/>
|
||||
</n-icon>
|
||||
</template>
|
||||
<span>固定到左侧</span>
|
||||
@@ -43,7 +44,7 @@
|
||||
<template #trigger>
|
||||
<n-icon size="18" :color="element.fixed === 'right' ? '#2080f0':undefined"
|
||||
class="cursor-pointer" @click="fixedColumn(element,'right')">
|
||||
<VerticalLeftOutlined />
|
||||
<VerticalLeftOutlined/>
|
||||
</n-icon>
|
||||
</template>
|
||||
<span>固定到右侧</span>
|
||||
@@ -131,7 +132,7 @@ export default defineComponent({
|
||||
function getColumns() {
|
||||
let newRet = []
|
||||
table.getColumns().forEach(item => {
|
||||
newRet.push({...item })
|
||||
newRet.push({ ...item })
|
||||
})
|
||||
return newRet
|
||||
}
|
||||
@@ -140,11 +141,11 @@ export default defineComponent({
|
||||
function resetColumns() {
|
||||
state.checkList = [...state.defaultCheckList]
|
||||
state.checkAll = true;
|
||||
let cacheColumnsKeys:any[] = table.getCacheColumns()
|
||||
let cacheColumnsKeys: any[] = table.getCacheColumns()
|
||||
let newColumns = cacheColumnsKeys.map(item => {
|
||||
return {
|
||||
...item,
|
||||
fixed:undefined
|
||||
fixed: undefined
|
||||
}
|
||||
})
|
||||
setColumns(newColumns);
|
||||
@@ -184,18 +185,18 @@ export default defineComponent({
|
||||
|
||||
//固定
|
||||
function fixedColumn(item, fixed) {
|
||||
console.log('item:',item)
|
||||
console.log('item:', item)
|
||||
if (!state.checkList.includes(item.key)) return;
|
||||
let columns = getColumns();
|
||||
const isFixed = item.fixed === fixed ? undefined : fixed
|
||||
let index = columns.findIndex(res => res.key === item.key)
|
||||
console.log('index:',index)
|
||||
if(index !== -1){
|
||||
console.log('index:', index)
|
||||
if (index !== -1) {
|
||||
columns[index].fixed = isFixed;
|
||||
}
|
||||
table.setCacheColumnsField(item.key, { fixed: isFixed })
|
||||
columnsList.value[index].fixed = isFixed
|
||||
console.log('columnsList:',columnsList.value)
|
||||
console.log('columnsList:', columnsList.value)
|
||||
setColumns(columns);
|
||||
}
|
||||
|
||||
@@ -217,15 +218,17 @@ export default defineComponent({
|
||||
|
||||
<style lang="less">
|
||||
.table-toolbar {
|
||||
&-inner-popover-title{
|
||||
&-inner-popover-title {
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
&-right {
|
||||
&-icon {
|
||||
margin-left: 12px;
|
||||
font-size: 16px;
|
||||
color:var(--text-color);
|
||||
color: var(--text-color);
|
||||
cursor: pointer;
|
||||
|
||||
:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
@@ -238,14 +241,17 @@ export default defineComponent({
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 14px;
|
||||
|
||||
&:hover {
|
||||
background: #e6f7ff;
|
||||
}
|
||||
|
||||
.drag-icon {
|
||||
display: inline-flex;
|
||||
margin-right: 8px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.fixed-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -261,14 +267,16 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
&-checkbox-dark{
|
||||
|
||||
&-checkbox-dark {
|
||||
&:hover {
|
||||
background: hsla(0, 0%, 100%, .08);
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar-popover{
|
||||
.n-popover__content{
|
||||
|
||||
.toolbar-popover {
|
||||
.n-popover__content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
95
src/components/Table/src/hooks/useColumns.ts
Normal file
95
src/components/Table/src/hooks/useColumns.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { ref, Ref, ComputedRef, unref, computed, watch, toRaw } from 'vue';
|
||||
import type { BasicColumn, BasicTableProps } from '../types/table';
|
||||
import { isEqual, cloneDeep } from 'lodash-es';
|
||||
import { isArray, isString } from '@/utils/is';
|
||||
|
||||
export function useColumns(propsRef: ComputedRef<BasicTableProps>) {
|
||||
const columnsRef = ref(unref(propsRef).columns) as unknown as Ref<BasicColumn[]>;
|
||||
let cacheColumns = unref(propsRef).columns;
|
||||
|
||||
const getColumnsRef = computed(() => {
|
||||
const columns = cloneDeep(unref(columnsRef));
|
||||
return columns;
|
||||
})
|
||||
|
||||
const getPageColumns = computed(() => {
|
||||
const pageColumns = unref(getColumnsRef);
|
||||
const columns = cloneDeep(pageColumns);
|
||||
return columns
|
||||
})
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).columns,
|
||||
(columns) => {
|
||||
columnsRef.value = columns;
|
||||
cacheColumns = columns;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
//设置
|
||||
function setColumns(columnList: string[]) {
|
||||
const columns: any[] = cloneDeep(columnList);
|
||||
if (!isArray(columns)) return;
|
||||
|
||||
if (!columns.length) {
|
||||
columnsRef.value = [];
|
||||
return;
|
||||
}
|
||||
const cacheKeys = cacheColumns.map((item) => item.key);
|
||||
//针对拖拽排序
|
||||
if (!isString(columns[0])) {
|
||||
columnsRef.value = columns;
|
||||
} else {
|
||||
const newColumns: any[] = []
|
||||
cacheColumns.forEach(item => {
|
||||
if (columnList.includes(item.key)) {
|
||||
newColumns.push({ ...item })
|
||||
}
|
||||
})
|
||||
if (!isEqual(cacheKeys, columns)) {
|
||||
newColumns.sort((prev, next) => {
|
||||
return (
|
||||
cacheKeys.indexOf(prev.key) - cacheKeys.indexOf(next.key)
|
||||
);
|
||||
});
|
||||
}
|
||||
columnsRef.value = newColumns
|
||||
}
|
||||
}
|
||||
|
||||
//获取
|
||||
function getColumns() {
|
||||
let columns = toRaw(unref(getColumnsRef));
|
||||
return columns.map(item => {
|
||||
return { ...item, title: item.title, key: item.key, fixed: item.fixed || undefined }
|
||||
})
|
||||
}
|
||||
|
||||
//获取原始
|
||||
function getCacheColumns(isKey?: boolean): any[] {
|
||||
return isKey ? cacheColumns.map(item => item.key) : cacheColumns;
|
||||
}
|
||||
|
||||
//更新原始数据单个字段
|
||||
function setCacheColumnsField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
|
||||
if (!dataIndex || !value) {
|
||||
return;
|
||||
}
|
||||
cacheColumns.forEach((item) => {
|
||||
if (item.key === dataIndex) {
|
||||
Object.assign(item, value);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getColumnsRef,
|
||||
getCacheColumns,
|
||||
setCacheColumnsField,
|
||||
setColumns,
|
||||
getColumns,
|
||||
getPageColumns
|
||||
};
|
||||
}
|
||||
141
src/components/Table/src/hooks/useDataSource.ts
Normal file
141
src/components/Table/src/hooks/useDataSource.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { ref, ComputedRef, unref, computed, onMounted, watchEffect, watch } from 'vue';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
import type { PaginationProps } from '../types/pagination';
|
||||
import { isBoolean } from '@/utils/is';
|
||||
import { APISETTING } from '../const';
|
||||
|
||||
export function useDataSource(
|
||||
propsRef: ComputedRef<BasicTableProps>,
|
||||
{
|
||||
getPaginationInfo,
|
||||
setPagination,
|
||||
setLoading,
|
||||
tableData
|
||||
},
|
||||
emit
|
||||
) {
|
||||
const dataSourceRef = ref([]);
|
||||
|
||||
watchEffect(() => {
|
||||
tableData.value = unref(dataSourceRef);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => unref(propsRef).dataSource,
|
||||
() => {
|
||||
const { dataSource }: any = unref(propsRef);
|
||||
dataSource && (dataSourceRef.value = dataSource);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const getRowKey = computed(() => {
|
||||
const { rowKey }: any = unref(propsRef);
|
||||
return rowKey ? rowKey : () => {
|
||||
return 'key'
|
||||
};
|
||||
});
|
||||
|
||||
const getDataSourceRef = computed(() => {
|
||||
const dataSource = unref(dataSourceRef);
|
||||
if (!dataSource || dataSource.length === 0) {
|
||||
return unref(dataSourceRef);
|
||||
}
|
||||
return unref(dataSourceRef);
|
||||
});
|
||||
|
||||
async function fetch(opt?) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { request, pagination }: any = unref(propsRef);
|
||||
|
||||
//组装分页信息
|
||||
const pageField = APISETTING.pageField
|
||||
const sizeField = APISETTING.sizeField
|
||||
const totalField = APISETTING.totalField
|
||||
const listField = APISETTING.listField
|
||||
|
||||
let pageParams = {};
|
||||
const { page = 1, pageSize = 10 } = unref(getPaginationInfo) as PaginationProps;
|
||||
|
||||
if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
|
||||
pageParams = {};
|
||||
} else {
|
||||
pageParams[pageField] = (opt && opt[pageField]) || page;
|
||||
pageParams[sizeField] = pageSize;
|
||||
}
|
||||
|
||||
let params = {
|
||||
...pageParams,
|
||||
}
|
||||
const res = await request(params);
|
||||
|
||||
const resultTotal = res[totalField] || 0
|
||||
const currentPage = res[pageField]
|
||||
|
||||
// 如果数据异常,需获取正确的页码再次执行
|
||||
if (resultTotal) {
|
||||
const currentTotalPage = Math.ceil(resultTotal / pageSize);
|
||||
if (page > currentTotalPage) {
|
||||
setPagination({
|
||||
[pageField]: currentTotalPage,
|
||||
});
|
||||
fetch(opt);
|
||||
}
|
||||
}
|
||||
let resultInfo = res[listField] ? res[listField] : []
|
||||
dataSourceRef.value = resultInfo;
|
||||
setPagination({
|
||||
[pageField]: currentPage,
|
||||
[totalField]: resultTotal,
|
||||
});
|
||||
if (opt && opt[pageField]) {
|
||||
setPagination({
|
||||
[pageField]: opt[pageField] || 1,
|
||||
});
|
||||
}
|
||||
emit('fetch-success', {
|
||||
items: unref(resultInfo),
|
||||
resultTotal
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
emit('fetch-error', error);
|
||||
dataSourceRef.value = [];
|
||||
// setPagination({
|
||||
// pageCount: 0,
|
||||
// });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
fetch();
|
||||
}, 16)
|
||||
});
|
||||
|
||||
function setTableData(values) {
|
||||
dataSourceRef.value = values;
|
||||
}
|
||||
|
||||
function getDataSource(): any[] {
|
||||
return getDataSourceRef.value;
|
||||
}
|
||||
|
||||
async function reload(opt?) {
|
||||
await fetch(opt);
|
||||
}
|
||||
|
||||
return {
|
||||
fetch,
|
||||
getRowKey,
|
||||
getDataSourceRef,
|
||||
getDataSource,
|
||||
setTableData,
|
||||
reload
|
||||
}
|
||||
}
|
||||
21
src/components/Table/src/hooks/useLoading.ts
Normal file
21
src/components/Table/src/hooks/useLoading.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { ref, ComputedRef, unref, computed, watch } from 'vue';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
|
||||
export function useLoading(props: ComputedRef<BasicTableProps>) {
|
||||
const loadingRef = ref(unref(props).loading);
|
||||
|
||||
watch(
|
||||
() => unref(props).loading,
|
||||
(loading) => {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
);
|
||||
|
||||
const getLoading = computed(() => unref(loadingRef));
|
||||
|
||||
function setLoading(loading: boolean) {
|
||||
loadingRef.value = loading;
|
||||
}
|
||||
|
||||
return { getLoading, setLoading };
|
||||
}
|
||||
48
src/components/Table/src/hooks/usePagination.ts
Normal file
48
src/components/Table/src/hooks/usePagination.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { PaginationProps } from '../types/pagination';
|
||||
import type { BasicTableProps } from '../types/table';
|
||||
import { computed, unref, ref, ComputedRef } from 'vue';
|
||||
|
||||
import { isBoolean } from '@/utils/is';
|
||||
import { DEFAULTPAGESIZE, PAGESIZES } from '../const';
|
||||
|
||||
export function usePagination(refProps: ComputedRef<BasicTableProps>) {
|
||||
const configRef = ref<PaginationProps>({});
|
||||
const show = ref(true);
|
||||
|
||||
const getPaginationInfo = computed((): PaginationProps | boolean => {
|
||||
const { pagination } = unref(refProps);
|
||||
if (!unref(show) || (isBoolean(pagination) && !pagination)) {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
pageSize: DEFAULTPAGESIZE,
|
||||
pageSizes: PAGESIZES,
|
||||
showSizePicker: true,
|
||||
showQuickJumper: true,
|
||||
...(isBoolean(pagination) ? {} : pagination),
|
||||
...unref(configRef),
|
||||
};
|
||||
});
|
||||
|
||||
function setPagination(info: Partial<PaginationProps>) {
|
||||
const paginationInfo = unref(getPaginationInfo);
|
||||
configRef.value = {
|
||||
...(!isBoolean(paginationInfo) ? paginationInfo : {}),
|
||||
...info,
|
||||
};
|
||||
}
|
||||
|
||||
function getPagination() {
|
||||
return unref(getPaginationInfo);
|
||||
}
|
||||
|
||||
function getShowPagination() {
|
||||
return unref(show);
|
||||
}
|
||||
|
||||
async function setShowPagination(flag: boolean) {
|
||||
show.value = flag;
|
||||
}
|
||||
|
||||
return { getPagination, getPaginationInfo, setShowPagination, getShowPagination, setPagination };
|
||||
}
|
||||
@@ -5,18 +5,18 @@ import { provide, inject, ComputedRef } from 'vue';
|
||||
const key = Symbol('s-table');
|
||||
|
||||
type Instance = TableActionType & {
|
||||
wrapRef: Ref<Nullable<HTMLElement>>;
|
||||
getBindValues: ComputedRef<Recordable>;
|
||||
wrapRef: Ref<Nullable<HTMLElement>>;
|
||||
getBindValues: ComputedRef<Recordable>;
|
||||
};
|
||||
|
||||
type RetInstance = Omit<Instance, 'getBindValues'> & {
|
||||
getBindValues: ComputedRef<BasicTableProps>;
|
||||
getBindValues: ComputedRef<BasicTableProps>;
|
||||
};
|
||||
|
||||
export function createTableContext(instance: Instance) {
|
||||
provide(key, instance);
|
||||
provide(key, instance);
|
||||
}
|
||||
|
||||
export function useTableContext(): RetInstance {
|
||||
return inject(key) as RetInstance;
|
||||
return inject(key) as RetInstance;
|
||||
}
|
||||
45
src/components/Table/src/props.ts
Normal file
45
src/components/Table/src/props.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { PropType } from 'vue'
|
||||
import { BasicColumn } from './types/table'
|
||||
|
||||
export const basicProps = {
|
||||
title: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
titleTooltip: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium',
|
||||
},
|
||||
tableData: {
|
||||
type: [Object],
|
||||
default: () => {
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
type: [Array] as PropType<BasicColumn[]>,
|
||||
default: () => [],
|
||||
required: true,
|
||||
},
|
||||
request: {
|
||||
type: Function as PropType<(...arg: any[]) => Promise<any>>,
|
||||
default: null,
|
||||
required: true
|
||||
},
|
||||
rowKey: {
|
||||
type: [String, Function] as PropType<string | ((record) => string)>,
|
||||
default: undefined,
|
||||
},
|
||||
pagination: {
|
||||
type: [Object, Boolean],
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
showPagination: {
|
||||
type: [String, Boolean],
|
||||
default: 'auto'
|
||||
}
|
||||
}
|
||||
11
src/components/Table/src/types/pagination.ts
Normal file
11
src/components/Table/src/types/pagination.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import Pagination from 'naive-ui/lib/pagination';
|
||||
import { VNodeChild } from 'vue';
|
||||
|
||||
export interface PaginationProps {
|
||||
page?: number;
|
||||
pageCount?: number,
|
||||
pageSize?: number,
|
||||
pageSizes?: number[],
|
||||
showSizePicker?: boolean,
|
||||
showQuickJumper?: boolean,
|
||||
}
|
||||
22
src/components/Table/src/types/table.ts
Normal file
22
src/components/Table/src/types/table.ts
Normal 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
|
||||
}
|
||||
1
src/components/Upload/index.ts
Normal file
1
src/components/Upload/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as BasicUpload } from './src/BasicUpload.vue';
|
||||
313
src/components/Upload/src/BasicUpload.vue
Normal file
313
src/components/Upload/src/BasicUpload.vue
Normal file
@@ -0,0 +1,313 @@
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div class="upload">
|
||||
<div class="upload-card">
|
||||
|
||||
<!--图片列表-->
|
||||
<div class="upload-card-item" :style="getCSSProperties" v-for="(item,index) in imgList">
|
||||
<div class="upload-card-item-info">
|
||||
<div class="img-box">
|
||||
<img :src="item"/>
|
||||
</div>
|
||||
<div class="img-box-actions">
|
||||
<n-icon size="18" class="action-icon mx-2" @click="preview(item)">
|
||||
<EyeOutlined/>
|
||||
</n-icon>
|
||||
<n-icon size="18" class="action-icon mx-2" @click="remove(index)">
|
||||
<DeleteOutlined/>
|
||||
</n-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--上传图片-->
|
||||
<div class="upload-card-item upload-card-item-select-picture" :style="getCSSProperties"
|
||||
v-if="imgList.length < maxNumber">
|
||||
<n-upload
|
||||
v-bind="$props"
|
||||
:file-list-style="{ display:'none'}"
|
||||
@before-upload="beforeUpload"
|
||||
@finish="finish"
|
||||
>
|
||||
<div class="flex justify-center flex-col">
|
||||
<n-icon size="18" class="m-auto">
|
||||
<PlusOutlined/>
|
||||
</n-icon>
|
||||
<span class="upload-title">上传图片</span>
|
||||
</div>
|
||||
</n-upload>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--上传图片-->
|
||||
<n-space>
|
||||
<n-alert title="提示" type="info" v-if="helpText" class="flex w-full">
|
||||
{{ helpText }}
|
||||
</n-alert>
|
||||
</n-space>
|
||||
|
||||
</div>
|
||||
|
||||
<!--预览图片-->
|
||||
<n-modal
|
||||
v-model:show="showModal"
|
||||
preset="card"
|
||||
title="预览"
|
||||
:bordered="false"
|
||||
:style="{width: '520px'}"
|
||||
>
|
||||
<img :src="previewUrl"/>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, toRefs, reactive, computed } from "vue";
|
||||
import { EyeOutlined, DeleteOutlined, PlusOutlined } from "@vicons/antd";
|
||||
import { NUpload } from 'naive-ui'
|
||||
import { basicProps } from "./props";
|
||||
import { useMessage, useDialog } from 'naive-ui'
|
||||
import { ResultEnum } from '@/enums/httpEnum'
|
||||
import componentSetting from '@/settings/componentSetting'
|
||||
import { useGlobSetting } from '@/hooks/setting'
|
||||
import { isString } from '@/utils/is'
|
||||
|
||||
const globSetting = useGlobSetting()
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BasicUpload',
|
||||
|
||||
components: { EyeOutlined, DeleteOutlined, PlusOutlined },
|
||||
props: {
|
||||
...NUpload.props, // 这里继承原 UI 组件的 props
|
||||
...basicProps
|
||||
},
|
||||
emits: ['uploadChange', 'delete'],
|
||||
setup(props, { emit }) {
|
||||
const { value, width, height } = props
|
||||
|
||||
const getCSSProperties = computed(() => {
|
||||
return {
|
||||
width: `${ width }px`,
|
||||
height: `${ height }px`,
|
||||
}
|
||||
})
|
||||
|
||||
const message = useMessage()
|
||||
const dialog = useDialog()
|
||||
|
||||
const state = reactive({
|
||||
showModal: false,
|
||||
previewUrl: '',
|
||||
originalImgList: [],
|
||||
imgList: []
|
||||
})
|
||||
|
||||
//赋值默认图片显示
|
||||
if (value.length) {
|
||||
state.imgList = value.map(item => {
|
||||
return getImgUrl(item)
|
||||
})
|
||||
}
|
||||
|
||||
//预览
|
||||
function preview(url: string) {
|
||||
state.showModal = true
|
||||
state.previewUrl = url
|
||||
}
|
||||
|
||||
//删除
|
||||
function remove(index: number) {
|
||||
dialog.info({
|
||||
title: '提示',
|
||||
content: '你确定要删除吗?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: () => {
|
||||
state.imgList.splice(index, 1)
|
||||
state.originalImgList.splice(index, 1)
|
||||
emit('uploadChange', state.originalImgList)
|
||||
emit('delete', state.originalImgList)
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//组装完整图片地址
|
||||
function getImgUrl(url: string) {
|
||||
const { imgUrl } = globSetting
|
||||
return (/(^http|https:\/\/)/g).test(url) ? url : `${ imgUrl }${ url }`
|
||||
}
|
||||
|
||||
|
||||
function checkFileType(fileType: string) {
|
||||
return componentSetting.upload.fileType.includes(fileType)
|
||||
}
|
||||
|
||||
//上传之前
|
||||
function beforeUpload({ file, fileList }) {
|
||||
const fileInfo = file.file;
|
||||
const { maxSize, accept, maxNumber } = props;
|
||||
const acceptRef = (isString(accept) && accept.split(',')) || [];
|
||||
|
||||
// 设置最大值,则判断
|
||||
if (maxSize && fileInfo.size / 1024 / 1024 >= maxSize) {
|
||||
message.error(`上传文件最大值不能超过${ maxSize }M`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置类型,则判断
|
||||
const fileType = componentSetting.upload.fileType
|
||||
if (acceptRef.length > 0 && !checkFileType(fileInfo.type)) {
|
||||
message.error(`只能上传文件类型为${ fileType.join(',') }`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
//上传结束
|
||||
function finish({ event: Event }) {
|
||||
const res = eval('(' + Event.target.response + ')');
|
||||
const infoField = componentSetting.upload.apiSetting.infoField
|
||||
const { code } = res
|
||||
const message = (res.msg || res.message) || '上传失败'
|
||||
const result = res[infoField]
|
||||
//成功
|
||||
if (code === ResultEnum.SUCCESS) {
|
||||
let imgUrl: string = getImgUrl(result.photo)
|
||||
state.imgList.push(imgUrl)
|
||||
state.originalImgList.push(result.photo)
|
||||
emit('uploadChange', state.originalImgList)
|
||||
} else message.error(message)
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
finish,
|
||||
preview,
|
||||
remove,
|
||||
beforeUpload,
|
||||
getCSSProperties
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
.upload {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
&-card {
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
|
||||
&-item {
|
||||
margin: 0 8px 8px 0;
|
||||
position: relative;
|
||||
padding: 8px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
background: 0 0;
|
||||
|
||||
&-info::before {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
|
||||
&-info {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
&:hover {
|
||||
.img-box-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
opacity: 0;
|
||||
transition: all .3s;
|
||||
content: ' ';
|
||||
}
|
||||
|
||||
.img-box {
|
||||
position: relative;
|
||||
//padding: 8px;
|
||||
//border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.img-box-actions {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 10;
|
||||
white-space: nowrap;
|
||||
transform: translate(-50%, -50%);
|
||||
opacity: 0;
|
||||
transition: all .3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&:hover {
|
||||
background: 0 0;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
color: rgba(255, 255, 255, .85);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #fff
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&-item-select-picture {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
|
||||
.upload-title {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&-item:hover {
|
||||
background: 0 0;
|
||||
|
||||
.upload-card-item-info::before {
|
||||
opacity: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
34
src/components/Upload/src/props.ts
Normal file
34
src/components/Upload/src/props.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { PropType } from 'vue'
|
||||
import { NUpload } from 'naive-ui'
|
||||
|
||||
export const basicProps = {
|
||||
...NUpload.props,
|
||||
accept: {
|
||||
type: String,
|
||||
default: '.jpg,.png,.jpeg,.svg,.gif',
|
||||
},
|
||||
helpText: {
|
||||
type: String as PropType<string>,
|
||||
default: '',
|
||||
},
|
||||
maxSize: {
|
||||
type: Number as PropType<number>,
|
||||
default: 2
|
||||
},
|
||||
maxNumber: {
|
||||
type: Number as PropType<number>,
|
||||
default: Infinity
|
||||
},
|
||||
value: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => []
|
||||
},
|
||||
width: {
|
||||
type: Number as PropType<number>,
|
||||
default: 104
|
||||
},
|
||||
height: {
|
||||
type: Number as PropType<number>,
|
||||
default: 104 //建议不小于这个尺寸 太小页面可能显示有异常
|
||||
},
|
||||
}
|
||||
7
src/components/Upload/src/type/index.ts
Normal file
7
src/components/Upload/src/type/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface BasicProps<T = any> {
|
||||
title?: string,
|
||||
dataSource: Function,
|
||||
columns: any[],
|
||||
pagination: object,
|
||||
showPagination: boolean
|
||||
}
|
||||
Reference in New Issue
Block a user