This commit is contained in:
wangdongbo 2026-02-12 15:06:29 +08:00
commit f33ec3920e
4 changed files with 191 additions and 211 deletions

View File

@ -1,13 +1,10 @@
<template>
<!-- Mobile 来源: ykt-management-mobile/src/pages/manage-plan/plan-list/plan-list.vue -->
<view class="page">
<view v-if="loading" class="loading">加载中...</view>
<view v-else-if="list.length === 0" class="empty">
<image class="empty-img" src="/static/empty.svg" mode="aspectFit" />
<view class="empty-text">暂无回访计划</view>
<full-page :customScroll="list.length === 0" pageStyle="background:#fff">
<view v-if="list.length === 0" class="h-full flex flex-col items-center justify-center">
<view v-if="loading" class="text-base text-center text-dark">加载中...</view>
<empty-data v-else text="暂无回访计划" />
</view>
<scroll-view v-else scroll-y class="scroll">
<template v-else>
<view v-for="(p, idx) in list" :key="p.id" class="item">
<view class="left">
<view class="name-row">
@ -19,9 +16,17 @@
</view>
<view class="btn" @click="select(p)">选择</view>
</view>
<view style="height: 24px;"></view>
</scroll-view>
</view>
</template>
<template #footer>
<view class="relative shadow-up bg-white">
<view class="p-15 text-center" @click="toService()">
<text class="mr-5 text-base text-gray">如没有符合的内容</text>
<text class="text-base text-primary">联系客服</text>
</view>
</view>
</template>
</full-page>
</template>
<script setup>
@ -33,6 +38,9 @@ import useAccountStore from '@/store/account';
import { toast } from '@/utils/widget';
import { getTodoEventTypeLabel } from '@/utils/todo-const';
import EmptyData from "@/components/empty-data.vue";
import fullPage from '@/components/full-page.vue';
const archiveId = ref('');
const loading = ref(false);
@ -97,6 +105,12 @@ function normalizePlan(raw) {
};
}
function toService() {
uni.navigateTo({
url: '/pages/work/service/contact-service'
})
}
async function loadList() {
if (loading.value) return;
loading.value = true;
@ -142,35 +156,36 @@ function preview(plan) {
</script>
<style scoped>
.page {
height: 100vh;
background: #fff;
}
.scroll {
height: 100vh;
}
.loading {
padding: 16px;
font-size: 13px;
color: #9aa0a6;
}
.item {
display: flex;
align-items: center;
padding: 12px 14px;
border-bottom: 1px solid #f2f2f2;
}
.left {
flex: 1;
min-width: 0;
margin-right: 10px;
}
.name-row {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 6px;
}
.name {
font-size: 14px;
font-weight: 600;
@ -180,20 +195,24 @@ function preview(plan) {
text-overflow: ellipsis;
white-space: nowrap;
}
.tag {
font-size: 12px;
padding: 4px 8px;
border-radius: 6px;
}
.tag.corp {
background: #0877F1;
color: #fff;
}
.tag.outline {
border: 1px solid #0877F1;
color: #0877F1;
background: #fff;
}
.desc {
font-size: 12px;
color: #999;
@ -201,6 +220,7 @@ function preview(plan) {
text-overflow: ellipsis;
white-space: nowrap;
}
.btn {
flex-shrink: 0;
padding: 8px 12px;
@ -209,6 +229,7 @@ function preview(plan) {
color: #0877F1;
font-size: 13px;
}
.empty {
height: 100vh;
display: flex;
@ -216,11 +237,13 @@ function preview(plan) {
align-items: center;
justify-content: center;
}
.empty-img {
width: 160px;
height: 160px;
opacity: 0.9;
}
.empty-text {
margin-top: 10px;
font-size: 13px;

View File

@ -1,109 +1,84 @@
<template>
<view class="article-page">
<view class="header">
<view class="search-bar">
<uni-icons type="search" size="18" color="#999" />
<input
class="search-input"
v-model="searchTitle"
placeholder="输入内容名称搜索"
@input="handleSearch"
/>
<full-page :customScroll="true" pageStyle="background:#f5f5f5">
<template #header>
<view class="header">
<view class="search-bar">
<uni-icons type="search" size="18" color="#999" />
<input class="search-input" v-model="searchTitle" placeholder="输入内容名称搜索" @input="handleSearch" />
</view>
</view>
</view>
</template>
<view class="content">
<view class="category-sidebar">
<scroll-view scroll-y class="category-scroll">
<view
v-for="cate in categoryList"
:key="cate._id || 'all'"
class="category-item"
:class="{ active: currentCateId === cate._id }"
@click="selectCategory(cate)"
>
{{ cate.label }}
</view>
</scroll-view>
</view>
<view class="h-full flex">
<scroll-view scroll-y class="flex-shrink-0 category-sidebar h-full">
<view v-for="cate in categoryList" :key="cate._id || 'all'" class="category-item"
:class="{ active: currentCateId === cate._id }" @click="selectCategory(cate)">
{{ cate.label }}
</view>
</scroll-view>
<scroll-view scroll-y class="w-0 flex-grow bg-white" @scrolltolower="loadMore" lower-threshold="50">
<view v-if="loading && articleList.length === 0" class="loading-container">
<uni-icons type="spinner-cycle" size="30" color="#999" />
<text class="loading-text">加载中...</text>
</view>
<view class="article-list">
<scroll-view
scroll-y
class="article-scroll"
@scrolltolower="loadMore"
lower-threshold="50"
>
<view
v-if="loading && articleList.length === 0"
class="loading-container"
>
<uni-icons type="spinner-cycle" size="30" color="#999" />
<text class="loading-text">加载中...</text>
</view>
<view v-else-if="articleList.length === 0" class="empty-container">
<empty-data title="暂无文章" />
</view>
<view v-else-if="articleList.length === 0" class="empty-container">
<empty-data title="暂无文章" />
</view>
<view v-else>
<view
v-for="article in articleList"
:key="article._id"
class="article-item"
>
<view class="article-content" @click="previewArticle(article)">
<text class="article-title">{{ article.title }}</text>
<view class="article-footer">
<text class="article-date">{{ article.date }}</text>
<button
class="send-btn"
size="mini"
type="primary"
@click.stop="handlePrimaryAction(article)"
>
{{ isSelectMode ? '选择' : '发送' }}
</button>
</view>
<view v-else>
<view v-for="article in articleList" :key="article._id" class="article-item">
<view class="article-content" @click="previewArticle(article)">
<text class="article-title">{{ article.title }}</text>
<view class="article-footer">
<text class="article-date">{{ article.date }}</text>
<button class="send-btn" size="mini" type="primary" @click.stop="handlePrimaryAction(article)">
{{ isSelectMode ? '选择' : '发送' }}
</button>
</view>
</view>
<view v-if="loading && articleList.length > 0" class="loading-more">
<uni-icons type="spinner-cycle" size="20" color="#999" />
<text>加载中...</text>
</view>
<view
v-if="!loading && articleList.length >= total"
class="no-more"
>
没有更多了
</view>
</view>
</scroll-view>
</view>
<view v-if="loading && articleList.length > 0" class="loading-more">
<uni-icons type="spinner-cycle" size="20" color="#999" />
<text>加载中...</text>
</view>
<view v-if="!loading && articleList.length >= total" class="no-more">
没有更多了
</view>
</view>
</scroll-view>
</view>
<!-- 文章预览弹窗 -->
<uni-popup ref="previewPopup" type="bottom" :safe-area="false">
<view class="preview-container">
<view class="preview-header">
<text class="preview-title">{{ previewArticleData.title }}</text>
<view class="preview-close" @click="closePreview">
<uni-icons type="closeempty" size="24" color="#333" />
</view>
</view>
<scroll-view scroll-y class="preview-content">
<view class="rich-text-wrapper">
<rich-text :nodes="previewArticleData.content"></rich-text>
</view>
</scroll-view>
<view class="preview-footer">
<button class="preview-close-btn" @click="closePreview">关闭</button>
<template #footer>
<view class="relative shadow-up bg-white">
<view class="p-15 text-center" @click="toService()">
<text class="mr-5 text-base text-gray">如没有符合的内容</text>
<text class="text-base text-primary">联系客服</text>
</view>
</view>
</uni-popup>
</view>
</template>
</full-page>
<!-- 文章预览弹窗 -->
<uni-popup ref="previewPopup" type="bottom" :safe-area="false">
<view class="preview-container">
<view class="preview-header">
<text class="preview-title">{{ previewArticleData.title }}</text>
<view class="preview-close" @click="closePreview">
<uni-icons type="closeempty" size="24" color="#333" />
</view>
</view>
<scroll-view scroll-y class="preview-content">
<view class="rich-text-wrapper">
<rich-text :nodes="previewArticleData.content"></rich-text>
</view>
</scroll-view>
<view class="preview-footer">
<button class="preview-close-btn" @click="closePreview">关闭</button>
</view>
</view>
</uni-popup>
</template>
<script setup>
@ -112,6 +87,7 @@ import { onLoad } from "@dcloudio/uni-app";
import api from "@/utils/api.js";
import useAccountStore from "@/store/account.js";
import { sendArticleMessage } from "@/utils/send-message-helper.js";
import fullPage from '@/components/full-page.vue';
import EmptyData from "@/components/empty-data.vue";
const accountStore = useAccountStore();
@ -383,6 +359,12 @@ const sendArticle = async (article) => {
}
};
function toService() {
uni.navigateTo({
url: '/pages/work/service/contact-service'
})
}
//
const goBack = () => {
uni.navigateBack();
@ -453,9 +435,7 @@ onMounted(() => {
border-right: 1px solid #eee;
}
.category-scroll {
height: 100%;
}
.category-item {
padding: 20rpx 24rpx;
@ -474,14 +454,6 @@ onMounted(() => {
border-left: 4rpx solid #0877f1;
}
.article-list {
flex: 1;
background-color: #fff;
}
.article-scroll {
height: 100%;
}
.loading-container,
.empty-container {

View File

@ -1,98 +1,79 @@
<template>
<view class="survey-page">
<view class="header">
<view class="search-bar">
<uni-icons type="search" size="18" color="#999" />
<input
class="search-input"
v-model="searchName"
placeholder="输入问卷名称搜索"
@input="handleSearch"
/>
<full-page :customScroll="true" pageStyle="background:#f5f5f5">
<template #header>
<view class="header">
<view class="search-bar">
<uni-icons type="search" size="18" color="#999" />
<input class="search-input" v-model="searchName" placeholder="输入问卷名称搜索" @input="handleSearch" />
</view>
</view>
</template>
<view class="h-full flex">
<scroll-view scroll-y class="flex-shrink-0 category-sidebar h-full">
<view v-for="cate in categoryList" :key="cate._id || 'all'" class="category-item"
:class="{ active: currentCateId === cate._id }" @click="selectCategory(cate)">
{{ cate.label }}
</view>
</scroll-view>
<scroll-view scroll-y class="w-0 flex-grow bg-white" @scrolltolower="loadMore" lower-threshold="50">
<view v-if="loading && surveyList.length === 0" class="loading-container">
<uni-icons type="spinner-cycle" size="30" color="#999" />
<text class="loading-text">加载中...</text>
</view>
<view v-else-if="surveyList.length === 0" class="empty-container">
<empty-data :title="emptyText || '暂无问卷'" />
</view>
<view v-else>
<view v-for="survey in surveyList" :key="survey._id" class="survey-item">
<view class="survey-content" @click="previewSurvey(survey)">
<text class="survey-title">{{ survey.name }}</text>
<text class="survey-desc">{{
survey.description || "暂无问卷说明"
}}</text>
</view>
<view class="survey-action">
<button class="send-btn" size="mini" type="primary" @click="handlePrimaryAction(survey)">
{{ isSelectMode ? '选择' : '发送' }}
</button>
</view>
</view>
<view v-if="loading && surveyList.length > 0" class="loading-more">
<uni-icons type="spinner-cycle" size="20" color="#999" />
<text>加载中...</text>
</view>
<view v-if="!loading && surveyList.length >= total" class="no-more">
没有更多了
</view>
</view>
</scroll-view>
</view>
<view class="content">
<view class="category-sidebar">
<scroll-view scroll-y class="category-scroll">
<view
v-for="cate in categoryList"
:key="cate._id || 'all'"
class="category-item"
:class="{ active: currentCateId === cate._id }"
@click="selectCategory(cate)"
>
{{ cate.label }}
</view>
</scroll-view>
<template #footer>
<view class="relative shadow-up bg-white">
<view class="p-15 text-center" @click="toService()">
<text class="mr-5 text-base text-gray">如没有符合的内容</text>
<text class="text-base text-primary">联系客服</text>
</view>
</view>
<view class="survey-list">
<scroll-view
scroll-y
class="survey-scroll"
@scrolltolower="loadMore"
lower-threshold="50"
>
<view
v-if="loading && surveyList.length === 0"
class="loading-container"
>
<uni-icons type="spinner-cycle" size="30" color="#999" />
<text class="loading-text">加载中...</text>
</view>
<view v-else-if="surveyList.length === 0" class="empty-container">
<empty-data :title="emptyText || '暂无问卷'" />
</view>
<view v-else>
<view
v-for="survey in surveyList"
:key="survey._id"
class="survey-item"
>
<view class="survey-content" @click="previewSurvey(survey)">
<text class="survey-title">{{ survey.name }}</text>
<text class="survey-desc">{{
survey.description || "暂无问卷说明"
}}</text>
</view>
<view class="survey-action">
<button
class="send-btn"
size="mini"
type="primary"
@click="handlePrimaryAction(survey)"
>
{{ isSelectMode ? '选择' : '发送' }}
</button>
</view>
</view>
<view v-if="loading && surveyList.length > 0" class="loading-more">
<uni-icons type="spinner-cycle" size="20" color="#999" />
<text>加载中...</text>
</view>
<view v-if="!loading && surveyList.length >= total" class="no-more">
没有更多了
</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
</full-page>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import api from "@/utils/api.js";
import useAccountStore from "@/store/account.js";
import { globalTimChatManager } from "@/utils/tim-chat.js";
import { sendSurveyMessage } from "@/utils/send-message-helper.js";
import fullPage from '@/components/full-page.vue';
import EmptyData from "@/components/empty-data.vue";
import { onLoad } from "@dcloudio/uni-app";
const env = __VITE_ENV__;
const accountStore = useAccountStore();
const corpId = env.MP_CORP_ID;
@ -317,13 +298,10 @@ const generateSendLink = (
// 使 VITE_SURVEY_URL
url = `${env.MP_SURVEY_URL}?corpId=${corpId}&surveryId=${survey.surveryId}&memberId=${customerId}&sendSurveyId=${sendSurveyId}&userId=${userId.value}`;
} else {
url = `${
env.MP_PATIENT_PAGE_BASE_URL
}pages/survery/fill?corpId=${corpId}&surveryId=${
survey._id
}&memberId=${customerId}&unionid=unionid&answerId=${answerId}&name=${
customerName || ""
}`;
url = `${env.MP_PATIENT_PAGE_BASE_URL
}pages/survery/fill?corpId=${corpId}&surveryId=${survey._id
}&memberId=${customerId}&unionid=unionid&answerId=${answerId}&name=${customerName || ""
}`;
}
return url;
};
@ -399,6 +377,12 @@ const goBack = () => {
uni.navigateBack();
};
function toService() {
uni.navigateTo({
url: '/pages/work/service/contact-service'
})
}
onMounted(() => {
getCategoryList();
loadSurveyList();
@ -448,6 +432,7 @@ onMounted(() => {
.category-scroll {
height: 100%;
}
.category-item {
padding: 20rpx 24rpx;
font-size: 28rpx;

View File

@ -2,7 +2,7 @@
<view class="flex flex-col justify-center h-full bg-white">
<view>
<view class="mb-10 text-dark text-lg font-semibold text-center mb-10">
康企微客服
助手客服
</view>
<view class="flex justify-center overflow-hidden">
<image :show-menu-by-longpress="true" class="qrcode" src="/static/work/service.png" />