diff --git a/README.md b/README.md index 090754a..fdffd7b 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,6 @@ Kinit 是一套全部开源的快速开发平台,毫无保留给个人及企 PC端演示地址:http://kinit.ktianc.top -移动端演示地址:http://h5.ktianc.top - 微信小程序端演示: - 搜索:kinit @@ -87,7 +85,7 @@ github地址:https://github.com/vvandk/kinit - [x] 文件上传:对接阿里云OSS与本地存储。 -- [x] 登录认证:目前支持用户使用手机号+密码方式或者手机验证码登录。 +- [x] 登录认证:目前支持用户使用手机号+密码登录方式,手机验证码登录方式。 说明:新建用户密码默认为手机号后六位; @@ -95,16 +93,16 @@ github地址:https://github.com/vvandk/kinit - [x] 系统配置:对本系统环境信息进行动态配置 - 网站标题,LOGO,描述,ICO,备案号,底部内容,百度统计代码,等等 + 网站标题,LOGO,描述,ICO,备案号,底部内容,微信小程序信息,等等 - [x] 用户分布:接入高德地图显示各地区用户分布情况 +- [x] 智慧大屏:大屏展示`办公室空气质量实时检测`数据分析 + - [x] 登录日志:用户登录日志记录和查询。 - [x] 操作日志:系统用户每次操作功能时的详细记录。 -- [ ] **异常日志:获取并展示接口异常日志** - - [x] 接口文档:提供自动生成的交互式 API 文档,与 ReDoc 文档 - [x] 导入导出:灵活支持数据导入导出功能 @@ -123,7 +121,7 @@ github地址:https://github.com/vvandk/kinit ## 移动端内置功能 -- [x] 登录认证:目前支持用户使用手机号+密码方式登录。 +- [x] 登录认证:支持用户使用手机号+密码方式登录,微信手机号一键登录方式。 说明:新建用户密码默认为手机号后六位; @@ -138,7 +136,6 @@ github地址:https://github.com/vvandk/kinit - [ ] 考虑支持多机部署方案,如果接口使用多机,那么用户是否支持统一认证 - [ ] **自动化编排服务:使用docker-compose部署项目** - [ ] **数据库备份:自动备份数据库** -- [ ] **接入数据大屏** - [ ] **可视化低代码表单:接入低代码表单,https://vform666.com/vform3.html?from=element_plus** ## 前序准备 @@ -315,6 +312,10 @@ Redis (推荐使用最新稳定版) # 高德地图配置 map_key + + # 微信小程序配置 + wx_server_app_id + wx_server_app_secret ``` 6. 启动 @@ -402,6 +403,8 @@ pnpm run build:pro ![image-20221010214526082](https://gitee.com/ktianc/kinit/raw/master/images/2.png) +![image-20221010214526082](https://gitee.com/ktianc/kinit/raw/master/images/10.png) + ![image-20221010214526082](https://gitee.com/ktianc/kinit/raw/master/images/3.png) ![image-20221010214526082](https://gitee.com/ktianc/kinit/raw/master/images/6.jpg) diff --git a/images/10.png b/images/10.png new file mode 100644 index 0000000..0262d74 Binary files /dev/null and b/images/10.png differ diff --git a/kinit-admin/src/App.vue b/kinit-admin/src/App.vue index 18be7c0..0109733 100644 --- a/kinit-admin/src/App.vue +++ b/kinit-admin/src/App.vue @@ -5,7 +5,7 @@ import { ConfigGlobal } from '@/components/ConfigGlobal' import { isDark } from '@/utils/is' import { useDesign } from '@/hooks/web/useDesign' import { useCache } from '@/hooks/web/useCache' -import { getSystemSettingsClassifysApi } from '@/api/vadmin/system/settings' +import { getSystemBaseConfigApi } from '@/api/vadmin/system/settings' const { getPrefixCls } = useDesign() @@ -23,16 +23,15 @@ const addMeta = (name: string, content: string) => { // 获取并设置系统配置 const setSystemConfig = async () => { - const res = await getSystemSettingsClassifysApi({ classify: 'web' }) + const res = await getSystemBaseConfigApi() if (res) { - appStore.setTitle(res.data.web_basic.web_title || import.meta.env.VITE_APP_TITLE) - appStore.setLogoImage(res.data.web_basic.web_logo || '/media/system/logo.png') - appStore.setFooterContent(res.data.web_basic.web_copyright || 'Copyright ©2022-present K') - appStore.setIcpNumber(res.data.web_basic.web_icp_number || '') + appStore.setTitle(res.data.web_title || import.meta.env.VITE_APP_TITLE) + appStore.setLogoImage(res.data.web_logo || '/media/system/logo.png') + appStore.setFooterContent(res.data.web_copyright || 'Copyright ©2022-present K') + appStore.setIcpNumber(res.data.web_icp_number || '') addMeta( 'description', - res.data.web_basic.web_desc || - 'Kinit 是一套开箱即用的中后台解决方案,可以作为新项目的启动模版。' + res.data.web_desc || 'Kinit 是一套开箱即用的中后台解决方案,可以作为新项目的启动模版。' ) } } diff --git a/kinit-admin/src/api/vadmin/auth/user.ts b/kinit-admin/src/api/vadmin/auth/user.ts index 18519da..ea67af9 100644 --- a/kinit-admin/src/api/vadmin/auth/user.ts +++ b/kinit-admin/src/api/vadmin/auth/user.ts @@ -28,8 +28,8 @@ export const postCurrentUserUpdateInfo = (data: any): Promise => { return request.post({ url: `/vadmin/auth/user/current/update/info/`, data }) } -export const getCurrentUserInfo = (): Promise => { - return request.get({ url: `/vadmin/auth/user/current/info/` }) +export const getCurrentAdminUserInfo = (): Promise => { + return request.get({ url: `/vadmin/auth/user/admin/current/info/` }) } export const postExportUserQueryListApi = (params: any, data: any): Promise => { @@ -43,10 +43,7 @@ export const getImportTemplateApi = (): Promise => { export const postImportUserApi = (data: any): Promise => { return request.post({ url: `/vadmin/auth/import/users/`, - headers: { - 'Content-Type': 'multipart/form-data' - }, - timeout: 5 * 60 * 1000, + headersType: 'multipart/form-data', data }) } diff --git a/kinit-admin/src/api/vadmin/help/issue.ts b/kinit-admin/src/api/vadmin/help/issue.ts new file mode 100644 index 0000000..d3e4d65 --- /dev/null +++ b/kinit-admin/src/api/vadmin/help/issue.ts @@ -0,0 +1,47 @@ +import request from '@/config/axios' + +// 常见问题类别 +export const getIssueCategoryListApi = (params: any): Promise => { + return request.get({ url: '/vadmin/help/issue/categorys/', params }) +} + +export const addIssueCategoryApi = (data: any): Promise => { + return request.post({ url: '/vadmin/help/issue/categorys/', data }) +} + +export const delIssueCategoryListApi = (data: any): Promise => { + return request.delete({ url: '/vadmin/help/issue/categorys/', data }) +} + +export const putIssueCategoryApi = (data: any): Promise => { + return request.put({ url: `/vadmin/help/issue/categorys/${data.id}/`, data }) +} + +export const getIssueCategoryApi = (dataId: number): Promise => { + return request.get({ url: `/vadmin/help/issue/categorys/${dataId}/` }) +} + +export const getIssueCategoryOptionsApi = (): Promise => { + return request.get({ url: `/vadmin/help/issue/categorys/options/` }) +} + +// 常见问题 +export const getIssueListApi = (params: any): Promise => { + return request.get({ url: '/vadmin/help/issues/', params }) +} + +export const addIssueApi = (data: any): Promise => { + return request.post({ url: '/vadmin/help/issues/', data }) +} + +export const delIssueListApi = (data: any): Promise => { + return request.delete({ url: '/vadmin/help/issues/', data }) +} + +export const putIssueApi = (data: any): Promise => { + return request.put({ url: `/vadmin/help/issues/${data.id}/`, data }) +} + +export const getIssueApi = (dataId: number): Promise => { + return request.get({ url: `/vadmin/help/issues/${dataId}/` }) +} diff --git a/kinit-admin/src/api/vadmin/system/files.ts b/kinit-admin/src/api/vadmin/system/files.ts new file mode 100644 index 0000000..3c5e99c --- /dev/null +++ b/kinit-admin/src/api/vadmin/system/files.ts @@ -0,0 +1,9 @@ +import request from '@/config/axios' + +export const addFilesListApi = (data: any): Promise => { + return request.post({ + url: `/vadmin/system/files/`, + headersType: 'multipart/form-data', + data + }) +} diff --git a/kinit-admin/src/api/vadmin/system/settings.ts b/kinit-admin/src/api/vadmin/system/settings.ts index 4654a7c..bd2c8c1 100644 --- a/kinit-admin/src/api/vadmin/system/settings.ts +++ b/kinit-admin/src/api/vadmin/system/settings.ts @@ -12,10 +12,17 @@ export const putSystemSettingsApi = (data: any): Promise => { return request.put({ url: '/vadmin/system/settings/tabs/values/', data }) } -export const getSystemSettingsClassifysApi = (params: any): Promise => { - return request.get({ url: '/vadmin/system/settings/classifys/', params }) +// 获取系统基础配置,每次进入系统时使用 +export const getSystemBaseConfigApi = (): Promise => { + return request.get({ url: '/vadmin/system/settings/base/config/' }) } -export const getSystemSettingsConfigValueApi = (params: any): Promise => { - return request.get({ url: '/vadmin/system/settings/config/value/', params }) +// 获取系统隐私协议 +export const getSystemPrivacyApi = (): Promise => { + return request.get({ url: '/vadmin/system/settings/privacy/' }) +} + +// 获取系统用户协议 +export const getSystemAgreementApi = (): Promise => { + return request.get({ url: '/vadmin/system/settings/agreement/' }) } diff --git a/kinit-admin/src/components/Dialog/src/Dialog.vue b/kinit-admin/src/components/Dialog/src/Dialog.vue index 163cf62..25d375b 100644 --- a/kinit-admin/src/components/Dialog/src/Dialog.vue +++ b/kinit-admin/src/components/Dialog/src/Dialog.vue @@ -63,7 +63,6 @@ const dialogStyle = computed(() => { destroy-on-close lock-scroll draggable - align-center :close-on-click-modal="false" > @@ -102,6 +125,8 @@ .normal-login-container { width: 100%; + height: 100vh; + position: relative; .logo-content { width: 100%; @@ -160,6 +185,14 @@ .easyinput { width: 100%; } + + .footer { + margin: 20px auto; + width: 80%; + position: absolute; + bottom: 30px; + left: 10%; + } } .login-code-img { diff --git a/kinit-uni/pages/mine/about/index.vue b/kinit-uni/pages/mine/about/index.vue index 5d37945..1638889 100644 --- a/kinit-uni/pages/mine/about/index.vue +++ b/kinit-uni/pages/mine/about/index.vue @@ -17,13 +17,13 @@ 官方邮箱 - kinit@xx.com + {{ WXEmail }} 服务热线 - 400-999-9999 + {{ WXPhone }} @@ -61,6 +61,12 @@ siteUrl() { return this.$store.state.app.siteUrl }, + WXEmail() { + return this.$store.state.app.WXEmail + }, + WXPhone() { + return this.$store.state.app.WXPhone + }, footerContent() { return this.$store.state.app.footerContent } diff --git a/kinit-uni/pages/mine/help/index.vue b/kinit-uni/pages/mine/help/index.vue deleted file mode 100644 index 034e7fd..0000000 --- a/kinit-uni/pages/mine/help/index.vue +++ /dev/null @@ -1,105 +0,0 @@ - - - - - diff --git a/kinit-uni/pages/mine/help/issue/index.vue b/kinit-uni/pages/mine/help/issue/index.vue new file mode 100644 index 0000000..ea2e403 --- /dev/null +++ b/kinit-uni/pages/mine/help/issue/index.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/kinit-uni/pages/mine/help/issue/info.vue b/kinit-uni/pages/mine/help/issue/info.vue new file mode 100644 index 0000000..2c20516 --- /dev/null +++ b/kinit-uni/pages/mine/help/issue/info.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/kinit-uni/pages/mine/index.vue b/kinit-uni/pages/mine/index.vue index b59ca4b..0b8b9f2 100644 --- a/kinit-uni/pages/mine/index.vue +++ b/kinit-uni/pages/mine/index.vue @@ -14,7 +14,7 @@ @@ -37,7 +37,7 @@ - 反馈社区 + 意见反馈 @@ -121,7 +121,7 @@ this.$tab.navigateTo('/pages/mine/setting/index') }, handleToLogin() { - this.$tab.reLaunch('/pages/login') + this.$tab.reLaunch('/pages/login/login') }, handleToAvatar() { this.$tab.navigateTo('/pages/mine/avatar/index') @@ -134,7 +134,7 @@ }) }, handleHelp() { - this.$tab.navigateTo('/pages/mine/help/index') + this.$tab.navigateTo('/pages/mine/help/issue/index') }, handleAbout() { this.$tab.navigateTo('/pages/mine/about/index') diff --git a/kinit-uni/pages/mine/info/edit.vue b/kinit-uni/pages/mine/info/edit.vue index 8f634a9..5bf3b57 100644 --- a/kinit-uni/pages/mine/info/edit.vue +++ b/kinit-uni/pages/mine/info/edit.vue @@ -63,7 +63,13 @@ - + + @@ -113,7 +119,7 @@ } }, onLoad() { - this.$store.dispatch('getDicts', ["sys_vadmin_gender"]).then(result => { + this.$store.dispatch('dict/getDicts', ["sys_vadmin_gender"]).then(result => { this.genderOptions = result.sys_vadmin_gender }) // this.resetForm() @@ -133,15 +139,18 @@ } }, getUser() { + this.$modal.loading("加载中") getInfo().then(res => { this.form = res.data + }).finally(() => { + this.$modal.closeLoading() }) }, submit(ref) { this.$refs.formRef.validate().then(res => { this.btnLoading = true updateCurrentUser(this.form).then(res => { - this.$store.dispatch('UpdateInfo', res.data) + this.$store.dispatch('auth/UpdateInfo', res.data) this.$modal.msgSuccess("更新成功"); }).finally(() => { this.btnLoading = false diff --git a/kinit-uni/pages/mine/pwd/index.vue b/kinit-uni/pages/mine/pwd/index.vue index 6dc9b48..2081c81 100644 --- a/kinit-uni/pages/mine/pwd/index.vue +++ b/kinit-uni/pages/mine/pwd/index.vue @@ -1,5 +1,14 @@ @@ -18,7 +27,6 @@ export default { data() { return { - btnLoading: false, form: { password: undefined, password_two: undefined @@ -49,17 +57,30 @@ } } }, + computed: { + isResetPassword() { + return this.$store.state.auth.isResetPassword + } + }, onReady() { this.$refs.form.setRules(this.rules) }, methods: { submit() { this.$refs.form.validate().then(res => { - this.btnLoading = true + this.$modal.loading("正在提交") postCurrentUserResetPassword(this.form).then(response => { - this.$modal.msgSuccess("修改成功") + this.form = { + password: "", + password_two: "" + } + this.$modal.msgSuccess("重置成功") + if (!this.isResetPassword) { + this.$store.commit('auth/SET_IS_RESET_PASSWORD', true) + this.$tab.reLaunch('/pages/index') + } }).finally(() => { - this.btnLoading = false + this.$modal.closeLoading() }) }) } @@ -75,5 +96,9 @@ .pwd-retrieve-container { padding-top: 36rpx; padding: 15px; + + .header { + padding-bottom: 36rpx; + } } diff --git a/kinit-uni/pages/mine/setting/index.vue b/kinit-uni/pages/mine/setting/index.vue index 6127590..785cb84 100644 --- a/kinit-uni/pages/mine/setting/index.vue +++ b/kinit-uni/pages/mine/setting/index.vue @@ -49,7 +49,7 @@ }, handleLogout() { this.$modal.confirm('确定注销并退出系统吗?').then(() => { - this.$store.dispatch('LogOut') + this.$store.dispatch('auth/LogOut') }) } } diff --git a/kinit-uni/permission.js b/kinit-uni/permission.js index 011d41a..046e0a9 100644 --- a/kinit-uni/permission.js +++ b/kinit-uni/permission.js @@ -1,9 +1,9 @@ import { getToken } from '@/common/utils/auth' import store from '@/store' -import {RouterMount, createRouter} from 'uni-simple-router'; +import { RouterMount, createRouter } from 'uni-simple-router'; // 登录页面 -const loginPage = "/pages/login" +const loginPage = "/pages/login/login" const router = createRouter({ platform: process.env.VUE_APP_PLATFORM, @@ -13,18 +13,34 @@ const router = createRouter({ //全局路由前置守卫 router.beforeEach((to, from, next) => { if (to.meta.loginAuth) { + // 如果跳转的路由需要登录权限,则验证该权限 if (getToken()) { if (!store.state.auth.isUser) { - store.dispatch('GetInfo') + store.dispatch('auth/GetInfo') } if (to.path === loginPage) { - uni.reLaunch({ url: "/" }) + next({ + path: `/pages/index`, + NAVTYPE: 'replaceAll' + }) } + next(); } else { - uni.reLaunch({ url: loginPage }) + next({ + path: loginPage, + NAVTYPE: 'replaceAll' + }) } + } else if (to.path === loginPage && getToken()) { + // 如果跳转路由为登录页面并且存在token,则跳转到首页 + next({ + path: `/pages/index`, + NAVTYPE: 'replaceAll' + }) + } else { + // 不需要权限,且不是登录页面则不进行验证 + next(); } - next(); }); // 全局路由后置守卫 diff --git a/kinit-uni/static/font/iconfont.js b/kinit-uni/static/font/iconfont.js deleted file mode 100644 index 2bb515e..0000000 --- a/kinit-uni/static/font/iconfont.js +++ /dev/null @@ -1 +0,0 @@ -window._iconfont_svg_string_3803079='',function(a){var c=(c=document.getElementsByTagName("script"))[c.length-1],l=c.getAttribute("data-injectcss"),c=c.getAttribute("data-disable-injectsvg");if(!c){var h,t,i,o,s,z=function(c,l){l.parentNode.insertBefore(c,l)};if(l&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}h=function(){var c,l=document.createElement("div");l.innerHTML=a._iconfont_svg_string_3803079,(l=l.getElementsByTagName("svg")[0])&&(l.setAttribute("aria-hidden","true"),l.style.position="absolute",l.style.width=0,l.style.height=0,l.style.overflow="hidden",l=l,(c=document.body).firstChild?z(l,c.firstChild):c.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),h()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(i=h,o=a.document,s=!1,p(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,d())})}function d(){s||(s=!0,i())}function p(){try{o.documentElement.doScroll("left")}catch(c){return void setTimeout(p,50)}d()}}(window); \ No newline at end of file diff --git a/kinit-uni/static/index.html b/kinit-uni/static/index.html index 9c467fd..86128e6 100644 --- a/kinit-uni/static/index.html +++ b/kinit-uni/static/index.html @@ -5,7 +5,7 @@ <%= htmlWebpackPlugin.options.title %> - +