diff --git a/.gitea/stat.html b/.gitea/stat.html
deleted file mode 100644
index 0ed7872..0000000
--- a/.gitea/stat.html
+++ /dev/null
@@ -1,4842 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+

+
欢迎访问%VITE_TITLE%
+
资源加载中, 请稍等...
diff --git a/package.json b/package.json
index b170dc0..f63c3fa 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vueuse/core": "^10.7.1",
+ "arconify": "^0.0.2",
"axios": "^1.6.5",
"dayjs": "^1.11.10",
"dplayer": "^1.27.1",
diff --git a/scripts/vite/plugin-pages.ts b/scripts/vite/plugin-pages.ts
new file mode 100644
index 0000000..5e3ba94
--- /dev/null
+++ b/scripts/vite/plugin-pages.ts
@@ -0,0 +1,20 @@
+import { RouteRecordRaw } from 'vue-router';
+
+export function onRoutesGenerated(routes: RouteRecordRaw[], mode: string) {
+ const isProd = mode !== 'development';
+ const result = [];
+ for (const route of routes) {
+ const { hide } = route.meta ?? {};
+ if (!route.meta) {
+ continue;
+ }
+ if (hide === true) {
+ continue;
+ }
+ if (isProd && hide === 'prod') {
+ continue;
+ }
+ result.push(route);
+ }
+ return result;
+}
diff --git a/src/api/interceptors/auth.ts b/src/api/interceptors/auth.ts
index f433c10..a48b640 100644
--- a/src/api/interceptors/auth.ts
+++ b/src/api/interceptors/auth.ts
@@ -12,7 +12,6 @@ export function addAuthInterceptor(axios: AxiosInstance) {
if (userStore.accessToken) {
config.headers.Authorization = `Bearer ${userStore.accessToken}`;
}
- // throw Error('dd');
return config;
});
}
diff --git a/src/components/AnBreadcrumb/bread-crumb.vue b/src/components/AnBreadcrumb.vue
similarity index 100%
rename from src/components/AnBreadcrumb/bread-crumb.vue
rename to src/components/AnBreadcrumb.vue
diff --git a/src/components/AnEmpty/AnEmpty.vue b/src/components/AnEmpty.vue
similarity index 100%
rename from src/components/AnEmpty/AnEmpty.vue
rename to src/components/AnEmpty.vue
diff --git a/src/components/AnForbidden/AnForbidden.vue b/src/components/AnForbidden.vue
similarity index 100%
rename from src/components/AnForbidden/AnForbidden.vue
rename to src/components/AnForbidden.vue
diff --git a/src/components/AnForm/components/Form.tsx b/src/components/AnForm/components/Form.tsx
deleted file mode 100644
index fb45352..0000000
--- a/src/components/AnForm/components/Form.tsx
+++ /dev/null
@@ -1,155 +0,0 @@
-import { Form, FormInstance, Message } from '@arco-design/web-vue';
-import { useVModel } from '@vueuse/core';
-import { ComputedRef, InjectionKey, PropType, Ref } from 'vue';
-import { initFormItems } from '../utils/useFormItems';
-import { FormRef, useFormRef } from '../utils/useFormRef';
-import { AnFormItem, AnFormItemProps } from './FormItem';
-import { cloneDeep, isFunction, isObject, merge } from 'lodash-es';
-import { getModel } from '../utils/useFormModel';
-
-const SUBMIT_ITEM = {
- field: 'id',
- setter: 'submit' as const,
- itemProps: {
- hideLabel: true,
- },
-};
-
-export type FormContextInterface = FormRef & {
- model: Ref
;
- items: ComputedRef;
- loading: Ref;
- submitForm: any;
- resetForm: any;
-};
-
-export const FormContextKey = Symbol('FormContextKey') as InjectionKey;
-
-/**
- * 表单组件
- */
-export const AnForm = defineComponent({
- name: 'AnForm',
- props: {
- /**
- * 表单数据
- * @example
- * ```ts
- * {
- * id: undefined
- * }
- * ```
- */
- model: {
- type: Object as PropType,
- default: () => ({}),
- },
- /**
- * 表单项
- * @example
- * ```ts
- * [{
- * field: 'name',
- * label: '昵称',
- * setter: 'input'
- * }]
- * ```
- */
- items: {
- type: Array as PropType,
- default: () => [],
- },
- /**
- * 提交表单
- * @example
- * ```ts
- * (model) => api.user.addUser(model)
- * ```
- */
- submit: {
- type: [Function, Object] as PropType,
- },
- /**
- * 传给Form组件的参数
- * @exmaple
- * ```ts
- * {
- * layout: 'vertical'
- * }
- * ```
- */
- formProps: {
- type: Object as PropType>,
- },
- },
- emits: ['update:model'],
- setup(props, { slots, emit }) {
- const model = useVModel(props, 'model', emit);
- const items = computed(() => props.items);
- const initModel = cloneDeep(model.value);
- const loading = ref(false);
- const { formRef, ...formMethods } = useFormRef();
-
- const submitItem = () => {
- if (!props.submit) {
- return null;
- }
- if (isFunction(props.submit)) {
- return SUBMIT_ITEM;
- }
- if (isObject(props.submit)) {
- return merge({}, SUBMIT_ITEM, props.submit);
- }
- };
-
- const resetForm = () => {
- model.value = cloneDeep(initModel);
- formRef.value?.clearValidate();
- };
-
- const submitForm = async () => {
- if (await formRef.value?.validate()) {
- return;
- }
- const submit: any = typeof props.submit === 'object' ? props.submit.visible : props.submit;
- try {
- loading.value = true;
- const data = getModel(model.value);
- const res = await submit?.(data, props.items);
- const msg = res?.data?.message;
- msg && Message.success(`提示: ${msg}`);
- } catch (e) {
- console.log(e);
- } finally {
- loading.value = false;
- }
- };
-
- const context = { slots, loading, resetForm, submitForm, submitItem, model, items, formRef, ...formMethods };
- provide(FormContextKey, context);
-
- onMounted(() => {
- initFormItems(props.items, model.value);
- });
-
- return context;
- },
- render() {
- return (
-
- );
- },
-});
-
-export type AnFormInstance = InstanceType;
-
-export type AnFormProps = Pick;
-
-export type AnFormSubmitFn = (model: Recordable, items: AnFormItemProps[]) => any;
-
-export type AnFormSubmit = AnFormSubmitFn | AnFormItemProps;
diff --git a/src/components/AnForm/components/FormItem.tsx b/src/components/AnForm/components/FormItem.tsx
deleted file mode 100644
index 4570c97..0000000
--- a/src/components/AnForm/components/FormItem.tsx
+++ /dev/null
@@ -1,226 +0,0 @@
-import { FormItem, FieldRule, FormItemInstance, SelectOptionData, SelectOptionGroup } from '@arco-design/web-vue';
-import { InjectionKey, PropType, provide } from 'vue';
-import { SetterItem, SetterType, setterMap } from './FormSetter';
-
-export const FormItemContextKey = Symbol('FormItemContextKey') as InjectionKey;
-
-/**
- * 表单项
- */
-export const AnFormItem = defineComponent({
- name: 'AnFormItem',
- props: {
- /**
- * 表单项
- */
- item: {
- type: Object as PropType,
- required: true,
- },
- /**
- * 表单项数组
- */
- items: {
- type: Array as PropType,
- required: true,
- },
- /**
- * 表单数据
- */
- model: {
- type: Object as PropType,
- required: true,
- },
- },
- setup(props) {
- const rules = computed(() => props.item.rules?.filter(i => !i.disable?.(props)));
- const disabled = computed(() => Boolean(props.item.disable?.(props)));
-
- const setterSlots = (() => {
- const slots = props.item.setterSlots;
- if (!slots) {
- return null;
- }
- const items: Recordable = {};
- for (const [name, Slot] of Object.entries(slots)) {
- items[name] = (p: Recordable) => ;
- }
- return items;
- })();
-
- const itemSlots = (() => {
- const Setter = setterMap[props.item.setter as SetterType]?.setter as any;
- const slots = props.item.itemSlots;
- if (!slots && !Setter) {
- return null;
- }
- const SetterRender = () => (
-
- {setterSlots}
-
- );
- if (!slots) {
- return {
- default: SetterRender,
- };
- }
- const items: Recordable = {};
- for (const [name, Slot] of Object.entries(slots)) {
- items[name] = (p: Recordable) => ;
- }
- if (Setter) {
- items.default = SetterRender;
- }
- return items;
- })();
-
- provide(FormItemContextKey, props);
-
- return () => {
- if (props.item.visible && !props.item.visible(props)) {
- return null;
- }
- return (
-
- {itemSlots}
-
- );
- };
- },
-});
-
-export type AnFormItemBoolFn = (args: AnFormItemFnProps) => boolean;
-
-export type AnFormItemElemFn = (args: AnFormItemFnProps) => any;
-
-export type AnFormItemFnProps = { model: Recordable; item: AnFormItemProps; items: AnFormItemProps[] };
-
-export type AnFormItemRule = FieldRule & { disable?: AnFormItemBoolFn };
-
-export type AnFormItemOption = string | number | boolean | SelectOptionData | SelectOptionGroup;
-
-export type AnFormItemSlot = (props: AnFormItemFnProps) => any;
-
-export type AnFormItemSlots = {
- /**
- * 默认插槽
- * @param props 参数
- */
- default?: AnFormItemSlot;
-
- /**
- * 帮助插槽
- * @param props 参数
- */
- help?: AnFormItemSlot;
-
- /**
- * 额外插槽
- * @param props 参数
- */
- extra?: AnFormItemSlot;
-
- /**
- * 标签插槽
- * @param props 参数
- */
- label?: AnFormItemSlot;
-};
-
-export type AnFormItemPropsBase = {
- /**
- * 字段名
- * @description 字段名唯一,支持特殊语法
- * @example
- * ```ts
- * 'username'
- * ```
- */
- field: string;
-
- /**
- * 标签
- * @example
- * ```ts
- * '昵称'
- * ```
- */
- label?: string;
-
- /**
- * 校验规则
- * @example
- * ```ts
- * ['email']
- * ```
- */
- rules?: AnFormItemRule[];
-
- /**
- * 是否可见
- * @example
- * ```ts
- * (props) => Boolean(props.model.id)
- * ```
- */
- visible?: AnFormItemBoolFn;
-
- /**
- * 是否禁用
- * @example
- * ```ts
- * (props) => Boolean(props.model.id)
- * ```
- */
- disable?: AnFormItemBoolFn;
-
- /**
- * 选项
- * @description 适用于下拉框等组件
- * @example
- * ```ts
- * [{
- * label: '方式1',
- * value: 1
- * }]
- * ```
- */
- options?: AnFormItemOption[] | ((args: AnFormItemFnProps) => AnFormItemOption[] | Promise);
-
- /**
- * 表单项参数
- * @example
- * ```ts
- * {
- * hideLabel: true
- * }
- * ```
- */
- itemProps?: Partial>;
-
- /**
- * 表单项插槽
- * @example
- * ```tsx
- * {
- * help: () => 帮助提示
- * }
- * ```
- */
- itemSlots?: AnFormItemSlots;
-
- /**
- * 内置
- * @private
- */
- $init?: () => void;
-};
-
-export type AnFormItemProps = AnFormItemPropsBase & SetterItem;
diff --git a/src/components/AnForm/components/FormModal.tsx b/src/components/AnForm/components/FormModal.tsx
deleted file mode 100644
index fa6c65c..0000000
--- a/src/components/AnForm/components/FormModal.tsx
+++ /dev/null
@@ -1,269 +0,0 @@
-import { Button, ButtonInstance, FormInstance, Message, Modal } from '@arco-design/web-vue';
-import { useVModel } from '@vueuse/core';
-import { InjectionKey, PropType, Ref } from 'vue';
-import { getModel, setModel } from '../utils/useFormModel';
-import { AnForm, AnFormInstance, AnFormSubmit } from './Form';
-import { AnFormItemProps } from './FormItem';
-import { cloneDeep } from 'lodash-es';
-
-export interface AnFormModalContext {
- visible: Ref;
- loading: Ref;
- anFormRef: Ref;
- submitForm: () => any | Promise;
- open: (data: Recordable) => void;
- close: () => void;
- modalTitle: () => any;
- modalTrigger: () => any;
- onClose: () => void;
-}
-
-export const AnFormModalContextKey = Symbol('AnFormModalContextKey') as InjectionKey;
-
-/**
- * 表单组件
- */
-export const AnFormModal = defineComponent({
- name: 'AnFormModal',
- props: {
- /**
- * 弹窗标题
- * @default
- * ```ts
- * '新增'
- * ```
- */
- title: {
- type: [String, Function] as PropType,
- default: '新增',
- },
- /**
- * 触发元素
- * @default
- * ```ts
- * '新增'
- * ```
- */
- trigger: {
- type: [Boolean, String, Function, Object] as PropType,
- default: true,
- },
- /**
- * 传递给Modal的props
- * @example
- * ```ts
- * {
- * closable: true
- * }
- * ```
- */
- modalProps: {
- type: Object as PropType['$props'], 'visible' | 'title'>>,
- },
- /**
- * 表单数据
- * @example
- * ```ts
- * {
- * id: undefined
- * }
- * ```
- */
- model: {
- type: Object as PropType,
- required: true,
- },
- /**
- * 表单项
- * @example
- * ```ts
- * [{
- * field: 'name',
- * label: '昵称',
- * setter: 'input'
- * }]
- * ```
- */
- items: {
- type: Array as PropType,
- default: () => [],
- },
- /**
- * 提交表单
- * @example
- * ```ts
- * (model) => api.user.addUser(model)
- * ```
- */
- submit: {
- type: [Object, Function] as PropType,
- },
- /**
- * 传给Form组件的参数
- * @example
- * ```ts
- * {
- * layout: 'vertical'
- * }
- * ```
- */
- formProps: {
- type: Object as PropType>,
- },
- },
- emits: ['update:model', 'submited'],
- setup(props, { emit }) {
- const model = useVModel(props, 'model', emit);
- const originModel = cloneDeep(model.value);
- const anFormRef = ref(null);
- const visible = ref(false);
- const loading = ref(false);
-
- const modalTitle = () => {
- if (typeof props.title === 'string') {
- return props.title;
- }
- return ;
- };
-
- const modalTrigger = () => {
- if (!props.trigger) {
- return null;
- }
- if (typeof props.trigger === 'function') {
- return ;
- }
- const internal = {
- text: '新增',
- buttonProps: {},
- buttonSlots: {},
- };
- if (typeof props.trigger === 'string') {
- internal.text = props.trigger;
- }
- if (typeof props.trigger === 'object') {
- Object.assign(internal, props.trigger);
- }
- return (
-
- );
- };
-
- const submitForm = async () => {
- if (await anFormRef.value?.validate()) {
- return;
- }
- try {
- loading.value = true;
- const data = getModel(model.value);
- const res = await (props as any).submit?.(data, props.items);
- const msg = res?.data?.message;
- msg && Message.success(msg);
- visible.value = false;
- emit('submited', res);
- } catch {
- // todo
- } finally {
- loading.value = false;
- }
- };
-
- const open = async (data: Recordable = {}) => {
- visible.value = true;
- await nextTick();
- model.value = cloneDeep(originModel)
- setModel(model.value, data);
- };
-
- const close = () => {
- loading.value = false;
- visible.value = false;
- };
-
- const onClose = () => {};
-
- const context: AnFormModalContext = {
- visible,
- loading,
- anFormRef,
- open,
- close,
- onClose,
- submitForm,
- modalTitle,
- modalTrigger,
- };
-
- provide(AnFormModalContextKey, context);
-
- return {
- ...context
- };
- },
- render() {
- return (
- <>
-
-
- {{
- title: this.modalTitle,
- default: () => (
- this.$emit('update:model', v)}
- items={this.items}
- formProps={this.formProps}
- >
- ),
- footer: () => (
-
-
-
-
-
-
-
- ),
- }}
-
- >
- );
- },
-});
-
-export type AnFormModalTitle = string | ((model: Recordable, items: AnFormItemProps[]) => any);
-
-export type AnFormModalTrigger =
- | boolean
- | string
- | ((model: Recordable, items: AnFormItemProps[]) => any)
- | {
- text?: string;
- buttonProps?: ButtonInstance['$props'];
- buttonSlots?: Recordable;
- };
-
-export type AnFormModalInstance = InstanceType;
-
-export type AnFormModalProps = Pick<
- AnFormModalInstance['$props'],
- 'title' | 'trigger' | 'modalProps' | 'model' | 'items' | 'submit' | 'formProps'
->;
diff --git a/src/components/AnForm/components/FormSetter.tsx b/src/components/AnForm/components/FormSetter.tsx
deleted file mode 100644
index 1762525..0000000
--- a/src/components/AnForm/components/FormSetter.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import setterMap from '../setters';
-
-/**
- * 键值对类型
- */
-export type SetterMap = typeof setterMap;
-
-/**
- * 组件名联合类型
- */
-export type SetterType = keyof SetterMap;
-
-/**
- * 重新映射
- */
-export type SetterItemMap = {
- [key in SetterType]: {
- /**
- * 控件类型
- * @example
- * ```ts
- * 'input'
- * ```
- */
- setter: key;
- /**
- * 控件参数
- * @example
- * ```tsx
- * { type: "password" }
- * ```
- */
- setterProps?: SetterMap[key]['setterProps'];
- /**
- * 控件插槽
- * @example
- * ```tsx
- * label: (props) => {props.item.label}
- * ```
- */
- setterSlots?: SetterMap[key]['setterSlots'];
- };
-};
-
-/**
- * 控件类型
- */
-export type SetterItem =
- | SetterItemMap[SetterType]
- | { setter?: undefined; setterProps?: undefined; setterSlots?: undefined };
-
-export { setterMap };
diff --git a/src/components/AnForm/hooks/useForm.tsx b/src/components/AnForm/hooks/useForm.tsx
deleted file mode 100644
index 797655b..0000000
--- a/src/components/AnForm/hooks/useForm.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { merge } from 'lodash-es';
-import { AnForm, AnFormInstance, AnFormProps } from '../components/Form';
-import { FormItem, useFormItems } from './useFormItems';
-
-export type FormUseOptions = Partial> & {
- /**
- * 表单项
- * @example
- * ```ts
- * [{
- * field: 'name',
- * label: '昵称',
- * setter: 'input'
- * }]
- * ```
- */
- items?: FormItem[];
-};
-
-export function useFormProps(options: FormUseOptions): Required {
- const { model: _model = {}, items: _items = [], submit = () => null, formProps = {} } = options;
- const model = merge({ id: undefined }, _model);
- const items = useFormItems(_items ?? [], model);
- return {
- model,
- items,
- submit,
- formProps,
- };
-}
-
-/**
- * 构建表单组件的参数
- */
-export const useForm = (options: FormUseOptions) => {
- const props = reactive(useFormProps(options));
- const formRef = ref(null);
-
- const AnFormer = () => (
- (formRef.value = el)}
- v-model:model={props.model}
- items={props.items}
- submit={props.submit}
- formProps={props.formProps}
- >
- );
-
- return {
- component: AnFormer,
- formRef,
- props,
- };
-};
diff --git a/src/components/AnForm/hooks/useFormItems.tsx b/src/components/AnForm/hooks/useFormItems.tsx
deleted file mode 100644
index 99d92ba..0000000
--- a/src/components/AnForm/hooks/useFormItems.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { defaultsDeep, has, merge, omit } from 'lodash-es';
-import { AnFormItemProps, AnFormItemPropsBase } from '../components/FormItem';
-import { SetterItem, setterMap } from '../components/FormSetter';
-import { Rule, useFormRules } from './useFormRules';
-
-/**
- * 表单项数据
- */
-export type FormItem = Omit &
- SetterItem & {
- /**
- * 默认值
- * @example
- * ```ts
- * '1'
- * ```
- */
- value?: any;
-
- /**
- * 是否必填
- * @default
- * ```ts
- * false
- * ```
- */
- required?: boolean;
-
- /**
- * 校验规则
- * @example
- * ```ts
- * ['email']
- * ```
- */
- rules?: Rule[];
-
- /**
- * 参数 `setterProps.placeholder` 的快捷语法
- * @example
- * ```ts
- * '请输入用户名称'
- * ```
- */
- placeholder?: string | string[];
- };
-
-const ITEM: Partial = {
- setter: 'input',
-};
-
-export function useFormItems(items: FormItem[], model: Recordable) {
- const data: AnFormItemProps[] = [];
-
- for (const item of items) {
- let target: AnFormItemProps = defaultsDeep({}, ITEM);
-
- if (!item.setter || typeof item.setter === 'string') {
- const setter = setterMap[item.setter ?? 'input'];
- if (setter) {
- defaultsDeep(target, { setterProps: setter.setterProps ?? {} });
- }
- }
-
- target = merge(target, omit(item, ['required', 'rules', 'value', 'placeholder']));
-
- if (item.required || item.rules) {
- const rules = useFormRules(item)!;
- target.rules = rules;
- }
-
- if (target.setterProps && has(item, 'placeholder')) {
- (target.setterProps as Recordable).placholder = item.placeholder;
- }
-
- if (!has(model, item.field)) {
- model[item.field] = item.value;
- }
-
- data.push(target);
- }
-
- return data;
-}
diff --git a/src/components/AnForm/hooks/useFormModal.tsx b/src/components/AnForm/hooks/useFormModal.tsx
deleted file mode 100644
index 0794d24..0000000
--- a/src/components/AnForm/hooks/useFormModal.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { merge } from 'lodash-es';
-import { AnFormModal, AnFormModalProps } from '../components/FormModal';
-import { useFormProps } from './useForm';
-import { FormItem } from './useFormItems';
-
-export type FormModalUseOptions = Partial> & {
- /**
- * 弹窗宽度
- * @description 参数 `modalProps.width` 的便捷语法
- * @example
- * ```ts
- * 580
- * ```
- */
- width?: number;
- /**
- * modal宽度
- * @example
- * ```ts
- * 1080
- * ```
- */
- modalWidth?: number;
- /**
- * 表单类名
- * @description 参数 `formProps.class` 的便捷语法
- * @example
- * ```ts
- * 'grid grid-cols-2'
- * ```
- */
- formClass?: unknown;
- /**
- * 表单项
- * @example
- * ```tsx
- * [{
- * field: 'name',
- * label: '昵称',
- * setter: 'input'
- * }]
- * ```
- */
- items: FormItem[];
-};
-
-export function useFormModalProps(options: FormModalUseOptions): AnFormModalProps {
- if (options.width) {
- merge(options, { modalProps: { width: options.width } });
- }
- if (options.formClass) {
- merge(options, { formProps: { class: options.formClass } });
- }
- const { items, model, formProps } = useFormProps({ ...options, submit: undefined });
- const { trigger, title, submit, modalProps } = options;
- return {
- trigger,
- model,
- items,
- title,
- submit,
- formProps,
- modalProps,
- };
-}
-
-export function useFormModal(options: FormModalUseOptions) {
- const modalRef = ref | null>(null);
- const formRef = computed(() => modalRef.value?.anFormRef);
- const open = (data: Recordable = {}) => modalRef.value?.open(data);
- const rawProps = useFormModalProps(options);
- const props = reactive(rawProps);
-
- const component = () => (
- (modalRef.value = el)}
- title={props.title}
- trigger={props.trigger}
- modalProps={props.modalProps as any}
- model={props.model}
- items={props.items}
- formProps={props.formProps}
- submit={props.submit}
- onUpdate:model={model => ((props as any).model = model)}
- >
- );
-
- return {
- props,
- component,
- modalRef,
- formRef,
- open,
- };
-}
diff --git a/src/components/AnForm/hooks/useFormRules.tsx b/src/components/AnForm/hooks/useFormRules.tsx
deleted file mode 100644
index fda9abe..0000000
--- a/src/components/AnForm/hooks/useFormRules.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import { FieldRule } from "@arco-design/web-vue";
-import { has, isString } from "lodash-es";
-import { AnFormItemRule } from "../components/FormItem";
-
-/**
- * 内置规则
- */
-export const FieldRuleMap = defineRuleMap({
- required: {
- required: true,
- message: "该项不能为空",
- },
- string: {
- type: "string",
- message: "请输入字符串",
- },
- number: {
- type: "number",
- message: "请输入数字",
- },
- email: {
- type: "email",
- message: "邮箱格式错误,示例: xx@abc.com",
- },
- url: {
- type: "url",
- message: "URL格式错误, 示例: www.abc.com",
- },
- ip: {
- type: "ip",
- message: "IP格式错误, 示例: 101.10.10.30",
- },
- phone: {
- match: /^(?:(?:\+|00)86)?1\d{10}$/,
- message: "手机格式错误, 示例(11位): 15912345678",
- },
- idcard: {
- match: /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/,
- message: "身份证格式错误, 长度为15或18位",
- },
- alphabet: {
- match: /^[a-zA-Z]\w{4,15}$/,
- message: "请输入英文字母, 长度为4~15位",
- },
- password: {
- match: /^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/,
- message: "至少包含大写字母、小写字母、数字和特殊字符",
- },
-});
-
-/**
- * 字符串形式(枚举)
- */
-export type FieldStringRule = keyof typeof FieldRuleMap;
-
-/**
- * 完整类型
- */
-export type Rule = FieldStringRule | AnFormItemRule;
-
-/**
- * 助手函数(获得TS提示)
- */
-function defineRuleMap>(ruleMap: T) {
- return ruleMap;
-}
-
-/**
- * 获取表单规则
- * @param item 表单项
- * @returns
- */
-export const useFormRules = (item: T) => {
- const data: AnFormItemRule[] = [];
- const { required, rules } = item;
-
- if (!has(item, "required") && !has(item, "rules")) {
- return null;
- }
-
- if (required) {
- data.push(FieldRuleMap.required);
- }
-
- for (const rule of rules ?? []) {
- if (isString(rule)) {
- if (FieldRuleMap[rule]) {
- data.push(FieldRuleMap[rule]);
- }
- } else {
- data.push(rule);
- }
- }
-
- return data;
-};
diff --git a/src/components/AnForm/index.ts b/src/components/AnForm/index.ts
deleted file mode 100644
index f60fea7..0000000
--- a/src/components/AnForm/index.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export * from './components/Form';
-export * from './components/FormItem';
-export * from './components/FormModal';
-export * from './components/FormSetter';
-export * from './utils/useFormItems';
-export * from './utils/useFormModel';
-export * from './utils/useFormRef';
-export * from './hooks/useForm';
-export * from './hooks/useFormModal';
-export * from './hooks/useFormItems';
-export * from './hooks/useFormRules';
-export * from './setters';
diff --git a/src/components/AnForm/setters/Cascader.tsx b/src/components/AnForm/setters/Cascader.tsx
deleted file mode 100644
index 2ff7c09..0000000
--- a/src/components/AnForm/setters/Cascader.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Cascader, CascaderInstance } from '@arco-design/web-vue';
-import { defineSetter, initOptions } from './util';
-
-type CascaderProps = CascaderInstance['$props'];
-
-type CascaderSlots = 'label' | 'prefix' | 'arrowIcon' | 'loadingIcon' | 'searchIcon' | 'empty' | 'option';
-
-export default defineSetter({
- setter: Cascader,
- setterProps: {
- placeholder: '请选择',
- allowClear: true,
- expandTrigger: 'hover',
- },
- onSetup: initOptions as any,
-});
diff --git a/src/components/AnForm/setters/Date.tsx b/src/components/AnForm/setters/Date.tsx
deleted file mode 100644
index 419b42f..0000000
--- a/src/components/AnForm/setters/Date.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DatePicker, DatePickerInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-import { PickerProps } from '@arco-design/web-vue/es/date-picker/interface';
-
-type DateProps = DatePickerInstance['$props'] & Partial;
-
-type DateSlots =
- | 'prefix'
- | 'suffixIcon'
- | 'iconNextDouble'
- | 'iconPrevDouble'
- | 'iconNext'
- | 'iconPrev'
- | 'cell'
- | 'extra';
-
-export default defineSetter({
- setter: DatePicker,
- setterProps: {
- placeholder: '请选择',
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/DateRange.tsx b/src/components/AnForm/setters/DateRange.tsx
deleted file mode 100644
index f2d8963..0000000
--- a/src/components/AnForm/setters/DateRange.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { RangePicker, RangePickerInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type RangeProps = RangePickerInstance['$props'];
-
-type RangeSlots = "none";
-
-export default defineSetter({
- setter: RangePicker,
- setterProps: {
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/Input.tsx b/src/components/AnForm/setters/Input.tsx
deleted file mode 100644
index aa41360..0000000
--- a/src/components/AnForm/setters/Input.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Input, InputInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type InputProps = InputInstance['$props'];
-
-type InputSlots = 'prepend' | 'append' | 'suffix' | 'prefix';
-
-export default defineSetter({
- setter: Input,
- setterProps: {
- placeholder: '请输入',
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/Number.tsx b/src/components/AnForm/setters/Number.tsx
deleted file mode 100644
index 4c5ecaf..0000000
--- a/src/components/AnForm/setters/Number.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { InputInstance, InputNumber, InputNumberInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type NumberProps = InputInstance['$props'] | InputNumberInstance['$props'];
-
-type NumberSlots = 'minus' | 'plus' | 'append' | 'prepend' | 'suffix' | 'prefix';
-
-export default defineSetter({
- setter: InputNumber,
- setterProps: {
- placeholder: '请输入',
- defaultValue: 0,
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/Password.tsx b/src/components/AnForm/setters/Password.tsx
deleted file mode 100644
index 2de9634..0000000
--- a/src/components/AnForm/setters/Password.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { InputInstance, InputPassword, InputPasswordInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type PasswordProps = InputInstance['$props'] & InputPasswordInstance['$props'];
-
-type PasswordSlots = 'none';
-
-export default defineSetter({
- setter: InputPassword,
- setterProps: {
- placeholder: '请输入',
- },
-});
diff --git a/src/components/AnForm/setters/Search.tsx b/src/components/AnForm/setters/Search.tsx
deleted file mode 100644
index f544771..0000000
--- a/src/components/AnForm/setters/Search.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { InputInstance, InputSearch, InputSearchInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type SearchProps = InputInstance['$props'] & InputSearchInstance['$props'];
-
-type SearchSlots = "none";
-
-export default defineSetter({
- setter: InputSearch,
- setterProps: {
- placeholder: '请输入',
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/Select.tsx b/src/components/AnForm/setters/Select.tsx
deleted file mode 100644
index 37a2195..0000000
--- a/src/components/AnForm/setters/Select.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Select, SelectInstance } from '@arco-design/web-vue';
-import { defineSetter, initOptions } from './util';
-
-type SelectProps = SelectInstance['$props'];
-
-type SelectSlots =
- | 'trigger'
- | 'prefix'
- | 'searchIcon'
- | 'loadingIcon'
- | 'arrowIcon'
- | 'footer'
- | 'header'
- | 'label'
- | 'option'
- | 'empty';
-
-export default defineSetter({
- setter: Select,
- onSetup: initOptions as any,
- setterProps: {
- placeholder: '请选择',
- allowClear: true,
- allowSearch: true,
- options: [],
- },
-});
diff --git a/src/components/AnForm/setters/Submit.tsx b/src/components/AnForm/setters/Submit.tsx
deleted file mode 100644
index 6eaf335..0000000
--- a/src/components/AnForm/setters/Submit.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Button } from '@arco-design/web-vue';
-import { FormContextKey } from '../components/Form';
-import { defineSetter } from './util';
-
-export default defineSetter<{}, 'none'>({
- setter() {
- const { submitForm, resetForm } = inject(FormContextKey)!;
- return (
- <>
-
-
- >
- );
- },
- setterProps: {},
-});
diff --git a/src/components/AnForm/setters/Textarea.tsx b/src/components/AnForm/setters/Textarea.tsx
deleted file mode 100644
index ee77484..0000000
--- a/src/components/AnForm/setters/Textarea.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { InputInstance, Textarea, TextareaInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type TextareaProps = InputInstance['$props'] & TextareaInstance['$props'];
-
-type TextareaSlots = "none";
-
-export default defineSetter({
- setter: Textarea,
- setterProps: {
- placeholder: '请输入',
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/Time.tsx b/src/components/AnForm/setters/Time.tsx
deleted file mode 100644
index 948b99f..0000000
--- a/src/components/AnForm/setters/Time.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { TimePicker, TimePickerInstance } from '@arco-design/web-vue';
-import { defineSetter } from './util';
-
-type TimeProps = TimePickerInstance['$props'];
-
-type TimeSlots = 'prefix' | 'suffixIcon' | 'extra';
-
-export default defineSetter({
- setter: TimePicker,
- setterProps: {
- allowClear: true,
- },
-});
diff --git a/src/components/AnForm/setters/TreeSelect.tsx b/src/components/AnForm/setters/TreeSelect.tsx
deleted file mode 100644
index 1c21160..0000000
--- a/src/components/AnForm/setters/TreeSelect.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { TreeSelect, TreeSelectInstance } from '@arco-design/web-vue';
-import { defineSetter, initOptions } from './util';
-
-type TreeSelectProps = TreeSelectInstance['$props'];
-
-type TreeSelectSlots =
- | 'trigger'
- | 'prefix'
- | 'label'
- | 'header'
- | 'loader'
- | 'empty'
- | 'footer'
- | 'treeSlotExtra'
- | 'treeSlotTitle'
- | 'treeSlotIcon'
- | 'treeSlotSwitcherIcon';
-
-export default defineSetter({
- setter: TreeSelect,
- onSetup: (arg: any) => initOptions(arg, 'data') as any,
- setterProps: {
- placeholder: '请选择',
- allowClear: true,
- allowSearch: true,
- },
-});
diff --git a/src/components/AnForm/setters/index.ts b/src/components/AnForm/setters/index.ts
deleted file mode 100644
index dbb460f..0000000
--- a/src/components/AnForm/setters/index.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import cascader from './Cascader';
-import date from './Date';
-import dateRange from './DateRange';
-import input from './Input';
-import number from './Number';
-import password from './Password';
-import search from './Search';
-import select from './Select';
-import submit from './Submit';
-import textarea from './Textarea';
-import time from './Time';
-import treeSelect from './TreeSelect';
-
-export default {
- input,
- number,
- search,
- textarea,
- select,
- treeSelect,
- time,
- password,
- cascader,
- date,
- submit,
- dateRange,
-};
diff --git a/src/components/AnForm/setters/util.ts b/src/components/AnForm/setters/util.ts
deleted file mode 100644
index 9df7193..0000000
--- a/src/components/AnForm/setters/util.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { Component } from 'vue';
-import { AnFormItemPropsBase, AnFormItemSlot, AnFormItemFnProps } from '../components/FormItem';
-
-export interface ItemSetter {
- /**
- * 输入组件
- */
- setter: Component;
-
- /**
- * 输入组件参数
- */
- setterProps?: P;
-
- /**
- * 空间插槽
- */
- setterSlots?: {
- /**
- * 控件插槽
- * @example
- * ```tsx
- * (props) => {
- * return {props.item.label}
- * }
- * ```
- */
- [key in S]?: AnFormItemSlot;
- };
-
- /**
- * 初始化钩子
- */
- onSetup?: (args: { model: Recordable; item: AnFormItemPropsBase; items: AnFormItemPropsBase[] }) => void;
-}
-
-export function defineSetter
(setter: ItemSetter
) {
- return setter;
-}
-
-export function initOptions({ item, model }: AnFormItemFnProps, key: string = 'options') {
- const setterProps: Recordable = item.setterProps!;
- if (Array.isArray(item.options) && item.setterProps) {
- setterProps[key] = item.options;
- return;
- }
- if (typeof item.options === 'function') {
- setterProps[key] = reactive([]);
- item.$init = async () => {
- const res = await (item as any).options({ item, model });
- if (Array.isArray(res)) {
- setterProps[key].splice(0);
- setterProps[key].push(...res);
- return;
- }
- const data = res?.data?.data;
- if (Array.isArray(data)) {
- const maped = data.map((i: any) => ({ ...i, value: i.id, label: i.name }));
- setterProps[key].splice(0);
- setterProps[key].push(...maped);
- return;
- }
- };
- item.$init();
- }
-}
diff --git a/src/components/AnForm/utils/context.ts b/src/components/AnForm/utils/context.ts
deleted file mode 100644
index e69de29..0000000
diff --git a/src/components/AnForm/utils/useFormItems.tsx b/src/components/AnForm/utils/useFormItems.tsx
deleted file mode 100644
index 9c461c3..0000000
--- a/src/components/AnForm/utils/useFormItems.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { AnFormItemProps } from '../components/FormItem';
-import { setterMap } from '../components/FormSetter';
-
-export const getFormItem = (items: AnFormItemProps[], field: string) => {
- return items.find(i => i.field === field);
-};
-
-export const initFormItems = (items: AnFormItemProps[], model: Recordable) => {
- for (const item of items) {
- const setter = setterMap[item.setter!];
- setter.onSetup?.({ item, items, model });
- }
-};
\ No newline at end of file
diff --git a/src/components/AnForm/utils/useFormModel.tsx b/src/components/AnForm/utils/useFormModel.tsx
deleted file mode 100644
index 82d2f05..0000000
--- a/src/components/AnForm/utils/useFormModel.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-export function getModel(model: Recordable) {
- const data: Recordable = {};
-
- for (const [key, value] of Object.entries(model)) {
- if (value === '') {
- continue;
- }
- if (/^\[.+\]$/.test(key)) {
- getModelArray(key, value, data);
- continue;
- }
- if (/^\{.+\}$/.test(key)) {
- getModelObject(key, value, data);
- continue;
- }
- data[key] = value;
- }
-
- return data;
-}
-
-export function setModel(model: Recordable, data: Recordable) {
- for (const [key, value] of Object.entries(model)) {
- if (/^\[.+\]$/.test(key)) {
- model[key] = setModelArray(data, key);
- continue;
- }
- if (/^\{.+\}$/.test(key)) {
- model[key] = setModelObject(data, key);
- continue;
- }
- model[key] = data[key];
- }
- console.log(model, data);
- return model;
-}
-
-function rmString(str: string) {
- const field = str.replaceAll(/\s/g, '');
- return field.match(/^(\{|\[)(.+)(\}|\])$/)?.[1] ?? '';
-}
-
-function setModelArray(data: Recordable, key: string) {
- const result: any[] = [];
- const field = rmString(key);
- for (const key of field.split(',')) {
- result.push(data[key]);
- }
- return result;
-}
-
-function setModelObject(data: Recordable, key: string) {
- const result: Recordable = {};
- const field = rmString(key);
- for (const key of field.split(',')) {
- result[key] = data[key];
- }
- return result;
-}
-
-function getModelArray(key: string, value: any, data: Recordable) {
- let field = rmString(key);
-
- if (!field) {
- data[key] = value;
- return;
- }
-
- field.split(',').forEach((key, index) => {
- data[key] = value?.[index];
- });
-
- return data;
-}
-
-function getModelObject(key: string, value: any, data: Recordable) {
- const field = rmString(key);
-
- if (!field) {
- data[key] = value;
- return;
- }
-
- for (const key of field.split(',')) {
- data[key] = value?.[key];
- }
-
- return data;
-}
diff --git a/src/components/AnForm/utils/useFormRef.tsx b/src/components/AnForm/utils/useFormRef.tsx
deleted file mode 100644
index 3aadc6c..0000000
--- a/src/components/AnForm/utils/useFormRef.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { FormInstance } from "@arco-design/web-vue";
-
-export function useFormRef() {
- /**
- * 原始表单实例
- */
- const formRef = ref(null);
-
- type Validate = FormInstance["validate"];
- type ValidateField = FormInstance["validateField"];
- type ResetFields = FormInstance["resetFields"];
- type ClearValidate = FormInstance["clearValidate"];
- type SetFields = FormInstance["setFields"];
- type ScrollToField = FormInstance["scrollToField"];
-
- const validate: Validate = async (...args) => formRef.value?.validate(...args);
- const validateField: ValidateField = async (...args) => formRef.value?.validateField(...args);
- const resetFields: ResetFields = (...args) => formRef.value?.resetFields(...args);
- const clearValidate: ClearValidate = (...args) => formRef.value?.clearValidate(...args);
- const setFields: SetFields = (...args) => formRef.value?.setFields(...args);
- const scrollToField: ScrollToField = (...args) => formRef.value?.scrollToField(...args);
-
- return {
- formRef,
- validate,
- validateField,
- resetFields,
- clearValidate,
- setFields,
- scrollToField,
- };
-}
-
-export type FormRef = ReturnType;
diff --git a/src/components/AnBreadcrumb/bread-page.vue b/src/components/AnPage.vue
similarity index 94%
rename from src/components/AnBreadcrumb/bread-page.vue
rename to src/components/AnPage.vue
index 153ccdf..45bd6fb 100644
--- a/src/components/AnBreadcrumb/bread-page.vue
+++ b/src/components/AnPage.vue
@@ -19,7 +19,7 @@
diff --git a/src/pages/setting/common/index.vue b/src/pages/setting/common/index.vue
index 977d6b4..1d31128 100644
--- a/src/pages/setting/common/index.vue
+++ b/src/pages/setting/common/index.vue
@@ -1,13 +1,13 @@
-
+
常规设置
首次为你的帐户添加密码时,你需要前往密码重置页面,以便我们验证你的身份。
-
+
-
+
@@ -43,7 +43,7 @@
保存修改
-
+