喵你个旺呀 1 год назад
Родитель
Сommit
109bccef06

+ 75 - 0
Web/src/components/callTel/callBar.vue

@@ -0,0 +1,75 @@
+<script lang="ts" setup>
+import { nextTick, onMounted, ref } from "vue";
+import QRCode from 'qrcodejs2-fixes';
+
+// 组件属性
+const props = defineProps({
+	realName: String,
+	number: String,
+	callbackUrl: String,
+	callbackData: String,
+  needToken: Boolean,
+});
+
+// 定义变量内容
+const qrcodeRef = ref<HTMLElement | null>(null);
+
+// 初始化生成二维码
+const initQrcode = () => {
+	nextTick(() => {
+		const token = props.needToken ? Local.get(accessTokenKey) : '';
+		const code = encodeURIComponent(JSON.stringify({
+			realName: props.realName,
+			number: props.number,
+			callbackUrl: props.callbackUrl,
+			callbackData: props.callbackData
+		}));
+		let url = `${location.origin}/$callTel#/$callTel?code=${encodeURIComponent(code)}&token=${encodeURIComponent(token)}`;
+		(<HTMLElement>qrcodeRef.value).innerHTML = '';
+		new QRCode(qrcodeRef.value, {
+			text: url,
+			width: 260,
+			height: 260,
+			colorDark: '#000000',
+			colorLight: '#ffffff',
+		});
+	});
+};
+
+// 拨打电话
+const callTel = () => {
+	location.href = 'tel:' + props.number;
+}
+
+// 页面加载时
+onMounted(() => {
+	initQrcode();
+});
+</script>
+
+<template>
+	<el-popover placement="bottom" width="300" trigger="hover">
+		<template #reference>
+			<i class="iconfont icon-dianhua" v-bind="$attrs" />
+		</template>
+		<el-descriptions direction="vertical" :column="1" border>
+			<el-descriptions-item align="center">
+				<template #label>
+					<el-button @click="callTel">直接拨打</el-button>
+				</template>
+			</el-descriptions-item>
+			<el-descriptions-item width="140" align="center">
+				手机扫一扫
+				<template #label>
+					<div ref="qrcodeRef" />
+				</template>
+			</el-descriptions-item>
+		</el-descriptions>
+	</el-popover>
+</template>
+
+<style scoped lang="scss">
+.call-bar-container {
+	display: flex;
+}
+</style>

+ 121 - 0
Web/src/components/callTel/index.vue

@@ -0,0 +1,121 @@
+<template>
+	<div class="page-container">
+		<!-- 姓名和号码部分 -->
+		<div class="name-number" v-if="state.data">
+			<span class="name">{{ state.data.realName }}</span>
+			<span class="spacing"></span> <!-- 新增的间距元素 -->
+			<span class="number">{{ state.data.number }}</span>
+		</div>
+		<!-- 头像容器 -->
+		<div class="avatars">
+			<!-- 绿色头像 -->
+			<div class="avatar-wrap green-icon-wrap" @click="handleClick(true)" v-reclick="1000">
+				<el-avatar :size="100" class="icon green-icon">
+					<i class="iconfont icon-dianhua"></i>
+				</el-avatar>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script lang="ts" name="callTel" setup>
+import { reactive, onMounted } from "vue";
+import { useRoute } from "vue-router";
+const route = useRoute();
+
+const state = reactive({
+	token: null as any,
+	data: {} as any
+});
+
+// 页面初始化
+const initializePage = () => {
+	state.data = JSON.parse(decodeURIComponent(route.query.code || '{}' as any));
+	state.token = route.query.token;
+};
+
+onMounted(() => {
+	initializePage();
+});
+
+// 点击事件
+const handleClick = (success: boolean) => {
+	if (success) location.href = 'tel:' + state.data.number;
+};
+</script>
+
+<style lang="scss" scoped>
+/* 样式保持不变 */
+.page-container {
+	display: flex;
+	flex-direction: column;
+	justify-content: flex-start; /* 使用flex-start而不是center以控制垂直对齐 */
+	align-items: center; /* 水平居中 */
+	height: 100vh;
+	padding-top: calc(100vh * (1 - 1/1.618)); /* 使用黄金分割比例计算顶部内边距 */
+}
+
+.name-number {
+	text-align: center;
+	margin-bottom: 20px; /* 添加与头像之间的间距 */
+	.name {
+		font-weight: bold;
+		font-size: 24px; /* 增大字体大小 */
+	}
+
+	.spacing {
+		display: block;
+		height: 10px; /* 设置间距的高度 */
+	}
+
+	.number {
+		font-size: 20px; /* 增大字体大小 */
+		color: #a09e9e; /* 更改号码颜色为指定的浅灰色 */
+		font-weight: 600; /* 加粗字体 */
+	}
+}
+
+.avatars {
+	display: flex;
+	justify-content: center; /* 使子元素(绿色头像)水平居中 */
+	gap: 40px; /* 增加头像之间的间距 */
+	.avatar-wrap {
+		cursor: pointer;
+		transition: background-color 0.2s, transform 0.2s;
+	}
+
+	.avatar-wrap:hover .icon {
+		filter: brightness(90%); /* 鼠标悬停时稍微变暗 */
+	}
+
+	.avatar-wrap:active .icon {
+		filter: brightness(80%); /* 点击时更明显地变暗 */
+		transform: scale(0.94); /* 点击时轻微缩小 */
+	}
+
+	.icon {
+		color: white;
+		transition: filter 0.2s, transform 0.2s;
+	}
+
+	.iconfont {
+		font-size: 70px;
+	}
+
+	.green-icon {
+		background-color: lawngreen;
+	}
+
+	.red-icon {
+		background-color: red;
+	}
+
+	.green-icon-wrap .icon {
+		background-color: lawngreen;
+	}
+
+	.red-icon-wrap .icon {
+		background-color: red;
+	}
+}
+</style>

+ 8 - 0
Web/src/router/route.ts

@@ -118,6 +118,14 @@ export const staticRoutes: Array<RouteRecordRaw> = [
 			title: '登录',
 			isPublic: true,
 		},
+	},{
+		path: '/$callTel',
+		name: '$callTel',
+		component: () => import('/@/components/callTel/index.vue'),
+		meta: {
+			title: '拨号',
+			isPublic: true,
+		},
 	},
 	/**
 	 * 提示:写在这里的为全屏界面,不建议写在这里

+ 6 - 1
Web/src/views/system/user/index.vue

@@ -42,7 +42,11 @@
 						<el-table-column prop="account" label="账号" width="120" align="center" show-overflow-tooltip />
 						<!-- <el-table-column prop="nickName" label="昵称" width="120" align="center" show-overflow-tooltip /> -->
 						<el-table-column prop="realName" label="姓名" width="120" align="center" show-overflow-tooltip />
-						<el-table-column prop="phone" label="手机号码" width="120" align="center" show-overflow-tooltip />
+						<el-table-column prop="phone" label="手机号码" width="120" align="center" show-overflow-tooltip>
+							<template #default="scope">
+								{{scope.row.phone}} <call-bar :real-name="scope.row.realName" :number="scope.row.phone" :callback-url="'123'" />
+							</template>
+						</el-table-column>
 						<!-- <el-table-column label="出生日期" width="100" align="center" show-overflow-tooltip>
 							<template #default="scope">
 								{{ formatDate(new Date(scope.row.birthday), 'YYYY-mm-dd') }}
@@ -116,6 +120,7 @@ import { ElMessageBox, ElMessage } from 'element-plus';
 import OrgTree from '/@/views/system/org/component/orgTree.vue';
 import EditUser from '/@/views/system/user/component/editUser.vue';
 import ModifyRecord from '/@/components/table/modifyRecord.vue';
+import CallBar from '/@/components/callTel/callBar.vue';
 import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 import { getAPI } from '/@/utils/axios-utils';