<!-- * Vue Study --> <script lang="ts"> export default { name: 'VUE_STUDY', }; </script> <script setup lang="ts"> import { reactive, onMounted, watch, ref, nextTick, markRaw } from 'vue'; import * as echarts from 'echarts'; import { getType, isEmpty } from 'hcy-tool-test'; // import { useMessage } from 'src/common/hooks'; import PROVICE from './provice'; import { ChartOption, Series_A, Series_B, Series_D } from './config'; import DateDetail from './element/DateDetail.vue'; import ImageScale from './element/ImageScale.vue'; import CropperImg from './element/CropperImg.vue'; import InsertCoin from './element/InsertCoin.vue'; // const { info } = useMessage(); const citySelectRef = ref<any>(null); const regionSelectRef = ref<any>(null); const chartRef = ref<any>(null); const CropperImgRef = ref<any>(null); const InsertCoinRef = ref<any>(null); const showContent = ref(false); const showContent2 = ref(false); const legendState = reactive<any>({ A: { show: true }, B: { show: false }, D: { show: true }, }); const state = reactive({ province: null as any, provinceOpt: [] as any[], city: null as any, cityOpt: [] as any[], region: null as any, regionOpt: [] as any[], myChart: null as any, uploadImgUrl: 'https://w.wallhaven.cc/full/kx/wallhaven-kx98xd.jpg', insertCoin: false, // 投币 }); watch( () => state.province, (newVal) => { state.city = null; state.cityOpt = newVal?.city || []; if (state.cityOpt.length > 0) { nextTick(() => { citySelectRef.value?.showPopup(); }); } } ); watch( () => state.city, (newVal) => { state.region = null; state.regionOpt = newVal?.districtAndCounty || []; if (state.regionOpt.length > 0) { nextTick(() => { regionSelectRef.value?.showPopup(); }); } } ); onMounted(() => { // const mytool = require('hcy-tool-test'); // const mytool = require('./test-utils/index'); const type = getType(123); console.log(type); const isE = isEmpty(0); console.log(isE); handleData(); setChart(); }); function handleData() { PROVICE.map((item) => { state.provinceOpt.push(item); }); } function setChart() { let option: { series: any[] } = ChartOption; let series = []; if (legendState.A.show) { series.push(...Series_A); } if (legendState.B.show) { series.push(...Series_B); } if (legendState.D.show) { series.push(...Series_D); } option.series = series; if (state.myChart?.id) { // state.myChart.dispose(); state.myChart.setOption(option, true); } else { state.myChart = markRaw(echarts.init(chartRef.value)); state.myChart.setOption(option); } } function showBox() { showContent.value = !showContent.value; } function showDate() { showContent2.value = !showContent2.value; } // function clickChartBox(e: any) { // e.stopPropagation(); // 阻止冒泡 // } function clickLegend(type: string) { legendState[type].show = !legendState[type].show; setChart(); } function openCropperModel() { CropperImgRef.value.openModel(); } function uploadImgOk(data: any) { state.uploadImgUrl = data; } function insertCoinClick() { InsertCoinRef.value.openModel(); } </script> <template> <div> <div class="q-pa-md"> <div class="item-box"> <div class="item"> <div>省</div> <q-select filled dense v-model="state.province" :options="state.provinceOpt" option-label="name" option-value="name" /> </div> <div class="item"> <div>市</div> <q-select ref="citySelectRef" filled dense v-model="state.city" :options="state.cityOpt" option-label="name" option-value="name" /> </div> <div class="item"> <div>区/县</div> <q-select ref="regionSelectRef" filled dense v-model="state.region" :options="state.regionOpt" /> </div> </div> </div> <div class="aniamte-box q-pa-md relative-position"> <div :class="['square', showContent ? 'square-show' : 'square-hide']"> <div class="title-box cursor-pointer" @click="showBox"> <div class="title-text">图表</div> <div class="title-action"> <div :class="[ 'icon-box', showContent ? 'icon-box-show' : 'icon-box-hide', ]" > <q-icon name="expand_more" /> </div> </div> </div> <div class="chart-box" ref="chartRef"></div> <div class="legend-box"> <div :class="[ 'legend-box-item', legendState.A.show ? 'opacity-1' : 'opacity-dis-4', ]" @click="clickLegend('A')" > <div class="legend-icon legend-icon-A"></div> <div class="legend-title">A</div> </div> <div :class="[ 'legend-box-item', legendState.B.show ? 'opacity-1' : 'opacity-dis-4', ]" @click="clickLegend('B')" > <div class="legend-icon legend-icon-B"></div> <div class="legend-title">B/C</div> </div> <div :class="[ 'legend-box-item', legendState.D.show ? 'opacity-1' : 'opacity-dis-4', ]" @click="clickLegend('D')" > <div class="legend-icon legend-icon-D"></div> <div class="legend-title">D/E</div> </div> </div> </div> </div> <div class="row"> <div class="aniamte-box q-pa-md relative-position" style="width: 400px"> <div :class="['square', showContent2 ? 'square-show-date' : 'square-hide']" > <div class="title-box cursor-pointer" @click="showDate"> <div class="title-text">日期</div> <div class="title-action"> <div :class="[ 'icon-box', showContent2 ? 'icon-box-show' : 'icon-box-hide', ]" > <q-icon name="expand_more" /> </div> </div> </div> <div class="chart-box" style="height: 620px"> <DateDetail /> </div> </div> </div> <ImageScale /> <div class="upload-img-action q-ma-md"> <div class="upload-img-content"> <q-btn color="primary" label="上传头像" @click="openCropperModel" /> <div class="upload-img-box"> <img :src="state.uploadImgUrl" alt="图片" v-if="state.uploadImgUrl" /> </div> </div> </div> <div class="q-ma-md"> <q-btn round flat :color="state.insertCoin ? 'primary' : 'grey-7'" icon="fa-brands fa-ello" @click="insertCoinClick" /> </div> </div> </div> <!-- 上传头像/修改头像 弹框 --> <CropperImg ref="CropperImgRef" @onOk="uploadImgOk" /> <!-- 投币弹框 --> <InsertCoin ref="InsertCoinRef" /> </template> <style lang="scss" scoped> .opacity-1 { opacity: 1; } .opacity-dis-4 { opacity: 0.4; } .item-box { display: flex; column-gap: 16px; } .item { width: 300px; } .aniamte-box { } .title-text { font-size: 16px; font-weight: bold; letter-spacing: 0.1em; color: rgb(75, 75, 75); } .title-action { } .icon-box { transition: all 0.4s cubic-bezier(0.33, 1, 0.68, 1); > i { font-size: 24px; color: rgb(150, 150, 150); } } .icon-box-hide { transform: rotate(0deg); } .icon-box-show { transform: rotate(180deg); } .square { box-sizing: border-box; width: 100%; position: relative; left: 0; overflow: hidden; transition: all 0.4s cubic-bezier(0.33, 1, 0.68, 1); .title-box { background-color: rgba(180, 180, 180, 0.2); height: 40px; padding: 0 8px; display: flex; justify-content: space-between; align-items: center; } .chart-box { box-sizing: border-box; border-left: 1px solid rgba(180, 180, 180, 0.3); border-right: 1px solid rgba(180, 180, 180, 0.3); border-bottom: 1px solid rgba(180, 180, 180, 0.3); border-bottom-left-radius: 12px; border-bottom-right-radius: 12px; width: 100%; height: 300px; background-color: #fff; } .legend-box { position: absolute; width: 80px; // background-color: pink; top: 160px; right: 0; .legend-box-item { width: 100%; box-sizing: border-box; min-height: 24px; // background-color: aqua; display: flex; align-items: center; &:hover { cursor: pointer; } .legend-icon { width: 28px; height: 24px; flex-shrink: 0; // background-color: red; position: relative; margin-right: 8px; &::before { position: absolute; content: ''; width: 100%; top: 10px; left: 0; } } .legend-icon-A { &::before { border-top: 2px solid #f2317f; } &::after { position: absolute; content: ''; width: 8px; height: 8px; border-radius: 50%; border: 2px solid #f2317f; background-color: #fff; top: 7px; left: 10px; } } .legend-icon-B { &::before { border-top: 2px dashed #a696c8; } } .legend-icon-D { &::before { border-top: 2px solid #8bc24c; } } .legend-title { font-size: 12px; color: rgb(94, 94, 94); } } } } .square-hide { height: 40px; border-radius: 2px; } .square-show { height: 340px; border-radius: 12px; } .square-show-date { height: 660px; border-radius: 12px; } .upload-img-content { display: flex; align-items: center; column-gap: 5px; } .upload-img-box { display: flex; align-items: center; justify-content: center; > img { width: 42px; height: 42px; object-fit: contain; border: 1px solid rgba(180, 180, 180, 0.3); border-radius: 50%; } } </style>