|
@@ -0,0 +1,365 @@
|
|
|
+import { defineComponent, onMounted, reactive, ref, nextTick } from 'vue';
|
|
|
+import styles from './index.module.less';
|
|
|
+import { List, Popup, DatePicker, Popover, Field, Picker, } from 'vant';
|
|
|
+import request from '@/helpers/request';
|
|
|
+import { useRoute, useRouter } from 'vue-router';
|
|
|
+import OEmpty from '@/components/m-empty';
|
|
|
+import MWxTip from '@/components/m-wx-tip';
|
|
|
+import OSearch from '@/components/m-search';
|
|
|
+import positionIcon from './images/position_icon.png';
|
|
|
+import scIcon1 from './images/sc_icon1.png';
|
|
|
+import scIcon2 from './images/sc_icon2.png';
|
|
|
+import scIcon3 from './images/sc_icon3.png';
|
|
|
+import schoolIcon from './images/school_icon.png';
|
|
|
+import searchIcon from './images/search_icon.png';
|
|
|
+import searchBtn from './images/search_btn.png';
|
|
|
+import totalBoxBg from './images/total_box_icon.png';
|
|
|
+import { drawCircle } from './drawGraph'
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'questionnaire-statistics-new',
|
|
|
+ setup() {
|
|
|
+ const route = useRoute();
|
|
|
+ const router = useRouter();
|
|
|
+ const tabName = ref('all');
|
|
|
+ const forms = reactive({
|
|
|
+ schoolName: '',
|
|
|
+ id: route.query.id,
|
|
|
+ // id: '1687275949971763202',
|
|
|
+ yearStatus: false,
|
|
|
+ schoolId: null,
|
|
|
+ classList: [] as any,
|
|
|
+ page: 1,
|
|
|
+ rows: 20,
|
|
|
+ isClick: false,
|
|
|
+ tenantId: route.query.id,
|
|
|
+ areaList: [] as any,
|
|
|
+ areaColumns: [] as any,
|
|
|
+ areaStatus: false,
|
|
|
+ areaPopupShow: false,
|
|
|
+ areaOptionIndex: [] as any,
|
|
|
+ currentArea: null as any, // 当前的区域
|
|
|
+ currentAreaInfo: null as any,
|
|
|
+ schoolList: [] as any,
|
|
|
+ totalInfo: {} as any,
|
|
|
+ sortType: 'DESC' as any, // 排序方式,ASC(升序)/DESC(降序)
|
|
|
+ sortField: 'totalNum', // totalNum: 总人数,supportNum:支持人数,supportRate:支持率
|
|
|
+ areaIdx: 0 as any,
|
|
|
+ });
|
|
|
+
|
|
|
+ const refreshing = ref(false);
|
|
|
+ const loading = ref(true);
|
|
|
+ const finished = ref(false);
|
|
|
+ const showContact = ref(false);
|
|
|
+ const list = ref([]);
|
|
|
+
|
|
|
+ const queryArea = async () => {
|
|
|
+ try {
|
|
|
+ const { data } = await request.get(
|
|
|
+ `/edu-app/open/tenantInfo/getArea?tenantId=${forms.tenantId}`, {
|
|
|
+ hideLoading: false,
|
|
|
+ }
|
|
|
+ );
|
|
|
+ forms.areaList = data || []
|
|
|
+ data.forEach((item: any, index: number) => {
|
|
|
+ const {provinceName='',cityName='',regionName=''} = item
|
|
|
+ forms.areaColumns.push({
|
|
|
+ text: provinceName + ' ' + cityName + ' ' + (regionName ? regionName : ''),
|
|
|
+ value: index
|
|
|
+ })
|
|
|
+ })
|
|
|
+ forms.currentArea = forms.areaColumns.length ? forms.areaColumns[forms.areaIdx].text : ''
|
|
|
+ forms.currentAreaInfo = forms.areaList.length ? forms.areaList[forms.areaIdx] : null;
|
|
|
+ } catch (error) {
|
|
|
+
|
|
|
+ }
|
|
|
+ await queryInfo();
|
|
|
+ await getList();
|
|
|
+ }
|
|
|
+
|
|
|
+ const queryInfo = async () => {
|
|
|
+ try {
|
|
|
+ const { provinceCode='',cityCode='',regionCode='' } = forms.currentAreaInfo
|
|
|
+ const res = await request.post(
|
|
|
+ '/edu-app/open/schoolMeetingQuestion/areaSummarySum',
|
|
|
+ {
|
|
|
+ data: {
|
|
|
+ tenantId: forms.tenantId,
|
|
|
+ schoolName: forms.schoolName,
|
|
|
+ provinceCode,
|
|
|
+ cityCode,
|
|
|
+ districtCode: regionCode,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ forms.totalInfo = res.data|| {}
|
|
|
+ } catch (error) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const getList = async () => {
|
|
|
+ try {
|
|
|
+ const { provinceCode='',cityCode='',regionCode='' } = forms.currentAreaInfo
|
|
|
+ const res = await request.post(
|
|
|
+ '/edu-app/open/schoolMeetingQuestion/areaSummary',
|
|
|
+ {
|
|
|
+ data: {
|
|
|
+ tenantId: forms.tenantId,
|
|
|
+ schoolName: forms.schoolName,
|
|
|
+ provinceCode,
|
|
|
+ cityCode,
|
|
|
+ districtCode: regionCode,
|
|
|
+ sortType: forms.sortType,
|
|
|
+ sortField: forms.sortField,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ forms.schoolList = res?.data || []
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ } finally {
|
|
|
+ //
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ const state = reactive({
|
|
|
+ saveLoading: false,
|
|
|
+ image: null as any,
|
|
|
+ shareLoading: false
|
|
|
+ });
|
|
|
+
|
|
|
+ const skipDetail = (id: any) => {
|
|
|
+ sessionStorage.setItem('areaIdx', forms.areaIdx)
|
|
|
+ router.push({
|
|
|
+ path: '/statistics-detail-new',
|
|
|
+ query: {
|
|
|
+ id,
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const filterList = (val: string) => {
|
|
|
+ if (forms.sortField !== val) {
|
|
|
+ forms.sortType = 'DESC'
|
|
|
+ } else {
|
|
|
+ forms.sortType = forms.sortType === 'DESC' ? 'ASC' : 'DESC'
|
|
|
+ }
|
|
|
+ forms.sortField = val
|
|
|
+ getList()
|
|
|
+ }
|
|
|
+
|
|
|
+ const formatNumberWithComma = (num: number | string) => {
|
|
|
+ // 将数字转换为字符串,去掉小数点后面的部分
|
|
|
+ let [integer, decimal] = num.toString().split('.');
|
|
|
+
|
|
|
+ // 使用正则表达式添加千分位分隔符
|
|
|
+ integer = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
|
+
|
|
|
+ // 如果有小数部分,则保留小数部分
|
|
|
+ return decimal ? `${integer}.${decimal}` : integer;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ // console.log('刷新页面')
|
|
|
+ forms.areaIdx = sessionStorage.getItem('areaIdx') || 0;
|
|
|
+ await queryArea();
|
|
|
+ nextTick(() => {
|
|
|
+ let percentage = 0;
|
|
|
+ const interval = setInterval(() => {
|
|
|
+ if (percentage <= forms.totalInfo.supportRate) {
|
|
|
+ drawCircle('circle1', 1, percentage)
|
|
|
+ }
|
|
|
+ if (percentage <= forms.totalInfo.participationRate) {
|
|
|
+ drawCircle('circle2', 2, percentage)
|
|
|
+ }
|
|
|
+ percentage += 1; // 每次增加1%
|
|
|
+ if (percentage > Math.max(forms.totalInfo.supportRate, forms.totalInfo.participationRate)) {
|
|
|
+ clearInterval(interval); // 停止定时器
|
|
|
+ }
|
|
|
+ }, 25); // 每25ms更新一次
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ return () => (
|
|
|
+ <div class={[styles.statisBody]}>
|
|
|
+ {
|
|
|
+ forms.areaColumns.length > 1 &&
|
|
|
+ <div class={[styles.spColumn, forms.areaStatus && styles.openVal]} onClick={() => {
|
|
|
+ forms.areaOptionIndex = [Number(forms.areaIdx)]
|
|
|
+ forms.areaStatus = true
|
|
|
+ }}>
|
|
|
+ <img src={positionIcon} />
|
|
|
+ <p>{forms.currentArea}</p>
|
|
|
+ <i></i>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+
|
|
|
+ {/** 参与学校统计 */}
|
|
|
+ <div class={styles.sTotal}>
|
|
|
+ <div class={styles.stOne}>
|
|
|
+ <div class={styles.soTitle}><span class={styles.sOrange}>{formatNumberWithComma(forms.totalInfo.schoolNum||0)}</span><i>所</i></div>
|
|
|
+ <p class={styles.soDesc}><img src={schoolIcon} />参与学校</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.stOne}>
|
|
|
+ <div class={styles.soTitle}><span class={styles.sRed}>{formatNumberWithComma(forms.totalInfo.totalNum||0)}</span><i>人</i></div>
|
|
|
+ <p class={styles.soDesc}><img src={scIcon1} />参与调查</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/** 圆环统计 */}
|
|
|
+ <div class={styles.sRing}>
|
|
|
+ <div class={[styles.srItem,styles.srItemOne]}>
|
|
|
+ <div class={styles.siLeft}>
|
|
|
+ <canvas id="circle1" width="70" height="70"></canvas>
|
|
|
+ <p>支持率</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.siRight}>
|
|
|
+ <div><span class={styles.sBlue}>{formatNumberWithComma(forms.totalInfo.supportNum||0)}</span><i>人</i></div>
|
|
|
+ <p>支持开展</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class={styles.srItem}>
|
|
|
+ <div class={styles.siLeft}>
|
|
|
+ <canvas id="circle2" width="70" height="70"></canvas>
|
|
|
+ <p>参加率</p>
|
|
|
+ </div>
|
|
|
+ <div class={styles.siRight}>
|
|
|
+ <div><span class={styles.sGreen}>{formatNumberWithComma(forms.totalInfo.participationNum||0)}</span><i>人</i></div>
|
|
|
+ <p>报名参加</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/** 搜索栏 */}
|
|
|
+ <div class={styles.searechInfo}>
|
|
|
+ <img src={searchIcon} class={styles.searchIcon} />
|
|
|
+ <Field
|
|
|
+ clearable={true}
|
|
|
+ inputAlign="left"
|
|
|
+ placeholder="请输入学校名称"
|
|
|
+ autocomplete="off"
|
|
|
+ center
|
|
|
+ maxlength={30}
|
|
|
+ v-model={forms.schoolName}
|
|
|
+ onUpdate:modelValue={(val: any) => {
|
|
|
+ // 输入框内容变化时触发
|
|
|
+ // console.log('搜索内容变化',val)
|
|
|
+ forms.schoolName = val
|
|
|
+ getList()
|
|
|
+ }}>
|
|
|
+ </Field>
|
|
|
+ <img src={searchBtn} class={styles.searchBtn} onClick={getList} />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/** 排序栏 */}
|
|
|
+ <ul class={styles.sortColumn}>
|
|
|
+ <li class={forms.sortField === 'totalNum' && styles.sortActive} onClick={() => filterList('totalNum')}>
|
|
|
+ <span>参与调查人数</span>
|
|
|
+ <i class={[(forms.sortField === 'totalNum' && forms.sortType === 'DESC') && styles.actDown, (forms.sortField === 'totalNum' && forms.sortType === 'ASC') && styles.actUp]}></i>
|
|
|
+ </li>
|
|
|
+ <li class={forms.sortField === 'supportNum' && styles.sortActive} onClick={() => filterList('supportNum')}>
|
|
|
+ <span>支持人数</span>
|
|
|
+ <i class={[(forms.sortField === 'supportNum' && forms.sortType === 'DESC') && styles.actDown, (forms.sortField === 'supportNum' && forms.sortType === 'ASC') && styles.actUp]}></i>
|
|
|
+ </li>
|
|
|
+ <li class={forms.sortField === 'supportRate' && styles.sortActive} onClick={() => filterList('supportRate')}>
|
|
|
+ <span>支持率</span>
|
|
|
+ <i class={[(forms.sortField === 'supportRate' && forms.sortType === 'DESC') && styles.actDown, (forms.sortField === 'supportRate' && forms.sortType === 'ASC') && styles.actUp]}></i>
|
|
|
+ </li>
|
|
|
+ <li class={forms.sortField === 'participationNum' && styles.sortActive} onClick={() => filterList('participationNum')}>
|
|
|
+ <span>参加人数</span>
|
|
|
+ <i class={[(forms.sortField === 'participationNum' && forms.sortType === 'DESC') && styles.actDown, (forms.sortField === 'participationNum' && forms.sortType === 'ASC') && styles.actUp]}></i>
|
|
|
+ </li>
|
|
|
+ <li class={forms.sortField === 'participationRate' && styles.sortActive} onClick={() => filterList('participationRate')}>
|
|
|
+ <span>参加率</span>
|
|
|
+ <i class={[(forms.sortField === 'participationRate' && forms.sortType === 'DESC') && styles.actDown, (forms.sortField === 'participationRate' && forms.sortType === 'ASC') && styles.actUp]}></i>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ {/** 学校列表 */}
|
|
|
+ {
|
|
|
+ forms.schoolList.length ?
|
|
|
+ <div class={styles.scList}>
|
|
|
+ {forms.schoolList.map((item: any) => (
|
|
|
+ <div class={styles.sItem} onClick={() => skipDetail(item.schoolAreaId)}>
|
|
|
+ <div class={styles.itemTile}>
|
|
|
+ <img src={schoolIcon} />
|
|
|
+ <p>{item.schoolName}</p>
|
|
|
+ <i></i>
|
|
|
+ </div>
|
|
|
+ <div class={[styles.itemDesc]}><span class={styles.sRed}>{formatNumberWithComma(item.totalNum || 0)}</span> 人参与调查</div>
|
|
|
+ <ul class={styles.itemContent}>
|
|
|
+ <li>
|
|
|
+ <div class={styles.icTop}>
|
|
|
+ <span class={styles.sRed}>{formatNumberWithComma(item.supportNum || 0)}</span><i>人</i>
|
|
|
+ </div>
|
|
|
+ <p>支持开展</p>
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <div class={styles.icTop}>
|
|
|
+ <span class={styles.sBlue}>{Number(item.supportRate || 0).toFixed(2)}%</span>
|
|
|
+ </div>
|
|
|
+ <p>支持率</p>
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <div class={styles.icTop}>
|
|
|
+ <span class={styles.sGreen}>{formatNumberWithComma(item.participationNum || 0)}</span><i>人</i>
|
|
|
+ </div>
|
|
|
+ <p>报名参加</p>
|
|
|
+ </li>
|
|
|
+ <li>
|
|
|
+ <div class={styles.icTop}>
|
|
|
+ <span class={styles.sGreen}>{Number(item.participationRate || 0).toFixed(2)}%</span>
|
|
|
+ </div>
|
|
|
+ <p>参加率</p>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div> :
|
|
|
+ <OEmpty description="暂无内容" class={styles.emptyC} />
|
|
|
+ }
|
|
|
+ {/* 区域 */}
|
|
|
+ <Popup
|
|
|
+ v-model:show={forms.areaStatus}
|
|
|
+ position="bottom"
|
|
|
+ round
|
|
|
+ safeAreaInsetBottom
|
|
|
+ lazyRender={false}
|
|
|
+ class={'popupBottomSearch'}
|
|
|
+ onOpen={() => {
|
|
|
+ forms.areaPopupShow = true;
|
|
|
+ }}
|
|
|
+ onClosed={() => {
|
|
|
+ forms.areaPopupShow = false;
|
|
|
+ }}>
|
|
|
+ {forms.areaPopupShow && (
|
|
|
+ <Picker
|
|
|
+ showToolbar
|
|
|
+ v-model={forms.areaOptionIndex}
|
|
|
+ columns={forms.areaColumns}
|
|
|
+ onCancel={() => (forms.areaStatus = false)}
|
|
|
+ onConfirm={(val: any) => {
|
|
|
+ // forms.gradeAndClassIndex = [val.selectedOptions[0].value, val.selectedOptions[1].value]
|
|
|
+ // forms.currentArea = val.selectedOptions[0].text;
|
|
|
+ // forms.currentClass = val.selectedOptions[1].text;
|
|
|
+ forms.currentArea = val.selectedOptions[0].text
|
|
|
+ forms.areaOptionIndex = [val.selectedOptions[0].value]
|
|
|
+ forms.areaIdx = val.selectedOptions[0].value
|
|
|
+ forms.areaStatus = false;
|
|
|
+ forms.currentAreaInfo = forms.areaList[val.selectedOptions[0].value]
|
|
|
+ queryInfo()
|
|
|
+ getList()
|
|
|
+ console.log('选择1111',val,forms.areaOptionIndex)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ {/* <MWxTip /> */}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|