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

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

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