feat: 端点登录

This commit is contained in:
caijun
2026-01-25 20:22:58 +08:00
parent f9e1a0cc18
commit f43f2ff3c2
12 changed files with 551 additions and 444 deletions

View File

@@ -90,6 +90,15 @@ export function getAdapterUserList(data, options) {
}
})
}
// 社交授权的跳转
export function socialAuthRedirect(type, redirectUri) {
return request({
url: '/admin-api/system/auth/social-auth-redirect?type=' + type + '&redirectUri=' + redirectUri,
method: 'GET'
})
}
// 获取人员角色
export function getAdapterRoleList() {
return request({
@@ -239,13 +248,18 @@ export function getPermissionInfo() {
}
// 获取token
export function socialLogin(token) {
export function socialLogin(type, code, state) {
console.log(type,code,state,'data数据---')
return request({
url: '/admin-api/system/auth/social-login',
method: 'post',
token,
data: {
type,
code,
state
},
header: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Type': 'application/json',
}
})
}

View File

@@ -1,6 +1,6 @@
{
"name" : "jnpf java vue3版",
"appid": "__UNI__663111E",
"appid" : "__UNI__55507A7",
"description" : "专注信息化平台、软件开发、app开发",
"versionName" : "1.0.0",
"versionCode" : "100",
@@ -235,3 +235,4 @@
}
}
/* 5+App */

View File

@@ -56,13 +56,16 @@
</view>
<!-- 底部操作按钮区域 -->
<view v-if="!loading && (!(dataForm.approveStatus == 1 || dataForm.approveStatus == 2 || dataForm.approveStatus == 4) || !dataForm.id || config.current && config.current == 2)" class="buttom-actions">
<view v-if="!loading && (dataForm.approveStatus != 4 || !dataForm.id || config.current && config.current == 2) && !isProcess" class="buttom-actions">
<u-button v-if="(!dataForm.approveStatus && dataForm.id) || dataForm.approveStatus == 3" class="buttom-btn launch-flow-btn" type="primary" @click.stop="handleLaunchFlow" :disabled="idDsabled" :loading="btnLoading">
发起流程
</u-button>
<u-button v-if="!config.current" class="buttom-btn" type="primary" @click.stop="submit" :disabled="idDsabled" :loading="btnLoading">
<u-button v-if="!config.current && !dataForm.approveStatus" class="buttom-btn" type="primary" @click.stop="submit" :disabled="idDsabled" :loading="btnLoading">
保存
</u-button>
<u-button v-if="!config.current && (dataForm.approveStatus == 1 || dataForm.approveStatus == 2)" class="buttom-btn" type="primary" @click.stop="goProcess">
查看流程
</u-button>
<u-button v-if="config.current == 2" class="buttom-btn" type="error" @click.stop="handleFail" :disabled="idDsabled" :loading="btnLoading">
不通过
</u-button>
@@ -344,6 +347,7 @@
currentProcessId: '',
selectedCandidates: {},
approvalData: [], // 存储审批记录
isProcess: false, // 点击查看流程
//审批意见弹窗相关数据
showApprovalReasonDialog: false, // 弹窗显示状态
@@ -381,7 +385,7 @@
},
isApproval(){
const {current} = this.config
return !!current
return !!current || this.isProcess
}
},
onLoad(option) {
@@ -426,7 +430,7 @@
const getNavigationTitle = () =>{
let titleName = ''
if(this.config.current){
if(this.config.current || this.isProcess){
titleName = this.config.name + '详情'
}else {
const name = this.dataForm.id ? this.$t('common.editText') : this.$t('common.addText')
@@ -483,8 +487,19 @@
getListCreateData(params){
getListCreate(params,this.modelId).then(res=>{
if(res.code == 0) {
// const name = this.approvalType == 'through' ? '申请通过成功' '发起成功'
let name = '发起成功'
switch(this.approvalType){
case 'through':
name = '审批通过成功'
break;
case 'fail':
name = '审批不通过成功'
break;
}
uni.showToast({
title: '发起成功',
title: name,
icon: 'success'
})
setTimeout(() => {
@@ -743,6 +758,14 @@
this.approvalReason = '' // 清空之前的意见
this.showApprovalReasonDialog = true
},
// 查看流程
goProcess(){
this.isProcess = true
console.log(this.config,'config-')
uni.setNavigationBarTitle({
title: `${this.config.name}流程详情`
})
},
// 提交审批结果(通过/不通过)
async submitApprovalResult() {

View File

@@ -94,6 +94,10 @@
</view>
</view>
</view>
<view v-if="todoList.length > 2" class="todo-more" @click="openToDoPage">
更多
<u-icon name="arrow-down" class="u-p-r-10"color="#666"></u-icon>
</view>
</scroll-view>
<view class="empty-container" v-else>
<view>
@@ -398,7 +402,7 @@
getDonePage() {
const params = {
pageNo:1,
pageSize: 3
pageSize: 2000
}
getDonePage(params).then(res=>{
const {code,data} = res
@@ -408,7 +412,7 @@
index: 1, // 待办任务的tab索引
text: res.data.total.toString() // 角标数字
});
this.todoList = data.list || []
this.todoList = data.list.slice(0,3) || []
}
})
},
@@ -585,7 +589,7 @@
/* 滚动容器样式 */
.todo-scroll-container {
width: 100%;
max-height: 680rpx !important;
max-height: 780rpx !important;
::-webkit-scrollbar {
width: 4rpx;
}
@@ -594,6 +598,12 @@
border-radius: 2rpx;
}
}
.todo-more {
text-align: center;
color: #666;
font-size: 28rpx;
margin-top: 5rpx;
}
.todo-item {
// display: flex;
align-items: flex-start;
@@ -652,7 +662,7 @@
}
.title-right {
align-items: center;
font-size: 24rpx;
font-size: 28rpx;
color: #666;
}
/* 滚动容器 */

View File

@@ -267,7 +267,7 @@
userStore.logout().then(() => {
uni.closeSocket()
uni.reLaunch({
url: '/pages/login/index'
url: '/pages/login/index?socialLogin=true'
})
})
this.removeAccount()

View File

@@ -17,7 +17,7 @@
</view>
<view class="logo-hd u-flex-col">
<view class="loginSwitch u-flex-col">
<view class="loginInputBox u-flex-col" v-show="!isSso && !ssoLoading">
<view class="loginInputBox u-flex-col" v-show=" true || !isSso && !ssoLoading">
<u-form :model="formData" :rules="rules" ref="dataForm" :errorType="['toast']" label-position="left"
label-width="150" label-align="left">
<u-form-item v-show="false" prop="account" :borderBottom="false">
@@ -49,9 +49,9 @@
<view class="remember-wrap">
<u-checkbox v-model="remember"><span class="remember-text">记住账号密码</span></u-checkbox>
</view>
<view class="remember-wrap">
<!-- <view class="remember-wrap">
<u-checkbox v-model="isCertify"><span class="remember-text">是否认证</span></u-checkbox>
</view>
</view> -->
<view class="loginBtnBox">
<u-button @click="login" type="primary" :loading="loading">{{ loading ? "登录中...":"登录"}}
</u-button>
@@ -130,7 +130,8 @@
getLoginConfig,
getSocialsUserList,
socialsLogin,
getTicket
getTicket,
socialAuthRedirect
} from '@/api/common.js'
import md5Libs from "@/uni_modules/vk-uview-ui/libs/function/md5";
import resources from '@/libs/resources'
@@ -171,7 +172,7 @@
},
sysConfigInfo: {},
appIcon: '',
sysName: '',
sysName: '综合监控系统',
copyright: '综合监控系统',
socialsList: [],
show: false,
@@ -183,7 +184,8 @@
preUrl: '',
ticketParams: "",
loginCode: '',
isKeyUp: true
isKeyUp: true,
ssoOptions: {} // 端点登录参数
}
},
watch: {
@@ -209,43 +211,59 @@
this.$refs.dataForm.setRules(this.rules);
},
onLoad(options) {
if (options?.JNPF_TICKET) {
this.ssoTicket = options.JNPF_TICKET
uni.navigateTo({
url: `/pages/login/otherLogin?ssoTicket=${this.ssoTicket}`
})
this.ssoOptions = options
if(options.code){
this.exchangeToken(options)
}else if(options.socialLogin){
this.getLogin()
}
this.ssoTicket = uni.getStorageSync('ssoTicket')
this.sysConfigInfo = uni.getStorageSync('sysConfigInfo')
console.log(this.define,'define-------------')
this.appIcon = !!this.sysConfigInfo.appIcon ? this.baseURL + this.sysConfigInfo.appIcon :
logoImg
this.sysName = !!this.sysConfigInfo.companyName ? this.sysConfigInfo.sysName :
'JNPF快速开发平台'
// this.copyright = !!this.sysConfigInfo.copyright ? this.sysConfigInfo.copyright :
// this.define.copyright
// this.copyright = !!this.sysConfigInfo.copyright && this.sysConfigInfo.copyright
else{
this.certifyLogin()
}
// if(JSON.stringify(options) == '{}'){
// // 端点登录
// this.certifyLogin()
// }else {
// this.getLogin()
// }
// if (options?.JNPF_TICKET) {
// this.ssoTicket = options.JNPF_TICKET
// uni.navigateTo({
// url: `/pages/login/otherLogin?ssoTicket=${this.ssoTicket}`
// })
// }
// this.ssoTicket = uni.getStorageSync('ssoTicket')
// this.sysConfigInfo = uni.getStorageSync('sysConfigInfo')
// console.log(this.define,'define-------------')
// this.appIcon = !!this.sysConfigInfo.appIcon ? this.baseURL + this.sysConfigInfo.appIcon :
// logoImg
// this.sysName = !!this.sysConfigInfo.companyName ? this.sysConfigInfo.sysName :
// '综合监控系统'
// // this.copyright = !!this.sysConfigInfo.copyright ? this.sysConfigInfo.copyright :
// // this.define.copyright
// // this.copyright = !!this.sysConfigInfo.copyright && this.sysConfigInfo.copyright
uni.setNavigationBarTitle({
title: this.sysName
})
let needCode = uni.getStorageSync('app_loginNeedCode')
this.isCode = needCode
this.changeCode()
// let needCode = uni.getStorageSync('app_loginNeedCode')
// this.isCode = needCode
// this.changeCode()
// this.getLoginConfig()
this.formData.password = '';
if (options.data) {
this.tenantUserInfo = JSON.parse(options.data)
// if (this.tenantUserInfo) this.show = true
}
this.initAccount()
// #ifndef H5
uni.onKeyboardHeightChange(res => {
this.isKeyUp = res.height == 0 ? true : false
return this.isKeyUp
})
// #endif
// this.formData.password = '';
// if (options.data) {
// this.tenantUserInfo = JSON.parse(options.data)
// // if (this.tenantUserInfo) this.show = true
// }
// this.initAccount()
// // #ifndef H5
// uni.onKeyboardHeightChange(res => {
// this.isKeyUp = res.height == 0 ? true : false
// return this.isKeyUp
// })
// // #endif
this.initLoginConfig()
// this.initLoginConfig()
},
methods: {
initAccount() {
@@ -499,30 +517,18 @@
this.imgUrl = `/api/oauth/ImageCode/${this.codeLength || 4}/${timestamp}`
},
login() {
if(this.ssoOptions.socialLogin){
this.$refs.dataForm.validate(valid => {
if (valid) {
this.loading = true
const password = md5Libs.md5(this.formData.password);
const encryptPassword = this.jnpf.aesEncryption.encrypt(password);
// let query = {
// account: this.formData.account,
// password: encryptPassword,
// timestamp: this.timestamp,
// code: this.formData.code,
// origin: this.formData.origin,
// jnpf_ticket: this.ssoTicket,
// grant_type: 'password',
// }
if(this.isCertify){
// 认证登录
this.certifyLogin()
}else {
this.getLogin()
}
}
});
return
}
this.certifyLogin()
},
// 普通登录
getLogin(){
@@ -540,8 +546,9 @@
// query.Client_Id = uni.getStorageSync('cid')
// #endif
login(query).then(res => {
let token = res.data.accessToken
userStore.setToken(token)
const {accessToken,refreshToken} = res.data
userStore.setToken(accessToken)
userStore.setRefreshToken(refreshToken)
this.rememberAccount()
if(res.code == 0){
getPermissionInfo().then(res=>{
@@ -576,33 +583,24 @@
})
},
// 认证登录
certifyLogin(){
lx.biz.getAuthCode({
appId: "8889088-16130048", // AppID
success: (res) => {
console.log('免登授权码:', res.authCode)
this.exchangeToken(res.authCode)
async certifyLogin(){
let type = '100'
let redirectUri = location.origin + '/pages/login/index?' + encodeURIComponent(`type=${type}&redirect=/`)
const res = await socialAuthRedirect(type,encodeURIComponent(redirectUri))
console.log(res,'res-------')
window.location.href = res.data
},
fail: (err) => {
console.error('获取免登授权码失败:', err)
uni.showToast({
title: '免登失败,请重试',
icon: 'none'
})
this.loading = false
}
})
},
async exchangeToken(authCode) {
async exchangeToken(options) {
try {
const type = '110'
const code = authCode
const state = this.uuid()
const type = '100'
const code = '1222' || options?.code
const state = this.uuid() || options?.state
const res = await socialLogin(type, code, state)
const {accessToken,refreshToken} = res.data
const userStore = useUserStore()
// 存储Token和用户信息
userStore.setToken(res)
userStore.setToken(accessToken)
userStore.setRefreshToken(refreshToken)
uni.switchTab({
url: '/pages/index/indexWork'
});

View File

@@ -10,9 +10,7 @@
</view>
<view class="content u-p-l-32 u-p-r-32 u-p-t-30 u-font-28">
<text>引迈信息技术有限公司是一家做快速开发平台的企业针对软件传统开发遇到招人难留人难用人成本高技术更新换代快等一系列问题只需要一套JNPF平台您遇到的一系列问题就依然而解
JNPF采用主流的两大技术Java/.Net开发是一套低代码开发平台可视化开发环境有拖拽式的代码生成器灵活的权限配置SaaS服务强大的接口对接随心可变的工作流引擎一站式开发多端使用WebAndroidIOS微信小程序并且有以构建业务流程逻辑和数据模型等所需的功能为企业项目节省80%的重回工作让开发者将重心放在业务逻辑不必烦恼底层架构设计可短时间开发出如ERPOACRMHRMIS以及电信银行政府企业等各行业的企业应用系统
引迈信息技术有限公司以诚信为根本服务为基础理念通过持续不断地研发技术创新强化平台质量和颜值为企业保驾护航</text>
<text>软通动力</text>
</view>
<view class="copyright">{{copyright}}</view>
</view>

BIN
static/image/logoT.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 835 KiB

View File

@@ -12,6 +12,7 @@ export const useUserStore = defineStore({
id: 'user',
state: () => ({
token: "",
refreshToken: "",
userInfo: {},
menuList: [],
tenantId: '',
@@ -38,6 +39,10 @@ export const useUserStore = defineStore({
this.token = token
uni.setStorageSync('token', token)
},
setRefreshToken(refreshToken) {
this.refreshToken = refreshToken
uni.setStorageSync('refreshToken', refreshToken)
},
setCid(cid) {
this.cid = cid
uni.setStorageSync('cid', cid)

View File

@@ -1,10 +1,10 @@
/* process.env.NODE_ENV设置生产环境模式 */
// #ifndef MP
const baseURL = process.env.NODE_ENV === "production" ? "http://10.0.64.25:48080" : "http://10.28.117.48:48080"
const baseURL = process.env.NODE_ENV === "production" ? "http://10.0.64.25:48080" : "http://10.0.64.25:48080"
const webSocketUrl = process.env.NODE_ENV === "production" ? "http://10.0.64.25:48080" :
"ws://10.28.117.183:30000/api/message/websocket"
const report = process.env.NODE_ENV === 'production' ? 'http://10.0.64.25:48080' : 'http://10.28.117.183:8200'
const pcURL = process.env.NODE_ENV === 'production' ? 'http://10.0.64.25:48080' : 'http://10.28.117.183:3000'
"ws://10.0.64.25:48080/api/message/websocket"
const report = process.env.NODE_ENV === 'production' ? 'http://10.0.64.25:48080' : 'http://10.0.64.25:48080'
const pcURL = process.env.NODE_ENV === 'production' ? 'http://10.0.64.25:48080' : 'http://10.0.64.25:48080'
// #endif
// #ifdef MP
@@ -15,7 +15,7 @@ const pcURL = process.env.NODE_ENV === 'production' ? 'http://10.0.64.25:48080'
// #endif
console.log(process.env.NODE_ENV === "production",'判断环境----------')
const define = {
copyright: "Copyright @ 2025 引迈信息技术有限公司版权所有",
copyright: "Copyright @ 2026 软通动力",
sysVersion: "V6.0",
baseURL, // 接口前缀
report,

View File

@@ -1,36 +1,26 @@
import define from './define'
import {
useLocale
} from '@/locale/useLocale';
import { useLocale } from '@/locale/useLocale';
const {
getBackLocale
} = useLocale();
const { getBackLocale } = useLocale();
let host = define.baseURL
const defaultOpt = {
load: true
}
const defaultOpt = { load: true }
// 示例
// async xxxx(code) {
// var res = await this.request({
// url: '/api/System/DictionaryData/All',
// method: 'GET',
// data,
// options: {
// load: false
// }
// })
// if (!res) return
// console.log(res)
// }
// ------------- token刷新核心配置 -------------
const whiteList = ['/login', '/system/auth/refresh-token']
let requestQueue = []
let isRefreshingToken = false
const isRelogin = { show: false }
// ------------- 核心request方法 -------------
function request(config) {
config.options = Object.assign(defaultOpt, config.options)
const token = uni.getStorageSync('token') || ''
const tenantId = uni.getStorageSync('tenantId') || ''
const refreshToken = uni.getStorageSync('refreshToken') || ''
const tenantId = '1' || uni.getStorageSync('tenantId')
const systemCode = uni.getStorageSync('systemCode') || ''
const locale = getBackLocale()
// 构建请求头
let header = {
"accept": 'application/json, text/plain, */*',
"App-Code": systemCode,
@@ -43,33 +33,89 @@ function request(config) {
}
header['App-Code'] = encodeURIComponent(header['App-Code'])
if (token) header['Authorization'] = token
// 测试 todo
console.log(config.url,config.url.includes('admin-api'),'config.url.includes---')
if(config.url.includes('admin-api')){
host = 'http://10.28.117.48:48080'
}else {
host = define.baseURL
}
let url = config.url.indexOf('http') > -1 ? config.url : host + config.url
// let url = config.url.indexOf('http') > -1 ? config.url : host + config.url
let url = host + config.url
console.log(url,'url---')
// 3. 显示加载中
if (config.options.load) {
uni.showLoading({
title: config.options.loadText || '正在加载'
})
uni.showLoading({ title: config.options.loadText || '正在加载' })
}
// 4. 返回Promise核心改造逻辑
return new Promise((resolve, reject) => {
// 封装核心请求逻辑
const coreRequest = () => {
uni.request({
url: url,
data: config.data || {},
method: config.method || 'GET',
header: header,
timeout: define.timeout,
success: res => {
success: async (res) => {
uni.hideLoading();
if (res.statusCode === 200) {
if (res.data.code == 200 || res.data.code == 0) {
resolve(res.data)
} else if ([401, 600, 601, 602].includes(res.data.code)) {
// 白名单接口不处理
const isWhiteList = whiteList.some(v => config.url.includes(v))
if (isWhiteList) {
ajaxError(res.data)
reject(res.data.msg)
return
}
// ------------- 核心调整刷新token请求改为问号拼接参数 -------------
if (!refreshToken) {
await handleAuthorized()
reject(res.data.msg)
return
}
if (isRefreshingToken) {
requestQueue.push(() => coreRequest())
return
}
isRefreshingToken = true
try {
// 拼接URL参数和PC端一致POST方法 + ?refreshToken=xxx
const refreshUrl = `${host}/admin-api/system/auth/refresh-token?refreshToken=${encodeURIComponent(refreshToken)}`
// 调用刷新token接口POST方法 + URL参数无请求体
const refreshRes = await uni.request({
url: refreshUrl, // 带参数的URL
method: 'POST', // 保持POST方法
header: {
'tenant-id': tenantId, // 携带租户ID
'Content-Type': 'application/json'
},
data: {} // 无请求体参数全在URL上
})
// 刷新成功处理
if (refreshRes.statusCode === 200 && refreshRes.data.code === 200) {
const newTokenData = refreshRes.data.data
// 存储新token建议用项目封装的setToken方法
uni.setStorageSync('token', newTokenData.token)
uni.setStorageSync('refreshToken', newTokenData.refreshToken)
// 更新请求头
header['Authorization'] = newTokenData.token
// 重试当前请求
coreRequest()
// 执行队列请求
requestQueue.forEach(cb => cb())
requestQueue = []
} else {
await handleAuthorized()
reject('刷新token失败' + (refreshRes.data?.msg || '接口返回异常'))
}
} catch (err) {
await handleAuthorized()
reject('刷新token异常' + err.errMsg)
} finally {
isRefreshingToken = false
requestQueue = []
}
} else {
ajaxError(res.data)
reject(res.data.msg)
@@ -78,42 +124,54 @@ function request(config) {
ajaxError(res.data)
reject(res.errMsg)
}
uni.hideLoading();
},
fail: err => {
uni.showToast({
title: '连接服务器失败',
icon: 'none',
})
setTimeout(function () {
fail: (err) => {
uni.hideLoading();
}, 2000);
uni.showToast({ title: '连接服务器失败', icon: 'none' })
reject(err)
}
})
}
coreRequest()
})
}
// ------------- 辅助函数 -------------
function ajaxError(data) {
uni.showToast({
title: data.msg || '请求出错,请重试',
icon: 'none',
complete() {
if (data.code === 600 || data.code === 601 || data.code === 602 || data.code === 401) {
setTimeout(() => {
uni.removeStorageSync('token')
uni.removeStorageSync('cid')
uni.removeStorageSync('userInfo')
uni.removeStorageSync('permissionList')
uni.removeStorageSync('sysVersion')
uni.removeStorageSync('dynamicModelExtra')
uni.reLaunch({
url: '/pages/login/index'
})
}, 1500)
if ([600, 601, 602, 401].includes(data.code) && !isRefreshingToken) {
setTimeout(() => handleAuthorized(), 1500)
}
}
})
}
async function handleAuthorized() {
if (!isRelogin.show) {
isRelogin.show = true
const res = await uni.showModal({
title: '登录过期',
content: '您的登录已过期,请重新登录',
showCancelButton: false,
confirmText: '重新登录'
})
if (res.confirm) {
// 清除缓存建议用项目封装的removeToken方法
uni.removeStorageSync('token')
uni.removeStorageSync('refreshToken')
uni.removeStorageSync('cid')
uni.removeStorageSync('userInfo')
uni.removeStorageSync('permissionList')
uni.removeStorageSync('sysVersion')
uni.removeStorageSync('dynamicModelExtra')
uni.reLaunch({ url: '/pages/login/index' })
}
isRelogin.show = false
}
}
export default request