li.shaoyi 3 jaren geleden
bovenliggende
commit
50646344d6

+ 2 - 2
public/config/appconfig.json

@@ -1,5 +1,5 @@
 {
-  "version": "1.0.6",
-  "versionCode": "100006",
+  "version": "1.0.7",
+  "versionCode": "100007",
   "apiUrl": "http://218.17.158.45:16021/cfg?key=test_thj"
 }

+ 20 - 1
src/business/goods/index.ts

@@ -1,5 +1,6 @@
-import { shallowRef } from 'vue'
+import { shallowRef, reactive } from 'vue'
 import { useDataTable } from '@/hooks/datatable'
+import { EchartsDataset } from '@/hooks/echarts/line/interface'
 import { queryTHJWrstandard, queryTHJWrstandardDetail, addUserFavoriteGoods, removeUserFavoriteGoods, queryTHJProduct, queryMarketRun, queryTHJTradeData, querySpotGoodsPrice } from '@/services/api/goods'
 import { useLoginStore } from '@/stores'
 
@@ -39,21 +40,39 @@ export function useWrstandardList() {
 
 // 采购详细
 export function useWrstandardDetails(wrstandardid: number) {
+    const loading = shallowRef(false)
     const details = shallowRef<Partial<Model.THJWrstandardDetailRsp>>({})
 
+    // 图表数据
+    const chartData = reactive<EchartsDataset['line']['source']>({
+        price: [],
+        date: []
+    })
+
     const getWrstandardDetails = () => {
+        loading.value = true
         return queryTHJWrstandardDetail({
             data: {
                 wrstandardid,
             },
             success: (res) => {
                 details.value = res.data
+
+                res.data.spotgoodspricelogs.forEach(({ spotgoodsprice, tradedate }) => {
+                    chartData.price.push(spotgoodsprice)
+                    chartData.date.push(tradedate)
+                })
+            },
+            complete: () => {
+                loading.value = false
             }
         })
     }
 
     return {
+        loading,
         details,
+        chartData,
         getWrstandardDetails,
     }
 }

+ 1 - 1
src/hooks/echarts/candlestick/index.ts

@@ -5,7 +5,7 @@ import { queryHistoryDatas } from '@/services/api/quote'
 import { useFuturesStore } from '@/stores'
 import { useDataset } from './dataset'
 import { useOptions } from './options'
-import moment from 'moment';
+import moment from 'moment'
 
 export function useCandlestickChart(goodscode: string) {
     const { getQuoteDayInfoByCode } = useFuturesStore()

+ 27 - 0
src/hooks/echarts/line/dataset.ts

@@ -0,0 +1,27 @@
+import { reactive } from 'vue'
+import { EchartsDataset } from './interface'
+
+export function useDataset() {
+    const dataset = reactive<EchartsDataset>({
+        line: {
+            dimensions: ['date', 'price'],
+            source: {
+                date: [],
+                price: [],
+            },
+        }
+    })
+
+    // 清空数据
+    const clearData = () => {
+        dataset.line.source = {
+            date: [],
+            price: [],
+        };
+    }
+
+    return {
+        dataset,
+        clearData,
+    }
+}

+ 22 - 0
src/hooks/echarts/line/index.ts

@@ -0,0 +1,22 @@
+import { useDataset } from './dataset'
+import { useOptions } from './options'
+import { EchartsDataset } from './interface'
+
+export function useLineChart() {
+    const { dataset, clearData } = useDataset()
+    const { options, initOptions } = useOptions(dataset)
+
+    /**
+     * 初始化数据
+     */
+    const initData = (data: EchartsDataset['line']['source']) => {
+        clearData()
+        dataset.line.source = data
+    }
+
+    return {
+        options,
+        initData,
+        initOptions,
+    }
+}

+ 43 - 0
src/hooks/echarts/line/interface.ts

@@ -0,0 +1,43 @@
+
+import { ECOption } from '@/components/base/echarts/core'
+
+/**
+ * 图表数据集
+ */
+export interface EchartsDataset {
+    line: Dataset;
+}
+
+/**
+ * 图表数据源
+ */
+export interface Dataset {
+    dimensions: (keyof Line)[];
+    source: Line;
+}
+
+/**
+ * 折线
+ */
+export type Line = {
+    date: string[], // xAxis数据,必须是第一个属性
+    price: number[], // 价格
+}
+
+/**
+ * 图表配置项
+ */
+export interface EchartsOptions {
+    colors: Colors;
+    line: ECOption;
+}
+
+/**
+ * 图表颜色
+ */
+export interface Colors {
+    upColor: string;
+    downColor: string;
+    xAxisLineColor: string;
+    yAxisLineColor: string;
+}

+ 93 - 0
src/hooks/echarts/line/options.ts

@@ -0,0 +1,93 @@
+import { reactive, watch } from 'vue'
+import { timerInterceptor } from '@/utils/timer'
+import { useThemeStore } from '@/stores'
+import { EchartsDataset, EchartsOptions, Colors } from './interface'
+
+const { appTheme } = useThemeStore();
+
+function getColors() {
+    // 默认主题色配置
+    const defaultColors: Colors = {
+        upColor: '#ff3333',
+        downColor: '#0aab62',
+        xAxisLineColor: 'rgba(128,128,128,.1)',
+        yAxisLineColor: 'rgba(128,128,128,.1)',
+    }
+
+    const colors = {
+        default: defaultColors,
+        dark: defaultColors,
+        light: {
+            ...defaultColors,
+            downColor: '#00A843',
+        }
+    }
+
+    return colors[appTheme.value];
+}
+
+export function useOptions(dataset: EchartsDataset) {
+    // 图表配置项
+    const options = reactive<EchartsOptions>({
+        colors: getColors(),
+        line: {},
+    })
+
+    const initOptions = () => {
+        const { xAxisLineColor } = options.colors
+        const { line } = dataset
+
+        options.line = {
+            dataset: line,
+            grid: {
+                left: '16px',
+                right: '16px',
+                top: '16px',
+                bottom: '16px',
+                containLabel: true,
+            },
+            xAxis: {
+                type: 'category',
+            },
+            yAxis: {
+                splitLine: {
+                    lineStyle: {
+                        // 坐标分隔线颜色
+                        color: xAxisLineColor,
+                    },
+                },
+            },
+            // series 中不指定 yAxisId 或 yAxisIndex 默认关联 yAxis 第一个配置,xAxis 配置同理
+            series: [
+                {
+                    name: '分时',
+                    type: 'line',
+                    smooth: true,
+                    symbol: 'none', //中时有小圆点
+                },
+            ],
+        }
+    }
+
+    // 动态更新数据
+    const updateOptions = timerInterceptor.setThrottle(() => {
+        const { line } = dataset;
+        options.line = {
+            dataset: {
+                source: line.source,
+            },
+        }
+    }, 1000)
+
+    // 监听主题变化
+    watch(appTheme, () => {
+        options.colors = getColors();
+        initOptions();
+    })
+
+    return {
+        options,
+        initOptions,
+        updateOptions,
+    }
+}

+ 15 - 17
src/packages/mobile/components/base/select/index.vue

@@ -1,21 +1,19 @@
 <template>
-    <div class="app-select">
-        <Field ref="fieldRef" :name="name" :rules="rules" @click="showPicker = true" :is-link="isLink">
-            <template #label>
-                <slot name="label">
-                    {{ label }}
-                </slot>
-            </template>
-            <template #input>
-                <slot name="input" :item="props.options[selectedIndex]">
-                    <input :value="columnLabel" :placeholder="placeholder" readonly />
-                </slot>
-            </template>
-        </Field>
-        <Popup v-model:show="showPicker" position="bottom" teleport="body">
-            <Picker :columns="columns" @cancel="onCancel" @confirm="onConfirm" />
-        </Popup>
-    </div>
+    <Field class="app-select" ref="fieldRef" :name="name" :rules="rules" @click="showPicker = true" :is-link="isLink">
+        <template #label>
+            <slot name="label">
+                {{ label }}
+            </slot>
+        </template>
+        <template #input>
+            <slot name="input" :item="props.options[selectedIndex]">
+                <input :value="columnLabel" :placeholder="placeholder" readonly />
+            </slot>
+        </template>
+    </Field>
+    <Popup v-model:show="showPicker" position="bottom" teleport="body">
+        <Picker :columns="columns" @cancel="onCancel" @confirm="onConfirm" />
+    </Popup>
 </template>
 
 <script lang="ts" setup>

+ 48 - 0
src/packages/mobile/components/modules/echarts-line/index.vue

@@ -0,0 +1,48 @@
+<template>
+    <div class="app-echats-line">
+        <template v-if="loading">
+            <div class="app-echats-line__tip">正在加载...</div>
+        </template>
+        <template v-else-if="isEmpty">
+            <div class="app-echats-line__tip">暂无数据</div>
+        </template>
+        <template v-else>
+            <app-echarts :option="options.line" @ready="initOptions" />
+        </template>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, PropType, watch } from 'vue'
+import { useLineChart } from '@/hooks/echarts/line'
+import { EchartsDataset } from '@/hooks/echarts/line/interface'
+import AppEcharts from '@/components/base/echarts/index.vue'
+
+const props = defineProps({
+    loading: {
+        type: Boolean,
+        default: false
+    },
+    dataList: {
+        type: Object as PropType<EchartsDataset['line']['source']>,
+        required: true
+    },
+})
+
+const { options, initData, initOptions } = useLineChart()
+const isEmpty = shallowRef(false)
+
+watch(() => props.loading, (status) => {
+    if (status) {
+        isEmpty.value = false
+    } else {
+        if (props.dataList.price.length) {
+            initData(props.dataList)
+        } else {
+            isEmpty.value = true
+        }
+    }
+}, {
+    immediate: true
+})
+</script>

+ 29 - 0
src/packages/mobile/views/goods/details/index.less

@@ -46,5 +46,34 @@
 
     &__content {
         background-color: #fff;
+
+        .van-divider {
+            font-size  : .36rem;
+            font-weight: bold;
+            color      : #333;
+        }
+
+        .submitbar {
+            padding: .32rem;
+        }
+
+        .titlebar {
+            display        : flex;
+            align-items    : center;
+            justify-content: center;
+            gap            : .16rem;
+
+            span {
+                &:first-child {
+                    font-size: .32rem;
+                }
+
+                &:last-child {
+                    font-size  : .4rem;
+                    font-weight: bold;
+                    color      : #E84F42;
+                }
+            }
+        }
     }
 }

+ 8 - 6
src/packages/mobile/views/goods/details/index.vue

@@ -54,19 +54,20 @@
             </CellGroup>
         </Form>
         <div class="goods-details__content">
-            <div class="">
+            <div class="submitbar">
                 <Button type="primary" @click="formRef?.submit" round block>采购下单</Button>
             </div>
-            <div class="" v-if="selectedDate">
+            <div class="titlebar" v-if="selectedDate">
                 <span>参考价(元/{{ getGoodsUnitName(details.goodsinfo?.unitid) }})</span>
                 <span>{{ selectedDate.unitprice }}</span>
             </div>
             <Divider>历史价格走势</Divider>
-            <div class="">
-                走势图
+            <div class="chart">
+                <component :is="componentMap.get('chart')" :loading="loading" :data-list="chartData"
+                    style="height:200px" />
             </div>
             <Divider>商品详情</Divider>
-            <div class="">
+            <div class="gallery">
                 <template v-for="(url, index) in goodsImages" :key="index">
                     <img :src="url" alt="" />
                 </template>
@@ -92,6 +93,7 @@ import Long from 'long'
 
 const componentMap = new Map<string, unknown>([
     ['address', defineAsyncComponent(() => import('./components/address/index.vue'))],
+    ['chart', defineAsyncComponent(() => import('@mobile/components/modules/echarts-line/index.vue'))],
 ])
 
 const { componentRef, componentId, openComponent, closeComponent, closeComponentEach } = useComponent()
@@ -100,7 +102,7 @@ const { getQueryStringToNumber, beforeRouteLeave } = useNavigation()
 const wrstandardid = getQueryStringToNumber('wrstandardid')
 const formRef = shallowRef<FormInstance>()
 
-const { details, getWrstandardDetails } = useWrstandardDetails(wrstandardid)
+const { loading, details, chartData, getWrstandardDetails } = useWrstandardDetails(wrstandardid)
 const { formData, formSubmit } = usePurchaseOrderDesting()
 
 // 交割日期列表

+ 1 - 1
src/types/model/goods.d.ts

@@ -124,7 +124,7 @@ declare namespace Model {
             discountamount: number; // 优惠金额(每吨)
             presaleapplyid: string; // 预售申请ID(184+Unix秒时间戳(10位)+xxxxxx)
         }[];
-        spotGoodspricelogs: {
+        spotgoodspricelogs: {
             spotgoodsprice: number; // 现货价格
             tradedate: string; // 交易日(yyyyMMdd)
         }[];