| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- <template>
- <view class="initial screenBody" :class="{ 'border_bottom': showScreen }">
- <view class="screenBox" :class="{ 'padding_0': !isShowTime }">
- <view v-if="isShowTime" class="dataBox displayFlexRow" :class="type">
- <view
- class="screen_time_item"
- :class="{ 'backgroundCustom': item.check && type }"
- v-for="(item, index) in screenTime"
- :key="index"
- @click="choiceTime(index)"
- >
- <text :class="{ 'font_weight': item.check }">{{ item.label }}</text>
- <view :class="{ 'backgroundCustom': item.check }"></view>
- </view>
- </view>
- <view v-if="isShowScreen" class="screenBtn" :class="{ 'width_100p': !isShowTime }" @click="toggleScreen">
- <view>
- <text :class="{ 'colorCustom': showScreen }">{{ localScreen.btnName ? localScreen.btnName : '筛选' }}</text>
- </view>
- <image class="screenIcon" v-if="!showScreen" :src="iconUrl.icon_bottom"></image>
- <image class="screenIcon" v-else :src="iconUrl.icon_bottom_y"></image>
- </view>
- </view>
- <!-- 筛选条件 -->
- <view class="mainScreenBox border-top" v-if="showScreen">
- <view class="cententBox">
- <view v-for="(column, index) in localScreen.columns" :key="index">
- <text class="screenTitle">{{ column.title }}</text>
- <view class="screenList">
- <text
- :class="{ 'active_screen': option.check }"
- v-for="(option, opIndex) in column.options"
- :key="opIndex"
- @click="selectItem(index, opIndex)"
- >
- {{ option.name }}
- </text>
- </view>
- </view>
- <view>
- <text class="screenTitle">查询时段</text>
- <view class="time_box displayFlexRow">
- <picker class="displayFlexRow" mode="date" :value="localScreen.startDate" :start="pickerStart" :end="localScreen.endDate" @change="onChangeStartDate">
- <view class="picker textTag">
- {{ localScreen.startDate }}
- </view>
- </picker>
- <text>至</text>
- <picker class="displayFlexRow" mode="date" :value="localScreen.endDate" :start="localScreen.startDate" :end="pickerEnd" @change="onChangeEndDate">
- <view class="picker textTag">
- {{ localScreen.endDate }}
- </view>
- </picker>
- </view>
- </view>
- </view>
- <view class="screenFooterBtn">
- <view class="border" @click.stop="onResetScreen">重置</view>
- <view class="backgroundCustom" @click.stop="onQueryRecords">确定</view>
- </view>
- </view>
- <!-- 遮罩 -->
- <view class="mask" v-if="showScreen" @click="hideScreen"></view>
- </view>
- </template>
- <script setup lang="ts">
- import { ref, watch, onMounted } from 'vue';
- import { common } from '@/utils';
- import icon from '@/utils/icon';
- const props = defineProps({
- screen: {
- type: Object,
- default: () => ({})
- },
- isShowTime: {
- type: Boolean,
- default: true
- },
- isShowScreen: {
- type: Boolean,
- default: true
- },
- pageType: {
- type: String,
- default: ""
- },
- pickerStart: {
- type: String,
- default: () => common.aFewDaysago(3650)
- },
- pickerEnd: {
- type: String,
- default: () => common.afterFewDays(3650)
- },
- type: {
- type: String,
- default: ""
- },
- defaultValue: {
- type: String,
- default: ""
- }
- });
- const emit = defineEmits(['changeStartDate', 'changeEndDate', 'setScreenData', 'queryRecords', 'resetScreen']);
- const iconUrl = ref(icon)
- const showScreen = ref(false);
- const screenTime = ref([
- { label: "近一周", value: "7", check: true },
- { label: "近一个月", value: "30", check: false },
- { label: "近三个月", value: "90", check: false },
- ]);
- const localScreen = ref<any>({});
- const backupsScreen = ref<any>(null);
- // Initialize
- onMounted(() => {
- if (common.isNotEmpty(props.screen.screenTime)) {
- screenTime.value = JSON.parse(JSON.stringify(props.screen.screenTime));
- }
- if (common.isNotEmpty(props.screen)) {
- localScreen.value = JSON.parse(JSON.stringify(props.screen));
- backupsScreen.value = JSON.parse(JSON.stringify(props.screen));
- }
- });
- watch(() => props.screen, (newVal) => {
- if (newVal) {
- localScreen.value = JSON.parse(JSON.stringify(newVal));
- }
- }, { deep: true });
- watch(() => props.defaultValue, (v) => {
- if (v) {
- screenTime.value.forEach(item => {
- item.check = item.value == v;
- });
- }
- });
- // Methods
- const choiceTime = (index: number) => {
- screenTime.value.forEach((item) => {
- item.check = false;
- });
- screenTime.value[index].check = true;
- let obj: any = {};
- let value = parseInt(screenTime.value[index].value);
-
- if (props.pageType == "yyjl") {
- obj = {
- startDate: common.dateFormat(new Date(Date.now())).formatYear,
- endDate: common.dateFormat(new Date(Date.now() + (value * 24 * 60 * 60 * 1000))).formatYear
- };
- } else if (props.pageType == "tabs") {
- obj = screenTime.value[index];
- // Special handling for tabs might be needed if it expects different structure
- } else {
- obj = {
- startDate: common.dateFormat(new Date(Date.now() - (value * 24 * 60 * 60 * 1000))).formatYear,
- endDate: common.dateFormat(new Date(Date.now() + (1 * 24 * 60 * 60 * 1000))).formatYear
- };
- }
- // Update local screen dates
- if (obj.startDate) localScreen.value.startDate = obj.startDate;
- if (obj.endDate) localScreen.value.endDate = obj.endDate;
- emit('changeStartDate', obj);
- };
- const onChangeStartDate = (e: any) => {
- let val = e.detail.value;
- localScreen.value.startDate = val;
- let obj = { startDate: val };
- if (showScreen.value) {
- emit('setScreenData', localScreen.value);
- } else {
- emit('changeStartDate', obj);
- }
- };
- const onChangeEndDate = (e: any) => {
- let val = e.detail.value;
- localScreen.value.endDate = val;
- let obj = { endDate: val };
- if (showScreen.value) {
- emit('setScreenData', localScreen.value);
- } else {
- emit('changeEndDate', obj);
- }
- };
- const toggleScreen = () => {
- showScreen.value = !showScreen.value;
- };
- const hideScreen = () => {
- showScreen.value = false;
- };
- const selectItem = (cIndex: number, index: number) => {
- let column = localScreen.value.columns[cIndex];
- let option = column.options[index];
- let key = column.key;
-
- // Logic for single/multiple selection
- let optionCheck = !option.check;
-
- // Modify localScreen directly
- column.options[index].check = optionCheck;
- if (column.single) {
- if (option.name == '全部') {
- if (optionCheck) {
- // Uncheck others
- column.options.forEach((opt: any, i: number) => {
- if (i != index) opt.check = false;
- });
- // Set value
- if (typeof(option.value) == "string" && option.value.indexOf(',') > -1) {
- localScreen.value[key] = option.value.split(',');
- } else {
- localScreen.value[key] = [option.value];
- }
- }
- } else {
- if (optionCheck) {
- // Uncheck others
- column.options.forEach((opt: any, i: number) => {
- if (i != index) opt.check = false;
- });
- localScreen.value[key] = [option.value];
- }
- }
- } else {
- // Multiple
- if (option.name == '全部') {
- if (optionCheck) {
- column.options.forEach((opt: any, i: number) => {
- if (i != index) opt.check = false;
- });
- if (option.value.indexOf(',') > -1) {
- localScreen.value[key] = option.value.split(',');
- } else {
- localScreen.value[key] = [option.value];
- }
- }
- } else {
- let keyVal = localScreen.value[key] || [];
- if (optionCheck) {
- // Uncheck '全部' if it was checked
- column.options.forEach((opt: any) => {
- if (opt.name == '全部' && opt.check) {
- opt.check = false;
- keyVal = [];
- }
- });
- keyVal.push(option.value);
- localScreen.value[key] = keyVal;
- } else {
- // Must select at least one? Original logic:
- if (keyVal.length > 1) {
- let idx = keyVal.indexOf(option.value);
- if (idx > -1) keyVal.splice(idx, 1);
- localScreen.value[key] = keyVal;
- } else {
- // Prevent unchecking the last one?
- // Original: if(keyVal.length>1){...} else { nothing } -> implies cannot uncheck last one
- // Revert check
- column.options[index].check = true;
- }
- }
- }
- }
- emit('setScreenData', localScreen.value);
- };
- const onQueryRecords = () => {
- screenTime.value.forEach((item) => {
- item.check = false;
- });
- emit('queryRecords', localScreen.value);
- showScreen.value = false;
- };
- const onResetScreen = () => {
- if (backupsScreen.value) {
- localScreen.value = JSON.parse(JSON.stringify(backupsScreen.value));
- emit('resetScreen', localScreen.value);
- }
- showScreen.value = false;
- };
- </script>
- <style lang="scss" scoped>
- @import "@/App.scss";
- .font_weight {
- font-weight: bold;
- }
- .displayFlexRow {
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- }
- .displayFlexCol {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- }
- .padding_0 {
- padding: 0 !important;
- }
- .width_100p {
- width: 100% !important;
- }
- .screenBody {
- position: relative;
- }
- /* 普通版 */
- .screenBox {
- width: 100%;
- height: 106upx;
- background: white;
- padding: 0upx 30upx;
- box-sizing: border-box;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- /* position: relative; */
- z-index: 15;
- border-radius: 0 0 30upx 30upx;
- }
- .dataBox {
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- }
- .screen_time_item {
- height: 100%;
- text-align: center;
- position: relative;
- }
- .screen_time_item text {
- line-height: 106upx;
- font-size: 32upx;
- color: #333;
- }
- .screen_time_item view {
- width: 56upx;
- height: 6upx;
- position: absolute;
- left: 50%;
- bottom: 0;
- margin-left: -28upx;
- }
- .screenBtn {
- width: 30%;
- min-width: 30%;
- display: flex;
- flex-direction: row;
- justify-content: flex-end;
- align-items: center;
- }
- .screenBtn text {
- font-size: 30upx;
- color: #666;
- padding-right: 16upx;
- }
- .screenIcon {
- width: 24upx;
- height: 14upx;
- }
- .mainScreenBox {
- width: 100%;
- max-height: 800upx;
- background: white;
- border-radius: 24upx 24upx 0 0;
- position: fixed;
- /* top: 100upx; */
- left: 0;
- bottom: 0;
- z-index: 15;
- }
- .cententBox {
- max-height: 640upx;
- padding: 40upx 30upx;
- box-sizing: border-box;
- overflow: auto;
- }
- .screenTitle {
- display: inline-block;
- font-size: 32upx;
- font-weight: bold;
- color: #333;
- margin-top: 64upx;
- margin-bottom: 36upx;
- }
- .screenTitle:nth-child(1) {
- margin-top: 0upx;
- }
- .screenList {
- display: flex;
- flex-direction: row;
- justify-content: flex-start;
- align-items: center;
- flex-wrap: wrap;
- }
- .screenList text {
- display: inline-block;
- width: 30%;
- line-height: 80upx;
- /* width: 210upx; */
- margin-right: 5%;
- margin-bottom: 30upx;
- font-size: 28upx;
- text-align: center;
- color: #333;
- padding: 0 20upx;
- background: #f7f7f7;
- border-radius: 80upx;
- }
- .active_screen {
- color: #007aff !important; /* var(--dominantColor) replacement */
- border: 1px solid #007aff;
- }
- .screenList text:nth-child(3n) {
- margin-right: 0upx;
- }
- .time_box {
- justify-content: flex-start;
- }
- .time_box text {
- margin: 0 30upx;
- }
- .picker {
- font-size: 32upx;
- padding: 27upx 44upx;
- background: #f1f1f6;
- border-radius: 100upx;
- }
- .screenFooterBtn {
- padding: 30upx;
- box-sizing: border-box;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- }
- .screenFooterBtn view {
- width: 30%;
- line-height: 98upx;
- font-size: 36upx;
- text-align: center;
- border-radius: 98upx;
- }
- .screenFooterBtn view:nth-child(2) {
- width: 65%;
- }
- .mask {
- width: 100%;
- height: 100%;
- background: black;
- opacity: 0.6;
- position: fixed;
- /* top: 480upx; */
- bottom: 0;
- z-index: 6;
- }
- .textColor {
- color: #306eff !important;
- }
- .border-bottom {
- position: relative;
- z-index: 10;
- }
- .border-bottom::after {
- content: " ";
- position: absolute;
- left: 0;
- bottom: 0;
- width: 100%;
- height: 1px;
- border-top: 1px solid #e6e6e6;
- -webkit-transform-origin: 0 0;
- transform-origin: 0 0;
- -webkit-transform: scaleY(0.5);
- transform: scaleY(0.5);
- }
- /* Card Type Styles */
- .card .screen_time_item {
- height: 80upx;
- padding: 0 20upx;
- background-color: #e5e9ec;
- border-radius: 20upx;
- }
- .card .screen_time_item text {
- line-height: 80upx;
- font-size: 28upx;
- }
- .card .screen_time_item.backgroundCustom text {
- color: #fff;
- }
- .card .screen_time_item:not(:first-child) {
- margin-left: 20upx;
- }
- .card .screen_time_item view {
- display: none;
- }
- </style>
|