提交 6934f737 authored 作者: lidongxu's avatar lidongxu

fix(utils/request.js): 修复 token 过期飞书客户端默认获取新 token 时,静默获取

同上
上级 6cae6489
......@@ -65,39 +65,40 @@ resize()
onMounted(() => {
window.addEventListener('resize', resize)
})
nextTick(() => {
let isDown = false
levitatedSphere.value.addEventListener('mousedown', (e) => {
e.preventDefault();
levitatedSphere.value.style.transition = 'none';
downPoint.x = e.clientX
downPoint.y = e.clientY
isDown = true
})
// 在拖拽过程中,组件应该跟随手指的移动而移动
window.addEventListener('mousemove', (e) => {
e.preventDefault();
if (isDown) {
let touch = e;
// 限制 left 和 top 的值,使其不会超出可视区域
left.value = Math.max(props.gapWidth, Math.min(touch.clientX - 20, clientWidth.value - props.itemWidth - props.gapWidth));
top.value = Math.max(0, Math.min(touch.clientY - 25, clientHeight.value - props.itemHeight));
}
nextTick(() => {
let isDown = false
levitatedSphere.value.addEventListener('mousedown', (e) => {
e.preventDefault();
levitatedSphere.value.style.transition = 'none';
downPoint.x = e.clientX
downPoint.y = e.clientY
isDown = true
})
// 在拖拽过程中,组件应该跟随手指的移动而移动
window.addEventListener('mousemove', (e) => {
e.preventDefault();
if (isDown) {
let touch = e;
// 限制 left 和 top 的值,使其不会超出可视区域
left.value = Math.max(props.gapWidth, Math.min(touch.clientX - 20, clientWidth.value - props.itemWidth - props.gapWidth));
top.value = Math.max(0, Math.min(touch.clientY - 25, clientHeight.value - props.itemHeight));
}
});
// 拖拽结束后,重新调整组件的位置并重新设置过渡动画
window.addEventListener('mouseup', (e) => {
levitatedSphere.value.style.transition = 'all 0.5s';
if (left.value > document.documentElement.clientWidth / 2) {
left.value = document.documentElement.clientWidth - props.itemWidth - props.gapWidth;
} else {
left.value = props.gapWidth;
}
isDown = false
upPoint.x = e.clientX
upPoint.y = e.clientY
})
});
// 拖拽结束后,重新调整组件的位置并重新设置过渡动画
window.addEventListener('mouseup', (e) => {
levitatedSphere.value.style.transition = 'all 0.5s';
if (left.value > document.documentElement.clientWidth / 2) {
left.value = document.documentElement.clientWidth - props.itemWidth - props.gapWidth;
} else {
left.value = props.gapWidth;
}
isDown = false
upPoint.x = e.clientX
upPoint.y = e.clientY
})
});
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resize)
......
import axios from 'axios'
import { ElNotification , ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import { tansParams, blobValidate } from '@/utils/ruoyi'
......@@ -67,46 +67,56 @@ service.interceptors.request.use(config => {
}
return config
}, error => {
console.log(error)
Promise.reject(error)
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
service.interceptors.response.use(async res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (window.h5sdk) {
// 如果在飞书客户端,则无感知重新获取token
const code = await fsClientAuth()
await useUserStore().login({
type: 'fs',
code
})
// 重新发送本次失败的请求
return service(res.config)
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '#/index';
})
if (!isRelogin.show) {
isRelogin.show = true;
ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
isRelogin.show = false;
useUserStore().logOut().then(() => {
location.href = '#/index';
})
}).catch(() => {
isRelogin.show = false;
});
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
ElMessage({ message: msg, type: 'error' })
return Promise.reject(new Error(msg))
} else if (code === 601) {
ElMessage({ message: msg, type: 'warning' })
return Promise.reject(new Error(msg))
} else if (code !== 200) {
ElNotification.error({ title: msg })
return Promise.reject('error')
} else {
return Promise.resolve(res.data)
}
},
error => {
console.log('err' + error)
let { message } = error;
......
......@@ -85,7 +85,6 @@ const setOptions = () => {
else yObj.name = target.name.split('-')[1]
})
})
chart.value.setOption({
xAxis: {
type: 'category',
......@@ -161,7 +160,7 @@ const setOptions = () => {
}
watchEffect(() => {
if (!chart.value || props.chartData.series.length === 0) return
if (!chart.value) return
myThousand = props.chartData.series?.some(o => {
return o.data.some(num => num >= 10000)
})
......
......@@ -55,24 +55,26 @@
</template>
<script setup>
import { ref, reactive } from 'vue'
import LineCharts from './LineAndBar.vue'
import { getCmmListAPI } from '@/api'
import { generatorDayList, parseTime, getBrandColor, resetObjValue } from '@/utils'
import { useDatePickerOptions } from '@/hooks/date'
// 最近 30 日日期数组
const dateList = [new Date().setDate((new Date().getDate() - 30)), new Date().setDate((new Date().getDate() - 1))]
// 数据类型
const dataTypeList = ['销售额', '观看人次']
// 静态数据
const dateList = [new Date().setDate((new Date().getDate() - 30)), new Date().setDate((new Date().getDate() - 1))] // 最近 30 日日期数组
const dataTypeList = ['销售额', '观看人次'] // 数据类型
// 页面使用数据
const brandList = ref([])// 直播间列表
const typeList = ref(dataTypeList) // 数据类型列表
const { pickerOptions } = useDatePickerOptions()
const queryParams = reactive({ // 查询表单
brandList: [],
date: dateList,
typeList: dataTypeList
})
const { pickerOptions } = useDatePickerOptions()
const brandList = ref([])// 直播间列表
const typeList = ref(dataTypeList)
const allChartData = reactive({ // 图表所有数据
xAxis: [],
legend: [],
......@@ -214,6 +216,7 @@ const filterData = () => {
// 最后赋予给要展示的部分
chartData.legend = legend
chartData.series = series
console.log(series)
chartData.xAxis = allChartData.xAxis
}
......
......@@ -24,7 +24,7 @@ const list = ref([
{ name: '生意参谋-竞店', component: shallowRef(sycmStore) },
{ name: '生意参谋-竞品', component: shallowRef(sycmPrd) }
])
const activeName = ref(list.value[0].name)
const activeName = ref(list.value[1].name)
</script>
<style scoped
......
<template>
<div :class="className"
<div ref="echartsRef"
:class="className"
:style="{ height: height, width: width }" />
</template>
<script>
// 渐变堆叠面积图
<script setup>
import * as echarts from 'echarts'
import resize from '@/views/dashboard/mixins/resize'
import { roundUpToNextHighestPowerOfTen } from '@/utils'
const props = defineProps({
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '600px'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object,
required: true
}
})
const echartsRef = ref(null)
const chart = shallowRef(null)
let myThousand = false // 是否显示万单位
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
const setOptions = () => {
chart.value.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
width: {
type: String,
default: '100%'
legend: {
data: props.chartData.legend
},
height: {
type: String,
default: '600px'
toolbox: {
feature: {
saveAsImage: {},
magicType: {
type: ['stack', 'tiled'] // 切换图表类型
},
}
},
autoResize: {
type: Boolean,
default: true
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
chartData: {
type: Object,
required: true
}
},
data() {
return {
chart: null,
myThousand: false
}
},
watch: {
chartData: {
deep: true,
handler(val) {
// this.chart.clear(); // 清除图表(重新设置)
this.setOptions(val)
xAxis: [
{
// type: 'category',
// boundaryGap: false,
data: props.chartData.xAxis
}
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
],
yAxis: [
{
type: 'value'
}
],
series: props.chartData.series
}, true)
}
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
watchEffect(() => {
if (!chart.value) return
myThousand = props.chartData.series?.some(o => {
return o.data.some(num => num >= 10000)
})
setOptions()
})
setTimeout(() => {
this.setOptions(this.chartData)
}, 10000)
},
setOptions({ expectedData, actualData } = {}) {
this.chart.setOption({
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
data: this.chartData.legend
},
toolbox: {
feature: {
saveAsImage: {},
magicType: {
type: ['stack', 'tiled'] // 切换图表类型
},
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
// type: 'category',
boundaryGap: false,
data: this.chartData.xAxis
}
],
yAxis: [
{
type: 'value'
}
],
series: this.chartData.series
// series: [
// {
// name: 'Line 1',
// type: 'line',
// stack: 'Total',
// smooth: true,
// lineStyle: {
// width: 0
// },
// showSymbol: false,
// areaStyle: {
// opacity: 0.8,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgb(128, 255, 165)'
// },
// {
// offset: 1,
// color: 'rgb(1, 191, 236)'
// }
// ])
// },
// emphasis: { // 高亮图形时,淡化其他
// focus: 'series'
// },
// data: [140, 232, 101, 264, 90, 340, 250]
// },
// {
// name: 'Line 2',
// type: 'line',
// stack: 'Total',
// smooth: true,
// lineStyle: {
// width: 0
// },
// showSymbol: false,
// areaStyle: {
// opacity: 0.8,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgb(0, 221, 255)'
// },
// {
// offset: 1,
// color: 'rgb(77, 119, 255)'
// }
// ])
// },
// emphasis: {
// focus: 'series'
// },
// data: [120, 282, 111, 234, 220, 340, 310]
// },
// {
// name: 'Line 3',
// type: 'line',
// stack: 'Total',
// smooth: true,
// lineStyle: {
// width: 0
// },
// showSymbol: false,
// areaStyle: {
// opacity: 0.8,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgb(55, 162, 255)'
// },
// {
// offset: 1,
// color: 'rgb(116, 21, 219)'
// }
// ])
// },
// emphasis: {
// focus: 'series'
// },
// data: [320, 132, 201, 334, 190, 130, 220]
// },
// {
// name: 'Line 4',
// type: 'line',
// stack: 'Total',
// smooth: true,
// lineStyle: {
// width: 0
// },
// showSymbol: false,
// areaStyle: {
// opacity: 0.8,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgb(255, 0, 135)'
// },
// {
// offset: 1,
// color: 'rgb(135, 0, 157)'
// }
// ])
// },
// emphasis: {
// focus: 'series'
// },
// data: [220, 402, 231, 134, 190, 230, 120]
// },
// {
// name: 'Line 5',
// type: 'line',
// stack: 'Total',
// smooth: true,
// lineStyle: {
// width: 0
// },
// showSymbol: false,
// label: {
// show: true,
// position: 'top'
// },
// areaStyle: {
// opacity: 0.8,
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgb(255, 191, 0)'
// },
// {
// offset: 1,
// color: 'rgb(224, 62, 76)'
// }
// ])
// },
// emphasis: {
// focus: 'series'
// },
// data: [220, 302, 181, 234, 210, 290, 150]
// }
// ]
})
}
}
const initChart = () => {
chart.value = echarts.init(echartsRef.value)
}
const resize = () => {
chart.value.resize()
}
</script>
onMounted(() => {
nextTick(() => {
initChart()
})
})
onBeforeUnmount(() => {
if (!chart.value) {
return
}
window.removeEventListener('resize', resize)
chart.value.dispose()
chart.value = null
})
</script>
\ No newline at end of file
<template>
<div>
<el-form :model="queryParams"
inline
size="small">
inline>
<el-form-item label="店铺">
<el-select v-model="queryParams.brandList"
@change="queryChangeFn"
......@@ -16,7 +15,7 @@
</el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="数据查看">
<el-form-item label="数据类型">
<el-select v-model="queryParams.typeList"
@change="queryChangeFn"
multiple
......@@ -31,14 +30,14 @@
<el-form-item label="日期选择">
<el-date-picker v-model="queryParams.date"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:shortcuts="pickerOptions"
@change="queryChangeFn('date')">
</el-date-picker>
</el-form-item> -->
</el-form-item>
</el-form>
<div class="chart_wrap">
<gradient-area :chartData="chartData"></gradient-area>
......@@ -47,34 +46,42 @@
</template>
<script setup>
import * as echarts from 'echarts'
import { ref, reactive, nextTick } from 'vue'
import GradientArea from './GradientArea.vue';
import { getSycmListAPI } from '@/api'
import { generatorDayList, parseTime, getBrandColor } from '@/utils'
import { generatorDayList, parseTime, getBrandColor, resetObjValue } from '@/utils'
import { useDatePickerOptions } from '@/hooks/date'
// 静态数据
const dateList = [new Date().setDate((new Date().getDate() - 30)), new Date().setDate((new Date().getDate() - 1))] // 最近 30 日日期数组
const dataTypeList = ['支付买家数', '交易增速', '独立访客范围', '流量增速'] // 数据类型
// 本页数据
const typeList = ref(dataTypeList)
const { pickerOptions } = useDatePickerOptions()
const brandList = ref([]) // 店铺列表
const queryParams = reactive({ // 查询表单
brandList: [],
date: [new Date().setDate(new Date().getDate() - 30), new Date().setDate(new Date().getDate() - 1)],
// typeList: []
typeList: [typeList.value[0]],
date: dateList,
})
const brandList = ref([]) // 直播间列表
const typeList = ref(['支付买家数', '交易增速', '独立访客范围', '流量增速'])
const allChartData = reactive({ // 图表所有数据
series: [],
xAxis: [],
legend: []
legend: [],
series: []
})
const chartData = reactive({ // 图表内要用的数据
series: [],
xAxis: [],
legend: []
legend: [],
series: [],
})
// 获取数据
const getList = async () => {
allChartData.series = []
allChartData.legend = []
resetObjValue(allChartData)
// 获取 x 轴时间
allChartData.xAxis = generatorDayList(queryParams.date[0], queryParams.date[1])
const { data } = await getSycmListAPI({
startDate: parseTime(queryParams.date[0], '{y}-{m}-{d}'),
endDate: parseTime(queryParams.date[1], '{y}-{m}-{d}'),
......@@ -94,7 +101,7 @@ const getList = async () => {
showSymbol: false,
emphasis: {
focus: 'series'
},
}
}
let jyzsObj = {
...commonObj,
......@@ -168,8 +175,9 @@ const getList = async () => {
// 筛选数据
const filterData = () => {
let series = allChartData.series
let legend = allChartData.legend
let series = allChartData.series
if (queryParams.brandList.length > 0) {
// 选择了店铺,筛选
series = series.filter(item => {
......@@ -179,8 +187,9 @@ const filterData = () => {
return queryParams.brandList.find(o => o === name.split('-')[0])
})
}
// 选择了数据类型,筛选
if (queryParams.typeList.length > 0) {
// 选择了数据类型,筛选
series = series.filter(item => {
return queryParams.typeList.find(o => o === item.name.split('-')[1])
})
......@@ -188,27 +197,23 @@ const filterData = () => {
return queryParams.typeList.find(o => o === name.split('-')[1])
})
}
// 展示所有
chartData.legend = legend
chartData.series = series
chartData.xAxis = allChartData.xAxis
}
// 默认打开页面请求一次所有数据,并保存在数据源
(function init() {
nextTick(async () => {
// // 初始化时间
// allChartData.xAxis = generatorDayList(queryParams.date[0], queryParams.date[1])
const data = await getList()
// 直播间列表
brandList.value = data.map(list => list[0].platformStore)
// 初始化筛选条件(默认请求第一个店铺的第一类型数据)
queryParams.brandList = [data[0][0].platformStore]
queryParams.typeList = [typeList.value[0]]
// 筛选图表数据
filterData()
})
})();
async function init() {
const data = await getList()
// 直播间列表
brandList.value = data.map(list => list[0].platformStore)
// 初始化筛选条件(默认请求第一个店铺的第一类型数据)
queryParams.brandList = [data[0][0].platformStore]
// 筛选图表数据
filterData()
};
init()
// 查询条件改变
const queryChangeFn = async (arg) => {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论