master
2358328281@qq.com 2 months ago
parent 5d2c6f77ba
commit de3c159519

@ -96,7 +96,7 @@
:total-points="signInDialogStore.summary.totalPoints" :total-points="signInDialogStore.summary.totalPoints"
:consecutive-sign-in-days="signInDialogStore.summary.consecutiveSignInDays" :consecutive-sign-in-days="signInDialogStore.summary.consecutiveSignInDays"
:sign-in-rank="signInDialogStore.summary.signInRank" :beat-percent="signInDialogStore.summary.beatPercent" :sign-in-rank="signInDialogStore.summary.signInRank" :beat-percent="signInDialogStore.summary.beatPercent"
@success="onSignInDialogSuccess" /> :has-drawn="signInDialogStore.summary.isDraw" @success="onSignInDialogSuccess" />
<!-- 全局奖励结果弹窗抽奖/签到/提交工单 共用 --> <!-- 全局奖励结果弹窗抽奖/签到/提交工单 共用 -->
<RewardResultDialog /> <RewardResultDialog />

@ -1,3 +1,4 @@
import { createApp } from "vue"; import { createApp } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
@ -10,6 +11,7 @@ import "@/assets/style/reset.css";
import "@/assets/style/index.scss"; import "@/assets/style/index.scss";
import "@/assets/style/common.scss"; import "@/assets/style/common.scss";
// SVG sprite 虚拟模块(必须引入才能注入 symbol // SVG sprite 虚拟模块(必须引入才能注入 symbol
import "virtual:svg-icons-register"; import "virtual:svg-icons-register";

@ -61,8 +61,10 @@ class Request {
if (!silent) ElMessage.error("无操作权限"); if (!silent) ElMessage.error("无操作权限");
} else if (status >= 500) { } else if (status >= 500) {
if (!silent) ElMessage.error("服务器内部错误"); if (!silent) ElMessage.error("服务器内部错误");
} }else {
ElMessage.error(error.response.data.message);
return Promise.reject(error); return Promise.reject(error);
}
}, },
); );
} }

@ -21,6 +21,7 @@ export const useSignInDialogStore = defineStore("signInDialog", () => {
// 透传给 SignInDialog 的字段(来自 /hospital/points 接口 summary // 透传给 SignInDialog 的字段(来自 /hospital/points 接口 summary
const summary = ref({ const summary = ref({
isSignIn: false, isSignIn: false,
isDraw: false,
totalPoints: 0, totalPoints: 0,
consecutiveSignInDays: 0, consecutiveSignInDays: 0,
signInRank: 0, signInRank: 0,
@ -54,6 +55,7 @@ export const useSignInDialogStore = defineStore("signInDialog", () => {
const setSummary = (data) => { const setSummary = (data) => {
summary.value = { summary.value = {
isSignIn: !!data?.isSignIn, isSignIn: !!data?.isSignIn,
isDraw: !!data?.isDraw,
totalPoints: Number(data?.totalPoints) || 0, totalPoints: Number(data?.totalPoints) || 0,
consecutiveSignInDays: Number(data?.consecutiveSignInDays) || 0, consecutiveSignInDays: Number(data?.consecutiveSignInDays) || 0,
signInRank: Number(data?.signInRank) || 0, signInRank: Number(data?.signInRank) || 0,

@ -41,10 +41,10 @@
</div> </div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="维保截止日期" width="140"> <el-table-column label="维保截止日期" width="120">
<template #default="{ row }">{{ formatDate(row.maintenanceEnd) }}</template> <template #default="{ row }">{{ formatDate(row.maintenanceEnd) }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="managerName" label="客户经理" width="110" show-overflow-tooltip /> <el-table-column prop="managerName" label="客户经理" width="80" show-overflow-tooltip />
<el-table-column label="续保完成" width="90" align="center"> <el-table-column label="续保完成" width="90" align="center">
<template #default="{ row }"> <template #default="{ row }">
<img style="width:16px;height:16px;" v-if="row.renewal === 'no'" src="@/assets/image/admin/orders/no.svg" <img style="width:16px;height:16px;" v-if="row.renewal === 'no'" src="@/assets/image/admin/orders/no.svg"
@ -77,7 +77,7 @@
alt=""> alt="">
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="服务操作" min-width="320" class-name="op-cell"> <el-table-column label="服务操作" min-width="415" class-name="op-cell">
<template #default="{ row }"> <template #default="{ row }">
<div class="op-buttons"> <div class="op-buttons">
<el-button class="op-btn" plain @click="openRecord(row, 'call')"> <el-button class="op-btn" plain @click="openRecord(row, 'call')">
@ -357,7 +357,7 @@ onMounted(() => {
.op-buttons { .op-buttons {
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
gap: 10px; gap: 5px;
} }
.op-btn { .op-btn {
@ -370,7 +370,7 @@ onMounted(() => {
line-height: 18px; line-height: 18px;
background: #fff; background: #fff;
font-weight: 400; font-weight: 400;
padding: 5px 10px; padding: 6px 10px !important;
margin: 0; margin: 0;
.el-icon { .el-icon {

@ -1,6 +1,6 @@
<template> <template>
<el-dialog :model-value="modelValue" @update:model-value="onDialogUpdate" :show-close="false" <el-dialog :model-value="modelValue" @update:model-value="onDialogUpdate" :show-close="false"
:close-on-click-modal="true" width="420px" align-center append-to-body class="lottery-dialog" @closed="onClosed"> :close-on-click-modal="true" align-center append-to-body class="lottery-dialog" @closed="onClosed">
<div class="lottery-main"> <div class="lottery-main">
<div class="lottery-header"> <div class="lottery-header">
<h2 class="lottery-title">积分抽奖</h2> <h2 class="lottery-title">积分抽奖</h2>
@ -236,13 +236,13 @@ const onClosed = () => {
/* ============ 所有样式都嵌套在 .lottery-dialog 下 ============ */ /* ============ 所有样式都嵌套在 .lottery-dialog 下 ============ */
.lottery-dialog { .lottery-dialog {
// ===== ===== // ===== =====
overflow: hidden; overflow: hidden !important;
padding: 0; padding: 0 !important;
width: 638px; width: 638px !important;
height: 766px; height: 766px !important;
background: transparent; background: transparent !important;
box-shadow: none; box-shadow: none !important;
transform: scale(0.75); transform: scale(0.75) !important;
.el-dialog__header { .el-dialog__header {

@ -64,6 +64,15 @@
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
<!-- 签到成功 今日未抽奖则弹出抽奖弹窗(抽过则不再弹,避免重复打扰) -->
<LotteryDialog
v-model="lotteryVisible"
:drawable="!hasDrawn"
:batch-goal="500"
:batch-current="0"
@success="onLotterySuccess"
/>
</template> </template>
<script setup> <script setup>
@ -73,6 +82,7 @@ import { ElMessage } from "element-plus";
import { signIn, getPoints } from "@/service/modular/hospital"; import { signIn, getPoints } from "@/service/modular/hospital";
import { useSignInDialogStore } from "@/stores/signInDialog"; import { useSignInDialogStore } from "@/stores/signInDialog";
import { useRewardResultStore } from "@/stores/rewardResult"; import { useRewardResultStore } from "@/stores/rewardResult";
import LotteryDialog from "@/views/hospital/LotteryDialog.vue";
import checkIcon from "@/assets/image/hospital/ponits/coin.svg"; import checkIcon from "@/assets/image/hospital/ponits/coin.svg";
import iconSign from "@/assets/image/hospital/ponits/icon-sign-large.svg"; import iconSign from "@/assets/image/hospital/ponits/icon-sign-large.svg";
@ -88,6 +98,8 @@ const props = defineProps({
signInRank: { type: Number, default: 0 }, signInRank: { type: Number, default: 0 },
// 0-1000 beatPercent // 0-1000 beatPercent
beatPercent: { type: Number, default: 0 }, beatPercent: { type: Number, default: 0 },
// ( summary.isDraw)
hasDrawn: { type: Boolean, default: false },
}); });
const emit = defineEmits(["update:modelValue", "success"]); const emit = defineEmits(["update:modelValue", "success"]);
@ -144,6 +156,7 @@ watch(
); );
const submitting = ref(false); const submitting = ref(false);
const lotteryVisible = ref(false);
const signInDialogStore = useSignInDialogStore(); const signInDialogStore = useSignInDialogStore();
const rewardResultStore = useRewardResultStore(); const rewardResultStore = useRewardResultStore();
@ -156,7 +169,7 @@ const onClosed = () => {
submitting.value = false; submitting.value = false;
}; };
// //
const fetchLatestPoints = async () => { const fetchLatestPoints = async () => {
try { try {
const res = unwrap(await getPoints()); const res = unwrap(await getPoints());
@ -166,6 +179,11 @@ const fetchLatestPoints = async () => {
} }
}; };
// summary( hasDrawn/isDraw )
const onLotterySuccess = async () => {
await signInDialogStore.refreshSummary();
};
// ============ ============ // ============ ============
const handleSignIn = async () => { const handleSignIn = async () => {
if (props.signedIn) { if (props.signedIn) {
@ -179,21 +197,26 @@ const handleSignIn = async () => {
// 7 () // 7 ()
days.value = buildSignInDays(props.consecutiveSignInDays, props.signedIn); days.value = buildSignInDays(props.consecutiveSignInDays, props.signedIn);
// + + // , /
const totalPoints = await fetchLatestPoints(); const totalPoints = await fetchLatestPoints();
// (), open // (),
emit("update:modelValue", false); emit("update:modelValue", false);
setTimeout(() => { setTimeout(() => {
rewardResultStore.open({ if (!props.hasDrawn) {
title: "签到成功", // ()
icon: iconSign, lotteryVisible.value = true;
points: 1, } else {
batchGoal: 500, // ()
batchCurrent: totalPoints, // rewardResultStore.open({
rewardName: "康小虎 AI 吉祥物", // title: "",
}); // icon: iconSign,
// points: 1,
// batchGoal: 500,
// batchCurrent: totalPoints,
// rewardName: " AI ",
// });
}
}, 100); }, 100);
// signInDialogStore onSigned ( summary) // signInDialogStore onSigned ( summary)
@ -211,11 +234,11 @@ const handleSignIn = async () => {
<style lang="scss"> <style lang="scss">
/* ============ 所有样式都嵌套在 .signin-dialog 下 ============ */ /* ============ 所有样式都嵌套在 .signin-dialog 下 ============ */
.signin-dialog { .signin-dialog {
min-width: 502px; min-width: 502px !important;
padding: 0; padding: 0 !important;
background: transparent; background: transparent !important;
box-shadow: none; box-shadow: none !important;
overflow: hidden; overflow: hidden !important;
.el-dialog__header { .el-dialog__header {
display: none; display: none;

@ -12,8 +12,7 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item :label="$t('label.type')" prop="serviceType"> <el-form-item :label="$t('label.type')" prop="serviceType">
<el-select v-model="form.serviceType" :placeholder="$t('placeholder.type')" clearable <el-select v-model="form.serviceType" :placeholder="$t('placeholder.type')" clearable style="width: 100%">
style="width: 100%">
<el-option label="故障报修" value="故障报修" /> <el-option label="故障报修" value="故障报修" />
<el-option label="业务咨询" value="业务咨询" /> <el-option label="业务咨询" value="业务咨询" />
<el-option label="需求变更" value="需求变更" /> <el-option label="需求变更" value="需求变更" />
@ -58,8 +57,7 @@
<!-- 标题 + 颜色标签 + 优先级 同一行 --> <!-- 标题 + 颜色标签 + 优先级 同一行 -->
<el-form-item :label="$t('label.title')" prop="title"> <el-form-item :label="$t('label.title')" prop="title">
<div class="title-row"> <div class="title-row">
<el-input v-model="form.title" :placeholder="$t('placeholder.title')" maxlength="300" <el-input v-model="form.title" :placeholder="$t('placeholder.title')" maxlength="300" class="title-input">
class="title-input">
<template #suffix> <template #suffix>
<span class="title-counter"><span :style="{ color: form.colorTag || '#dcdfe6' }">{{ form.title.length <span class="title-counter"><span :style="{ color: form.colorTag || '#dcdfe6' }">{{ form.title.length
}}</span>/300</span> }}</span>/300</span>
@ -108,8 +106,7 @@
</el-form-item> </el-form-item>
<el-form-item class="fujian" :label="$t('label.attachment')"> <el-form-item class="fujian" :label="$t('label.attachment')">
<el-upload class="upload-wrap" v-model:file-list="form.files" :auto-upload="false" :limit="1" <el-upload class="upload-wrap" v-model:file-list="form.files" :auto-upload="false" :limit="1"
:on-exceed="handleAttachmentExceed" :on-remove="handleAttachmentRemove" :on-exceed="handleAttachmentExceed" :on-remove="handleAttachmentRemove" :on-change="handleAttachmentChange">
:on-change="handleAttachmentChange">
<div class="upload-btn"> <div class="upload-btn">
<div class="left">+ 添加文件</div> <div class="left">+ 添加文件</div>
<div class="right">{{ $t('label.attachmentTip') }}</div> <div class="right">{{ $t('label.attachmentTip') }}</div>
@ -689,6 +686,7 @@ onBeforeUnmount(() => {
<style lang="scss"> <style lang="scss">
.hospital-order-form-dialog { .hospital-order-form-dialog {
max-width: 90vw;
width: 1168px; width: 1168px;
overflow: visible; overflow: visible;

@ -384,7 +384,7 @@ onBeforeUnmount(() => {
flex-wrap: wrap; flex-wrap: wrap;
gap: 12px; gap: 12px;
align-items: center; align-items: center;
width: 1800px; width: 100%;
:deep(.el-form-item), :deep(.el-form-item),
:deep(.el-button) { :deep(.el-button) {

@ -62,7 +62,7 @@
<img src="@/assets/image/hospital/ponits/gift-bear.svg" class="reward-img" alt="" /> <img src="@/assets/image/hospital/ponits/gift-bear.svg" class="reward-img" alt="" />
<div class="reward-text"> <div class="reward-text">
<div class="name">{{ REWARD_NAME }}</div> <div class="name">{{ REWARD_NAME }}</div>
<div class="desc">赚徽章·智聊语音互动</div> <div class="desc">限量款 · 智能语音互动</div>
</div> </div>
<button class="exchange-btn" :class="{ active: canExchange }" :disabled="!canExchange" <button class="exchange-btn" :class="{ active: canExchange }" :disabled="!canExchange"
@click="openExchangeModal"> @click="openExchangeModal">

Loading…
Cancel
Save