{"id":19692736,"url":"https://github.com/shonesinglone/germinal","last_synced_at":"2025-08-12T18:12:51.961Z","repository":{"id":40464375,"uuid":"417027427","full_name":"ShoneSingLone/germinal","owner":"ShoneSingLone","description":"vue3 antdv admin","archived":false,"fork":false,"pushed_at":"2022-10-26T10:11:06.000Z","size":21180,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-27T11:53:51.996Z","etag":null,"topics":["admin-dashboard","antd-vue","jsx-syntax","vue3","yapi","yapi-client","yapi-client-vue3"],"latest_commit_sha":null,"homepage":"https://shonesinglone.github.io/germinal/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ShoneSingLone.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":"2021-10-14T07:14:58.000Z","updated_at":"2022-07-03T03:50:09.000Z","dependencies_parsed_at":"2023-01-19T21:17:28.597Z","dependency_job_id":null,"html_url":"https://github.com/ShoneSingLone/germinal","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ShoneSingLone/germinal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoneSingLone%2Fgerminal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoneSingLone%2Fgerminal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoneSingLone%2Fgerminal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoneSingLone%2Fgerminal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ShoneSingLone","download_url":"https://codeload.github.com/ShoneSingLone/germinal/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ShoneSingLone%2Fgerminal/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270109984,"owners_count":24528946,"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","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["admin-dashboard","antd-vue","jsx-syntax","vue3","yapi","yapi-client","yapi-client-vue3"],"created_at":"2024-11-11T19:14:15.923Z","updated_at":"2025-08-12T18:12:51.928Z","avatar_url":"https://github.com/ShoneSingLone.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Info 不要使用pnpm\r\n- 2022年8月20日\r\n\t- 建议用npm，因为使用了`\"file:./local_moduels\"`,pnpm似乎还没有支持......\r\n\t\r\n\u003e **_非_** 最佳实践，尽量多样： Just for fun :)\r\n\r\n- [TODO](./README/README.todo.md)\r\n- [BOUNDLESS](./README/README.boundless.md)\r\n- [I18N](./README/README.i18n.md)\r\n- [ISSUE](./README/README.issue.md)\r\n\r\n- `npm i -g mirror-config-china --registry=https://registry.npm.taobao.org`\r\n  ~~[Germinal](https://shonesinglone.github.io/germinal/)[![Build\r\nStatus](https://app.travis-ci.com/ShoneSingLone/germinal.svg?branch=master)](https://app.travis-ci.com/ShoneSingLone/germinal)~~\r\n\r\n- [Actions: deploy app](https://dev.to/pierresaid/deploy-node-projects-to-github-pages-with-github-actions-4jco)\r\n- [TODO](README/README.todo.md)\r\n\r\n```js\r\n/* README: */\r\n/* NOTICE: */\r\n/* TODO: */\r\n```\r\n\r\n初次运行：\r\n\r\n```bash\r\n# install package and generate language\r\nnpm run bs npm start\r\n```\r\n\r\n## package.json\r\n\r\n- `file:./local_moduels/**`\r\n  - 有朝一日稳定了，可以独立发布出去（UI）。\r\n  - 放一些不与业务代码耦合的代码（单纯 API 发请求，Mock 数据）\r\n\r\n## 样式\r\n\r\n```less\r\n/* App.less TODO:更新后不会刷新页面  */\r\n/* 变量在configs.jsx中，加载为全应用的css原生变量*/\r\n/* less 样式可以单独使用webpack、rollup等工具打包（build目录下），生成不同主题 */\r\nhtml,\r\nbody,\r\n#app {\r\n\theight: 100%;\r\n\toverflow: hidden;\r\n}\r\n\r\n@import url(\"./layout/User.less\");\r\n...;\r\n```\r\n\r\n## boundless demo 页面\r\n\r\n[https://shonesinglone.github.io/germinal/boundless/index.html?APP_ENTRY_NAME=demo](https://shonesinglone.github.io/germinal/boundless/index.html?APP_ENTRY_NAME=demo)\r\n[http://localhost:3000/boundless/index.html?APP_ENTRY_NAME=demo](http://localhost:3000/boundless/index.html?APP_ENTRY_NAME=demo)\r\n\r\n## 开发测试 demo 页面\r\n\r\n[http://localhost:3000/#/dev-demo](http://localhost:3000/#/dev-demo)\r\n[http://localhost:3000/yapi.html#/dev](http://localhost:3000/yapi.html#/dev)\r\n\r\n\r\n## 编写客户端的 Programs Language\r\n\r\n- boundless `js`\r\n- app `js-ts`\r\n- yapi `ts`\r\n\r\n## Reference\r\n\r\n- []()\r\n\r\n  - npm update --depth=9999 vue-loader\r\n\r\n- [Vue3](https://v3.cn.vuejs.org/api/)\r\n  - [sfc-script-setup](https://v3.cn.vuejs.org/api/sfc-script-setup.html)\r\n  - [composition-api-lifecycle-hooks](https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html)\r\n  - [Vue-Router](https://next.router.vuejs.org/zh/introduction.html)\r\n- [ant-design-vue](https://next.antdv.com/components/overview-cn/)\r\n  - [Ant Design Vue3](https://mp.weixin.qq.com/s?__biz=MzU4NTgyMTM0MQ==\u0026mid=2247484357\u0026idx=1\u0026sn=478c97c3ddd1703f4851863a8f4b2863\u0026chksm=fd85fe37caf27721818cfcef9521116cb54ca4c023951445ed71a1d87786c383f2888d64035f\u0026mpshare=1\u0026scene=23\u0026srcid=10203hvGd6nN3z8bEYuCS1LI\u0026sharer_sharetime=1634692039568\u0026sharer_shareid=966f440169937ddeabee7cec964be6bc#rd)\r\n  - [ant-design-vue-pro](https://github.com/vueComponent/ant-design-vue-pro)\r\n    - [pro-layout](https://github.com/vueComponent/pro-layout)\r\n- [URL-friendly characters](https://stackoverflow.com/questions/695438/what-are-the-safe-characters-for-making-urls)\r\n- [popover](https://www.jqueryscript.net/blog/best-popover.htm)\r\n- [popper](https://popper.js.org/)\r\n- [regexper 正则可视化](https://regexper.com/#%2F%5B%7D%7B*%60~!%40%5C%23%5C%24%5C%26%5C%28%5C%29%5C-%5C_%5C%3D%5C%2B%5C%5B%5C%5D%5C%7C%3B%3A'%5C%22%2C%5C.%5C%2F%5C%3F%25%5C%5E%5D%2F)\r\n\r\n\u003e 关于命令式代码，私以为诸如 `tips`、`popover`、`confirm`、`dialog` 这类的场景都是合适的，一味无脑使用声明，颇有一种手里只有一把锤子的意思。\r\n\r\n## jsx slot 的写法\r\n\r\n\u003e [vue-jsx-next](https://github.com/vuejs/jsx-next)\r\n\r\n```js\r\nconst genMenu = () =\u003e {\r\n\tconst MenuItemRender = menuInfo =\u003e {\r\n\t\tif (_.isArrayFill(menuInfo.children)) {\r\n\t\t\t/* 第一种 */\r\n\t\t\treturn (\r\n\t\t\t\t\u003cSubMenu\r\n\t\t\t\t\tv-slots={{\r\n\t\t\t\t\t\ticon: () =\u003e \u003cAppleOutlined /\u003e,\r\n\t\t\t\t\t\ttitle: () =\u003e menuInfo.label,\r\n\t\t\t\t\t\tdefault: () =\u003e _.map(menuInfo.children, MenuItemRender)\r\n\t\t\t\t\t}}\r\n\t\t\t\t/\u003e\r\n\t\t\t);\r\n\t\t} else {\r\n\t\t\t/* 第二种 */\r\n\t\t\treturn (\r\n\t\t\t\t\u003cMenuItem key={menuInfo.id}\u003e\r\n\t\t\t\t\t{{\r\n\t\t\t\t\t\ticon: () =\u003e \u003cUserOutlined /\u003e,\r\n\t\t\t\t\t\tdefault: () =\u003e \u003cspan\u003e{menuInfo.label}\u003c/span\u003e\r\n\t\t\t\t\t}}\r\n\t\t\t\t\u003c/MenuItem\u003e\r\n\t\t\t);\r\n\t\t}\r\n\t};\r\n\treturn _.map(props.tree, MenuItemRender);\r\n};\r\n```\r\n\r\n## 常用函数\r\n\r\n### $t 多语言转换\r\n\r\n- 懒加载，最好是当前模块用到的才加载。\r\n- 如何做到异步？使用 DelayCall function？\r\n\r\n单一数据源`build/make/language.js`\r\n\r\n```json\r\n{\r\n\t\"make:language\": \"node ./build/make.js language\"\r\n}\r\n```\r\n\r\n```js\r\nreturn { label: \"显示的对应语言\", prop: \"key\" };\r\n```\r\n\r\n```js\r\n/* main.js 第一行 window._ 工具 常用工具函数 */\r\nimport \"@ventose/ui/loadCommonUtil.js\";\r\n```\r\n\r\n## appPlugins\r\n\r\n针对 popover 单例的使用，Vue3 以应用为单位配置属性的方式相较于 Vue2 的全局配置，带来了灵活，就需要但对每个应用单独配置，\r\n\r\n```js\r\n/* Vue3 组件方式加载 popover content */\r\nif (this.options.component) {\r\n\tthis.$popoverMountDOM = $(\r\n\t\t`\u003cdiv id=\"${this.id}\" class=\"x-popover-content\"/\u003e`\r\n\t).prependTo($(\"body\"));\r\n\tconst popoverApp = createApp(this.options.component);\r\n\t/* 独立应用，配置是否共享、同步，可以配置，此处用appPlugins方法，保持一致 */\r\n\tappPlugins(popoverApp);\r\n\tconst vm = popoverApp.mount(`#${this.id}`);\r\n\tthis.$popoverDOM = $(vm.$el);\r\n\tthis.$popoverDOM.appendTo(this.$popoverMountDOM);\r\n\treturn;\r\n}\r\n```\r\n\r\n与 Vue2 处理方式不同，需要使用 appPlugins 给`createApp`返回的`app`添加 plugin。应对 app 独立化后，无法共享 component 依赖的特性。\r\n\r\n## 状态管理 ~~VueX~~\r\n\r\n\u003e 视图归视图，状态归状态\r\n\r\n- State\\_\\*: 状态（变量）\r\n- Methods\\_\\*: 方法\r\n- Cpt\\_\\*: 计算属性 .value\r\n\r\nVue2 中的 this 就是用来保存状态，Vue3 的进步之处在于状态的解耦。\r\n\r\nxItem 的设计与使用充分基于这种原则，xItem 视图本身，与 configs 相关，状态与 v-model 绑定相关。\r\n\r\n\r\nxItem value可以直接用configs里面的value 不需要额外的v-model\r\n```js\r\n/* FILE:src\\state\\State_App.js */\r\n/* state State_App 相当于命名空间*/\r\nexport const State_App = reactive({ configs: lStorage.appConfigs });\r\n\r\n/* getter 就用computed代替;commit直接修改StateApp  */\r\nexport const APP_LANGUAGE = computed({\r\n\tget: () =\u003e State_UI.language,\r\n\tset: lang =\u003e (State_UI.language = lang)\r\n});\r\n\r\n/* 副作用 effect */\r\n/* 同步AppConfigs 到 localStorage */\r\nwatchEffect(() =\u003e (lStorage.appConfigs = State_App.configs));\r\n\r\n/* actions 异步修改 效果同事务 自己去保证原子性 */\r\nexport const Actions_App = {\r\n\tGetInfo: async () =\u003e {},\r\n\tLogin: async () =\u003e {},\r\n\tLogout: async () =\u003e {}\r\n};\r\n```\r\n\r\n\r\n## 开发\r\n\r\nApp.vue 中完成\r\n\r\n## pro-component\r\n\r\n### xItem\r\n\r\n错误信息可以单独提供，默认是在 formItem 下方展示 tips ，也可以利用错误信息做其他展现方式，比如 popup， 提供 id 定位，方便滑动定位 vModel 与配置信息分开\r\n\r\n- 参考\r\n  - `src/views/user/LoginCredentials.vue`\r\n  - `src/views/user/State_Login.jsx`\r\n\r\n```js\r\nimport {State_App} from \"@ventose/state/State_App\";\r\nimport {defItem, ITEM_TYPE} from \"@ventose/ui\";\r\nimport {watch} from \"vue\";\r\n\r\n- [ ] 自定义组件的校验如何处理?\r\n\r\nconst inputConfigs = defItem({\r\n    type: ITEM_TYPE.input,\r\n    onAfterValueChange: (configs) =\u003e {\r\n        State_App.count++;\r\n    }\r\n});\r\nconst state = reactive({name: ''})\r\n\r\nwatch(() =\u003e State_App.count, (count) =\u003e {\r\n    State_App.count = count;\r\n});\r\n```\r\n\r\n```html\r\nState_App.count: {{State_App.count}}\r\n\u003cxItem :configs=\"inputConfigs\" v-model=\"state.name\" /\u003e\r\n```\r\n\r\n### xDataGrid\r\n\r\n- 拖动排序 字典下拉顺序=\u003e order 的修改\r\n\r\n### Utils\r\n\r\n- 设置 title\r\n  - setDocumentTitle()\r\n- root var css 变量\r\n  - setCSSVariables\r\n\r\n## 自定义的折叠按钮(未使用)\r\n\r\n```html\r\n\u003c!--    \u003cxRender :render=\"render.collapsedButton\" :collapsed=\"State_App.collapsed\"/\u003e--\u003e\r\n```\r\n\r\n## log\r\n\r\n1. `no-mutating-props`:`MutatingProps`\r\n2. `pickValueFrom`：从 xItem 的 configs 中获取 value；\r\n3. xItem 错误提示随语言切换变更 涉及到 $t 的配置项都需要 ()=\u003e\r\n\r\n- 20211117 登陆框 blur 未触发 update 校验\r\n- 20211127022841 v-uiPopover\r\n- 20220110095314\r\n  - xIcon ：异步，动态懒加载 src\\assets\\svg 目录下单个文件，经过插件处理，分别打包成独立文件\r\n  - SvgRender: 同步，首页不想让用户看到 loading 状态，可提前加载图标\r\n\r\n```html\r\n\u003c!-- src\\assets\\svg\\lockStrok.svg --\u003e\r\n\u003cxIcon\r\n\ticon=\"lockStrok\"\r\n\tstyle=\"color: red; height: 100px; width: 100px; outline: 1px solid black; margin: 10px; \" /\u003e\r\n```\r\n\r\n- 20220328210842\r\n\r\n国际化,用于内部通信\r\n\r\n```js\r\nexport const State_UI = reactive({\r\n\tlanguage: lStorage[\"language\"] || \"zh-CN\",\r\n\t/* svg 的路径  */\r\n\tassetsSvgPath:'',\r\n\t$t: (prop, payload) =\u003e ({\r\n\t\tlabel: prop\r\n\t})\r\n});\r\n```\r\n\r\nxItem msg 可以是 function 根据传入的参数显示不同信息\r\n\r\n- 20220506234727\r\n  如果 response 是 auth 清空 token refresh 页面\r\n\r\n### 链式调用，延迟异步操作\r\n\r\n- api.service.request\r\n\t- service 是可以延迟调用的\r\n\t- 但是可以将异步操作放在request里面，\r\n\t- 需要将参数传递到request\r\n\r\n\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshonesinglone%2Fgerminal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshonesinglone%2Fgerminal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshonesinglone%2Fgerminal/lists"}