Commit ad9f760b authored by shilei's avatar shilei

Merge branch 'dev' of http://101.201.78.203/cfld-front/liyeyun into dev

parents 8f0a61ff 9cec705a
......@@ -62,5 +62,6 @@ module.exports = {
registeredComponentsOnly: false,
},
],
'vue-scoped-css/require-v-deep-argument': 'off',
},
};
......@@ -32,3 +32,5 @@ playwright-report/
auto-imports.d.ts
components.d.ts
yarn.lock
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -18,35 +18,35 @@
"@vueuse/core": "^10.6.1",
"axios": "^1.6.2",
"big.js": "^6.2.1",
"element-plus": "^2.4.2",
"element-plus": "^2.4.3",
"lodash-es": "^4.17.21",
"pinia": "^2.1.7",
"swiper": "^11.0.5",
"vue": "^3.3.8",
"vue": "^3.3.9",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.5.1",
"@rushstack/eslint-patch": "^1.6.0",
"@tsconfig/node18": "^18.2.2",
"@types/jsdom": "^21.1.5",
"@types/node": "^20.9.2",
"@types/jsdom": "^21.1.6",
"@types/node": "^20.10.3",
"@types/qs": "^6.9.10",
"@vitejs/plugin-legacy": "^5.0.0",
"@vitejs/plugin-vue": "^4.5.0",
"@vitejs/plugin-legacy": "^5.2.0",
"@vitejs/plugin-vue": "^4.5.1",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.2",
"@vue/test-utils": "^2.4.3",
"@vue/tsconfig": "^0.4.0",
"autoprefixer": "^10.4.16",
"browserslist": "^4.22.1",
"eslint": "^8.54.0",
"browserslist": "^4.22.2",
"eslint": "^8.55.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-tailwindcss": "^3.13.0",
"eslint-plugin-vue": "^9.18.1",
"eslint-plugin-vue": "^9.19.2",
"eslint-plugin-vue-scoped-css": "^2.5.1",
"jsdom": "^22.1.0",
"jsdom": "^23.0.1",
"npm-run-all2": "^6.1.1",
"postcss-preset-env": "^9.3.0",
"postcss-scss": "^4.0.9",
......@@ -54,11 +54,11 @@
"sass": "^1.69.5",
"tailwindcss": "^3.3.5",
"typescript": "~5.2.2",
"unplugin-auto-import": "^0.16.7",
"unplugin-vue-components": "^0.25.2",
"vite": "^5.0.0",
"unplugin-auto-import": "^0.17.2",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.0.5",
"vite-plugin-eslint": "^1.8.1",
"vitest": "^0.34.6",
"vue-tsc": "^1.8.22"
"vue-tsc": "^1.8.24"
}
}
<template>
<div class="flex h-12 items-center justify-between">
<div class="flex h-full items-center">
<div>
<img class="h-10 w-auto" src="@/assets/images/logo-head.png" alt="立业云" />
</div>
<div
class="ml-4 flex h-8 items-center px-4 font-yahei text-base text-[#C0322B] outline outline-1 outline-[#C0322B]"
>
{{ typeName }}
</div>
</div>
<div class="h-full">
<div class="search-input-shadow flex h-full items-center overflow-hidden rounded">
<div class="flex flex-1 items-center justify-center">
<input
class="search-input h-full w-[375px] px-3 py-[14px] text-sm"
type="text"
:placeholder="`请输入${typeName}名称进行搜索`"
/>
</div>
<div class="flex h-full w-[70px] items-center justify-center bg-[#C0322B]">
<img class="h-[30px] w-[30px]" src="@/assets/images/icon-search.png" alt="search" />
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
withDefaults(
defineProps<{
typeName: string;
}>(),
{},
);
</script>
<style lang="scss">
.search-input-shadow {
box-shadow: 0px 2px 8px 0px rgba(90, 0, 0, 0.1);
}
.search-input {
&:focus {
outline: none;
}
&::placeholder {
@apply text-[#999999];
}
}
</style>
<template>
<div v-if="infos.length > 0">
<div v-for="(line, index) of infos" :key="index" class="min-h-10 flex">
<div v-for="(line, index) of infos" :key="index" class="min-h-10 inline-flex w-full">
<div v-for="col in line" :key="col.name" class="flex flex-1 text-xs text-[#1A1A1A]">
<div class="flex w-[160px] items-center bg-[#FAFAFC] px-[30px] py-[10px] leading-5">
{{ col.name }}
......
......@@ -10,7 +10,10 @@
{{ title }}
</div>
</h2>
<div class="relative flex h-[17px] items-center justify-center">
<div
v-if="titleCenter || toListText"
class="relative flex h-[17px] items-center justify-center"
>
<div v-if="titleCenter" class="title-bottom-bg h-1 w-[102px] rounded-[30px]"></div>
<div
v-if="toListText"
......@@ -20,13 +23,34 @@
更多
</div>
</div>
<div class="mt-5">
<div
ref="test"
class="mt-5"
:class="{ 'content-hidden': !isContentExpand }"
:style="contentStyle"
>
<slot></slot>
</div>
<div
v-if="showContentExpand"
class="flex h-10 w-full cursor-pointer justify-center"
@click="changeContentExpand(!isContentExpand)"
>
<div class="flex h-full items-center px-4">
<div class="text-xs leading-[14px] text-[#4D4D4D]">
{{ isContentExpand ? '收起' : '展示全部' }}
</div>
<div class="ml-1">
<img class="h-3 w-3" src="@/assets/images/icon-arrow_down.png" alt="" />
</div>
</div>
</div>
</section>
</template>
<script lang="ts" setup>
import { ref, computed, watchEffect } from 'vue';
export interface DetailInfoCellProps {
/** 标题 */
title?: string;
......@@ -34,15 +58,49 @@ export interface DetailInfoCellProps {
toListText?: string;
/** 是否标题居中 */
titleCenter?: boolean;
/** 最大展示行数 */
maxLines?: number;
}
withDefaults(defineProps<DetailInfoCellProps>(), {
const props = withDefaults(defineProps<DetailInfoCellProps>(), {
title: '',
toListText: '',
titleCenter: false,
maxLines: -1,
});
const emit = defineEmits(['to-list']);
/** 当前内容是否展开 */
const isContentExpand = ref(true);
/** 展示内容展示按钮 */
const showContentExpand = computed(() => {
return props.maxLines > -1;
});
const contentStyle = computed(() => {
if (showContentExpand.value) {
return {
'-webkit-line-clamp': props.maxLines,
};
} else {
return {};
}
});
watchEffect(() => {
if (showContentExpand.value) {
isContentExpand.value = false;
} else {
isContentExpand.value = true;
}
});
/** 改变展开状态 */
const changeContentExpand = (b: boolean) => {
isContentExpand.value = b;
};
const handleToList = () => {
emit('to-list');
};
......@@ -57,4 +115,10 @@ const handleToList = () => {
rgba(192, 50, 43, 0) 100%
);
}
.content-hidden {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
}
</style>
<!-- 主图部分 -->
<template>
<div v-if="detail">
<div class="flex h-12 items-center justify-between">
<div class="flex h-full items-center">
<div>
<img class="h-10 w-auto" src="@/assets/images/logo-head.png" alt="立业云" />
</div>
<div
class="ml-4 flex h-8 items-center px-4 font-yahei text-base text-[#C0322B] outline outline-1 outline-[#C0322B]"
>
{{ headerType }}
</div>
</div>
<div class="h-full">
<div class="search-input-shadow flex h-full items-center overflow-hidden rounded">
<div class="flex flex-1 items-center justify-center">
<input
class="search-input h-full w-[375px] px-3 py-[14px] text-sm"
type="text"
:placeholder="`请输入${headerType}名称进行搜索`"
/>
</div>
<div class="flex h-full w-[70px] items-center justify-center bg-[#C0322B]">
<img class="h-[30px] w-[30px]" src="@/assets/images/icon-search.png" alt="search" />
</div>
</div>
</div>
</div>
<CommonTitle :type-name="headerType"></CommonTitle>
<div class="mt-5 py-5">
<div class="flex h-10 items-center">
<div class="font-yahei text-[32px] font-bold leading-10 text-[#333333]">
......@@ -95,6 +70,7 @@ import { computed } from 'vue';
import ImageList from '@/components/common/ImageList.vue';
import type { Investment } from '@/types/common.ts';
import { haveValue } from '@/utils/filters.ts';
import CommonTitle from '@/components/common/CommonTitle.vue';
export interface HeaderDetail {
name: string;
......@@ -143,17 +119,3 @@ const area = computed(() => {
return [provinceName, cityName, regionName].filter(haveValue).join('-');
});
</script>
<style lang="scss">
.search-input-shadow {
box-shadow: 0px 2px 8px 0px rgba(90, 0, 0, 0.1);
}
.search-input {
&:focus {
outline: none;
}
&::placeholder {
@apply text-[#999999];
}
}
</style>
......@@ -138,7 +138,7 @@
</template>
<script setup lang="ts">
import { ref, onMounted, computed, watch } from 'vue';
import { FilterListItem } from '@/types/common.ts';
// import type { FilterListItem } from '@/types/common.ts';
import { filterStore } from '@/stores/filterEnum.ts';
import { defaultFiltersConfig } from '@/components/filter/config.ts';
import { isEmpty } from 'lodash-es';
......@@ -212,12 +212,12 @@ onMounted(async () => {
const filterEnum = await store.getFilterEnum();
props.filterKeyList.forEach((item) => {
const list = filterEnum[item];
filterList.value.push({ ...defaultFiltersConfig[item], list });
filterList.value.push({ ...(defaultFiltersConfig as any)[item], list });
});
});
// 处理输入
function handleEnter<T>(arg: Ref<T>) {
function handleEnter(arg: any) {
if (!isEmpty(arg.plugins.value1) || !isEmpty(arg.plugins.value2)) {
if (isEmpty(arg.plugins.value2)) {
arg.valueLabel = `≥${arg.plugins.value1}${arg.plugins.unit}`;
......@@ -291,9 +291,10 @@ function selectAll(filter) {
const emit = defineEmits(['change']);
watch(
selected,
(newVal) => {
console.log(newVal);
emit('change', selected);
(newVal, oldVal) => {
if (!isEmpty(newVal) || !isEmpty(oldVal)) {
emit('change', selected);
}
},
{
immediate: false,
......
<template>
<div class="flex cursor-pointer">
<div class="media-left mr-[16px]">
<img class="h-[156px] w-[208px]" :src="detail.imgUrl" alt="" />
<div class="flex">
<div class="media-left mr-[16px] cursor-pointer" @click="handleDetail">
<CommonImage class="h-[156px] w-[208px]" :src="detail.imgUrl" alt="" />
</div>
<div
class="media-right relative flex w-[408px] flex-col justify-between pt-[8px] text-[12px] leading-[20px] text-[#4d4d4d]"
>
<p class="ell2 mb-[7px] text-[20px] font-semibold leading-[20px] text-[#1a1a1a]">
<p
class="ell2 mb-[7px] cursor-pointer text-[20px] font-semibold leading-[20px] text-[#1a1a1a]"
@click="handleDetail"
>
{{ detail.provinceName?.replace('省', '').replace('市', '')
}}{{ detail.cityName?.replace('市', '') }}{{ detail.regionName }}{{ detail.area }}{{
detail.type
......@@ -31,6 +34,7 @@
</template>
<script lang="ts" setup>
import type { CarrierListItem } from '@/types/api/carrierList';
import CommonImage from '@/components/common/CommonImage.vue';
withDefaults(
defineProps<{
......@@ -38,6 +42,14 @@ withDefaults(
}>(),
{},
);
const emit = defineEmits<{
'to-detail': [];
}>();
const handleDetail = () => {
emit('to-detail');
};
</script>
<style lang="scss" scoped>
.info-icon {
......
<template>
<div class="flex cursor-pointer">
<div class="media-left mr-[16px]">
<img class="h-[156px] w-[208px]" :src="detail.imgUrl" alt="" />
<div class="flex">
<div class="media-left mr-[16px] cursor-pointer" @click="handleDetail">
<CommonImage class="h-[156px] w-[208px]" :src="detail.imgUrl" alt="" />
</div>
<div
class="media-right relative flex w-[408px] flex-col justify-between pt-[8px] text-[12px] leading-[20px] text-[#4d4d4d]"
>
<p class="ell2 mb-[7px] text-[20px] font-semibold leading-[20px] text-[#1a1a1a]">
<p
class="ell2 mb-[7px] cursor-pointer text-[20px] font-semibold leading-[20px] text-[#1a1a1a]"
@click="handleDetail"
>
{{ detail.provinceName?.replace('省', '').replace('市', '')
}}{{ detail.cityName?.replace('市', '') }}{{ detail.regionName }}{{ detail.area }}{{
detail.landType
......@@ -34,6 +37,7 @@
</template>
<script lang="ts" setup>
import type { LandListItem } from '@/types/api/landList';
import CommonImage from '@/components/common/CommonImage.vue';
withDefaults(
defineProps<{
......@@ -41,6 +45,14 @@ withDefaults(
}>(),
{},
);
const emit = defineEmits<{
'to-detail': [];
}>();
const handleDetail = () => {
emit('to-detail');
};
</script>
<style lang="scss" scoped>
.info-icon {
......
import { useQueryList } from '@/composable/useQueryList.ts';
import { ref, watchEffect, type Ref } from 'vue';
import { ref, type Ref, watchEffect } from 'vue';
import { RequestUrl } from '@/types/api.ts';
import type { CommonListResp, CommonListParams } from '@/types/common';
import type { RouteName } from '@/router/router.ts';
......@@ -9,20 +9,21 @@ import { useJump } from './useJump.ts';
export function useListView<
T extends { id: number; [index: string]: any },
C extends Record<any, any>,
>(url: RequestUrl, searchParams: any = {}) {
>(url: RequestUrl, searchParams: Ref<any> = ref({})) {
const { open } = useJump();
const { request: requestList } = useRequest<CommonListResp<T>, CommonListParams<C>>(url, {
method: 'POST',
});
const { pageNum, pageSize, totalCount, queryList } = useQueryList<T, C>(requestList);
const { pageNum, pageSize, totalCount, queryList, initPagination } = useQueryList<T, C>(
requestList,
);
const datas = ref([]) as Ref<T[]>;
// const searchParams = ref({}) as Ref<C>;
watchEffect(async () => {
try {
const { data } = await queryList(searchParams);
const { data } = await queryList(searchParams.value || {});
datas.value = data.records;
} catch (error) {
console.log(error);
......@@ -48,5 +49,6 @@ export function useListView<
datas,
queryList,
handleDetail,
initPagination,
};
}
......@@ -44,7 +44,7 @@ export function useQueryList<T, C>(queryFn: QueryFn<T, CommonListParams<C>>) {
};
const initPagination = () => {
changePagination({ page: 1, size: 0, total: 0 });
changePagination({ page: 1, size: 10, total: 0 });
};
const assignPageParams = (params: C): CommonListParams<C> => {
......@@ -88,5 +88,6 @@ export function useQueryList<T, C>(queryFn: QueryFn<T, CommonListParams<C>>) {
changeTotalCount,
changePagination,
queryList,
initPagination,
};
}
<!-- 载体 -->
<template>
<div class="container">
<CommonTitle class="my-[30px]" type-name="载体"></CommonTitle>
<FilterView
class="mb-6"
:filter-key-list="filterKeyList"
......@@ -14,13 +15,11 @@
个相关载体
</p>
<div>
<div
v-for="item in datas"
:key="item.id"
class="mb-5"
@click="handleDetail(RouteName.landDetail, item)"
>
<CarrierListItemView :detail="item"></CarrierListItemView>
<div v-for="item in datas" :key="item.id" class="mb-5">
<CarrierListItemView
:detail="item"
@to-detail="handleDetail(RouteName.carrierDetail, item)"
></CarrierListItemView>
</div>
<ListPagination
v-model:current-page="pageNum"
......@@ -38,14 +37,17 @@ import { RouteName } from '@/router/router.ts';
import { RequestUrl } from '@/types/api.ts';
import ListPagination from '@/components/list/ListPagination.vue';
import CarrierListItemView from '@/components/list/list-carrier-item.vue';
import CommonTitle from '@/components/common/CommonTitle.vue';
import FilterView from '@/components/filter/filter-view.vue';
import type { CarrierListCondition, CarrierListItem } from '@/types/api/carrierList';
import { ref } from 'vue';
const { pageNum, pageSize, totalCount, datas, handleDetail, queryList } = useListView<
const searchParams = ref<any>({});
const { pageNum, pageSize, totalCount, datas, handleDetail, initPagination } = useListView<
CarrierListItem,
CarrierListCondition
>(RequestUrl.carrierList);
>(RequestUrl.carrierList, searchParams);
// 筛选项
const filterKeyList = ref([
'carrier_area',
......@@ -56,14 +58,13 @@ const filterKeyList = ref([
'pillar_distance',
]);
// 处理筛选条件
const handleFilterChange = async function (selectList) {
const handleFilterChange = async (selectList: any) => {
const temp: any = {};
for (const item of selectList.value) {
temp[item.key] = item.value;
}
pageNum.value = 1;
const { data } = await queryList(temp);
datas.value = data.records;
initPagination();
searchParams.value = temp;
};
</script>
<style lang="scss" scoped>
......
<!-- 开发区列表 -->
<template>
<div class="main-width mx-auto">
<CommonTitle class="my-[30px]" type-name="开发区"></CommonTitle>
<FilterView
:filter-key-list="filterKeyList"
class="mb-6"
......@@ -33,6 +34,7 @@ import { RequestUrl } from '@/types/api.ts';
import type { DevelopZoneItem, DevelopZoneListCondition } from '@/types/api/developZoneList';
import { ParkItemType } from '@/types/enum.ts';
import FilterView from '@/components/filter/filter-view.vue';
import CommonTitle from '@/components/common/CommonTitle.vue';
// 筛选项列表
const filterKeyList = [
......@@ -49,7 +51,7 @@ const { pageNum, pageSize, totalCount, datas, handleDetail, queryList } = useLis
>(RequestUrl.developZoneList);
// 处理筛选条件
const handleFilterChange = async function (selectList) {
const handleFilterChange = async (selectList: any) => {
const temp: any = {};
for (const item of selectList.value) {
temp[item.key] = item.value;
......
<!-- 产业园列表 -->
<template>
<div class="main-width mx-auto">
<CommonTitle class="my-[30px]" type-name="产业园"></CommonTitle>
<FilterView
class="mb-6"
:filter-key-list="filterKeyList"
......@@ -33,6 +34,7 @@ import { RouteName } from '@/router/router.ts';
import { RequestUrl } from '@/types/api.ts';
import ListPagination from '@/components/list/ListPagination.vue';
import FilterView from '@/components/filter/filter-view.vue';
import CommonTitle from '@/components/common/CommonTitle.vue';
import ParkItem from '@/components/list/ParkItem.vue';
import type {
IndustrialParkItem,
......@@ -53,7 +55,7 @@ const filterKeyList = [
'industry_policy',
];
// 处理筛选条件
const handleFilterChange = async function (selectList) {
const handleFilterChange = async (selectList: any) => {
const temp: any = {};
for (const item of selectList.value) {
temp[item.key] = item.value;
......
......@@ -2,18 +2,17 @@
<template>
<div class="container">
<div>
<CommonTitle class="my-[30px]" type-name="土地"></CommonTitle>
<FilterView
:filter-key-list="filterKeyList"
class="mb-6"
@change="handleFilterChange"
></FilterView>
<div
v-for="item in datas"
:key="item.id"
class="mb-5"
@click="handleDetail(RouteName.landDetail, item)"
>
<LandListItemView :detail="item"></LandListItemView>
<div v-for="item in datas" :key="item.id" class="mb-5">
<LandListItemView
:detail="item"
@to-detail="handleDetail(RouteName.landDetail, item)"
></LandListItemView>
</div>
<ListPagination
......@@ -31,6 +30,7 @@ import { RouteName } from '@/router/router.ts';
import { RequestUrl } from '@/types/api.ts';
import ListPagination from '@/components/list/ListPagination.vue';
import LandListItemView from '@/components/list/list-land-item.vue';
import CommonTitle from '@/components/common/CommonTitle.vue';
import FilterView from '@/components/filter/filter-view.vue';
import type { LandListCondition, LandListItem } from '@/types/api/landList';
import { ref } from 'vue';
......@@ -40,7 +40,7 @@ const { datas, pageNum, totalCount, pageSize, handleDetail, queryList } = Respon
const filterKeyList = ref(['land_price', 'land_type', 'land_area']);
// 处理筛选条件
const handleFilterChange = async function (selectList) {
const handleFilterChange = async (selectList: any) => {
const temp: any = {};
for (const item of selectList.value) {
temp[item.key] = item.value;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment