<template>
	<view class="container">
		<view class="content">
			<view class="title">
				{{ articleInfo.Title }}
			</view>
			<view class="info_row_1 displayFlexRow">
				<view class="source-type">
					{{ articleInfo.SourceType == 1 ? '原创' : '转载' }}
				</view>
				<view class="author">
					{{ articleInfo.Author }}
				</view>
				<view class="dept_name">
					<text v-for="item in articleInfo.Depts" :key="item.Key">{{ item.Value }}</text>
				</view>
				<view>
					{{ articleInfo.PublishTime }}
				</view>
			</view>
			<view class="mt-20">
				<text>分类：</text>
				<text
					class="tag"
					v-for="(item, index) in articleInfo.ArticleTypeList"
					:key="index"
					catchtap="toList"
					data-param-value="{{item.Id}}"
					data-param-name="TypeId"
					data-param-label="{{item.Title}}"
				>
					#{{ item.Title }}
				</text>
			</view>
			<view class="mt-20">
				<text>标签：</text>
				<text
					class="tag"
					v-for="(item, index) in articleInfo.Diseases"
					:key="index"
					catchtap="toList"
					data-param-value="{{item.Key}}"
					data-param-name="DiseaseId"
					data-param-label="{{item.Value}}"
				>
					#{{ item.Value }}
				</text>
				<text
					class="tag"
					v-for="(item, index) in articleInfo.Tags"
					:key="index"
					catchtap="toList"
					data-param-value="{{item.Key}}"
					data-param-name="TagId"
					data-param-label="{{item.Value}}"
				>
					#{{ item.Value }}
				</text>
			</view>
			<view class="description">
				{{ articleInfo.Description }}
			</view>
			<view>
				<mp-html
					v-if="articleInfo.ContentType != 1"
					:domain="domain"
					:content="articleInfo.Content"
					:token="token"
				></mp-html>
			</view>
			<view class="source_row" v-if="articleInfo.SourceType == 2">
				<view class="source"> 本文来自【{{ articleInfo.OriginalSource }}】 </view>
				<view
					v-if="articleInfo.OriginalLink != ''"
					class="to_source"
					data-url="{{articleInfo.OriginalLink}}"
					bindtap="toSource"
				>
					阅读原文
				</view>
			</view>
			<view class="data-bar">
				<text> 阅读：{{ articleInfo.SeeCount }} </text>
				<view class="data-bar-btn">
					<view @click="like">
						<image
							:src="articleInfo.MyLike ? icon.article_like_active : icon.article_like"
							class="icon_like"
						/>
						{{ articleInfo.LikeCount > 999 ? '999+' : articleInfo.LikeCount || 0 }}
					</view>
					<view>
						<image :src="icon.article_share" class="icon_share" />
						<button
							class="share no-margin no-padding"
							open-type="share"
							style="font-weight: 400; font-size: 28rpx"
						>
							去分享
						</button>
					</view>
				</view>
			</view>
			<!-- 文章评论列表 -->
			<block v-if="articleInfo.EnableComment">
				<view class="comment-box">
					<view style="display: flex; justify-content: space-between">
						<text>评论 {{ commentCount }}</text>
						<text
							v-if="commentList.length > 0"
							style="color: var(--uni-color-primary)"
							@click="toComment"
						>
							我要评论
						</text>
					</view>
					<view
						v-if="commentLoad && commentList.length == 0"
						style="text-align: center; margin-top: 30rpx"
					>
						<text>暂无评论</text>
						<text style="color: var(--uni-color-primary)" @click="toComment">我要评论</text>
					</view>
					<block v-if="commentList.length > 0">
						<view v-for="item in commentList" class="comment-list" :key="item.Id">
							<view class="comment-item" W>
								<text class="comment-member-name">{{ item.MemberName }}</text>
								<text class="comment-time">{{ item.CreateTime }}</text>
							</view>
							<view style="margin-right: 40rpx">
								<zy-rate :max="5" :score="item.Score" :size="20" disabled></zy-rate>
							</view>
						</view>
					</block>
				</view>
			</block>
			<!-- 快捷服务悬浮窗 -->
			<view
				@touchstart="serviceDialogTouchStart"
				@touchmove="serviceDialogTouchMove"
				@touchend="serviceDialogTouchEnd"
				class="article-convenient-service-list"
				id="service-float"
				:style="
					serviceDialogXY.x !== null && serviceDialogXY.y !== null
						? { left: serviceDialogXY.x + 'px', top: serviceDialogXY.y + 'px', bottom: 'auto' }
						: { left: '25px', bottom: '100px' }
				"
				v-if="showConvenientServices"
			>
				<block v-for="(item, field) in convenientServices">
					<view
						v-if="item.show"
						class="article-convenient-service-item"
						style="display: flex; align-items: center"
						:data-service="field"
						@click="toServicePage"
					>
						<image :src="item.icon" style="width: 40rpx; height: 40rpx; margin-right: 10rpx" />
						<text>{{ item.title }}</text>
					</view>
				</block>
			</view>
			<!-- 文章评价弹窗 -->
			<zy-half-screen-dialog
				height="25%"
				extClass="zy_half_screen_dialog"
				v-model:show="articleCommentDialogVisible"
				maskClosable
			>
				<view class="zy_half_screen_dialog_content">
					<text>对文章进行评价</text>
					<view style="display: flex; justify-content: space-between; margin-top: 50rpx">
						<zy-rate :max="5" v-model:score="commentScore" :size="20"></zy-rate>
						<view style="width: 200rpx !important">
							<button
								class="comment_btn"
								:disabled="commentCommiting || commentScore == 0"
								@click="commitComment"
							>
								确定
							</button>
						</view>
					</view>
				</view>
			</zy-half-screen-dialog>
		</view>
	</view>
</template>

<script lang="ts" setup>
import { ref, computed, reactive, getCurrentInstance, watch, nextTick } from 'vue';
import { onShareAppMessage, onShareTimeline, onReachBottom } from '@dcloudio/uni-app';
import { useOnLoad, useDomain, useGetMember, useIsToAuthPage, useGetDefaultMember } from '@/hook';
import { mapState, mapMutations } from '@kasite/uni-app-base/store';
import {
	ArticleDetail,
	ShareArticle,
	LikeArticle,
	GetCommentList,
	CreateComment,
} from '../../../service';
import ZyHalfScreenDialog from '../../../components/half-screen-dialog/index.vue';
import ZyRate from '../../../components/rate/index.vue';
import icon from '@/utils/icon';
import { common, menuClick } from '@/utils';

const app = getApp();

const domain = useDomain();
const { token, currentUser } = mapState({
	token: 'token',
	currentUser: 'currentUser',
});
const { setCurrentUser } = mapMutations({
	setCurrentUser: 'setCurrentUser',
});
const id = ref();
const _msgUUID = ref();
const articleInfo = ref({} as any);
const commentList = ref([]);
const commentCount = ref(0);
const commentLoad = ref(false);
const _commentPage = reactive({
	PIndex: 1,
	PSize: 10,
});
const isLastPage = ref(false);
const convenientServices = ref({
	DoctorVideocons: {
		title: '视频问诊',
		show: false,
		pagePath: '',
		icon: icon.article_video_cons,
	},
	DoctorServiceCons: {
		title: '图文咨询',
		show: false,
		pagePath: '',
		icon: icon.article_service_cons,
	},
	DoctorServiceGh: {
		title: '预约挂号',
		show: false,
		pagePath: '',
		icon: icon.article_service_gh,
	},
});
const doctorDeptList = ref([]);
const showConvenientServices = ref(false);
const articleCommentDialogVisible = ref(false);
const commentScore = ref(0);
const commentCommiting = ref(false);
const serviceDialogXY = reactive({
	x: 25,
	y: null as number | null,
});

// 悬浮窗拖动数据与方法
const instance = getCurrentInstance();
const serviceDrag = reactive({
	dragging: false,
	startX: 0,
	startY: 0,
	elemW: 0,
	elemH: 0,
	winW: uni.getSystemInfoSync().windowWidth,
	winH: uni.getSystemInfoSync().windowHeight,
});

const measureServiceFloat = () => {
	return new Promise<void>((resolve) => {
		uni
			.createSelectorQuery()
			.in(instance?.proxy as any)
			.select('#service-float')
			.boundingClientRect((rect) => {
				if (rect) {
					serviceDrag.elemW = rect.width || 0;
					serviceDrag.elemH = rect.height || 0;
					// 首次测量时如果还未设置 y，则用当前 rect.top 作为初始 top
					if (serviceDialogXY.y === null) {
						serviceDialogXY.x = rect.left || serviceDialogXY.x;
						serviceDialogXY.y = rect.top || 0;
					}
				}
				resolve();
			})
			.exec();
	});
};

// 首次显示悬浮窗时，基于默认 bottom:200px 计算等价的 top，避免首次触摸从 bottom 切换到 top 产生位移
watch(showConvenientServices, async (val) => {
	if (!val) return;
	await nextTick();
	uni
		.createSelectorQuery()
		.in(instance?.proxy as any)
		.select('#service-float')
		.boundingClientRect((rect) => {
			if (!rect) return;
			serviceDrag.elemW = rect.width || 0;
			serviceDrag.elemH = rect.height || 0;
			if (serviceDialogXY.y === null) {
				// 将默认的 bottom:200px 转换为 top 值，保持视觉位置不变
				const topY = Math.max(0, serviceDrag.winH - (rect.height || 0) - 100);
				serviceDialogXY.x = serviceDialogXY.x ?? 25;
				serviceDialogXY.y = topY;
			}
		})
		.exec();
});

const clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));

function serviceDialogTouchStart(e: any) {
	serviceDrag.dragging = true;
	const touch = e.touches && e.touches[0];
	if (!touch) return;
	serviceDrag.startX = touch.pageX;
	serviceDrag.startY = touch.pageY;
	measureServiceFloat();
}

function serviceDialogTouchMove(e: any) {
	if (!serviceDrag.dragging) return;
	// 阻止页面滚动
	if (e && typeof e.preventDefault === 'function') e.preventDefault();
	if (e && typeof e.stopPropagation === 'function') e.stopPropagation();
	const touch = e.touches && e.touches[0];
	if (!touch) return;
	const dx = touch.pageX - serviceDrag.startX;
	const dy = touch.pageY - serviceDrag.startY;
	let nextX = serviceDialogXY.x + dx;
	let nextY = (serviceDialogXY.y ?? 0) + dy;
	nextX = clamp(nextX, 0, Math.max(0, serviceDrag.winW - serviceDrag.elemW));
	nextY = clamp(nextY, 0, Math.max(0, serviceDrag.winH - serviceDrag.elemH));
	serviceDialogXY.x = nextX;
	serviceDialogXY.y = nextY;
	serviceDrag.startX = touch.pageX;
	serviceDrag.startY = touch.pageY;
}

function serviceDialogTouchEnd() {
	serviceDrag.dragging = false;
}

/** 获取文章详情 */
const getArticleDetail = async () => {
	const { resp } = await ArticleDetail({
		Id: id.value,
		Uuid: _msgUUID.value,
	});
	if (resp && resp.length) {
		const info = resp[0];
		const content = unescape(info.Content);
		info.Content = content;
		info.PublishTime = formatDate2(info.PublishTime);
		let articleConvenientServices = info.Config?.ConvenientServices || {};
		if (articleConvenientServices) {
			for (const field in articleConvenientServices) {
				convenientServices.value[field].show = articleConvenientServices[field].Checked;
			}
		}
		articleInfo.value = info;
		doctorDeptList.value = info.DoctorInfo?.DoctorInfo || [];
		setConvenientServices();
	}
};
/** 格式化日期 */
const formatDate2 = (date) => {
	if (!date) {
		return '';
	}
	return date.substring(5, 16);
};
const setConvenientServices = () => {
	showConvenientServices.value =
		Object.keys(convenientServices.value).find((field) => {
			return convenientServices.value[field]?.show === true;
		}) != undefined;
};
/** 点赞 */
const like = async () => {
	const { Id: id, MyLike: like = false } = articleInfo.value;
	if (like) {
		common.showModal('已点赞');
	} else {
		const res = await LikeArticle({ Id: id });
		if (res.resData.RespCode === '10000') {
			// 点赞成功
			articleInfo.value.MyLike = true;
			articleInfo.value.LikeCount++;
		}
	}
};
/** 获取评论 */
const getCommentList = async (page) => {
	const res = await GetCommentList({
		ArticleId: id.value,
		Page: page,
		IsShow: 1,
	});
	const { PCount = 0 } = res.resData?.Page;
	commentCount.value = PCount;
	commentLoad.value = true;
	if (PCount <= _commentPage.PSize) {
		isLastPage.value = true;
	}
	return res.resp || [];
};
const refershCommentList = async () => {
	_commentPage.PIndex = 1;
	const list = await getCommentList(_commentPage);
	commentList.value = list;
};
const loadCommentListNextPage = async () => {
	_commentPage.PIndex += 1;
	isLastPage.value = false;
	const list = await getCommentList(_commentPage);
	if (list.length < _commentPage.PSize) {
		isLastPage.value = true;
	}
	commentList.value.push(...list);
	return commentList;
};

const toComment = () => {
	if (!currentUser.value) {
		uni.showToast({
			title: '请先添加就诊人',
			icon: 'none',
		});
		return;
	}
	articleCommentDialogVisible.value = true;
};
/** 提交评论 */
const commitComment = async () => {
	commentCommiting.value = true;
	try {
		const params = {
			ArticleId: id.value,
			score: commentScore.value,
			MemberId: currentUser.value.memberId,
			MemberName: currentUser.value.memberName,
		};
		const res = await CreateComment(params);
		if (res.resData.RespCode !== '10000') {
			uni.showToast({
				title: res.resData.RespMessage,
				icon: 'error',
			});
		} else {
			uni.showToast({
				title: '评论成功',
			});
			articleCommentDialogVisible.value = false;
			isLastPage.value = false;
			commentScore.value = 0;
			refershCommentList();
		}
	} catch (error) {
		uni.showToast({
			title: '评论失败',
			icon: 'error',
		});
	} finally {
		commentCommiting.value = false;
	}
};

const toServicePage = (e) => {
	const service = e.currentTarget.dataset.service;

	if (service === 'DoctorServiceCons') {
		uni.showActionSheet({
			alertText: '请选择科室',
			itemList: articleInfo.value.DoctorInfo?.DoctorInfo?.map((item) => item.DeptName) || [],
			success: ({ tapIndex }) => {
				const doctorInfo = articleInfo.value.DoctorInfo.DoctorInfo[tapIndex];
				// 图文咨询
				const queryBean = common.stringify(doctorInfo);
				const url = `/pagesNetHos/st1/business/doctor/supplement/supplement?queryBean=${queryBean}&selectedType=twzx`;
				let data = {
					Url: url,
				};
				menuClick(data, this);
			},
		});
	} else if (service === 'DoctorVideocons') {
		uni.showActionSheet({
			alertText: '请选择科室',
			itemList: articleInfo.value.DoctorInfo?.DoctorInfo?.map((item) => item.DeptName) || [],
			success: ({ tapIndex }) => {
				const doctorInfo = articleInfo.value.DoctorInfo.DoctorInfo[tapIndex];
				const queryBean = common.stringify(doctorInfo);
				const url = `/pagesNetHos/st1/business/doctor/supplement/supplement?queryBean=${queryBean}&selectedType=spzx`;
				let data = {
					Url: url,
				};
				menuClick(data, this);
			},
		});
	} else if (service === 'DoctorServiceGh') {
		const doctorInfo = articleInfo.value.DoctorInfo.DoctorInfo[0];
		handleRouter(
			{
				DoctorId: doctorInfo.DoctorId,
				DoctorCode: doctorInfo.DoctorCode,
				DoctorName: doctorInfo.DoctorName,
				DoctorUid: doctorInfo.DoctorUid,
				HosId: doctorInfo.HosId,
			},
			'yyghClinicMsg',
			0
		);
	} else {
		// 服务未开通
		console.error('服务未开通');
	}
};
const handleRouter = async (queryBean, page, serviceId, selectedIndex) => {
	app.globalData.queryBean = queryBean;
	let url = `/pagesPatient/st1/business/yygh/${page}/${page}?serviceId=${serviceId || 0}`;
	if (selectedIndex != undefined) {
		url = url + `&selectedIndex=${selectedIndex}`;
	}
	if (page == 'yyghClinicMsg') {
		/**跳转到挂号页面 需要判断就诊人 和公众号授权*/
		if (useIsToAuthPage()) {
			return;
		}
		// 获取当前设置的患者信息 判断是否可以无卡预约 取不同的值允许无卡预约或者默认就诊人信息 否者获取就诊卡信息，如当前默认就诊人无就诊卡，跳转选卡界面
		let lastOperatorResp = await useGetDefaultMember({
			cardType: app.globalData.withoutCard ? '' : '1',
			url: url,
			isKeepPage: true,
		});
		// 判断返回的操作人为null 代表跳转选择界面了
		if (lastOperatorResp === null) return;
		if (common.isEmpty(lastOperatorResp)) {
			app.globalData.toUrl = url; //保存添加成功后跳转地址
			app.globalData.cardType = app.globalData.withoutCard ? '' : '1'; //保存添加成功，要查询的默认人信息
			url = `/pagesPersonal/st1/business/patientManagement/addMember/addMember`;
		}
	}
	common.goToUrl(url);
};

useOnLoad((options) => {
	if (uni.onCopyUrl) {
		uni.onCopyUrl(() => {
			ShareArticle({ Id: id.value, OptType: 'copy_url' });
			return { query: `id=${options.id}` };
		});
	}
	id.value = options.id;
	_msgUUID.value = options.msgId || null;
	getArticleDetail();
	refershCommentList();
	if (common.isEmpty(currentUser.value)) {
		useGetMember('defaultInfo').then((data) => {
			setCurrentUser(data);
		});
	}
});
onReachBottom(() => {
	if (!isLastPage.value) {
		loadCommentListNextPage();
	}
});
/** 转发 */
onShareAppMessage(() => {
	ShareArticle({ Id: id.value, OptType: 'send' });
	return {
		title: articleInfo.value.Title,
		path: `/pagesAdmin/article/business/article/detail/detail?id=${id.value}`,
	};
});
/** 分享到朋友圈 */
onShareTimeline(() => {
	ShareArticle({ Id: id.value, OptType: 'share' });
	return {
		title: articleInfo.value.Title,
	};
});
</script>

<style lang="scss" scoped>
page {
	height: auto !important;
}
view.content {
	padding: 60rpx 30rpx 120rpx 30rpx;
	background-color: #ffffff;
}
.container view {
	overflow: visible;
}
.title {
	font-size: 36rpx;
	color: #222326;
	font-weight: 600;
	line-height: 1.2em;
}
.info_row_1 {
	margin-top: 26rpx;
	justify-content: start;
	flex-wrap: wrap;
}
.info_row_1 > view {
	font-size: 26rpx;
	color: #8a8a99;
	margin-right: 20rpx;
	flex: 0 0 auto;
}
.info_row_1 > view:first-of-type {
	padding-left: 0;
}
.source-type {
	background-color: #169bd5;
	color: #ffffff !important;
	padding: 10rpx 20rpx !important;
	display: inline-block;
	border-radius: 8rpx;
}
.dept_name {
	display: flex;
	flex-wrap: wrap;
	max-width: 100%;
}
.dept_name text:not(:last-of-type):after {
	content: '、';
}
.info_row_2 {
	margin-top: 36rpx;
	justify-content: start;
}
.info_row_2 > view {
	border-radius: 6rpx;
	border: #e8e9f0 solid 1px;
	color: #8a8a99;
	font-size: 22rpx;
	padding: 8rpx 12rpx;
	margin-right: 12rpx;
}
.description {
	font-size: 30rpx;
	color: #43434a;
	text-indent: 2em;
	margin: 40rpx 0;
	padding-bottom: 40rpx;
	border-bottom: #e6e6e6 solid 1rpx;
	line-height: 1.5em;
}
.source_row {
	margin: 30rpx 0;
	display: flex;
	font-size: 28rpx;
}
.to_source {
	color: var(--uni-color-primary);
}
.like_count {
	position: relative;
	z-index: 1001;
	font-size: 20rpx;
	color: #ffffff;
	background-color: var(--auxiliaryColor);
	padding: 0.3em;
	min-width: 3em;
	border-radius: 1em;
	border-bottom-left-radius: 0;
	margin-top: -20rpx;
	margin-left: -20rpx;
	margin-bottom: 20rpx;
}
.icon_like,
.icon_share {
	width: 32rpx;
	height: 32rpx;
	margin-right: 14rpx;
	flex: 0 0 auto;
}
.wxParse-p {
	line-height: 1.5em;
}
.data-bar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-top: 40rpx;
}
.data-bar-btn {
	display: flex;
	align-items: center;
}
.data-bar-btn view {
	display: flex;
	align-items: center;
	margin-left: 30rpx;
}
.zy_half_screen_dialog_content {
	padding: 50rpx 50rpx 0;
}
.comment-box {
	margin-top: 60rpx;
}
.comment-list {
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	margin-top: 32rpx;
}
.comment-item {
	display: flex;
	flex-direction: column;
}
.comment-member-name {
	padding-bottom: 16rpx;
}
.comment-time {
	color: #888888;
	font-size: 24rpx;
}
.tag {
	color: var(--uni-color-primary);
	display: inline-block;
	margin-right: 20rpx;
}
.article-convenient-service-list {
	position: fixed;
	background-color: #000000b0;
	padding: 24rpx 24rpx;
	border-radius: 12rpx;
	font-size: 28rpx;
	color: #ffffff;
	/* 允许手势穿透边缘位置，提升拖拽体验 */
	z-index: 9999;
}
.article-convenient-service-item {
	margin-bottom: 20rpx;
}
.article-convenient-service-item:last-of-type {
	margin-bottom: 0rpx;
}
.share::after {
	border: none;
}
.comment_btn {
	background: var(--uni-color-primary);
	color: var(--uni-color-white);
	height: 24px;
	line-height: 24px;
}
</style>
