fix: 封装数据处理

This commit is contained in:
mtruning 2022-03-21 00:57:23 +08:00
parent 593a48eea4
commit c937555020
12 changed files with 338 additions and 199 deletions

4
.env
View File

@ -2,10 +2,10 @@
VITE_DEV_PORT = '8001'
# development path
VITE_DEV_PATH = /
VITE_DEV_PATH = '/'
# production path
VITE_PRO_PATH = /
VITE_PRO_PATH = '/'
# spa-title
VITE_GLOB_APP_TITLE = GoView

View File

@ -1,34 +1,35 @@
import axiosInstance from './axios'
import { RequestEnum, ContentTypeEnum } from '@/enums/httpEnum'
// 缓存处理
const filterUrl = (url: string) => {
return url.indexOf('?') !== -1 ? `${url}&time=${new Date().getTime()}` : `${url}?time=${new Date().getTime()}`
}
export const get = (params: object, url: string) => {
export const get = (url: string, params: object) => {
return axiosInstance({
url: filterUrl(url),
url: url,
method: RequestEnum.GET,
params
params,
})
}
export const post = (params: object, url: string, headersType: string) => {
export const post = (url: string, params: object, headersType: string) => {
return axiosInstance({
url: url,
method: RequestEnum.POST,
data: params,
headers: {
'Content-Type': headersType || ContentTypeEnum.JSON
}
'Content-Type': headersType || ContentTypeEnum.JSON,
},
})
}
export const del = (params: object, url: string) => {
export const del = (url: string, params: object) => {
return axiosInstance({
url: filterUrl(url),
url: url,
method: RequestEnum.DELETE,
params
params,
})
}
export default {
get,
post,
del,
}

13
src/api/mock/index.js Normal file
View File

@ -0,0 +1,13 @@
import Mock from 'mockjs'
import test from './test.mock'
Mock.setup({
timeout: '300-600'
})
// 单个X数据
const featchMockData = '/api/mockData'
Mock.mock(/\/api\/test(|\?\S*)$/, 'get', test.featchMockData)
export {
featchMockData
}

42
src/api/mock/test.mock.js Normal file
View File

@ -0,0 +1,42 @@
export default {
// 轮播图
featchMockData: {
status: 200,
msg: "请求成功",
data: {
dimensions: ["product", "data1", "data2"],
source: [
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
{
'product': '@name',
'data1|100-900': 3,
'data2|100-900': 3,
},
]
}
}
}

View File

@ -1,14 +1,14 @@
<template>
<div v-show="load" class="go-skeleton">
<div v-show="repeat == 1">
<n-skeleton v-bind="$attrs"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs"></n-skeleton>
</div>
<div v-show="repeat == 2">
<n-skeleton v-bind="$attrs"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 60%;"></n-skeleton>
</div>
<div v-show="repeat > 2">
<n-skeleton v-bind="$attrs" :repeat="repeat - 2"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" :repeat="repeat - 2"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 60%;"></n-skeleton>
<n-skeleton class="item" v-bind="$attrs" style="width: 50%;"></n-skeleton>
</div>
@ -29,9 +29,11 @@ defineProps({
</script>
<style lang="scss" scoped>
@include go('skeleton') {
@include go("skeleton") {
.item {
margin-top: 5px;
margin-left: 5px;
}
padding-bottom: 5px;
}
</style>

View File

@ -0,0 +1,3 @@
import ChartDataAjax from './index.vue'
export { ChartDataAjax }

View File

@ -0,0 +1,11 @@
<template>
<div>ajax</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,3 @@
import ChartDataMatchingAndShow from './index.vue'
export { ChartDataMatchingAndShow }

View File

@ -0,0 +1,195 @@
<template>
<n-timeline class="go-chart-configurations-timeline">
<n-timeline-item type="info" :title="TimelineTitleEnum.MAPPING">
<n-table striped>
<thead>
<tr>
<th v-for="item in tableTitle" :key="item">{{ item }}</th>
</tr>
</thead>
<tbody v-show="!tableLoad">
<go-skeleton :repeat="3" :load="tableLoad" style="width: 200px;"></go-skeleton>
<tr v-for="(item, index) in tableData" :key="index">
<td>{{ item.field }}</td>
<td>{{ item.mapping }}</td>
<td>
<n-space v-if="item.result === 0">
<n-badge dot type="success"></n-badge>
<n-text></n-text>
</n-space>
<n-space v-else>
<n-badge dot :type="item.result === 1 ? 'success' : 'error'"></n-badge>
<n-text>匹配{{ item.result === 1 ? '成功' : '失败' }}</n-text>
</n-space>
</td>
</tr>
</tbody>
</n-table>
</n-timeline-item>
<n-timeline-item type="success" :title="TimelineTitleEnum.CONTENT">
<n-space vertical>
<n-text depth="3">数据需要符合 ECharts-setdata 规范</n-text>
<n-space class="source-btn-box">
<n-upload
v-model:file-list="uploadFileListRef"
:show-file-list="false"
:customRequest="customRequest"
@before-upload="beforeUpload"
>
<n-space>
<n-button class="sourceBtn-item">
<template #icon>
<n-icon>
<document-add-icon />
</n-icon>
</template>
导入json / txt
</n-button>
</n-space>
</n-upload>
<n-button class="sourceBtn-item" @click="download">
<template #icon>
<n-icon>
<document-download-icon />
</n-icon>
</template>
下载
</n-button>
</n-space>
<n-card>
<n-code :code="getSource" language="json"></n-code>
</n-card>
</n-space>
</n-timeline-item>
</n-timeline>
</template>
<script setup lang="ts">
import { ref, computed, watch, nextTick, PropType } from 'vue'
import { UploadCustomRequestOptions } from 'naive-ui'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { readFile, downloadFile } from '@/utils'
import { icon } from '@/plugins'
import { DataResultEnum, TimelineTitleEnum } from '../../index.d'
const props = defineProps({
tableData: {
type: Object,
required: true
}
})
const tableLoad = ref(true)
//
const tableTitle = ['字段', '映射', '状态']
//
watch(() => props.tableData.value, (newData: object[]) => {
if (!(newData && newData.length !== 0)) {
tableLoad.value = false
}
}, {
immediate: true
})
const { DocumentAddIcon, DocumentDownloadIcon } = icon.carbon
const uploadFileListRef = ref()
const source = ref()
const dimensions = ref()
//
const getSource = computed(() => {
return JSON.stringify(source.value)
})
watch(() => props.targetData?.option?.dataset, (newData) => {
if (newData) {
source.value = newData.source
dimensions.value = newData.dimensions
}
}, {
immediate: true
})
//
const matchingHandle = (mapping: string) => {
for (let i = 0; i < source.value.length; i++) {
let res = DataResultEnum.FAILURE
if (source.value[i][mapping] !== undefined) {
return DataResultEnum.SUCCESS
}
return res
}
return DataResultEnum.SUCCESS
}
//
const getDimensionsAndSource = computed(() => {
//
return dimensions.value.map((item: string, index: number) => {
return index === 0 ?
{
//
field: '通用标识',
//
mapping: item,
//
result: DataResultEnum.NULL
} : {
field: `数据项-${index}`,
mapping: item,
result: matchingHandle(item)
}
})
})
//@ts-ignore
const beforeUpload = ({ file }) => {
uploadFileListRef.value = []
const type = file.file.type
if (type !== FileTypeEnum.JSON && type !== FileTypeEnum.TXT) {
window['$message'].warning('仅支持上传 【JSON】 格式文件,请重新上传!')
return false
}
return true
}
//
const customRequest = (options: UploadCustomRequestOptions) => {
const { file } = options
nextTick(() => {
if (file.file) {
readFile(file.file).then((fileData: any) => {
props.targetData.option.dataset = JSON.parse(fileData)
});
} else {
window['$message'].error('导入数据失败,请稍后重试或联系管理员!')
}
})
}
//
const download = () => {
try {
window['$message'].success('正在下载文件!')
downloadFile(JSON.stringify(props.targetData?.option?.dataset), undefined, 'json')
} catch (error) {
window['$message'].success('下载失败,数据错误!')
}
}
</script>
<style lang="scss" scoped>
@include go("chart-configurations-data-static") {
@include deep() {
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
}
.source-btn-box {
margin-top: 10px !important;
}
}
</style>

View File

@ -0,0 +1,3 @@
import ChartDataStatic from './index.vue'
export { ChartDataStatic }

View File

@ -0,0 +1,33 @@
<template>
<div class="go-chart-configurations-data-static" v-if="targetData">
<ChartDataMatchingAndShow :tableData="targetData"></ChartDataMatchingAndShow>
</div>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { ChartDataMatchingAndShow } from '../ChartDataMatchingAndShow'
const props = defineProps({
targetData: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
</script>
<style lang="scss" scoped>
@include go("chart-configurations-data-static") {
@include deep() {
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
}
.source-btn-box {
margin-top: 10px !important;
}
}
</style>

View File

@ -1,98 +1,28 @@
<template>
<div class="go-chart-configurations-data" v-if="targetData">
<setting-item-box name="请求方式" :alone="true">
<n-select
v-model:value="targetData.data.requestDataType"
:options="selectOptions"
@on-update="selectHandle"
/>
<n-select v-model:value="targetData.data.requestDataType" :options="selectOptions" />
</setting-item-box>
<n-timeline>
<n-timeline-item type="info" :title="TimelineTitleEnum.MAPPING">
<n-table striped>
<thead>
<tr>
<th v-for="item in tableTitle" :key="item">{{ item }}</th>
</tr>
</thead>
<go-skeleton :repeat="3" :load="tableLoad" style="width: 300px;"></go-skeleton>
<tbody v-show="!tableLoad">
<tr v-for="(item, index) in getDimensionsAndSource" :key="index">
<td>{{ item.field }}</td>
<td>{{ item.mapping }}</td>
<td>
<n-space v-if="item.result === 0">
<n-badge dot type="success"></n-badge>
<n-text></n-text>
</n-space>
<n-space v-else>
<n-badge dot :type="item.result === 1 ? 'success' : 'error'"></n-badge>
<n-text>匹配{{ item.result === 1 ? '成功' : '失败' }}</n-text>
</n-space>
</td>
</tr>
</tbody>
</n-table>
</n-timeline-item>
<n-timeline-item type="success" :title="TimelineTitleEnum.CONTENT">
<n-space vertical>
<n-text depth="3">数据需要符合 ECharts-setdata 规范</n-text>
<n-space class="source-btn-box">
<n-upload
v-model:file-list="uploadFileListRef"
:show-file-list="false"
:customRequest="customRequest"
@before-upload="beforeUpload"
>
<n-space>
<n-button class="sourceBtn-item">
<template #icon>
<n-icon>
<document-add-icon />
</n-icon>
</template>
导入json / txt
</n-button>
</n-space>
</n-upload>
<n-button class="sourceBtn-item" @click="download">
<template #icon>
<n-icon>
<document-download-icon />
</n-icon>
</template>
下载
</n-button>
</n-space>
<n-card>
<n-code :code="getSource" language="json"></n-code>
</n-card>
</n-space>
</n-timeline-item>
</n-timeline>
<!-- 静态 -->
<chart-data-static
v-if="targetData.data.requestDataType === RequestDataTypeEnum.STATIC"
:targetData="targetData"
></chart-data-static>
<!-- 动态 -->
<chart-data-ajax v-else></chart-data-ajax>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import { SettingItemBox } from '@/components/ChartItemSetting/index'
import { RequestDataTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useTargetData } from '../hooks/useTargetData.hook'
import { UploadCustomRequestOptions } from 'naive-ui'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { readFile, downloadFile } from '@/utils'
import { DataResultEnum, TimelineTitleEnum, SelcetOptionsLableEnum, SelectOptionsType } from './index.d'
import { icon } from '@/plugins'
import { ChartDataStatic } from './components/ChartDataStatic/index'
import { ChartDataAjax } from './components/ChartDataAjax/index'
import { SelectOptionsType, SelcetOptionsLableEnum } from './index.d'
const { DocumentAddIcon, DocumentDownloadIcon } = icon.carbon
const uploadFileListRef = ref()
const { targetData } = useTargetData()
const source = ref()
const dimensions = ref()
//
const tableTitle = ['字段', '映射', '状态']
//
const selectOptions: SelectOptionsType[] = [
{
@ -102,111 +32,14 @@ const selectOptions: SelectOptionsType[] = [
{
label: SelcetOptionsLableEnum.AJAX,
value: RequestDataTypeEnum.AJAX,
disabled: true,
}
]
//
const getSource = computed(() => {
return JSON.stringify(source.value)
})
watch(() => targetData.value?.option?.dataset, (newData) => {
if (newData) {
source.value = newData.source
dimensions.value = newData.dimensions
}
}, {
immediate: true
})
//
const matchingHandle = (mapping: string) => {
for (let i = 0; i < source.value.length; i++) {
let res = DataResultEnum.FAILURE
if (source.value[i][mapping] !== undefined) {
return DataResultEnum.SUCCESS
}
return res
}
return DataResultEnum.SUCCESS
}
//
const getDimensionsAndSource = computed(() => {
//
return dimensions.value.map((item: string, index: number) => {
return index === 0 ?
{
//
field: '通用标识',
//
mapping: item,
//
result: DataResultEnum.NULL
} : {
field: `数据项-${index}`,
mapping: item,
result: matchingHandle(item)
}
})
})
//
const tableLoad = computed(() => {
return !getDimensionsAndSource.value || getDimensionsAndSource.value.length === 0
})
//
const selectHandle = () => { }
//@ts-ignore
const beforeUpload = ({ file }) => {
uploadFileListRef.value = []
const type = file.file.type
if (type !== FileTypeEnum.JSON && type !== FileTypeEnum.TXT) {
window['$message'].warning('仅支持上传 【JSON】 格式文件,请重新上传!')
return false
}
return true
}
//
const customRequest = (options: UploadCustomRequestOptions) => {
const { file } = options
nextTick(() => {
if (file.file) {
readFile(file.file).then((fileData: any) => {
targetData.value.option.dataset = JSON.parse(fileData)
});
} else {
window['$message'].error('导入数据失败,请稍后重试或联系管理员!')
}
})
}
//
const download = () => {
try {
window['$message'].success('正在下载文件!')
downloadFile(JSON.stringify(targetData.value?.option?.dataset), undefined, 'json')
} catch (error) {
window['$message'].success('下载失败,数据错误!')
}
}
</script>
<style>
</style>
<style lang="scss" scoped>
@include go("chart-configurations-data") {
@include deep() {
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
}
.source-btn-box {
margin-top: 10px !important;
}
}
</style>