| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- <template>
- <FlexCol :padding="[30,30,0,30]" gap="gap.lg">
- <!-- 卡片背景 -->
- <BackgroundBox
- color1="#eecaa0"
- color2="white"
- color2Position="85%"
- color3="white"
- radius="radius.lg"
- direction="column"
- :padding="[35,30]"
- gap="gap.lg"
- >
- <!-- 标题 -->
- <FlexRow justify="space-between" align="flex-end" width="100%">
- <FlexCol gap="gap.md">
- <Text :text="villageInfoLoader.content.value?.title" fontConfig="primaryTitle" />
- </FlexCol>
- <FlexRow center gap="gap.lg">
- <BubbleTip
- v-model:show="showFollowTip"
- content="关注我,方便下次进入"
- @contentClick="isFollowed ? undefined : onFollow()"
- @close="handleCloseFollowTip"
- >
- <Button
- icon="https://xy.wenlvti.net/app_static/images/village/IconJoin.png"
- radius="radius.lgr"
- @click="isFollowed ? onUnFollow() : onFollow()"
- >
- {{ isFollowed ? '已关注' : '关注' }}
- </Button>
- </BubbleTip>
- <Button
- icon="https://xy.wenlvti.net/app_static/images/village/IconFollow.png"
- radius="radius.lgr"
- @click="handleGoJoin()"
- >
- {{ isJoined ? '已加入' : '加入' }}
- </Button>
- </FlexRow>
- </FlexRow>
- <!-- 简介 -->
- <TextEllipsis
- fontConfig="secondText"
- :lines="2"
- :expandable="(villageInfoLoader.content.value?.desc as string || '').length > 80"
- :text="(villageInfoLoader.content.value?.desc as string) || '暂无简介,欢迎您来编写完善!'"
- />
- <!-- 状态与申请 -->
- <FlexRow
- backgroundColor="background.tertiary"
- radius="radius.md"
- padding="space.md"
- justify="space-between"
- >
- <FlexRow align="center">
- <FlexCol gap="gap.md">
- <Text :text="`${villageInfoLoader.content.value?.levelText || '默认级别'}`" fontConfig="secondText" />
- <Text :text="`存储空间内存:${villageInfoLoader.content.value?.sizeText || 0}`" fontConfig="secondText" />
- </FlexCol>
- </FlexRow>
- <FlexRow align="center" gap="gap.md">
- <IconButton icon="help-filling" @click="navTo('/pages/article/details', { id: 7021, modelId: 18, showRecommend: false })" />
- <Button
- icon="https://xy.wenlvti.net/app_static/images/village/IconUser.png"
- radius="radius.lgr"
- :padding="[10, 30]"
- backgroundColor="white"
- @click="upgradeRef?.show()"
- >
- 升级村社
- </Button>
- </FlexRow>
- </FlexRow>
-
- <!-- 图片 -->
- <VillageGallery
- v-if="villageInfoLoader.content.value"
- ref="villageGalleryRef"
- :villageId="villageStore.currentVillage?.id ?? 0"
- @goGallery="handleGoGallery"
- />
- <!-- 地址 -->
- <FlexRow justify="space-between" align="center">
- <FlexRow align="center" gap="gap.sm">
- <Icon name="https://xy.wenlvti.net/app_static/images/village/IconMap.png" size="fontSize.md" />
- <Text :text="villageInfoLoader.content.value?.address" fontConfig="contentText" />
- </FlexRow>
- <Button size="mini" icon="picture" text="村社相册" @click="handleGoGallery" />
- </FlexRow>
- <VillageMiniMap
- v-if="villageInfoLoader.content.value"
- :lonlat="{
- longitude: villageInfoLoader.content.value.longitude,
- latitude: villageInfoLoader.content.value.latitude
- }"
- :currentNoticeContent="currentNoticeContent"
- />
- <FlexRow justify="space-between" align="center">
- <FlexRow center gap="gap.lg" flexBasis="50%">
- <Text text="村社排名" fontConfig="contentText" />
- <Text text="No." fontConfig="lightTitle" />
- <Text :text="villageInfoLoader.content.value?.rankText" fontConfig="primaryTitle" />
- </FlexRow>
- <FlexRow center gap="gap.lg" flexBasis="50%">
- <Text text="村社等级" fontConfig="contentText" />
- <Text :text="`${villageInfoLoader.content.value?.level}级`" fontConfig="primaryTitle" />
- </FlexRow>
- </FlexRow>
- <FlexRow backgroundColor="background.tertiary" radius="radius.md" :padding="[30, 20]">
- <FlexCol center gap="gap.sm" flexBasis="25%">
- <Text text="乡源光" fontConfig="secondText" />
- <Text :text="villageInfoLoader.content.value?.light || '0'" fontConfig="importantTitle" />
- <Button type="text" size="mini" text="做任务" @click="navTo('/pages/home/village/task/index')" />
- </FlexCol>
- <Divider type="vertical" />
- <FlexCol center gap="gap.sm" flexBasis="25%">
- <Touchable direction="column" center @click="navTo('/pages/home/village/volunteer/list', { villageId: villageStore.currentVillage?.id ?? undefined })">
- <Text text="乡源人数" fontConfig="contentText" />
- <Text :text="villageInfoLoader.content.value?.memberCount|| '0'" fontConfig="importantTitle" />
- </Touchable>
- <WxButton openType="share">
- <Button type="text" size="mini" text="邀请加入" @click="navTo('/pages/home/village/task/index')" />
- </WxButton>
- </FlexCol>
- <Divider type="vertical" />
- <Touchable direction="column" center gap="gap.sm" flexBasis="25%" @click="navTo('/pages/home/village/volunteer/list', {
- villageId: villageStore.currentVillage?.id ?? undefined,
- })">
- <Text text="关注人数" fontConfig="contentText" />
- <Text :text="villageInfoLoader.content.value?.followerCount|| '0'" fontConfig="importantTitle" />
- <Height :size="36" />
- </Touchable>
- <Divider type="vertical" />
- <Button
- :padding="0"
- type="text"
- size="small"
- textColor="text.title"
- text="新手上路"
- rightIcon="arrow-right"
- @click="handleGoNew()"
- />
- </FlexRow>
- </BackgroundBox>
- <!-- 排行榜 -->
- <HomeTitle
- title="排行榜"
- showMore
- @moreClicked="navTo('/pages/home/village/rank/volunteer', {
- villageId: villageStore.currentVillage?.id ?? undefined,
- })"
- />
- <!-- <RoundTags v-model:active="rankActiveTag" :tags="['乡源果', '乡源光', '文化积分' ]" /> -->
- <VillageUserRankList
- :list="villageUserRankListLoader.content.value ?? []"
- :scoreSuffix="rankActiveTag"
- @goDetails="navTo('/pages/home/village/volunteer/detail', { id: $event.id })"
- />
- <!-- 魅力乡源 -->
- <HomeTitle title="魅力乡源" showMore @moreClicked="handleGoCollect()">
- <template #right>
- <FlexRow align="center" gap="gap.md">
- <Touchable
- :padding="[15, 20]"
- direction="row"
- center
- gap="gap.md"
- @click="handleGoDigManage()"
- >
- <Icon name="https://xy.wenlvti.net/app_static/images/village/IconLargeFolkloreVibe.png" :size="30" />
- <Text text="管理" fontConfig="contentText" />
- </Touchable>
- <Touchable
- :padding="[15, 20]"
- :innerStyle="{
- marginRight: '20rpx'
- }"
- borderStyle="solid"
- borderColor="border.secondary"
- borderWidth="1px"
- backgroundColor="background.quaternary"
- radius="radius.md"
- direction="row"
- center
- gap="gap.sm"
- @click="handleGoCollect()"
- >
- <Icon name="https://xy.wenlvti.net/app_static/images/village/IconHistory.png" :size="30" />
- <Text text="共编村史" fontConfig="contentText" />
- </Touchable>
- </FlexRow>
- </template>
- </HomeTitle>
- <ProvideVar :vars="{
- GridItemIconSize: 90,
- GridItemBackgroundColor: 'transparent',
- GridItemPaddingHorizontal: 0,
- GridItemPaddingVertical: 8,
- }">
- <Grid :borderGrid="false" :mainAxisCount="4">
- <GridItem title="村社概况" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeIntrod.png" touchable @click="handleGoCollect(11, '村社概况')" />
- <GridItem title="自然风光" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeEnvirounment.png" touchable @click="handleGoCollect(13, '自然风光')" />
- <GridItem title="历史沿革" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeHistory.png" touchable @click="handleGoCollect(2, '历史沿革')" />
- <GridItem title="特色产业" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeIndustry.png" touchable @click="handleGoCollect(9, '特色产业' )" />
- <GridItem title="文艺活动" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeActivity.png" touchable @click="handleGoCollect(12, '文艺活动')" />
- <GridItem title="非遗展示" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeShow.png" touchable @click="handleGoCollect(10, '非遗展示')" />
- <GridItem title="民俗风采" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeFolkloreVibe.png" touchable @click="handleGoCollect(8, '民俗风采')" />
- <GridItem title="历史人物" icon="https://xy.wenlvti.net/app_static/images/village/IconGoods.png" touchable @click="handleGoCollect(7, '历史人物')" />
- </Grid>
- </ProvideVar>
- <!-- 活力乡源 -->
- <HomeTitle title="活力乡源" />
- <ProvideVar :vars="{
- GridItemIconSize: 90,
- GridItemBackgroundColor: 'transparent',
- GridItemPaddingHorizontal: 0,
- GridItemPaddingVertical: 8,
- }">
- <Grid :borderGrid="false" :mainAxisCount="4">
- <GridItem title="乡源荣光" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeHornor.png" touchable @click="handleGoCollect(23, '乡源荣光')" />
- <GridItem title="乡源好物" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeGoods.png" touchable @click="navTo('/pages/home/village/goods/index', { villageId: villageStore.currentVillage?.id ?? undefined })" />
- <GridItem title="乡源树" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeTree.png" touchable @click="emit('goTree')" />
- <!-- <GridItem title="政贤连心" icon="https://xy.wenlvti.net/app_static/images/village/IconGovAffairs.png" touchable @click="navTo('/pages/home/village/gov/index')" /> -->
- <GridItem title="互动游戏" icon="https://xy.wenlvti.net/app_static/images/village/IconLargeGame.png" touchable @click="navTo('/pages/home/village/games/index')" />
- </Grid>
- </ProvideVar>
- <!-- 文脉乡源 -->
- <HomeTitle title="文脉乡源">
- <template #right>
- <FlexRow align="center" gap="gap.md">
- <BubbleTip
- v-model:show="showManageTip"
- position="bottom"
- crossPosition="left"
- arrowOffsetX="-50rpx"
- content="村社贴图太乱?点这里整理"
- @contentClick="handleCloseManageTip(true)"
- @close="handleCloseManageTip(false)"
- >
- <Touchable
- :padding="[15, 20]"
- direction="row"
- center
- gap="gap.md"
- @click="handleGoOfficalManage()"
- >
- <Icon name="https://xy.wenlvti.net/app_static/images/village/IconLargeFolkloreVibe.png" :size="30" />
- <Text text="管理" fontConfig="contentText" />
- </Touchable>
- </BubbleTip>
- <Touchable
- :padding="[15, 20]"
- direction="row"
- center
- gap="gap.md"
- @click="handleGoPublish()"
- >
- <Icon name="https://xy.wenlvti.net/app_static/images/village/IconLargeHistory.png" :size="30" />
- <Text text="乡源AI帮你写" fontConfig="contentText" />
- </Touchable>
- </FlexRow>
- </template>
- </HomeTitle>
- <RoundTags v-model:active="listActiveTag" :tags="['广场', '老味道', '老手艺', '老物件', '老故事']" />
- </FlexCol>
- <OfficialAccountPublishWrap
- :topic="recommendTagName"
- @publishsuccess="onPublishSuccess"
- @empty="isOfficialEmpty=true"
- />
- <UpgradeDialog
- ref="upgradeRef"
- v-if="villageStore.currentVillage"
- :villageId="villageStore.currentVillage.id"
- />
- </template>
- <script setup lang="ts">
- import { computed, ref, watch } from 'vue';
- import { useUserTools } from '@/common/composeabe/UserTools';
- import { useOfficialAccount } from '../../composeabe/OfficialAccount';
- import { useAuthStore } from '@/store/auth';
- import { useSimpleDataLoader } from '@/components/composeabe/loader/SimpleDataLoader';
- import { useVillageStore } from '@/store/village';
- import { useRequireLogin } from '@/common/composeabe/RequireLogin';
- import { useFollow } from '../composeabe/Follow';
- import { ArrayUtils, assertNotNull, waitTimeOut } from '@imengyu/imengyu-utils';
- import { navTo } from '@/components/utils/PageAction';
- import HomeTitle from '@/common/components/parts/HomeTitle.vue';
- import Icon from '@/components/basic/Icon.vue';
- import Text from '@/components/basic/Text.vue';
- import BackgroundBox from '@/components/display/block/BackgroundBox.vue';
- import Touchable from '@/components/feedback/Touchable.vue';
- import FlexCol from '@/components/layout/FlexCol.vue';
- import FlexRow from '@/components/layout/FlexRow.vue';
- import VillageMiniMap from '../../components/VillageMiniMap.vue';
- import Divider from '@/components/display/Divider.vue';
- import RoundTags from '@/common/components/parts/RoundTags.vue';
- import VillageUserRankList from '../../components/VillageUserRankList.vue';
- import ProvideVar from '@/components/theme/ProvideVar.vue';
- import Grid from '@/components/layout/grid/Grid.vue';
- import GridItem from '@/components/layout/grid/GridItem.vue';
- import LightVillageApi from '@/api/light/LightVillageApi';
- import OfficialAccountPublishWrap from '@/common/components/OfficialAccountPublishWrap.vue';
- import UpgradeDialog from '../dialogs/UpgradeDialog.vue';
- import VillageGallery from '../components/VillageGallery.vue';
- import WxButton from '@/components/basic/WxButton.vue';
- import Height from '@/components/layout/space/Height.vue';
- import IconButton from '@/components/basic/IconButton.vue';
- import Button from '@/components/basic/Button.vue';
- import BubbleTip from '@/components/feedback/BubbleTip.vue';
- import MemoryTimeOut from '@/components/composeabe/MemoryTimeOut';
- import TextEllipsis from '@/components/display/TextEllipsis.vue';
- import { confirm, toast } from '@/components/dialog/CommonRoot';
- import { useGetNotice } from '../composeabe/GetNotice';
- import OfficialApi from '@/api/light/OfficialApi';
- const authStore = useAuthStore();
- const { getIsVolunteer } = useUserTools();
- const { requireLogin } = useRequireLogin();
- const { onPublishSuccess } = useOfficialAccount(() => {
- return {
- villageId: villageStore.currentVillage?.id ?? 0,
- userId: authStore.userId,
- tag: recommendTagName.value,
- };
- });
- const { isFollowed, onFollow, onUnFollow } = useFollow();
- const villageStore = useVillageStore();
- const { getIsJoinedVillage } = useUserTools();
- const isOfficialEmpty = ref(false);
- const isJoined = ref(false);
- const villageInfoLoader = useSimpleDataLoader(async () => {
- const village = villageStore.currentVillage;
- try {
- if (village)
- isJoined.value = await getIsJoinedVillage(village.id);
- } catch {
- isJoined.value = false;
- }
- handleShowFollowTip();
- isOfficialEmpty.value = false;
- setTimeout(() => {
- handleManageFollowTip();
- }, 3000);
- return {
- title: village?.name || '',
- desc: village?.desc || '',
- address: village?.address,
- sizeText: village?.storageLimit || 0,
- level: village?.level.toString() || '',
- levelText: village?.levelText || '',
- rankText: village?.rank.toString() || '',
- light: village?.light || 0,
- memberCount: village?.volunteerCount || 0,
- followerCount: village?.followCount || 0,
- images: village?.images || [],
- longitude: village?.longitude || 0,
- latitude: village?.latitude || 0,
- };
- });
- const emit = defineEmits<{
- (e: 'goTree'): void;
- (e: 'goJoin'): void;
- }>();
- const rankActiveTag = ref('文化积分');
- const listActiveTag = ref('广场');
- const villageUserRankListLoader = useSimpleDataLoader(async () => {
- const res = (await LightVillageApi.getVolunteerRankList({
- num: 3,
- village_id: villageStore.currentVillage?.id ?? undefined,
- }))
- .map((item, i) => ({
- id: item.id,
- image: item.image ?? '',
- title: item.name,
- rank: i + 1,
- score: item.points,
- }));
- if (res.length >= 3) {
- //移动第一名到中间
- const first = res[0];
- ArrayUtils.removeAt(res, 0);
- ArrayUtils.insert(res, 1, first);
- }
- return res
- });
- const showFollowTipTimeout = new MemoryTimeOut('FollowTip', 1000 * 3600);//1h
- const showFollowTip = ref(false);
- function handleShowFollowTip() {
- if (!isFollowed.value && showFollowTipTimeout.isTimeout()) {
- showFollowTip.value = true;
- }
- }
- function handleCloseFollowTip() {
- showFollowTipTimeout.recordTime();
- }
- const showManageTipTimeout = new MemoryTimeOut('VillageManageTip', 1000 * 3600 * 20);//30h
- const showManageTip = ref(false);
- function handleManageFollowTip() {
- if (showManageTipTimeout.isTimeout() && !isOfficialEmpty.value)
- showManageTip.value = true;
- }
- function handleCloseManageTip(goComp: boolean) {
- showManageTipTimeout.recordTime();
- }
- watch(rankActiveTag, () => {
- villageUserRankListLoader.reload();
- });
- const recommendTagName = computed(() => {
- return '亮乡源·' + villageInfoLoader.content.value?.title + '·' + listActiveTag.value;
- });
- function handleGoJoin() {
- if (isJoined.value)
- return;
- emit('goJoin');
- }
- function handleGoNew() {
- navTo('/pages/article/common/list', {
- modelId: 18,
- mainBodyColumnId: 356,
- title: '新手上路',
- });
- }
- function handleGoCollect(collectModuleId?: number, title?: string) {
- if (!collectModuleId) {
- navTo('/pages/dig/details', {
- villageId: villageStore.currentVillage?.id ?? undefined,
- name: villageInfoLoader.content.value?.title,
- });
- return;
- }
- navTo('/pages/dig/forms/list-ordinary', {
- villageId: villageStore.currentVillage?.id ?? undefined,
- collectModuleId: collectModuleId,
- title: title,
- });
- }
- function handleGoPublish() {
- requireLogin(async () => {
- navTo('/pages/home/chat/dependent/post/publish', {
- tag: recommendTagName.value,
- villageId: villageStore.currentVillage?.id ?? undefined,
- });
- }, '登录后以便发布文章使用更多功能哦!');
- }
- function handleGoGallery() {
- navTo('/pages/home/village/gallery/index', {
- villageId: villageStore.currentVillage?.id ?? 0 ,
- maxCount: villageStore.currentVillage?.imageLimit || 3,
- });
- }
- async function handleGoOfficalManage() {
- assertNotNull(villageStore.currentVillage?.id)
- const isAdmin = await OfficialApi.checkTopicRule(villageStore.currentVillage.id);
- if (!isAdmin) {
- const goUpgrade = await confirm({
- title: '提示',
- content: '您还不是管理员,无法管理贴图哦。您可以联系村社管理员将你添加为管理员,若当前村社暂无管理员,您可以点击“去升级”将您升级为管理员。',
- confirmText: '去升级',
- cancelText: '取消',
- });
- if (goUpgrade) {
- navTo('/pages/home/village/upgrade/my-upgrade-management', {
- villageId: villageStore.currentVillage.id,
- });
- }
- return;
- }
- navTo('/pages/home/village/post/management-list', {
- villageId: villageStore.currentVillage.id,
- topic: recommendTagName.value,
- });
- }
- async function handleGoDigManage() {
- assertNotNull(villageStore.currentVillage?.id)
- const isAdmin = (authStore.isAdmin || await OfficialApi.checkTopicRule(villageStore.currentVillage.id));
- if (!isAdmin) {
- const goUpgrade = await confirm({
- title: '提示',
- content: '您还不是管理员,您可以联系村社管理员将你添加为管理员,若当前村社暂无管理员,您可以点击“去升级”将您升级为管理员。',
- confirmText: '去升级',
- cancelText: '取消',
- });
- if (goUpgrade) {
- navTo('/pages/home/village/upgrade/my-upgrade-management', {
- villageId: villageStore.currentVillage.id,
- });
- }
- return;
- }
- navTo('/pages/dig/details', {
- name: villageStore.currentVillage.title,
- villageId: villageStore.currentVillage.id,
- });
- }
- const { currentNoticeContent, noticeListLoader } = useGetNotice(() => villageStore.currentVillage?.id || 0);
- const upgradeRef = ref<InstanceType<typeof UpgradeDialog>>();
- const villageGalleryRef = ref<InstanceType<typeof VillageGallery>>();
- watch(() => villageStore.currentVillage, async () => {
- await waitTimeOut(100);
- await villageInfoLoader.reload();
- await waitTimeOut(100);
- await villageUserRankListLoader.reload();
- await waitTimeOut(100);
- await noticeListLoader.reload();
- }, { immediate: true });
- defineExpose({
- onPageBack: (name: string, data: Record<string, unknown>) => {
- if (name === 'refreshVillageGrallery') {
- villageGalleryRef.value?.refresh();
- } else if (name === 'showVillageUpgrade') {
- upgradeRef.value?.show();
- } else if (name === 'refreshOfficialAccount') {
- const tag = listActiveTag.value;
- listActiveTag.value = '';
- setTimeout(() => listActiveTag.value = tag, 100);
- }
- },
- });
- </script>
|