# component自定義組件目錄
自定義頁面是由組件進行配置開發的,自定義組件開發包括后臺配置與uniapp頁面展示,下面說明后臺配置方面,具體的自定義模板開發會在模板開發詳細說明
## component目錄
```
├─component
├─├─controller
│ Article.php 文章組件
│ BaseDiyView.php 自定義組件基類
│ FloatBtn.php 浮動按鈕
│ GoodsBrand.php 商品品牌
│ GoodsCategory.php 商品分類
│ GoodsList.php 商品列表
│ GoodsRecommend.php 商品推薦
│ HorzBlank.php 輔助空白
│ HorzLine.php 輔助線
│ ImageAds.php 圖片廣告
│ ManyGoodsList.php 多商品組
│ Notice.php 公告
│ RichText.php 富文本
│ RubikCube.php 魔方
│ Search.php 商品搜索
│ Text.php 標題
│ TopCategory.php 頂部商品分類
│ Video.php 視頻
```
**一,設計自定義組件后臺配置**
~~~
<?php
namespace app\component\controller;
/**
* 公告·組件
*/
class Notice extends BaseDiyView
{
/**
* 后臺編輯界面
*/
public function design()
{
return $this->fetch("notice/design.html");
}
}
~~~
~~~
<nc-component :data="data[index]" class="notice">
<!-- 預覽 -->
<template slot="preview">
<template v-if="nc.lazyLoad">
<div class="preview-box"
:style="{
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
backgroundColor : nc.componentBgColor }">
<div :class="['notice-box',nc.contentStyle]">
<div class="notice-con" v-for="(item, previewIndex) in nc.list" v-if="previewIndex < 1">
<div :class="['img-wrap',nc.iconType]" v-if="previewIndex == 0">
<img v-if="nc.iconType == 'img'" :src="changeImgUrl(nc.imageUrl)" />
<div v-if="nc.iconType == 'icon'" class="icon-box">
<iconfont :icon="nc.icon" v-if="nc.icon" :value="nc.style ? nc.style : ''"></iconfont>
</div>
</div>
<div class="notice-con-split"></div>
<span v-if="nc.contentStyle=='style-2'" class="iconfont icongonggao notice-icon-one" :style="{color: nc.textColor ? nc.textColor : 'rgba(0,0,0,0)'}"></span>
<span class="notice-con-font" :style="{color: nc.textColor ? nc.textColor : 'rgba(0,0,0,0)'}">{{ item.title }}</span>
<span v-if="nc.contentStyle=='style-2'" class="iconfont iconyoujiantou notice-icon-two"></span>
</div>
</div>
</div>
</template>
</template>
<!-- 內容編輯 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<notice-sources></notice-sources>
<div class="template-edit-title">
<h3>公告風格</h3>
<div class="goods-list-edit layui-form" v-if="nc.tempData.iconList">
<div class="layui-form-item icon-radio">
<label class="layui-form-label sm">公告圖標</label>
<div class="layui-input-block">
<span v-for="(item, sourcesKey) in nc.tempData.iconList" :key="sourcesKey" :class="[sourcesKey == nc.iconSources ? '' : 'layui-hide']">{{item.text}}</span>
<ul class="icon-wrap">
<li v-for="(item, sourcesKey) in nc.tempData.iconList" :key="sourcesKey" :class="[sourcesKey == nc.iconSources ? 'text-color border-color' : '']" @click="nc.iconSources=sourcesKey;nc.iconType=item.type;">
<i class="iconfont" :class="[{'text-color': sourcesKey == nc.iconSources}, item.src]"></i>
</li>
</ul>
</div>
<div v-if="nc.iconSources == 'initial'" class="system-img">
<div class="system-img-item" v-for="item in nc.tempData.iconList[nc.iconSources].icon" :class="{'border-color': nc.imageUrl == item}" @click="nc.imageUrl = item">
<img :src="item"/>
</div>
</div>
</div>
<div class="diy-img" v-show="nc.iconSources == 'diy'">
<img-icon-upload :data="{data : nc}"></img-icon-upload>
<div class="right-wrap">
<div class="action-box" v-show="nc.iconType == 'icon'">
<div class="action" @click="nc.tempData.methods.iconStyle($event)"><i class="iconfont iconpifu"></i></div>
<div class="action" :id="'notice-color-' + nc.index"><i class="iconfont iconyanse"></i></div>
</div>
<div class="desc">高度20像素,寬度自適應</div>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label sm">風格</label>
<div class="layui-input-block">
<div @click="nc.contentStyle='style-1'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.contentStyle=='style-1') }">
<i class="layui-anim layui-icon">{{ nc.contentStyle=='style-1' ? "" : "" }}</i>
<div>風格一</div>
</div>
<div @click="nc.contentStyle='style-2'" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.contentStyle=='style-2') }">
<i class="layui-anim layui-icon">{{ nc.contentStyle=='style-2' ? "" : "" }}</i>
<div>風格二</div>
</div>
</div>
</div>
</div>
</div>
<div class="template-edit-title">
<h3>公告內容</h3>
<div class="layui-form-item" v-if="nc.tempData.noticeSources">
<label class="layui-form-label sm">數據來源</label>
<div class="layui-input-block">
<div class="source-selected">
<div class="source">{{ nc.tempData.noticeSources[nc.sources].text }}</div>
<div v-for="(item,sourcesKey) in nc.tempData.noticeSources" :key="sourcesKey" class="source-item" :title="item.text" @click="nc.sources=sourcesKey" :class="{ 'text-color border-color' : (nc.sources == sourcesKey) }">
<i class='iconfont' :class='item.icon'></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-if="nc.sources == 'initial' && nc.tempData.methods">
<label class="layui-form-label sm">選擇公告</label>
<div class="layui-input-block">
<div class="input-text selected-style" @click="nc.tempData.methods.addNotice()">
<span v-if="nc.noticeIds.length == 0">請選擇</span>
<span v-if="nc.noticeIds.length > 0" class="text-color">已選{{ nc.noticeIds.length }}個</span>
<i class="iconfont iconyoujiantou"></i>
</div>
</div>
</div>
<div class="notice-config" v-if="nc.sources == 'diy'">
<ul>
<li v-for="(item,index) in nc.list">
<div class="content-block">
<div class="layui-form-item" >
<label class="layui-form-label sm">公告內容</label>
<div class="layui-input-block">
<input type="text" name='title' v-model="item.title" class="layui-input" />
</div>
</div>
<nc-link :data="{ field : nc.list[index].link }"></nc-link>
</div>
<i class="del" @click="list.splice(index,1)">x</i>
</li>
</ul>
<div class="add-item text-color border-color" @click="nc.list.push({ title:'公告',link:{name:''}})">
<i>+</i>
<span>添加一條公告</span>
</div>
</div>
</div>
</template>
</template>
<!-- 樣式編輯 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>公告樣式</h3>
<color :data="{ field : 'textColor', 'label' : '文本顏色','defaultColor': '#303133' }"></color>
</div>
</template>
</template>
<!-- 資源 -->
<template slot="resource">
<js>
var noticeResourcePath = "{$resource_path}";
</js>
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>
~~~
**一,uniapp開發**
自定義組件統計在components/diy-components
~~~
<template>
<view class="diy-notice">
<view class="notice notice-1" :style="noticeWrapCss">
<image v-if="value.iconType == 'img'" class="notice-img" :src="$util.img(value.imageUrl)" mode="heightFix"></image>
<diy-icon
v-if="value.iconType == 'icon'"
:icon="value.icon"
:value="value.style ? value.style : 'null'"
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx', width: '100%', height: '100%' }"
></diy-icon>
<view class="notice-xian"></view>
<view class="main-wrap">
<view class="uni-swiper-msg">
<swiper vertical="true" autoplay="true" duration="0" circular="true">
<swiper-item v-for="(item, index) in list" :key="index" @touchmove.stop>
<text @click="toLink(item)" class="beyond-hiding animate" :style="{ color: value.textColor }">{{ item.title }}</text>
</swiper-item>
</swiper>
</view>
</view>
</view>
</view>
</template>
<script>
// 公告
export default {
name: 'diy-notice',
props: {
value: {
type: Object
}
},
data() {
return {
list: []
};
},
computed: {
noticeWrapCss: function() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
created() {
// 數據源:公告系統
if (this.value.sources == 'default') this.getData();
else this.list = this.value.list;
},
methods: {
getData() {
var data = {};
data.id_arr = this.value.noticeIds.toString();
this.$api.sendRequest({
url: '/api/notice/lists',
data: data,
success: res => {
if (res.code == 0 && res.data) {
this.list = res.data;
console.log('test - 公告信息', this.list);
}
}
});
},
toLink(item) {
if (this.value.sources == 'default') this.$util.redirectTo('/pages_tool/notice/detail', { notice_id: item.id });
else this.$util.diyRedirectTo(item.link);
}
}
};
</script>
<style lang="scss">
.notice-1 {
height: 80rpx;
position: relative;
display: flex;
align-items: center;
overflow: hidden;
padding: 20rpx;
font-size: 70rpx;
.notice-img {
width: 212rpx;
height: 40rpx;
}
.notice-xian {
width: 1rpx;
height: 26rpx;
background-color: #e4e4e4;
margin: 0 22rpx;
}
}
.main-wrap {
display: inline-block;
width: calc(100% - 115rpx);
position: relative;
}
swiper {
height: 50rpx;
}
.beyond-hiding {
display: inline-block;
width: 100%;
white-space: nowrap;
}
.animate {
padding-left: 40rpx;
font-size: $font-size-base;
color: #000;
display: inline-block;
white-space: nowrap;
animation: 5s wordsLoop linear infinite normal;
}
@keyframes wordsLoop {
0% {
transform: translateX(400rpx);
-webkit-transform: translateX(400rpx);
}
100% {
transform: translateX(-100%);
-webkit-transform: translateX(-100%);
}
}
@-webkit-keyframes wordsLoop {
0% {
transform: translateX(400rpx);
-webkit-transform: translateX(400rpx);
}
100% {
transform: translateX(-100%);
-webkit-transform: translateX(-100%);
}
}
</style>
~~~
- 序言
- 安裝教程
- 運行環境
- 安裝手冊
- 基礎
- 前期準備
- 偽靜態配置
- 后臺目錄結構
- uniapp(手機端)目錄結構
- 開發命名規范
- 控制器命名規范
- model層命名規范
- 前端(管理頁面)命名規范
- 提示面板
- 表單
- uniapp(手機端)命名規范
- api接口命名規范
- 架構
- 入口文件
- config設置
- app應用目錄
- component(自定義模板組件)
- model層(數據業務層)
- 數據庫操作
- job(消息隊列)
- event(事件)
- request(請求對象)
- common(公共函數)
- log(日志處理)
- lang(語言包)
- addon插件
- 數據字典
- 系統基礎表
- 配送相關表
- 商品相關表
- 網站設置相關
- 會員相關表
- 訂單相關表
- 營銷(組合套餐)
- 營銷(砍價)
- 營銷(優惠券)
- 營銷(滿減)
- 營銷(拼團)
- 營銷(秒殺)
- 店鋪相關表
- 微信相關表
- 門店相關表
- 結算相關表
- 應用(分銷)
- 功能模塊
- 商品模塊
- 會員模塊
- 訂單模塊
- 數據統計
- 消息隊列
- 支付模塊
- 短信模塊
- 客服
- api接口
- 接口開發
- 插件開發
- 事件開發
- 常用事件
- 插件目錄與開發
- 常用插件
- 支付插件
- 拼團插件
- 新人禮