{"id":18319492,"url":"https://github.com/wl-ui/wl","last_synced_at":"2025-10-30T07:08:48.573Z","repository":{"id":38223605,"uuid":"257167096","full_name":"wl-ui/wl","owner":"wl-ui","description":"探索项目架构方案之路","archived":false,"fork":false,"pushed_at":"2023-01-06T15:39:08.000Z","size":1933,"stargazers_count":22,"open_issues_count":46,"forks_count":7,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-02T09:01:33.449Z","etag":null,"topics":["wl-core","wl-http","wl-ui","wl-vue"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wl-ui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-20T04:02:30.000Z","updated_at":"2023-07-17T06:41:05.000Z","dependencies_parsed_at":"2023-02-06T06:00:39.661Z","dependency_job_id":null,"html_url":"https://github.com/wl-ui/wl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wl-ui%2Fwl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wl-ui%2Fwl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wl-ui%2Fwl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wl-ui%2Fwl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wl-ui","download_url":"https://codeload.github.com/wl-ui/wl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411236,"owners_count":20934650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["wl-core","wl-http","wl-ui","wl-vue"],"created_at":"2024-11-05T18:13:27.883Z","updated_at":"2025-10-30T07:08:43.539Z","avatar_url":"https://github.com/wl-ui.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wl\n项目架构方案之路\n\n## List\n1. wl-core 框架无关核心层级工具类\n\n2. wl-http 基于axios封装的请求类\n\n3. wl-baseui 基础ui组件\n\n4. wl-vue vue通用基础封装 \n\n\u003e 下列说明中 export 内的方法名，均可 import { xx } from 'wl-core' 导入使用\n\n## wl-core\n\n无框架依赖的核心层及工具层封装\n\n### array\n提供有关数组的操作方法 Function\n```js\nexport {\n  valInDeep, // 从树形数据中递归筛选目标值\n  flattenDeep, // 将树形数据向下递归为一维数组\n  flattenDeepParents, // 将树形数据向上将此支线递归为一维数组\n  regDeepParents, // 根据条件递归祖先元素\n  arrayToTree, // 将数组转化成树结构\n  patchTreeChain, // 如果数据里缺少树枝节点，则根据parents和自增长id补全整条树链，输出数据调用上部arrToTree函数组装成完整的树\n  locationAfterDelete, // 数组删除后重新定位\n  splicParentsUntil, // 从坐标值拼接指定字段到祖先元素\n  intersectionBy, // 根据数组2内的元素，通过match字段匹配数组1内的完整内容组成的数据\n  deepClone, // 深拷贝\n  getMax, // 筛选出数组中最大值\n  getMin, // 筛选出数组中最小值\n  autoPositionAfterDelete, // 重写的一维数组删除数据后自动定位\n};\n```\n\n### event\n提供对浏览器事件的封装 Function\n```js\nexport {\n  throttle, // 节流函数\n  debounce // 防抖函数\n}\n```\n\n### Storage\n提供对Storage操作的类，包括local和session两种 Class\n```js\nexport {\n  Storage\n}\n```\n均为静态方法，可直接调用。它包括有：\n```js\nStorage.set('key','value','type[local|session]') // 将键值存入本地存储\nStorage.get('key','type[local|session]') // 根据key取本地存储数据\nStorage.remove('key','type[local|session]') // 根据key删除本地存储数据\nStorage.had('key','type[local|session]') // 根据key查询本地存储中是否存在key的实例\nStorage.clear('type[local|session]') // 清空本地存储\nStorage.count('type[local|session]') // 获取存储库里存储实例个数\n```\n\n### Time\n提供对时间操作的类 Class\n```js\nexport {\n  Time\n}\n```\n主要用于对时间进行两次及以上操作的情况！对于时间格式化，在wl-vue中提供了time过滤器\n1. 使用需要先实例化，全部方法如下：\n```js\nconst timer = new Time('2020-02-14', 'YYYY/MM/DD');\n\ntimer.dayjs(date) // 将时间格式转化为dayjs格式（实例化时已经自动调用了此方法）\ntimer.format(format) // 格式化时间\ntimer.add(num, unit) // 时间加上数量，要加的时间数量，数量的时间单位\ntimer.subtract(num, unit) // 时间减去数量，要加的时间数量，数量的时间单位\ntimer.isBefore(date, unit) // 时间是否在date之前，要比较的时间，时间的单位\ntimer.diff(date, unit) // 计算时差，要减的日期，时间计算时间的单位\n```\n2. 静态方法可直接调用\n```js\nTime.quickFormat(new Date(), 'YYYY/MM/DD')\nTime.init(new Date())\n```\n\n### Type\n提供判断数据类型的类 Class\n```js\nexport {\n  DataType\n}\n```\n均为静态方法，可直接调用。它包括有：\n```js\nDataType.isObject(data) // 是否对象\nDataType.isEmptyObject(data) // 是否空对象\nDataType.isArray(data) // 是否数组\nDataType.isEmptyArray(data) // 是否空数组\n```\n\n### validate\n数据验证\n```js\nexport {\n  vaPhone, // el手机格式校验\n  regPhone, // 正则手机格式校验\n  isNum, // 验证数字\n  isInteger, // 验证整数\n  validate, // 整体表单验证\n}\n\n```\n### WlNumber\n提供精确数字计算的类 Class\n```js\nexport {\n  WlNumber\n}\n```\n\n```js\nconst beginNum = new WlNumber(1);\n// 以下返回big数据，可以使用toString()或to.Fixed()转化\nbeginNum.plus(2) // 加\nbeginNum.minus(2) // 减\nbeginNum.times(2) // 乘\nbeginNum.div(2) // 除以\nbeginNum.mod(2) // 取余\nbeginNum.abs() // 取绝对值\n// 以下返回Boolean值\nbeginNum.gt(2) // 大于\nbeginNum.gte(2) // 大于等于\nbeginNum.lt(2) // 小于\nbeginNum.lte(2) // 小于等于\n```\n静态方法\n```js\nWlNumber.toNumber(val) // 返回转化后的bumber型值，不可转化的返回0\n```\n\n## wl-http\n\n通信层封装\n\n### 1. 实例化http：__http__.js\n\n```js\nimport Http from \"wl-http\"\n\nconst options = {\n  axios: null, // 是否使用外部axios实例，无特殊情况禁止使用\n  options: {\n    retry: 2, //Number 请求失败自动重连次数 默认2\n    retryDelay: 1000, // 请求失败自动重连时间间隔 默认1000ms\n    withCredentials: true, // Boolean 开启请求跨域 默认true\n    headers: {\n      \"Content-Type\": \"application/json;charset=UTF-8\"\n    }, // Object 请求头配置 默认\"Content-Type\": \"application/json;charset=UTF-8\"\n    timeout: 5000, // Number 请求超时时间 默认5000\n    baseURL: '' // String 请求地址前缀 默认''\n    expand: {} // 其他需要扩展的配置项 other axios 支持的config字段\n  }, // 以上字段均有默认值，正常情况下 此options 无需提供\n  requestInterceptorSuccessCb:()=\u003e{}, // 非必填 请求拦截器成功回调，必须返回一个config对象\n  responseInterceptorSuccessCb:()=\u003e{}, // 非必填 响应拦截器成功回调，必须返回一个response对象\n  responseInterceptorErrorCb:()=\u003e{}, // 非必填 响应拦截器失败回调，必须返回一个response对象\n}, // 实例化http可选配置项 均为非必填项\n\nconst http = new Http(options);\n\nexport default http;\n```\n\n### 2. 在具体的api文件中使用：user.js\n```js\nimport http from \"__http__.js\"\n\nconst getMenuApi = (params) =\u003e http.get({\n  url:'',\n  params\n})\n\nconst addUserApi = (data) =\u003e http.post({\n  url:'',\n  data\n})\n\nexport {\n  getMenuApi,\n  addUserApi\n}\n```\n\n### 3. 在vue文件中最终调用\n```js\nimport {addUserApi} from \"@/api/user.js\"\n\nmethods: {\n  addUser(){\n    const _data = {\n      name: 'weilan',\n      des: '前端架构师'\n    }\n    addUserApi(_data).then( ({data})=\u003e{\n      ...\n    })\n  }\n}\n```\n\n### 4. Http类提供 get，post，all，del，put，patch 共6中方法\n\n## wl-baseui\n\n基础ui库，不包含复杂组件，完整组件库见wlui\n\n```js\nimport WlBaseUi from \"wl-base-ui\"\n\nVue.use(WlBaseUi)\n\n// 下为详细列表\n{\n  WlAdd, // 防抖按钮\n  WlContainer, // 页面视图盒子\n  WlContextMenu, // 右键扩展组件\n  WlFadeIn, // 右侧滑入组件\n  WlInput, // 带校验的输入框组件\n  WlScroll, // 滚动条美化组件\n  WlTable, // 表格组件\n  WlTableDynamic, // 动态表格组件\n}\n```\n\n## wl-vue\n\nvue基础层封装\n\n### 1. 使用render函数创建vue实例：render.js\n\n```js\nimport { render } from \"wl-vue\"\nimport App from \"./App.vue\";\nimport router from \"./router\";\nimport store from \"./store\";\n\nconst options = {\n  root: App, // 必须 当前应用的根组件 一般是app.vue\n  router: router, // 必须  router实例\n  store: store, // 必须  store实例\n  options: { // options 实例化vue配置项 下为详细注解\n    fastclick: false, // 默认false 是否启用移动端快速点击插件\n    cookie: false, // 默认false 是否启用vue-cookie操作插件\n    lazyOptions: {}, // 默认null 启用图片VueLazyLoad懒加载插件时的配置项, 不传表示不启用\n    filters: [], // 默认[] 过滤器数组 格式为 {name:\"\", rule: ()=\u003e{}} 内置有date，dateTime时间格式化过滤器\n    directives: [], // 默认[] 指令数组 格式为 {name:\"\", rule: ()=\u003e{}} 内置有v-auth鉴权指令\n    plugins: [], // 默认[] 插件数组 [wlui, el-input] 可以直接Vue.use()的插件数组\n    fncBeforeVue: ()=\u003e{}, // 实例化vue前可执行的回调函数 fncBeforeVue(vue){... 你的逻辑}\n    auth: true, // 默认true 是否需要鉴权系统，如果不需要，后续参数无需再传\n  }, \n  routeOptions:{ // 路由守卫配置项 用于前端鉴权及异步路由 下为详细注解\n    tokenKey: 'token', // 存储在local中的token的key\n    dispatchSetToken: 'app/setToken', // store设置token的actions命名空间 默认'app/setToken'\n    dispatchSetMenu: 'menu/setMenu', // store设置菜单的actions命名空间 默认'menu/setMenu'\n    dispatchSetMenuList: 'menu/setMenuList', // store设置一维菜单的actions命名空间\n    dispatchSetPermissions: 'menu/setPermissions', // store设置按钮权限码的actions命名空间 默认'menu/setPermissions'\n    pathLogin: '/login', // 登录页的 router path 默认'/login'\n    pathLogged: '/index', // 已登录后 再进登录页时自动重定向的 router path 默认'/index'\n    apiFn: ()=\u003e{}, // **必须** 获取菜单数据的api函数，返回值为一个promise\n    vaJwtExpiredFn: ()=\u003e{}, // 自定义校验jwt是否过期的函数 默认为比较jwt携带过期时间与当前时间比较，单位秒，传入表示自定义过期规则\n  },\n  menuOptions:{ // 菜单数据解析为路由数据配置项 下为详细注解\n    url: 'url', // 前端地址栏路由 将映射真实文件路径 映射规则：import(`@/views${url}/index.vue`)\n    name: 'routerName', // 命名路由 \n    meta: 'meta', // 路由元数据\n    children: 'children', // 子菜单字段\n    permissions: 'permissions', // 按钮权限字段\n    path404: 'error/404' // 404路径,\n    mapPathFn: (item) =\u003e {} // 路由映射文件路径方法 必填\n  },\n  nextRoutes:[] // 需要登录后插入的、非后台返回的路由列表 默认[] \n}\nconst mount = \"#app\"; // 非必选 vue挂载dom 默认为#app\n\n// 实例化vue\nconst vueRender = () =\u003e render(options, mount);\n\nexport default vueRender;\n```\n\n### 2. 在main.js内实例化vue\n下面是 最少 \u0026 必须 的配置项：\n```js\nimport { render } from \"wl-vue\"\nimport App from \"./App.vue\";\nimport store from \"./store\";\nimport router from \"./router\";\nimport nextRoutes from \"./router/next-router\"\nimport routeMap from \"./router/map-router\"\nimport { getMenuApi } from \"./api/menu\"\n\n// 声明鉴权需要的参数\nconst routeOptions = {\n  apiFn: getMenuApi\n}\n\n// 声明菜单解析为路由所需参数\nconst menuOptions = {\n  mapPathFn: (item) =\u003e routeMap(item.url)\n}\n\n// 导出手动实例化vue函数\nconst vueRender = () =\u003e render({ root: App, router, store, routeOptions, nextRoutes, menuOptions });\n\nexport default vueRender;\n```\n\n### 3. 注意事项\n\n1. 注意：菜单数据映射为路由数据默认你有一个layout路由且默认重定向至`/index`如下, 其他菜单路由均挂载在layout的children内\n```js\n  let userRouter = {\n    path: \"/layout\",\n    name: \"layout\",\n    component: () =\u003e import('@/views/layout/index.vue'),\n    redirect: '/index',\n    children: []\n  };\n```\n2. 注意：路由的映射规则如下：\n```js\ncomponent: () =\u003e import(`@/views${url}/index.vue`)\n```\n3. 注意：因为在封装里路由映射文件会找不到，因此需要在每个项目里传入一个映射方法\nsrc/router/map-router.js\n```js\nmodule.exports = path =\u003e () =\u003e import(`@/views${path}/index.vue`);\n```\n\n4. 注意：路由守卫检查store中是否已经存在用户菜单指定为：\n```js\nstore.getters.menu\n```\n\n### 4. 其他方法\n```js\nimport { VaJwt } from \"wl-vue\"\n\n// VaJwt是一个验证和解析未加密jwt的类，提供了许多静态方法\n// console.log(VaJwt) 打印查看\n// 静态方法无需实例化可直接使用，例：\nconst payload = VaJwt.payloadAtob(jwt);\n// 解析jwt中有效载荷内的数据\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwl-ui%2Fwl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwl-ui%2Fwl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwl-ui%2Fwl/lists"}