Compare commits
2 Commits
6f0d10b881
...
676b213a7d
| Author | SHA1 | Date | |
|---|---|---|---|
| 676b213a7d | |||
| 600684570a |
@@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="zh">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
|||||||
334
my-vue-app/src/components/FeedbackForm.vue
Normal file
334
my-vue-app/src/components/FeedbackForm.vue
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="isVisible" class="modal-overlay" @click="closeModal">
|
||||||
|
<div class="modal-container" @click.stop>
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>意见反馈</h3>
|
||||||
|
<button class="modal-close-btn" @click="closeModal">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="feedback-form-container">
|
||||||
|
<h2>意见反馈</h2>
|
||||||
|
<p class="subtitle">我们期待听到您的声音,不断改进我们的产品。</p>
|
||||||
|
|
||||||
|
<!-- 提交成功或失败的提示信息 -->
|
||||||
|
<div v-if="submitStatus === 'success'" class="feedback-message success">
|
||||||
|
✓ 感谢您的反馈!我们已经收到您的宝贵意见。
|
||||||
|
</div>
|
||||||
|
<div v-if="submitStatus === 'error'" class="feedback-message error">
|
||||||
|
✗ 提交失败,请检查网络或稍后重试。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form v-if="submitStatus !== 'success'" @submit.prevent="handleSubmit">
|
||||||
|
<!-- 反馈类型 -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="feedback-type">反馈类型</label>
|
||||||
|
<select id="feedback-type" v-model="formData.type">
|
||||||
|
<option>功能建议</option>
|
||||||
|
<option>界面优化</option>
|
||||||
|
<option>Bug 反馈</option>
|
||||||
|
<option>其他</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 反馈内容 -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="feedback-content">反馈内容 (必填)</label>
|
||||||
|
<textarea
|
||||||
|
id="feedback-content"
|
||||||
|
v-model="formData.content"
|
||||||
|
placeholder="请详细描述您的问题或建议..."
|
||||||
|
rows="6"
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<!-- 提交按钮 -->
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" :disabled="isSubmitting">
|
||||||
|
<span v-if="isSubmitting">正在提交...</span>
|
||||||
|
<span v-else>提交反馈</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
|
||||||
|
// 定义组件的props
|
||||||
|
const props = defineProps({
|
||||||
|
isVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 定义组件要触发的事件
|
||||||
|
const emit = defineEmits(['submit-feedback', 'close']);
|
||||||
|
|
||||||
|
// 使用 reactive 创建响应式表单数据对象
|
||||||
|
const formData = reactive({
|
||||||
|
type: '功能建议', // 默认值
|
||||||
|
content: '',
|
||||||
|
contact: '',
|
||||||
|
screenshot: null, // 存储文件对象
|
||||||
|
});
|
||||||
|
|
||||||
|
// ref 用于独立的响应式值
|
||||||
|
const isSubmitting = ref(false); // 是否正在提交
|
||||||
|
const submitStatus = ref(null); // 'success', 'error', or null
|
||||||
|
const imagePreviewUrl = ref(null); // 图片预览 URL
|
||||||
|
const fileInputRef = ref(null); // 用于引用文件输入元素
|
||||||
|
|
||||||
|
// 文件选择变化时的处理函数
|
||||||
|
const handleFileChange = (event) => {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
formData.screenshot = file;
|
||||||
|
// 创建一个临时的 URL 用于图片预览
|
||||||
|
imagePreviewUrl.value = URL.createObjectURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除已选图片
|
||||||
|
const removeImage = () => {
|
||||||
|
formData.screenshot = null;
|
||||||
|
imagePreviewUrl.value = null;
|
||||||
|
// 清空文件输入框的值,以便用户可以再次选择相同的文件
|
||||||
|
if (fileInputRef.value) {
|
||||||
|
fileInputRef.value.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭模态框
|
||||||
|
const closeModal = () => {
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单提交处理函数
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
// 简单验证
|
||||||
|
if (!formData.content.trim()) {
|
||||||
|
alert('反馈内容不能为空!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSubmitting.value = true;
|
||||||
|
submitStatus.value = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 创建 FormData 对象
|
||||||
|
// 获取 token (假设存储在 localStorage 中)
|
||||||
|
const token = localStorage.getItem('token') || '';
|
||||||
|
|
||||||
|
// 发送 POST 请求到后端接口
|
||||||
|
const response = await axios.post('https://mldash.nycjy.cn/api/v1/submit_feedback', {type: formData.type, content: formData.content}, {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('响应状态8888:', response.data.message);
|
||||||
|
// 提交成功
|
||||||
|
submitStatus.value = 'success';
|
||||||
|
// 触发父组件的事件,并传递数据
|
||||||
|
emit('submit-feedback', { ...formData });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('提交反馈失败:', error);
|
||||||
|
// 提交失败
|
||||||
|
submitStatus.value = 'error';
|
||||||
|
} finally {
|
||||||
|
// 请求结束
|
||||||
|
isSubmitting.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
max-width: 600px;
|
||||||
|
width: 90%;
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-bottom: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
color: #1a202c;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #718096;
|
||||||
|
padding: 0;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close-btn:hover {
|
||||||
|
color: #1a202c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-form-container {
|
||||||
|
padding: 2rem;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
text-align: center;
|
||||||
|
color: #1a202c;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
text-align: center;
|
||||||
|
color: #718096;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #4a5568;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid #cbd5e0;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #2d3748;
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"]:focus,
|
||||||
|
select:focus,
|
||||||
|
textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #4299e1;
|
||||||
|
box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="file"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 1rem;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-preview img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-image-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: -10px;
|
||||||
|
right: -10px;
|
||||||
|
background-color: #e53e3e;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[type="submit"] {
|
||||||
|
padding: 0.75rem 2rem;
|
||||||
|
background-color: #4299e1;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[type="submit"]:hover:not(:disabled) {
|
||||||
|
background-color: #3182ce;
|
||||||
|
}
|
||||||
|
|
||||||
|
button[type="submit"]:disabled {
|
||||||
|
background-color: #a0aec0;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-message {
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-message.success {
|
||||||
|
background-color: #c6f6d5;
|
||||||
|
color: #2f855a;
|
||||||
|
border: 1px solid #9ae6b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-message.error {
|
||||||
|
background-color: #fed7d7;
|
||||||
|
color: #c53030;
|
||||||
|
border: 1px solid #feb2b2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -74,7 +74,7 @@ import TeamReport from "./components/TeamReport.vue";
|
|||||||
import SalesFunnel from "./components/SalesFunnel.vue";
|
import SalesFunnel from "./components/SalesFunnel.vue";
|
||||||
import PerformanceRanking from "./components/PerformanceRanking.vue";
|
import PerformanceRanking from "./components/PerformanceRanking.vue";
|
||||||
import MemberDetails from "./components/MemberDetails.vue";
|
import MemberDetails from "./components/MemberDetails.vue";
|
||||||
import Sale from "../person/Sale.vue";
|
import Sale from "../person/sale.vue";
|
||||||
import SalesTimelineWithTaskList from "../person/components/SalesTimelineWithTaskList.vue";
|
import SalesTimelineWithTaskList from "../person/components/SalesTimelineWithTaskList.vue";
|
||||||
import RawDataCards from "../person/components/RawDataCards.vue";
|
import RawDataCards from "../person/components/RawDataCards.vue";
|
||||||
import CustomerDetail from "../person/components/CustomerDetail.vue";
|
import CustomerDetail from "../person/components/CustomerDetail.vue";
|
||||||
|
|||||||
@@ -29,11 +29,21 @@
|
|||||||
style="display: flex; align-items: center; gap: 30px"
|
style="display: flex; align-items: center; gap: 30px"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px;">
|
||||||
|
<button @click="showFeedbackFormModal" class="feedback-btn">意见反馈</button>
|
||||||
|
<FeedbackForm
|
||||||
|
:is-visible="showFeedbackForm"
|
||||||
|
@close="closeFeedbackFormModal"
|
||||||
|
@submit-feedback="closeFeedbackFormModal"
|
||||||
|
/>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
:card-visibility="cardVisibility"
|
:card-visibility="cardVisibility"
|
||||||
@update-card-visibility="updateCardVisibility"
|
@update-card-visibility="updateCardVisibility"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="section-content">
|
<div class="section-content">
|
||||||
@@ -182,6 +192,7 @@ import RawDataCards from "./components/RawDataCards.vue";
|
|||||||
import WeekAnalize from "./components/WeekAnalize.vue";
|
import WeekAnalize from "./components/WeekAnalize.vue";
|
||||||
import UserDropdown from "@/components/UserDropdown.vue";
|
import UserDropdown from "@/components/UserDropdown.vue";
|
||||||
import Loading from "@/components/Loading.vue";
|
import Loading from "@/components/Loading.vue";
|
||||||
|
import FeedbackForm from "@/components/FeedbackForm.vue";
|
||||||
import {getCustomerAttendance,getTodayCall,getProblemDistribution,getTableFillingRate,getAverageResponseTime,
|
import {getCustomerAttendance,getTodayCall,getProblemDistribution,getTableFillingRate,getAverageResponseTime,
|
||||||
getWeeklyActiveCommunicationRate,getTimeoutResponseRate,getCustomerCallInfo,getCustomerChatInfo,getCustomerFormInfo,
|
getWeeklyActiveCommunicationRate,getTimeoutResponseRate,getCustomerCallInfo,getCustomerChatInfo,getCustomerFormInfo,
|
||||||
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,
|
getConversionRateAndAllocatedData,getCustomerAttendanceAfterClass4,getPayMoneyCustomers,getSalesFunnel,getGoldContactTime,
|
||||||
@@ -294,6 +305,9 @@ const showModal = ref(false)
|
|||||||
const modalContent = ref('')
|
const modalContent = ref('')
|
||||||
const modalTitle = ref('')
|
const modalTitle = ref('')
|
||||||
|
|
||||||
|
// FeedbackForm 弹框状态
|
||||||
|
const showFeedbackForm = ref(false)
|
||||||
|
|
||||||
// 下载弹框状态
|
// 下载弹框状态
|
||||||
const showDownloadModal = ref(false)
|
const showDownloadModal = ref(false)
|
||||||
const downloadModalContent = ref('')
|
const downloadModalContent = ref('')
|
||||||
@@ -891,6 +905,16 @@ const closeDownloadModal = () => {
|
|||||||
downloadModalTitle.value = ''
|
downloadModalTitle.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显示 FeedbackForm
|
||||||
|
const showFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭 FeedbackForm
|
||||||
|
const closeFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// // 处理SOP分析事件
|
// // 处理SOP分析事件
|
||||||
// const handleAnalyzeSop = (analyzeData) => {
|
// const handleAnalyzeSop = (analyzeData) => {
|
||||||
// console.log('handleAnalyzeSop', analyzeData)
|
// console.log('handleAnalyzeSop', analyzeData)
|
||||||
@@ -1944,6 +1968,22 @@ $primary: #3b82f6;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 意见反馈按钮样式
|
||||||
|
.feedback-btn {
|
||||||
|
background-color: #4299e1;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-btn:hover {
|
||||||
|
background-color: #3182ce;
|
||||||
|
}
|
||||||
|
|
||||||
// 弹框响应式样式
|
// 弹框响应式样式
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.modal-container {
|
.modal-container {
|
||||||
|
|||||||
@@ -28,11 +28,19 @@
|
|||||||
|
|
||||||
<div v-if="!isRouteNavigation">
|
<div v-if="!isRouteNavigation">
|
||||||
<!-- 用户下拉菜单 -->
|
<!-- 用户下拉菜单 -->
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px;">
|
||||||
|
<button @click="showFeedbackFormModal" class="feedback-btn">意见反馈</button>
|
||||||
|
<FeedbackForm
|
||||||
|
:is-visible="showFeedbackForm"
|
||||||
|
@close="closeFeedbackFormModal"
|
||||||
|
@submit-feedback="closeFeedbackFormModal"
|
||||||
|
/>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
:card-visibility="cardVisibility"
|
:card-visibility="cardVisibility"
|
||||||
@update-card-visibility="updateCardVisibility"
|
@update-card-visibility="updateCardVisibility"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,7 +184,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, computed,reactive } from 'vue'
|
import { ref, onMounted, computed,reactive } from 'vue'
|
||||||
|
import FeedbackForm from "@/components/FeedbackForm.vue";
|
||||||
// 30分钟数据缓存系统
|
// 30分钟数据缓存系统
|
||||||
const cache = new Map()
|
const cache = new Map()
|
||||||
const CACHE_DURATION = 30 * 60 * 1000 // 30分钟
|
const CACHE_DURATION = 30 * 60 * 1000 // 30分钟
|
||||||
@@ -272,11 +280,23 @@
|
|||||||
teamDetail: true
|
teamDetail: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// FeedbackForm 控制变量
|
||||||
|
const showFeedbackForm = ref(false)
|
||||||
|
|
||||||
// 更新卡片显示状态
|
// 更新卡片显示状态
|
||||||
const updateCardVisibility = (newVisibility) => {
|
const updateCardVisibility = (newVisibility) => {
|
||||||
Object.assign(cardVisibility.value, newVisibility)
|
Object.assign(cardVisibility.value, newVisibility)
|
||||||
console.log('卡片显示状态已更新:', cardVisibility.value)
|
console.log('卡片显示状态已更新:', cardVisibility.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FeedbackForm 控制方法
|
||||||
|
const showFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = false
|
||||||
|
}
|
||||||
// 营期调控逻辑
|
// 营期调控逻辑
|
||||||
// This would ideally come from a prop or API call based on the logged-in user
|
// This would ideally come from a prop or API call based on the logged-in user
|
||||||
const centerData = ref({
|
const centerData = ref({
|
||||||
@@ -1646,6 +1666,22 @@ const hideTooltip = () => {
|
|||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 意见反馈按钮样式 */
|
||||||
|
.feedback-btn {
|
||||||
|
background-color: #4299e1;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #3182ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.stage-control {
|
.stage-control {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
|
|||||||
@@ -27,15 +27,21 @@
|
|||||||
|
|
||||||
<div v-if="!isRouteNavigation">
|
<div v-if="!isRouteNavigation">
|
||||||
<!-- 用户下拉菜单 -->
|
<!-- 用户下拉菜单 -->
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px;">
|
||||||
|
<button @click="showFeedbackFormModal" class="feedback-btn">意见反馈</button>
|
||||||
|
<FeedbackForm
|
||||||
|
:is-visible="showFeedbackForm"
|
||||||
|
@close="closeFeedbackFormModal"
|
||||||
|
@submit-feedback="closeFeedbackFormModal"
|
||||||
|
/>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
class="header-ringht"
|
|
||||||
style="margin-left: auto;"
|
|
||||||
:card-visibility="cardVisibility"
|
:card-visibility="cardVisibility"
|
||||||
@update-card-visibility="updateCardVisibility"
|
@update-card-visibility="updateCardVisibility"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<main class="dashboard-main">
|
<main class="dashboard-main">
|
||||||
@@ -198,6 +204,7 @@ import { getOverallTeamPerformance,getTotalGroupCount,getConversionRate,getTotal
|
|||||||
getTimeoutRate,getTableFillingRate,getUrgentNeedToAddress,getTeamRanking,getTeamRankingInfo,getAbnormalResponseRate } from '@/api/senorManger.js'
|
getTimeoutRate,getTableFillingRate,getUrgentNeedToAddress,getTeamRanking,getTeamRankingInfo,getAbnormalResponseRate } from '@/api/senorManger.js'
|
||||||
|
|
||||||
import { useUserStore } from '@/stores/user.js'
|
import { useUserStore } from '@/stores/user.js'
|
||||||
|
import FeedbackForm from "@/components/FeedbackForm.vue";
|
||||||
|
|
||||||
// 缓存系统
|
// 缓存系统
|
||||||
const cache = new Map()
|
const cache = new Map()
|
||||||
@@ -307,6 +314,8 @@ const timeoutResponseRate = ref(5)
|
|||||||
const severeTimeoutRate = ref(2)
|
const severeTimeoutRate = ref(2)
|
||||||
const formCompletionRate = ref(90)
|
const formCompletionRate = ref(90)
|
||||||
const CheckType = ref('month')
|
const CheckType = ref('month')
|
||||||
|
// FeedbackForm 控制变量
|
||||||
|
const showFeedbackForm = ref(false)
|
||||||
|
|
||||||
// 更新CheckType的方法
|
// 更新CheckType的方法
|
||||||
const updateCheckType = async (newValue) => {
|
const updateCheckType = async (newValue) => {
|
||||||
@@ -318,6 +327,15 @@ const updateCheckType = async (newValue) => {
|
|||||||
console.log('数据已根据新的统计模式重新加载')
|
console.log('数据已根据新的统计模式重新加载')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FeedbackForm 控制方法
|
||||||
|
const showFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 卡片显示状态
|
// 卡片显示状态
|
||||||
const cardVisibility = ref({
|
const cardVisibility = ref({
|
||||||
centerOverview: true,
|
centerOverview: true,
|
||||||
@@ -1490,4 +1508,20 @@ const hideTooltip = () => {
|
|||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 意见反馈按钮样式
|
||||||
|
.feedback-btn {
|
||||||
|
background-color: #4299e1;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-btn:hover {
|
||||||
|
background-color: #3182ce;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -4,11 +4,19 @@
|
|||||||
<div class="dashboard-header">
|
<div class="dashboard-header">
|
||||||
<h1>管理者数据看板</h1>
|
<h1>管理者数据看板</h1>
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
|
<div style="display: flex; align-items: center; gap: 20px;">
|
||||||
|
<button @click="showFeedbackFormModal" class="feedback-btn">意见反馈</button>
|
||||||
|
<FeedbackForm
|
||||||
|
:is-visible="showFeedbackForm"
|
||||||
|
@close="closeFeedbackFormModal"
|
||||||
|
@submit-feedback="closeFeedbackFormModal"
|
||||||
|
/>
|
||||||
<UserDropdown
|
<UserDropdown
|
||||||
:card-visibility="cardVisibility"
|
:card-visibility="cardVisibility"
|
||||||
@update-card-visibility="updateCardVisibility"
|
@update-card-visibility="updateCardVisibility"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 第一行:核心业绩指标、销售实时进度 -->
|
<!-- 第一行:核心业绩指标、销售实时进度 -->
|
||||||
<div class="dashboard-row row-1">
|
<div class="dashboard-row row-1">
|
||||||
@@ -111,6 +119,7 @@ import PeriodStage from "./components/PeriodStage.vue";
|
|||||||
import { getOverallCompanyPerformance,getCompanyDepositConversionRate,getCompanyTotalCallCount,getCompanyNewCustomer,getCompanyConversionRate,getCompanyRealTimeProgress
|
import { getOverallCompanyPerformance,getCompanyDepositConversionRate,getCompanyTotalCallCount,getCompanyNewCustomer,getCompanyConversionRate,getCompanyRealTimeProgress
|
||||||
,getCompanyConversionRateVsLast,getSalesMonthlyPerformance,getCustomerTypeDistribution,getUrgentNeedToAddress,getLevelTree,getDetailedDataTable,getExcellentRecordFile } from "@/api/top";
|
,getCompanyConversionRateVsLast,getSalesMonthlyPerformance,getCustomerTypeDistribution,getUrgentNeedToAddress,getLevelTree,getDetailedDataTable,getExcellentRecordFile } from "@/api/top";
|
||||||
import { useUserStore } from "@/stores/user.js";
|
import { useUserStore } from "@/stores/user.js";
|
||||||
|
import FeedbackForm from "@/components/FeedbackForm.vue";
|
||||||
|
|
||||||
// 缓存系统
|
// 缓存系统
|
||||||
const cache = new Map();
|
const cache = new Map();
|
||||||
@@ -236,6 +245,18 @@ const cardVisibility = ref({
|
|||||||
detailedDataTable: true
|
detailedDataTable: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FeedbackForm 控制变量
|
||||||
|
const showFeedbackForm = ref(false);
|
||||||
|
|
||||||
|
// FeedbackForm 控制方法
|
||||||
|
const showFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeFeedbackFormModal = () => {
|
||||||
|
showFeedbackForm.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
// 更新卡片显示状态
|
// 更新卡片显示状态
|
||||||
const updateCardVisibility = (newVisibility) => {
|
const updateCardVisibility = (newVisibility) => {
|
||||||
Object.assign(cardVisibility.value, newVisibility);
|
Object.assign(cardVisibility.value, newVisibility);
|
||||||
@@ -2164,4 +2185,20 @@ button {
|
|||||||
-ms-user-select: text;
|
-ms-user-select: text;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 意见反馈按钮样式 */
|
||||||
|
.feedback-btn {
|
||||||
|
background-color: #4299e1;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feedback-btn:hover {
|
||||||
|
background-color: #3182ce;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user