hookehuyr

feat: 添加微信支付和配置相关API及环境变量配置

refactor: 重构axios和api模块结构,移除无用代码

chore: 更新vite配置和项目基础设置

docs: 添加接口文档注释

style: 格式化代码并统一代码风格
# 开发环境配置
###
# 资源公共路径
VITE_BASE = /
# API 基础地址
VITE_API_BASE_URL=http://localhost:3000/api
# 测试open-id
VITE_OPENID = api-test-openid
# VITE_OPENID = o8BRf1gLDWieH3Y3JvbrI_4IjaME
# VITE_OPENID = oJLZq5t9PIKLW9tm1oSUNAuPwssA
# VITE_OPENID = oJLZq5uT_6GwIh2tQWh1F9IoHZ3U
# VITE_OPENID =
# 是否开启 Mock
VITE_USE_MOCK=true
# B端账号
VITE_ID = 13761653761
# 开发服务器端口
VITE_PORT=5173
# 验证码
VITE_PIN =
# 是否自动打开浏览器
VITE_OPEN=true
\ No newline at end of file
# 反向代理服务器地址
VITE_PROXY_TARGET = https://oa-dev.onwall.cn
# VITE_PROXY_TARGET = http://oa.onwall.cn
# PC端地址
VITE_MOBILE_URL = http://localhost:5173/
......
# 生产环境配置
###
# 资源公共路径
VITE_BASE = /f/stdj/
# API 基础地址
VITE_API_BASE_URL=https://api.yourdomain.com
# 测试open-id
VITE_APP_OPENID =
# 是否开启 Mock
VITE_USE_MOCK=false
# B端账号
VITE_APP_ID =
# 构建输出目录
VITE_OUTPUT_DIR=dist
# 验证码
VITE_APP_PIN =
# 静态资源目录
VITE_ASSETS_DIR=assets
\ No newline at end of file
# 反向代理服务器地址
VITE_PROXY_TARGET = https://oa.onwall.cn
# PC端地址
# VITE_MOBILE_URL = http://oa.onwall.cn/f/guanzong/web/
# VITE_MOBILE_URL = http://guanzong.onwall.cn/f/guanzong/web/
......
/*
* @Date: 2022-06-17 14:54:29
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-06-25 09:33:28
* @FilePath: /huizhu/src/api/common.js
* @Description: 通用接口
*/
import { fn, fetch, uploadFn } from '@/api/fn';
const Api = {
SMS: '/srv/?a=sms',
TOKEN: '/srv/?a=upload',
SAVE_FILE: '/srv/?a=upload&t=save_file',
}
/**
* @description: 发送验证码
* @param {*} phone 手机号码
* @returns
*/
export const smsAPI = (params) => fn(fetch.post(Api.SMS, params));
/**
* @description: 获取七牛token
* @param {*} filename 文件名
* @param {*} file 图片base64
* @returns
*/
export const qiniuTokenAPI = (params) => fn(fetch.stringifyPost(Api.TOKEN, params));
/**
* @description: 上传七牛
* @param {*}
* @returns
*/
export const qiniuUploadAPI = (url, data, config) => uploadFn(fetch.basePost(url, data, config));
/**
* @description: 保存图片
* @param {*} format
* @param {*} hash
* @param {*} height
* @param {*} width
* @param {*} filekey
* @returns
*/
export const saveFileAPI = (params) => fn(fetch.stringifyPost(Api.SAVE_FILE, params));
/*
* @Date: 2022-05-18 22:56:08
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2023-08-24 10:56:44
* @FilePath: /front/src/api/fn.js
* @Description: 文件描述
*/
import axios from '@/utils/axios';
import { showSuccessToast, showFailToast } from 'vant';
import qs from 'Qs'
/**
* 网络请求功能函数
* @param {*} api 请求axios接口
* @returns 请求成功后,获取数据
*/
export const fn = (api) => {
return api
.then(res => {
if (res.data.code === 1) {
return res.data || true;
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
showFailToast(res.data.msg);
return false;
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
return false;
})
.finally(() => { // 最终执行
})
}
/**
* 七牛返回格式
* @param {*} api
* @returns
*/
export const uploadFn = (api) => {
return api
.then(res => {
if (res.statusText === 'OK') {
return res.data || true;
} else {
// tslint:disable-next-line: no-console
console.warn(res);
if (!res.data.show) return false;
showFailToast(res.data.msg);
return false;
}
})
.catch(err => {
// tslint:disable-next-line: no-console
console.error(err);
return false;
})
}
/**
* 统一 GET/POST 不同传参形式
*/
export const fetch = {
get: function (api, params) {
return axios.get(api, { params })
},
post: function (api, params) {
return axios.post(api, params)
},
stringifyPost: function (api, params) {
return axios.post(api, qs.stringify(params))
},
basePost: function (url, data, config) {
return axios.post(url, data, config)
}
}
import request from '@/utils/request'
/*
* @Date: 2023-08-24 09:42:27
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-10-31 11:04:23
* @FilePath: /stdj_h5/src/api/index.js
* @Description: 文件描述
*/
import { fn, fetch } from '@/api/fn';
// 用户相关 API
export const userApi = {
// 获取用户信息
getUserInfo: () => request.get('/user/info'),
const Api = {
GET_HOME: '/srv/?a=home',
GET_ARTICLE: '/srv/?a=get_article',
};
// 更新用户信息
updateUserInfo: (data) => request.put('/user/info', data),
/**
* @description: 首页数据
* @returns {Object} list
* @property [Object] list.STDJSSQZ 三师七证
* @property integer list.STDJSSQZ.id 分类id
* @property string list.STDJSSQZ.category_name 分类名称
* @property string list.STDJSSQZ.cover 封面图
* @property string list.STDJSSQZ.parent_sn 父分类id
* @property [Object] list.STDJFHLC 法会流程
* @property integer list.STDJFHLC.id 分类id
* @property string list.STDJFHLC.category_name 分类名称
* @property string list.STDJFHLC.cover 封面图
* @property string list.STDJFHLC.parent_sn 父分类id
* @property [Object] list.STDJXGXW 新闻
* @property integer list.STDJXGXW.id 分类id
* @property string list.STDJXGXW.post_title 新闻标题
* @property string list.STDJXGXW.post_date 发布日期
* @property string list.STDJXGXW.photo 封面图
*/
export const homePageAPI = (params) => fn(fetch.get(Api.GET_HOME, params));
// 用户登录
login: (data) => request.post('/user/login', data),
/**
* @description: 三師七證数据
* @param {String} pid 分类id
* @returns {Object} list
* @property integer list.id 分类id
* @property string list.category_name 分类名称
* @property string list.category_seq 分类顺序
* @property [Object] list.list 子分类列表
* @property integer list.list.id 子分类id
* @property string list.list.post_title 标题/名称
* @property string list.list.post_date 发布日期
* @property string list.list.post_excerpt 简介
* @property string list.list.post_content 内容/描述
* @property string list.list.photo 封面图
* @property string list.list.category_id 分类id
*/
export const getSSQZAPI = (params) => fn(fetch.get(Api.GET_ARTICLE, params));
// 用户注册
register: (data) => request.post('/user/register', data),
/**
* @description: 图片流媒体数据
* @param {String} cid 分类id
* @param {String} page 页码,默认0
* @param {String} limit 每页数量,默认10
* @returns {Object} list
* @property integer list.id 分类id
* @property string list.post_title 标题/名称
* @property string list.post_date 发布日期
* @property string list.post_excerpt 简介
* @property string list.photo 封面图
*/
export const getImgStreamAPI = (params) => fn(fetch.get(Api.GET_ARTICLE, params));
// 用户登出
logout: () => request.post('/user/logout')
}
// 通用 API
export const commonApi = {
// 上传文件
upload: (file) => {
const formData = new FormData()
formData.append('file', file)
return request.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
},
// 获取配置信息
getConfig: () => request.get('/config'),
// 发送验证码
sendSms: (phone) => request.post('/sms/send', { phone })
}
// 示例 API
export const demoApi = {
// 获取列表数据
getList: (params) => request.get('/demo/list', { params }),
// 获取详情
getDetail: (id) => request.get(`/demo/${id}`),
// 创建数据
create: (data) => request.post('/demo', data),
// 更新数据
update: (id, data) => request.put(`/demo/${id}`, data),
// 删除数据
delete: (id) => request.delete(`/demo/${id}`)
}
// 导出所有 API
export default {
userApi,
commonApi,
demoApi
}
\ No newline at end of file
/**
* @description: 文章详情数据
* @param {String} i 文章id
* @returns {Object} data
* @property integer data.post_author 作者
* @property string data.post_title 标题/名称
* @property string data.post_date 发布日期
* @property string data.post_excerpt 简介
* @property string data.post_content 内容/描述
* @property string data.post_modified 修改日期
* @property string data.post_status 状态
* @property string data.post_type 类型
* @property object data.file_list 文件列表
* @property object data.file_list.photo 照片
* @property string data.file_list.photo.value 照片地址
*/
export const getArticleDetailAPI = (params) => fn(fetch.get(Api.GET_ARTICLE, params));
......
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-09 13:32:44
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-14 14:47:01
* @FilePath: /tswj/src/api/wx/config.js
* @Description:
*/
import { fn, fetch } from '@/api/fn';
const Api = {
WX_JSAPI: '/srv/?a=wx_share',
}
/**
* @description 获取微信CONFIG配置文件
* @param {*} url
* @returns {*} cfg
*/
export const wxJsAPI = (params) => fn(fetch.get(Api.WX_JSAPI, params));
/*
* @Date: 2022-06-13 14:18:57
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-13 14:27:21
* @FilePath: /tswj/src/api/wx/jsApiList.js
* @Description: 文件描述
*/
export const apiList = [
"updateAppMessageShareData",
"updateTimelineShareData",
"onMenuShareTimeline",
"onMenuShareAppMessage",
"onMenuShareQQ",
"onMenuShareWeibo",
"onMenuShareQZone",
"startRecord",
"stopRecord",
"onVoiceRecordEnd",
"playVoice",
"pauseVoice",
"stopVoice",
"onVoicePlayEnd",
"uploadVoice",
"downloadVoice",
"chooseImage",
"previewImage",
"uploadImage",
"downloadImage",
"translateVoice",
"getNetworkType",
"openLocation",
"getLocation",
"hideOptionMenu",
"showOptionMenu",
"hideMenuItems",
"showMenuItems",
"hideAllNonBaseMenuItem",
"showAllNonBaseMenuItem",
"closeWindow",
"scanQRCode",
"chooseWXPay",
"openProductSpecificView",
"addCard",
"chooseCard",
"openCard"
]
/*
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-06-09 13:32:44
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-09 13:42:06
* @FilePath: /tswj/src/api/wx/config.js
* @Description:
*/
import { fn, fetch } from '@/api/fn';
const Api = {
WX_PAY: 'c/bill_paymentForBill.do',
}
/**
* @description 微信支付接口
* @param {*}
* @returns {*}
*/
export const wxPayAPI = (params) => fn(fetch.get(Api.WX_PAY, params));
......@@ -2,38 +2,18 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-28 10:17:40
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-07-01 16:23:59
* @FilePath: /mlaj/src/utils/axios.js
* @LastEditTime: 2025-10-31 09:52:30
* @FilePath: /stdj_h5/src/utils/axios.js
* @Description:
*/
import axios from 'axios';
import router from '@/router';
// import router from '@/router';
// import qs from 'Qs'
// import { strExist } from '@/utils/tools'
// import { parseQueryString } from '@/utils/tools'
// axios.defaults.baseURL = 'http://localhost:3000/api';
axios.defaults.params = {
f: 'behalo',
};
/**
* 设置用户认证信息到请求头
* @param {string} userId - 用户ID
* @param {string} userToken - 用户Token
*/
export const setAuthHeaders = (userId, userToken) => {
if (userId && userToken) {
axios.defaults.headers['User-Id'] = userId;
axios.defaults.headers['User-Token'] = userToken;
}
};
/**
* 清除用户认证信息
*/
export const clearAuthHeaders = () => {
delete axios.defaults.headers['User-Id'];
delete axios.defaults.headers['User-Token'];
f: 'stdj',
};
/**
......@@ -41,16 +21,6 @@ export const clearAuthHeaders = () => {
*/
axios.interceptors.request.use(
config => {
/**
* 司总授权信息
* 动态获取 user_info 并设置到请求头
* 确保每个请求都带上最新的 user_info
*/
const user_info = localStorage.getItem('user_info') ? JSON.parse(localStorage.getItem('user_info')) : {};
if (user_info) {
config.headers['User-Id'] = user_info.user_id;
config.headers['User-Token'] = user_info.HTTP_USER_TOKEN;
}
// const url_params = parseQueryString(location.href);
// GET请求默认打上时间戳,避免从缓存中拿数据。
const timestamp = config.method === 'get' ? (new Date()).valueOf() : '';
......@@ -73,20 +43,9 @@ axios.interceptors.request.use(
*/
axios.interceptors.response.use(
response => {
if (response.data && response.data.code === 401) {
// 清除用户登录信息
localStorage.removeItem('currentUser');
// 清除认证请求头
clearAuthHeaders();
// 跳转到登录页面,并携带当前路由信息
const currentPath = router.currentRoute.value.fullPath;
router.push(`/login?redirect=${encodeURIComponent(currentPath)}`);
// router.push(`/login`);
}
return response;
},
error => {
// 响应错误处理
return Promise.reject(error);
});
......
/*
* @Date: 2025-10-30 10:27:43
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-10-30 15:24:36
* @LastEditTime: 2025-10-30 21:48:53
* @FilePath: /stdj_h5/vite.config.js
* @Description: 文件描述
*/
import { defineConfig } from 'vite'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
......@@ -14,9 +14,16 @@ import path from 'path'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
import postcsspxtoviewport from 'postcss-px-to-viewport'
import { createProxy } from './build/proxy'
// https://vitejs.dev/config/
export default defineConfig({
export default ({ command, mode }) => {
const root = process.cwd();
const viteEnv = loadEnv(mode, root);
// let isProd = (command === 'serve'); // 情景配置是否为开发模式 serve 或 build
return defineConfig({
base: viteEnv.VITE_BASE, // 开发或生产环境服务的公共基础路径。
plugins: [
vue(),
AutoImport({
......@@ -66,25 +73,40 @@ export default defineConfig({
},
server: {
host: '0.0.0.0',
port: 5573,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
port: viteEnv.VITE_PORT, // 本地服务端口
// strictPort: true, // 设为true时若端口已被占用则会直接退出, 而不是尝试下一个可用端口
// https: '',
// open: false, // 在服务器启动时自动在浏览器中打开应用程序. 当此值为字符串时, 会被当作URL的路径名.
// proxy: { // 代理
// '/srv/': {
// // target: 'http://voice.onwall.cn',
// target: viteEnv.VITE_PROXY_TARGET,
// changeOrigin: true,
// // rewrite: (path) => path.replace(/^\/api/, '')
// },
// },
proxy: createProxy(viteEnv.VITE_PROXY_PREFIX, viteEnv.VITE_PROXY_TARGET),
// cors: '', // 为开发服务器配置 CORS。默认启用并允许任何源,传递一个 选项对象 来调整行为或设为 false 表示禁用。
// force: '', // 设置为 true 强制使依赖预构建。
// hmr: '', // 禁用或配置 HMR 连接(用于 HMR websocket 必须使用不同的 http 服务器地址的情况)。 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层。
// watch: '', // 传递给 chokidar 的文件系统监视器选项。
},
build: {
outDir: 'dist',
// outDir: 'voice', // 指定输出路径(相对于项目根目录).
outDir: viteEnv.VITE_OUTDIR, // 指定输出路径(相对于项目根目录).
assetsDir: 'static',
rollupOptions: {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
}
}
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
},
input: { // 多页面应用模式, 打包时配置,运行配置要处理root
main: path.resolve(__dirname, 'index.html'),
// mono1: path.resolve(__dirname, 'src/packages/mono1/index.html'),
// mono2: path.resolve(__dirname, 'src/packages/mono2/index.html'),
}
})
},
},
});
};
......