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
	
	 xingyu
						xingyu