| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- <template>
- <ContentWrap>
- <el-form
- class="-mb-15px"
- :model="queryParams"
- :inline="true"
- label-width="90px"
- >
- <TenantSelect
- v-model="queryParams.tenantIds"
- single
- :disabled="!canSwitchTenant"
- placeholder="请选择机构名称"
- prop="tenantIds"
- @change="handleQuery"
- />
- <el-form-item v-if="!canSwitchTenant">
- <span class="text-12px text-gray-500">当前账号已绑定院区,院区不可切换</span>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="handleQuery">
- <Icon icon="ep:search" class="mr-5px" /> 查询
- </el-button>
- </el-form-item>
- </el-form>
- </ContentWrap>
- <ContentWrap>
- <div class="mb-15px flex items-center justify-between">
- <div class="flex items-center">
- <span class="text-16px font-bold">预约须知内容</span>
- <span class="ml-10px text-12px text-gray-500">保存后小程序端将展示该内容</span>
- </div>
- <div>
- <el-button @click="handleQuery">
- <Icon icon="ep:refresh" class="mr-5px" /> 重新加载
- </el-button>
- <el-button type="primary" :loading="saveLoading" @click="handleSave">
- <Icon icon="ep:select" class="mr-5px" /> 保存
- </el-button>
- </div>
- </div>
- <el-input
- v-loading="loading"
- v-model="formData.content"
- type="textarea"
- :rows="18"
- maxlength="2000"
- show-word-limit
- placeholder="请输入须知内容,每条建议单独一行(换行即视为一条)"
- />
- </ContentWrap>
- <ContentWrap>
- <div class="mb-15px text-16px font-bold">小程序预览</div>
- <div class="preview-wrap">
- <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>
- </div>
- </ContentWrap>
- </template>
- <script lang="ts" setup>
- import {
- createNoticeCustomer,
- getNoticeCustomerList,
- saveNoticeCustomer
- } from '@/api/elderly/elder/notice-customer'
- import { useUserStore } from '@/store/modules/user'
- 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)
- const queryParams = reactive({
- tenantIds: userStore.orgTenantId || []
- })
- const formData = reactive({
- id: undefined as number | undefined,
- content: ''
- })
- // 预览:按换行拆分为多条
- const previewLines = computed(() =>
- (formData.content || '')
- .split('\n')
- .map((item) => item.trim())
- .filter((item) => item)
- )
- /** 当前选中院区 */
- const currentTenantId = computed(() => queryParams.tenantIds?.[0])
- /** 是否集团账号:集团账号可切换院区,普通院区账号固定为当前院区 */
- const canSwitchTenant = computed(() => !!userStore.getOrgTenant?.multiple)
- /** 内容换行处理:兼容后端存的字面量 \n */
- const normalizeContent = (content?: string) => (content || '').replace(/\\n/g, '\n')
- /** 按机构查询须知(返回第一条) */
- 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, tenantId: 1 })
- // 初始数据可能返回多条,用 \n 拼接后展示
- const initContent = (defaultList || [])
- .map((item) => normalizeContent(item?.content))
- .filter((item) => item.trim())
- .join('\n')
- 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('请先选择机构')
- return
- }
- loading.value = true
- try {
- const detail = await fetchDetail()
- if (detail) {
- formData.id = detail.id
- formData.content = normalizeContent(detail.content)
- return
- }
- // 机构下无数据 -> 自动初始化后再查一次回填
- const created = await initNotice()
- if (created) {
- const newDetail = await fetchDetail()
- formData.id = newDetail?.id
- formData.content = normalizeContent(newDetail?.content)
- return
- }
- formData.id = undefined
- formData.content = ''
- } finally {
- loading.value = false
- }
- }
- /** 切换机构 / 查询 */
- const handleQuery = () => {
- getDetail()
- }
- /** 保存 */
- const handleSave = async () => {
- if (!currentTenantId.value) {
- message.warning('请先选择机构')
- return
- }
- if (!formData.content || !formData.content.trim()) {
- message.warning('须知内容不能为空')
- return
- }
- saveLoading.value = true
- try {
- await saveNoticeCustomer({
- id: formData.id,
- type: NOTICE_TYPE,
- tenantId: currentTenantId.value,
- content: formData.content
- })
- message.success('保存成功')
- await getDetail()
- } finally {
- saveLoading.value = false
- }
- }
- /** 初始化 */
- onMounted(() => {
- getDetail()
- })
- </script>
- <style lang="scss" scoped>
- .preview-wrap {
- width: 320px;
- padding: 15px;
- background: #fafafa;
- border: 1px solid #e4e7ed;
- border-radius: 8px;
- }
- .preview-title {
- margin-bottom: 10px;
- font-weight: bold;
- text-align: center;
- }
- .preview-line {
- margin: 6px 0;
- font-size: 13px;
- line-height: 1.6;
- color: #333;
- }
- </style>
|