Skip to content

Commit

Permalink
chore(完善配置、基础组件): 完善配置、基础组件
Browse files Browse the repository at this point in the history
完善配置、基础组件
  • Loading branch information
jianfengtheboy committed Aug 13, 2024
1 parent ad4d015 commit deeee8e
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 42 deletions.
4 changes: 2 additions & 2 deletions .env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ VITE_OUT_DIR = 'dev_ui'
VITE_BASE_API = '/dev-flow/prod-api'

# 开发环境接口地址
VITE_PROXY_URL = 'https://cloud.whtyinfo.com/dev-flow/prod-api'
VITE_PROXY_URL = 'https://cloud.xxxx.com/dev-api'

# 文件服务NG配置
VITE_APP_FILE_API = 'https://cloud.whtyinfo.com/dev-flow'
VITE_APP_FILE_API = 'https://cloud.xxxx.com/file/dev-api'
6 changes: 2 additions & 4 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ VITE_OUT_DIR = 'development_ui'
VITE_BASE_API = '/dev-api'

# 开发环境接口地址
VITE_PROXY_URL = 'https://cloud.whtyinfo.com/dev-flow/prod-api'
# 测试环境接口地址
# VITE_PROXY_URL = 'https://cloud.whtyinfo.com/test-flow/prod-api'
VITE_PROXY_URL = 'https://cloud.xxxx.com/dev-api'

# 文件服务NG配置
VITE_APP_FILE_API = 'https://cloud.whtyinfo.com/dev-flow'
VITE_APP_FILE_API = 'https://cloud.xxxx.com/file/dev-api'
4 changes: 2 additions & 2 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ VITE_OUT_DIR = 'production_ui'
VITE_BASE_API = '/prod-api'

# 开发环境接口地址
VITE_PROXY_URL = 'http://securelink.whtyiot.com/prod-api'
VITE_PROXY_URL = 'https://cloud.xxxx.com/prod-api'

# 文件服务NG配置
VITE_APP_FILE_API = 'http://securelink.whtyiot.com'
VITE_APP_FILE_API = 'https://cloud.xxxx.com/file/prod-api'
4 changes: 2 additions & 2 deletions .env.staging
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ VITE_OUT_DIR = 'staging_ui'
VITE_BASE_API = '/stg-api'

# 开发环境接口地址
VITE_PROXY_URL = 'http://securelink.whtyiot.com/stg-api'
VITE_PROXY_URL = 'https://cloud.xxxx.com/stg-api'

# 文件服务NG配置
VITE_APP_FILE_API = 'http://securelink.whtyiot.com'
VITE_APP_FILE_API = 'https://cloud.xxxx.com/file/stg-api'
6 changes: 3 additions & 3 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ VITE_ENV = 'test'
VITE_OUT_DIR = 'test_ui'

# 开发环境
VITE_BASE_API = '/test-flow/prod-api'
VITE_BASE_API = '/test-api'

# 生产环境接口地址
VITE_PROXY_URL = 'https://cloud.whtyinfo.com/test-flow/prod-api'
VITE_PROXY_URL = 'https://cloud.xxxx.com/test-api'

# 文件服务NG配置
VITE_APP_FILE_API = 'https://cloud.whtyinfo.com/test-flow'
VITE_APP_FILE_API = 'https://cloud.xxxx.com/file/test-api'
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "arco-app-ui",
"private": true,
"version": "1.0.0",
"description": "基于 Vue3、Vite、TypeScript、Arco Design Vue、Pinia、VueUse 等的中后台模版",
"scripts": {
"dev": "vite",
"build": "vite build --mode development",
Expand Down
34 changes: 20 additions & 14 deletions src/components/BaseBreadCrumb/index.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
<script lang="ts" setup>
import type { RouteLocationMatched } from 'vue-router'
import { findTree } from 'xe-utils'
import { useRouteStore } from '@/store'
const route = useRoute()
const router = useRouter()
const { routes } = useRouteStore()
let home: RouteLocationMatched | null = null
const getHome = () => {
if (!home) {
const cloneRoutes = JSON.parse(JSON.stringify(routes)) as RouteLocationMatched[]
const obj = findTree(cloneRoutes, i => i.path === '/home')
home = obj.item
}
}
const breadcrumbList = ref<RouteLocationMatched[]>([])
function getBreadcrumbList() {
// 只显示有title标题的
const matched = route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!isHome(first)) {
matched.unshift({ path: '/', meta: { title: '首页' } } as RouteLocationMatched)
getHome()
const cloneRoutes = JSON.parse(JSON.stringify(routes)) as RouteLocationMatched[]
const obj = findTree(cloneRoutes, i => i.path === route.path)
// 获取当前节点的所有上级节点集合,包含当前节点
const arr = obj ? obj.nodes.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) : []
if (home) {
breadcrumbList.value = [home, ...arr]
}
breadcrumbList.value = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}
getBreadcrumbList()
Expand All @@ -21,15 +34,8 @@ watchEffect(() => {
getBreadcrumbList()
})
// 判断是否为首页
function isHome(route: RouteLocationMatched) {
const name = (route?.name as string) || ''
if (!name) return false
return name.trim() === 'Home'
}
// 路由跳转
function handleLink(item: RouteLocationMatched) {
const handleLink = (item: RouteLocationMatched) => {
const { redirect, path } = item
if (redirect) {
return router.push(redirect as string)
Expand Down
74 changes: 67 additions & 7 deletions src/components/BaseForm/src/BaseForm.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts" setup>
import type { Options, Columns, ColumnsItemHide, ColumnsItem } from './type'
import type { Columns, ColumnsItem, ColumnsItemDisabled, ColumnsItemHide, Options } from './type'
import type * as A from '@arco-design/web-vue'
interface IProps {
Expand Down Expand Up @@ -32,6 +32,14 @@ const isHide = (hide?: ColumnsItemHide<boolean | object>) => {
}
}
const isDisabled = (disabled?: ColumnsItemDisabled<boolean | object>) => {
if (disabled === undefined) return false
if (typeof disabled === 'boolean') return disabled
if (typeof disabled === 'function') {
return disabled(props.modelValue)
}
}
const dicData: Record<string, any> = reactive({})
props.columns.forEach(item => {
if (item.request && typeof item.request === 'function' && item?.init) {
Expand Down Expand Up @@ -88,14 +96,20 @@ watch(cloneForm as any, (newVal, oldVal) => {
v-bind="item.col || item.span ? item.col : options.col"
v-show="index <= (options.fold?.index || 0) || (index >= (options.fold?.index || 0) && !collapsed)"
>
<a-form-item v-bind="item.item" :label="item.label" :field="item.field" :rules="item.rules">
<slot :name="item.field">
<a-form-item
v-bind="item.item"
:label="item.label"
:field="item.field"
:rules="item.rules"
:disabled="isDisabled(item.disabled)"
>
<slot :name="item.field" v-bind="{ disabled: isDisabled(item.disabled) }">
<!-- 输入框 -->
<template v-if="item.type === 'input'">
<a-input
:allow-clear="true"
:placeholder="item.placeholder || `请输入${item.label}`"
:max-length="20"
:max-length="item.maxLength || 20"
v-bind="(item.props as A.InputInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
Expand All @@ -115,7 +129,7 @@ watch(cloneForm as any, (newVal, oldVal) => {
<a-textarea
:allow-clear="true"
:placeholder="item.placeholder || `请输入${item.label}`"
:max-length="200"
:max-length="item.maxLength || 200"
:show-word-limit="true"
v-bind="(item.props as A.TextareaInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
Expand Down Expand Up @@ -183,6 +197,46 @@ watch(cloneForm as any, (newVal, oldVal) => {
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 年选择器 -->
<template v-if="item.type === 'year-picker'">
<a-year-picker
v-bind="(item.props as A.YearPickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 月选择器 -->
<template v-if="item.type === 'month-picker'">
<a-month-picker
v-bind="(item.props as A.MonthPickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>

<template v-if="item.type === 'quarter-picker'">
<a-quarter-picker
v-bind="(item.props as A.QuarterPickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 周选择器 -->
<template v-if="item.type === 'week-picker'">
<a-week-picker
v-bind="(item.props as A.WeekPickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>

<template v-if="item.type === 'range-picker'">
<a-range-picker
v-bind="(item.props as A.RangePickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 时间选择器 -->
<template v-if="item.type === 'time-picker'">
<a-time-picker
Expand All @@ -193,6 +247,14 @@ watch(cloneForm as any, (newVal, oldVal) => {
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 颜色选择器 -->
<template v-if="item.type === 'color-picker'">
<a-color-picker
v-bind="(item.props as A.ColorPickerInstance['$props'])"
:model-value="modelValue[item.field as keyof typeof modelValue]"
@update:model-value="valueChange($event, item.field)"
/>
</template>
<!-- 评分 -->
<template v-if="item.type === 'rate'">
<a-rate
Expand Down Expand Up @@ -246,5 +308,3 @@ watch(cloneForm as any, (newVal, oldVal) => {
</a-row>
</a-form>
</template>

<style lang="less" scoped></style>
23 changes: 20 additions & 3 deletions src/components/BaseForm/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export type FormType =
| 'checkbox-group'
| 'textarea'
| 'date-picker'
| 'year-picker'
| 'quarter-picker'
| 'week-picker'
| 'range-picker'
| 'month-picker'
| 'time-picker'
| 'color-picker'
| 'input-number'
| 'rate'
| 'switch'
Expand All @@ -20,7 +26,13 @@ export type ColumnsItemPropsKey =
| keyof A.SelectInstance['$props']
| keyof A.TextareaInstance['$props']
| keyof A.DatePickerInstance['$props']
| keyof A.YearPickerInstance['$props']
| keyof A.MonthPickerInstance['$props']
| keyof A.QuarterPickerInstance['$props']
| keyof A.WeekPickerInstance['$props']
| keyof A.RangePickerInstance['$props']
| keyof A.TimePickerInstance['$props']
| keyof A.ColorPickerInstance['$props']
| keyof A.RadioGroupInstance['$props']
| keyof A.CheckboxGroupInstance['$props']
| keyof A.InputNumberInstance['$props']
Expand All @@ -30,7 +42,8 @@ export type ColumnsItemPropsKey =
| keyof A.CascaderInstance['$props']
| keyof A.TreeSelectInstance['$props']

export type ColumnsItemHide<F = any> = boolean | ((form: F) => boolean)
export type ColumnsItemHide<F> = boolean | ((form: F) => boolean)
export type ColumnsItemDisabled<F> = boolean | ((form: F) => boolean)
export type ColumnsItemRequest<F = any> = (form: F) => Promise<any>
export type ColumnsItemFormat<T = any> = (
res: T
Expand All @@ -50,11 +63,13 @@ export type ColumnsItemOptionsOrData =

export interface ColumnsItem<F = any> {
// 类型
type: FormType
type?: FormType
// 标签
label: A.FormItemInstance['label']
label?: A.FormItemInstance['label']
// placeholder
placeholder?: string
// 长度限制
maxLength?: number
// 字段(必须唯一)
field: A.FormItemInstance['field']
// 栅格占位格数
Expand Down Expand Up @@ -89,6 +104,8 @@ export interface ColumnsItem<F = any> {
data?: A.TreeSelectInstance['$props']['data']
// 是否隐藏
hide?: ColumnsItemHide<F>
// 是否禁用
disabled?: ColumnsItemDisabled<F>
// 接口请求api
request?: ColumnsItemRequest<F>
// 结果集格式化
Expand Down
5 changes: 2 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import _ from 'lodash'
// 自定义指令
import directives from './directives'
// 引入 Arco Design 组件库以及自定义主题
import ArcoVue from '@arco-design/web-vue'
import ArcoVue, { Card, Modal } from '@arco-design/web-vue'
import ArcoVueIcon from '@arco-design/web-vue/es/icon'
import { Card, Modal } from '@arco-design/web-vue'
Card.props.bordered = false
// 支持SVG
import 'virtual:svg-icons-register'
// 引入全局样式
Expand All @@ -23,6 +21,7 @@ window.$_ = _

const app = createApp(App)
Modal._context = app._context
Card.props.bordered = false

app.use(router)
app.use(store)
Expand Down
16 changes: 16 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,48 @@
{
"compilerOptions": {
// 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"target": "ES2020",
"module": "ES2020",
"useDefineForClassFields": true,
// 指定要包含在编译中的库文件
"lib": ["ES2020", "DOM", "DOM.Iterable"],
// 是否跳过声明文件的类型检查,这可以在编译期间以牺牲类型系统准确性为代价来节省时间,默认:false
"skipLibCheck": true,
// 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"moduleResolution": "Node",
"allowImportingTsExtensions": true,
// 是否解析 JSON 模块
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
// 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
"jsx": "preserve",
// 当使用经典的JSX运行时编译JSX元素时,更改.js文件中调用的函数,默认:React.createElement
"jsxFactory": "h",
// 指定 JSX 片段工厂函数在指定了 jsxFactory 编译器选项的情况下针对 react JSX 发出时使用 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"jsxFragmentFactory": "Fragment",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// 是否生成相应的Map映射的文件,默认:false
"sourceMap": true,
// 是否通过为所有导入模块创建命名空间对象,允许CommonJS和ES模块之间的互操作性,开启改选项时,也自动开启allowSyntheticDefaultImports选项,默认:false
"esModuleInterop": true,
// 允许编译 javascript 文件
"allowJs": true,
// 报告 javascript 文件中的错误
"checkJs": true,
"noImplicitAny": false,
"strictNullChecks": true,
// 用于解析非相对模块名称的基目录
"baseUrl": ".",
// 模块名到基于 baseUrl 的路径映射的列表
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/types/*.d.ts"],
"exclude": ["node_modules", "dist", "**/*.js"],
"references": [{ "path": "./tsconfig.node.json" }]
}
4 changes: 2 additions & 2 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path from 'node:path'
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import path from 'path'
import { fileURLToPath, URL } from 'url'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// vue 自动引入
import AutoImport from 'unplugin-auto-import/vite'
Expand Down

0 comments on commit deeee8e

Please sign in to comment.