feat: wx news init
parent
d6cd366c12
commit
e9a7b476aa
|
@ -72,11 +72,12 @@ import { computed, onMounted, ref } from 'vue'
|
||||||
import { EditOutlined, EllipsisOutlined, RedoOutlined, TableOutlined } from '@ant-design/icons-vue'
|
import { EditOutlined, EllipsisOutlined, RedoOutlined, TableOutlined } from '@ant-design/icons-vue'
|
||||||
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue'
|
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue'
|
||||||
import { Dropdown } from '@/components/Dropdown'
|
import { Dropdown } from '@/components/Dropdown'
|
||||||
import { BasicForm, useForm } from '@/components/Form'
|
import { BasicForm, useForm, FormSchema } from '@/components/Form'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { Button } from '@/components/Button'
|
import { Button } from '@/components/Button'
|
||||||
import { isFunction } from '@/utils/is'
|
import { isFunction } from '@/utils/is'
|
||||||
import { useSlider, grid } from './data'
|
import { useSlider, grid } from './data'
|
||||||
|
|
||||||
const ListItem = List.Item
|
const ListItem = List.Item
|
||||||
const CardMeta = Card.Meta
|
const CardMeta = Card.Meta
|
||||||
const TypographyText = Typography.Text
|
const TypographyText = Typography.Text
|
||||||
|
@ -87,7 +88,10 @@ const props = defineProps({
|
||||||
// 请求API的参数
|
// 请求API的参数
|
||||||
params: propTypes.object.def({}),
|
params: propTypes.object.def({}),
|
||||||
//api
|
//api
|
||||||
api: propTypes.func
|
api: propTypes.func,
|
||||||
|
searchSchema: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
})
|
})
|
||||||
//暴露内部方法
|
//暴露内部方法
|
||||||
const emit = defineEmits(['getMethod', 'delete'])
|
const emit = defineEmits(['getMethod', 'delete'])
|
||||||
|
@ -102,7 +106,7 @@ const height = computed(() => {
|
||||||
})
|
})
|
||||||
//表单
|
//表单
|
||||||
const [registerForm, { validate }] = useForm({
|
const [registerForm, { validate }] = useForm({
|
||||||
schemas: [{ field: 'type', component: 'Input', label: '类型' }],
|
schemas: props.searchSchema as FormSchema[],
|
||||||
labelWidth: 80,
|
labelWidth: 80,
|
||||||
baseColProps: { span: 6 },
|
baseColProps: { span: 6 },
|
||||||
actionColOptions: { span: 24 },
|
actionColOptions: { span: 24 },
|
||||||
|
@ -129,7 +133,7 @@ async function fetch(p = {}) {
|
||||||
const { api, params } = props
|
const { api, params } = props
|
||||||
if (api && isFunction(api)) {
|
if (api && isFunction(api)) {
|
||||||
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p })
|
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p })
|
||||||
data.value = res.items
|
data.value = res.list
|
||||||
total.value = res.total
|
total.value = res.total
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
<template>
|
||||||
|
<div class="p-2">
|
||||||
|
<div class="p-4 mb-2 bg-white">
|
||||||
|
<BasicForm @register="registerForm" />
|
||||||
|
</div>
|
||||||
|
<div class="p-2 bg-white">
|
||||||
|
<List :grid="{ gutter: 5, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: grid }" :data-source="data" :pagination="paginationProp">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex justify-end space-x-2">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
<Tooltip>
|
||||||
|
<template #title>
|
||||||
|
<div class="w-50">每行显示数量</div>
|
||||||
|
<Slider id="slider" v-bind="sliderProp" v-model:value="grid" @change="sliderChange" />
|
||||||
|
</template>
|
||||||
|
<a-button><TableOutlined /></a-button>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip @click="fetch">
|
||||||
|
<template #title>刷新</template>
|
||||||
|
<a-button><RedoOutlined /></a-button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<ListItem>
|
||||||
|
<Card>
|
||||||
|
<template #title>{{ item.content.newsItem[0].title }}</template>
|
||||||
|
<template #cover>
|
||||||
|
<div :class="height">
|
||||||
|
<Image :src="item.content.newsItem[0].thumbUrl" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #actions>
|
||||||
|
<Icon icon="ant-design:delete-outlined" @click="handleDelete.bind(null, item.id)" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<CardMeta>
|
||||||
|
<template #title>
|
||||||
|
<TypographyText :content="item.name" :ellipsis="{ tooltip: item.address }" />
|
||||||
|
</template>
|
||||||
|
<template #avatar>
|
||||||
|
<Avatar :src="item.avatar" />
|
||||||
|
</template>
|
||||||
|
<template #description>{{ item.time }}</template>
|
||||||
|
</CardMeta>
|
||||||
|
</Card>
|
||||||
|
</ListItem>
|
||||||
|
</template>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, onMounted, ref } from 'vue'
|
||||||
|
import { RedoOutlined, TableOutlined } from '@ant-design/icons-vue'
|
||||||
|
import { List, Card, Image, Typography, Tooltip, Slider, Avatar } from 'ant-design-vue'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
import { BasicForm, useForm, FormSchema } from '@/components/Form'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { isFunction } from '@/utils/is'
|
||||||
|
import { useSlider, grid } from './data'
|
||||||
|
|
||||||
|
const ListItem = List.Item
|
||||||
|
const CardMeta = Card.Meta
|
||||||
|
const TypographyText = Typography.Text
|
||||||
|
// 获取slider属性
|
||||||
|
const sliderProp = computed(() => useSlider(4))
|
||||||
|
// 组件接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
// 请求API的参数
|
||||||
|
params: propTypes.object.def({}),
|
||||||
|
//api
|
||||||
|
api: propTypes.func,
|
||||||
|
searchSchema: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//暴露内部方法
|
||||||
|
const emit = defineEmits(['getMethod', 'delete'])
|
||||||
|
//数据
|
||||||
|
const data = ref([])
|
||||||
|
// 切换每行个数
|
||||||
|
// cover图片自适应高度
|
||||||
|
//修改pageSize并重新请求数据
|
||||||
|
|
||||||
|
const height = computed(() => {
|
||||||
|
return `h-${120 - grid.value * 6}`
|
||||||
|
})
|
||||||
|
//表单
|
||||||
|
const [registerForm, { validate }] = useForm({
|
||||||
|
schemas: props.searchSchema as FormSchema[],
|
||||||
|
labelWidth: 80,
|
||||||
|
baseColProps: { span: 6 },
|
||||||
|
actionColOptions: { span: 24 },
|
||||||
|
autoSubmitOnEnter: true,
|
||||||
|
submitFunc: handleSubmit
|
||||||
|
})
|
||||||
|
//表单提交
|
||||||
|
async function handleSubmit() {
|
||||||
|
const data = await validate()
|
||||||
|
await fetch(data)
|
||||||
|
}
|
||||||
|
function sliderChange(n: number) {
|
||||||
|
pageSize.value = n * 4
|
||||||
|
fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动请求并暴露内部方法
|
||||||
|
onMounted(() => {
|
||||||
|
fetch()
|
||||||
|
emit('getMethod', fetch)
|
||||||
|
})
|
||||||
|
|
||||||
|
async function fetch(p = {}) {
|
||||||
|
const { api, params } = props
|
||||||
|
if (api && isFunction(api)) {
|
||||||
|
const res = await api({ ...params, page: page.value, pageSize: pageSize.value, ...p })
|
||||||
|
data.value = res.list
|
||||||
|
total.value = res.total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//分页相关
|
||||||
|
const page = ref(1)
|
||||||
|
const pageSize = ref(36)
|
||||||
|
const total = ref(0)
|
||||||
|
const paginationProp = ref({
|
||||||
|
showSizeChanger: false,
|
||||||
|
showQuickJumper: true,
|
||||||
|
pageSize,
|
||||||
|
current: page,
|
||||||
|
total,
|
||||||
|
showTotal: (total: number) => `总 ${total} 条`,
|
||||||
|
onChange: pageChange,
|
||||||
|
onShowSizeChange: pageSizeChange
|
||||||
|
})
|
||||||
|
|
||||||
|
function pageChange(p: number, pz: number) {
|
||||||
|
page.value = p
|
||||||
|
pageSize.value = pz
|
||||||
|
fetch()
|
||||||
|
}
|
||||||
|
function pageSizeChange(_current, size: number) {
|
||||||
|
pageSize.value = size
|
||||||
|
fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(id) {
|
||||||
|
emit('delete', id)
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { ref } from 'vue'
|
||||||
|
// 每行个数
|
||||||
|
export const grid = ref(12)
|
||||||
|
// slider属性
|
||||||
|
export const useSlider = (min = 6, max = 12) => {
|
||||||
|
// 每行显示个数滑动条
|
||||||
|
const getMarks = () => {
|
||||||
|
const l = {}
|
||||||
|
for (let i = min; i < max + 1; i++) {
|
||||||
|
l[i] = {
|
||||||
|
style: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
label: i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
marks: getMarks(),
|
||||||
|
step: 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,138 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<PageWrapper :class="prefixCls" title="公众号图文">
|
<PageWrapper title="公众号图文">
|
||||||
<template #headerContent>
|
<NewsList :search-schema="searchSchema" :api="getFreePublishPage" @get-method="getMethod" @delete="handleDelete" />
|
||||||
请选择公众号
|
|
||||||
<div :class="`${prefixCls}__link`">
|
|
||||||
<Select :value="queryParams.accountId as any" style="width: 200px" @change="getList">
|
|
||||||
<SelectOption v-for="item in accounts" :label="item.name" :value="parseInt(item.id)" :key="parseInt(item.id)" />
|
|
||||||
</Select>
|
|
||||||
<!-- <a><Icon icon="bx:bx-paper-plane" color="#1890ff" /><span>开始</span></a>
|
|
||||||
<a><Icon icon="carbon:warning" color="#1890ff" /><span>简介</span></a>
|
|
||||||
<a><Icon icon="ion:document-text-outline" color="#1890ff" /><span>文档</span></a> -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div :class="`${prefixCls}__content`">
|
|
||||||
<List :grid="{ gutter: 16, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: 3, xxxl: 2 }" :data-source="cardList">
|
|
||||||
<template v-for="item in cardList" :key="item.title">
|
|
||||||
<ListItem>
|
|
||||||
<Card :hoverable="true" :class="`${prefixCls}__card`">
|
|
||||||
<List>
|
|
||||||
<template v-for="(article, index) in item.content.newsItem" :key="index">
|
|
||||||
<ListItem>
|
|
||||||
<Image :src="article.picUrl" :key="index" />
|
|
||||||
<div :class="`${prefixCls}__card-title`">
|
|
||||||
{{ article.title }}
|
|
||||||
</div>
|
|
||||||
<div :class="`${prefixCls}__card-detail`"></div>
|
|
||||||
</ListItem>
|
|
||||||
</template>
|
|
||||||
</List>
|
|
||||||
<!-- <div :class="`${prefixCls}__card-title`">
|
|
||||||
<Icon class="icon" v-if="item.icon" :icon="item.icon" :color="item.color" />
|
|
||||||
{{ item.title }}
|
|
||||||
</div>
|
|
||||||
<div :class="`${prefixCls}__card-detail`"> 基于Vue Next, TypeScript, Ant Design Vue实现的一套完整的企业级后台管理系统 </div> -->
|
|
||||||
</Card>
|
|
||||||
</ListItem>
|
|
||||||
</template>
|
|
||||||
</List>
|
|
||||||
<Pagination showLessItems size="small" :pageSize="queryParams.queryParamsSize" :total="queryParams.total" @change="getList" />
|
|
||||||
</div>
|
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
// import { Icon } from '@/components/Icon'
|
// import { Icon } from '@/components/Icon'
|
||||||
import { PageWrapper } from '@/components/Page'
|
import { PageWrapper } from '@/components/Page'
|
||||||
import { Card, List, Image, Select, Pagination } from 'ant-design-vue'
|
import NewsList from './NewsList.vue'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
|
||||||
import { getSimpleAccounts } from '@/api/mp/account'
|
import { getSimpleAccounts } from '@/api/mp/account'
|
||||||
import { useMessage } from '@/hooks/web/useMessage'
|
import { deleteFreePublish, getFreePublishPage } from '@/api/mp/freePublish'
|
||||||
import { getFreePublishPage } from '@/api/mp/freePublish'
|
import { FormSchema } from '@/components/Form'
|
||||||
|
|
||||||
const ListItem = List.Item
|
const searchSchema: FormSchema[] = [
|
||||||
const SelectOption = Select.Option
|
{
|
||||||
|
label: '公众号',
|
||||||
const { prefixCls } = useDesign('list-card')
|
field: 'accountId',
|
||||||
const { createMessage } = useMessage()
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
const cardList = ref<any[]>([])
|
api: () => getSimpleAccounts(),
|
||||||
|
labelField: 'name',
|
||||||
const accounts = ref()
|
valueField: 'id'
|
||||||
|
},
|
||||||
const queryParams = reactive({
|
colProps: { span: 8 }
|
||||||
accountId: null,
|
|
||||||
total: 0,
|
|
||||||
currentPage: 1,
|
|
||||||
queryParamsSize: 20
|
|
||||||
})
|
|
||||||
|
|
||||||
async function init() {
|
|
||||||
const res = await getSimpleAccounts()
|
|
||||||
accounts.value = res
|
|
||||||
if (accounts.value.length > 0) {
|
|
||||||
queryParams.accountId = accounts.value[0].id
|
|
||||||
}
|
}
|
||||||
await getList()
|
]
|
||||||
|
|
||||||
|
let reload = () => {}
|
||||||
|
// 获取内部fetch方法;
|
||||||
|
function getMethod(m: any) {
|
||||||
|
reload = m
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getList() {
|
//删除按钮事件
|
||||||
if (!queryParams.accountId) {
|
function handleDelete(id) {
|
||||||
createMessage.error('未选中公众号,无法查询已发表图文!')
|
deleteFreePublish(id, id)
|
||||||
return false
|
reload()
|
||||||
}
|
|
||||||
const res = await getFreePublishPage(queryParams)
|
|
||||||
cardList.value = res.list
|
|
||||||
queryParams.total = res.total
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await init()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
|
||||||
.list-card {
|
|
||||||
&__link {
|
|
||||||
margin-top: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin-right: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__card {
|
|
||||||
width: 100%;
|
|
||||||
margin-bottom: -8px;
|
|
||||||
|
|
||||||
.ant-card-body {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-title {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: @text-color;
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin-top: -5px;
|
|
||||||
margin-right: 10px;
|
|
||||||
font-size: 38px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-detail {
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-left: 30px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: @text-color-secondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
Loading…
Reference in New Issue