Bläddra i källkod

优化公告内容

xiongxing 2 veckor sedan
förälder
incheckning
36a2c85fd5

+ 46 - 18
src/api/elderly/elder/notice-customer/index.ts

@@ -1,37 +1,65 @@
 import request from '@/config/axios'
 
 /**
- * 探访公告(notice-customer)
+ * 须知(notice-customer)
  *
- * 说明:每个院区(租户)可自定义公告内容,小程序端通过接口获取并展示。
- * 接口前缀统一在下方 API_PREFIX 维护,如后端实际路径不同,改这一处即可。
+ * 后端接口:
+ * - 创建:POST /jiashu/notice/create
+ * - 更新:PUT /jiashu/notice/update
+ * - 列表:GET /jiashu/notice/listByType
  */
-const API_PREFIX = 'elderly/notice-customer'
+const API_PREFIX = '/jiashu/notice'
 
-/** 探访公告 VO */
+/**
+ * 须知类型:APPOINTMENT 预约须知 / VISIT 探访须知
+ * 后台只维护 APPOINTMENT(VISIT 为后端固定文案)
+ */
+export type NoticeCustomerType = 'APPOINTMENT' | 'VISIT'
+
+/** 须知 VO */
 export interface NoticeCustomerVO {
+  /** 须知编号,修改时必传 */
   id?: number
+  /** 须知类型:APPOINTMENT 或者 VISIT */
+  type?: NoticeCustomerType
+  /** 须知内容 */
+  content?: string
+  /** 机构(租户)id */
+  tenantId?: number
+}
+
+/**
+ * 根据须知类型 + 机构 id 查询须知列表
+ */
+export const getNoticeCustomerList = async (params: {
+  type: NoticeCustomerType
+  /** 机构 id,不传时获取初始化(默认)须知数据 */
   tenantId?: number
-  /** 公告内容,各条以 \n 换行 */
-  notice?: string
-  createTime?: string
-  updateTime?: string
-  creator?: string
-  updater?: string
+}) => {
+  const data = await request.get<NoticeCustomerVO[]>({
+    url: `${API_PREFIX}/listByType`,
+    params
+  })
+  return (data || []) as NoticeCustomerVO[]
+}
+
+/**
+ * 创建须知
+ */
+export const createNoticeCustomer = (data: NoticeCustomerVO) => {
+  return request.post({ url: `${API_PREFIX}/create`, data })
 }
 
 /**
- * 查询指定院区的探访公告
- * @param tenantId 院区(租户)id
+ * 更新须知(id 必传)
  */
-export const getNoticeCustomer = async (tenantId: number) => {
-  const data = await request.get({ url: `${API_PREFIX}/get`, params: { tenantId } })
-  return (data || {}) as NoticeCustomerVO
+export const updateNoticeCustomer = (data: NoticeCustomerVO) => {
+  return request.put({ url: `${API_PREFIX}/update`, data })
 }
 
 /**
- * 保存指定院区的探访公告(存在 id 走更新,否则新增)
+ * 保存须知:有 id 走更新,无 id 走新增
  */
 export const saveNoticeCustomer = (data: NoticeCustomerVO) => {
-  return request.post({ url: `${API_PREFIX}/save`, data })
+  return data.id ? updateNoticeCustomer(data) : createNoticeCustomer(data)
 }

+ 71 - 18
src/views/elderly/elder/notice-customer/index.vue

@@ -28,7 +28,7 @@
   <ContentWrap>
     <div class="mb-15px flex items-center justify-between">
       <div class="flex items-center">
-        <span class="text-16px font-bold">探访公告内容</span>
+        <span class="text-16px font-bold">预约须知内容</span>
         <span class="ml-10px text-12px text-gray-500">保存后小程序端将展示该内容</span>
       </div>
       <div>
@@ -43,33 +43,37 @@
 
     <el-input
       v-loading="loading"
-      v-model="formData.notice"
+      v-model="formData.content"
       type="textarea"
       :rows="18"
       maxlength="2000"
       show-word-limit
-      placeholder="请输入探访公告内容,每条建议单独一行(换行即视为一条)"
+      placeholder="请输入须知内容,每条建议单独一行(换行即视为一条)"
     />
   </ContentWrap>
 
   <ContentWrap>
     <div class="mb-15px text-16px font-bold">小程序预览</div>
     <div class="preview-wrap">
-      <div class="preview-title">探访公告</div>
+      <div class="preview-title">预约须知</div>
       <div class="preview-content">
         <template v-if="previewLines.length">
           <p v-for="(line, index) in previewLines" :key="index" class="preview-line">
             {{ line }}
           </p>
         </template>
-        <div v-else class="text-gray-400">暂无公告内容</div>
+        <div v-else class="text-gray-400">暂无须知内容</div>
       </div>
     </div>
   </ContentWrap>
 </template>
 
 <script lang="ts" setup>
-import { getNoticeCustomer, saveNoticeCustomer } from '@/api/elderly/elder/notice-customer'
+import {
+  createNoticeCustomer,
+  getNoticeCustomerList,
+  saveNoticeCustomer
+} from '@/api/elderly/elder/notice-customer'
 import { useUserStore } from '@/store/modules/user'
 
 defineOptions({ name: 'NoticeCustomer' })
@@ -77,6 +81,9 @@ defineOptions({ name: 'NoticeCustomer' })
 const userStore = useUserStore()
 const message = useMessage()
 
+/** 须知类型固定为预约须知(APPOINTMENT,VISIT 为后端固定文案) */
+const NOTICE_TYPE = 'APPOINTMENT' as const
+
 const loading = ref(false)
 const saveLoading = ref(false)
 
@@ -85,12 +92,12 @@ const queryParams = reactive({
 })
 const formData = reactive({
   id: undefined as number | undefined,
-  notice: ''
+  content: ''
 })
 
 // 预览:按换行拆分为多条
 const previewLines = computed(() =>
-  (formData.notice || '')
+  (formData.content || '')
     .split('\n')
     .map((item) => item.trim())
     .filter((item) => item)
@@ -102,23 +109,68 @@ const currentTenantId = computed(() => queryParams.tenantIds?.[0])
 /** 是否集团账号:集团账号可切换院区,普通院区账号固定为当前院区 */
 const canSwitchTenant = computed(() => !!userStore.getOrgTenant?.multiple)
 
-/** 查询院区公告 */
+/** 按机构查询须知(返回第一条) */
+const fetchDetail = async () => {
+  const list = await getNoticeCustomerList({
+    type: NOTICE_TYPE,
+    tenantId: currentTenantId.value
+  })
+  return list?.[0]
+}
+
+/**
+ * 用初始化数据为当前机构创建须知
+ * 后端未做初始化:机构下无数据时,不传 tenantId 再查一次拿到初始须知,
+ * 自动创建到当前机构下
+ */
+const initNotice = async () => {
+  try {
+    const defaultList = await getNoticeCustomerList({ type: NOTICE_TYPE })
+    const initContent = defaultList?.[0]?.content
+    if (!initContent) {
+      return false
+    }
+    await createNoticeCustomer({
+      type: NOTICE_TYPE,
+      tenantId: currentTenantId.value,
+      content: initContent
+    })
+    return true
+  } catch {
+    return false
+  }
+}
+
+/** 查询院区须知:无数据时先自动初始化,再查询回填 */
 const getDetail = async () => {
   if (!currentTenantId.value) {
-    message.warning('请先选择院区')
+    message.warning('请先选择机构')
     return
   }
   loading.value = true
   try {
-    const data = await getNoticeCustomer(currentTenantId.value)
-    formData.id = data?.id
-    formData.notice = data?.notice || ''
+    const detail = await fetchDetail()
+    if (detail) {
+      formData.id = detail.id
+      formData.content = detail.content || ''
+      return
+    }
+    // 机构下无数据 -> 自动初始化后再查一次回填
+    const created = await initNotice()
+    if (created) {
+      const newDetail = await fetchDetail()
+      formData.id = newDetail?.id
+      formData.content = newDetail?.content || ''
+      return
+    }
+    formData.id = undefined
+    formData.content = ''
   } finally {
     loading.value = false
   }
 }
 
-/** 切换院区 / 查询 */
+/** 切换机构 / 查询 */
 const handleQuery = () => {
   getDetail()
 }
@@ -126,19 +178,20 @@ const handleQuery = () => {
 /** 保存 */
 const handleSave = async () => {
   if (!currentTenantId.value) {
-    message.warning('请先选择院区')
+    message.warning('请先选择机构')
     return
   }
-  if (!formData.notice || !formData.notice.trim()) {
-    message.warning('公告内容不能为空')
+  if (!formData.content || !formData.content.trim()) {
+    message.warning('须知内容不能为空')
     return
   }
   saveLoading.value = true
   try {
     await saveNoticeCustomer({
       id: formData.id,
+      type: NOTICE_TYPE,
       tenantId: currentTenantId.value,
-      notice: formData.notice
+      content: formData.content
     })
     message.success('保存成功')
     await getDetail()