mirror of
https://github.com/ialley-workshop-open/uni-halo.git
synced 2026-09-02 17:30:44 +08:00
@@ -20,7 +20,11 @@ export default {
|
|||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
|
uni.$tm.vx.actions('config/fetchConfigs').then((res) => {
|
||||||
|
console.log('fetchConfigs', res);
|
||||||
})
|
})
|
||||||
|
uni.$tm.vx.actions('config/fetchHaloConfigs').then((res) => {
|
||||||
|
console.log('fetchHaloConfigs', res);
|
||||||
|
})
|
||||||
// 启动检查app的配置是否已经就绪,若未就绪则设置默认的
|
// 启动检查app的配置是否已经就绪,若未就绪则设置默认的
|
||||||
uni.$tm.vx.actions('setting/checkAndSetDefaultAppSettings');
|
uni.$tm.vx.actions('setting/checkAndSetDefaultAppSettings');
|
||||||
},
|
},
|
||||||
|
|||||||
+34
-17
@@ -3,11 +3,13 @@ import {
|
|||||||
} from '@/utils/token.js'
|
} from '@/utils/token.js'
|
||||||
import HttpHandler from '@/common/http/request.js'
|
import HttpHandler from '@/common/http/request.js'
|
||||||
import qs from 'qs'
|
import qs from 'qs'
|
||||||
|
import { getCache } from "@/utils/storage";
|
||||||
|
import { getAppConfigs } from '@/config/index.js'
|
||||||
import {
|
import {
|
||||||
getAppConfigs
|
getNologinEmail,
|
||||||
} from '@/config/index.js'
|
getOpenid
|
||||||
import { getNologinEmail, getOpenid } from "@/utils/auth";
|
} from "@/utils/auth";
|
||||||
|
import { CommentWidgetCaptchaCookies } from '@/common/constant/cookies.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getPostList: (params) => {
|
getPostList: (params) => {
|
||||||
@@ -52,11 +54,27 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
addPostComment: (data) => {
|
addPostComment: (data) => {
|
||||||
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data)
|
const captchaCode = data.captchaCode;
|
||||||
|
delete data.captchaCode;
|
||||||
|
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments`, data, {
|
||||||
|
header: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-Captcha-Code": captchaCode,
|
||||||
|
"Cookie": getCache(CommentWidgetCaptchaCookies) ?? undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
addPostCommentReply: (commentName, data) => {
|
addPostCommentReply: (commentName, data) => {
|
||||||
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, data)
|
const captchaCode = data.captchaCode;
|
||||||
|
delete data.captchaCode;
|
||||||
|
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/comments/${commentName}/reply`, data, {
|
||||||
|
header: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-Captcha-Code": captchaCode,
|
||||||
|
"Cookie": getCache(CommentWidgetCaptchaCookies) ?? undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
getTagList: (params) => {
|
getTagList: (params) => {
|
||||||
@@ -68,19 +86,11 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getMomentList: (params) => {
|
getMomentList: (params) => {
|
||||||
return HttpHandler.Get(`/apis/api.moment.halo.run/v1alpha1/moments`, params, {
|
return HttpHandler.Get(`/apis/api.moment.halo.run/v1alpha1/moments`, params)
|
||||||
custom: {
|
|
||||||
personalToken: getPersonalToken()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getMomentByName: (name) => {
|
getMomentByName: (name) => {
|
||||||
return HttpHandler.Get(`/apis/api.moment.halo.run/v1alpha1/moments/${name}`, {}, {
|
return HttpHandler.Get(`/apis/api.moment.halo.run/v1alpha1/moments/${name}`, {})
|
||||||
custom: {
|
|
||||||
personalToken: getPersonalToken()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getBlogStatistics: () => {
|
getBlogStatistics: () => {
|
||||||
@@ -176,10 +186,17 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getDoubanDetail: (url) => {
|
getDoubanDetail: (url) => {
|
||||||
return HttpHandler.Get(`/apis/api.douban.moony.la/v1alpha1/doubanmovies/-/getDoubanDetail`, { url })
|
return HttpHandler.Get(`/apis/api.douban.moony.la/v1alpha1/doubanmovies/-/getDoubanDetail`, {
|
||||||
|
url
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
postTrackersCounter: (data) => {
|
postTrackersCounter: (data) => {
|
||||||
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/trackers/counter`, data)
|
return HttpHandler.Post(`/apis/api.halo.run/v1alpha1/trackers/counter`, data)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 获取评论验证码 */
|
||||||
|
getCommentWidgetCaptcha: () => {
|
||||||
|
return HttpHandler.Get(`/apis/api.commentwidget.halo.run/v1alpha1/captcha/-/generate`, {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,4 +7,14 @@ export default {
|
|||||||
getAppConfigs: () => {
|
getAppConfigs: () => {
|
||||||
return HttpHandler.Get(`/apis/api.uni.uhalo.pro/v1alpha1/plugins/plugin-uni-halo/getConfigs`, {})
|
return HttpHandler.Get(`/apis/api.uni.uhalo.pro/v1alpha1/plugins/plugin-uni-halo/getConfigs`, {})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 获取全局配置信息 */
|
||||||
|
getHaloGlobalInfo: () => {
|
||||||
|
return HttpHandler.Get(`/actuator/globalinfo`, {})
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 获取评论组件配置 */
|
||||||
|
getCommentWidgetConfig: () => {
|
||||||
|
return HttpHandler.Get(`/apis/api.commentwidget.halo.run/v1alpha1/config`, {})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/** 评论验证码 */
|
||||||
|
export const CommentWidgetCaptchaCookies = 'comment-widget-captcha';
|
||||||
@@ -16,7 +16,9 @@ import {
|
|||||||
} from "./interceptors.js";
|
} from "./interceptors.js";
|
||||||
import Request from "@/js_sdk/luch-request/luch-request";
|
import Request from "@/js_sdk/luch-request/luch-request";
|
||||||
|
|
||||||
const http = new Request()
|
const http = new Request({
|
||||||
|
withCredentials: true, // 是否携带cookie
|
||||||
|
})
|
||||||
/* 设置全局配置 */
|
/* 设置全局配置 */
|
||||||
http.setConfig((config) => {
|
http.setConfig((config) => {
|
||||||
|
|
||||||
|
|||||||
+154
-118
@@ -9,133 +9,169 @@
|
|||||||
* 修改人员:
|
* 修改人员:
|
||||||
* 修改时间:
|
* 修改时间:
|
||||||
*/
|
*/
|
||||||
import {delCache, setCache} from "@/utils/storage";
|
import {
|
||||||
|
delCache,
|
||||||
|
setCache
|
||||||
|
} from "@/utils/storage";
|
||||||
|
import {
|
||||||
|
CommentWidgetCaptchaCookies
|
||||||
|
} from '@/common/constant/cookies.js'
|
||||||
|
import {
|
||||||
|
extractCookieItem,
|
||||||
|
getHeaderCaseInsensitive
|
||||||
|
} from '@/utils/cookies.js'
|
||||||
|
|
||||||
const getCategoryNameByUrl = (url) => {
|
const getCategoryNameByUrl = (url) => {
|
||||||
const reg = '(?<=/api/content/categories/).+(?=/posts)'
|
const reg = '(?<=/api/content/categories/).+(?=/posts)'
|
||||||
return url.match(reg)[0] || '无分类名'
|
return url.match(reg)[0] || '无分类名'
|
||||||
}
|
}
|
||||||
|
|
||||||
const showCategoryInputPasswordModal = (response, category) => {
|
const showCategoryInputPasswordModal = (response, category) => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: `[ ${category} ] 分类已加密`, // TODO 这里应该获取分类的名字,可以在弹窗之前请求后台拿到所有分类根据分类code拿到名称,但是不会在这之前发送请求
|
title: `[ ${category} ] 分类已加密`, // TODO 这里应该获取分类的名字,可以在弹窗之前请求后台拿到所有分类根据分类code拿到名称,但是不会在这之前发送请求
|
||||||
content: '',
|
content: '',
|
||||||
editable: true,
|
editable: true,
|
||||||
placeholderText: '请输入分类密码后访问',
|
placeholderText: '请输入分类密码后访问',
|
||||||
confirmText: '验证密码',
|
confirmText: '验证密码',
|
||||||
cancelText: '暂不访问',
|
cancelText: '暂不访问',
|
||||||
showCancel: true,
|
showCancel: true,
|
||||||
cancelColor: '#999999',
|
cancelColor: '#999999',
|
||||||
confirmColor: '#03a9f4',
|
confirmColor: '#03a9f4',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
// TODO 这里如果没有输入密码点击确认应该阻止窗口关闭,但是没找到方法
|
// TODO 这里如果没有输入密码点击确认应该阻止窗口关闭,但是没找到方法
|
||||||
if (!res.content) {
|
if (!res.content) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '提示:请输入密码', icon: 'none', success: () => {
|
title: '提示:请输入密码',
|
||||||
setTimeout(() => {
|
icon: 'none',
|
||||||
showCategoryInputPasswordModal(response, category);
|
success: () => {
|
||||||
}, 800)
|
setTimeout(() => {
|
||||||
}
|
showCategoryInputPasswordModal(response, category);
|
||||||
})
|
}, 800)
|
||||||
return;
|
}
|
||||||
}
|
})
|
||||||
// 根据请求URL正则匹配分类code,然后把输入的密码根据分类code放入缓存,然后在category.getCategoryPostList中获取,解决多个分类加密输入密码后点错的问题
|
return;
|
||||||
// 目前存在一个问题,比如前两个都需要密码,如果先输入第二个的密码之后,重新进来默认打开第一个还会弹窗,所以想在弹窗标题上增加分类名字
|
}
|
||||||
// 另外有以下两种方式科技解决
|
// 根据请求URL正则匹配分类code,然后把输入的密码根据分类code放入缓存,然后在category.getCategoryPostList中获取,解决多个分类加密输入密码后点错的问题
|
||||||
// TODO 1.其实这里获取到密码之后可以直接发送一个请求追加上password参数,因为后台会缓存权限,后续不输入密码也可以访问,可惜不会
|
// 目前存在一个问题,比如前两个都需要密码,如果先输入第二个的密码之后,重新进来默认打开第一个还会弹窗,所以想在弹窗标题上增加分类名字
|
||||||
// TODO 2.另外也可以拿到密码之后,直接选中该分类追加password参数,重新请求,可惜也不会
|
// 另外有以下两种方式科技解决
|
||||||
setCache('APP_CATEGORY_PWD_' + category, res.content)
|
// TODO 1.其实这里获取到密码之后可以直接发送一个请求追加上password参数,因为后台会缓存权限,后续不输入密码也可以访问,可惜不会
|
||||||
uni.reLaunch({
|
// TODO 2.另外也可以拿到密码之后,直接选中该分类追加password参数,重新请求,可惜也不会
|
||||||
url: '/pages/tabbar/category/category'
|
setCache('APP_CATEGORY_PWD_' + category, res.content)
|
||||||
});
|
uni.reLaunch({
|
||||||
} else if (res.cancel) {
|
url: '/pages/tabbar/category/category'
|
||||||
}
|
});
|
||||||
},
|
} else if (res.cancel) {}
|
||||||
})
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveCookies = (response) => {
|
||||||
|
const cookies = getHeaderCaseInsensitive(response.header, 'set-cookie');
|
||||||
|
|
||||||
|
// app/小程序将 cookies 存储起来
|
||||||
|
// #ifdef MP-WEIXIN || APP-PLUS
|
||||||
|
// 存储评论验证码cookies
|
||||||
|
const MatchCommentApis = [
|
||||||
|
'/apis/api.commentwidget.halo.run/v1alpha1/captcha/-/generate',
|
||||||
|
'/apis/api.halo.run/v1alpha1/comments'
|
||||||
|
]
|
||||||
|
if (MatchCommentApis.includes(response.config.url)) {
|
||||||
|
setCache(CommentWidgetCaptchaCookies, extractCookieItem(cookies, CommentWidgetCaptchaCookies))
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setInterceptors = (http) => {
|
export const setInterceptors = (http) => {
|
||||||
http.interceptors.request.use((config) => {
|
http.interceptors.request.use((config) => {
|
||||||
console.log("config", config)
|
console.log("config", config)
|
||||||
|
|
||||||
// 可使用async await 做异步操作
|
// 可使用async await 做异步操作
|
||||||
config.header = {
|
config.header = {
|
||||||
...config.header
|
...config.header
|
||||||
// ... 可以直接加参数
|
// ... 可以直接加参数
|
||||||
};
|
};
|
||||||
if (config.custom.personalToken) {
|
if (config.custom.personalToken) {
|
||||||
config.header['Authorization'] = `Bearer ${config.custom.personalToken}`
|
config.header['Authorization'] = `Bearer ${config.custom.personalToken}`
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
}, (config) => {
|
}, (config) => {
|
||||||
// 可使用async await 做异步操作
|
// 可使用async await 做异步操作
|
||||||
return Promise.reject(config);
|
return Promise.reject(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
http.interceptors.response.use((response) => {
|
http.interceptors.response.use((response) => {
|
||||||
/* 对响应成功做点什么 可使用async await 做异步操作*/
|
/* 对响应成功做点什么 可使用async await 做异步操作*/
|
||||||
// if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
|
// if (response.data.code !== 200) { // 服务端返回的状态码不等于200,则reject()
|
||||||
// return Promise.reject(response) // return Promise.reject 可使promise状态进入catch
|
// return Promise.reject(response) // return Promise.reject 可使promise状态进入catch
|
||||||
// if (response.config.custom.verification) { // 演示自定义参数的作用
|
// if (response.config.custom.verification) { // 演示自定义参数的作用
|
||||||
// return response.data
|
// return response.data
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
saveCookies(response);
|
||||||
return response.data;
|
|
||||||
} else {
|
|
||||||
return Promise.reject(response);
|
|
||||||
}
|
|
||||||
}, (response) => {
|
|
||||||
/* 对响应错误做点什么 (statusCode !== 200)*/
|
|
||||||
if (!response.data) {
|
|
||||||
return Promise.reject({
|
|
||||||
status: 500, message: 'API接口服务异常!'
|
|
||||||
})
|
|
||||||
} else if (response.data.status == 401) {
|
|
||||||
uni.$tm.toast(response.data.message);
|
|
||||||
// 如果是请求分类之后报401说明密码错误,那么清除该密码,下次点击会报403弹窗再次输入密码
|
|
||||||
if (response.config.url.indexOf('/api/content/categories') >= 0) {
|
|
||||||
const category = getCategoryNameByUrl(response.config.url)
|
|
||||||
delCache('APP_CATEGORY_PWD_' + category);
|
|
||||||
uni.showToast({
|
|
||||||
title: '提示:密码不正确', icon: 'none', success: () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
showCategoryInputPasswordModal(response, category);
|
|
||||||
}, 800)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 其他情况维持原来的逻辑
|
|
||||||
delCache('APP_ADMIN_LOGIN_TOKEN');
|
|
||||||
uni.$eShowModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '您未登录超管账号或登录已过期,是否重新登录?',
|
|
||||||
showCancel: true,
|
|
||||||
cancelText: '否',
|
|
||||||
cancelColor: '#999999',
|
|
||||||
confirmText: '是',
|
|
||||||
confirmColor: '#03a9f4'
|
|
||||||
}).then(res => {
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pagesB/login/login'
|
|
||||||
})
|
|
||||||
}).catch(err => {
|
|
||||||
uni.switchTab({
|
|
||||||
url: '/pages/tabbar/about/about'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return Promise.reject(response.data);
|
|
||||||
} else if (response.data.status == 403) {
|
|
||||||
// 如果报403是请求分类文章接口(您没有该分类的访问权限)的话说明是私密分类,需要输入密码请求
|
|
||||||
if (response.config.url.indexOf('/api/content/categories') >= 0) {
|
|
||||||
const category = getCategoryNameByUrl(response.config.url);
|
|
||||||
showCategoryInputPasswordModal(response, category);
|
|
||||||
}
|
|
||||||
return Promise.reject(response.data);
|
|
||||||
} else {
|
|
||||||
return Promise.reject(response.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
if (response.statusCode == 200) {
|
||||||
|
return response.data;
|
||||||
|
} else {
|
||||||
|
return Promise.reject(response);
|
||||||
|
}
|
||||||
|
}, (response) => {
|
||||||
|
|
||||||
|
saveCookies(response);
|
||||||
|
|
||||||
|
/* 对响应错误做点什么 (statusCode !== 200)*/
|
||||||
|
if (!response.data) {
|
||||||
|
return Promise.reject({
|
||||||
|
status: 500,
|
||||||
|
message: 'API接口服务异常!'
|
||||||
|
})
|
||||||
|
} else if (response.data.status == 401) {
|
||||||
|
uni.$tm.toast(response.data.message);
|
||||||
|
// 如果是请求分类之后报401说明密码错误,那么清除该密码,下次点击会报403弹窗再次输入密码
|
||||||
|
if (response.config.url.indexOf('/api/content/categories') >= 0) {
|
||||||
|
const category = getCategoryNameByUrl(response.config.url)
|
||||||
|
delCache('APP_CATEGORY_PWD_' + category);
|
||||||
|
uni.showToast({
|
||||||
|
title: '提示:密码不正确',
|
||||||
|
icon: 'none',
|
||||||
|
success: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
showCategoryInputPasswordModal(response, category);
|
||||||
|
}, 800)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 其他情况维持原来的逻辑
|
||||||
|
delCache('APP_ADMIN_LOGIN_TOKEN');
|
||||||
|
uni.$eShowModal({
|
||||||
|
title: '提示',
|
||||||
|
content: '您未登录超管账号或登录已过期,是否重新登录?',
|
||||||
|
showCancel: true,
|
||||||
|
cancelText: '否',
|
||||||
|
cancelColor: '#999999',
|
||||||
|
confirmText: '是',
|
||||||
|
confirmColor: '#03a9f4'
|
||||||
|
}).then(res => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pagesB/login/login'
|
||||||
|
})
|
||||||
|
}).catch(err => {
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/pages/tabbar/about/about'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return Promise.reject(response.data);
|
||||||
|
} else if (response.data.status == 403) {
|
||||||
|
// 如果报403是请求分类文章接口(您没有该分类的访问权限)的话说明是私密分类,需要输入密码请求
|
||||||
|
if (response.config.url.indexOf('/api/content/categories') >= 0) {
|
||||||
|
const category = getCategoryNameByUrl(response.config.url);
|
||||||
|
showCategoryInputPasswordModal(response, category);
|
||||||
|
}
|
||||||
|
return Promise.reject(response.data);
|
||||||
|
} else {
|
||||||
|
return Promise.reject(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
};
|
};
|
||||||
@@ -91,9 +91,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
created() {
|
|
||||||
console.log("comment", this.comment)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,233 +1,341 @@
|
|||||||
<template>
|
<template>
|
||||||
<tm-poup v-model="isShow" position="bottom" height="71vh" @change="handleOnChange">
|
<tm-poup v-model="isShow" position="bottom" height="71vh" @change="handleOnChange">
|
||||||
<view class="title text-align-center">{{ calcTitle }}</view>
|
<view class="title text-align-center">{{ calcTitle }}</view>
|
||||||
<tm-form @submit="fnOnSubmit">
|
<tm-form @submit="fnOnSubmit">
|
||||||
<tm-input name="content" :vertical="true" required :height="220" input-type="textarea"
|
<tm-input name="content" :vertical="true" required :height="200" input-type="textarea"
|
||||||
bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false" placeholder="请输入内容,不超过200字符..."
|
bg-color="grey-lighten-5" :maxlength="200" :borderBottom="false"
|
||||||
v-model="form.content"></tm-input>
|
:placeholder="config.editor.placeholder" v-model="form.content"></tm-input>
|
||||||
<tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..."
|
<tm-input name="author" align="right" required title="我的昵称" placeholder="请输入您的昵称..."
|
||||||
v-model="form.author"></tm-input>
|
v-model="form.author"></tm-input>
|
||||||
<tm-input name="avatar" align="right" title="我的头像" placeholder="请输入您的头像..."
|
<tm-input v-if="false" name="avatar" align="right" title="我的头像" placeholder="请输入您的头像..."
|
||||||
v-model="form.avatar"></tm-input>
|
v-model="form.avatar"></tm-input>
|
||||||
<tm-input name="email" align="right" title="邮箱地址" placeholder="请输入您的邮箱..." v-model="form.email"></tm-input>
|
<tm-input name="email" required align="right" title="我的邮箱" placeholder="请输入您的邮箱..." v-model="form.email"></tm-input>
|
||||||
<tm-input name="authorUrl" align="right" title="我的网站" placeholder="请输入您的网址..."
|
<tm-input name="authorUrl" align="right" title="我的网站" placeholder="请输入您的网址..."
|
||||||
v-model="form.authorUrl"></tm-input>
|
v-model="form.authorUrl"></tm-input>
|
||||||
<view class="pa-24 pl-30 pr-30">
|
<template v-if="config.security.captcha.anonymousCommentCaptcha">
|
||||||
<tm-button navtie-type="form" theme="bg-gradient-blue-accent" block>提交
|
<tm-input required name="captchaCode" align="right" title="验证码" placeholder="请输入验证码结果"
|
||||||
</tm-button>
|
v-model="form.captchaCode">
|
||||||
</view>
|
<template v-slot:rightBtn>
|
||||||
</tm-form>
|
<view class="captch-wrapper text-size-n">
|
||||||
</tm-poup>
|
<view v-if="captchaData.status==='loading'" class="text-grey">获取中...</view>
|
||||||
|
<view v-else-if="captchaData.status==='fail'" class="text-red"
|
||||||
|
@click="handleGetCaptchaImage()">
|
||||||
|
请重试
|
||||||
|
</view>
|
||||||
|
<image v-else :src="captchaData.image" class="w-full h-full" mode="aspectFit"
|
||||||
|
@click="handleGetCaptchaImage()"></image>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</tm-input>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<view class="pa-24 pl-30 pr-30">
|
||||||
|
<tm-button navtie-type="form" theme="bg-gradient-blue-accent" block>提交
|
||||||
|
</tm-button>
|
||||||
|
</view>
|
||||||
|
</tm-form>
|
||||||
|
</tm-poup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
|
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
|
||||||
import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
|
import tmForm from '@/tm-vuetify/components/tm-form/tm-form.vue';
|
||||||
import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
|
import tmInput from '@/tm-vuetify/components/tm-input/tm-input.vue';
|
||||||
import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
|
import tmSwitch from '@/tm-vuetify/components/tm-switch/tm-switch.vue';
|
||||||
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
|
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CommentModal',
|
name: 'CommentModal',
|
||||||
components: {
|
components: {
|
||||||
tmPoup,
|
tmPoup,
|
||||||
tmForm,
|
tmForm,
|
||||||
tmInput,
|
tmInput,
|
||||||
tmSwitch,
|
tmSwitch,
|
||||||
tmButton
|
tmButton
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
show: {
|
show: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
isComment: {
|
isComment: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: ""
|
||||||
},
|
},
|
||||||
postName: {
|
postName: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isShow: false,
|
isShow: false,
|
||||||
params: {
|
config: {
|
||||||
postName: '',
|
basic: {
|
||||||
title: '', // 被回复的标题 type=user =用户名 否则为文章标题
|
enablePrivateComment: true,
|
||||||
form: '',
|
},
|
||||||
formPage: '', // 来自哪个页面
|
security: {
|
||||||
type: 'post' // 来源文章/页面 还是用户 user=用户
|
captcha: {
|
||||||
},
|
enable: false,
|
||||||
form: {
|
type: "ARITHMETIC",
|
||||||
allowNotification: true,
|
captchaLength: 4,
|
||||||
author: '', // 作者
|
arithmeticRange: "20",
|
||||||
avatar: '',
|
ignoreCase: true,
|
||||||
authorUrl: '', // 作者主页
|
anonymousCommentCaptcha: false
|
||||||
content: '', // 评论内容
|
}
|
||||||
email: '', // 邮件
|
},
|
||||||
postName: ""
|
editor: {
|
||||||
}
|
placeholder: "请输入内容,不超过200字符..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
captchaData: {
|
||||||
calcTitle() {
|
image: '', // 验证码
|
||||||
if (this.isComment) {
|
status: 'loading', // 状态 loading = 正在获取 success = 获取成功 fail = 获取失败
|
||||||
return this.title
|
},
|
||||||
}
|
params: {
|
||||||
return `回复用户:${this.title}`
|
postName: '',
|
||||||
}
|
title: '', // 被回复的标题 type=user =用户名 否则为文章标题
|
||||||
},
|
form: '',
|
||||||
watch: {
|
formPage: '', // 来自哪个页面
|
||||||
show: {
|
type: 'post' // 来源文章/页面 还是用户 user=用户
|
||||||
immediate: true,
|
},
|
||||||
handler: function (newVal) {
|
form: {
|
||||||
if (!newVal) return;
|
allowNotification: true,
|
||||||
this.isShow = true;
|
author: '', // 作者
|
||||||
this.handleResetForm();
|
avatar: '',
|
||||||
this.form.postName = this.postName;
|
authorUrl: '', // 作者主页
|
||||||
let visitor = uni.getStorageSync('Visitor')
|
content: '', // 评论内容
|
||||||
if (!visitor) return;
|
email: '', // 邮件
|
||||||
visitor = JSON.parse(visitor)
|
postName: "",
|
||||||
this.form.author = visitor.author;
|
captchaCode: undefined,
|
||||||
this.form.avatar = visitor.avatar;
|
}
|
||||||
this.form.email = visitor.email;
|
}
|
||||||
this.form.authorUrl = visitor.authorUrl;
|
},
|
||||||
}
|
computed: {
|
||||||
}
|
calcTitle() {
|
||||||
},
|
if (this.isComment) {
|
||||||
methods: {
|
return this.title
|
||||||
handleResetForm() {
|
}
|
||||||
this.params = {
|
return `回复用户:${this.title}`
|
||||||
postName: '',
|
}
|
||||||
title: '',
|
},
|
||||||
form: '',
|
watch: {
|
||||||
formPage: '',
|
show: {
|
||||||
type: 'post'
|
immediate: true,
|
||||||
}
|
handler: function(newVal) {
|
||||||
this.form = {
|
console.log("评论弹窗:", newVal)
|
||||||
allowNotification: true,
|
if (!newVal) return;
|
||||||
author: '',
|
this.isShow = true;
|
||||||
avatar: '',
|
this.handleResetForm();
|
||||||
authorUrl: '',
|
this.form.postName = this.postName;
|
||||||
content: '',
|
|
||||||
email: '',
|
|
||||||
postName: ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fnOnSubmit(e) {
|
|
||||||
if (e === false) {
|
|
||||||
return uni.$tm.toast('请检查所有的必填项是否填写完整!');
|
|
||||||
}
|
|
||||||
// if (!this.form.email) {
|
|
||||||
// return uni.$tm.toast('未填写邮箱地址,将无法接收提醒!');
|
|
||||||
// }
|
|
||||||
// if (this.form.email && !uni.$tm.test.email(this.form.email)) {
|
|
||||||
// return uni.$tm.toast('请填写正确的邮箱地址!');
|
|
||||||
// }
|
|
||||||
// if (this.form.authorUrl && !uni.$tm.test.url(this.form.authorUrl)) {
|
|
||||||
// return uni.$tm.toast('请输入正确的Url地址!');
|
|
||||||
// }
|
|
||||||
this.fnHandle();
|
|
||||||
},
|
|
||||||
handleSetVisitor() {
|
|
||||||
uni.setStorageSync('Visitor', JSON.stringify({
|
|
||||||
author: this.form.author,
|
|
||||||
avatar: this.form.avatar,
|
|
||||||
email: this.form.email,
|
|
||||||
authorUrl: this.form.authorUrl,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
fnHandle() {
|
|
||||||
uni.showLoading({
|
|
||||||
title: '正在提交...'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 评论
|
this.handleGetConfig();
|
||||||
if (this.isComment) {
|
|
||||||
const commentForm = {
|
|
||||||
allowNotification: true,
|
|
||||||
raw: this.form.content,
|
|
||||||
content: this.form.content,
|
|
||||||
owner: {
|
|
||||||
avatar: this.form.avatar,
|
|
||||||
displayName: this.form.author,
|
|
||||||
email: this.form.email,
|
|
||||||
website: this.form.authorUrl,
|
|
||||||
},
|
|
||||||
subjectRef: {
|
|
||||||
group: "content.halo.run",
|
|
||||||
kind: "Post",
|
|
||||||
name: this.form.postName,
|
|
||||||
version: "v1alpha1",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$httpApi.v2.addPostComment(commentForm)
|
|
||||||
.then(res => {
|
|
||||||
uni.$tm.toast('评论成功,可能需要审核!');
|
|
||||||
// 更新评论者信息
|
|
||||||
this.handleSetVisitor();
|
|
||||||
this.handleClose(true)
|
|
||||||
this.handleResetForm()
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
uni.$tm.toast("评论失败");
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 回复
|
this.handleInitVisitor();
|
||||||
const replyForm = {
|
}
|
||||||
allowNotification: true,
|
}
|
||||||
raw: this.form.content,
|
},
|
||||||
content: this.form.content,
|
methods: {
|
||||||
owner: {
|
handleResetForm() {
|
||||||
avatar: this.form.avatar,
|
this.params = {
|
||||||
displayName: this.form.author,
|
postName: '',
|
||||||
email: this.form.email,
|
title: '',
|
||||||
website: this.form.authorUrl,
|
form: '',
|
||||||
},
|
formPage: '',
|
||||||
quoteReply: this.form.postName
|
type: 'post'
|
||||||
}
|
}
|
||||||
this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm)
|
this.form = {
|
||||||
.then(res => {
|
allowNotification: true,
|
||||||
uni.$tm.toast('回复成功,可能需要审核!');
|
author: '',
|
||||||
// 更新评论者信息
|
avatar: '',
|
||||||
this.handleSetVisitor();
|
authorUrl: '',
|
||||||
this.handleClose(true)
|
content: '',
|
||||||
this.handleResetForm()
|
email: '',
|
||||||
})
|
postName: "",
|
||||||
.catch(err => {
|
captchaCode: "",
|
||||||
uni.$tm.toast("回复失败");
|
}
|
||||||
});
|
},
|
||||||
},
|
fnOnSubmit(e) {
|
||||||
handleOnChange(isOpen) {
|
console.log("评论弹窗:", e)
|
||||||
this.isShow = isOpen;
|
if (e === false) {
|
||||||
if(!isOpen){
|
return uni.$tm.toast('请检查所有的必填项是否填写完整!');
|
||||||
|
}
|
||||||
|
// if (!this.form.email) {
|
||||||
|
// return uni.$tm.toast('未填写邮箱地址,将无法接收提醒!');
|
||||||
|
// }
|
||||||
|
// if (this.form.email && !uni.$tm.test.email(this.form.email)) {
|
||||||
|
// return uni.$tm.toast('请填写正确的邮箱地址!');
|
||||||
|
// }
|
||||||
|
// if (this.form.authorUrl && !uni.$tm.test.url(this.form.authorUrl)) {
|
||||||
|
// return uni.$tm.toast('请输入正确的Url地址!');
|
||||||
|
// }
|
||||||
|
if (this.config?.security?.captcha?.anonymousCommentCaptcha) {
|
||||||
|
if (!this.form.captchaCode.trim()) {
|
||||||
|
return uni.$tm.toast('请填写验证码结果!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.form.captchaCode = undefined;
|
||||||
|
}
|
||||||
|
this.fnHandle();
|
||||||
|
},
|
||||||
|
handleGetConfig() {
|
||||||
|
this.$httpApi.v2Config.getCommentWidgetConfig()
|
||||||
|
.then(res => {
|
||||||
|
console.log("获取验证码配置", res)
|
||||||
|
this.config = this.$utils.deepMerge(this.config, res)
|
||||||
|
if (this.config?.security?.captcha?.anonymousCommentCaptcha) {
|
||||||
|
this.handleGetCaptchaImage();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("获取验证码配置失败", err)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleGetCaptchaImage() {
|
||||||
|
this.captchaData.status = 'loading';
|
||||||
|
this.$httpApi.v2.getCommentWidgetCaptcha()
|
||||||
|
.then(res => {
|
||||||
|
this.form.captchaCode = undefined;
|
||||||
|
this.captchaData.image = res;
|
||||||
|
this.captchaData.status = 'success';
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("获取验证码失败", err)
|
||||||
|
this.captchaData.status = 'fail';
|
||||||
|
this.captchaData.image = '';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleInitVisitor() {
|
||||||
|
let visitor = uni.getStorageSync('Visitor')
|
||||||
|
if (!visitor) return;
|
||||||
|
visitor = JSON.parse(visitor)
|
||||||
|
this.form.author = visitor.author;
|
||||||
|
this.form.avatar = visitor.avatar;
|
||||||
|
this.form.email = visitor.email;
|
||||||
|
this.form.authorUrl = visitor.authorUrl;
|
||||||
|
},
|
||||||
|
handleSetVisitor() {
|
||||||
|
uni.setStorageSync('Visitor', JSON.stringify({
|
||||||
|
author: this.form.author,
|
||||||
|
avatar: this.form.avatar,
|
||||||
|
email: this.form.email,
|
||||||
|
authorUrl: this.form.authorUrl,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
fnHandle() {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '正在提交...'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 评论
|
||||||
|
if (this.isComment) {
|
||||||
|
const commentForm = {
|
||||||
|
allowNotification: true,
|
||||||
|
raw: this.form.content,
|
||||||
|
content: this.form.content,
|
||||||
|
owner: {
|
||||||
|
// avatar: this.form.avatar,
|
||||||
|
displayName: this.form.author,
|
||||||
|
email: this.form.email,
|
||||||
|
website: this.form.authorUrl,
|
||||||
|
},
|
||||||
|
subjectRef: {
|
||||||
|
group: "content.halo.run",
|
||||||
|
kind: "Post",
|
||||||
|
name: this.form.postName,
|
||||||
|
version: "v1alpha1",
|
||||||
|
},
|
||||||
|
captchaCode: this.form.captchaCode,
|
||||||
|
}
|
||||||
|
this.$httpApi.v2.addPostComment(commentForm)
|
||||||
|
.then(res => {
|
||||||
|
uni.$tm.toast('评论成功,可能需要审核!');
|
||||||
|
// 更新评论者信息
|
||||||
|
this.handleSetVisitor();
|
||||||
|
this.handleClose(true)
|
||||||
|
this.handleResetForm()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (this.config?.security?.captcha?.anonymousCommentCaptcha) {
|
||||||
|
this.captchaData.image = err.captcha;
|
||||||
|
this.captchaData.status = 'success';
|
||||||
|
this.form.captchaCode = undefined;
|
||||||
|
uni.$tm.toast(err.detail ?? '评论失败');
|
||||||
|
} else {
|
||||||
|
uni.$tm.toast("评论失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回复
|
||||||
|
const replyForm = {
|
||||||
|
allowNotification: true,
|
||||||
|
raw: this.form.content,
|
||||||
|
content: this.form.content,
|
||||||
|
owner: {
|
||||||
|
// avatar: this.form.avatar,
|
||||||
|
displayName: this.form.author,
|
||||||
|
email: this.form.email,
|
||||||
|
website: this.form.authorUrl,
|
||||||
|
},
|
||||||
|
quoteReply: this.form.postName,
|
||||||
|
captchaCode: this.form.captchaCode,
|
||||||
|
}
|
||||||
|
this.$httpApi.v2.addPostCommentReply(this.form.postName, replyForm)
|
||||||
|
.then(res => {
|
||||||
|
uni.$tm.toast('回复成功,可能需要审核!');
|
||||||
|
// 更新评论者信息
|
||||||
|
this.handleSetVisitor();
|
||||||
|
this.handleClose(true)
|
||||||
|
this.handleResetForm()
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (this.config?.security?.captcha?.anonymousCommentCaptcha) {
|
||||||
|
this.captchaData.image = err.captcha;
|
||||||
|
this.captchaData.status = 'success';
|
||||||
|
this.form.captchaCode = undefined;
|
||||||
|
uni.$tm.toast(err.detail ?? '恢复失败');
|
||||||
|
} else {
|
||||||
|
uni.$tm.toast("回复失败");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleOnChange(isOpen) {
|
||||||
|
this.isShow = isOpen;
|
||||||
|
if (!isOpen) {
|
||||||
|
this.$emit("on-close", {
|
||||||
|
isSubmit: false,
|
||||||
|
refresh: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleClose(refresh = false) {
|
||||||
|
this.isShow = false;
|
||||||
this.$emit("on-close", {
|
this.$emit("on-close", {
|
||||||
isSubmit:false,
|
isSubmit: true,
|
||||||
refresh: false
|
refresh: refresh
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
handleClose(refresh = false) {
|
}
|
||||||
this.isShow = false;
|
|
||||||
this.$emit("on-close", {
|
|
||||||
isSubmit:true,
|
|
||||||
refresh: refresh
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.title {
|
.title {
|
||||||
margin: 24rpx 0;
|
margin: 24rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.captch-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 200rpx;
|
||||||
|
height: 68rpx;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// 应用设置存储key值
|
||||||
|
export const _HaloConfigKey = 'HALO_GLOBAL_CONFIGS';
|
||||||
|
|
||||||
|
// 默认的应用设置
|
||||||
|
export const DefaultHaloGlobalConfigs = {
|
||||||
|
allowAnonymousComments: true,
|
||||||
|
allowRegistration: true,
|
||||||
|
mustVerifyEmailOnRegistration: true,
|
||||||
|
mustVerifyPhoneOnRegistration: false,
|
||||||
|
restrictRegistrationDomain: false,
|
||||||
|
shopDisabled: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用设置
|
||||||
|
*/
|
||||||
|
export const getHaloGlobalConfigs = () => {
|
||||||
|
let configs = uni.getStorageSync(_HaloConfigKey)
|
||||||
|
if (configs) return JSON.parse(configs)
|
||||||
|
|
||||||
|
uni.setStorageSync(_HaloConfigKey, JSON.stringify(DefaultHaloGlobalConfigs))
|
||||||
|
return DefaultHaloConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存应用设置
|
||||||
|
*/
|
||||||
|
export const setHaloGlobalConfigs = (configs) => {
|
||||||
|
uni.setStorageSync(_HaloConfigKey, JSON.stringify(configs))
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
* 版本:v0.1.0
|
* 版本:v0.1.0
|
||||||
*/
|
*/
|
||||||
import {DefaultAppConfigs, getAppConfigs, getAppMockJson, setAppConfigs, setAppMockJson} from '@/config/index.js'
|
import {DefaultAppConfigs, getAppConfigs, getAppMockJson, setAppConfigs, setAppMockJson} from '@/config/index.js'
|
||||||
|
import {DefaultHaloGlobalConfigs, getHaloGlobalConfigs, setHaloGlobalConfigs} from '@/config/halo.config.js'
|
||||||
import v2Config from '@/api/v2/all.config.js'
|
import v2Config from '@/api/v2/all.config.js'
|
||||||
import utils from '@/utils/index.js'
|
import utils from '@/utils/index.js'
|
||||||
import {setTokens} from "@/utils/token";
|
import {setTokens} from "@/utils/token";
|
||||||
@@ -13,10 +14,15 @@ import {setTokens} from "@/utils/token";
|
|||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
state: {
|
state: {
|
||||||
|
haloConfig: getHaloGlobalConfigs(),
|
||||||
configs: getAppConfigs(),
|
configs: getAppConfigs(),
|
||||||
mockJson: getAppMockJson(),
|
mockJson: getAppMockJson(),
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
|
getHaloConfig(state) {
|
||||||
|
if (state.haloConfig) return state.haloConfig;
|
||||||
|
return getHaloGlobalConfigs();
|
||||||
|
},
|
||||||
getConfigs(state) {
|
getConfigs(state) {
|
||||||
if (state.configs) return state.configs;
|
if (state.configs) return state.configs;
|
||||||
return getAppConfigs()
|
return getAppConfigs()
|
||||||
@@ -27,6 +33,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
setHaloConfigs(state, data) {
|
||||||
|
state.haloConfig = data;
|
||||||
|
setHaloGlobalConfigs(data);
|
||||||
|
},
|
||||||
setConfigs(state, data) {
|
setConfigs(state, data) {
|
||||||
state.configs = data;
|
state.configs = data;
|
||||||
setAppConfigs(data)
|
setAppConfigs(data)
|
||||||
@@ -37,6 +47,23 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
fetchHaloConfigs({state, commit, dispatch}) {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const res = await v2Config.getHaloGlobalInfo()
|
||||||
|
if (res) {
|
||||||
|
commit('setHaloConfigs', utils.deepMerge(DefaultHaloGlobalConfigs, res))
|
||||||
|
resolve(res)
|
||||||
|
} else {
|
||||||
|
dispatch("setDefaultHaloGlobalConfigs");
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
dispatch("setDefaultHaloGlobalConfigs");
|
||||||
|
reject()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
fetchConfigs({state, commit, dispatch}) {
|
fetchConfigs({state, commit, dispatch}) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
@@ -59,6 +86,10 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
// 设置默认的数据
|
||||||
|
setDefaultHaloGlobalConfigs({commit}) {
|
||||||
|
commit('setHaloConfigs', JSON.parse(JSON.stringify(DefaultHaloGlobalConfigs)))
|
||||||
|
},
|
||||||
// 设置默认的数据
|
// 设置默认的数据
|
||||||
setDefaultAppSettings({commit}) {
|
setDefaultAppSettings({commit}) {
|
||||||
commit('setConfigs', JSON.parse(JSON.stringify(DefaultAppConfigs)))
|
commit('setConfigs', JSON.parse(JSON.stringify(DefaultAppConfigs)))
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 从带换行的cookie原始串提取某一条cookie(带;结尾)
|
||||||
|
* @param {string} cookieRaw set‑cookie原始字符串
|
||||||
|
* @param {string} cookieKey cookie名称,例如 "comment-widget-captcha"
|
||||||
|
* @returns {string} 清理换行后的cookie片段,没匹配返回''
|
||||||
|
*/
|
||||||
|
export function extractCookieItem(cookieRaw, cookieKey) {
|
||||||
|
if (!cookieRaw || !cookieKey) return ''
|
||||||
|
|
||||||
|
// 转义正则特殊字符
|
||||||
|
function escapeRegExp(str) {
|
||||||
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyEscaped = escapeRegExp(cookieKey)
|
||||||
|
const reg = new RegExp(`${keyEscaped}=[\\s\\S]*?;`)
|
||||||
|
const m = cookieRaw.match(reg)
|
||||||
|
return m ? m[0].replace(/\r?\n/g, '') : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取header中指定key的值,忽略大小写
|
||||||
|
* @param {object} headers HTTP header对象
|
||||||
|
* @param {string} name HTTP header键名
|
||||||
|
* @returns {string} HTTP header值,没找到返回''
|
||||||
|
*/
|
||||||
|
export function getHeaderCaseInsensitive(headers, name) {
|
||||||
|
if (!headers || typeof headers !== 'object') return '';
|
||||||
|
const lowerName = name.toLowerCase();
|
||||||
|
const key = Object.keys(headers).find(k => k.toLowerCase() === lowerName);
|
||||||
|
return key ? headers[key] : '';
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user