feat: 第三方库作为VUE插件进行初始化

master
luoer 2024-01-30 10:02:28 +08:00
parent 95021c503e
commit 7f9cbe8466
19 changed files with 108 additions and 93 deletions

View File

@ -1,6 +1,6 @@
{
"tabWidth": 2,
"printWidth": 120,
"printWidth": 180,
"bracketSpacing": true,
"singleQuote": true,
"arrowParens": "avoid"

View File

@ -1,7 +1,7 @@
{
"name": "starter-vue",
"private": true,
"version": "0.0.0",
"version": "0.0.1",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -22,8 +22,8 @@ addToastInterceptor(api.instance);
*
*/
addExceptionInterceptor(api.instance, () => api.expireHandler?.());
/**
*
*/
addAuthInterceptor(api.instance);

View File

@ -1,3 +1,4 @@
import { App } from 'vue';
import { Api } from '../generated/Api';
/**
@ -9,4 +10,12 @@ export class Service extends Api<unknown> {
* @description
*/
expireHandler: () => void = () => {};
/**
* VUE
* @param app
*/
install(app: App) {
app.config.globalProperties.$api = this;
}
}

View File

@ -5,11 +5,6 @@
<BreadCrumb></BreadCrumb>
<div>
<a-link>需要帮助</a-link>
<a-button size="mini" @click="router.push({ path: route.path, query: { s: Math.random() }, force: true })">
<template #icon>
<i class="icon-park-outline-redo"></i>
</template>
</a-button>
</div>
</div>
</div>

View File

@ -1,12 +1,4 @@
import {
AnForm,
AnFormInstance,
AnFormModal,
AnFormModalInstance,
AnFormModalProps,
AnFormProps,
getModel,
} from '@/components/AnForm';
import { AnForm, AnFormInstance, AnFormModal, AnFormModalInstance, AnFormModalProps, AnFormProps, getModel } from '@/components/AnForm';
import AnEmpty from '@/components/AnEmpty/AnEmpty.vue';
import { Button, PaginationProps, Table, TableColumnData, TableData, TableInstance } from '@arco-design/web-vue';
import { isArray, isFunction, merge } from 'lodash-es';
@ -14,14 +6,8 @@ import { InjectionKey, PropType, Ref, VNodeChild, defineComponent, ref } from 'v
import { PluginContainer } from '../hooks/useTablePlugin';
type DataFn = (filter: { page: number; size: number; [key: string]: any }) => any | Promise<any>;
export type ArcoTableProps = Omit<
TableInstance['$props'],
'ref' | 'pagination' | 'loading' | 'data' | 'onPageChange' | 'onPageSizeChange'
>;
export type ArcoTableProps = Omit<TableInstance['$props'], 'ref' | 'pagination' | 'loading' | 'data' | 'onPageChange' | 'onPageSizeChange'>;
export const AnTableContextKey = Symbol('AnTableContextKey') as InjectionKey<AnTableContext>;
export type TableColumnRender = (data: { record: TableData; column: TableColumnData; rowIndex: number }) => VNodeChild;
/**
@ -207,9 +193,7 @@ export const AnTable = defineComponent({
<div class="an-table table w-full">
<div class={`mb-3 flex gap-2 toolbar justify-between`}>
{this.create && <AnFormModal {...this.create} ref="createRef" onSubmited={this.reload}></AnFormModal>}
{this.modify && (
<AnFormModal {...this.modify} trigger={false} ref="modifyRef" onSubmited={this.refresh}></AnFormModal>
)}
{this.modify && <AnFormModal {...this.modify} trigger={false} ref="modifyRef" onSubmited={this.refresh}></AnFormModal>}
{this.$slots.action?.(this.renderData)}
{this.pluginer?.actions && (
<div class={`flex-1 flex gap-2 items-center`}>
@ -220,12 +204,7 @@ export const AnTable = defineComponent({
)}
{this.search && (
<div>
<AnForm
ref="searchRef"
v-model:model={this.search.model}
items={this.search.items}
formProps={this.search.formProps}
>
<AnForm ref="searchRef" v-model:model={this.search.model} items={this.search.items} formProps={this.search.formProps}>
{{
submit: () => (
<Button type="primary" loading={this.loading} onClick={this.reload}>
@ -279,10 +258,7 @@ export type AnTableInstance = InstanceType<typeof AnTable>;
/**
*
*/
export type AnTableProps = Pick<
AnTableInstance['$props'],
'source' | 'columns' | 'search' | 'paging' | 'create' | 'modify' | 'tableProps' | 'pluginer'
>;
export type AnTableProps = Pick<AnTableInstance['$props'], 'source' | 'columns' | 'search' | 'paging' | 'create' | 'modify' | 'tableProps' | 'pluginer'>;
export interface AnTableContext {
/**

View File

@ -0,0 +1,16 @@
import { ButtonProps, TableData } from '@arco-design/web-vue';
export interface AnTableActionBase {
text: string;
icon: string | Component;
visible: () => boolean;
disable: () => boolean;
buttonProps: ButtonProps;
}
interface AnTableActionBatch {
type: 'batch';
onClick: (rows: TableData) => void;
}
export type AnTableAction = AnTableActionBase & AnTableActionBatch;

View File

@ -35,6 +35,16 @@ export interface TableUseOptions extends Pick<AnTableProps, 'source' | 'tablePro
* ```
*/
columns?: TableColumn[];
/**
*
* @example
* ```ts
* [{
* text: '按钮',
* onClick: () => null,
* }]
* ```
*/
actions?: any[];
/**
*

View File

@ -2,22 +2,7 @@ import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import localData from 'dayjs/plugin/localeData';
import relativeTime from 'dayjs/plugin/relativeTime';
/**
*
*
*/
const DATETIME = 'YYYY-MM-DD HH:mm';
/**
*
*/
const DATE = 'YYYY-MM-DD';
/**
*
*/
const TIME = 'HH:mm:ss';
import { App } from 'vue';
/**
*
@ -63,4 +48,11 @@ dayjs.prototype.format = function (format: string = dayjs.DATETIME) {
return this._format(format);
};
export { DATE, DATETIME, TIME, dayjs };
/**
* VUE
*/
dayjs.install = function dayjsPlugin(app: App) {
app.config.globalProperties.$dayjs = dayjs;
};
export { dayjs };

View File

@ -1,4 +1,5 @@
import 'dayjs';
import { App } from 'vue';
declare module 'dayjs' {
/**
@ -13,4 +14,6 @@ declare module 'dayjs' {
interface Dayjs {
_format: Dayjs['format'];
}
export var install: (app: App) => void;
}

View File

@ -1,6 +1,7 @@
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import './nprogress.css';
import { App } from 'vue';
NProgress.configure({
showSpinner: false,
@ -8,5 +9,9 @@ NProgress.configure({
minimum: 0.3,
});
export { NProgress };
/**
* VUE
*/
NProgress.install = function (app: App) {};
export { NProgress };

8
src/libs/nprogress/interface.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
import 'nprogress';
import { App } from 'vue';
declare module 'nprogress' {
interface NProgress {
install: (app: App) => void;
}
}

View File

@ -1,12 +1,18 @@
import { createApp } from 'vue';
import App from './App.vue';
import { router } from './router';
import { store } from './store';
import { style } from './styles';
import App from '@/App.vue';
import { router } from '@/router';
import { store } from '@/store';
import { style } from '@/styles';
import { dayjs } from '@/libs/dayjs';
import { NProgress } from '@/libs/nprogress';
import { api } from '@/api';
const run = async () => {
const app = createApp(App);
app.use(dayjs);
app.use(NProgress);
app.use(store);
app.use(api);
app.use(style);
app.use(router);
await router.isReady();

View File

@ -42,14 +42,26 @@ export default defineComponent({
}
return (
<>
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => goto(route)}>
<div class="flex items-center justify-between gap-2">
<div>{route.title}</div>
<div class="text-xs text-gray-400">
{/* <a-badge count={8}>8</a-badge> */}
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
<a-menu-item key={route.path} v-slots={{ icon }}>
{route.link ? (
<div class="flex items-center justify-between gap-2" onClick={() => goto(route)}>
<div>{route.title}</div>
<div class="text-xs text-gray-400">
{/* <a-badge count={8}>8</a-badge> */}
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
</div>
</div>
</div>
) : (
<router-link to={route.path}>
<div class="flex items-center justify-between gap-2">
<div>{route.title}</div>
<div class="text-xs text-gray-400">
{/* <a-badge count={8}>8</a-badge> */}
{route.hide === 'prod' ? <a-tag color="red">{'开发'}</a-tag> : null}
</div>
</div>
</router-link>
)}
</a-menu-item>
</>
);

View File

@ -1,8 +1,6 @@
<template>
<a-layout class="layout">
<a-layout-header
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
>
<a-layout-header class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700">
<div class="h-13 flex items-center">
<!-- <a-button size="small" @click="isCollapsed = !isCollapsed">
<template #icon>
@ -19,18 +17,6 @@
</router-link>
</div>
<div class="flex items-center gap-2">
<div>
<a-input-search placeholder="搜索菜单/页面" :allow-clear="true"></a-input-search>
</div>
<a-tooltip content="上传文件">
<a-button @click="() => null" class="!bg-transparent !hover:bg-gray-100">
<template #icon>
<a-badge :count="1" :dot="true">
<i class="text-base icon-park-outline-upload-one"></i>
</a-badge>
</template>
</a-button>
</a-tooltip>
<a-tooltip v-for="btn in buttons" :key="btn.icon" :content="btn.tooltip">
<a-button @click="btn.onClick" class="!bg-transparent !hover:bg-gray-100">
<template #icon>
@ -90,9 +76,9 @@ import { useAppStore } from '@/store/app';
import { useMenuStore } from '@/store/menu';
import { Message } from '@arco-design/web-vue';
import { IconSync } from '@arco-design/web-vue/es/icon';
import { useFullscreen } from '@vueuse/core';
import Menu from './Menu.vue';
import userDropdown from './UserDropdown.vue';
import { useFullscreen } from '@vueuse/core';
defineOptions({ name: 'LayoutPage' });

View File

@ -2,10 +2,6 @@
<AnPage></AnPage>
</template>
<script setup lang="tsx"></script>
<style lang="less"></style>
<route lang="json">
{
"redirect": "/setting/common",

View File

@ -1,4 +1,4 @@
import { NProgress } from '@/libs/nprogress';
import NProgress from 'nprogress';
import { useAppStore } from '@/store/app';
import { Router } from 'vue-router';

View File

@ -78,10 +78,10 @@ body {
background-color: var(--color-neutral-2);
}
&.arco-menu-selected {
color: @arcoblue-6;
background-color: rgb(var(--primary-1));
// color: #fff;
// background-color: rgb(var(--primary-6));
// color: @arcoblue-6;
// background-color: rgb(var(--primary-1));
color: #fff;
background-color: rgb(var(--primary-6));
.arco-menu-icon {
color: inherit;
}

5
src/types/vue.d.ts vendored
View File

@ -1,8 +1,9 @@
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { Router, RouteLocationNormalizedLoaded } from 'vue-router';
declare module "vue" {
declare module 'vue' {
interface ComponentCustomProperties {
$router: Router;
$route: RouteLocationNormalizedLoaded;
$dayjs: Dayjs;
}
}