Commit 64958ad7 by lijiabin

【需求 17679】 perf: 继续优化 完善实践内容、优化文章内容换展示等

parent cfe3bd46
import service from '@/utils/request/index' import service from '@/utils/request/index'
import type { AddOrUpdateTagDto, BackendTagListItemDto, BackendTagSearchParams } from './types' import type {
ChangeUsageStatusDto,
AuditCaseDto,
BackendCaseListItemDto,
CaseListSearchParams,
} from './types'
import type { BackendServicePageResult } from '@/utils/request/types' import type { BackendServicePageResult } from '@/utils/request/types'
// 后台管理案例库相关接口 // 后台管理案例库相关接口
/** /**
* 案例库后台列表 * 案例库后台列表
*/ */
export const getCaseList = (data: PageSearchParams) => { export const getCaseList = (data: CaseListSearchParams) => {
return service.request<BackendServicePageResult<BackendTagListItemDto>>({ return service.request<BackendServicePageResult<BackendCaseListItemDto>>({
url: '/api/cultureCase/caseListByPage', url: '/api/cultureCase/caseListByPage',
method: 'POST', method: 'POST',
data, data,
...@@ -15,9 +20,19 @@ export const getCaseList = (data: PageSearchParams) => { ...@@ -15,9 +20,19 @@ export const getCaseList = (data: PageSearchParams) => {
} }
/** /**
* 删除案例库
*/
export const deleteCase = (id: number) => {
return service.request({
url: `/api/cultureCase/deleteCase?id=${id}`,
method: 'POST',
})
}
/**
* 审核接口 * 审核接口
*/ */
export const auditCase = (data: AddOrUpdateCarouselDto) => { export const auditCase = (data: AuditCaseDto) => {
return service.request({ return service.request({
url: '/api/cultureCase/auditCase', url: '/api/cultureCase/auditCase',
method: 'POST', method: 'POST',
...@@ -26,11 +41,13 @@ export const auditCase = (data: AddOrUpdateCarouselDto) => { ...@@ -26,11 +41,13 @@ export const auditCase = (data: AddOrUpdateCarouselDto) => {
} }
/** /**
* 删除案例库 * 修改使用状态
*/ */
export const deleteCase = (id: number) => {
export const changeUsageStatus = (data: ChangeUsageStatusDto) => {
return service.request({ return service.request({
url: `/api/cultureCase/deleteCase?id=${id}`, url: '/api/cultureCase/userCase',
method: 'POST', method: 'POST',
data,
}) })
} }
import { UsageStatusEnum, AuditStatusEnum } from '@/constants'
import type { PageSearchParams } from '@/utils/request/types'
export interface CaseListSearchParams extends PageSearchParams {
isAudit?: AuditStatusEnum
isUse?: UsageStatusEnum
title?: string
}
export interface BackendCaseListItemDto {
caseType: string
content: string
createTime: number
createUser: number
cultureKeywordMain: string
cultureKeywordSecond: string[]
cultureRelation: number
dataSources: number
depIdList: string[]
depNameList: string[]
deptId: string
deptName: string
id: number
integrity: number
isAudit: number
isDelete: number
isDispose: number
isUse: number
mainScene: string
minorScene: string
number: string
sceneKeywordMain: string
sceneKeywordSecond: string[]
sourceProject: string
sourceTime: number
sourceType: string
sourceUser: number
title: string
yearKeywordMain: string
yearKeywordSecond: string[]
sourceUserName: string
sourceUserWorkNo: string
}
export interface ChangeUsageStatusDto {
id: number
isUse: UsageStatusEnum
}
export interface AuditCaseDto {
id: number
isAudit: AuditStatusEnum
}
...@@ -16,6 +16,7 @@ export interface BackendColumnListItemDto { ...@@ -16,6 +16,7 @@ export interface BackendColumnListItemDto {
color: string color: string
createTime: number createTime: number
createUserId: number createUserId: number
content: string
id: number id: number
isDelete: number isDelete: number
postCount: number postCount: number
......
...@@ -4,12 +4,12 @@ import type { TagItemDto } from './types' ...@@ -4,12 +4,12 @@ import type { TagItemDto } from './types'
/** /**
* 获取标签 不分页 * 获取标签 不分页
*/ */
export const getTagList = () => { export const getTagList = (type?: string) => {
return service.request<TagItemDto[]>({ return service.request<TagItemDto[]>({
url: '/api/cultureTag/listNoPage', url: '/api/cultureTag/listNoPage',
method: 'POST', method: 'POST',
data: { data: {
type: 'culture', type,
}, },
}) })
} }
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
<!-- 文章内容 --> <!-- 文章内容 -->
<div v-if="!isHtml" class="prose prose-lg max-w-none"> <div v-if="!isHtml" class="prose prose-lg max-w-none">
<div class="text-gray-700 leading-relaxed space-y-4"> <div class="text-gray-700 leading-relaxed space-y-4 whitespace-pre-line">
{{ articleDetail?.content }} {{ articleDetail?.content }}
</div> </div>
......
...@@ -4,7 +4,12 @@ ...@@ -4,7 +4,12 @@
<!-- 主输入区域 --> <!-- 主输入区域 -->
<div class="flex gap-3 mb-2 items-start"> <div class="flex gap-3 mb-2 items-start">
<!-- 用户头像 --> <!-- 用户头像 -->
<el-avatar :size="48" :src="userAvatar" class="flex-shrink-0"> <el-avatar
:size="48"
:src="userAvatar"
class="flex-shrink-0"
@click="() => console.log(form)"
>
<el-icon> <el-icon>
<User /> <User />
</el-icon> </el-icon>
...@@ -14,12 +19,25 @@ ...@@ -14,12 +19,25 @@
<div class="flex-1"> <div class="flex-1">
<!-- 话题标签输入 --> <!-- 话题标签输入 -->
<div class="mb-4"> <div class="mb-4">
<el-input v-model="form.title" :placeholder="textMap[type].title" class="tag-input" clearable /> <el-input
v-model="form.title"
:placeholder="textMap[type].title"
class="tag-input"
clearable
/>
</div> </div>
<!-- 主要内容输入 --> <!-- 主要内容输入 -->
<div class="relative mb-3"> <div class="relative mb-3">
<el-input type="textarea" :placeholder="textMap[type].content" :rows="6" :maxlength="maxLength" <el-input
show-word-limit resize="none" class="main-textarea" v-model="form.content" /> type="textarea"
:placeholder="textMap[type].content"
:rows="6"
:maxlength="maxLength"
show-word-limit
resize="none"
class="main-textarea"
v-model="form.content"
/>
<!-- 字符计数 --> <!-- 字符计数 -->
<!-- <div class="absolute bottom-3 right-3 text-xs text-gray-400">1/30</div> --> <!-- <div class="absolute bottom-3 right-3 text-xs text-gray-400">1/30</div> -->
</div> </div>
...@@ -27,10 +45,12 @@ ...@@ -27,10 +45,12 @@
<div class="mb-2"> <div class="mb-2">
<!-- 选择的标签内容 --> <!-- 选择的标签内容 -->
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span v-if="mainTagText" class="text-sm text-gray-500">主标签: <span v-if="mainTagText" class="text-sm text-gray-500"
>主标签:
<el-tag>{{ mainTagText }}</el-tag> <el-tag>{{ mainTagText }}</el-tag>
</span> </span>
<span v-if="subTagTextList.length > 0" class="text-sm text-gray-500">副标签: <span v-if="subTagTextList.length > 0" class="text-sm text-gray-500"
>副标签:
<el-tag class="mr-2" v-for="tag in subTagTextList" :key="tag">{{ tag }}</el-tag> <el-tag class="mr-2" v-for="tag in subTagTextList" :key="tag">{{ tag }}</el-tag>
</span> </span>
</div> </div>
...@@ -38,15 +58,24 @@ ...@@ -38,15 +58,24 @@
<!-- 图片相关 --> <!-- 图片相关 -->
<div v-if="form.imgUrl.length" class="flex flex-wrap gap-2"> <div v-if="form.imgUrl.length" class="flex flex-wrap gap-2">
<!-- 删除图片 --> <!-- 删除图片 -->
<div class="relative w-20 h-20 rounded-lg overflow-hidden group" v-for="img in form.imgUrl" :key="img"> <div
class="relative w-20 h-20 rounded-lg overflow-hidden group"
v-for="img in form.imgUrl"
:key="img"
>
<div <div
class="absolute top-1 right-1 z-10 w-5 h-5 flex items-center justify-center bg-black/60 rounded-full cursor-pointer opacity-0 group-hover:opacity-100 transition-all duration-200 hover:bg-black/80 hover:scale-110" class="absolute top-1 right-1 z-10 w-5 h-5 flex items-center justify-center bg-black/60 rounded-full cursor-pointer opacity-0 group-hover:opacity-100 transition-all duration-200 hover:bg-black/80 hover:scale-110"
@click="handleDeleteImg(img)"> @click="handleDeleteImg(img)"
>
<el-icon class="text-white text-xs"> <el-icon class="text-white text-xs">
<Close /> <Close />
</el-icon> </el-icon>
</div> </div>
<el-image :src="img" class="w-full h-full rounded-lg border border-gray-200" fit="cover" /> <el-image
:src="img"
class="w-full h-full rounded-lg border border-gray-200"
fit="cover"
/>
</div> </div>
</div> </div>
</div> </div>
...@@ -57,9 +86,14 @@ ...@@ -57,9 +86,14 @@
<!-- 左侧工具按钮 --> <!-- 左侧工具按钮 -->
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<el-tooltip content="添加标签" placement="top" :visible="visibleTagTooltip"> <el-tooltip content="添加标签" placement="top" :visible="visibleTagTooltip">
<el-button ref="tagButtonRef" text <el-button
class="w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg" @click="handleAddTag" ref="tagButtonRef"
@mouseenter="visibleTagTooltip = true" @mouseleave="visibleTagTooltip = false"> text
class="w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
@click="handleAddTag"
@mouseenter="visibleTagTooltip = true"
@mouseleave="visibleTagTooltip = false"
>
<el-icon size="18"> <el-icon size="18">
<CollectionTag /> <CollectionTag />
</el-icon> </el-icon>
...@@ -69,8 +103,11 @@ ...@@ -69,8 +103,11 @@
<!-- 隐藏上传文件的input --> <!-- 隐藏上传文件的input -->
<input type="file" class="hidden" ref="fileInputRef" @change="handleFileChange" /> <input type="file" class="hidden" ref="fileInputRef" @change="handleFileChange" />
<el-tooltip content="添加图片" placement="top"> <el-tooltip content="添加图片" placement="top">
<el-button text class="w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg" <el-button
@click="fileInputRef?.click()"> text
class="w-10 h-10 text-gray-500 hover:bg-gray-100 hover:text-gray-700 rounded-lg"
@click="fileInputRef?.click()"
>
<el-icon size="18"> <el-icon size="18">
<Picture /> <Picture />
</el-icon> </el-icon>
...@@ -100,19 +137,27 @@ ...@@ -100,19 +137,27 @@
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<el-button <el-button
class="px-4 py-2 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded-lg border border-gray-200 text-sm" class="px-4 py-2 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded-lg border border-gray-200 text-sm"
@click="handlePublish(ReleaseStatusTypeEnum.DRAFT)"> @click="handlePublish(ReleaseStatusTypeEnum.DRAFT)"
>
存草稿 存草稿
</el-button> </el-button>
<el-button type="primary" :disabled="disabledSubmit" <el-button
type="primary"
:disabled="disabledSubmit"
class="px-6 py-2 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200" class="px-6 py-2 bg-blue-500 hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
@click="handlePublish(ReleaseStatusTypeEnum.PUBLISH)"> @click="handlePublish(ReleaseStatusTypeEnum.PUBLISH)"
>
发布 {{ type === ArticleTypeEnum.QUESTION ? '问题' : '实践' }} 发布 {{ type === ArticleTypeEnum.QUESTION ? '问题' : '实践' }}
</el-button> </el-button>
</div> </div>
</div> </div>
</div> </div>
<SelectTagsDialog v-model:mainTagId="form.mainTagId" v-model:tagList="form.tagList" ref="selectTagsDialogRef" /> <SelectTagsDialog
v-model:mainTagId="form.mainTagId"
v-model:tagList="form.tagList"
ref="selectTagsDialogRef"
/>
<el-tour v-model="openTour" :mask="false" placement="left-start" type="primary"> <el-tour v-model="openTour" :mask="false" placement="left-start" type="primary">
<el-tour-step :target="tagButtonRef?.$el" description="在这里选择标签" placement="top" /> <el-tour-step :target="tagButtonRef?.$el" description="在这里选择标签" placement="top" />
...@@ -137,7 +182,11 @@ import { useAnimate } from '@vueuse/core' ...@@ -137,7 +182,11 @@ import { useAnimate } from '@vueuse/core'
type ArticleType = ArticleTypeEnum.QUESTION | ArticleTypeEnum.PRACTICE type ArticleType = ArticleTypeEnum.QUESTION | ArticleTypeEnum.PRACTICE
const { type, isReal, maxLength = 500 } = defineProps<{ const {
type,
isReal,
maxLength = 500,
} = defineProps<{
type: ArticleType type: ArticleType
isReal: BooleanFlag isReal: BooleanFlag
maxLength?: number maxLength?: number
......
...@@ -65,13 +65,17 @@ import { useTagsStore } from '@/stores/tags' ...@@ -65,13 +65,17 @@ import { useTagsStore } from '@/stores/tags'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import type { TagItemDto } from '@/api/tag/types' import type { TagItemDto } from '@/api/tag/types'
import type { SelectTagProps } from './types' import type { SelectTagProps } from './types'
const { maxSelectedTags = 1, filterTagsFn } = defineProps<SelectTagProps>() const { maxSelectedTags = 1, filterTagsFn, tagType = 'culture' } = defineProps<SelectTagProps>()
const emit = defineEmits<{ const emit = defineEmits<{
selected: [tag?: TagItemDto] selected: [tag?: TagItemDto]
}>() }>()
const tagsStore = useTagsStore() const tagsStore = useTagsStore()
const { tagList } = storeToRefs(tagsStore) const { tagList: cultureTagList, relatedScenariosTagList } = storeToRefs(tagsStore)
const tagList = computed<TagItemDto[]>(() =>
tagType === 'culture' ? cultureTagList.value : relatedScenariosTagList.value,
)
const filterTags = computed(() => { const filterTags = computed(() => {
if (filterTagsFn) { if (filterTagsFn) {
...@@ -155,10 +159,4 @@ const toggleTag = (tagId: number) => { ...@@ -155,10 +159,4 @@ const toggleTag = (tagId: number) => {
addTag(tagId) addTag(tagId)
} }
} }
// onMounted(() => {
// if (tagList.value.length === 0) {
// tagsStore.fetchTagList()
// }
// })
</script> </script>
...@@ -3,4 +3,5 @@ import type { TagItemDto } from '@/api/tag/types' ...@@ -3,4 +3,5 @@ import type { TagItemDto } from '@/api/tag/types'
export type SelectTagProps = { export type SelectTagProps = {
maxSelectedTags?: number maxSelectedTags?: number
filterTagsFn?: (tags: TagItemDto[]) => TagItemDto[] filterTagsFn?: (tags: TagItemDto[]) => TagItemDto[]
tagType?: 'culture' | 'related_scenarios'
} }
...@@ -90,3 +90,11 @@ export enum AuditStatusEnum { ...@@ -90,3 +90,11 @@ export enum AuditStatusEnum {
// 驳回审核 // 驳回审核
REJECTED = 2, REJECTED = 2,
} }
// 使用状态枚举
export enum UsageStatusEnum {
// 待使用
UNUSABLE = 0,
// 已使用
USED = 1,
}
import { ArticleTypeEnum, AuditStatusEnum, CommentTypeEnum, TaskTypeEnum } from './enums' import {
ArticleTypeEnum,
AuditStatusEnum,
CommentTypeEnum,
TaskTypeEnum,
UsageStatusEnum,
} from './enums'
// 地区列表 // 地区列表
export const regionListOptions = [ export const regionListOptions = [
...@@ -106,6 +112,18 @@ export const auditTypeListOptions: { label: string; value: AuditStatusEnum }[] = ...@@ -106,6 +112,18 @@ export const auditTypeListOptions: { label: string; value: AuditStatusEnum }[] =
}, },
] ]
// 使用状态列表
export const usageStatusListOptions: { label: string; value: UsageStatusEnum }[] = [
{
label: '待使用',
value: UsageStatusEnum.UNUSABLE,
},
{
label: '已使用',
value: UsageStatusEnum.USED,
},
]
// 任务类型列表 // 任务类型列表
export const taskTypeListOptions = [ export const taskTypeListOptions = [
{ {
......
...@@ -104,7 +104,7 @@ export default defineComponent((_, { expose }) => { ...@@ -104,7 +104,7 @@ export default defineComponent((_, { expose }) => {
<el-input <el-input
v-model={form.value.content} v-model={form.value.content}
type="textarea" type="textarea"
placeholder="分享你的企业文化实践实例" placeholder="请输入专栏内容"
rows={6} rows={6}
maxlength={1000} maxlength={1000}
show-word-limit show-word-limit
......
...@@ -101,7 +101,7 @@ export default defineComponent((_, { expose }) => { ...@@ -101,7 +101,7 @@ export default defineComponent((_, { expose }) => {
<el-input <el-input
v-model={form.value.content} v-model={form.value.content}
type="textarea" type="textarea"
placeholder="分享你的企业文化实践实例" placeholder="请输入专访内容"
rows={6} rows={6}
maxlength={1000} maxlength={1000}
show-word-limit show-word-limit
......
...@@ -92,7 +92,7 @@ export default defineComponent((_, { expose }) => { ...@@ -92,7 +92,7 @@ export default defineComponent((_, { expose }) => {
type="textarea" type="textarea"
placeholder="分享你的企业文化实践实例" placeholder="分享你的企业文化实践实例"
rows={6} rows={6}
maxlength={1000} maxlength={2000}
show-word-limit show-word-limit
class="content-input" class="content-input"
/> />
......
...@@ -5,15 +5,20 @@ import type { TagItemDto } from '@/api/tag/types' ...@@ -5,15 +5,20 @@ import type { TagItemDto } from '@/api/tag/types'
* 关于标签的store * 关于标签的store
*/ */
export const useTagsStore = defineStore('tags', () => { export const useTagsStore = defineStore('tags', () => {
// 文化关键词标签
const tagList = ref<TagItemDto[]>([]) const tagList = ref<TagItemDto[]>([])
// 关联场景相关的标签
const relatedScenariosTagList = ref<TagItemDto[]>([])
let isLoading = false let isLoading = false
const fetchTagList = async () => { const fetchAllTagList = async () => {
if (isLoading) return if (isLoading) return
isLoading = true isLoading = true
try { try {
const { data } = await getTagList() const { data } = await getTagList()
tagList.value = data tagList.value = data.filter((i) => i.type === 'culture')
relatedScenariosTagList.value = data.filter((i) => i.type === 'related_scenarios')
console.log(tagList.value, 'tagList') console.log(tagList.value, 'tagList')
} catch (error) { } catch (error) {
console.error(error) console.error(error)
...@@ -22,7 +27,7 @@ export const useTagsStore = defineStore('tags', () => { ...@@ -22,7 +27,7 @@ export const useTagsStore = defineStore('tags', () => {
} }
} }
// 手动调用一次 // 手动调用一次
fetchTagList() fetchAllTagList()
return { tagList, fetchTagList } return { tagList, fetchAllTagList, relatedScenariosTagList }
}) })
export * from './app' export * from './app'
export * from './wxUtil'
...@@ -46,22 +46,28 @@ export function wxShare(option: IShareWxOption) { ...@@ -46,22 +46,28 @@ export function wxShare(option: IShareWxOption) {
*/ */
interface ISelectDepOrUser { interface ISelectDepOrUser {
err_msg: string err_msg: string
result: { result: IResult
}
interface IResult {
userList: ISelectUser[] userList: ISelectUser[]
} departmentList: ISelectDept[]
} }
interface ISelectUser { interface ISelectUser {
id: string id: string
name: string name: string
avatar: string avatar: string
} }
export function selectDepOrUser(wxOption = {}): Promise<ISelectDepOrUser> { interface ISelectDept {
id: string
name: string
}
export function selectDepOrUser(wxOption = {}): Promise<IResult> {
const defaultOption = { const defaultOption = {
fromDepartmentId: -1, fromDepartmentId: -1,
mode: 'single', mode: 'single', // single multi
type: ['user', 'department'], type: ['user', 'department'], // 'user' 'department'
// "selectedDepartmentIds": [], // "selectedDepartmentIds": ['2', '3'],
// "selectedUserIds": checkPerson // "selectedUserIds": ['lisi', 'lisi2']
} }
const option = { const option = {
...defaultOption, ...defaultOption,
...@@ -70,7 +76,9 @@ export function selectDepOrUser(wxOption = {}): Promise<ISelectDepOrUser> { ...@@ -70,7 +76,9 @@ export function selectDepOrUser(wxOption = {}): Promise<ISelectDepOrUser> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
ww.invoke('selectEnterpriseContact', option, function (res: ISelectDepOrUser) { ww.invoke('selectEnterpriseContact', option, function (res: ISelectDepOrUser) {
if (res.err_msg == 'selectEnterpriseContact:ok') { if (res.err_msg == 'selectEnterpriseContact:ok') {
resolve(res) resolve(res.result)
} else {
reject(res)
} }
}) })
}) })
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
import { getWxSignature } from '@/api' import { getWxSignature } from '@/api'
import * as ww from '@wecom/jssdk' import * as ww from '@wecom/jssdk'
// export async function initWxConfig() { // export async function initWxConfig() {
// const url = location.href.split('#')[0] // const url = location.href.split('#')[0]
// const response = await getWxSignature(url) // const response = await getWxSignature(url)
...@@ -42,7 +41,7 @@ export async function initWxConfig() { ...@@ -42,7 +41,7 @@ export async function initWxConfig() {
ww.register({ ww.register({
corpId, // 必填,当前用户企业所属企业ID corpId, // 必填,当前用户企业所属企业ID
agentId, // 必填,当前应用的AgentID agentId, // 必填,当前应用的AgentID
jsApiList: ['shareAppMessage'], // 必填,需要使用的JSAPI列表 jsApiList: ['shareAppMessage', 'selectEnterpriseContact'], // 必填,需要使用的JSAPI列表
getConfigSignature: function () { getConfigSignature: function () {
return { return {
timestamp: timestamp, timestamp: timestamp,
......
...@@ -2,10 +2,18 @@ ...@@ -2,10 +2,18 @@
<div> <div>
<div class="header h-40px items-center justify-between"> <div class="header h-40px items-center justify-between">
<div class="left flex gap-3 flex items-center"> <div class="left flex gap-3 flex items-center">
<Tabs :modelValue="activeTab" @update:modelValue="(e) => updateActiveTab(e as string)" :tabs="tabs" /> <Tabs
:modelValue="activeTab"
@update:modelValue="(e) => updateActiveTab(e as string)"
:tabs="tabs"
/>
<!-- 直接在@change里面拿最新的动态组件实例 拿不到 可以在@enter 动画钩子里面拿 --> <!-- 直接在@change里面拿最新的动态组件实例 拿不到 可以在@enter 动画钩子里面拿 -->
<!-- 刷新图标 --> <!-- 刷新图标 -->
<el-icon size="15" class="cursor-pointer hover:rotate-180 transition-all duration-300" @click="handleRefresh"> <el-icon
size="15"
class="cursor-pointer hover:rotate-180 transition-all duration-300"
@click="handleRefresh"
>
<Refresh /> <Refresh />
</el-icon> </el-icon>
</div> </div>
...@@ -55,10 +63,12 @@ const handleRefresh = () => { ...@@ -55,10 +63,12 @@ const handleRefresh = () => {
const handleEnter = () => { const handleEnter = () => {
handleRefresh() handleRefresh()
} }
const updateActiveTab = (val: string) => { const updateActiveTab = (val: string) => {
if (val === '关爱基金') { if (val === '关爱基金') {
window.open('https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww42a2d34b42b8d721&redirect_uri=oa.yswg.com.cn:3456/careFund/publicNotice/index&response_type=code&scope=snsapi_base&state=#wechat_redirect', '_blank') window.open(
'https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww42a2d34b42b8d721&redirect_uri=oa.yswg.com.cn:3456/careFund/publicNotice/index&response_type=code&scope=snsapi_base&state=#wechat_redirect',
'_blank',
)
return return
} }
activeTab.value = val activeTab.value = val
......
...@@ -26,15 +26,14 @@ ...@@ -26,15 +26,14 @@
show-word-limit show-word-limit
/> />
</el-form-item> </el-form-item>
<!-- 关键词选择 --> <!-- 文化关键词选择 -->
<el-form-item label="文化关键词" class="mb-6" prop="mainTagId"> <el-form-item label="文化关键词" class="mb-6" prop="mainTagId">
<div class="flex flex-wrap gap-3"> <div class="flex items-start">
<div class="flex flex-wrap gap-3 items-start">
主标签 主标签
<SelectTags v-model="form.mainTagId" /> <SelectTags v-model="form.mainTagId" />
</div> </div>
</el-form-item> <div class="flex flex-wrap gap-3 items-start ml-5">
<el-form-item class="mb-6">
<div class="flex flex-wrap gap-3">
副标签 副标签
<SelectTags <SelectTags
v-model="form.subTagIds" v-model="form.subTagIds"
...@@ -42,6 +41,40 @@ ...@@ -42,6 +41,40 @@
:filter-tags-fn="filterTagsFn" :filter-tags-fn="filterTagsFn"
/> />
</div> </div>
</div>
</el-form-item>
<el-form-item label="关联场景" class="mb-6">
<div class="flex items-start">
<div class="flex flex-wrap gap-3 items-start">
主标签
<SelectTags v-model="form.relatedScenariosMainTagId" tagType="related_scenarios" />
</div>
<div class="flex flex-wrap gap-3 items-start ml-5">
副标签
<SelectTags
tagType="related_scenarios"
v-model="form.relatedScenariosSubTagIds"
:max-selected-tags="4"
:filter-tags-fn="filterRelatedScenariosTagsFn"
/>
</div>
</div>
</el-form-item>
<el-form-item label="关联部门" class="mb-6">
<div class="flex items-start gap-3">
<el-button class="button-new-tag" size="small" @click="selcetDept">
+ 添加部门
</el-button>
<el-tag
v-for="tag in form.departmentList"
:key="tag.id"
closable
type="primary"
@close="() => delDept(tag.id)"
>
{{ tag.name }}
</el-tag>
</div>
</el-form-item> </el-form-item>
<!-- 是否同步发布 --> <!-- 是否同步发布 -->
...@@ -53,15 +86,17 @@ ...@@ -53,15 +86,17 @@
</el-form-item> </el-form-item>
<!-- 底部按钮组 --> <!-- 底部按钮组 -->
<div class="flex items-center justify-between gap-4 pt-4"> <div class="flex items-center justify-end gap-4 pt-4">
<div class="flex gap-4"> <el-button class="rounded-lg" @click="handleCancel"> 取消 </el-button>
<el-button @click="handleCancel"> 取消 </el-button>
<!-- <el-button @click="handlePreview"> 预览 </el-button> --> <!-- <el-button @click="handlePreview"> 预览 </el-button> -->
<el-button type="info" plain @click="handleSubmit(ReleaseStatusTypeEnum.DRAFT)"> <el-button class="rounded-lg" plain @click="handleSubmit(ReleaseStatusTypeEnum.DRAFT)">
存草稿 存草稿
</el-button> </el-button>
</div> <el-button
<el-button type="primary" @click="handleSubmit(ReleaseStatusTypeEnum.PUBLISH)"> class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
type="primary"
@click="handleSubmit(ReleaseStatusTypeEnum.PUBLISH)"
>
提交 提交
</el-button> </el-button>
</div> </div>
...@@ -79,9 +114,12 @@ import SelectTags from '@/components/common/SelectTags/index.vue' ...@@ -79,9 +114,12 @@ import SelectTags from '@/components/common/SelectTags/index.vue'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import type { TagItemDto } from '@/api' import type { TagItemDto } from '@/api'
import { TagTypeEnum, TagLevelEnum, BooleanFlag, ReleaseStatusTypeEnum } from '@/constants' import { TagTypeEnum, TagLevelEnum, BooleanFlag, ReleaseStatusTypeEnum } from '@/constants'
import { selectDepOrUser } from '@/utils'
import { useUserStore } from '@/stores'
import { storeToRefs } from 'pinia'
const router = useRouter() const router = useRouter()
const userStore = useUserStore()
const { userInfo } = storeToRefs(userStore)
const formRef = useTemplateRef<FormInstance>('formRef') const formRef = useTemplateRef<FormInstance>('formRef')
const rules = { const rules = {
...@@ -96,10 +134,32 @@ const [form, resetForm] = useResetData({ ...@@ -96,10 +134,32 @@ const [form, resetForm] = useResetData({
content: '', content: '',
mainTagId: '', mainTagId: '',
subTagIds: [], subTagIds: [],
relatedScenariosMainTagId: '',
relatedScenariosSubTagIds: [],
isSync: BooleanFlag.NO, isSync: BooleanFlag.NO,
releaseStatus: ReleaseStatusTypeEnum.PUBLISH, releaseStatus: ReleaseStatusTypeEnum.PUBLISH,
deptId: '',
deptName: '',
departmentList: [],
}) })
// 选择部门
const selcetDept = async () => {
const { departmentList } = await selectDepOrUser({
mode: 'multi', // single multi
type: ['department'],
selectedDepartmentIds: form.value.departmentList.map((i) => i.id),
})
if (departmentList.length > 3) {
return ElMessage.warning('最多只能选择3个部门,请重新选择')
}
console.log('选中的部门等等', departmentList)
form.value.departmentList = departmentList
}
const delDept = (id: string) => {
form.value.departmentList = form.value.departmentList.filter((i) => i.id !== id)
}
// 取消 // 取消
const handleCancel = () => { const handleCancel = () => {
resetForm() resetForm()
...@@ -115,13 +175,20 @@ const handleCancel = () => { ...@@ -115,13 +175,20 @@ const handleCancel = () => {
// 保存草稿 // 保存草稿
const transformData = (releaseStatus: ReleaseStatusTypeEnum): AddOrUpdateCaseDto => { const transformData = (releaseStatus: ReleaseStatusTypeEnum): AddOrUpdateCaseDto => {
const { mainTagId, subTagIds, ...rest } = form.value const {
mainTagId,
subTagIds,
relatedScenariosMainTagId,
relatedScenariosSubTagIds,
departmentList,
...rest
} = form.value
const obj: AddOrUpdateCaseDto = { const obj: AddOrUpdateCaseDto = {
...rest, ...rest,
releaseStatus, releaseStatus,
tagRelationDtoList: [], tagRelationDtoList: [],
} }
// 添加标签内容 // 添加文化标签内容
obj.tagRelationDtoList.push({ obj.tagRelationDtoList.push({
tagId: Number(mainTagId), tagId: Number(mainTagId),
type: TagTypeEnum.CULTURE_TAG, type: TagTypeEnum.CULTURE_TAG,
...@@ -134,12 +201,32 @@ const transformData = (releaseStatus: ReleaseStatusTypeEnum): AddOrUpdateCaseDto ...@@ -134,12 +201,32 @@ const transformData = (releaseStatus: ReleaseStatusTypeEnum): AddOrUpdateCaseDto
keywordType: TagLevelEnum.SUB_TAG, keywordType: TagLevelEnum.SUB_TAG,
}) })
}) })
// 添加关联场景
obj.tagRelationDtoList.push({
tagId: Number(relatedScenariosMainTagId),
type: TagTypeEnum.SCENE_TAG,
keywordType: TagLevelEnum.MAIN_TAG,
})
relatedScenariosSubTagIds.forEach((id) => {
obj.tagRelationDtoList.push({
tagId: id,
type: TagTypeEnum.SCENE_TAG,
keywordType: TagLevelEnum.SUB_TAG,
})
})
// 添加部门相关字段
obj.deptId = departmentList.map((i) => i.id).join(',')
obj.deptName = departmentList.map((i) => i.name).join(',')
obj.sourceUser = userInfo.value.userId
return obj return obj
} }
// 提交 // 提交
const handleSubmit = async (releaseStatus: ReleaseStatusTypeEnum) => { const handleSubmit = async (releaseStatus: ReleaseStatusTypeEnum) => {
await formRef.value?.validate() await formRef.value?.validate()
console.log('form', { ...transformData(releaseStatus) })
const res = await addOrUpdateCase({ ...transformData(releaseStatus) }) const res = await addOrUpdateCase({ ...transformData(releaseStatus) })
if (res) { if (res) {
ElMessage.success('提交成功') ElMessage.success('提交成功')
...@@ -150,7 +237,7 @@ const handleSubmit = async (releaseStatus: ReleaseStatusTypeEnum) => { ...@@ -150,7 +237,7 @@ const handleSubmit = async (releaseStatus: ReleaseStatusTypeEnum) => {
const showSubmissionGuide = () => { const showSubmissionGuide = () => {
const countdown = ref(0) const countdown = ref(0)
let timer: number | null = null let timer: NodeJS.Timeout | null = null
const MessageContent = (): VNode => { const MessageContent = (): VNode => {
return ( return (
...@@ -172,7 +259,7 @@ const showSubmissionGuide = () => { ...@@ -172,7 +259,7 @@ const showSubmissionGuide = () => {
<div class="flex justify-center pt-3 border-t border-[#ebeef5]"> <div class="flex justify-center pt-3 border-t border-[#ebeef5]">
<el-button <el-button
type="primary" class="px-6 py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white text-sm font-medium shadow-sm hover:shadow-md transition-all duration-200"
disabled={countdown.value > 0} disabled={countdown.value > 0}
loading={countdown.value > 0} loading={countdown.value > 0}
onClick={() => { onClick={() => {
...@@ -211,6 +298,9 @@ const showSubmissionGuide = () => { ...@@ -211,6 +298,9 @@ const showSubmissionGuide = () => {
const filterTagsFn = (allTags: TagItemDto[]) => { const filterTagsFn = (allTags: TagItemDto[]) => {
return allTags.filter((tag) => tag.id !== Number(form.value.mainTagId)) return allTags.filter((tag) => tag.id !== Number(form.value.mainTagId))
} }
const filterRelatedScenariosTagsFn = (allTags: TagItemDto[]) => {
return allTags.filter((tag) => tag.id !== Number(form.value.relatedScenariosMainTagId))
}
onActivated(() => { onActivated(() => {
showSubmissionGuide() showSubmissionGuide()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment