版本升级:
1. 修复(kinit-admin):页面缓存问题修复 2. 更新(kinit-api,kinit-admin):菜单管理新增是否缓存字段 3. 更新(kinit-admin):将缓存默认存储在localStorage中 4. 更新(kinit-api):将python-jose库更换为pyjwt库 5. 优化(kinit-admin,kinit-uni):退出登录方法优化 6. 优化(kinit-admin,kinit-uni):response拦截优化 7. 新增(kinit-api,kinit-admin,kinit-uni):jwt到期时间缩短,加入刷新token功能 8. (kinit-uni)切换到 vscode 开发 uniapp 项目
This commit is contained in:
parent
06012fda6e
commit
ff56a184ca
@ -5,6 +5,7 @@ import { useAuthStore } from '@/store/modules/auth'
|
|||||||
import qs from 'qs'
|
import qs from 'qs'
|
||||||
import { config } from './config'
|
import { config } from './config'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import request from '@/config/axios'
|
||||||
|
|
||||||
const { result_code, unauthorized_code, request_timeout } = config
|
const { result_code, unauthorized_code, request_timeout } = config
|
||||||
|
|
||||||
@ -62,33 +63,99 @@ service.interceptors.request.use(
|
|||||||
// response 拦截器
|
// response 拦截器
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response: AxiosResponse<any>) => {
|
(response: AxiosResponse<any>) => {
|
||||||
|
// 这个状态码是和后端约定好的
|
||||||
|
const code = response.data.code || unauthorized_code
|
||||||
|
const message = response.data.message || '后端接口无返回内容'
|
||||||
|
const refresh = response.data.refresh || false
|
||||||
|
|
||||||
if (response.config.responseType === 'blob') {
|
if (response.config.responseType === 'blob') {
|
||||||
// 如果是文件流,直接过
|
// 如果是文件流,直接过
|
||||||
return response
|
return response
|
||||||
} else if (response.data.code === result_code) {
|
} else if (code === result_code) {
|
||||||
|
if (refresh) {
|
||||||
|
// 因token快过期,刷新token
|
||||||
|
refreshToken().then((res) => {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
wsCache.set(appStore.getRefreshToken, res.data.refresh_token)
|
||||||
|
})
|
||||||
|
// .catch(() => {
|
||||||
|
// const authStore = useAuthStore()
|
||||||
|
// authStore.logout()
|
||||||
|
// ElMessage.error('未认证,请登录')
|
||||||
|
// })
|
||||||
|
}
|
||||||
return response.data
|
return response.data
|
||||||
} else if (response.data.code === unauthorized_code) {
|
} else if (code === unauthorized_code) {
|
||||||
// 请重新登录
|
// 因token无效,token过期导致
|
||||||
ElMessage.error(response.data.message)
|
refreshToken().then((res) => {
|
||||||
const authStore = useAuthStore()
|
const appStore = useAppStore()
|
||||||
authStore.logout()
|
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
wsCache.set(appStore.getRefreshToken, res.data.refresh_token)
|
||||||
|
ElMessage.error('操作失败,请重试')
|
||||||
|
})
|
||||||
|
// .catch(() => {
|
||||||
|
// const authStore = useAuthStore()
|
||||||
|
// authStore.logout()
|
||||||
|
// ElMessage.error('未认证,请登录')
|
||||||
|
// })
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.data.message)
|
ElMessage.error(message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error: AxiosError) => {
|
(error: AxiosError) => {
|
||||||
console.log('err' + error)
|
|
||||||
let { message } = error
|
let { message } = error
|
||||||
if (message == 'Network Error') {
|
const status = error.response?.status
|
||||||
message = '后端接口连接异常'
|
switch (status) {
|
||||||
} else if (message.includes('timeout')) {
|
case 400:
|
||||||
message = '系统接口请求超时'
|
message = '请求错误'
|
||||||
} else if (message.includes('Request failed with status code')) {
|
break
|
||||||
message = '系统接口' + message.substr(message.length - 3) + '异常'
|
case 401:
|
||||||
|
// 强制要求重新登录,因账号已冻结,账号已过期,手机号码错误,刷新token无效等问题导致
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
authStore.logout()
|
||||||
|
message = '未认证,请登录'
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
message = '拒绝访问'
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
message = `请求地址出错: ${error.response?.config.url}`
|
||||||
|
break
|
||||||
|
case 408:
|
||||||
|
message = '请求超时'
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
message = '服务器内部错误'
|
||||||
|
break
|
||||||
|
case 501:
|
||||||
|
message = '服务未实现'
|
||||||
|
break
|
||||||
|
case 502:
|
||||||
|
message = '网关错误'
|
||||||
|
break
|
||||||
|
case 503:
|
||||||
|
message = '服务不可用'
|
||||||
|
break
|
||||||
|
case 504:
|
||||||
|
message = '网关超时'
|
||||||
|
break
|
||||||
|
case 505:
|
||||||
|
message = 'HTTP版本不受支持'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
ElMessage.error(message)
|
ElMessage.error(message)
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 刷新Token
|
||||||
|
const refreshToken = (): Promise<IResponse> => {
|
||||||
|
const appStore = useAppStore()
|
||||||
|
const data = wsCache.get(appStore.getRefreshToken)
|
||||||
|
return request.post({ url: '/auth/token/refresh/', data })
|
||||||
|
}
|
||||||
|
|
||||||
export { service }
|
export { service }
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* 配置浏览器本地存储的方式,可直接存储对象数组。
|
* 配置浏览器本地存储的方式,可直接存储对象数组。
|
||||||
|
* sessionStorage 多标签页情况下互不共享
|
||||||
|
* localStorage 多标签页情况下互相共享
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import WebStorageCache from 'web-storage-cache'
|
import WebStorageCache from 'web-storage-cache'
|
||||||
|
|
||||||
type CacheType = 'sessionStorage' | 'localStorage'
|
type CacheType = 'sessionStorage' | 'localStorage'
|
||||||
|
|
||||||
export const useCache = (type: CacheType = 'sessionStorage') => {
|
export const useCache = (type: CacheType = 'localStorage') => {
|
||||||
const wsCache: WebStorageCache = new WebStorageCache({
|
const wsCache: WebStorageCache = new WebStorageCache({
|
||||||
storage: type
|
storage: type
|
||||||
})
|
})
|
||||||
|
@ -39,6 +39,7 @@ interface AppState {
|
|||||||
footerContent: string
|
footerContent: string
|
||||||
icpNumber: string
|
icpNumber: string
|
||||||
token: string
|
token: string
|
||||||
|
refreshToken: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAppStore = defineStore('app', {
|
export const useAppStore = defineStore('app', {
|
||||||
@ -46,6 +47,7 @@ export const useAppStore = defineStore('app', {
|
|||||||
return {
|
return {
|
||||||
userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
|
userInfo: 'userInfo', // 登录信息存储字段-建议每个项目换一个字段,避免与其他项目冲突
|
||||||
token: 'Token', // 存储Token字段
|
token: 'Token', // 存储Token字段
|
||||||
|
refreshToken: 'RefreshToken', // 存储刷新Token字段
|
||||||
sizeMap: ['default', 'large', 'small'],
|
sizeMap: ['default', 'large', 'small'],
|
||||||
mobile: false, // 是否是移动端
|
mobile: false, // 是否是移动端
|
||||||
title: import.meta.env.VITE_APP_TITLE, // 标题
|
title: import.meta.env.VITE_APP_TITLE, // 标题
|
||||||
@ -170,6 +172,9 @@ export const useAppStore = defineStore('app', {
|
|||||||
getToken(): string {
|
getToken(): string {
|
||||||
return this.token
|
return this.token
|
||||||
},
|
},
|
||||||
|
getRefreshToken(): string {
|
||||||
|
return this.refreshToken
|
||||||
|
},
|
||||||
getIsDark(): boolean {
|
getIsDark(): boolean {
|
||||||
return this.isDark
|
return this.isDark
|
||||||
},
|
},
|
||||||
|
@ -7,6 +7,7 @@ import { useCache } from '@/hooks/web/useCache'
|
|||||||
import { getCurrentAdminUserInfo } from '@/api/vadmin/auth/user'
|
import { getCurrentAdminUserInfo } from '@/api/vadmin/auth/user'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||||
|
import router from '@/router'
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
if (res) {
|
if (res) {
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
wsCache.set(appStore.getToken, `${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
wsCache.set(appStore.getRefreshToken, res.data.refresh_token)
|
||||||
// 存储用户信息
|
// 存储用户信息
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
await auth.getUserInfo()
|
await auth.getUserInfo()
|
||||||
@ -61,7 +63,7 @@ export const useAuthStore = defineStore('auth', {
|
|||||||
const tagsViewStore = useTagsViewStore()
|
const tagsViewStore = useTagsViewStore()
|
||||||
tagsViewStore.delAllViews()
|
tagsViewStore.delAllViews()
|
||||||
resetRouter()
|
resetRouter()
|
||||||
window.location.href = '/login'
|
router.push('/login')
|
||||||
},
|
},
|
||||||
updateUser(data: UserState) {
|
updateUser(data: UserState) {
|
||||||
this.user.gender = data.gender
|
this.user.gender = data.gender
|
||||||
|
@ -24,6 +24,7 @@ const rules = reactive({
|
|||||||
disabled: [required()],
|
disabled: [required()],
|
||||||
hidden: [required()],
|
hidden: [required()],
|
||||||
path: [required()],
|
path: [required()],
|
||||||
|
noCache: [required()],
|
||||||
order: [required()]
|
order: [required()]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -44,6 +44,12 @@ export const columns = reactive<TableColumn[]>([
|
|||||||
label: '组件路径',
|
label: '组件路径',
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'noCache',
|
||||||
|
label: '页面缓存',
|
||||||
|
width: '120px',
|
||||||
|
show: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'hidden',
|
field: 'hidden',
|
||||||
label: '显示状态',
|
label: '显示状态',
|
||||||
@ -224,5 +230,31 @@ export const schema = reactive<FormSchema[]>([
|
|||||||
span: 12
|
span: 12
|
||||||
},
|
},
|
||||||
ifshow: (values) => values.menu_type === '2'
|
ifshow: (values) => values.menu_type === '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'noCache',
|
||||||
|
label: '页面缓存',
|
||||||
|
colProps: {
|
||||||
|
span: 12
|
||||||
|
},
|
||||||
|
component: 'Radio',
|
||||||
|
componentProps: {
|
||||||
|
style: {
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '缓存',
|
||||||
|
value: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '不缓存',
|
||||||
|
value: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
value: false,
|
||||||
|
ifshow: (values) => values.menu_type === '1',
|
||||||
|
labelMessage: '开启页面缓存,需要组件名称必须与xx.vue页面的name一致'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'AuthMenu'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { RightToolbar } from '@/components/RightToolbar'
|
import { RightToolbar } from '@/components/RightToolbar'
|
||||||
@ -213,12 +219,16 @@ watch(
|
|||||||
<ElSwitch :value="!row.hidden" disabled />
|
<ElSwitch :value="!row.hidden" disabled />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #noCache="{ row }">
|
||||||
|
<ElSwitch :value="!row.noCache" disabled />
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #disabled="{ row }">
|
<template #disabled="{ row }">
|
||||||
<ElSwitch :value="!row.disabled" disabled />
|
<ElSwitch :value="!row.disabled" disabled />
|
||||||
</template>
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="700px">
|
<Dialog v-model="dialogVisible" :title="dialogTitle" width="800px">
|
||||||
<Write ref="writeRef" :current-row="tableObject.currentRow" :parent-id="parentId" />
|
<Write ref="writeRef" :current-row="tableObject.currentRow" :parent-id="parentId" />
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'AuthRole'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'AuthUser'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'HelpIssueForm'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Form } from '@/components/Form'
|
import { Form } from '@/components/Form'
|
||||||
import { useForm } from '@/hooks/web/useForm'
|
import { useForm } from '@/hooks/web/useForm'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'HelpIssue'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -118,7 +118,7 @@ export const searchSchema = reactive<FormSchema[]>([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'platform',
|
field: 'platform',
|
||||||
label: '展示平台',
|
label: '登录平台',
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
style: {
|
style: {
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'HelpIssue'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SystemDictDetail'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SystemDict'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SystemRecordLogin'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SystemRecordOperation'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ContentWrap } from '@/components/ContentWrap'
|
import { ContentWrap } from '@/components/ContentWrap'
|
||||||
import { Table } from '@/components/Table'
|
import { Table } from '@/components/Table'
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SystemSettings'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ElTabs, ElTabPane } from 'element-plus'
|
import { ElTabs, ElTabPane } from 'element-plus'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
@ -11,7 +11,7 @@ from fastapi.security import OAuth2PasswordBearer
|
|||||||
"""
|
"""
|
||||||
系统版本
|
系统版本
|
||||||
"""
|
"""
|
||||||
VERSION = "1.6.1"
|
VERSION = "1.6.2"
|
||||||
|
|
||||||
"""安全警告: 不要在生产中打开调试运行!"""
|
"""安全警告: 不要在生产中打开调试运行!"""
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
@ -21,6 +21,7 @@ DEMO = not DEBUG
|
|||||||
"""演示功能白名单"""
|
"""演示功能白名单"""
|
||||||
DEMO_WHITE_LIST_PATH = [
|
DEMO_WHITE_LIST_PATH = [
|
||||||
"/auth/login/",
|
"/auth/login/",
|
||||||
|
"/auth/token/refresh/",
|
||||||
"/auth/wx/login/",
|
"/auth/wx/login/",
|
||||||
"/vadmin/system/dict/types/details/",
|
"/vadmin/system/dict/types/details/",
|
||||||
"/vadmin/auth/user/export/query/list/to/excel/"
|
"/vadmin/auth/user/export/query/list/to/excel/"
|
||||||
@ -49,8 +50,12 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login/", auto_error=False)
|
|||||||
SECRET_KEY = 'vgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=kbvqacjq75vzps$'
|
SECRET_KEY = 'vgb0tnl9d58+6n-6h-ea&u^1#s0ccp!794=kbvqacjq75vzps$'
|
||||||
"""用于设定 JWT 令牌签名算法"""
|
"""用于设定 JWT 令牌签名算法"""
|
||||||
ALGORITHM = "HS256"
|
ALGORITHM = "HS256"
|
||||||
"""令牌过期时间,9999分钟"""
|
"""access_token 过期时间,一天"""
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 9999
|
ACCESS_TOKEN_EXPIRE_MINUTES = 1440
|
||||||
|
"""refresh_token 过期时间,用于刷新token使用,两天"""
|
||||||
|
REFRESH_TOKEN_EXPIRE_MINUTES = 1440 * 2
|
||||||
|
"""access_token 缓存时间,用于刷新token使用,30分钟"""
|
||||||
|
ACCESS_TOKEN_CACHE_MINUTES = 30
|
||||||
|
|
||||||
"""
|
"""
|
||||||
挂载临时文件目录,并添加路由访问,此路由不会在接口文档中显示
|
挂载临时文件目录,并添加路由访问,此路由不会在接口文档中显示
|
||||||
|
@ -30,11 +30,11 @@ async def get_banners(auth: Auth = Depends(AllUserAuth())):
|
|||||||
"id": 3, "image": "https://ktianc.oss-cn-beijing.aliyuncs.com/kinit/system/banner/2022-11-09/banner3.png"
|
"id": 3, "image": "https://ktianc.oss-cn-beijing.aliyuncs.com/kinit/system/banner/2022-11-09/banner3.png"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return SuccessResponse(data)
|
return SuccessResponse(data, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/user/access/source/", summary="用户来源")
|
@app.get("/user/access/source/", summary="用户来源")
|
||||||
async def get_user_access_source():
|
async def get_user_access_source(auth: Auth = Depends(AllUserAuth())):
|
||||||
data = [
|
data = [
|
||||||
{"value": 1000, "name": 'analysis.directAccess'},
|
{"value": 1000, "name": 'analysis.directAccess'},
|
||||||
{"value": 310, "name": 'analysis.mailMarketing'},
|
{"value": 310, "name": 'analysis.mailMarketing'},
|
||||||
@ -42,11 +42,11 @@ async def get_user_access_source():
|
|||||||
{"value": 135, "name": 'analysis.videoAdvertising'},
|
{"value": 135, "name": 'analysis.videoAdvertising'},
|
||||||
{"value": 1548, "name": 'analysis.searchEngines'}
|
{"value": 1548, "name": 'analysis.searchEngines'}
|
||||||
]
|
]
|
||||||
return SuccessResponse(data)
|
return SuccessResponse(data, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/weekly/user/activity/", summary="每周用户活跃量")
|
@app.get("/weekly/user/activity/", summary="每周用户活跃量")
|
||||||
async def get_weekly_user_activity():
|
async def get_weekly_user_activity(auth: Auth = Depends(AllUserAuth())):
|
||||||
data = [
|
data = [
|
||||||
{"value": 13253, "name": 'analysis.monday'},
|
{"value": 13253, "name": 'analysis.monday'},
|
||||||
{"value": 34235, "name": 'analysis.tuesday'},
|
{"value": 34235, "name": 'analysis.tuesday'},
|
||||||
@ -56,11 +56,11 @@ async def get_weekly_user_activity():
|
|||||||
{"value": 1322, "name": 'analysis.saturday'},
|
{"value": 1322, "name": 'analysis.saturday'},
|
||||||
{"value": 1324, "name": 'analysis.sunday'}
|
{"value": 1324, "name": 'analysis.sunday'}
|
||||||
]
|
]
|
||||||
return SuccessResponse(data)
|
return SuccessResponse(data, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/monthly/sales/", summary="每月销售额")
|
@app.get("/monthly/sales/", summary="每月销售额")
|
||||||
async def get_monthly_sales():
|
async def get_monthly_sales(auth: Auth = Depends(AllUserAuth())):
|
||||||
data = [
|
data = [
|
||||||
{"estimate": 100, "actual": 120, "name": 'analysis.january'},
|
{"estimate": 100, "actual": 120, "name": 'analysis.january'},
|
||||||
{"estimate": 120, "actual": 82, "name": 'analysis.february'},
|
{"estimate": 120, "actual": 82, "name": 'analysis.february'},
|
||||||
@ -75,4 +75,4 @@ async def get_monthly_sales():
|
|||||||
{"estimate": 118, "actual": 99, "name": 'analysis.november'},
|
{"estimate": 118, "actual": 99, "name": 'analysis.november'},
|
||||||
{"estimate": 123, "actual": 123, "name": 'analysis.december'}
|
{"estimate": 123, "actual": 123, "name": 'analysis.december'}
|
||||||
]
|
]
|
||||||
return SuccessResponse(data)
|
return SuccessResponse(data, refresh=auth.refresh)
|
||||||
|
@ -4,10 +4,9 @@
|
|||||||
# @File : current.py
|
# @File : current.py
|
||||||
# @IDE : PyCharm
|
# @IDE : PyCharm
|
||||||
# @desc : 获取认证后的信息工具
|
# @desc : 获取认证后的信息工具
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
import jwt
|
||||||
from jose import jwt, JWTError
|
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
from apps.vadmin.auth.crud import UserDal
|
from apps.vadmin.auth.crud import UserDal
|
||||||
@ -43,7 +42,7 @@ class OpenAuth(AuthValidation):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_token(cls, token: str | None, db: AsyncSession) -> str | None:
|
def validate_token(cls, request: Request, token: str | None) -> str | None:
|
||||||
"""
|
"""
|
||||||
验证用户 token,没有则返回 None
|
验证用户 token,没有则返回 None
|
||||||
"""
|
"""
|
||||||
@ -52,9 +51,19 @@ class OpenAuth(AuthValidation):
|
|||||||
try:
|
try:
|
||||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||||
telephone: str = payload.get("sub")
|
telephone: str = payload.get("sub")
|
||||||
if telephone is None:
|
exp: int = payload.get("exp")
|
||||||
|
is_refresh: bool = payload.get("is_refresh")
|
||||||
|
if telephone is None or is_refresh:
|
||||||
return None
|
return None
|
||||||
except JWTError:
|
# 计算当前时间 + 缓冲时间是否大于等于 JWT 过期时间
|
||||||
|
buffer_time = (datetime.now() + timedelta(minutes=settings.ACCESS_TOKEN_CACHE_MINUTES)).timestamp()
|
||||||
|
if buffer_time >= exp:
|
||||||
|
request.scope["refresh"] = True
|
||||||
|
else:
|
||||||
|
request.scope["refresh"] = False
|
||||||
|
except jwt.exceptions.InvalidSignatureError:
|
||||||
|
return None
|
||||||
|
except jwt.exceptions.ExpiredSignatureError:
|
||||||
return None
|
return None
|
||||||
return telephone
|
return telephone
|
||||||
|
|
||||||
@ -83,7 +92,7 @@ class OpenAuth(AuthValidation):
|
|||||||
"""
|
"""
|
||||||
每次调用依赖此类的接口会执行该方法
|
每次调用依赖此类的接口会执行该方法
|
||||||
"""
|
"""
|
||||||
telephone = self.validate_token(token, db)
|
telephone = self.validate_token(request, token)
|
||||||
if telephone:
|
if telephone:
|
||||||
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
|
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
|
||||||
return await self.validate_user(request, user, db)
|
return await self.validate_user(request, user, db)
|
||||||
@ -106,7 +115,9 @@ class AllUserAuth(AuthValidation):
|
|||||||
"""
|
"""
|
||||||
每次调用依赖此类的接口会执行该方法
|
每次调用依赖此类的接口会执行该方法
|
||||||
"""
|
"""
|
||||||
telephone = self.validate_token(token, db)
|
if not settings.OAUTH_ENABLE:
|
||||||
|
return Auth(db=db)
|
||||||
|
telephone = self.validate_token(request, token)
|
||||||
if isinstance(telephone, Auth):
|
if isinstance(telephone, Auth):
|
||||||
return telephone
|
return telephone
|
||||||
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
|
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
|
||||||
@ -136,7 +147,9 @@ class FullAdminAuth(AuthValidation):
|
|||||||
"""
|
"""
|
||||||
每次调用依赖此类的接口会执行该方法
|
每次调用依赖此类的接口会执行该方法
|
||||||
"""
|
"""
|
||||||
telephone = self.validate_token(token, db)
|
if not settings.OAUTH_ENABLE:
|
||||||
|
return Auth(db=db)
|
||||||
|
telephone = self.validate_token(request, token)
|
||||||
if isinstance(telephone, Auth):
|
if isinstance(telephone, Auth):
|
||||||
return telephone
|
return telephone
|
||||||
options = [joinedload(VadminUser.roles), joinedload("roles.menus")]
|
options = [joinedload(VadminUser.roles), joinedload("roles.menus")]
|
||||||
|
@ -20,21 +20,20 @@ PassLib 是一个用于处理哈希密码的很棒的 Python 包。它支持许
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from fastapi import APIRouter, Depends, Request
|
import jwt
|
||||||
|
from fastapi import APIRouter, Depends, Request, Body
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from core.database import db_getter
|
from core.database import db_getter
|
||||||
|
from utils import status
|
||||||
from utils.response import SuccessResponse, ErrorResponse
|
from utils.response import SuccessResponse, ErrorResponse
|
||||||
from application import settings
|
from application import settings
|
||||||
from utils.tools import generate_string
|
|
||||||
from .login_manage import LoginManage
|
from .login_manage import LoginManage
|
||||||
from .validation import LoginForm, WXLoginForm
|
from .validation import LoginForm, WXLoginForm
|
||||||
from apps.vadmin.record.models import VadminLoginRecord
|
from apps.vadmin.record.models import VadminLoginRecord
|
||||||
from apps.vadmin.auth.crud import MenuDal, UserDal
|
from apps.vadmin.auth.crud import MenuDal, UserDal
|
||||||
from apps.vadmin.auth.schemas import UserIn
|
|
||||||
from .current import FullAdminAuth
|
from .current import FullAdminAuth
|
||||||
from .validation.auth import Auth
|
from .validation.auth import Auth
|
||||||
from utils.wx.oauth import WXOAuth
|
from utils.wx.oauth import WXOAuth
|
||||||
from core.data_types import Telephone
|
|
||||||
|
|
||||||
app = APIRouter()
|
app = APIRouter()
|
||||||
|
|
||||||
@ -57,10 +56,12 @@ async def login_for_access_token(
|
|||||||
if not result.status:
|
if not result.status:
|
||||||
raise ValueError(result.msg)
|
raise ValueError(result.msg)
|
||||||
|
|
||||||
token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
access_token = LoginManage.create_token({"sub": result.user.telephone, "is_refresh": False})
|
||||||
token = LoginManage.create_access_token(data={"sub": result.user.telephone}, expires_delta=token_expires)
|
expires = timedelta(minutes=settings.REFRESH_TOKEN_EXPIRE_MINUTES)
|
||||||
|
refresh_token = LoginManage.create_token({"sub": result.user.telephone, "is_refresh": True}, expires=expires)
|
||||||
resp = {
|
resp = {
|
||||||
"access_token": token,
|
"access_token": access_token,
|
||||||
|
"refresh_token": refresh_token,
|
||||||
"token_type": "bearer",
|
"token_type": "bearer",
|
||||||
"is_reset_password": result.user.is_reset_password,
|
"is_reset_password": result.user.is_reset_password,
|
||||||
"is_wx_server_openid": result.user.is_wx_server_openid
|
"is_wx_server_openid": result.user.is_wx_server_openid
|
||||||
@ -95,10 +96,12 @@ async def wx_login_for_access_token(request: Request, data: WXLoginForm, db: Asy
|
|||||||
await user.update_login_info(db, request.client.host)
|
await user.update_login_info(db, request.client.host)
|
||||||
|
|
||||||
# 登录成功创建 token
|
# 登录成功创建 token
|
||||||
token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
access_token = LoginManage.create_token({"sub": user.telephone, "is_refresh": False})
|
||||||
token = LoginManage.create_access_token(data={"sub": user.telephone}, expires_delta=token_expires)
|
expires = timedelta(minutes=settings.REFRESH_TOKEN_EXPIRE_MINUTES)
|
||||||
|
refresh_token = LoginManage.create_token({"sub": user.telephone, "is_refresh": True}, expires=expires)
|
||||||
resp = {
|
resp = {
|
||||||
"access_token": token,
|
"access_token": access_token,
|
||||||
|
"refresh_token": refresh_token,
|
||||||
"token_type": "bearer",
|
"token_type": "bearer",
|
||||||
"is_reset_password": user.is_reset_password,
|
"is_reset_password": user.is_reset_password,
|
||||||
"is_wx_server_openid": user.is_wx_server_openid
|
"is_wx_server_openid": user.is_wx_server_openid
|
||||||
@ -110,3 +113,28 @@ async def wx_login_for_access_token(request: Request, data: WXLoginForm, db: Asy
|
|||||||
@app.get("/getMenuList/", summary="获取当前用户菜单树")
|
@app.get("/getMenuList/", summary="获取当前用户菜单树")
|
||||||
async def get_menu_list(auth: Auth = Depends(FullAdminAuth())):
|
async def get_menu_list(auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse(await MenuDal(auth.db).get_routers(auth.user))
|
return SuccessResponse(await MenuDal(auth.db).get_routers(auth.user))
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/token/refresh/", summary="刷新Token")
|
||||||
|
async def token_refresh(refresh: str = Body(..., title="刷新Token")):
|
||||||
|
error_code = status.HTTP_401_UNAUTHORIZED
|
||||||
|
try:
|
||||||
|
payload = jwt.decode(refresh, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||||
|
telephone: str = payload.get("sub")
|
||||||
|
is_refresh: bool = payload.get("is_refresh")
|
||||||
|
if telephone is None or not is_refresh:
|
||||||
|
return ErrorResponse("未认证,请您重新登录", code=error_code, status=error_code)
|
||||||
|
except jwt.exceptions.InvalidSignatureError:
|
||||||
|
return ErrorResponse("无效认证,请您重新登录", code=error_code, status=error_code)
|
||||||
|
except jwt.exceptions.ExpiredSignatureError:
|
||||||
|
return ErrorResponse("登录已超时,请您重新登录", code=error_code, status=error_code)
|
||||||
|
|
||||||
|
access_token = LoginManage.create_token({"sub": telephone, "is_refresh": False})
|
||||||
|
expires = timedelta(minutes=settings.REFRESH_TOKEN_EXPIRE_MINUTES)
|
||||||
|
refresh_token = LoginManage.create_token({"sub": telephone, "is_refresh": True}, expires=expires)
|
||||||
|
resp = {
|
||||||
|
"access_token": access_token,
|
||||||
|
"refresh_token": refresh_token,
|
||||||
|
"token_type": "bearer"
|
||||||
|
}
|
||||||
|
return SuccessResponse(resp)
|
||||||
|
@ -7,10 +7,9 @@
|
|||||||
# @desc : 简要说明
|
# @desc : 简要说明
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Optional
|
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from application import settings
|
from application import settings
|
||||||
from jose import jwt
|
import jwt
|
||||||
from apps.vadmin.auth import models
|
from apps.vadmin.auth import models
|
||||||
from .validation import LoginValidation, LoginForm, LoginResult
|
from .validation import LoginValidation, LoginForm, LoginResult
|
||||||
from utils.aliyun_sms import AliyunSMS
|
from utils.aliyun_sms import AliyunSMS
|
||||||
@ -44,15 +43,19 @@ class LoginManage:
|
|||||||
return LoginResult(status=False, msg="验证码错误")
|
return LoginResult(status=False, msg="验证码错误")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
|
def create_token(payload: dict, expires: timedelta = None):
|
||||||
"""
|
"""
|
||||||
创建一个生成新的访问令牌的工具函数。
|
创建一个生成新的访问令牌的工具函数。
|
||||||
|
|
||||||
|
pyjwt:https://github.com/jpadilla/pyjwt/blob/master/docs/usage.rst
|
||||||
|
jwt 博客:https://geek-docs.com/python/python-tutorial/j_python-jwt.html
|
||||||
|
|
||||||
|
#TODO 传入的时间为UTC时间datetime.datetime类型,但是在解码时获取到的是本机时间的时间戳
|
||||||
"""
|
"""
|
||||||
to_encode = data.copy()
|
if expires:
|
||||||
if expires_delta:
|
expire = datetime.utcnow() + expires
|
||||||
expire = datetime.utcnow() + expires_delta
|
|
||||||
else:
|
else:
|
||||||
expire = datetime.utcnow() + timedelta(minutes=60)
|
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||||
to_encode.update({"exp": expire})
|
payload.update({"exp": expire})
|
||||||
encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
encoded_jwt = jwt.encode(payload, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
|
||||||
return encoded_jwt
|
return encoded_jwt
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
# @File : auth.py
|
# @File : auth.py
|
||||||
# @IDE : PyCharm
|
# @IDE : PyCharm
|
||||||
# @desc : 用户凭证验证装饰器
|
# @desc : 用户凭证验证装饰器
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from jose import jwt, JWTError
|
import jwt
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from application import settings
|
from application import settings
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
@ -17,6 +17,7 @@ from utils import status
|
|||||||
|
|
||||||
class Auth(BaseModel):
|
class Auth(BaseModel):
|
||||||
user: models.VadminUser = None
|
user: models.VadminUser = None
|
||||||
|
refresh: bool = False
|
||||||
db: AsyncSession
|
db: AsyncSession
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
@ -29,22 +30,35 @@ class AuthValidation:
|
|||||||
用于用户每次调用接口时,验证用户提交的token是否正确,并从token中获取用户信息
|
用于用户每次调用接口时,验证用户提交的token是否正确,并从token中获取用户信息
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
error_code = status.HTTP_401_UNAUTHORIZED
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_token(cls, token: str, db: AsyncSession) -> str | Auth:
|
def validate_token(cls, request: Request, token: str) -> str:
|
||||||
"""
|
"""
|
||||||
验证用户 token
|
验证用户 token
|
||||||
"""
|
"""
|
||||||
if not settings.OAUTH_ENABLE:
|
|
||||||
return Auth(db=db)
|
|
||||||
if not token:
|
if not token:
|
||||||
raise CustomException(msg="请您先登录!", code=status.HTTP_ERROR)
|
raise CustomException(msg="请您先登录!", code=status.HTTP_ERROR)
|
||||||
try:
|
try:
|
||||||
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
|
||||||
telephone: str = payload.get("sub")
|
telephone: str = payload.get("sub")
|
||||||
if telephone is None:
|
exp: int = payload.get("exp")
|
||||||
raise CustomException(msg="认证已过期,请您重新登陆", code=status.HTTP_401_UNAUTHORIZED)
|
is_refresh: bool = payload.get("is_refresh")
|
||||||
except JWTError:
|
if telephone is None or is_refresh:
|
||||||
raise CustomException(msg="认证已过期,请您重新登陆", code=status.HTTP_401_UNAUTHORIZED)
|
raise CustomException(msg="未认证,请您重新登录", code=cls.error_code)
|
||||||
|
# 计算当前时间 + 缓冲时间是否大于等于 JWT 过期时间
|
||||||
|
buffer_time = (datetime.now() + timedelta(minutes=settings.ACCESS_TOKEN_CACHE_MINUTES)).timestamp()
|
||||||
|
# print("过期时间", exp, datetime.fromtimestamp(exp))
|
||||||
|
# print("当前时间", buffer_time, datetime.fromtimestamp(buffer_time))
|
||||||
|
# print("剩余时间", exp - buffer_time)
|
||||||
|
if buffer_time >= exp:
|
||||||
|
request.scope["refresh"] = True
|
||||||
|
else:
|
||||||
|
request.scope["refresh"] = False
|
||||||
|
except jwt.exceptions.InvalidSignatureError:
|
||||||
|
raise CustomException(msg="无效认证,请您重新登录", code=cls.error_code)
|
||||||
|
except jwt.exceptions.ExpiredSignatureError:
|
||||||
|
raise CustomException(msg="认证已过期,请您重新登录", code=cls.error_code)
|
||||||
return telephone
|
return telephone
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -53,12 +67,13 @@ class AuthValidation:
|
|||||||
验证用户信息
|
验证用户信息
|
||||||
"""
|
"""
|
||||||
if user is None:
|
if user is None:
|
||||||
raise CustomException(msg="认证已过期,请您重新登陆", code=status.HTTP_401_UNAUTHORIZED)
|
raise CustomException(msg="未认证,请您重新登陆", code=cls.error_code, status_code=cls.error_code)
|
||||||
elif not user.is_active:
|
elif not user.is_active:
|
||||||
raise CustomException(msg="用户已被冻结!", code=status.HTTP_403_FORBIDDEN)
|
raise CustomException(msg="用户已被冻结!", code=cls.error_code, status_code=cls.error_code)
|
||||||
request.scope["telephone"] = user.telephone
|
request.scope["telephone"] = user.telephone
|
||||||
try:
|
try:
|
||||||
request.scope["body"] = await request.body()
|
request.scope["body"] = await request.body()
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
request.scope["body"] = "获取失败"
|
request.scope["body"] = "获取失败"
|
||||||
return Auth(user=user, db=db)
|
refresh = request.scope.get("refresh", False)
|
||||||
|
return Auth(user=user, db=db, refresh=refresh)
|
||||||
|
@ -31,12 +31,12 @@ async def get_users(
|
|||||||
schema = schemas.UserOut
|
schema = schemas.UserOut
|
||||||
datas = await crud.UserDal(auth.db).get_datas(**params.dict(), v_options=options, v_schema=schema)
|
datas = await crud.UserDal(auth.db).get_datas(**params.dict(), v_options=options, v_schema=schema)
|
||||||
count = await crud.UserDal(auth.db).get_count(**params.to_count())
|
count = await crud.UserDal(auth.db).get_count(**params.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/users/", summary="创建用户")
|
@app.post("/users/", summary="创建用户")
|
||||||
async def create_user(data: schemas.UserIn, auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.create"]))):
|
async def create_user(data: schemas.UserIn, auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.create"]))):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).create_data(data=data))
|
return SuccessResponse(await crud.UserDal(auth.db).create_data(data=data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/users/", summary="批量删除用户", description="软删除,删除后清空所关联的角色")
|
@app.delete("/users/", summary="批量删除用户", description="软删除,删除后清空所关联的角色")
|
||||||
@ -46,7 +46,7 @@ async def delete_users(ids: IdList = Depends(), auth: Auth = Depends(FullAdminAu
|
|||||||
elif 1 in ids.ids:
|
elif 1 in ids.ids:
|
||||||
return ErrorResponse("不能删除超级管理员用户")
|
return ErrorResponse("不能删除超级管理员用户")
|
||||||
await crud.UserDal(auth.db).delete_datas(ids=ids.ids, v_soft=True, is_active=False)
|
await crud.UserDal(auth.db).delete_datas(ids=ids.ids, v_soft=True, is_active=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/users/{data_id}/", summary="更新用户信息")
|
@app.put("/users/{data_id}/", summary="更新用户信息")
|
||||||
@ -55,7 +55,7 @@ async def put_user(
|
|||||||
data: schemas.UserUpdate,
|
data: schemas.UserUpdate,
|
||||||
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.update"]))
|
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.update"]))
|
||||||
):
|
):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.UserDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/users/{data_id}/", summary="获取用户信息")
|
@app.get("/users/{data_id}/", summary="获取用户信息")
|
||||||
@ -66,29 +66,32 @@ async def get_user(
|
|||||||
model = models.VadminUser
|
model = models.VadminUser
|
||||||
options = [joinedload(model.roles)]
|
options = [joinedload(model.roles)]
|
||||||
schema = schemas.UserOut
|
schema = schemas.UserOut
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).get_data(data_id, options, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.UserDal(auth.db).get_data(data_id, options, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/user/current/reset/password/", summary="重置当前用户密码")
|
@app.post("/user/current/reset/password/", summary="重置当前用户密码")
|
||||||
async def user_current_reset_password(data: schemas.ResetPwd, auth: Auth = Depends(AllUserAuth())):
|
async def user_current_reset_password(data: schemas.ResetPwd, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).reset_current_password(auth.user, data))
|
return SuccessResponse(await crud.UserDal(auth.db).reset_current_password(auth.user, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/user/current/update/info/", summary="更新当前用户基本信息")
|
@app.post("/user/current/update/info/", summary="更新当前用户基本信息")
|
||||||
async def post_user_current_update_info(data: schemas.UserUpdateBaseInfo, auth: Auth = Depends(AllUserAuth())):
|
async def post_user_current_update_info(data: schemas.UserUpdateBaseInfo, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).update_current_info(auth.user, data))
|
return SuccessResponse(await crud.UserDal(auth.db).update_current_info(auth.user, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/user/current/update/avatar/", summary="更新当前用户头像")
|
@app.post("/user/current/update/avatar/", summary="更新当前用户头像")
|
||||||
async def post_user_current_update_avatar(file: UploadFile, auth: Auth = Depends(AllUserAuth())):
|
async def post_user_current_update_avatar(file: UploadFile, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).update_current_avatar(auth.user, file))
|
return SuccessResponse(await crud.UserDal(auth.db).update_current_avatar(auth.user, file), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/user/admin/current/info/", summary="获取当前管理员信息")
|
@app.get("/user/admin/current/info/", summary="获取当前管理员信息")
|
||||||
async def get_user_admin_current_info(auth: Auth = Depends(FullAdminAuth())):
|
async def get_user_admin_current_info(auth: Auth = Depends(FullAdminAuth())):
|
||||||
result = schemas.UserOut.from_orm(auth.user).dict()
|
result = schemas.UserOut.from_orm(auth.user).dict()
|
||||||
result["permissions"] = list(get_user_permissions(auth.user))
|
result["permissions"] = list(get_user_permissions(auth.user))
|
||||||
return SuccessResponse(result)
|
return SuccessResponse(result, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/user/export/query/list/to/excel/", summary="导出用户查询列表为excel")
|
@app.post("/user/export/query/list/to/excel/", summary="导出用户查询列表为excel")
|
||||||
@ -97,17 +100,17 @@ async def post_user_export_query_list(
|
|||||||
params: UserParams = Depends(),
|
params: UserParams = Depends(),
|
||||||
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.export"]))
|
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.export"]))
|
||||||
):
|
):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).export_query_list(header, params))
|
return SuccessResponse(await crud.UserDal(auth.db).export_query_list(header, params), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/user/download/import/template/", summary="下载最新批量导入用户模板")
|
@app.get("/user/download/import/template/", summary="下载最新批量导入用户模板")
|
||||||
async def get_user_download_new_import_template(auth: Auth = Depends(AllUserAuth())):
|
async def get_user_download_new_import_template(auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).download_import_template())
|
return SuccessResponse(await crud.UserDal(auth.db).download_import_template(), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/import/users/", summary="批量导入用户")
|
@app.post("/import/users/", summary="批量导入用户")
|
||||||
async def post_import_users(file: UploadFile, auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.import"]))):
|
async def post_import_users(file: UploadFile, auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.import"]))):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).import_users(file))
|
return SuccessResponse(await crud.UserDal(auth.db).import_users(file), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/users/init/password/send/sms/", summary="初始化所选用户密码并发送通知短信")
|
@app.post("/users/init/password/send/sms/", summary="初始化所选用户密码并发送通知短信")
|
||||||
@ -116,13 +119,16 @@ async def post_users_init_password(
|
|||||||
ids: IdList = Depends(),
|
ids: IdList = Depends(),
|
||||||
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.reset"]))
|
auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.reset"]))
|
||||||
):
|
):
|
||||||
return SuccessResponse(await crud.UserDal(auth.db).init_password_send_sms(ids.ids, request.app.state.redis))
|
return SuccessResponse(
|
||||||
|
await crud.UserDal(auth.db).init_password_send_sms(ids.ids, request.app.state.redis),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/users/wx/server/openid/", summary="更新当前用户服务端微信平台openid")
|
@app.put("/users/wx/server/openid/", summary="更新当前用户服务端微信平台openid")
|
||||||
async def put_user_wx_server_openid(request: Request, code: str, auth: Auth = Depends(AllUserAuth())):
|
async def put_user_wx_server_openid(request: Request, code: str, auth: Auth = Depends(AllUserAuth())):
|
||||||
result = await crud.UserDal(auth.db).update_wx_server_openid(code, auth.user, request.app.state.redis)
|
result = await crud.UserDal(auth.db).update_wx_server_openid(code, auth.user, request.app.state.redis)
|
||||||
return SuccessResponse(result)
|
return SuccessResponse(result, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
@ -135,12 +141,12 @@ async def get_roles(
|
|||||||
):
|
):
|
||||||
datas = await crud.RoleDal(auth.db).get_datas(**params.dict())
|
datas = await crud.RoleDal(auth.db).get_datas(**params.dict())
|
||||||
count = await crud.RoleDal(auth.db).get_count(**params.to_count())
|
count = await crud.RoleDal(auth.db).get_count(**params.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/roles/", summary="创建角色信息")
|
@app.post("/roles/", summary="创建角色信息")
|
||||||
async def create_role(role: schemas.RoleIn, auth: Auth = Depends(FullAdminAuth(permissions=["auth.role.create"]))):
|
async def create_role(role: schemas.RoleIn, auth: Auth = Depends(FullAdminAuth(permissions=["auth.role.create"]))):
|
||||||
return SuccessResponse(await crud.RoleDal(auth.db).create_data(data=role))
|
return SuccessResponse(await crud.RoleDal(auth.db).create_data(data=role), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/roles/", summary="批量删除角色", description="硬删除, 如果存在用户关联则无法删除")
|
@app.delete("/roles/", summary="批量删除角色", description="硬删除, 如果存在用户关联则无法删除")
|
||||||
@ -148,7 +154,7 @@ async def delete_roles(ids: IdList = Depends(), auth: Auth = Depends(FullAdminAu
|
|||||||
if 1 in ids.ids:
|
if 1 in ids.ids:
|
||||||
return ErrorResponse("不能删除管理员角色")
|
return ErrorResponse("不能删除管理员角色")
|
||||||
await crud.RoleDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
await crud.RoleDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/roles/{data_id}/", summary="更新角色信息")
|
@app.put("/roles/{data_id}/", summary="更新角色信息")
|
||||||
@ -159,12 +165,12 @@ async def put_role(
|
|||||||
):
|
):
|
||||||
if 1 == data_id:
|
if 1 == data_id:
|
||||||
return ErrorResponse("不能修改管理员角色")
|
return ErrorResponse("不能修改管理员角色")
|
||||||
return SuccessResponse(await crud.RoleDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.RoleDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/roles/options/", summary="获取角色选择项")
|
@app.get("/roles/options/", summary="获取角色选择项")
|
||||||
async def get_role_options(auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.create", "auth.user.update"]))):
|
async def get_role_options(auth: Auth = Depends(FullAdminAuth(permissions=["auth.user.create", "auth.user.update"]))):
|
||||||
return SuccessResponse(await crud.RoleDal(auth.db).get_select_datas())
|
return SuccessResponse(await crud.RoleDal(auth.db).get_select_datas(), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/roles/{data_id}/", summary="获取角色信息")
|
@app.get("/roles/{data_id}/", summary="获取角色信息")
|
||||||
@ -175,7 +181,10 @@ async def get_role(
|
|||||||
model = models.VadminRole
|
model = models.VadminRole
|
||||||
options = [joinedload(model.menus)]
|
options = [joinedload(model.menus)]
|
||||||
schema = schemas.RoleOut
|
schema = schemas.RoleOut
|
||||||
return SuccessResponse(await crud.RoleDal(auth.db).get_data(data_id, options, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.RoleDal(auth.db).get_data(data_id, options, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
@ -184,33 +193,33 @@ async def get_role(
|
|||||||
@app.get("/menus/", summary="获取菜单列表")
|
@app.get("/menus/", summary="获取菜单列表")
|
||||||
async def get_menus(auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.list"]))):
|
async def get_menus(auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.list"]))):
|
||||||
datas = await crud.MenuDal(auth.db).get_tree_list(mode=1)
|
datas = await crud.MenuDal(auth.db).get_tree_list(mode=1)
|
||||||
return SuccessResponse(datas)
|
return SuccessResponse(datas, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/menus/tree/options/", summary="获取菜单树选择项,添加/修改菜单时使用")
|
@app.get("/menus/tree/options/", summary="获取菜单树选择项,添加/修改菜单时使用")
|
||||||
async def get_menus_options(auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.create", "auth.menu.update"]))):
|
async def get_menus_options(auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.create", "auth.menu.update"]))):
|
||||||
datas = await crud.MenuDal(auth.db).get_tree_list(mode=2)
|
datas = await crud.MenuDal(auth.db).get_tree_list(mode=2)
|
||||||
return SuccessResponse(datas)
|
return SuccessResponse(datas, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/menus/role/tree/options/", summary="获取菜单列表树信息,角色权限使用")
|
@app.get("/menus/role/tree/options/", summary="获取菜单列表树信息,角色权限使用")
|
||||||
async def get_menus_treeselect(
|
async def get_menus_treeselect(
|
||||||
auth: Auth = Depends(FullAdminAuth(permissions=["auth.role.create", "auth.role.update"]))
|
auth: Auth = Depends(FullAdminAuth(permissions=["auth.role.create", "auth.role.update"]))
|
||||||
):
|
):
|
||||||
return SuccessResponse(await crud.MenuDal(auth.db).get_tree_list(mode=3))
|
return SuccessResponse(await crud.MenuDal(auth.db).get_tree_list(mode=3), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/menus/", summary="创建菜单信息")
|
@app.post("/menus/", summary="创建菜单信息")
|
||||||
async def create_menu(menu: schemas.Menu, auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.create"]))):
|
async def create_menu(menu: schemas.Menu, auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.create"]))):
|
||||||
if menu.parent_id:
|
if menu.parent_id:
|
||||||
menu.alwaysShow = False
|
menu.alwaysShow = False
|
||||||
return SuccessResponse(await crud.MenuDal(auth.db).create_data(data=menu))
|
return SuccessResponse(await crud.MenuDal(auth.db).create_data(data=menu), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/menus/", summary="批量删除菜单", description="硬删除, 如果存在角色关联则无法删除")
|
@app.delete("/menus/", summary="批量删除菜单", description="硬删除, 如果存在角色关联则无法删除")
|
||||||
async def delete_menus(ids: IdList = Depends(), auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.delete"]))):
|
async def delete_menus(ids: IdList = Depends(), auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.delete"]))):
|
||||||
await crud.MenuDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
await crud.MenuDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/menus/{data_id}/", summary="更新菜单信息")
|
@app.put("/menus/{data_id}/", summary="更新菜单信息")
|
||||||
@ -218,7 +227,7 @@ async def put_menus(
|
|||||||
data_id: int,
|
data_id: int,
|
||||||
data: schemas.Menu, auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.update"]))
|
data: schemas.Menu, auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.update"]))
|
||||||
):
|
):
|
||||||
return SuccessResponse(await crud.MenuDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.MenuDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/menus/{data_id}/", summary="获取菜单信息")
|
@app.get("/menus/{data_id}/", summary="获取菜单信息")
|
||||||
@ -227,7 +236,7 @@ async def put_menus(
|
|||||||
auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.view", "auth.menu.update"]))
|
auth: Auth = Depends(FullAdminAuth(permissions=["auth.menu.view", "auth.menu.update"]))
|
||||||
):
|
):
|
||||||
schema = schemas.MenuSimpleOut
|
schema = schemas.MenuSimpleOut
|
||||||
return SuccessResponse(await crud.MenuDal(auth.db).get_data(data_id, None, v_schema=schema))
|
return SuccessResponse(await crud.MenuDal(auth.db).get_data(data_id, None, v_schema=schema), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/role/menus/tree/{role_id}/", summary="获取菜单列表树信息以及角色菜单权限ID,角色权限使用")
|
@app.get("/role/menus/tree/{role_id}/", summary="获取菜单列表树信息以及角色菜单权限ID,角色权限使用")
|
||||||
@ -237,4 +246,4 @@ async def get_role_menu_tree(
|
|||||||
):
|
):
|
||||||
treeselect = await crud.MenuDal(auth.db).get_tree_list(mode=3)
|
treeselect = await crud.MenuDal(auth.db).get_tree_list(mode=3)
|
||||||
role_menu_tree = await crud.RoleDal(auth.db).get_role_menu_tree(role_id)
|
role_menu_tree = await crud.RoleDal(auth.db).get_role_menu_tree(role_id)
|
||||||
return SuccessResponse({"role_menu_tree": role_menu_tree, "menus": treeselect})
|
return SuccessResponse({"role_menu_tree": role_menu_tree, "menus": treeselect}, refresh=auth.refresh)
|
||||||
|
@ -29,36 +29,42 @@ async def get_issue_categorys(p: params.IssueCategoryParams = Depends(), auth: A
|
|||||||
schema = schemas.IssueCategoryListOut
|
schema = schemas.IssueCategoryListOut
|
||||||
datas = await crud.IssueCategoryDal(auth.db).get_datas(**p.dict(), v_options=options, v_schema=schema)
|
datas = await crud.IssueCategoryDal(auth.db).get_datas(**p.dict(), v_options=options, v_schema=schema)
|
||||||
count = await crud.IssueCategoryDal(auth.db).get_count(**p.to_count())
|
count = await crud.IssueCategoryDal(auth.db).get_count(**p.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/issue/categorys/options/", summary="获取类别选择项")
|
@app.get("/issue/categorys/options/", summary="获取类别选择项")
|
||||||
async def get_issue_categorys_options(auth: Auth = Depends(AllUserAuth())):
|
async def get_issue_categorys_options(auth: Auth = Depends(AllUserAuth())):
|
||||||
schema = schemas.IssueCategoryOptionsOut
|
schema = schemas.IssueCategoryOptionsOut
|
||||||
return SuccessResponse(await crud.IssueCategoryDal(auth.db).get_datas(limit=0, is_active=True, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.IssueCategoryDal(auth.db).get_datas(limit=0, is_active=True, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/issue/categorys/", summary="创建类别")
|
@app.post("/issue/categorys/", summary="创建类别")
|
||||||
async def create_issue_category(data: schemas.IssueCategory, auth: Auth = Depends(AllUserAuth())):
|
async def create_issue_category(data: schemas.IssueCategory, auth: Auth = Depends(AllUserAuth())):
|
||||||
data.user_id = auth.user.id
|
data.user_id = auth.user.id
|
||||||
return SuccessResponse(await crud.IssueCategoryDal(auth.db).create_data(data=data))
|
return SuccessResponse(await crud.IssueCategoryDal(auth.db).create_data(data=data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/issue/categorys/", summary="批量删除类别", description="硬删除")
|
@app.delete("/issue/categorys/", summary="批量删除类别", description="硬删除")
|
||||||
async def delete_issue_categorys(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def delete_issue_categorys(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
await crud.IssueCategoryDal(auth.db).delete_datas(ids=ids.ids, v_soft=False)
|
await crud.IssueCategoryDal(auth.db).delete_datas(ids=ids.ids, v_soft=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/issue/categorys/{data_id}/", summary="更新类别信息")
|
@app.put("/issue/categorys/{data_id}/", summary="更新类别信息")
|
||||||
async def put_issue_category(data_id: int, data: schemas.IssueCategory, auth: Auth = Depends(AllUserAuth())):
|
async def put_issue_category(data_id: int, data: schemas.IssueCategory, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.IssueCategoryDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.IssueCategoryDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/issue/categorys/{data_id}/", summary="获取类别信息")
|
@app.get("/issue/categorys/{data_id}/", summary="获取类别信息")
|
||||||
async def get_issue_category(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
async def get_issue_category(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
||||||
schema = schemas.IssueCategorySimpleOut
|
schema = schemas.IssueCategorySimpleOut
|
||||||
return SuccessResponse(await crud.IssueCategoryDal(auth.db).get_data(data_id, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.IssueCategoryDal(auth.db).get_data(data_id, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/issue/categorys/platform/{platform}/", summary="获取平台中的常见问题类别列表")
|
@app.get("/issue/categorys/platform/{platform}/", summary="获取平台中的常见问题类别列表")
|
||||||
@ -81,24 +87,24 @@ async def get_issues(p: params.IssueParams = Depends(), auth: Auth = Depends(All
|
|||||||
schema = schemas.IssueListOut
|
schema = schemas.IssueListOut
|
||||||
datas = await crud.IssueDal(auth.db).get_datas(**p.dict(), v_options=options, v_schema=schema)
|
datas = await crud.IssueDal(auth.db).get_datas(**p.dict(), v_options=options, v_schema=schema)
|
||||||
count = await crud.IssueDal(auth.db).get_count(**p.to_count())
|
count = await crud.IssueDal(auth.db).get_count(**p.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/issues/", summary="创建问题")
|
@app.post("/issues/", summary="创建问题")
|
||||||
async def create_issue(data: schemas.Issue, auth: Auth = Depends(AllUserAuth())):
|
async def create_issue(data: schemas.Issue, auth: Auth = Depends(AllUserAuth())):
|
||||||
data.user_id = auth.user.id
|
data.user_id = auth.user.id
|
||||||
return SuccessResponse(await crud.IssueDal(auth.db).create_data(data=data))
|
return SuccessResponse(await crud.IssueDal(auth.db).create_data(data=data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/issues/", summary="批量删除问题", description="硬删除")
|
@app.delete("/issues/", summary="批量删除问题", description="硬删除")
|
||||||
async def delete_issues(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def delete_issues(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
await crud.IssueDal(auth.db).delete_datas(ids=ids.ids, v_soft=False)
|
await crud.IssueDal(auth.db).delete_datas(ids=ids.ids, v_soft=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/issues/{data_id}/", summary="更新问题信息")
|
@app.put("/issues/{data_id}/", summary="更新问题信息")
|
||||||
async def put_issue(data_id: int, data: schemas.Issue, auth: Auth = Depends(AllUserAuth())):
|
async def put_issue(data_id: int, data: schemas.Issue, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.IssueDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.IssueDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/issues/{data_id}/", summary="获取问题信息")
|
@app.get("/issues/{data_id}/", summary="获取问题信息")
|
||||||
|
@ -23,7 +23,7 @@ app = APIRouter()
|
|||||||
async def get_record_login(p: LoginParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def get_record_login(p: LoginParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
datas = await crud.LoginRecordDal(auth.db).get_datas(**p.dict())
|
datas = await crud.LoginRecordDal(auth.db).get_datas(**p.dict())
|
||||||
count = await crud.LoginRecordDal(auth.db).get_count(**p.to_count())
|
count = await crud.LoginRecordDal(auth.db).get_count(**p.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/operations/", summary="获取操作日志列表")
|
@app.get("/operations/", summary="获取操作日志列表")
|
||||||
@ -31,14 +31,14 @@ async def get_record_operation(p: OperationParams = Depends(), db: DatabaseManag
|
|||||||
auth: Auth = Depends(AllUserAuth())):
|
auth: Auth = Depends(AllUserAuth())):
|
||||||
count = await db.get_count("operation_record", **p.to_count())
|
count = await db.get_count("operation_record", **p.to_count())
|
||||||
datas = await db.get_datas("operation_record", v_schema=schemas.OpertionRecordSimpleOut, **p.dict())
|
datas = await db.get_datas("operation_record", v_schema=schemas.OpertionRecordSimpleOut, **p.dict())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/sms/send/list/", summary="获取短信发送列表")
|
@app.get("/sms/send/list/", summary="获取短信发送列表")
|
||||||
async def get_sms_send_list(p: SMSParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def get_sms_send_list(p: SMSParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
datas = await crud.SMSSendRecordDal(auth.db).get_datas(**p.dict())
|
datas = await crud.SMSSendRecordDal(auth.db).get_datas(**p.dict())
|
||||||
count = await crud.SMSSendRecordDal(auth.db).get_count(**p.to_count())
|
count = await crud.SMSSendRecordDal(auth.db).get_count(**p.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
@ -46,4 +46,4 @@ async def get_sms_send_list(p: SMSParams = Depends(), auth: Auth = Depends(AllUs
|
|||||||
###########################################################
|
###########################################################
|
||||||
@app.get("/analysis/user/login/distribute/", summary="获取用户登录分布情况列表")
|
@app.get("/analysis/user/login/distribute/", summary="获取用户登录分布情况列表")
|
||||||
async def get_user_login_distribute(auth: Auth = Depends(AllUserAuth())):
|
async def get_user_login_distribute(auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.LoginRecordDal(auth.db).get_user_distribute())
|
return SuccessResponse(await crud.LoginRecordDal(auth.db).get_user_distribute(), refresh=auth.refresh)
|
||||||
|
@ -31,18 +31,18 @@ app = APIRouter()
|
|||||||
async def get_dict_types(p: DictTypeParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def get_dict_types(p: DictTypeParams = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
datas = await crud.DictTypeDal(auth.db).get_datas(**p.dict())
|
datas = await crud.DictTypeDal(auth.db).get_datas(**p.dict())
|
||||||
count = await crud.DictTypeDal(auth.db).get_count(**p.to_count())
|
count = await crud.DictTypeDal(auth.db).get_count(**p.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/dict/types/", summary="创建字典类型")
|
@app.post("/dict/types/", summary="创建字典类型")
|
||||||
async def create_dict_types(data: schemas.DictType, auth: Auth = Depends(AllUserAuth())):
|
async def create_dict_types(data: schemas.DictType, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.DictTypeDal(auth.db).create_data(data=data))
|
return SuccessResponse(await crud.DictTypeDal(auth.db).create_data(data=data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/dict/types/", summary="批量删除字典类型")
|
@app.delete("/dict/types/", summary="批量删除字典类型")
|
||||||
async def delete_dict_types(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def delete_dict_types(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
await crud.DictTypeDal(auth.db).delete_datas(ids=ids.ids)
|
await crud.DictTypeDal(auth.db).delete_datas(ids=ids.ids)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/dict/types/details/", summary="获取多个字典类型下的字典元素列表")
|
@app.post("/dict/types/details/", summary="获取多个字典类型下的字典元素列表")
|
||||||
@ -51,23 +51,26 @@ async def post_dicts_details(
|
|||||||
dict_types: List[str] = Body(None, title="字典元素列表", description="查询字典元素列表")
|
dict_types: List[str] = Body(None, title="字典元素列表", description="查询字典元素列表")
|
||||||
):
|
):
|
||||||
datas = await crud.DictTypeDal(auth.db).get_dicts_details(dict_types)
|
datas = await crud.DictTypeDal(auth.db).get_dicts_details(dict_types)
|
||||||
return SuccessResponse(datas)
|
return SuccessResponse(datas, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/dict/types/options/", summary="获取字典类型选择项")
|
@app.get("/dict/types/options/", summary="获取字典类型选择项")
|
||||||
async def get_dicts_options(auth: Auth = Depends(AllUserAuth())):
|
async def get_dicts_options(auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.DictTypeDal(auth.db).get_select_datas())
|
return SuccessResponse(await crud.DictTypeDal(auth.db).get_select_datas(), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/dict/types/{data_id}/", summary="更新字典类型")
|
@app.put("/dict/types/{data_id}/", summary="更新字典类型")
|
||||||
async def put_dict_types(data_id: int, data: schemas.DictType, auth: Auth = Depends(AllUserAuth())):
|
async def put_dict_types(data_id: int, data: schemas.DictType, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.DictTypeDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.DictTypeDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/dict/types/{data_id}/", summary="获取字典类型详细")
|
@app.get("/dict/types/{data_id}/", summary="获取字典类型详细")
|
||||||
async def get_dict_type(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
async def get_dict_type(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
||||||
schema = schemas.DictTypeSimpleOut
|
schema = schemas.DictTypeSimpleOut
|
||||||
return SuccessResponse(await crud.DictTypeDal(auth.db).get_data(data_id, None, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.DictTypeDal(auth.db).get_data(data_id, None, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
@ -75,7 +78,7 @@ async def get_dict_type(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
|||||||
###########################################################
|
###########################################################
|
||||||
@app.post("/dict/details/", summary="创建字典元素")
|
@app.post("/dict/details/", summary="创建字典元素")
|
||||||
async def create_dict_details(data: schemas.DictDetails, auth: Auth = Depends(AllUserAuth())):
|
async def create_dict_details(data: schemas.DictDetails, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.DictDetailsDal(auth.db).create_data(data=data))
|
return SuccessResponse(await crud.DictDetailsDal(auth.db).create_data(data=data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/dict/details/", summary="获取单个字典类型下的字典元素列表,分页")
|
@app.get("/dict/details/", summary="获取单个字典类型下的字典元素列表,分页")
|
||||||
@ -84,24 +87,27 @@ async def get_dict_details(params: DictDetailParams = Depends(), auth: Auth = De
|
|||||||
return ErrorResponse(msg="未获取到字典类型!")
|
return ErrorResponse(msg="未获取到字典类型!")
|
||||||
datas = await crud.DictDetailsDal(auth.db).get_datas(**params.dict())
|
datas = await crud.DictDetailsDal(auth.db).get_datas(**params.dict())
|
||||||
count = await crud.DictDetailsDal(auth.db).get_count(**params.to_count())
|
count = await crud.DictDetailsDal(auth.db).get_count(**params.to_count())
|
||||||
return SuccessResponse(datas, count=count)
|
return SuccessResponse(datas, count=count, refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.delete("/dict/details/", summary="批量删除字典元素", description="硬删除")
|
@app.delete("/dict/details/", summary="批量删除字典元素", description="硬删除")
|
||||||
async def delete_dict_details(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
async def delete_dict_details(ids: IdList = Depends(), auth: Auth = Depends(AllUserAuth())):
|
||||||
await crud.DictDetailsDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
await crud.DictDetailsDal(auth.db).delete_datas(ids.ids, v_soft=False)
|
||||||
return SuccessResponse("删除成功")
|
return SuccessResponse("删除成功", refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/dict/details/{data_id}/", summary="更新字典元素")
|
@app.put("/dict/details/{data_id}/", summary="更新字典元素")
|
||||||
async def put_dict_details(data_id: int, data: schemas.DictDetails, auth: Auth = Depends(AllUserAuth())):
|
async def put_dict_details(data_id: int, data: schemas.DictDetails, auth: Auth = Depends(AllUserAuth())):
|
||||||
return SuccessResponse(await crud.DictDetailsDal(auth.db).put_data(data_id, data))
|
return SuccessResponse(await crud.DictDetailsDal(auth.db).put_data(data_id, data), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/dict/details/{data_id}/", summary="获取字典元素详情")
|
@app.get("/dict/details/{data_id}/", summary="获取字典元素详情")
|
||||||
async def get_dict_detail(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
async def get_dict_detail(data_id: int, auth: Auth = Depends(AllUserAuth())):
|
||||||
schema = schemas.DictDetailsSimpleOut
|
schema = schemas.DictDetailsSimpleOut
|
||||||
return SuccessResponse(await crud.DictDetailsDal(auth.db).get_data(data_id, None, v_schema=schema))
|
return SuccessResponse(
|
||||||
|
await crud.DictDetailsDal(auth.db).get_data(data_id, None, v_schema=schema),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
###########################################################
|
###########################################################
|
||||||
@ -136,17 +142,23 @@ async def sms_send(request: Request, telephone: str):
|
|||||||
###########################################################
|
###########################################################
|
||||||
@app.get("/settings/tabs/", summary="获取系统配置标签列表")
|
@app.get("/settings/tabs/", summary="获取系统配置标签列表")
|
||||||
async def get_settings_tabs(classify: str, auth: Auth = Depends(FullAdminAuth())):
|
async def get_settings_tabs(classify: str, auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse(await crud.SettingsTabDal(auth.db).get_datas(limit=0, classify=classify))
|
return SuccessResponse(
|
||||||
|
await crud.SettingsTabDal(auth.db).get_datas(limit=0, classify=classify),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/settings/tabs/values/", summary="获取系统配置标签下的信息")
|
@app.get("/settings/tabs/values/", summary="获取系统配置标签下的信息")
|
||||||
async def get_settings_tabs_values(tab_id: int, auth: Auth = Depends(FullAdminAuth())):
|
async def get_settings_tabs_values(tab_id: int, auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse(await crud.SettingsDal(auth.db).get_tab_values(tab_id=tab_id))
|
return SuccessResponse(await crud.SettingsDal(auth.db).get_tab_values(tab_id=tab_id), refresh=auth.refresh)
|
||||||
|
|
||||||
|
|
||||||
@app.put("/settings/tabs/values/", summary="更新系统配置信息")
|
@app.put("/settings/tabs/values/", summary="更新系统配置信息")
|
||||||
async def put_settings_tabs_values(request: Request, datas: dict = Body(...), auth: Auth = Depends(FullAdminAuth())):
|
async def put_settings_tabs_values(request: Request, datas: dict = Body(...), auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse(await crud.SettingsDal(auth.db).update_datas(datas, request.app.state.redis))
|
return SuccessResponse(
|
||||||
|
await crud.SettingsDal(auth.db).update_datas(datas, request.app.state.redis),
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/settings/base/config/", summary="获取系统基础配置", description="每次进入系统中时使用")
|
@app.get("/settings/base/config/", summary="获取系统基础配置", description="每次进入系统中时使用")
|
||||||
@ -156,9 +168,15 @@ async def get_setting_base_config(db: AsyncSession = Depends(db_getter)):
|
|||||||
|
|
||||||
@app.get("/settings/privacy/", summary="获取隐私协议")
|
@app.get("/settings/privacy/", summary="获取隐私协议")
|
||||||
async def get_settings_privacy(auth: Auth = Depends(FullAdminAuth())):
|
async def get_settings_privacy(auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_privacy")).config_value)
|
return SuccessResponse(
|
||||||
|
(await crud.SettingsDal(auth.db).get_data(config_key="web_privacy")).config_value,
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/settings/agreement/", summary="获取用户协议")
|
@app.get("/settings/agreement/", summary="获取用户协议")
|
||||||
async def get_settings_agreement(auth: Auth = Depends(FullAdminAuth())):
|
async def get_settings_agreement(auth: Auth = Depends(FullAdminAuth())):
|
||||||
return SuccessResponse((await crud.SettingsDal(auth.db).get_data(config_key="web_agreement")).config_value)
|
return SuccessResponse(
|
||||||
|
(await crud.SettingsDal(auth.db).get_data(config_key="web_agreement")).config_value,
|
||||||
|
refresh=auth.refresh
|
||||||
|
)
|
||||||
|
@ -21,6 +21,30 @@ def register_redis(app: FastAPI) -> None:
|
|||||||
博客:https://blog.csdn.net/wgPython/article/details/107668521
|
博客:https://blog.csdn.net/wgPython/article/details/107668521
|
||||||
博客:https://www.cnblogs.com/emunshe/p/15761597.html
|
博客:https://www.cnblogs.com/emunshe/p/15761597.html
|
||||||
官网:https://aioredis.readthedocs.io/en/latest/getting-started/
|
官网:https://aioredis.readthedocs.io/en/latest/getting-started/
|
||||||
|
Github: https://github.com/aio-libs/aioredis-py
|
||||||
|
|
||||||
|
aioredis.from_url(url, *, encoding=None, parser=None, decode_responses=False, db=None, password=None, ssl=None,
|
||||||
|
connection_cls=None, loop=None, **kwargs) 方法是 aioredis 库中用于从 Redis 连接 URL 创建 Redis 连接对象的方法。
|
||||||
|
|
||||||
|
以下是该方法的参数说明:
|
||||||
|
url:Redis 连接 URL。例如 redis://localhost:6379/0。
|
||||||
|
encoding:可选参数,Redis 编码格式。默认为 utf-8。
|
||||||
|
parser:可选参数,Redis 数据解析器。默认为 None,表示使用默认解析器。
|
||||||
|
decode_responses:可选参数,是否将 Redis 响应解码为 Python 字符串。默认为 False。
|
||||||
|
db:可选参数,Redis 数据库编号。默认为 None。
|
||||||
|
password:可选参数,Redis 认证密码。默认为 None,表示无需认证。
|
||||||
|
ssl:可选参数,是否使用 SSL/TLS 加密连接。默认为 None。
|
||||||
|
connection_cls:可选参数,Redis 连接类。默认为 None,表示使用默认连接类。
|
||||||
|
loop:可选参数,用于创建连接对象的事件循环。默认为 None,表示使用默认事件循环。
|
||||||
|
**kwargs:可选参数,其他连接参数,用于传递给 Redis 连接类的构造函数。
|
||||||
|
|
||||||
|
aioredis.from_url() 方法的主要作用是将 Redis 连接 URL 转换为 Redis 连接对象。
|
||||||
|
除了 URL 参数外,其他参数用于指定 Redis 连接的各种选项,例如 Redis 数据库编号、密码、SSL/TLS 加密等等。可以根据需要选择使用这些选项。
|
||||||
|
|
||||||
|
health_check_interval 是 aioredis.from_url() 方法中的一个可选参数,用于设置 Redis 连接的健康检查间隔时间。
|
||||||
|
健康检查是指在 Redis 连接池中使用的连接对象会定期向 Redis 服务器发送 PING 命令来检查连接是否仍然有效。
|
||||||
|
该参数的默认值是 0,表示不进行健康检查。如果需要启用健康检查,则可以将该参数设置为一个正整数,表示检查间隔的秒数。
|
||||||
|
例如,如果需要每隔 5 秒对 Redis 连接进行一次健康检查,则可以将 health_check_interval 设置为 5
|
||||||
:param app:
|
:param app:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
@ -16,9 +16,10 @@ from core.logger import logger
|
|||||||
|
|
||||||
|
|
||||||
class CustomException(Exception):
|
class CustomException(Exception):
|
||||||
def __init__(self, msg: str, code: int):
|
def __init__(self, msg: str, code: int, status_code: int = status.HTTP_200_OK):
|
||||||
self.msg = msg
|
self.msg = msg
|
||||||
self.code = code
|
self.code = code
|
||||||
|
self.status_code = status_code
|
||||||
|
|
||||||
|
|
||||||
def register_exception(app: FastAPI):
|
def register_exception(app: FastAPI):
|
||||||
|
Binary file not shown.
37
kinit-uni/.eslintrc.js
Normal file
37
kinit-uni/.eslintrc.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es6: true,
|
||||||
|
node: true
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:vue/recommended',
|
||||||
|
'prettier',
|
||||||
|
'plugin:prettier/recommended'
|
||||||
|
],
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: 'module'
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
uni: true,
|
||||||
|
wx: true,
|
||||||
|
ROUTES: true
|
||||||
|
},
|
||||||
|
plugins: ['vue', 'prettier'],
|
||||||
|
rules: {
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
'prettier/prettier': 'error',
|
||||||
|
'vue/html-indent': ['error', 2],
|
||||||
|
'vue/max-attributes-per-line': 'off',
|
||||||
|
'no-console': 'off',
|
||||||
|
'no-unused-vars': ['warn', { args: 'none' }],
|
||||||
|
'arrow-parens': ['error', 'always'],
|
||||||
|
'comma-dangle': ['error', 'never'],
|
||||||
|
quotes: ['error', 'single'],
|
||||||
|
semi: ['error', 'never'],
|
||||||
|
'object-curly-spacing': ['error', 'always'],
|
||||||
|
indent: ['error', 2, { SwitchCase: 1 }]
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import config from './config'
|
export default {
|
||||||
import { getToken } from '@/common/utils/auth'
|
onLaunch: function () {
|
||||||
|
|
||||||
export default {
|
|
||||||
onLaunch: function() {
|
|
||||||
this.initApp()
|
this.initApp()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -13,9 +10,9 @@
|
|||||||
this.$store.dispatch('app/InitConfig')
|
this.$store.dispatch('app/InitConfig')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '@/static/scss/index.scss';
|
@import '@/static/scss/index.scss';
|
||||||
</style>
|
</style>
|
||||||
|
@ -47,3 +47,23 @@ RuoYi App 移动解决方案,采用uniapp框架,一份代码多终端适配
|
|||||||
- 文档地址:https://uviewui.com
|
- 文档地址:https://uviewui.com
|
||||||
|
|
||||||
uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
|
uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
|
||||||
|
|
||||||
|
## 开发工具
|
||||||
|
|
||||||
|
在此项目中我将开发`uni-app`的开发工具从 Hbuilder X 换到了 VSCode,没有谁好谁坏,只是本人更习惯使用 VSCode,但是在运行项目时依然使用的是 Hbuilder X,VSCode只是用来编写代码。当然使用 Hbuilder X 也是支持的,只做一个分享。
|
||||||
|
|
||||||
|
以下是我在VSCode中安装的几个插件:
|
||||||
|
|
||||||
|
1. 名称: Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code
|
||||||
|
2. 名称: ESLint
|
||||||
|
3. 名称: Image preview
|
||||||
|
4. 名称: Markdown Preview Enhanced
|
||||||
|
5. 名称: Path Intellisense
|
||||||
|
6. 名称: Prettier - Code formatter
|
||||||
|
7. 名称: Sass (.sass only)
|
||||||
|
8. 名称: SCSS IntelliSense
|
||||||
|
9. 名称: Stylelint
|
||||||
|
10. 名称: uni-app-schemas
|
||||||
|
11. 名称: uni-app-snippets
|
||||||
|
12. 名称: uni-create-view
|
||||||
|
13. 名称: Vetur
|
||||||
|
@ -9,57 +9,56 @@ import { toast } from '@/common/utils/common'
|
|||||||
|
|
||||||
export const wxLoginMixins = {
|
export const wxLoginMixins = {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters(['isUserOpenid'])
|
||||||
'isUserOpenid',
|
|
||||||
])
|
|
||||||
},
|
},
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onGetPhoneNumber(e) {
|
onGetPhoneNumber(e) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// 获取手机号官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
|
// 获取手机号官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
|
||||||
if (e.detail.errMsg === "getPhoneNumber:fail user deny") {
|
if (e.detail.errMsg === 'getPhoneNumber:fail user deny') {
|
||||||
// 用户拒绝授权
|
// 用户拒绝授权
|
||||||
toast("已取消授权")
|
toast('已取消授权')
|
||||||
reject("已取消授权")
|
reject('已取消授权')
|
||||||
} else if (e.detail.errMsg === "getPhoneNumber:fail no permission") {
|
} else if (e.detail.errMsg === 'getPhoneNumber:fail no permission') {
|
||||||
// 微信公众平台未认证或未使用企业认证
|
// 微信公众平台未认证或未使用企业认证
|
||||||
toast("微信公众平台未认证或未使用企业认证")
|
toast('微信公众平台未认证或未使用企业认证')
|
||||||
reject("微信公众平台未认证或未使用企业认证")
|
reject('微信公众平台未认证或未使用企业认证')
|
||||||
} else if (e.detail.errMsg === "getPhoneNumber:ok") {
|
} else if (e.detail.errMsg === 'getPhoneNumber:ok') {
|
||||||
// code换取用户手机号。 每个code只能使用一次,code的有效期为5min
|
// code换取用户手机号。 每个code只能使用一次,code的有效期为5min
|
||||||
this.$store.dispatch('auth/wxLogin', e.detail.code).then(res => {
|
this.$store.dispatch('auth/wxLogin', e.detail.code).then((res) => {
|
||||||
this.setOpenid();
|
this.setOpenid()
|
||||||
this.$store.dispatch('auth/GetInfo').then(result => {
|
this.$store.dispatch('auth/GetInfo').then((result) => {
|
||||||
resolve(result)
|
resolve(result)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
toast("授权失败")
|
toast('授权失败')
|
||||||
reject("授权失败")
|
reject('授权失败')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setOpenid() {
|
setOpenid() {
|
||||||
let self = this;
|
let self = this
|
||||||
// uniapp 官方文档:https://uniapp.dcloud.io/api/plugins/login.html#login
|
// uniapp 官方文档:https://uniapp.dcloud.io/api/plugins/login.html#login
|
||||||
if (self.isUserOpenid) { return; };
|
if (self.isUserOpenid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
uni.login({
|
uni.login({
|
||||||
provider: 'weixin',
|
provider: 'weixin',
|
||||||
success: function (loginRes) {
|
success: function (loginRes) {
|
||||||
if (loginRes.code) {
|
if (loginRes.code) {
|
||||||
setUserOpenid(loginRes.code).then(res => {
|
setUserOpenid(loginRes.code).then(() => {
|
||||||
// console.log("更新openid成功", res)
|
// console.log("更新openid成功", res)
|
||||||
self.$store.commit("auth/SET_IS_USER_OPENID", true);
|
self.$store.commit('auth/SET_IS_USER_OPENID', true)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('登录失败!获取code失败!' + res.errMsg)
|
console.log('登录失败!获取code失败!' + loginRes.errMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,36 +2,36 @@ export const wxShareMixins = {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
share: {
|
share: {
|
||||||
title: "",
|
title: '',
|
||||||
path: "",
|
path: '',
|
||||||
imageUrl: ""
|
imageUrl: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad: function() {
|
onLoad: function () {
|
||||||
wx.showShareMenu({
|
wx.showShareMenu({
|
||||||
withShareTicket: true,
|
withShareTicket: true,
|
||||||
menus: ["shareAppMessage", "shareTimeline"]
|
menus: ['shareAppMessage', 'shareTimeline']
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onShareAppMessage(res) {
|
onShareAppMessage(res) {
|
||||||
let that = this;
|
let that = this
|
||||||
let imageUrl = that.share.imageUrl || '';
|
let imageUrl = that.share.imageUrl || ''
|
||||||
if (res.from === 'button') {
|
if (res.from === 'button') {
|
||||||
//这块需要传参,不然链接地址进去获取不到数据
|
//这块需要传参,不然链接地址进去获取不到数据
|
||||||
let path = `/` + that.$scope.route + `?item=` + that.$scope.options.item;
|
let path = '/' + that.$scope.route + '?item=' + that.$scope.options.item
|
||||||
return {
|
return {
|
||||||
title: '商品分享~',
|
title: '商品分享~',
|
||||||
path: path,
|
path: path,
|
||||||
imageUrl: imageUrl
|
imageUrl: imageUrl
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
if (res.from === 'menu') {
|
if (res.from === 'menu') {
|
||||||
return {
|
return {
|
||||||
title: that.share.title,
|
title: that.share.title,
|
||||||
path: that.share.path,
|
path: that.share.path,
|
||||||
imageUrl: that.share.imageUrl
|
imageUrl: that.share.imageUrl
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 分享到朋友圈
|
// 分享到朋友圈
|
||||||
@ -40,7 +40,7 @@ export const wxShareMixins = {
|
|||||||
title: this.share.title,
|
title: this.share.title,
|
||||||
path: this.share.path,
|
path: this.share.path,
|
||||||
imageUrl: this.share.imageUrl
|
imageUrl: this.share.imageUrl
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
methods: {}
|
methods: {}
|
||||||
}
|
}
|
@ -8,18 +8,18 @@ export function login(telephone, password) {
|
|||||||
method: '0',
|
method: '0',
|
||||||
platform: '1'
|
platform: '1'
|
||||||
}
|
}
|
||||||
return request.post(`/auth/login/`, data)
|
return request.post('/auth/login/', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户详细信息
|
// 获取用户详细信息
|
||||||
export function getInfo() {
|
export function getInfo() {
|
||||||
return request.get(`/vadmin/auth/user/admin/current/info/`)
|
return request.get('/vadmin/auth/user/admin/current/info/')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新用户openid
|
// 更新用户openid
|
||||||
export function setUserOpenid(code) {
|
export function setUserOpenid(code) {
|
||||||
const params = {code}
|
const params = { code }
|
||||||
return request.put(`/vadmin/auth/users/wx/server/openid/`, {}, {params: params})
|
return request.put('/vadmin/auth/users/wx/server/openid/', {}, { params: params })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用微信一键登录
|
// 使用微信一键登录
|
||||||
@ -29,5 +29,5 @@ export function wxCodeLogin(code) {
|
|||||||
method: '2',
|
method: '2',
|
||||||
platform: '1'
|
platform: '1'
|
||||||
}
|
}
|
||||||
return request.post(`/auth/wx/login/`, data)
|
return request.post('/auth/wx/login/', data)
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,18 @@ import request from '@/common/request/request'
|
|||||||
|
|
||||||
// 更新当前用户基本信息
|
// 更新当前用户基本信息
|
||||||
export function updateCurrentUser(data) {
|
export function updateCurrentUser(data) {
|
||||||
return request.post(`/vadmin/auth/user/current/update/info/`, data)
|
return request.post('/vadmin/auth/user/current/update/info/', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置当前用户密码
|
// 重置当前用户密码
|
||||||
export function postCurrentUserResetPassword(data) {
|
export function postCurrentUserResetPassword(data) {
|
||||||
return request.post(`/vadmin/auth/user/current/reset/password/`, data)
|
return request.post('/vadmin/auth/user/current/reset/password/', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新当前用户头像
|
// 更新当前用户头像
|
||||||
export function postCurrentUserUploadAvatar(filePath) {
|
export function postCurrentUserUploadAvatar(filePath) {
|
||||||
return request.upload(`/vadmin/auth/user/current/update/avatar/`, {filePath: filePath, name: 'file'})
|
return request.upload('/vadmin/auth/user/current/update/avatar/', {
|
||||||
|
filePath: filePath,
|
||||||
|
name: 'file'
|
||||||
|
})
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ import request from '@/common/request/request.js'
|
|||||||
|
|
||||||
// 获取平台中的常见问题类别列表
|
// 获取平台中的常见问题类别列表
|
||||||
export function getIssueCategoryList() {
|
export function getIssueCategoryList() {
|
||||||
return request.get(`/vadmin/help/issue/categorys/platform/1/`)
|
return request.get('/vadmin/help/issue/categorys/platform/1/')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取问题详情
|
// 获取问题详情
|
||||||
|
@ -2,5 +2,5 @@ import request from '@/common/request/request.js'
|
|||||||
|
|
||||||
// 获取多个字典类型下的字典元素列表
|
// 获取多个字典类型下的字典元素列表
|
||||||
export function getDictTypeDetailsApi(data) {
|
export function getDictTypeDetailsApi(data) {
|
||||||
return request.post(`/vadmin/system/dict/types/details/`, data)
|
return request.post('/vadmin/system/dict/types/details/', data)
|
||||||
}
|
}
|
||||||
|
@ -2,5 +2,5 @@ import request from '@/common/request/request'
|
|||||||
|
|
||||||
// 获取系统基本配置
|
// 获取系统基本配置
|
||||||
export function getSystemBaseConfigApi() {
|
export function getSystemBaseConfigApi() {
|
||||||
return request.get(`/vadmin/system/settings/base/config/`)
|
return request.get('/vadmin/system/settings/base/config/')
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
export default {
|
export default {
|
||||||
"401": "认证失败,无法访问系统资源",
|
401: '认证失败,无法访问系统资源',
|
||||||
"403": "当前操作没有权限",
|
403: '当前操作没有权限',
|
||||||
"404": "访问资源不存在",
|
404: '访问资源不存在',
|
||||||
"default": "系统未知错误,请反馈给管理员"
|
default: '系统未知错误,请反馈给管理员'
|
||||||
};
|
}
|
||||||
|
@ -1,78 +1,127 @@
|
|||||||
import luchRequest from '@/components/luch-request' // 使用npm
|
import luchRequest from '@/components/luch-request' // 使用npm
|
||||||
import config from '@/config.js';
|
import config from '@/config.js'
|
||||||
import errorCode from "@/common/request/errorCode";
|
import errorCode from '@/common/request/errorCode'
|
||||||
import { getToken } from '@/common/utils/auth'
|
import { getToken, getRefreshToken, setToken, setRefreshToken } from '@/common/utils/auth'
|
||||||
import { toast, showConfirm } from '@/common/utils/common'
|
import { toast } from '@/common/utils/common'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
import request from '@/common/request/request.js'
|
||||||
|
|
||||||
// luch-request插件官网:https://www.quanzhan.co/luch-request/guide/3.x/#%E5%85%A8%E5%B1%80%E8%AF%B7%E6%B1%82%E9%85%8D%E7%BD%AE
|
// luch-request插件官网:https://www.quanzhan.co/luch-request/guide/3.x/#%E5%85%A8%E5%B1%80%E8%AF%B7%E6%B1%82%E9%85%8D%E7%BD%AE
|
||||||
// 创建luchRequest实例
|
// 创建luchRequest实例
|
||||||
console.log(config.baseUrl)
|
|
||||||
const http = new luchRequest({
|
const http = new luchRequest({
|
||||||
baseURL: config.baseUrl,
|
baseURL: config.baseUrl,
|
||||||
timeout: 20000, // 请求超时时间
|
timeout: 20000, // 请求超时时间
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
custom: {
|
custom: {
|
||||||
loading: true
|
loading: true
|
||||||
},
|
}
|
||||||
sslVerify: true,
|
|
||||||
header: {}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
http.interceptors.request.use(
|
http.interceptors.request.use(
|
||||||
config => {
|
(config) => {
|
||||||
// 在发送请求之前
|
// 在发送请求之前
|
||||||
let token = getToken()
|
let token = getToken()
|
||||||
if (token) {
|
if (token) {
|
||||||
// 添加头信息,token验证
|
// 添加头信息,token验证
|
||||||
config.header["Authorization"] = token
|
config.header['Authorization'] = token
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
error => {
|
(error) => {
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
http.interceptors.response.use(res => {
|
http.interceptors.response.use(
|
||||||
|
(res) => {
|
||||||
// console.log("响应拦截器:", res)
|
// console.log("响应拦截器:", res)
|
||||||
// 未设置状态码则默认成功状态
|
// 未设置状态码则默认401状态
|
||||||
const code = res.data.code || 200;
|
const code = res.data.code || 200
|
||||||
// 获取错误信息
|
// 获取错误信息
|
||||||
const msg = res.data.message || errorCode[code] || errorCode["default"];
|
const msg = res.data.message || errorCode[code] || errorCode['default']
|
||||||
|
// 是否刷新token
|
||||||
|
const refresh = res.data.refresh || false
|
||||||
if (code === 500) {
|
if (code === 500) {
|
||||||
toast(msg)
|
toast(msg)
|
||||||
return Promise.reject(new Error(msg));
|
return Promise.reject(new Error(msg))
|
||||||
} else if (code === 401) {
|
} else if (code === 401) {
|
||||||
showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => {
|
// 因token快过期,刷新token
|
||||||
if (res.confirm) {
|
refreshToken().then((res) => {
|
||||||
store.dispatch('auth/LogOut')
|
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
||||||
}
|
setRefreshToken(res.data.refresh_token)
|
||||||
})
|
})
|
||||||
return Promise.reject("error");
|
toast('操作失败,请重试')
|
||||||
|
return Promise.reject('error')
|
||||||
} else if (code !== 200) {
|
} else if (code !== 200) {
|
||||||
toast(msg)
|
toast(msg)
|
||||||
return Promise.reject("error");
|
return Promise.reject('error')
|
||||||
|
} else if (code === 200) {
|
||||||
|
if (refresh) {
|
||||||
|
// 因token快过期,刷新token
|
||||||
|
refreshToken().then((res) => {
|
||||||
|
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
setRefreshToken(res.data.refresh_token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res.data
|
||||||
} else {
|
} else {
|
||||||
return res.data;
|
return res.data
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
(error) => {
|
||||||
console.log("请求状态码服务器直接报错", error);
|
console.log('err', error)
|
||||||
let { errMsg } = error;
|
let message = error.data.message || error.errMsg
|
||||||
if (errMsg == "request:fail") {
|
const status = error.statusCode
|
||||||
errMsg = "接口连接异常";
|
switch (status) {
|
||||||
} else if (errMsg == "request:fail timeout") {
|
case 400:
|
||||||
errMsg = "接口连接超时";
|
message = '请求错误'
|
||||||
} else {
|
break
|
||||||
errMsg = error.data.message;
|
case 401:
|
||||||
|
// 强制要求重新登录,因账号已冻结,账号已过期,手机号码错误,刷新token无效等问题导致
|
||||||
|
store.dispatch('auth/LogOut')
|
||||||
|
message = '未认证,请登录'
|
||||||
|
break
|
||||||
|
case 403:
|
||||||
|
message = '拒绝访问'
|
||||||
|
break
|
||||||
|
case 404:
|
||||||
|
message = '请求地址出错'
|
||||||
|
break
|
||||||
|
case 408:
|
||||||
|
message = '请求超时'
|
||||||
|
break
|
||||||
|
case 500:
|
||||||
|
message = '服务器内部错误'
|
||||||
|
break
|
||||||
|
case 501:
|
||||||
|
message = '服务未实现'
|
||||||
|
break
|
||||||
|
case 502:
|
||||||
|
message = '网关错误'
|
||||||
|
break
|
||||||
|
case 503:
|
||||||
|
message = '服务不可用'
|
||||||
|
break
|
||||||
|
case 504:
|
||||||
|
message = '网关超时'
|
||||||
|
break
|
||||||
|
case 505:
|
||||||
|
message = 'HTTP版本不受支持'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
toast(errMsg)
|
toast(message)
|
||||||
return Promise.reject(error);
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
|
// 刷新 token
|
||||||
|
function refreshToken() {
|
||||||
|
const data = JSON.stringify(getRefreshToken())
|
||||||
|
return request.post('/auth/token/refresh/', data)
|
||||||
|
}
|
||||||
|
|
||||||
export default http
|
export default http
|
@ -11,3 +11,17 @@ export function setToken(token) {
|
|||||||
export function removeToken() {
|
export function removeToken() {
|
||||||
return uni.removeStorageSync(TokenKey)
|
return uni.removeStorageSync(TokenKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RefreshTokenKey = 'Refresh-Token'
|
||||||
|
|
||||||
|
export function getRefreshToken() {
|
||||||
|
return uni.getStorageSync(RefreshTokenKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRefreshToken(token) {
|
||||||
|
return uni.setStorageSync(RefreshTokenKey, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeRefreshToken() {
|
||||||
|
return uni.removeStorageSync(RefreshTokenKey)
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* 显示消息提示框
|
* 显示消息提示框
|
||||||
* @param content 提示的标题
|
* @param content 提示的标题
|
||||||
*/
|
*/
|
||||||
export function toast(content) {
|
export function toast(content) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
@ -10,9 +10,9 @@ export function toast(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示模态弹窗
|
* 显示模态弹窗
|
||||||
* @param content 提示的标题
|
* @param content 提示的标题
|
||||||
*/
|
*/
|
||||||
export function showConfirm(content) {
|
export function showConfirm(content) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
@ -20,7 +20,7 @@ export function showConfirm(content) {
|
|||||||
content: content,
|
content: content,
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
confirmText: '确定',
|
confirmText: '确定',
|
||||||
success: function(res) {
|
success: function (res) {
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -28,25 +28,25 @@ export function showConfirm(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参数处理
|
* 参数处理
|
||||||
* @param params 参数
|
* @param params 参数
|
||||||
*/
|
*/
|
||||||
export function tansParams(params) {
|
export function tansParams(params) {
|
||||||
let result = ''
|
let result = ''
|
||||||
for (const propName of Object.keys(params)) {
|
for (const propName of Object.keys(params)) {
|
||||||
const value = params[propName]
|
const value = params[propName]
|
||||||
var part = encodeURIComponent(propName) + "="
|
var part = encodeURIComponent(propName) + '='
|
||||||
if (value !== null && value !== "" && typeof (value) !== "undefined") {
|
if (value !== null && value !== '' && typeof value !== 'undefined') {
|
||||||
if (typeof value === 'object') {
|
if (typeof value === 'object') {
|
||||||
for (const key of Object.keys(value)) {
|
for (const key of Object.keys(value)) {
|
||||||
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
|
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
|
||||||
let params = propName + '[' + key + ']'
|
let params = propName + '[' + key + ']'
|
||||||
var subPart = encodeURIComponent(params) + "="
|
var subPart = encodeURIComponent(params) + '='
|
||||||
result += subPart + encodeURIComponent(value[key]) + "&"
|
result += subPart + encodeURIComponent(value[key]) + '&'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result += part + encodeURIComponent(value) + "&"
|
result += part + encodeURIComponent(value) + '&'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
const TokenKey = 'Admin-Token'
|
|
||||||
|
|
||||||
// 获取客户端token
|
|
||||||
export function getToken() {
|
|
||||||
try {
|
|
||||||
const value = uni.getStorageSync(TokenKey);
|
|
||||||
if (value) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
} catch (e) {
|
|
||||||
// error
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置客户端token
|
|
||||||
export function setToken(token) {
|
|
||||||
uni.setStorage({
|
|
||||||
key: TokenKey,
|
|
||||||
data: token,
|
|
||||||
success: function (res) {
|
|
||||||
console.log('成功存储token');
|
|
||||||
},
|
|
||||||
fail:function(e){
|
|
||||||
console.log(e)
|
|
||||||
console.log("存储token失败");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除客户端token
|
|
||||||
export function removeToken() {
|
|
||||||
uni.removeStorage({
|
|
||||||
key: TokenKey,
|
|
||||||
success: function (res) {
|
|
||||||
console.log('成功删除token');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取客户端
|
|
||||||
export function getStorage(key) {
|
|
||||||
try {
|
|
||||||
const value = uni.getStorageSync(key);
|
|
||||||
if (value) {
|
|
||||||
// console.log("成功获取到 Storage:", value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
} catch (e) {
|
|
||||||
// error
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置客户端 Storage
|
|
||||||
export function setStorage(key, value) {
|
|
||||||
uni.setStorage({
|
|
||||||
key: key,
|
|
||||||
data: value,
|
|
||||||
success: function (res) {
|
|
||||||
console.log('成功存储');
|
|
||||||
},
|
|
||||||
fail:function(e){
|
|
||||||
console.log(e)
|
|
||||||
console.log("存储失败");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除客户端 Storage
|
|
||||||
export function removeStorage(key) {
|
|
||||||
uni.removeStorage({
|
|
||||||
key: key,
|
|
||||||
success: function (res) {
|
|
||||||
console.log('成功删除Storage');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
@ -17,12 +17,14 @@ module.exports = {
|
|||||||
if (!log) return
|
if (!log) return
|
||||||
log.error.apply(log, arguments)
|
log.error.apply(log, arguments)
|
||||||
},
|
},
|
||||||
setFilterMsg(msg) { // 从基础库2.7.3开始支持
|
setFilterMsg(msg) {
|
||||||
|
// 从基础库2.7.3开始支持
|
||||||
if (!log || !log.setFilterMsg) return
|
if (!log || !log.setFilterMsg) return
|
||||||
if (typeof msg !== 'string') return
|
if (typeof msg !== 'string') return
|
||||||
log.setFilterMsg(msg)
|
log.setFilterMsg(msg)
|
||||||
},
|
},
|
||||||
addFilterMsg(msg) { // 从基础库2.8.1开始支持
|
addFilterMsg(msg) {
|
||||||
|
// 从基础库2.8.1开始支持
|
||||||
if (!log || !log.addFilterMsg) return
|
if (!log || !log.addFilterMsg) return
|
||||||
if (typeof msg !== 'string') return
|
if (typeof msg !== 'string') return
|
||||||
log.addFilterMsg(msg)
|
log.addFilterMsg(msg)
|
||||||
|
@ -9,9 +9,9 @@ export function checkPermi(value) {
|
|||||||
if (value && value instanceof Array && value.length > 0) {
|
if (value && value instanceof Array && value.length > 0) {
|
||||||
const permissions = store.getters && store.getters.permissions
|
const permissions = store.getters && store.getters.permissions
|
||||||
const permissionDatas = value
|
const permissionDatas = value
|
||||||
const all_permission = "*:*:*"
|
const all_permission = '*:*:*'
|
||||||
|
|
||||||
const hasPermission = permissions.some(permission => {
|
const hasPermission = permissions.some((permission) => {
|
||||||
return all_permission === permission || permissionDatas.includes(permission)
|
return all_permission === permission || permissionDatas.includes(permission)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export function checkPermi(value) {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
|
console.error('未获取到校验的字符权限!')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,9 +34,9 @@ export function checkRole(value) {
|
|||||||
if (value && value instanceof Array && value.length > 0) {
|
if (value && value instanceof Array && value.length > 0) {
|
||||||
const roles = store.getters && store.getters.roles
|
const roles = store.getters && store.getters.roles
|
||||||
const permissionRoles = value
|
const permissionRoles = value
|
||||||
const super_admin = "admin"
|
const super_admin = 'admin'
|
||||||
|
|
||||||
const hasRole = roles.some(role => {
|
const hasRole = roles.some((role) => {
|
||||||
return super_admin === role || permissionRoles.includes(role)
|
return super_admin === role || permissionRoles.includes(role)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export function checkRole(value) {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
console.error(`need roles! Like checkRole="['admin','editor']"`)
|
console.error('未获取到校验的角色!')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,13 +5,11 @@
|
|||||||
博客:https://www.jianshu.com/p/71ad2f45120c
|
博客:https://www.jianshu.com/p/71ad2f45120c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import config from '@/config.js'
|
import config from '@/config.js'
|
||||||
import { getToken, removeToken } from '@/common/utils/cookies'
|
import { getToken } from '@/common/utils/auth'
|
||||||
|
|
||||||
|
|
||||||
// 单个文件上传
|
// 单个文件上传
|
||||||
export function uploadFile(api, file, data={}) {
|
export function uploadFile(api, file, data = {}) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.uploadFile({
|
uni.uploadFile({
|
||||||
url: config.baseUrl + api,
|
url: config.baseUrl + api,
|
||||||
@ -23,16 +21,16 @@ export function uploadFile(api, file, data={}) {
|
|||||||
Authorization: getToken()
|
Authorization: getToken()
|
||||||
},
|
},
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
let data = JSON.parse(res.data);
|
let data = JSON.parse(res.data)
|
||||||
if (data.code !== 200) {
|
if (data.code !== 200) {
|
||||||
reject(data);
|
reject(data)
|
||||||
}
|
}
|
||||||
resolve(data);
|
resolve(data)
|
||||||
},
|
},
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.log("上传失败", err);
|
console.log('上传失败', err)
|
||||||
reject(err);
|
reject(err)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,22 +38,22 @@ export function getDate(date, AddDayCount = 0) {
|
|||||||
// 日期格式化
|
// 日期格式化
|
||||||
export function parseTime(time, pattern) {
|
export function parseTime(time, pattern) {
|
||||||
if (arguments.length === 0 || !time) {
|
if (arguments.length === 0 || !time) {
|
||||||
return null;
|
return null
|
||||||
}
|
}
|
||||||
const format = pattern || "{y}-{m}-{d} {h}:{i}:{s}";
|
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||||
let date;
|
let date
|
||||||
if (typeof time === "object") {
|
if (typeof time === 'object') {
|
||||||
date = time;
|
date = time
|
||||||
} else {
|
} else {
|
||||||
if ((typeof time === "string") && (/^[0-9]+$/.test(time))) {
|
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
|
||||||
time = parseInt(time);
|
time = parseInt(time)
|
||||||
} else if (typeof time === "string") {
|
} else if (typeof time === 'string') {
|
||||||
time = time.replace(new RegExp(/-/gm), "/");
|
time = time.replace(new RegExp(/-/gm), '/')
|
||||||
}
|
}
|
||||||
if ((typeof time === "number") && (time.toString().length === 10)) {
|
if (typeof time === 'number' && time.toString().length === 10) {
|
||||||
time = time * 1000;
|
time = time * 1000
|
||||||
}
|
}
|
||||||
date = new Date(time);
|
date = new Date(time)
|
||||||
}
|
}
|
||||||
const formatObj = {
|
const formatObj = {
|
||||||
y: date.getFullYear(),
|
y: date.getFullYear(),
|
||||||
@ -63,129 +63,132 @@ export function parseTime(time, pattern) {
|
|||||||
i: date.getMinutes(),
|
i: date.getMinutes(),
|
||||||
s: date.getSeconds(),
|
s: date.getSeconds(),
|
||||||
a: date.getDay()
|
a: date.getDay()
|
||||||
};
|
|
||||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
|
||||||
let value = formatObj[key];
|
|
||||||
// Note: getDay() returns 0 on Sunday
|
|
||||||
if (key === "a") { return ["日", "一", "二", "三", "四", "五", "六"][value]; }
|
|
||||||
if (result.length > 0 && value < 10) {
|
|
||||||
value = "0" + value;
|
|
||||||
}
|
}
|
||||||
return value || 0;
|
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||||
});
|
let value = formatObj[key]
|
||||||
return time_str;
|
// Note: getDay() returns 0 on Sunday
|
||||||
|
if (key === 'a') {
|
||||||
|
return ['日', '一', '二', '三', '四', '五', '六'][value]
|
||||||
|
}
|
||||||
|
if (result.length > 0 && value < 10) {
|
||||||
|
value = '0' + value
|
||||||
|
}
|
||||||
|
return value || 0
|
||||||
|
})
|
||||||
|
return time_str
|
||||||
}
|
}
|
||||||
|
|
||||||
// 表单重置
|
// 表单重置
|
||||||
export function resetForm(refName) {
|
export function resetForm(refName) {
|
||||||
if (this.$refs[refName]) {
|
if (this.$refs[refName]) {
|
||||||
this.$refs[refName].resetFields();
|
this.$refs[refName].resetFields()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加日期范围
|
// 添加日期范围
|
||||||
export function addDateRange(params, dateRange, propName) {
|
export function addDateRange(params, dateRange, propName) {
|
||||||
const search = JSON.parse(JSON.stringify(params));
|
const search = JSON.parse(JSON.stringify(params))
|
||||||
if (dateRange != null && dateRange !== "" && dateRange.length !== 0) {
|
if (dateRange != null && dateRange !== '' && dateRange.length !== 0) {
|
||||||
search.as = JSON.stringify({ create_datetime__range: dateRange });
|
search.as = JSON.stringify({ create_datetime__range: dateRange })
|
||||||
}
|
}
|
||||||
return search;
|
return search
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回显数据字典
|
// 回显数据字典
|
||||||
export function selectDictLabel(datas, value) {
|
export function selectDictLabel(datas, value) {
|
||||||
var actions = [];
|
var actions = []
|
||||||
Object.keys(datas).some((key) => {
|
Object.keys(datas).some((key) => {
|
||||||
if (String(datas[key].value) === ("" + String(value))) {
|
if (String(datas[key].value) === '' + String(value)) {
|
||||||
actions.push(datas[key].label);
|
actions.push(datas[key].label)
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return actions.join("");
|
return actions.join('')
|
||||||
}
|
}
|
||||||
// 获取字典默认值
|
// 获取字典默认值
|
||||||
export function selectDictDefault(datas) {
|
export function selectDictDefault(datas) {
|
||||||
var actions = [];
|
var actions = []
|
||||||
Object.keys(datas).some((key) => {
|
Object.keys(datas).some((key) => {
|
||||||
if (datas[key].is_default === true) {
|
if (datas[key].is_default === true) {
|
||||||
actions.push(datas[key].dictValue);
|
actions.push(datas[key].dictValue)
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
if (!actions[0] && datas[0]) {
|
if (!actions[0] && datas[0]) {
|
||||||
actions.push(datas[0].dictValue);
|
actions.push(datas[0].dictValue)
|
||||||
}
|
}
|
||||||
return actions.join("");
|
return actions.join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回显数据字典(字符串数组)
|
// 回显数据字典(字符串数组)
|
||||||
export function selectDictLabels(datas, value, separator) {
|
export function selectDictLabels(datas, value, separator) {
|
||||||
var actions = [];
|
var actions = []
|
||||||
var currentSeparator = undefined === separator ? "," : separator;
|
var currentSeparator = undefined === separator ? ',' : separator
|
||||||
var temp = value.split(currentSeparator);
|
var temp = value.split(currentSeparator)
|
||||||
Object.keys(value.split(currentSeparator)).some((val) => {
|
Object.keys(value.split(currentSeparator)).some((val) => {
|
||||||
Object.keys(datas).some((key) => {
|
Object.keys(datas).some((key) => {
|
||||||
if (datas[key].dictValue == ("" + temp[val])) {
|
if (datas[key].dictValue == '' + temp[val]) {
|
||||||
actions.push(datas[key].dictLabel + currentSeparator);
|
actions.push(datas[key].dictLabel + currentSeparator)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
return actions.join("").substring(0, actions.join("").length - 1);
|
return actions.join('').substring(0, actions.join('').length - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换字符串,undefined,null等转化为""
|
// 转换字符串,undefined,null等转化为""
|
||||||
export function praseStrEmpty(str) {
|
export function praseStrEmpty(str) {
|
||||||
if (!str || str == "undefined" || str == "null") {
|
if (!str || str == 'undefined' || str == 'null') {
|
||||||
return "";
|
return ''
|
||||||
}
|
}
|
||||||
return str;
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// js模仿微信朋友圈计算时间显示几天/几小时/几分钟/刚刚
|
// js模仿微信朋友圈计算时间显示几天/几小时/几分钟/刚刚
|
||||||
//datetime 格式为2019-11-22 12:23:59样式
|
//datetime 格式为2019-11-22 12:23:59样式
|
||||||
export function timeConversion(datetime) { //dateTimeStamp是一个时间毫秒,注意时间戳是秒的形式,在这个毫秒的基础上除以1000,就是十位数的时间戳。13位数的都是时间毫秒。
|
export function timeConversion(datetime) {
|
||||||
|
//dateTimeStamp是一个时间毫秒,注意时间戳是秒的形式,在这个毫秒的基础上除以1000,就是十位数的时间戳。13位数的都是时间毫秒。
|
||||||
// var dateTimeStamp = new Date(datetime.replace(/ /, 'T')).getTime()-8 * 60 * 60 * 1000;//这里要减去中国的时区8小时
|
// var dateTimeStamp = new Date(datetime.replace(/ /, 'T')).getTime()-8 * 60 * 60 * 1000;//这里要减去中国的时区8小时
|
||||||
var dateTimeStamp = new Date(datetime.replace(/ /, 'T')).getTime();//这里不减去中国的时区8小时
|
var dateTimeStamp = new Date(datetime.replace(/ /, 'T')).getTime() //这里不减去中国的时区8小时
|
||||||
var minute = 1000 * 60; //把分,时,天,周,半个月,一个月用毫秒表示
|
var minute = 1000 * 60 //把分,时,天,周,半个月,一个月用毫秒表示
|
||||||
var hour = minute * 60;
|
var hour = minute * 60
|
||||||
var day = hour * 24;
|
var day = hour * 24
|
||||||
var week = day * 7;
|
var week = day * 7
|
||||||
var halfamonth = day * 15;
|
var month = day * 30
|
||||||
var month = day * 30;
|
var now = new Date().getTime() //获取当前时间毫秒
|
||||||
var now = new Date().getTime(); //获取当前时间毫秒
|
var diffValue = now - dateTimeStamp //时间差
|
||||||
var diffValue = now - dateTimeStamp; //时间差
|
|
||||||
|
|
||||||
if (diffValue < 0) {
|
if (diffValue < 0) {
|
||||||
return '刚刚';
|
return '刚刚'
|
||||||
}
|
}
|
||||||
var minC = diffValue / minute; //计算时间差的分,时,天,周,月
|
var minC = diffValue / minute //计算时间差的分,时,天,周,月
|
||||||
var hourC = diffValue / hour;
|
var hourC = diffValue / hour
|
||||||
var dayC = diffValue / day;
|
var dayC = diffValue / day
|
||||||
var weekC = diffValue / week;
|
var weekC = diffValue / week
|
||||||
var monthC = diffValue / month;
|
var monthC = diffValue / month
|
||||||
var result = "2";
|
var result = '2'
|
||||||
if (monthC >= 1 && monthC <= 3) {
|
if (monthC >= 1 && monthC <= 3) {
|
||||||
result = " " + parseInt(monthC) + "月前"
|
result = ' ' + parseInt(monthC) + '月前'
|
||||||
} else if (weekC >= 1 && weekC <= 3) {
|
} else if (weekC >= 1 && weekC <= 3) {
|
||||||
result = " " + parseInt(weekC) + "周前"
|
result = ' ' + parseInt(weekC) + '周前'
|
||||||
} else if (dayC >= 1 && dayC <= 6) {
|
} else if (dayC >= 1 && dayC <= 6) {
|
||||||
result = " " + parseInt(dayC) + "天前"
|
result = ' ' + parseInt(dayC) + '天前'
|
||||||
} else if (hourC >= 1 && hourC <= 23) {
|
} else if (hourC >= 1 && hourC <= 23) {
|
||||||
result = " " + parseInt(hourC) + "小时前"
|
result = ' ' + parseInt(hourC) + '小时前'
|
||||||
} else if (minC >= 1 && minC <= 59) {
|
} else if (minC >= 1 && minC <= 59) {
|
||||||
result = " " + parseInt(minC) + "分钟前"
|
result = ' ' + parseInt(minC) + '分钟前'
|
||||||
} else if (diffValue >= 0 && diffValue <= minute) {
|
} else if (diffValue >= 0 && diffValue <= minute) {
|
||||||
result = "刚刚"
|
result = '刚刚'
|
||||||
} else {
|
} else {
|
||||||
var datetime = new Date();
|
let datetime = new Date()
|
||||||
datetime.setTime(dateTimeStamp);
|
datetime.setTime(dateTimeStamp)
|
||||||
var Nyear = datetime.getFullYear(); {}
|
let Nyear = datetime.getFullYear()
|
||||||
var Nmonth = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
|
var Nmonth =
|
||||||
var Ndate = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
|
datetime.getMonth() + 1 < 10 ? '0' + (datetime.getMonth() + 1) : datetime.getMonth() + 1
|
||||||
var Nhour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
|
var Ndate = datetime.getDate() < 10 ? '0' + datetime.getDate() : datetime.getDate()
|
||||||
var Nminute = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
|
var Nhour = datetime.getHours() < 10 ? '0' + datetime.getHours() : datetime.getHours()
|
||||||
var Nsecond = datetime.getSeconds() < 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();
|
var Nminute = datetime.getMinutes() < 10 ? '0' + datetime.getMinutes() : datetime.getMinutes()
|
||||||
result = Nyear + "-" + Nmonth + "-" + Ndate
|
var Nsecond = datetime.getSeconds() < 10 ? '0' + datetime.getSeconds() : datetime.getSeconds()
|
||||||
|
result = Nyear + '-' + Nmonth + '-' + Ndate
|
||||||
}
|
}
|
||||||
return result;
|
return result
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ let storageNodeKeys = [...Object.values(auth)]
|
|||||||
let storageData = uni.getStorageSync(storageKey) || {}
|
let storageData = uni.getStorageSync(storageKey) || {}
|
||||||
|
|
||||||
const storage = {
|
const storage = {
|
||||||
set: function(key, value) {
|
set: function (key, value) {
|
||||||
if (storageNodeKeys.indexOf(key) != -1) {
|
if (storageNodeKeys.indexOf(key) != -1) {
|
||||||
let tmp = uni.getStorageSync(storageKey)
|
let tmp = uni.getStorageSync(storageKey)
|
||||||
tmp = tmp ? tmp : {}
|
tmp = tmp ? tmp : {}
|
||||||
@ -21,14 +21,14 @@ const storage = {
|
|||||||
uni.setStorageSync(storageKey, tmp)
|
uni.setStorageSync(storageKey, tmp)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
get: function(key) {
|
get: function (key) {
|
||||||
return storageData[key] || ""
|
return storageData[key] || ''
|
||||||
},
|
},
|
||||||
remove: function(key) {
|
remove: function (key) {
|
||||||
delete storageData[key]
|
delete storageData[key]
|
||||||
uni.setStorageSync(storageKey, storageData)
|
uni.setStorageSync(storageKey, storageData)
|
||||||
},
|
},
|
||||||
clean: function() {
|
clean: function () {
|
||||||
uni.removeStorageSync(storageKey)
|
uni.removeStorageSync(storageKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import { toast, showConfirm, tansParams } from '@/common/utils/common'
|
|||||||
let timeout = 10000
|
let timeout = 10000
|
||||||
const baseUrl = config.baseUrl
|
const baseUrl = config.baseUrl
|
||||||
|
|
||||||
const upload = config => {
|
const upload = (config) => {
|
||||||
// 是否需要设置 token
|
// 是否需要设置 token
|
||||||
const isToken = (config.headers || {}).isToken === false
|
const isToken = (config.headers || {}).isToken === false
|
||||||
config.header = config.header || {}
|
config.header = config.header || {}
|
||||||
@ -35,7 +35,7 @@ const upload = config => {
|
|||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
resolve(result)
|
resolve(result)
|
||||||
} else if (code == 401) {
|
} else if (code == 401) {
|
||||||
showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => {
|
showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then((res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
store.dispatch('LogOut')
|
store.dispatch('LogOut')
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,13 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
// 测试环境
|
// 测试环境
|
||||||
baseUrl: 'http://127.0.0.1:9000',
|
baseUrl: 'http://127.0.0.1:9000',
|
||||||
// 生产环境
|
|
||||||
// baseUrl: 'https://api.kinit.ktianc.top',
|
|
||||||
// 应用信息
|
// 应用信息
|
||||||
appInfo: {
|
appInfo: {
|
||||||
// 应用版本
|
// 应用版本
|
||||||
version: "1.1.0",
|
version: '1.2.0',
|
||||||
// 隐私政策,不支持本地路径
|
// 隐私政策,不支持本地路径
|
||||||
privacy: "http://kinit.ktianc.top/docs/privacy",
|
privacy: 'http://kinit.ktianc.top/docs/privacy',
|
||||||
// 用户协议,不支持本地路径
|
// 用户协议,不支持本地路径
|
||||||
agreement: "http://kinit.ktianc.top/docs/agreement"
|
agreement: 'http://kinit.ktianc.top/docs/agreement'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
kinit-uni/jsconfig.json
Normal file
8
kinit-uni/jsconfig.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,8 +2,8 @@ import Vue from 'vue'
|
|||||||
import App from './App'
|
import App from './App'
|
||||||
import store from './store' // store
|
import store from './store' // store
|
||||||
import plugins from './plugins' // plugins
|
import plugins from './plugins' // plugins
|
||||||
import {router,RouterMount} from './permission.js' // 路由拦截
|
import { router, RouterMount } from './permission.js' // 路由拦截
|
||||||
import uView from "uview-ui"
|
import uView from 'uview-ui'
|
||||||
|
|
||||||
Vue.use(uView)
|
Vue.use(uView)
|
||||||
Vue.use(router)
|
Vue.use(router)
|
||||||
@ -49,9 +49,9 @@ const app = new Vue({
|
|||||||
|
|
||||||
//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
|
//v1.3.5起 H5端 你应该去除原有的app.$mount();使用路由自带的渲染方式
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
RouterMount(app, router, '#app')
|
RouterMount(app, router, '#app')
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifndef H5
|
// #ifndef H5
|
||||||
app.$mount(); //为了兼容小程序及app端必须这样写才有效果
|
app.$mount() //为了兼容小程序及app端必须这样写才有效果
|
||||||
// #endif
|
// #endif
|
||||||
|
@ -3,5 +3,11 @@
|
|||||||
"uni-read-pages": "^1.0.5",
|
"uni-read-pages": "^1.0.5",
|
||||||
"uni-simple-router": "^2.0.8-beta.3",
|
"uni-simple-router": "^2.0.8-beta.3",
|
||||||
"uview-ui": "^2.0.34"
|
"uview-ui": "^2.0.34"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.35.0",
|
||||||
|
"eslint-config-prettier": "^8.7.0",
|
||||||
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
|
"eslint-plugin-vue": "^9.9.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: '',
|
title: '',
|
||||||
@ -26,23 +26,23 @@
|
|||||||
title: options.title
|
title: options.title
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.view-title {
|
.view-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.view-content {
|
.view-content {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
padding: 12px 5px 0;
|
padding: 12px 5px 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -6,23 +6,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
props: {
|
||||||
|
src: {
|
||||||
|
type: [String],
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
params: {},
|
params: {},
|
||||||
webviewStyles: {
|
webviewStyles: {
|
||||||
progress: {
|
progress: {
|
||||||
color: "#FF3333"
|
color: '#FF3333'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
src: {
|
|
||||||
type: [String],
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLoad(event) {
|
onLoad(event) {
|
||||||
this.params = event
|
this.params = event
|
||||||
if (event.title) {
|
if (event.title) {
|
||||||
@ -31,5 +31,5 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { wxShareMixins } from '@/common/mixins/share.js'
|
import { wxShareMixins } from '@/common/mixins/share.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [wxShareMixins],
|
mixins: [wxShareMixins],
|
||||||
computed: {
|
computed: {
|
||||||
name() {
|
name() {
|
||||||
@ -22,12 +22,12 @@
|
|||||||
logoImage() {
|
logoImage() {
|
||||||
return this.$store.state.app.logoImage
|
return this.$store.state.app.logoImage
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.content {
|
.content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -51,5 +51,5 @@
|
|||||||
color: #8f8f94;
|
color: #8f8f94;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,29 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="normal-login-container">
|
<view class="normal-login-container">
|
||||||
<view class="logo-content align-center justify-center flex">
|
<view class="logo-content align-center justify-center flex">
|
||||||
<image v-if="logo" style="width: 100rpx;height: 100rpx;" :src="logoImage" mode="widthFix">
|
<image v-if="logo" style="width: 100rpx; height: 100rpx" :src="logoImage" mode="widthFix">
|
||||||
</image>
|
</image>
|
||||||
<text class="title">{{ title }}</text>
|
<text class="title">{{ title }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="login-form-content">
|
<view class="login-form-content">
|
||||||
<view class="input-item flex align-center">
|
<view class="input-item flex align-center">
|
||||||
<view class="iconfont icon-user icon"></view>
|
<view class="iconfont icon-user icon"></view>
|
||||||
<input v-model="loginForm.telephone" class="input" type="text" placeholder="请输入手机号" maxlength="30" />
|
<input
|
||||||
|
v-model="loginForm.telephone"
|
||||||
|
class="input"
|
||||||
|
type="text"
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
maxlength="30"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="input-item flex align-center">
|
<view class="input-item flex align-center">
|
||||||
<view class="iconfont icon-password icon"></view>
|
<view class="iconfont icon-password icon"></view>
|
||||||
<input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" />
|
<input
|
||||||
|
v-model="loginForm.password"
|
||||||
|
type="password"
|
||||||
|
class="input"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
maxlength="20"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="action-btn">
|
<view class="action-btn">
|
||||||
<!-- <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button> -->
|
<!-- <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button> -->
|
||||||
<u-button type="primary" text="登录" @click="handleLogin" shape="circle"></u-button>
|
<u-button type="primary" text="登录" shape="circle" @click="handleLogin"></u-button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="xieyi text-center">
|
<view class="xieyi text-center">
|
||||||
<text class="text-grey1">登录即代表同意</text>
|
<text class="text-grey1">登录即代表同意</text>
|
||||||
<text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
|
<text class="text-blue" @click="handleUserAgrement">《用户协议》</text>
|
||||||
<text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
|
<text class="text-blue" @click="handlePrivacy">《隐私协议》</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="footer text-center">
|
<view class="footer text-center">
|
||||||
@ -39,15 +51,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { wxLoginMixins } from '@/common/mixins/auth.js'
|
import { wxLoginMixins } from '@/common/mixins/auth.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [wxLoginMixins],
|
mixins: [wxLoginMixins],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loginForm: {
|
loginForm: {
|
||||||
telephone: "15020221010",
|
telephone: '15020221010',
|
||||||
password: "kinit2022"
|
password: 'kinit2022'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -84,12 +96,12 @@
|
|||||||
},
|
},
|
||||||
// 登录方法
|
// 登录方法
|
||||||
async handleLogin() {
|
async handleLogin() {
|
||||||
if (this.loginForm.telephone === "") {
|
if (this.loginForm.telephone === '') {
|
||||||
this.$modal.msgError("请输入您的手机号")
|
this.$modal.msgError('请输入您的手机号')
|
||||||
} else if (this.loginForm.password === "") {
|
} else if (this.loginForm.password === '') {
|
||||||
this.$modal.msgError("请输入您的密码")
|
this.$modal.msgError('请输入您的密码')
|
||||||
}else {
|
} else {
|
||||||
this.$modal.loading("正在登录中...")
|
this.$modal.loading('正在登录中...')
|
||||||
this.pwdLogin()
|
this.pwdLogin()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -110,20 +122,20 @@
|
|||||||
},
|
},
|
||||||
// 微信一键登录
|
// 微信一键登录
|
||||||
wxLogin(detail) {
|
wxLogin(detail) {
|
||||||
this.onGetPhoneNumber(detail).then(res => {
|
this.onGetPhoneNumber(detail).then((res) => {
|
||||||
this.loginSuccess()
|
this.loginSuccess()
|
||||||
})
|
})
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.normal-login-container {
|
.normal-login-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -168,7 +180,6 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-btn {
|
.login-btn {
|
||||||
@ -193,9 +204,9 @@
|
|||||||
bottom: 30px;
|
bottom: 30px;
|
||||||
left: 10%;
|
left: 10%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-code-img {
|
.login-code-img {
|
||||||
height: 45px;
|
height: 45px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="about-container">
|
<view class="about-container">
|
||||||
<view class="header-section text-center">
|
<view class="header-section text-center">
|
||||||
<image style="width: 150rpx;height: 150rpx;" :src="logoImage" mode="widthFix">
|
<image style="width: 150rpx; height: 150rpx" :src="logoImage" mode="widthFix"> </image>
|
||||||
</image>
|
|
||||||
<uni-title type="h2" :title="title"></uni-title>
|
<uni-title type="h2" :title="title"></uni-title>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -11,7 +10,7 @@
|
|||||||
<view class="list-cell list-cell-arrow">
|
<view class="list-cell list-cell-arrow">
|
||||||
<view class="menu-item-box">
|
<view class="menu-item-box">
|
||||||
<view>版本信息</view>
|
<view>版本信息</view>
|
||||||
<view class="text-right">v{{version}}</view>
|
<view class="text-right">v{{ version }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="list-cell list-cell-arrow">
|
<view class="list-cell list-cell-arrow">
|
||||||
@ -30,7 +29,7 @@
|
|||||||
<view class="menu-item-box">
|
<view class="menu-item-box">
|
||||||
<view>公司网站</view>
|
<view>公司网站</view>
|
||||||
<view class="text-right">
|
<view class="text-right">
|
||||||
<uni-link :href="siteUrl" :text="siteUrl" showUnderLine="false"></uni-link>
|
<uni-link :href="siteUrl" :text="siteUrl" show-under-line="false"></uni-link>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -44,7 +43,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
@ -70,26 +69,26 @@
|
|||||||
footerContent() {
|
footerContent() {
|
||||||
return this.$store.state.app.footerContent
|
return this.$store.state.app.footerContent
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
margin-top: 50rpx;
|
margin-top: 50rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 60rpx;
|
line-height: 60rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-section {
|
.header-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 30rpx 0 0;
|
padding: 30rpx 0 0;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,50 +1,130 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view class="page-body uni-content-info">
|
<view class="page-body uni-content-info">
|
||||||
<view class='cropper-content'>
|
<view class="cropper-content">
|
||||||
<view v-if="isShowImg" class="uni-corpper" :style="'width:'+cropperInitW+'px;height:'+cropperInitH+'px;background:#000'">
|
<view
|
||||||
<view class="uni-corpper-content" :style="'width:'+cropperW+'px;height:'+cropperH+'px;left:'+cropperL+'px;top:'+cropperT+'px'">
|
v-if="isShowImg"
|
||||||
<image :src="imageSrc" :style="'width:'+cropperW+'px;height:'+cropperH+'px'"></image>
|
class="uni-corpper"
|
||||||
<view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove" @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd"
|
:style="'width:' + cropperInitW + 'px;height:' + cropperInitH + 'px;background:#000'"
|
||||||
:style="'left:'+cutL+'px;top:'+cutT+'px;right:'+cutR+'px;bottom:'+cutB+'px'">
|
>
|
||||||
|
<view
|
||||||
|
class="uni-corpper-content"
|
||||||
|
:style="{
|
||||||
|
width: cropperW + 'px',
|
||||||
|
height: cropperH + 'px',
|
||||||
|
left: cropperL + 'px',
|
||||||
|
top: cropperT + 'px'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="imageSrc"
|
||||||
|
:style="'width:' + cropperW + 'px;height:' + cropperH + 'px'"
|
||||||
|
></image>
|
||||||
|
<view
|
||||||
|
class="uni-corpper-crop-box"
|
||||||
|
:style="
|
||||||
|
'left:' + cutL + 'px;top:' + cutT + 'px;right:' + cutR + 'px;bottom:' + cutB + 'px'
|
||||||
|
"
|
||||||
|
@touchstart.stop="contentStartMove"
|
||||||
|
@touchmove.stop="contentMoveing"
|
||||||
|
@touchend.stop="contentTouchEnd"
|
||||||
|
>
|
||||||
<view class="uni-cropper-view-box">
|
<view class="uni-cropper-view-box">
|
||||||
<view class="uni-cropper-dashed-h"></view>
|
<view class="uni-cropper-dashed-h"></view>
|
||||||
<view class="uni-cropper-dashed-v"></view>
|
<view class="uni-cropper-dashed-v"></view>
|
||||||
<view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
<view
|
||||||
<view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
class="uni-cropper-line-t"
|
||||||
<view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
data-drag="top"
|
||||||
<view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
@touchstart.stop="dragStart"
|
||||||
<view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-line-r"
|
||||||
|
data-drag="right"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-line-b"
|
||||||
|
data-drag="bottom"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-line-l"
|
||||||
|
data-drag="left"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-point point-t"
|
||||||
|
data-drag="top"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
<view class="uni-cropper-point point-tr" data-drag="topTight"></view>
|
<view class="uni-cropper-point point-tr" data-drag="topTight"></view>
|
||||||
<view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
<view
|
||||||
<view class="uni-cropper-point point-rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
class="uni-cropper-point point-r"
|
||||||
<view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
|
data-drag="right"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-point point-rb"
|
||||||
|
data-drag="rightBottom"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
|
<view
|
||||||
|
class="uni-cropper-point point-b"
|
||||||
|
data-drag="bottom"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
@touchend.stop="dragEnd"
|
||||||
|
></view>
|
||||||
<view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
|
<view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
|
||||||
<view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
|
<view
|
||||||
|
class="uni-cropper-point point-l"
|
||||||
|
data-drag="left"
|
||||||
|
@touchstart.stop="dragStart"
|
||||||
|
@touchmove.stop="dragMove"
|
||||||
|
></view>
|
||||||
<view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
|
<view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class='cropper-config'>
|
<view class="cropper-config">
|
||||||
<button type="primary reverse" @click="getImage" style='margin-top: 30rpx;'> 选择头像 </button>
|
<button type="primary reverse" style="margin-top: 30rpx" @click="getImage">
|
||||||
<button type="warn" @click="getImageInfo" style='margin-top: 30rpx;'> 提交 </button>
|
选择头像
|
||||||
|
</button>
|
||||||
|
<button type="warn" style="margin-top: 30rpx" @click="getImageInfo"> 提交 </button>
|
||||||
</view>
|
</view>
|
||||||
<canvas canvas-id="myCanvas" :style="'position:absolute;border: 1px solid red; width:'+imageW+'px;height:'+imageH+'px;top:-9999px;left:-9999px;'"></canvas>
|
<canvas
|
||||||
|
canvas-id="myCanvas"
|
||||||
|
:style="{
|
||||||
|
width: imageW + 'px',
|
||||||
|
height: imageH + 'px',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '-9999px',
|
||||||
|
border: '1px solid red',
|
||||||
|
left: '-9999px'
|
||||||
|
}"
|
||||||
|
></canvas>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import config from '@/config'
|
import config from '@/config'
|
||||||
import store from "@/store"
|
import store from '@/store'
|
||||||
import { postCurrentUserUploadAvatar } from "@/common/request/api/vadmin/auth/user.js"
|
import { postCurrentUserUploadAvatar } from '@/common/request/api/vadmin/auth/user.js'
|
||||||
|
|
||||||
const baseUrl = config.baseUrl
|
const baseUrl = config.baseUrl
|
||||||
let sysInfo = uni.getSystemInfoSync()
|
let sysInfo = uni.getSystemInfoSync()
|
||||||
let SCREEN_WIDTH = sysInfo.screenWidth
|
let SCREEN_WIDTH = sysInfo.screenWidth
|
||||||
let PAGE_X, // 手按下的x位置
|
let PAGE_X, // 手按下的x位置
|
||||||
PAGE_Y, // 手按下y的位置
|
PAGE_Y, // 手按下y的位置
|
||||||
PR = sysInfo.pixelRatio, // dpi
|
PR = sysInfo.pixelRatio, // dpi
|
||||||
T_PAGE_X, // 手移动的时候x的位置
|
T_PAGE_X, // 手移动的时候x的位置
|
||||||
@ -62,7 +142,7 @@
|
|||||||
INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
|
INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
|
||||||
DRAW_IMAGE_W = sysInfo.screenWidth // 设置生成的图片宽度
|
DRAW_IMAGE_W = sysInfo.screenWidth // 设置生成的图片宽度
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* 页面的初始数据
|
* 页面的初始数据
|
||||||
*/
|
*/
|
||||||
@ -115,10 +195,10 @@
|
|||||||
uni.chooseImage({
|
uni.chooseImage({
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
_this.setData({
|
_this.setData({
|
||||||
imageSrc: res.tempFilePaths[0],
|
imageSrc: res.tempFilePaths[0]
|
||||||
})
|
})
|
||||||
_this.loadImage()
|
_this.loadImage()
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
loadImage: function () {
|
loadImage: function () {
|
||||||
@ -139,7 +219,9 @@
|
|||||||
INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange
|
INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange
|
||||||
// 根据图片的宽高显示不同的效果 保证图片可以正常显示
|
// 根据图片的宽高显示不同的效果 保证图片可以正常显示
|
||||||
if (IMG_RATIO >= 1) {
|
if (IMG_RATIO >= 1) {
|
||||||
let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2)
|
let cutT = Math.ceil(
|
||||||
|
(SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2
|
||||||
|
)
|
||||||
let cutB = cutT
|
let cutB = cutT
|
||||||
let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2)
|
let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2)
|
||||||
let cutR = cutL
|
let cutR = cutL
|
||||||
@ -161,7 +243,7 @@
|
|||||||
innerAspectRadio: IMG_RATIO
|
innerAspectRadio: IMG_RATIO
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - (SCREEN_WIDTH * IMG_RATIO)) / 2)
|
let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - SCREEN_WIDTH * IMG_RATIO) / 2)
|
||||||
let cutR = cutL
|
let cutR = cutL
|
||||||
let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2)
|
let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2)
|
||||||
let cutB = cutT
|
let cutB = cutT
|
||||||
@ -199,7 +281,6 @@
|
|||||||
|
|
||||||
// 拖动时候触发的touchMove事件
|
// 拖动时候触发的touchMove事件
|
||||||
contentMoveing(e) {
|
contentMoveing(e) {
|
||||||
var _this = this
|
|
||||||
var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
||||||
var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
||||||
// 左移
|
// 左移
|
||||||
@ -225,15 +306,13 @@
|
|||||||
PAGE_Y = e.touches[0].pageY
|
PAGE_Y = e.touches[0].pageY
|
||||||
},
|
},
|
||||||
|
|
||||||
contentTouchEnd() {
|
contentTouchEnd() {},
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取图片
|
// 获取图片
|
||||||
getImageInfo() {
|
getImageInfo() {
|
||||||
var _this = this
|
var _this = this
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: '图片生成中...',
|
title: '图片生成中...'
|
||||||
})
|
})
|
||||||
uni.getImageInfo({
|
uni.getImageInfo({
|
||||||
src: _this.imageSrc,
|
src: _this.imageSrc,
|
||||||
@ -258,19 +337,16 @@
|
|||||||
canvasId: 'myCanvas',
|
canvasId: 'myCanvas',
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
postCurrentUserUploadAvatar(res.tempFilePath).then(response => {
|
postCurrentUserUploadAvatar(res.tempFilePath).then((response) => {
|
||||||
store.commit('SET_AVATAR', response.data)
|
store.commit('auth/SET_AVATAR', response.data)
|
||||||
uni.showToast({ title: "修改成功", icon: 'success' })
|
uni.showToast({ title: '修改成功', icon: 'success' })
|
||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
|
||||||
fail: function (err) {
|
|
||||||
uni.hideLoading()
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
// 设置大小的时候触发的touchStart事件
|
// 设置大小的时候触发的touchStart事件
|
||||||
dragStart(e) {
|
dragStart(e) {
|
||||||
@ -284,51 +360,53 @@
|
|||||||
|
|
||||||
// 设置大小的时候触发的touchMove事件
|
// 设置大小的时候触发的touchMove事件
|
||||||
dragMove(e) {
|
dragMove(e) {
|
||||||
var _this = this
|
let dragType = e.target.dataset.drag
|
||||||
var dragType = e.target.dataset.drag
|
let dragLength = undefined
|
||||||
|
let dragLengthX = undefined
|
||||||
|
let dragLengthY = undefined
|
||||||
switch (dragType) {
|
switch (dragType) {
|
||||||
case 'right':
|
case 'right':
|
||||||
var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
||||||
if (CUT_R + dragLength < 0) dragLength = -CUT_R
|
if (CUT_R + dragLength < 0) dragLength = -CUT_R
|
||||||
this.setData({
|
this.setData({
|
||||||
cutR: CUT_R + dragLength
|
cutR: CUT_R + dragLength
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'left':
|
case 'left':
|
||||||
var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
||||||
if (CUT_L - dragLength < 0) dragLength = CUT_L
|
if (CUT_L - dragLength < 0) dragLength = CUT_L
|
||||||
if ((CUT_L - dragLength) > (this.cropperW - this.cutR)) dragLength = CUT_L - (this.cropperW - this.cutR)
|
if (CUT_L - dragLength > this.cropperW - this.cutR)
|
||||||
|
dragLength = CUT_L - (this.cropperW - this.cutR)
|
||||||
this.setData({
|
this.setData({
|
||||||
cutL: CUT_L - dragLength
|
cutL: CUT_L - dragLength
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'top':
|
case 'top':
|
||||||
var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
||||||
if (CUT_T - dragLength < 0) dragLength = CUT_T
|
if (CUT_T - dragLength < 0) dragLength = CUT_T
|
||||||
if ((CUT_T - dragLength) > (this.cropperH - this.cutB)) dragLength = CUT_T - (this.cropperH - this.cutB)
|
if (CUT_T - dragLength > this.cropperH - this.cutB)
|
||||||
|
dragLength = CUT_T - (this.cropperH - this.cutB)
|
||||||
this.setData({
|
this.setData({
|
||||||
cutT: CUT_T - dragLength
|
cutT: CUT_T - dragLength
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'bottom':
|
case 'bottom':
|
||||||
var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
||||||
if (CUT_B + dragLength < 0) dragLength = -CUT_B
|
if (CUT_B + dragLength < 0) dragLength = -CUT_B
|
||||||
this.setData({
|
this.setData({
|
||||||
cutB: CUT_B + dragLength
|
cutB: CUT_B + dragLength
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case 'rightBottom':
|
case 'rightBottom':
|
||||||
var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
|
||||||
var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
|
||||||
|
|
||||||
if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B
|
if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B
|
||||||
if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R
|
if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R
|
||||||
let cutB = CUT_B + dragLengthY
|
|
||||||
let cutR = CUT_R + dragLengthX
|
|
||||||
|
|
||||||
this.setData({
|
this.setData({
|
||||||
cutB: cutB,
|
cutB: CUT_B + dragLengthY,
|
||||||
cutR: cutR
|
cutR: CUT_R + dragLengthX
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -336,13 +414,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* pages/uni-cropper/index.wxss */
|
/* pages/uni-cropper/index.wxss */
|
||||||
|
|
||||||
.uni-content-info {
|
.uni-content-info {
|
||||||
/* position: fixed;
|
/* position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -351,18 +429,18 @@
|
|||||||
display: block;
|
display: block;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column; */
|
flex-direction: column; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-config {
|
.cropper-config {
|
||||||
padding: 20rpx 40rpx;
|
padding: 20rpx 40rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cropper-content {
|
.cropper-content {
|
||||||
min-height: 750rpx;
|
min-height: 750rpx;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-corpper {
|
.uni-corpper {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
@ -372,13 +450,13 @@
|
|||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-corpper-content {
|
.uni-corpper-content {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-corpper-content image {
|
.uni-corpper-content image {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: 0 !important;
|
min-width: 0 !important;
|
||||||
@ -388,10 +466,10 @@
|
|||||||
max-height: none !important;
|
max-height: none !important;
|
||||||
image-orientation: 0deg !important;
|
image-orientation: 0deg !important;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
/* 移动图片效果 */
|
/* 移动图片效果 */
|
||||||
|
|
||||||
.uni-cropper-drag-box {
|
.uni-cropper-drag-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -400,27 +478,27 @@
|
|||||||
cursor: move;
|
cursor: move;
|
||||||
background: rgba(0, 0, 0, 0.6);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
/* 内部的信息 */
|
/* 内部的信息 */
|
||||||
|
|
||||||
.uni-corpper-crop-box {
|
.uni-corpper-crop-box {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(255, 255, 255, 0.3);
|
background: rgba(255, 255, 255, 0.3);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-corpper-crop-box .uni-cropper-view-box {
|
.uni-corpper-crop-box .uni-cropper-view-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
outline: 1rpx solid #69f;
|
outline: 1rpx solid #69f;
|
||||||
outline-color: rgba(102, 153, 255, .75)
|
outline-color: rgba(102, 153, 255, 0.75);
|
||||||
}
|
}
|
||||||
/* 横向虚线 */
|
/* 横向虚线 */
|
||||||
|
|
||||||
.uni-cropper-dashed-h {
|
.uni-cropper-dashed-h {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 33.33333333%;
|
top: 33.33333333%;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -428,10 +506,10 @@
|
|||||||
height: 33.33333333%;
|
height: 33.33333333%;
|
||||||
border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
|
border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
|
||||||
border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
|
border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
/* 纵向虚线 */
|
/* 纵向虚线 */
|
||||||
|
|
||||||
.uni-cropper-dashed-v {
|
.uni-cropper-dashed-v {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 33.33333333%;
|
left: 33.33333333%;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -439,10 +517,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
|
border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
|
||||||
border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
|
border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
/* 四个方向的线 为了之后的拖动事件*/
|
/* 四个方向的线 为了之后的拖动事件*/
|
||||||
|
|
||||||
.uni-cropper-line-t {
|
.uni-cropper-line-t {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -452,9 +530,9 @@
|
|||||||
height: 1rpx;
|
height: 1rpx;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-t::before {
|
.uni-cropper-line-t::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@ -466,9 +544,9 @@
|
|||||||
height: 41rpx;
|
height: 41rpx;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-r {
|
.uni-cropper-line-r {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
background-color: #69f;
|
background-color: #69f;
|
||||||
@ -478,9 +556,9 @@
|
|||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: e-resize;
|
cursor: e-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-r::before {
|
.uni-cropper-line-r::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -492,9 +570,9 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-b {
|
.uni-cropper-line-b {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -504,9 +582,9 @@
|
|||||||
height: 1rpx;
|
height: 1rpx;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
cursor: s-resize;
|
cursor: s-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-b::before {
|
.uni-cropper-line-b::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
@ -518,9 +596,9 @@
|
|||||||
height: 41rpx;
|
height: 41rpx;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-l {
|
.uni-cropper-line-l {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
background-color: #69f;
|
background-color: #69f;
|
||||||
@ -530,9 +608,9 @@
|
|||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
cursor: w-resize;
|
cursor: w-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-line-l::before {
|
.uni-cropper-line-l::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -544,40 +622,40 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-point {
|
.uni-cropper-point {
|
||||||
width: 5rpx;
|
width: 5rpx;
|
||||||
height: 5rpx;
|
height: 5rpx;
|
||||||
background-color: #69f;
|
background-color: #69f;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-t {
|
.point-t {
|
||||||
top: -3rpx;
|
top: -3rpx;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-tr {
|
.point-tr {
|
||||||
top: -3rpx;
|
top: -3rpx;
|
||||||
left: 100%;
|
left: 100%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-r {
|
.point-r {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 100%;
|
left: 100%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
margin-top: -3rpx;
|
margin-top: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-rb {
|
.point-rb {
|
||||||
left: 100%;
|
left: 100%;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
-webkit-transform: translate3d(-50%, -50%, 0);
|
-webkit-transform: translate3d(-50%, -50%, 0);
|
||||||
@ -589,50 +667,50 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1112;
|
z-index: 1112;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-b {
|
.point-b {
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
margin-top: -3rpx;
|
margin-top: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-bl {
|
.point-bl {
|
||||||
left: 0%;
|
left: 0%;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
margin-top: -3rpx;
|
margin-top: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-l {
|
.point-l {
|
||||||
left: 0%;
|
left: 0%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
margin-top: -3rpx;
|
margin-top: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.point-lt {
|
.point-lt {
|
||||||
left: 0%;
|
left: 0%;
|
||||||
top: 0%;
|
top: 0%;
|
||||||
margin-left: -3rpx;
|
margin-left: -3rpx;
|
||||||
margin-top: -3rpx;
|
margin-top: -3rpx;
|
||||||
cursor: n-resize;
|
cursor: n-resize;
|
||||||
}
|
}
|
||||||
/* 裁剪框预览内容 */
|
/* 裁剪框预览内容 */
|
||||||
|
|
||||||
.uni-cropper-viewer {
|
.uni-cropper-viewer {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uni-cropper-viewer image {
|
.uni-cropper-viewer image {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,10 +5,15 @@
|
|||||||
<view>{{ item.name }}</view>
|
<view>{{ item.name }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="childList">
|
<view class="childList">
|
||||||
<view v-for="(issue, zindex) in item.issues" :key="zindex" class="question" hover-class="hover"
|
<view
|
||||||
@click="handleText(issue)">
|
v-for="(issue, zindex) in item.issues"
|
||||||
|
:key="zindex"
|
||||||
|
class="question"
|
||||||
|
hover-class="hover"
|
||||||
|
@click="handleText(issue)"
|
||||||
|
>
|
||||||
<view class="text-item">{{ issue.title }}</view>
|
<view class="text-item">{{ issue.title }}</view>
|
||||||
<view class="line" v-if="zindex !== item.issues.length - 1"></view>
|
<view v-if="zindex !== item.issues.length - 1" class="line"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -16,16 +21,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getIssueCategoryList } from '@/common/request/api/vadmin/help/issue.js'
|
import { getIssueCategoryList } from '@/common/request/api/vadmin/help/issue.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
list: []
|
list: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
getIssueCategoryList().then(res => {
|
getIssueCategoryList().then((res) => {
|
||||||
this.list = res.data
|
this.list = res.data
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -34,50 +39,50 @@
|
|||||||
this.$tab.navigateTo(`/pages/mine/help/issue/info?id=${item.id}`)
|
this.$tab.navigateTo(`/pages/mine/help/issue/info?id=${item.id}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.help-container {
|
.help-container {
|
||||||
margin-bottom: 100rpx;
|
margin-bottom: 100rpx;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-title {
|
.list-title {
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.childList {
|
.childList {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2);
|
box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2);
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
margin-top: 10rpx;
|
margin-top: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
.line {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 1rpx;
|
height: 1rpx;
|
||||||
background-color: #F5F5F5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-title {
|
.text-title {
|
||||||
color: #303133;
|
color: #303133;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-left: 10rpx;
|
margin-left: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-item {
|
.text-item {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question {
|
.question {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<uni-card v-if="isSuccess" class="view-title" :title="model.title">
|
<uni-card v-if="isSuccess" class="view-title">
|
||||||
|
<u--text :text="model.title" bold></u--text>
|
||||||
<rich-text class="uni-body view-content" :nodes="model.content"></rich-text>
|
<rich-text class="uni-body view-content" :nodes="model.content"></rich-text>
|
||||||
</uni-card>
|
</uni-card>
|
||||||
<u-empty
|
<u-empty
|
||||||
v-else
|
v-else
|
||||||
mode="data"
|
mode="data"
|
||||||
icon="https://cdn.uviewui.com/uview/empty/data.png"
|
icon="https://cdn.uviewui.com/uview/empty/data.png"
|
||||||
:marginTop="100"
|
:margin-top="100"
|
||||||
:width="300"
|
:width="300"
|
||||||
:height="300"
|
:height="300"
|
||||||
>
|
>
|
||||||
@ -16,9 +17,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getIssue, updateIssueAddViewNumber } from '@/common/request/api/vadmin/help/issue.js'
|
import { getIssue, updateIssueAddViewNumber } from '@/common/request/api/vadmin/help/issue.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isSuccess: true,
|
isSuccess: true,
|
||||||
@ -36,35 +37,35 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getData() {
|
getData() {
|
||||||
if (!this.dataId) { return; }
|
if (!this.dataId) {
|
||||||
getIssue(this.dataId).then(res => {
|
return
|
||||||
this.model = res.data;
|
}
|
||||||
|
getIssue(this.dataId)
|
||||||
|
.then((res) => {
|
||||||
|
this.model = res.data
|
||||||
uni.setNavigationBarTitle({
|
uni.setNavigationBarTitle({
|
||||||
title: res.data.title
|
title: res.data.title
|
||||||
})
|
})
|
||||||
updateIssueAddViewNumber(this.dataId)
|
updateIssueAddViewNumber(this.dataId)
|
||||||
}).catch(() => {
|
})
|
||||||
|
.catch(() => {
|
||||||
this.isSuccess = false
|
this.isSuccess = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.view-title {
|
.view-content {
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.view-content {
|
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
padding: 12px 5px 0;
|
padding: 12px 5px 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="mine-container" :style="{height: `${windowHeight}px`}">
|
<view class="mine-container" :style="{ height: `${windowHeight}px` }">
|
||||||
<!--顶部个人信息栏-->
|
<!--顶部个人信息栏-->
|
||||||
<view class="header-section">
|
<view class="header-section">
|
||||||
<view class="flex padding justify-between">
|
<view class="flex padding justify-between">
|
||||||
@ -7,19 +7,23 @@
|
|||||||
<view v-if="!avatar" class="cu-avatar xl round bg-white">
|
<view v-if="!avatar" class="cu-avatar xl round bg-white">
|
||||||
<view class="iconfont icon-people text-gray icon"></view>
|
<view class="iconfont icon-people text-gray icon"></view>
|
||||||
</view>
|
</view>
|
||||||
<image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="aspectFill">
|
<image
|
||||||
|
v-if="avatar"
|
||||||
|
:src="avatar"
|
||||||
|
class="cu-avatar xl round"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="handleToAvatar"
|
||||||
|
>
|
||||||
</image>
|
</image>
|
||||||
<view v-if="!name" @click="handleToLogin" class="login-tip">
|
<view v-if="!name" class="login-tip" @click="handleToLogin"> 点击登录 </view>
|
||||||
点击登录
|
<view v-if="name" class="user-info" @click="handleToInfo">
|
||||||
</view>
|
|
||||||
<view v-if="name" @click="handleToInfo" class="user-info">
|
|
||||||
<view class="u_title">
|
<view class="u_title">
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view @click="handleToInfo" class="flex align-center">
|
<view class="flex align-center" @click="handleToInfo">
|
||||||
<text style="font-size: 30rpx;">个人信息</text>
|
<text style="font-size: 30rpx">个人信息</text>
|
||||||
<view class="iconfont icon-right1"></view>
|
<view class="iconfont icon-right1"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -41,7 +45,9 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="action-item" @click="praiseMe">
|
<view class="action-item" @click="praiseMe">
|
||||||
<view class="iconfont icon-dianzan text-green icon"></view>
|
<view class="iconfont icon-dianzan text-green icon"></view>
|
||||||
<view style="height: 0px;" :animation="animationData" class="praise-me animation-opacity"> +1 </view>
|
<view style="height: 0px" :animation="animationData" class="praise-me animation-opacity">
|
||||||
|
+1
|
||||||
|
</view>
|
||||||
<text class="text">点赞我们</text>
|
<text class="text">点赞我们</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -72,29 +78,26 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import storage from '@/common/utils/storage'
|
export default {
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
animation: "",
|
animation: '',
|
||||||
animationData: {}
|
animationData: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
// 1 在页面创建的时候,创建一个临时动画对象
|
// 1 在页面创建的时候,创建一个临时动画对象
|
||||||
this.animation = uni.createAnimation();
|
this.animation = uni.createAnimation()
|
||||||
this.animationData = {};
|
this.animationData = {}
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
// 5 页面卸载的时候,清除动画数据
|
// 5 页面卸载的时候,清除动画数据
|
||||||
this.animationData = {};
|
this.animationData = {}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
version() {
|
version() {
|
||||||
@ -150,43 +153,42 @@
|
|||||||
// 2 调用 step() 来表示一组动画完成
|
// 2 调用 step() 来表示一组动画完成
|
||||||
this.animation.translateY(-90).opacity(1).step({
|
this.animation.translateY(-90).opacity(1).step({
|
||||||
duration: 400
|
duration: 400
|
||||||
});
|
})
|
||||||
|
|
||||||
// 3 通过动画实例的export方法导出动画数据传递给组件的animation属性
|
// 3 通过动画实例的export方法导出动画数据传递给组件的animation属性
|
||||||
this.animationData = this.animation.export();
|
this.animationData = this.animation.export()
|
||||||
|
|
||||||
// 4 还原动画
|
// 4 还原动画
|
||||||
setTimeout(()=> {
|
setTimeout(() => {
|
||||||
this.animation.translateY(0).opacity(0).step({
|
this.animation.translateY(0).opacity(0).step({
|
||||||
duration: 0
|
duration: 0
|
||||||
});
|
})
|
||||||
this.animationData = this.animation.export();
|
this.animationData = this.animation.export()
|
||||||
}, 300)
|
}, 300)
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.praise-me {
|
.praise-me {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #feab2a;
|
color: #feab2a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.animation-opacity {
|
.animation-opacity {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
page {
|
page {
|
||||||
background-color: #f5f6f7;
|
background-color: #f5f6f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mine-container {
|
.mine-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
|
||||||
.header-section {
|
.header-section {
|
||||||
padding: 15px 15px 45px 15px;
|
padding: 15px 15px 45px 15px;
|
||||||
background-color: #3c96f3;
|
background-color: #3c96f3;
|
||||||
@ -238,5 +240,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,60 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<view style="padding: 20px;">
|
<view style="padding: 20px">
|
||||||
<u--form
|
<u--form ref="formRef" label-position="left" label-width="100px" :model="form" :rules="rules">
|
||||||
labelPosition="left"
|
<u-form-item label="用户姓名" prop="name" border-bottom :required="true">
|
||||||
labelWidth="100px"
|
<u--input v-model="form.name" placeholder="请输入用户姓名" border="none"></u--input>
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
ref="formRef"
|
|
||||||
>
|
|
||||||
<u-form-item
|
|
||||||
label="用户姓名"
|
|
||||||
prop="name"
|
|
||||||
borderBottom
|
|
||||||
:required="true"
|
|
||||||
>
|
|
||||||
<u--input
|
|
||||||
v-model="form.name"
|
|
||||||
placeholder="请输入用户姓名"
|
|
||||||
border="none"
|
|
||||||
></u--input>
|
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
<u-form-item
|
<u-form-item label="用户昵称" prop="nickname" border-bottom :required="false">
|
||||||
label="用户昵称"
|
<u--input v-model="form.nickname" placeholder="请输入用户昵称" border="none"></u--input>
|
||||||
prop="nickname"
|
|
||||||
borderBottom
|
|
||||||
:required="false"
|
|
||||||
>
|
|
||||||
<u--input
|
|
||||||
v-model="form.nickname"
|
|
||||||
placeholder="请输入用户昵称"
|
|
||||||
border="none"
|
|
||||||
></u--input>
|
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
<u-form-item
|
<u-form-item label="手机号码" prop="telephone" border-bottom :required="true">
|
||||||
label="手机号码"
|
<u--input v-model="form.telephone" placeholder="请输入手机号码" border="none"></u--input>
|
||||||
prop="telephone"
|
|
||||||
borderBottom
|
|
||||||
:required="true"
|
|
||||||
>
|
|
||||||
<u--input
|
|
||||||
v-model="form.telephone"
|
|
||||||
placeholder="请输入手机号码"
|
|
||||||
border="none"
|
|
||||||
></u--input>
|
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
<u-form-item
|
<u-form-item label="用户性别" prop="gender" border-bottom :required="false">
|
||||||
label="用户性别"
|
|
||||||
prop="gender"
|
|
||||||
borderBottom
|
|
||||||
:required="false"
|
|
||||||
>
|
|
||||||
<u-radio-group v-model="form.gender">
|
<u-radio-group v-model="form.gender">
|
||||||
<u-radio
|
<u-radio
|
||||||
:customStyle="{marginRight: '16px'}"
|
|
||||||
v-for="(item, index) in genderOptions"
|
v-for="(item, index) in genderOptions"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
:custom-style="{ marginRight: '16px' }"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:name="item.value"
|
:name="item.value"
|
||||||
>
|
>
|
||||||
@ -62,32 +24,26 @@
|
|||||||
</u-radio-group>
|
</u-radio-group>
|
||||||
</u-form-item>
|
</u-form-item>
|
||||||
</u--form>
|
</u--form>
|
||||||
<view style="margin-top: 20px;">
|
<view style="margin-top: 20px">
|
||||||
<u-button
|
<u-button :loading="btnLoading" type="primary" text="提交" @click="submit"> </u-button>
|
||||||
:loading="btnLoading"
|
|
||||||
type="primary"
|
|
||||||
@click="submit"
|
|
||||||
text="提交"
|
|
||||||
>
|
|
||||||
</u-button>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getInfo } from '@/common/request/api/login'
|
import { getInfo } from '@/common/request/api/login'
|
||||||
import { updateCurrentUser } from '@/common/request/api/vadmin/auth/user.js'
|
import { updateCurrentUser } from '@/common/request/api/vadmin/auth/user.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
btnLoading: false,
|
btnLoading: false,
|
||||||
form: {
|
form: {
|
||||||
name: "",
|
name: '',
|
||||||
nickname: "",
|
nickname: '',
|
||||||
telephone: "",
|
telephone: '',
|
||||||
gender: ""
|
gender: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
name: {
|
name: {
|
||||||
@ -107,11 +63,11 @@
|
|||||||
validator: (rule, value, callback) => {
|
validator: (rule, value, callback) => {
|
||||||
// 上面有说,返回true表示校验通过,返回false表示不通过
|
// 上面有说,返回true表示校验通过,返回false表示不通过
|
||||||
// uni.$u.test.mobile()就是返回true或者false的
|
// uni.$u.test.mobile()就是返回true或者false的
|
||||||
return uni.$u.test.mobile(value);
|
return uni.$u.test.mobile(value)
|
||||||
},
|
},
|
||||||
message: '手机号码不正确',
|
message: '手机号码不正确',
|
||||||
// 触发器可以同时用blur和change
|
// 触发器可以同时用blur和change
|
||||||
trigger: ['change','blur'],
|
trigger: ['change', 'blur']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -119,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.$store.dispatch('dict/getDicts', ["sys_vadmin_gender"]).then(result => {
|
this.$store.dispatch('dict/getDicts', ['sys_vadmin_gender']).then((result) => {
|
||||||
this.genderOptions = result.sys_vadmin_gender
|
this.genderOptions = result.sys_vadmin_gender
|
||||||
})
|
})
|
||||||
// this.resetForm()
|
// this.resetForm()
|
||||||
@ -132,37 +88,41 @@
|
|||||||
methods: {
|
methods: {
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.form = {
|
this.form = {
|
||||||
name: "",
|
name: '',
|
||||||
nickname: "",
|
nickname: '',
|
||||||
telephone: "",
|
telephone: '',
|
||||||
gender: ""
|
gender: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getUser() {
|
getUser() {
|
||||||
this.$modal.loading("加载中")
|
this.$modal.loading('加载中')
|
||||||
getInfo().then(res => {
|
getInfo()
|
||||||
|
.then((res) => {
|
||||||
this.form = res.data
|
this.form = res.data
|
||||||
}).finally(() => {
|
})
|
||||||
|
.finally(() => {
|
||||||
this.$modal.closeLoading()
|
this.$modal.closeLoading()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
submit(ref) {
|
submit(ref) {
|
||||||
this.$refs.formRef.validate().then(res => {
|
this.$refs.formRef.validate().then((res) => {
|
||||||
this.btnLoading = true
|
this.btnLoading = true
|
||||||
updateCurrentUser(this.form).then(res => {
|
updateCurrentUser(this.form)
|
||||||
|
.then((res) => {
|
||||||
this.$store.dispatch('auth/UpdateInfo', res.data)
|
this.$store.dispatch('auth/UpdateInfo', res.data)
|
||||||
this.$modal.msgSuccess("更新成功");
|
this.$modal.msgSuccess('更新成功')
|
||||||
}).finally(() => {
|
})
|
||||||
|
.finally(() => {
|
||||||
this.btnLoading = false
|
this.btnLoading = false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
name() {
|
name() {
|
||||||
return this.$store.state.auth.name
|
return this.$store.state.auth.name
|
||||||
@ -38,12 +38,12 @@
|
|||||||
createDatetime() {
|
createDatetime() {
|
||||||
return this.$store.state.auth.createDatetime
|
return this.$store.state.auth.createDatetime
|
||||||
}
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,30 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="pwd-retrieve-container">
|
<view class="pwd-retrieve-container">
|
||||||
<view class="header">
|
<uni-forms ref="form" :value="form" label-width="80px">
|
||||||
<u--text
|
|
||||||
v-if="!isResetPassword"
|
|
||||||
text="第一次进入系统,必须先重置密码。"
|
|
||||||
:size="33"
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
</u--text>
|
|
||||||
</view>
|
|
||||||
<uni-forms ref="form" :value="form" labelWidth="80px">
|
|
||||||
<uni-forms-item name="newPassword" label="新密码">
|
<uni-forms-item name="newPassword" label="新密码">
|
||||||
<uni-easyinput type="password" v-model="form.password" placeholder="请输入新密码" />
|
<uni-easyinput v-model="form.password" type="password" placeholder="请输入新密码" />
|
||||||
</uni-forms-item>
|
</uni-forms-item>
|
||||||
<uni-forms-item name="confirmPassword" label="确认密码">
|
<uni-forms-item name="confirmPassword" label="确认密码">
|
||||||
<uni-easyinput type="password" v-model="form.password_two" placeholder="请确认新密码" />
|
<uni-easyinput v-model="form.password_two" type="password" placeholder="请确认新密码" />
|
||||||
</uni-forms-item>
|
</uni-forms-item>
|
||||||
<u-button text="提交" @click="submit" type="primary"></u-button>
|
<u-button text="提交" color="#e09bc7" @click="submit"></u-button>
|
||||||
</uni-forms>
|
</uni-forms>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { postCurrentUserResetPassword } from '@/common/request/api/vadmin/auth/user.js'
|
import { postCurrentUserResetPassword } from '@/common/request/api/vadmin/auth/user.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
@ -33,9 +24,10 @@
|
|||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
password: {
|
password: {
|
||||||
rules: [{
|
rules: [
|
||||||
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '新密码不能为空',
|
errorMessage: '新密码不能为空'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
minLength: 8,
|
minLength: 8,
|
||||||
@ -45,10 +37,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
password_two: {
|
password_two: {
|
||||||
rules: [{
|
rules: [
|
||||||
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '确认密码不能为空'
|
errorMessage: '确认密码不能为空'
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
validateFunction: (rule, value, data) => data.password === value,
|
validateFunction: (rule, value, data) => data.password === value,
|
||||||
errorMessage: '两次输入的密码不一致'
|
errorMessage: '两次输入的密码不一致'
|
||||||
}
|
}
|
||||||
@ -57,48 +51,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
isResetPassword() {
|
|
||||||
return this.$store.state.auth.isResetPassword
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onReady() {
|
onReady() {
|
||||||
this.$refs.form.setRules(this.rules)
|
this.$refs.form.setRules(this.rules)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
submit() {
|
submit() {
|
||||||
this.$refs.form.validate().then(res => {
|
this.$refs.form.validate().then((res) => {
|
||||||
this.$modal.loading("正在提交")
|
this.$modal.loading('正在提交')
|
||||||
postCurrentUserResetPassword(this.form).then(response => {
|
postCurrentUserResetPassword(this.form)
|
||||||
|
.then((response) => {
|
||||||
this.form = {
|
this.form = {
|
||||||
password: "",
|
password: '',
|
||||||
password_two: ""
|
password_two: ''
|
||||||
}
|
}
|
||||||
this.$modal.msgSuccess("重置成功")
|
this.$modal.msgSuccess('修改成功')
|
||||||
if (!this.isResetPassword) {
|
})
|
||||||
this.$store.commit('auth/SET_IS_RESET_PASSWORD', true)
|
.finally(() => {
|
||||||
this.$tab.reLaunch('/pages/index')
|
|
||||||
}
|
|
||||||
}).finally(() => {
|
|
||||||
this.$modal.closeLoading()
|
this.$modal.closeLoading()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pwd-retrieve-container {
|
.pwd-retrieve-container {
|
||||||
padding-top: 36rpx;
|
padding-top: 36rpx;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
}
|
||||||
.header {
|
|
||||||
padding-bottom: 36rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="setting-container" :style="{height: `${windowHeight}px`}">
|
<view class="setting-container" :style="{ height: `${windowHeight}px` }">
|
||||||
<view class="menu-list">
|
<view class="menu-list">
|
||||||
<view class="list-cell list-cell-arrow" @click="handleToPwd">
|
<view class="list-cell list-cell-arrow" @click="handleToPwd">
|
||||||
<view class="menu-item-box">
|
<view class="menu-item-box">
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
windowHeight: uni.getSystemInfoSync().windowHeight
|
windowHeight: uni.getSystemInfoSync().windowHeight
|
||||||
@ -53,16 +53,16 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.page {
|
.page {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-box {
|
.item-box {
|
||||||
background-color: #FFFFFF;
|
background-color: #ffffff;
|
||||||
margin: 30rpx;
|
margin: 30rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -72,5 +72,5 @@
|
|||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
color: #303133;
|
color: #303133;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -4,25 +4,18 @@
|
|||||||
<u-swiper
|
<u-swiper
|
||||||
:list="images"
|
:list="images"
|
||||||
indicator
|
indicator
|
||||||
indicatorMode="line"
|
indicator-mode="line"
|
||||||
circular
|
circular
|
||||||
:height="`${windowWidth / 2.5}px`"
|
:height="`${windowWidth / 2.5}px`"
|
||||||
></u-swiper>
|
></u-swiper>
|
||||||
|
|
||||||
<!-- 宫格组件 -->
|
<!-- 宫格组件 -->
|
||||||
<view class="grid-body">
|
<view class="grid-body">
|
||||||
<u-grid
|
<u-grid :border="false" col="3" @click="changeGrid">
|
||||||
:border="false"
|
<u-grid-item v-for="(item, index) in baseList" :key="index">
|
||||||
col="3"
|
|
||||||
@click="changeGrid"
|
|
||||||
>
|
|
||||||
<u-grid-item
|
|
||||||
v-for="(item, index) in baseList"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<view class="grid-item">
|
<view class="grid-item">
|
||||||
<view :class="'iconfont ' + item.icon + ' grid-icon'"></view>
|
<view :class="'iconfont ' + item.icon + ' grid-icon'"></view>
|
||||||
<u--text :text="item.title" align="center" lineHeight="32px"></u--text>
|
<u--text :text="item.title" align="center" line-height="32px"></u--text>
|
||||||
</view>
|
</view>
|
||||||
</u-grid-item>
|
</u-grid-item>
|
||||||
</u-grid>
|
</u-grid>
|
||||||
@ -31,7 +24,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
windowWidth: uni.getSystemInfoSync().windowWidth,
|
windowWidth: uni.getSystemInfoSync().windowWidth,
|
||||||
@ -64,7 +57,7 @@
|
|||||||
{
|
{
|
||||||
icon: 'icon-rizhi',
|
icon: 'icon-rizhi',
|
||||||
title: '日志管理'
|
title: '日志管理'
|
||||||
},
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -73,19 +66,19 @@
|
|||||||
this.$modal.showToast('模块建设中~')
|
this.$modal.showToast('模块建设中~')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
page {
|
page {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.grid-body {
|
.grid-body {
|
||||||
margin-top: 60rpx;
|
margin-top: 60rpx;
|
||||||
|
|
||||||
.grid-item {
|
.grid-item {
|
||||||
@ -96,5 +89,5 @@
|
|||||||
.grid-icon {
|
.grid-icon {
|
||||||
font-size: 40rpx;
|
font-size: 40rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
import { getToken } from '@/common/utils/auth'
|
import { getToken } from '@/common/utils/auth'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import { RouterMount, createRouter } from 'uni-simple-router';
|
import { RouterMount, createRouter } from 'uni-simple-router'
|
||||||
|
|
||||||
|
// uni-simple-router 官方文档:https://www.hhyang.cn/v2/start/cross/codeRoute.html
|
||||||
|
|
||||||
// 登录页面
|
// 登录页面
|
||||||
const loginPage = "/pages/login/login"
|
const loginPage = '/pages/login/login'
|
||||||
|
// 首页
|
||||||
|
const indexPage = '/pages/index'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
platform: process.env.VUE_APP_PLATFORM,
|
platform: process.env.VUE_APP_PLATFORM,
|
||||||
routes: [...ROUTES]
|
detectBeforeLock: (router, to, navType) => {
|
||||||
});
|
if (navType === 'replaceAll' && (to.path === loginPage || to.path === indexPage)) {
|
||||||
|
router.$lockStatus = false // 取消跳转锁
|
||||||
|
}
|
||||||
|
},
|
||||||
|
routes: [...ROUTES] // ROUTES是通过webpack的defaultPlugin编译成全局变量
|
||||||
|
})
|
||||||
|
|
||||||
//全局路由前置守卫
|
//全局路由前置守卫
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
@ -20,11 +29,11 @@ router.beforeEach((to, from, next) => {
|
|||||||
}
|
}
|
||||||
if (to.path === loginPage) {
|
if (to.path === loginPage) {
|
||||||
next({
|
next({
|
||||||
path: `/pages/index`,
|
path: indexPage,
|
||||||
NAVTYPE: 'replaceAll'
|
NAVTYPE: 'replaceAll'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
next();
|
next()
|
||||||
} else {
|
} else {
|
||||||
next({
|
next({
|
||||||
path: loginPage,
|
path: loginPage,
|
||||||
@ -34,21 +43,18 @@ router.beforeEach((to, from, next) => {
|
|||||||
} else if (to.path === loginPage && getToken()) {
|
} else if (to.path === loginPage && getToken()) {
|
||||||
// 如果跳转路由为登录页面并且存在token,则跳转到首页
|
// 如果跳转路由为登录页面并且存在token,则跳转到首页
|
||||||
next({
|
next({
|
||||||
path: `/pages/index`,
|
path: indexPage,
|
||||||
NAVTYPE: 'replaceAll'
|
NAVTYPE: 'replaceAll'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 不需要权限,且不是登录页面则不进行验证
|
// 不需要权限,且不是登录页面则不进行验证
|
||||||
next();
|
next()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
// 全局路由后置守卫
|
// 全局路由后置守卫
|
||||||
router.afterEach((to, from) => {
|
router.afterEach((to, from) => {
|
||||||
// console.log('跳转结束')
|
// console.log('跳转结束')
|
||||||
})
|
})
|
||||||
|
|
||||||
export {
|
export { router, RouterMount }
|
||||||
router,
|
|
||||||
RouterMount
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
function authPermission(permission) {
|
function authPermission(permission) {
|
||||||
const all_permission = "*:*:*"
|
const all_permission = '*:*:*'
|
||||||
const permissions = store.getters && store.getters.permissions
|
const permissions = store.getters && store.getters.permissions
|
||||||
if (permission && permission.length > 0) {
|
if (permission && permission.length > 0) {
|
||||||
return permissions.some(v => {
|
return permissions.some((v) => {
|
||||||
return all_permission === v || v === permission
|
return all_permission === v || v === permission
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -13,10 +13,10 @@ function authPermission(permission) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function authRole(role) {
|
function authRole(role) {
|
||||||
const super_admin = "admin"
|
const super_admin = 'admin'
|
||||||
const roles = store.getters && store.getters.roles
|
const roles = store.getters && store.getters.roles
|
||||||
if (role && role.length > 0) {
|
if (role && role.length > 0) {
|
||||||
return roles.some(v => {
|
return roles.some((v) => {
|
||||||
return super_admin === v || v === role
|
return super_admin === v || v === role
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -31,13 +31,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 验证用户是否含有指定权限,只需包含其中一个
|
// 验证用户是否含有指定权限,只需包含其中一个
|
||||||
hasPermiOr(permissions) {
|
hasPermiOr(permissions) {
|
||||||
return permissions.some(item => {
|
return permissions.some((item) => {
|
||||||
return authPermission(item)
|
return authPermission(item)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 验证用户是否含有指定权限,必须全部拥有
|
// 验证用户是否含有指定权限,必须全部拥有
|
||||||
hasPermiAnd(permissions) {
|
hasPermiAnd(permissions) {
|
||||||
return permissions.every(item => {
|
return permissions.every((item) => {
|
||||||
return authPermission(item)
|
return authPermission(item)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -47,13 +47,13 @@ export default {
|
|||||||
},
|
},
|
||||||
// 验证用户是否含有指定角色,只需包含其中一个
|
// 验证用户是否含有指定角色,只需包含其中一个
|
||||||
hasRoleOr(roles) {
|
hasRoleOr(roles) {
|
||||||
return roles.some(item => {
|
return roles.some((item) => {
|
||||||
return authRole(item)
|
return authRole(item)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 验证用户是否含有指定角色,必须全部拥有
|
// 验证用户是否含有指定角色,必须全部拥有
|
||||||
hasRoleAnd(roles) {
|
hasRoleAnd(roles) {
|
||||||
return roles.every(item => {
|
return roles.every((item) => {
|
||||||
return authRole(item)
|
return authRole(item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ export default {
|
|||||||
content: content,
|
content: content,
|
||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
confirmText: '确定',
|
confirmText: '确定',
|
||||||
success: function(res) {
|
success: function (res) {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
resolve(res.confirm)
|
resolve(res.confirm)
|
||||||
}
|
}
|
||||||
@ -50,12 +50,12 @@ export default {
|
|||||||
},
|
},
|
||||||
// 提示信息
|
// 提示信息
|
||||||
showToast(option) {
|
showToast(option) {
|
||||||
if (typeof option === "object") {
|
if (typeof option === 'object') {
|
||||||
uni.showToast(option)
|
uni.showToast(option)
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: option,
|
title: option,
|
||||||
icon: "none",
|
icon: 'none',
|
||||||
duration: 2500
|
duration: 2500
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
19
kinit-uni/prettier.config.js
Normal file
19
kinit-uni/prettier.config.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
module.exports = {
|
||||||
|
printWidth: 100,
|
||||||
|
tabWidth: 2,
|
||||||
|
useTabs: false,
|
||||||
|
semi: false,
|
||||||
|
vueIndentScriptAndStyle: false,
|
||||||
|
singleQuote: true,
|
||||||
|
quoteProps: 'as-needed',
|
||||||
|
bracketSpacing: true,
|
||||||
|
trailingComma: 'none',
|
||||||
|
jsxSingleQuote: false,
|
||||||
|
arrowParens: 'always',
|
||||||
|
insertPragma: false,
|
||||||
|
requirePragma: false,
|
||||||
|
proseWrap: 'never',
|
||||||
|
htmlWhitespaceSensitivity: 'strict',
|
||||||
|
endOfLine: 'auto',
|
||||||
|
rangeStart: 0
|
||||||
|
}
|
@ -1,26 +1,26 @@
|
|||||||
const getters = {
|
const getters = {
|
||||||
isUser: state => state.auth.isUser,
|
isUser: (state) => state.auth.isUser,
|
||||||
isUserOpenid: state => state.auth.isUserOpenid,
|
isUserOpenid: (state) => state.auth.isUserOpenid,
|
||||||
isResetPassword: state => state.auth.isResetPassword,
|
isResetPassword: (state) => state.auth.isResetPassword,
|
||||||
token: state => state.auth.token,
|
token: (state) => state.auth.token,
|
||||||
avatar: state => state.auth.avatar,
|
avatar: (state) => state.auth.avatar,
|
||||||
name: state => state.auth.name,
|
name: (state) => state.auth.name,
|
||||||
roles: state => state.auth.roles,
|
roles: (state) => state.auth.roles,
|
||||||
permissions: state => state.auth.permissions,
|
permissions: (state) => state.auth.permissions,
|
||||||
telephone: state => state.auth.telephone,
|
telephone: (state) => state.auth.telephone,
|
||||||
|
|
||||||
version: state => state.app.version,
|
version: (state) => state.app.version,
|
||||||
title: state => state.app.title,
|
title: (state) => state.app.title,
|
||||||
logo: state => state.app.logo,
|
logo: (state) => state.app.logo,
|
||||||
logoImage: state => state.app.logoImage,
|
logoImage: (state) => state.app.logoImage,
|
||||||
footer: state => state.app.footer,
|
footer: (state) => state.app.footer,
|
||||||
footerContent: state => state.app.footerContent,
|
footerContent: (state) => state.app.footerContent,
|
||||||
icpNumber: state => state.app.icpNumber,
|
icpNumber: (state) => state.app.icpNumber,
|
||||||
privacy: state => state.app.privacy,
|
privacy: (state) => state.app.privacy,
|
||||||
agreement: state => state.app.agreement,
|
agreement: (state) => state.app.agreement,
|
||||||
siteUrl: state => state.app.siteUrl,
|
siteUrl: (state) => state.app.siteUrl,
|
||||||
WXEmail: state => state.app.WXEmail,
|
WXEmail: (state) => state.app.WXEmail,
|
||||||
WXPhone: state => state.app.WXPhone,
|
WXPhone: (state) => state.app.WXPhone,
|
||||||
dictObj: state => state.dict.dictObj,
|
dictObj: (state) => state.dict.dictObj
|
||||||
}
|
}
|
||||||
export default getters
|
export default getters
|
||||||
|
@ -2,7 +2,7 @@ import config from '@/config.js'
|
|||||||
import { getSystemBaseConfigApi } from '@/common/request/api/vadmin/system/settings.js'
|
import { getSystemBaseConfigApi } from '@/common/request/api/vadmin/system/settings.js'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
title: "", // 标题
|
title: '', // 标题
|
||||||
logo: true, // 是否开启logo显示
|
logo: true, // 是否开启logo显示
|
||||||
logoImage: '', // logo图片
|
logoImage: '', // logo图片
|
||||||
footer: true, // 显示页脚
|
footer: true, // 显示页脚
|
||||||
@ -11,9 +11,9 @@ const state = {
|
|||||||
version: config.appInfo.version, // 版本
|
version: config.appInfo.version, // 版本
|
||||||
privacy: config.appInfo.privacy, // 隐私政策
|
privacy: config.appInfo.privacy, // 隐私政策
|
||||||
agreement: config.appInfo.agreement, // 用户协议
|
agreement: config.appInfo.agreement, // 用户协议
|
||||||
siteUrl: "", // 源码地址
|
siteUrl: '', // 源码地址
|
||||||
WXEmail: "", // 官方邮箱
|
WXEmail: '', // 官方邮箱
|
||||||
WXPhone: "" // 服务热线
|
WXPhone: '' // 服务热线
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
@ -46,14 +46,15 @@ const mutations = {
|
|||||||
},
|
},
|
||||||
SET_WX_PHONE: (state, WXPhone) => {
|
SET_WX_PHONE: (state, WXPhone) => {
|
||||||
state.WXPhone = WXPhone
|
state.WXPhone = WXPhone
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
// 初始化系统配置
|
// 初始化系统配置
|
||||||
InitConfig({ commit }) {
|
InitConfig({ commit }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getSystemBaseConfigApi().then(res => {
|
getSystemBaseConfigApi()
|
||||||
|
.then((res) => {
|
||||||
commit('SET_TITLE', res.data.web_title || 'Kinit')
|
commit('SET_TITLE', res.data.web_title || 'Kinit')
|
||||||
commit('SET_LOGO_IMAGE', config.baseUrl + (res.data.web_logo || '/media/system/logo.png'))
|
commit('SET_LOGO_IMAGE', config.baseUrl + (res.data.web_logo || '/media/system/logo.png'))
|
||||||
commit('SET_FOOTER_CONTENT', res.data.web_copyright || 'Copyright ©2022-present K')
|
commit('SET_FOOTER_CONTENT', res.data.web_copyright || 'Copyright ©2022-present K')
|
||||||
@ -62,14 +63,14 @@ const actions = {
|
|||||||
commit('SET_WX_EMAIL', res.data.wx_server_email || '')
|
commit('SET_WX_EMAIL', res.data.wx_server_email || '')
|
||||||
commit('SET_WX_PHONE', res.data.wx_server_phone || '')
|
commit('SET_WX_PHONE', res.data.wx_server_phone || '')
|
||||||
resolve()
|
resolve()
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
||||||
state,
|
state,
|
||||||
|
@ -1,10 +1,18 @@
|
|||||||
import storage from '@/common/utils/storage'
|
import storage from '@/common/utils/storage'
|
||||||
import { auth } from '@/common/utils/constant'
|
import { auth } from '@/common/utils/constant'
|
||||||
import { getInfo, wxCodeLogin, login } from '@/common/request/api/login'
|
import { getInfo, wxCodeLogin, login } from '@/common/request/api/login'
|
||||||
import { getToken, setToken, removeToken } from '@/common/utils/auth'
|
import {
|
||||||
|
getToken,
|
||||||
|
setToken,
|
||||||
|
removeToken,
|
||||||
|
getRefreshToken,
|
||||||
|
setRefreshToken,
|
||||||
|
removeRefreshToken
|
||||||
|
} from '@/common/utils/auth'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
token: getToken(),
|
token: getToken(),
|
||||||
|
refreshToken: getRefreshToken(),
|
||||||
isUser: storage.get(auth.isUser) || false,
|
isUser: storage.get(auth.isUser) || false,
|
||||||
isUserOpenid: storage.get(auth.isUserOpenid) || false,
|
isUserOpenid: storage.get(auth.isUserOpenid) || false,
|
||||||
isResetPassword: storage.get(auth.isResetPassword) || false,
|
isResetPassword: storage.get(auth.isResetPassword) || false,
|
||||||
@ -22,6 +30,10 @@ const mutations = {
|
|||||||
SET_TOKEN: (state, token) => {
|
SET_TOKEN: (state, token) => {
|
||||||
state.token = token
|
state.token = token
|
||||||
},
|
},
|
||||||
|
SET_REFRESH_TOKEN: (state, refreshToken) => {
|
||||||
|
state.refreshToken = refreshToken
|
||||||
|
setRefreshToken(refreshToken)
|
||||||
|
},
|
||||||
SET_IS_USER_OPENID: (state, isUserOpenid) => {
|
SET_IS_USER_OPENID: (state, isUserOpenid) => {
|
||||||
state.isUserOpenid = isUserOpenid
|
state.isUserOpenid = isUserOpenid
|
||||||
storage.set(auth.isUserOpenid, isUserOpenid)
|
storage.set(auth.isUserOpenid, isUserOpenid)
|
||||||
@ -65,7 +77,7 @@ const mutations = {
|
|||||||
SET_ISUSER: (state, isUser) => {
|
SET_ISUSER: (state, isUser) => {
|
||||||
state.isUser = isUser
|
state.isUser = isUser
|
||||||
storage.set(auth.isUser, isUser)
|
storage.set(auth.isUser, isUser)
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
@ -74,13 +86,16 @@ const actions = {
|
|||||||
const telephone = userInfo.telephone.trim()
|
const telephone = userInfo.telephone.trim()
|
||||||
const password = userInfo.password
|
const password = userInfo.password
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login(telephone, password).then(res => {
|
login(telephone, password)
|
||||||
|
.then((res) => {
|
||||||
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
||||||
commit('SET_TOKEN', `${res.data.token_type} ${res.data.access_token}`)
|
commit('SET_TOKEN', `${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
commit('SET_REFRESH_TOKEN', res.data.refresh_token)
|
||||||
commit('SET_IS_USER_OPENID', res.data.is_wx_server_openid)
|
commit('SET_IS_USER_OPENID', res.data.is_wx_server_openid)
|
||||||
commit('SET_IS_RESET_PASSWORD', res.data.is_reset_password)
|
commit('SET_IS_RESET_PASSWORD', res.data.is_reset_password)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -90,13 +105,16 @@ const actions = {
|
|||||||
// 微信文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
|
// 微信文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
|
||||||
wxLogin({ commit }, code) {
|
wxLogin({ commit }, code) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
wxCodeLogin(code).then(res => {
|
wxCodeLogin(code)
|
||||||
|
.then((res) => {
|
||||||
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
setToken(`${res.data.token_type} ${res.data.access_token}`)
|
||||||
commit('SET_TOKEN', `${res.data.token_type} ${res.data.access_token}`)
|
commit('SET_TOKEN', `${res.data.token_type} ${res.data.access_token}`)
|
||||||
|
commit('SET_REFRESH_TOKEN', res.data.refresh_token)
|
||||||
commit('SET_IS_USER_OPENID', res.data.is_wx_server_openid)
|
commit('SET_IS_USER_OPENID', res.data.is_wx_server_openid)
|
||||||
commit('SET_IS_RESET_PASSWORD', res.data.is_reset_password)
|
commit('SET_IS_RESET_PASSWORD', res.data.is_reset_password)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -105,10 +123,14 @@ const actions = {
|
|||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
GetInfo({ commit }) {
|
GetInfo({ commit }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getInfo().then(res => {
|
getInfo()
|
||||||
|
.then((res) => {
|
||||||
const user = res.data
|
const user = res.data
|
||||||
const avatar = (user == null || user.avatar == "" || user.avatar == null) ? "https://vv-reserve.oss-cn-hangzhou.aliyuncs.com/avatar/2023-01-27/1674820804e81e7631.png" : user.avatar
|
const avatar =
|
||||||
const name = (user == null || user.name == "" || user.name == null) ? "" : user.name
|
user == null || user.avatar == '' || user.avatar == null
|
||||||
|
? 'https://vv-reserve.oss-cn-hangzhou.aliyuncs.com/avatar/2023-01-27/1674820804e81e7631.png'
|
||||||
|
: user.avatar
|
||||||
|
const name = user == null || user.name == '' || user.name == null ? '' : user.name
|
||||||
commit('SET_ROLES', user.roles.map((item) => item.name) || ['ROLE_DEFAULT'])
|
commit('SET_ROLES', user.roles.map((item) => item.name) || ['ROLE_DEFAULT'])
|
||||||
commit('SET_PERMISSIONS', user.permissions)
|
commit('SET_PERMISSIONS', user.permissions)
|
||||||
commit('SET_NAME', name)
|
commit('SET_NAME', name)
|
||||||
@ -119,7 +141,8 @@ const actions = {
|
|||||||
commit('SET_CREATE_DATETIME', user.create_datetime)
|
commit('SET_CREATE_DATETIME', user.create_datetime)
|
||||||
commit('SET_ISUSER', true)
|
commit('SET_ISUSER', true)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -137,26 +160,31 @@ const actions = {
|
|||||||
LogOut({ commit }) {
|
LogOut({ commit }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
commit('SET_TOKEN', '')
|
commit('SET_TOKEN', '')
|
||||||
|
commit('SET_REFRESH_TOKEN', '')
|
||||||
commit('SET_ROLES', [])
|
commit('SET_ROLES', [])
|
||||||
commit('SET_PERMISSIONS', [])
|
commit('SET_PERMISSIONS', [])
|
||||||
commit('SET_NAME', "")
|
commit('SET_NAME', '')
|
||||||
commit('SET_NICKNAME', "")
|
commit('SET_NICKNAME', '')
|
||||||
commit('SET_GENDER', "")
|
commit('SET_GENDER', '')
|
||||||
commit('SET_TELEPHONE', "")
|
commit('SET_TELEPHONE', '')
|
||||||
commit('SET_AVATAR', "")
|
commit('SET_AVATAR', '')
|
||||||
commit('SET_CREATE_DATETIME', "")
|
commit('SET_CREATE_DATETIME', '')
|
||||||
commit('SET_IS_USER_OPENID', false)
|
commit('SET_IS_USER_OPENID', false)
|
||||||
commit('SET_IS_RESET_PASSWORD', false)
|
commit('SET_IS_RESET_PASSWORD', false)
|
||||||
commit('SET_ISUSER', false)
|
commit('SET_ISUSER', false)
|
||||||
removeToken()
|
removeToken()
|
||||||
|
removeRefreshToken()
|
||||||
storage.clean()
|
storage.clean()
|
||||||
uni.reLaunch({ url: '/pages/login/login' })
|
uni.reLaunch({
|
||||||
|
url: '/pages/login/login',
|
||||||
|
complete: () => {
|
||||||
resolve()
|
resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
||||||
state,
|
state,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { getDictTypeDetailsApi } from '@/common/request/api/vadmin/system/dict.js'
|
import { getDictTypeDetailsApi } from '@/common/request/api/vadmin/system/dict.js'
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
dictObj: {}, // 字典元素
|
dictObj: {} // 字典元素
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
@ -26,14 +26,16 @@ const actions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (addList.length > 0) {
|
if (addList.length > 0) {
|
||||||
getDictTypeDetailsApi(addList).then(res => {
|
getDictTypeDetailsApi(addList)
|
||||||
|
.then((res) => {
|
||||||
for (const item of addList) {
|
for (const item of addList) {
|
||||||
result[item] = res.data[item]
|
result[item] = res.data[item]
|
||||||
dictObj[item] = res.data[item]
|
dictObj[item] = res.data[item]
|
||||||
}
|
}
|
||||||
commit('SET_DICT_OBJ', dictObj)
|
commit('SET_DICT_OBJ', dictObj)
|
||||||
resolve(result)
|
resolve(result)
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -43,7 +45,6 @@ const actions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
namespaced: true, // 使用命名空间去访问模块中属性,user/login
|
||||||
state,
|
state,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//vue.config.js
|
//vue.config.js
|
||||||
const TransformPages = require('uni-read-pages')
|
const TransformPages = require('uni-read-pages')
|
||||||
const {webpack} = new TransformPages()
|
const { webpack } = new TransformPages()
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
@ -12,9 +12,9 @@ module.exports = {
|
|||||||
// 后续如果有用到meta等路由信息,可以在 includes 里增加 'meta',
|
// 后续如果有用到meta等路由信息,可以在 includes 里增加 'meta',
|
||||||
// 在pages路由中写对应的数据,router中就可以获取得到
|
// 在pages路由中写对应的数据,router中就可以获取得到
|
||||||
includes: ['path', 'name', 'aliasPath', 'meta']
|
includes: ['path', 'name', 'aliasPath', 'meta']
|
||||||
});
|
})
|
||||||
return JSON.stringify(tfPages.routes)
|
return JSON.stringify(tfPages.routes)
|
||||||
}, true )
|
}, true)
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user