@@ -24,6 +24,49 @@ export namespace MpDraftApi {
|
||||
articles: Article[];
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** 图文项(包含预览字段) */
|
||||
export interface NewsItem {
|
||||
title: string;
|
||||
thumbMediaId: string;
|
||||
author: string;
|
||||
digest: string;
|
||||
showCoverPic: number;
|
||||
content: string;
|
||||
contentSourceUrl: string;
|
||||
needOpenComment: number;
|
||||
onlyFansCanComment: number;
|
||||
thumbUrl: string;
|
||||
picUrl?: string; // 用于预览封面
|
||||
}
|
||||
|
||||
/** 图文列表 */
|
||||
export interface NewsItemList {
|
||||
newsItem: NewsItem[];
|
||||
}
|
||||
|
||||
/** 草稿文章(用于展示) */
|
||||
export interface DraftArticle {
|
||||
mediaId: string;
|
||||
content: NewsItemList;
|
||||
updateTime: number;
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建空的图文项 */
|
||||
export function createEmptyNewsItem(): MpDraftApi.NewsItem {
|
||||
return {
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: 0,
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: 0,
|
||||
onlyFansCanComment: 0,
|
||||
thumbUrl: '',
|
||||
};
|
||||
}
|
||||
|
||||
/** 查询草稿列表 */
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
import { MaterialType } from '@vben/constants';
|
||||
|
||||
/** 素材类型枚举 */
|
||||
// TODO @hw:mp 相关的枚举,可以考虑放这里来。
|
||||
export enum MaterialType {
|
||||
IMAGE = 1, // 图片
|
||||
THUMB = 4, // 缩略图
|
||||
VIDEO = 3, // 视频
|
||||
VOICE = 2, // 语音
|
||||
}
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MpMaterialApi {
|
||||
/** 素材信息 */
|
||||
|
||||
@@ -1,20 +1,6 @@
|
||||
import { requestClient } from '#/api/request';
|
||||
import { MenuType } from '@vben/constants';
|
||||
|
||||
/** 菜单类型枚举 */
|
||||
// TODO @hw:mp 相关的枚举,可以考虑放这里来。
|
||||
export enum MenuType {
|
||||
CLICK = 'click', // 点击推事件
|
||||
LOCATION_SELECT = 'location_select', // 发送位置
|
||||
MEDIA_ID = 'media_id', // 下发消息
|
||||
MINIPROGRAM = 'miniprogram', // 小程序
|
||||
PIC_PHOTO_OR_ALBUM = 'pic_photo_or_album', // 拍照或者相册发图
|
||||
PIC_SYSPHOTO = 'pic_sysphoto', // 系统拍照发图
|
||||
PIC_WEIXIN = 'pic_weixin', // 微信相册发图
|
||||
SCANCODE_PUSH = 'scancode_push', // 扫码推事件
|
||||
SCANCODE_WAITMSG = 'scancode_waitmsg', // 扫码带提示
|
||||
VIEW = 'view', // 跳转 URL
|
||||
VIEW_LIMITED = 'view_limited', // 跳转图文消息URL
|
||||
}
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MpMenuApi {
|
||||
/** 菜单按钮信息 */
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
import { MessageType } from '@vben/constants';
|
||||
|
||||
/** 消息类型枚举 */
|
||||
// TODO @hw:mp 相关的枚举,可以考虑放这里来。
|
||||
export enum MessageType {
|
||||
IMAGE = 'image', // 图片消息
|
||||
MPNEWS = 'mpnews', // 公众号图文消息
|
||||
MUSIC = 'music', // 音乐消息
|
||||
NEWS = 'news', // 图文消息
|
||||
TEXT = 'text', // 文本消息
|
||||
VIDEO = 'video', // 视频消息
|
||||
VOICE = 'voice', // 语音消息
|
||||
WXCARD = 'wxcard', // 卡券消息
|
||||
}
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MpMessageApi {
|
||||
/** 消息信息 */
|
||||
|
||||
@@ -3,13 +3,11 @@ import type { VxeGridPropTypes } from '#/adapter/vxe-table';
|
||||
|
||||
import { markRaw } from 'vue';
|
||||
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { DICT_TYPE, AutoReplyMsgType as MsgType } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
|
||||
import { WxReply } from '#/views/mp/components';
|
||||
|
||||
import { MsgType } from './types';
|
||||
|
||||
// TODO @芋艿:要不要使用统一枚举?
|
||||
const RequestMessageTypes = new Set([
|
||||
'image',
|
||||
@@ -143,10 +141,6 @@ export function useFormSchema(msgType: MsgType): VbenFormSchema[] {
|
||||
fieldName: 'reply',
|
||||
label: '回复消息',
|
||||
component: markRaw(WxReply),
|
||||
// TODO @hw:这里注释,要不要删除掉?
|
||||
// componentProps: {
|
||||
// modelValue: { type: 'video', content: '12456' },
|
||||
// },
|
||||
modelPropName: 'modelValue',
|
||||
});
|
||||
return schema;
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { MpAutoReplyApi } from '#/api/mp/autoReply';
|
||||
import { computed, nextTick, ref } from 'vue';
|
||||
|
||||
import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||
import { AutoReplyMsgType as MsgType } from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { message, Row, Tabs } from 'ant-design-vue';
|
||||
@@ -21,7 +22,6 @@ import { WxAccountSelect } from '#/views/mp/components';
|
||||
import { useGridColumns, useGridFormSchema } from './data';
|
||||
import ReplyContentCell from './modules/content.vue';
|
||||
import Form from './modules/form.vue';
|
||||
import { MsgType } from './types';
|
||||
|
||||
defineOptions({ name: 'MpAutoReply' });
|
||||
|
||||
|
||||
@@ -4,16 +4,15 @@ import type { Reply } from '#/views/mp/components';
|
||||
import { computed, nextTick, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { AutoReplyMsgType as MsgType, ReplyType } from '@vben/constants';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from '#/adapter/form';
|
||||
import { createAutoReply, updateAutoReply } from '#/api/mp/autoReply';
|
||||
import { $t } from '#/locales';
|
||||
import { ReplyType } from '#/views/mp/components/constants';
|
||||
|
||||
import { useFormSchema } from '../data';
|
||||
import { MsgType } from '../types';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
|
||||
@@ -113,13 +112,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||
// 编辑:加载数据
|
||||
const rowData = data.row;
|
||||
const formValues: any = { ...rowData };
|
||||
// TODO @hw:下面要删除掉么,注释。
|
||||
// delete formValues.responseMessageType;
|
||||
// delete formValues.responseContent;
|
||||
// delete formValues.responseMediaId;
|
||||
// delete formValues.responseMediaUrl;
|
||||
// delete formValues.responseDescription;
|
||||
// delete formValues.responseArticles;
|
||||
formValues.reply = {
|
||||
type: rowData.responseMessageType,
|
||||
accountId: data.accountId || -1,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
// 消息类型(Follow: 关注时回复;Message: 消息回复;Keyword: 关键词回复)
|
||||
// 作为 tab.name,enum 的数字不能随意修改,与 api 参数相关
|
||||
// TODO @hw:可以搞到 biz-mp-enum.ts 里。
|
||||
export enum MsgType {
|
||||
Follow = 1,
|
||||
Keyword = 3,
|
||||
Message = 2,
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// TODO @hw:看看要不要迁移到 packages/constants/src/biz-mp-enum.ts
|
||||
export enum ReplyType {
|
||||
Image = 'image',
|
||||
Music = 'music',
|
||||
News = 'news',
|
||||
Text = 'text',
|
||||
Video = 'video',
|
||||
Voice = 'voice',
|
||||
}
|
||||
|
||||
export enum NewsType {
|
||||
Draft = '2',
|
||||
Published = '1',
|
||||
}
|
||||
|
||||
export enum MaterialType {
|
||||
Image = 'image',
|
||||
News = 'news',
|
||||
Video = 'video',
|
||||
Voice = 'voice',
|
||||
}
|
||||
|
||||
export enum MsgType {
|
||||
Event = 'event',
|
||||
Image = 'image',
|
||||
Link = 'link',
|
||||
Location = 'location',
|
||||
Music = 'music',
|
||||
News = 'news',
|
||||
Text = 'text',
|
||||
Video = 'video',
|
||||
Voice = 'voice',
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
export * from './constants';
|
||||
|
||||
export * from './wx-account-select';
|
||||
export * from './wx-location';
|
||||
export * from './wx-material-select';
|
||||
export * from './wx-msg';
|
||||
export * from './wx-music';
|
||||
export * from './wx-news';
|
||||
export * from './wx-reply';
|
||||
export * from './wx-video-play';
|
||||
export * from './wx-voice-play';
|
||||
|
||||
// TODO @hw:要不使用 export { default as WxAccountSelect } from './account-select.vue'; 形式;
|
||||
export { default as WxAccountSelect } from './wx-account-select/account-select.vue';
|
||||
export { default as WxLocation } from './wx-location/wx-location.vue';
|
||||
export { default as WxMaterialSelect } from './wx-material-select/wx-material-select.vue';
|
||||
export { default as WxMsg } from './wx-msg/msg.vue';
|
||||
export { default as WxMusic } from './wx-music/wx-music.vue';
|
||||
export { default as WxNews } from './wx-news/wx-news.vue';
|
||||
export { default as WxReply } from './wx-reply/wx-reply.vue';
|
||||
export { default as WxVideoPlayer } from './wx-video-play/wx-video-play.vue';
|
||||
export { default as WxVoicePlayer } from './wx-voice-play/wx-voice-play.vue';
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { NewsType } from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Pagination, Row, Spin } from 'ant-design-vue';
|
||||
@@ -14,8 +15,6 @@ import { getFreePublishPage } from '#/api/mp/freePublish';
|
||||
import { getMaterialPage } from '#/api/mp/material';
|
||||
import { WxNews, WxVideoPlayer, WxVoicePlayer } from '#/views/mp/components';
|
||||
|
||||
import { NewsType } from '../constants';
|
||||
|
||||
defineOptions({ name: 'WxMaterialSelect' });
|
||||
|
||||
const props = withDefaults(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { MpMsgType as MsgType } from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import {
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
WxVoicePlayer,
|
||||
} from '#/views/mp/components';
|
||||
|
||||
import { MsgType } from '../constants';
|
||||
import MsgEvent from './msg-event.vue';
|
||||
|
||||
defineOptions({ name: 'Msg' });
|
||||
|
||||
@@ -28,7 +28,7 @@ defineExpose({
|
||||
<Image
|
||||
:src="article.picUrl"
|
||||
:preview="false"
|
||||
class="material-img"
|
||||
class="material-img flex items-center justify-center"
|
||||
/>
|
||||
<div class="news-content-title">
|
||||
<span>{{ article.title }}</span>
|
||||
|
||||
@@ -3,14 +3,13 @@ import type { Reply } from './types';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { NewsType } from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Col, Modal, Row } from 'ant-design-vue';
|
||||
|
||||
import { WxMaterialSelect, WxNews } from '#/views/mp/components';
|
||||
|
||||
import { NewsType } from '../constants';
|
||||
|
||||
defineOptions({ name: 'TabNews' });
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Ref } from 'vue';
|
||||
|
||||
import type { ReplyType } from '../constants';
|
||||
import type { ReplyType } from '@vben/constants';
|
||||
|
||||
import { unref } from 'vue';
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ import type { Reply } from './types';
|
||||
|
||||
import { computed, ref, unref, watch } from 'vue';
|
||||
|
||||
import { NewsType, ReplyType } from '@vben/constants';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Row, Tabs } from 'ant-design-vue';
|
||||
|
||||
import { NewsType, ReplyType } from '../constants';
|
||||
import TabImage from './tab-image.vue';
|
||||
import TabMusic from './tab-music.vue';
|
||||
import TabNews from './tab-news.vue';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Article } from './modules/types';
|
||||
|
||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
import type { MpDraftApi } from '#/api/mp/draft';
|
||||
|
||||
import { confirm, DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
@@ -9,10 +8,9 @@ import { $t } from '@vben/locales';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import { deleteDraft, getDraftPage } from '#/api/mp/draft';
|
||||
import { createEmptyNewsItem, deleteDraft, getDraftPage } from '#/api/mp/draft';
|
||||
import { submitFreePublish } from '#/api/mp/freePublish';
|
||||
import { WxAccountSelect } from '#/views/mp/components';
|
||||
import { createEmptyNewsItem } from '#/views/mp/draft/modules/types';
|
||||
|
||||
import { useGridColumns, useGridFormSchema } from './data';
|
||||
import DraftTableCell from './modules/draft-table.vue';
|
||||
@@ -49,7 +47,7 @@ async function handleCreate() {
|
||||
}
|
||||
|
||||
/** 修改草稿 */
|
||||
async function handleEdit(row: Article) {
|
||||
async function handleEdit(row: MpDraftApi.DraftArticle) {
|
||||
const formValues = await gridApi.formApi.getValues();
|
||||
const accountId = formValues.accountId;
|
||||
if (!accountId) {
|
||||
@@ -67,7 +65,7 @@ async function handleEdit(row: Article) {
|
||||
}
|
||||
|
||||
/** 删除草稿 */
|
||||
async function handleDelete(row: Article) {
|
||||
async function handleDelete(row: MpDraftApi.DraftArticle) {
|
||||
const formValues = await gridApi.formApi.getValues();
|
||||
const accountId = formValues.accountId;
|
||||
if (!accountId) {
|
||||
@@ -89,7 +87,7 @@ async function handleDelete(row: Article) {
|
||||
}
|
||||
|
||||
/** 发布草稿 */
|
||||
async function handlePublish(row: Article) {
|
||||
async function handlePublish(row: MpDraftApi.DraftArticle) {
|
||||
const formValues = await gridApi.formApi.getValues();
|
||||
const accountId = formValues.accountId;
|
||||
if (!accountId) {
|
||||
@@ -145,7 +143,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
}
|
||||
});
|
||||
return {
|
||||
list: drafts.list as unknown as Article[],
|
||||
list: drafts.list as unknown as MpDraftApi.DraftArticle[],
|
||||
total: drafts.total,
|
||||
};
|
||||
},
|
||||
@@ -160,8 +158,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
refresh: true,
|
||||
search: true,
|
||||
},
|
||||
// TODO @hw:这里有点纠结,一般是 MpDraftApi.Article,但是一改貌似就 linter 告警了。
|
||||
} as VxeTableGridOptions<Article>,
|
||||
} as VxeTableGridOptions<MpDraftApi.DraftArticle>,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import type { UploadFile } from 'ant-design-vue';
|
||||
|
||||
import type { NewsItem } from './types';
|
||||
import type { MpDraftApi } from '#/api/mp/draft';
|
||||
|
||||
import { computed, inject, reactive, ref } from 'vue';
|
||||
|
||||
@@ -14,16 +14,16 @@ import { UploadType, useBeforeUpload } from '#/utils/useUpload';
|
||||
|
||||
const props = defineProps<{
|
||||
isFirst: boolean;
|
||||
modelValue: NewsItem;
|
||||
modelValue: MpDraftApi.NewsItem;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', v: NewsItem): void;
|
||||
(e: 'update:modelValue', v: MpDraftApi.NewsItem): void;
|
||||
}>();
|
||||
|
||||
const UPLOAD_URL = `${import.meta.env.VITE_BASE_URL}/admin-api/mp/material/upload-permanent`; // 上传永久素材的地址
|
||||
const HEADERS = { Authorization: `Bearer ${useAccessStore().accessToken}` };
|
||||
const newsItem = computed<NewsItem>({
|
||||
const newsItem = computed<MpDraftApi.NewsItem>({
|
||||
get() {
|
||||
return props.modelValue;
|
||||
},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Article } from './types';
|
||||
import type { MpDraftApi } from '#/api/mp/draft';
|
||||
|
||||
import { WxNews } from '#/views/mp/components';
|
||||
|
||||
defineOptions({ name: 'DraftTableCell' });
|
||||
|
||||
const props = defineProps<{
|
||||
row: Article;
|
||||
row: MpDraftApi.DraftArticle;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import type { NewsItem } from './types';
|
||||
import type { MpDraftApi } from '#/api/mp/draft';
|
||||
|
||||
import { computed, provide, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message, Spin } from 'ant-design-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { createDraft, updateDraft } from '#/api/mp/draft';
|
||||
|
||||
@@ -16,10 +16,9 @@ const emit = defineEmits(['success']);
|
||||
const formData = ref<{
|
||||
accountId: number;
|
||||
mediaId?: string;
|
||||
newsList?: NewsItem[];
|
||||
newsList?: MpDraftApi.NewsItem[];
|
||||
}>();
|
||||
const newsList = ref<NewsItem[]>([]);
|
||||
const isSubmitting = ref(false);
|
||||
const newsList = ref<MpDraftApi.NewsItem[]>([]);
|
||||
|
||||
const getTitle = computed(() => {
|
||||
return formData.value?.mediaId ? '修改图文' : '新建图文';
|
||||
@@ -35,9 +34,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||
if (!formData.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO @hw:是不是 isSubmitting 非必须哈?因为 modal 已经去 lock 啦。
|
||||
isSubmitting.value = true;
|
||||
modalApi.lock();
|
||||
try {
|
||||
if (formData.value.mediaId) {
|
||||
@@ -54,7 +50,6 @@ const [Modal, modalApi] = useVbenModal({
|
||||
await modalApi.close();
|
||||
emit('success');
|
||||
} finally {
|
||||
isSubmitting.value = false;
|
||||
modalApi.unlock();
|
||||
}
|
||||
},
|
||||
@@ -68,7 +63,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
accountId: number;
|
||||
isCreating: boolean;
|
||||
mediaId?: string;
|
||||
newsList?: NewsItem[];
|
||||
newsList?: MpDraftApi.NewsItem[];
|
||||
}>();
|
||||
if (!data) {
|
||||
return;
|
||||
@@ -85,12 +80,10 @@ const [Modal, modalApi] = useVbenModal({
|
||||
|
||||
<template>
|
||||
<Modal :title="getTitle" class="w-4/5" destroy-on-close>
|
||||
<Spin :spinning="isSubmitting">
|
||||
<NewsForm
|
||||
v-if="formData"
|
||||
v-model="newsList"
|
||||
:is-creating="!formData.mediaId"
|
||||
/>
|
||||
</Spin>
|
||||
<NewsForm
|
||||
v-if="formData"
|
||||
v-model="newsList"
|
||||
:is-creating="!formData.mediaId"
|
||||
/>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import type { NewsItem } from './types';
|
||||
import type { MpDraftApi } from '#/api/mp/draft';
|
||||
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
@@ -8,23 +8,23 @@ import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
import { Button, Col, Input, Layout, Row, Textarea } from 'ant-design-vue';
|
||||
|
||||
import { createEmptyNewsItem } from '#/api/mp/draft';
|
||||
import { Tinymce as RichTextarea } from '#/components/tinymce';
|
||||
|
||||
import CoverSelect from './cover-select.vue';
|
||||
import { createEmptyNewsItem } from './types';
|
||||
|
||||
defineOptions({ name: 'NewsForm' });
|
||||
|
||||
const props = defineProps<{
|
||||
isCreating: boolean;
|
||||
modelValue: NewsItem[] | null;
|
||||
modelValue: MpDraftApi.NewsItem[] | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', v: NewsItem[]): void;
|
||||
(e: 'update:modelValue', v: MpDraftApi.NewsItem[]): void;
|
||||
}>();
|
||||
|
||||
const newsList = computed<NewsItem[]>({
|
||||
const newsList = computed<MpDraftApi.NewsItem[]>({
|
||||
get() {
|
||||
return props.modelValue === null
|
||||
? [createEmptyNewsItem()]
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// TODO @hw:这个要融合到 draftApi 里么?类似其他模块的。
|
||||
interface NewsItem {
|
||||
title: string;
|
||||
thumbMediaId: string;
|
||||
author: string;
|
||||
digest: string;
|
||||
showCoverPic: number;
|
||||
content: string;
|
||||
contentSourceUrl: string;
|
||||
needOpenComment: number;
|
||||
onlyFansCanComment: number;
|
||||
thumbUrl: string;
|
||||
picUrl?: string; // 用于预览封面
|
||||
}
|
||||
|
||||
interface NewsItemList {
|
||||
newsItem: NewsItem[];
|
||||
}
|
||||
|
||||
interface Article {
|
||||
mediaId: string;
|
||||
content: NewsItemList;
|
||||
updateTime: number;
|
||||
}
|
||||
|
||||
function createEmptyNewsItem(): NewsItem {
|
||||
return {
|
||||
title: '',
|
||||
thumbMediaId: '',
|
||||
author: '',
|
||||
digest: '',
|
||||
showCoverPic: 0,
|
||||
content: '',
|
||||
contentSourceUrl: '',
|
||||
needOpenComment: 0,
|
||||
onlyFansCanComment: 0,
|
||||
thumbUrl: '',
|
||||
};
|
||||
}
|
||||
|
||||
export type { Article, NewsItem, NewsItemList };
|
||||
export { createEmptyNewsItem };
|
||||
@@ -3,13 +3,13 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||
|
||||
import { onMounted, watch } from 'vue';
|
||||
|
||||
import { MpMsgType as MsgType } from '@vben/constants';
|
||||
import { formatDate2 } from '@vben/utils';
|
||||
|
||||
import { Button, Image, Tag } from 'ant-design-vue';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
import {
|
||||
MsgType,
|
||||
WxLocation,
|
||||
WxMusic,
|
||||
WxNews,
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Dayjs } from 'dayjs';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { DICT_TYPE } from '@vben/constants';
|
||||
import { DICT_TYPE, MpMsgType as MsgType } from '@vben/constants';
|
||||
import { getDictOptions } from '@vben/hooks';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { getMessagePage } from '#/api/mp/message';
|
||||
import { MsgType, WxAccountSelect, WxMsg } from '#/views/mp/components';
|
||||
import { WxAccountSelect, WxMsg } from '#/views/mp/components';
|
||||
|
||||
import MessageTable from './MessageTable.vue';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user