Compare commits
3 Commits
515ae4e78c
...
d83cdba468
| Author | SHA1 | Date | |
|---|---|---|---|
| d83cdba468 | |||
| 613a2be148 | |||
|
|
46a3b6a878 |
2
App.vue
2
App.vue
@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import { onLaunch, onShow, onHide, onLoad } from "@dcloudio/uni-app";
|
||||
import { checkPhone } from "@/manager/LoginManager";
|
||||
import { goLogin } from "@/hooks/useGoLogin";
|
||||
import { goHome } from "@/hooks/useGoHome";
|
||||
|
||||
@ -1,15 +1,5 @@
|
||||
.create-service-order {
|
||||
// margin-left: 12px;
|
||||
// margin-right: 12px;
|
||||
}
|
||||
|
||||
.create-service-wrapper {
|
||||
// box-sizing: border-box;
|
||||
padding: 12px 0;
|
||||
// background-color: #eff6fa;
|
||||
// box-shadow: 2px 2px 10px 0px rgba(0, 0, 0, 0.1);
|
||||
// border-radius: 4px 20px 20px 20px;
|
||||
// border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
@ -116,7 +106,7 @@
|
||||
}
|
||||
|
||||
.order-button {
|
||||
width: 280px;
|
||||
width: 300px;
|
||||
height: 42px;
|
||||
background: linear-gradient(90deg, #ff7e00, #ffba00);
|
||||
color: #fff;
|
||||
|
||||
BIN
components/Feedback/images/icon_volume.png
Normal file
BIN
components/Feedback/images/icon_volume.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 844 B |
140
components/Feedback/index.vue
Normal file
140
components/Feedback/index.vue
Normal file
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<view class="create-service-order">
|
||||
<view class="create-service-wrapper">
|
||||
<view class="order-header">
|
||||
<text>反馈意见</text>
|
||||
</view>
|
||||
<view class="order-content">
|
||||
<view class="detail-item">
|
||||
<text class="detail-label">联系电话:</text>
|
||||
<input
|
||||
v-if="!isCallSuccess"
|
||||
class="detail-input"
|
||||
placeholder="请填写联系电话"
|
||||
v-model="contactPhone"
|
||||
/>
|
||||
<text v-else class="detail-value">{{ contactPhone }}</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<text class="detail-label">意见内容:</text>
|
||||
<textarea
|
||||
v-if="!isCallSuccess"
|
||||
class="detail-textarea"
|
||||
placeholder="请输入反馈意见"
|
||||
v-model="contactText"
|
||||
/>
|
||||
<text v-else class="detail-value">{{ contactText }}</text>
|
||||
</view>
|
||||
|
||||
<button
|
||||
v-if="!isCallSuccess"
|
||||
class="order-button submit-button"
|
||||
@click="handleCall"
|
||||
>
|
||||
立即提交
|
||||
</button>
|
||||
|
||||
<button v-else class="order-button look-button" @click="viewWorkOrder">
|
||||
查看意见
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="footer-help">
|
||||
<image src="./images/icon_volume.png" class="help-icon"></image>
|
||||
<text class="help-text">朵朵收到您的意见将第一时间为您处理!</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, nextTick } from "vue";
|
||||
import { SCROLL_TO_BOTTOM } from "@/constant/constant";
|
||||
import { createWorkOrder } from "@/request/api/OrderApi";
|
||||
const workOrderTypeId = ref("");
|
||||
const contactPhone = ref("");
|
||||
const contactText = ref("");
|
||||
const isCallSuccess = ref(false); // 呼叫成功状态
|
||||
const workOrderId = ref(0); // 工单ID
|
||||
|
||||
const handleCall = async () => {
|
||||
if (!contactPhone.value.trim()) {
|
||||
uni.showToast({
|
||||
title: "请填写联系电话",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!contactText.value.trim()) {
|
||||
uni.showToast({
|
||||
title: "请填写意见内容",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
sendCreateWorkOrder();
|
||||
};
|
||||
|
||||
/// 创建工单
|
||||
const sendCreateWorkOrder = async () => {
|
||||
try {
|
||||
const res = await createWorkOrder({
|
||||
contactName: contactText.value,
|
||||
contactPhone: contactPhone.value,
|
||||
workOrderTypeId: workOrderTypeId.value,
|
||||
});
|
||||
|
||||
if (res.code === 0) {
|
||||
// 保存工单ID
|
||||
workOrderId.value = res.data?.id || "";
|
||||
|
||||
// 设置呼叫成功状态
|
||||
isCallSuccess.value = true;
|
||||
|
||||
uni.showToast({
|
||||
title: "工单创建成功",
|
||||
icon: "success",
|
||||
duration: 2000,
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.message || "创建工单失败",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("创建工单失败:", error);
|
||||
uni.showToast({
|
||||
title: "网络错误,请重试",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 查看工单
|
||||
const viewWorkOrder = () => {
|
||||
console.log("查看工单:", workOrderId.value);
|
||||
// 这里可以跳转到工单详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/list?id=${workOrderId.value}`,
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
uni.$emit(SCROLL_TO_BOTTOM, true);
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/index.scss";
|
||||
</style>
|
||||
95
components/Feedback/styles/index.scss
Normal file
95
components/Feedback/styles/index.scss
Normal file
@ -0,0 +1,95 @@
|
||||
.create-service-wrapper {
|
||||
padding: 6px 0 12px;
|
||||
}
|
||||
|
||||
.order-header {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.order-content {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
width: 70px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.detail-textarea {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.detail-input {
|
||||
border: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.order-button {
|
||||
width: 300px;
|
||||
height: 42px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
border-radius: 21px;
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
background: linear-gradient(90deg, #ff7e00, #ffba00);
|
||||
}
|
||||
|
||||
.look-button {
|
||||
background: linear-gradient(90deg, #0256ff, #00a6ff);
|
||||
}
|
||||
|
||||
.footer-help {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #ed6a0c;
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
margin-right: 5px;
|
||||
}
|
||||
@ -12,7 +12,8 @@ export const MessageType = {
|
||||
|
||||
|
||||
export const CompName = {
|
||||
quickBookingCard: 'quickBookingCard',
|
||||
createWorkOrderCard: 'createWorkOrderCard',
|
||||
discoveryCard: 'discoveryCard',
|
||||
}
|
||||
quickBookingCard: "quickBookingCard",
|
||||
createWorkOrderCard: "createWorkOrderCard",
|
||||
feedbackCard: "feedbackCard",
|
||||
discoveryCard: "discoveryCard",
|
||||
};
|
||||
@ -5,7 +5,8 @@
|
||||
<image
|
||||
v-if="isLoading"
|
||||
class="loading-img"
|
||||
src="/static/msg_loading.svg"
|
||||
src="/static/chat_msg_loading.gif"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
<!-- <loading v-if="isLoading" /> -->
|
||||
<ChatMarkdown :key="textKey" :text="processedText" />
|
||||
@ -94,8 +95,8 @@ watch(
|
||||
}
|
||||
|
||||
.loading-img {
|
||||
margin-left: -4px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 8px;
|
||||
width: 30px;
|
||||
height: 25px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -61,6 +61,12 @@
|
||||
item.toolCall.componentName === CompName.createWorkOrderCard
|
||||
"
|
||||
/>
|
||||
<Feedback
|
||||
v-else-if="
|
||||
item.toolCall.componentName === CompName.feedbackCard
|
||||
"
|
||||
:toolCall="item.toolCall"
|
||||
/>
|
||||
<DetailCardCompontent
|
||||
v-else-if="item.toolCall.componentName === ''"
|
||||
:toolCall="item.toolCall"
|
||||
@ -148,6 +154,7 @@ import ActivityListComponent from "../module/banner/ActivityListComponent.vue";
|
||||
import RecommendPostsComponent from "../module/recommend/RecommendPostsComponent.vue";
|
||||
import AttachListComponent from "../module/attach/AttachListComponent.vue";
|
||||
import CreateServiceOrder from "@/components/CreateServiceOrder/index.vue";
|
||||
import Feedback from "@/components/Feedback/index.vue";
|
||||
import DetailCardCompontent from "../module/detail/DetailCardCompontent.vue";
|
||||
import { mainPageData } from "@/request/api/MainPageDataApi";
|
||||
import {
|
||||
@ -157,7 +164,9 @@ import {
|
||||
import WebSocketManager from "@/utils/WebSocketManager";
|
||||
import TypewriterManager from "@/utils/TypewriterManager";
|
||||
import { IdUtils } from "@/utils";
|
||||
import { useAppStore } from "@/store";
|
||||
|
||||
const appStore = useAppStore();
|
||||
/// 导航栏相关
|
||||
const statusBarHeight = ref(20);
|
||||
/// 输入框组件引用
|
||||
@ -182,8 +191,6 @@ const chatMsgList = ref([]);
|
||||
/// 输入口的输入消息
|
||||
const inputMessage = ref("");
|
||||
|
||||
/// 从个渠道获取如二维,没有的时候就返回首页的数据
|
||||
const sceneId = ref("");
|
||||
/// agentId 首页接口中获取
|
||||
const agentId = ref("1");
|
||||
/// 会话ID 历史数据接口中获取
|
||||
@ -383,7 +390,9 @@ const loadConversationMsgList = async () => {
|
||||
|
||||
// 获取首页数据
|
||||
const getMainPageData = async () => {
|
||||
const res = await mainPageData(sceneId.value);
|
||||
/// 从个渠道获取如二维,没有的时候就返回首页的数据
|
||||
const sceneId = appStore.sceneId || "";
|
||||
const res = await mainPageData(sceneId);
|
||||
if (res.code === 0) {
|
||||
mainPageDataModel.value = res.data;
|
||||
agentId.value = res.data.agentId;
|
||||
|
||||
@ -58,8 +58,8 @@ const initData = () => {
|
||||
},
|
||||
{
|
||||
icon: "/static/quick/quick_icon_call.png",
|
||||
title: "呼叫服务",
|
||||
content: "加水、客房服务等",
|
||||
title: "反馈意见",
|
||||
content: "有意见告诉朵朵",
|
||||
type: "Command.createWorkOrder",
|
||||
},
|
||||
];
|
||||
|
||||
@ -11,15 +11,18 @@
|
||||
@close="handleCalendarClose"
|
||||
@select="handleDateSelect"
|
||||
/>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from "vue";
|
||||
import ChatMainList from "../chat/ChatMainList.vue";
|
||||
import Calender from "@/components/Calender/index.vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { GetWxMiniProgramUrlParam } from "@/utils/UrlParams";
|
||||
|
||||
import { useAppStore } from "@/store";
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
const calendarVisible = ref(false);
|
||||
const selectedDate = ref("");
|
||||
@ -35,17 +38,28 @@ const handleDateSelect = (data) => {
|
||||
calendarVisible.value = false;
|
||||
console.log("选择的日期:", data.date);
|
||||
uni.$emit("selectCalendarDate", selectedDate.value); // 传回父组件
|
||||
|
||||
};
|
||||
|
||||
uni.$on("openCalendar", () => {
|
||||
calendarVisible.value = true;
|
||||
});
|
||||
|
||||
const getWeixinMiniProgramParams = (e) => {
|
||||
console.log("Params:", e);
|
||||
if (e.q && e.q != "undefined") {
|
||||
const qrUrl = decodeURIComponent(e.q); // 获取到二维码原始链接内容
|
||||
const params = GetWxMiniProgramUrlParam(qrUrl);
|
||||
appStore.setSceneId(params.sceneId);
|
||||
}
|
||||
};
|
||||
|
||||
onLoad((e) => {
|
||||
getWeixinMiniProgramParams(e);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// uni.$off('openCalendar')
|
||||
})
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
BIN
static/chat_msg_loading.gif
Normal file
BIN
static/chat_msg_loading.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
@ -4,6 +4,7 @@ export const useAppStore = defineStore("app", {
|
||||
state() {
|
||||
return {
|
||||
title: "",
|
||||
sceneId: "",
|
||||
};
|
||||
},
|
||||
getters: {},
|
||||
@ -12,6 +13,9 @@ export const useAppStore = defineStore("app", {
|
||||
setData(data) {
|
||||
this.title = data;
|
||||
},
|
||||
setSceneId(data) {
|
||||
this.sceneId = data;
|
||||
},
|
||||
},
|
||||
|
||||
unistorage: true,
|
||||
|
||||
@ -94,15 +94,15 @@ export default {
|
||||
const fontFamily = this.fontFamily
|
||||
let zeroStyle = {
|
||||
p: `
|
||||
margin:6px 0;
|
||||
margin:4px 0;
|
||||
font-size: 15px;
|
||||
line-height:1.65;
|
||||
font-family: ${fontFamily};
|
||||
`,
|
||||
// 一级标题
|
||||
h1: `
|
||||
margin:6px 0;
|
||||
font-size: 24px;
|
||||
margin:4px 0;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: ${themeColor};
|
||||
@ -115,8 +115,8 @@ export default {
|
||||
`,
|
||||
// 二级标题
|
||||
h2: `
|
||||
margin:6px 0;
|
||||
font-size: 20px;
|
||||
margin:4px 0;
|
||||
font-size: 18px;
|
||||
text-align:center;
|
||||
color:${themeColor};
|
||||
font-family: ${fontFamily};
|
||||
@ -126,8 +126,8 @@ export default {
|
||||
`,
|
||||
// 三级标题
|
||||
h3: `
|
||||
margin:6px 0;
|
||||
font-size: 18px;
|
||||
margin:4px 0;
|
||||
font-size: 16px;
|
||||
color: ${themeColor};
|
||||
font-family: ${fontFamily};
|
||||
padding-left:10px;
|
||||
@ -135,7 +135,7 @@ export default {
|
||||
`,
|
||||
// 引用
|
||||
blockquote: `
|
||||
margin:6px 0;
|
||||
margin:4px 0;
|
||||
font-size:15px;
|
||||
font-family: ${fontFamily};
|
||||
color: #777777;
|
||||
@ -144,7 +144,7 @@ export default {
|
||||
`,
|
||||
// 列表
|
||||
ul: `
|
||||
margin: 6px 0;
|
||||
margin: 4px 0;
|
||||
color: #555;
|
||||
`,
|
||||
li: `
|
||||
@ -208,7 +208,7 @@ export default {
|
||||
const fontFamily = this.fontFamily
|
||||
let zeroStyle = {
|
||||
p: `
|
||||
margin:6px 0;
|
||||
margin:4px 0;
|
||||
font-size: 15px;
|
||||
line-height:1.55;
|
||||
font-family: ${fontFamily};
|
||||
|
||||
17
utils/UrlParams.js
Normal file
17
utils/UrlParams.js
Normal file
@ -0,0 +1,17 @@
|
||||
export function GetWxMiniProgramUrlParam(url) {
|
||||
let theRequest = {};
|
||||
if(url.indexOf("#") != -1){
|
||||
const str=url.split("#")[1];
|
||||
const strs=str.split("&");
|
||||
for (let i = 0; i < strs.length; i++) {
|
||||
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
|
||||
}
|
||||
}else if(url.indexOf("?") != -1){
|
||||
const str=url.split("?")[1];
|
||||
const strs=str.split("&");
|
||||
for (let i = 0; i < strs.length; i++) {
|
||||
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
|
||||
}
|
||||
}
|
||||
return theRequest;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user