# vuex
获取值
import {mapActions} from "vuex";
methods: {
...mapActions("admin/user", ["load"]),
getData(){
let data = await this.load();
this.provider = data.user;
}
}
load({state, dispatch}) {
return new Promise(async resolve => {
// store 赋值
state.info = await dispatch('admin/db/get', {
dbName: 'sys',
path: 'user.info',
defaultValue: {},
user: true
}, {root: true});
if (state.info) {
state.authorized = true;
}
// end
resolve(state.info);
})
}
```html
<FormItem label="满意度" prop="manyidu">
<Input v-model="form.manyidu" type="text" placeholder=""></Input>
</FormItem>
<Col span="24">
<FormItem label="满意度" prop="manyidu">
<Select v-model="form.manyidu" placeholder="请选择">
<Option value="满意">满意</Option>
<Option value="不满意">不满意</Option>
</Select>
</FormItem>
</Col>
递归更改用户所属者:orangbus:用户 www:所属组 文件夹|文件名
chown -R orangbus:www admin.no1time.com/
# 模板
# 抽屉提交
ui-drawer-submit
<Drawer
title="Create"
v-model="drawer"
width="720"
:mask-closable="false"
:styles="styles"
>
content
<div class="drawer-footer">
<Button style="margin-right: 8px" @click="drawer = false">关闭</Button>
<Button type="primary" @click="drawer = false" :loading="submitting">保存</Button>
</div>
</Drawer>
ui-drawer-data
drawer: false,
styles: {
height: 'calc(100% - 55px)',
overflow: 'auto',
paddingBottom: '53px',
position: 'static'
},
ui-drawer-css
<style>
.demo-drawer-footer{
width: 100%;
position: absolute;
bottom: 0;
left: 0;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
background: #fff;
}
</style>
# 表格编辑
# ui-tb-field
submitting: false, // 是否是提交状态
loading: false,
columns: [
{
type: 'selection',
width: 60,
align: 'center',
show: true
},
{
title: 'ID',
key: 'id',
minWidth: 140,
show: false
},
{
title: '角色名称',
key: 'name',
minWidth: 140,
tooltip: true,
show: true
},
{
title: '创建时间',
key: 'created_at',
minWidth: 200,
show: true
},
{
title: '操作',
key: 'action',
slot: 'action',
minWidth: 200,
maxWidth: 200,
align: 'center',
fixed: 'right',
show: true
}
],
list: [], // 列表数据
selectedData: [], // 选择数据
page: 1, // 当前页码
limit: 10, // 每页条数
total: 0, // 总条数
# ui-action-curd
<template slot-scope="{ row }" slot="action">
<div @click.stop.prevent>
<a type="text" @click="add(row.id)">添加</a>
<Divider type="vertical"/>
<a type="text" @click="edit(row.id)">编辑</a>
<Divider type="vertical"/>
<Poptip
confirm
:transfer="true"
:title="`是否确定删除?`"
@on-ok="del(row.id)">
<a type="text">删除</a>
</Poptip>
</div>
</template>
# ui-action-curd-js
add(row, index) {
this.title = "添加";
this.form = {};
this.$model$ = true
},
edit(row, index) {
this.title = row.name;
this.form = cloneDeep(row);
this.$model$ = true
},
del(row, index) {
},
# 表单
# ui-form-field
keys: {},
form: {
id: 0,
name: "",
},
formRule: {
name: [
{required: true, message: '必填', trigger: 'blur'}
]
},
# ui-field-init
this.keys = Object.keys(this.form);
# 网站Logo
src/layouts/basic-layout/header-logo/index.vue
# 表格模板
// ui-table
<Table
ref="table"
:columns="tableColumns"
:data="list"
:loading="loading"
:size="tableSize"
:transfer="true"
:border="true"
class="ivu-mt"
@on-select="handleSelect"
@on-select-cancel="handleSelectCancel"
@on-select-all="handleSelectAll"
@on-select-all-cancel="handleSelectAllCancel"
>
<template slot-scope="{ row,index }" slot="course">
{{ row.course ? row.course.name : '无' }}
</template>
<template slot-scope="{ row, index }" slot="action">
<a @click="follow(index)">跟进</a>
<Divider type="vertical"/>
<Dropdown @on-click="(name) => action(name, index)" :transfer="true">
<a type="text">更多
<Icon type="ios-arrow-down"/>
</a>
<DropdownMenu slot="list" trigger="hover" :transfer="true">
<DropdownItem name="editArchive">编辑客户</DropdownItem>
<DropdownItem divided name="delete">删除</DropdownItem>
</DropdownMenu>
</Dropdown>
</template>
</Table>
ui-table-fileds
loading: false,
tableSize:"smail",
list: [],
selectedData: [],
page: 1,
limit: 10,
total: 0,
columns: [
{
type: 'selection',
width: 60,
align: 'center',
show: true
},
{
title: '姓名',
key: 'name',
minWidth: 140,
slot: 'name',
show: true
},
{
title: '操作',
slot: 'action',
align: 'center',
minWidth: 240,
fixed: 'right',
show: true
}
],
ui-table-column
computed: {
tableColumns () {
const columns = [...this.columns];
return columns.filter(item => item.show);
}
}
ui-table-default-methods
// 选中一项,将数据添加至已选项中
handleSelect (selection, row) {
this.selectedData.push(row);
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel (selection, row) {
const index = this.selectedData.findIndex(item => item.id === row.id);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll (selection) {
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.id === item.id) < 0) {
this.selectedData.push(item);
}
});
},
// 取消当前页全选时,将当前页的数据(即 dataWithPage)从已选项中删除
handleSelectAllCancel () {
this.selectedData = [];
},
// 清空所有已选项
handleClearSelect () {
let ids = [];
this.selectedData.forEach(item => {
ids.push(item.id);
})
if (ids.length === 0) {
return this.$Message.error('请选择数据');
}
this.$Modal.confirm({
title: '删除提示',
content: `是否删除?`,
onOk: () => {
customerDelete({ ids }).then(res => {
this.$Message.success(res.msg);
this.getData();
this.selectedData = [];
});
}
});
},
// ui-table-templet
<template slot-scope="{ row,index }" slot="course">
{{ row.course ? row.course.name : '无' }}
</template>
// ui-table-more
<template slot-scope="{ row, index }" slot="action">
<a @click="follow(index)">跟进</a>
<Divider type="vertical"/>
<Dropdown @on-click="(name) => action(name, index)" :transfer="true">
<a type="text">更多
<Icon type="ios-arrow-down"/>
</a>
<DropdownMenu slot="list" trigger="hover" :transfer="true">
<DropdownItem name="editArchive">编辑客户</DropdownItem>
<DropdownItem divided name="delete">删除</DropdownItem>
</DropdownMenu>
</Dropdown>
</template>
# 表格增删改查
// ui-table-js-curd
# 全屏
ref="card"
tableFullscreen = false
handleFullscreen() {
this.tableFullscreen = !this.tableFullscreen;
if (this.tableFullscreen) {
screenfull.request(this.$refs.card.$el);
} else {
screenfull.exit();
}
},
# 表格辅助
<div class="ivu-inline-block ivu-fr">
<Dropdown @on-click="handleChangeTableSize" trigger="click">
<Tooltip class="ivu-ml" content="密度" placement="top">
<i-link>
<Icon type="md-list"/>
</i-link>
</Tooltip>
<DropdownMenu slot="list">
<DropdownItem name="default" :selected="tableSize === 'default'">默认</DropdownItem>
<DropdownItem name="large" :selected="tableSize === 'large'">宽松</DropdownItem>
<DropdownItem name="small" :selected="tableSize === 'small'">紧凑</DropdownItem>
</DropdownMenu>
</Dropdown>
<Tooltip class="ivu-ml" :content="tableFullscreen ? '退出全屏' : '全屏'" placement="top">
<i-link @click.native="handleFullscreen">
<Icon
:custom="tableFullscreen ? 'i-icon i-icon-exit-full-screen' : 'i-icon i-icon-full-screen'"/>
</i-link>
</Tooltip>
<Tooltip class="ivu-ml" content="刷新" placement="top">
<i-link @click.native="getData">
<Icon custom="i-icon i-icon-refresh"/>
</i-link>
</Tooltip>
<Dropdown trigger="click">
<Tooltip class="ivu-ml" content="列设置" placement="top">
<i-link>
<Icon type="md-options"/>
</i-link>
</Tooltip>
<DropdownMenu slot="list">
<div class="ivu-p-8">列展示</div>
<Divider size="small" class="ivu-mt-8 ivu-mb-8"/>
<li class="ivu-dropdown-item" v-for="item in columns" :key="item.title" v-if="item.title"
@click="item.show = !item.show">
<Checkbox v-model="item.show"></Checkbox>
<span>{{ item.title }}</span>
</li>
</DropdownMenu>
</Dropdown>
</div>
// 改变表格尺寸
handleChangeTableSize(size) {
this.tableSize = size;
},
// 表格全屏
handleFullscreen() {
this.tableFullscreen = !this.tableFullscreen;
if (this.tableFullscreen) {
screenfull.request(this.$refs.card.$el);
} else {
screenfull.exit();
}
},
// 刷新表格数据
handleRefresh() {
this.getData();
},
// 切换页码
handleChangePage(page) {
this.page = page;
this.getData();
},
// 切换每页条数
handleChangePageSize(size) {
this.page = 1;
this.limit = size;
this.getData();
},
// 选中一项,将数据添加至已选项中
handleSelect(selection, row) {
this.selectedData.push(row);
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel(selection, row) {
const index = this.selectedData.findIndex(item => item.id === row.id);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll(selection) {
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.id === item.id) < 0) {
this.selectedData.push(item);
}
});
},
// 清空所有已选项
handleClearSelect() {
this.selectedData = [];
},
// 查找单一用户信息
handleGetUser(id) {
return this.list.find(item => item.id === id);
},
# 批量删除
# html
<!--批量删除-->
<Alert show-icon class="ivu-mt" v-if="selectedData.length > 0">
<div v-font="14">
已选择 <strong v-color="'#2d8cf0'">{{ selectedData.length }}</strong>条数据
<a class="ivu-ml" @click="handleClearSelect">删除</a>
</div>
</Alert>
# js
handleClearSelect() {
let ids = [];
this.selectedData.forEach(item => {
ids.push(item.id);
})
this.$Modal.confirm({
title: '删除提示',
content: `是否删除?`,
onOk: () => {
$method$({ids}).then(res => {
this.$Message.success(res.msg);
this.selectedData = [];
this.getData();
});
}
});
},
# header
ui-header-html
<PageHeader
back hidden-breadcrumb
:tab-list="tabList"
:title="title"
:tab-active-key="tab"
@on-back="backPage"
@on-tab-change="changeTab"
>
<div slot="action">
<ButtonGroup>
<Button>操作</Button>
<Button>操作</Button>
</ButtonGroup>
<Button type="primary">主操作</Button>
</div>
<div slot="content">
<DescriptionList :col="2">
<Description term="申请人:">公孙离</Description>
<Description term="部门:">可视化架构组</Description>
<Description term="产品线:">View UI</Description>
<Description term="用途说明:">生产环境</Description>
<Description term="申请时间:">2019-05-05</Description>
<Description term="申请时长:">1年</Description>
</DescriptionList>
</div>
<div slot="extra">
<p style="color: #808695">状态</p>
<p style="font-size: 24px">待审批</p>
</div>
</PageHeader>
<Card dis-hover class="ivu-mt-8">
</Card>
ui-header-data
title: "标题",
tab: "1",
tabList: [
{
label: '统计',
name: '1'
},
{
label: '排名',
name: '2'
}
]
ui-header-methods
// 返回页面
backPage() {
},
// 切换选项卡
changeTab(item) {
this.tab = item.name;
}
# 描述
ui-des
<DescriptionList :col="2">
<Description term="申请人:">公孙离</Description>
<Description term="部门:">可视化架构组</Description>
<Description term="产品线:">View UI</Description>
<Description term="用途说明:">生产环境</Description>
<Description term="申请时间:">2019-05-05</Description>
<Description term="申请时长:">1年</Description>
</DescriptionList>
# 数字展示
ui-numberinfo
<Row>
<Col span="8">
<NumberInfo title="" sub-title="今日" sub-total="17.1"
status="up">
<Numeral value="12321" format="0,0" slot="total"/>
</NumberInfo>
</Col>
<Col span="8">
<NumberInfo title="" sub-title="本月" sub-total="5.3"
status="down">
<CountUp :end="50193" :duration="4" slot="total"/>
</NumberInfo>
</Col>
<Col span="8">
<NumberInfo title="" sub-title="累计" sub-total="17.1"
status="up">
<Numeral value="12321" format="0,0" slot="total"/>
</NumberInfo>
</Col>
</Row>
# 按钮组
ui-btn-group
<ButtonGroup>
<Button type="primary">L</Button>
<Button>M</Button>
<Button>M</Button>
<Button type="dashed">R</Button>
</ButtonGroup>
# 时间戳-页面展示
ui-time-show
<Time :time="timestamp" type="$TYPE$"/>
enum("date","datetime")
# 过渡效果
ui-transition
<transition name="$NAME$">
</transition>
enum("ivu-anim-fade","ivu-anim-ease","ivu-anim-move-up","ivu-anim-move-down","ivu-anim-move-left","ivu-anim-move-right","ivu-anim-transition-drop","ivu-anim-slide-up","ivu-anim-slide-down","ivu-anim-slide-left","ivu-anim-slide-right")
# 头部导航
ui-pg-header
<div class="i-layout-page-header">
<PageHeader
title="搜索列表(文章)"
hidden-breadcrumb
:tab-list="tabList"
:tab-active-key="tabKey"
@on-tab-change="changeHeaderTab"
>
<div slot="content" class="ivu-mt ivu-mb" style="max-width: 500px;margin: 0 auto;">
<Input search size="large" enter-button="搜索" placeholder="Enter something..." />
</div>
</PageHeader>
</div>
ui-pg-header-data-js
tabKey: 'article',
tabList: [
{
label: '文章',
name: 'article'
},
{
label: '项目',
name: 'projects'
},
{
label: '应用',
name: 'apps'
}
]
ui-pg-header-methods
# vue父子组件互相操作
<template>
<div class="container">
<Row :gutter="24">
<Col span="24">
<Card :bordered="false" dis-hover>
<div class="ui-flex ui-flex-align-center ui-flex-space-between">
<div
v-if="archive.id && archive.id !== 0"
class="ui-flex ui-flex-align-center text-pointer userName"
@click="archiveModal = true">
<h2 class="ivu-mr-8">{{ archive.name }}</h2>
<Tooltip content="男" v-if="archive.sex == 1">
<Icon type="md-male" color="#2d8cf0"/>
</Tooltip>
<Tooltip content="女" v-if="archive.sex == 2">
<Icon type="md-female" color="red"/>
</Tooltip>
<div class="ivu-ml">
<span>手机号:{{ archive.phone }}</span>
</div>
<div class="ivu-ml">
<span>民族:{{ archive.mz ? archive.mz : ' - ' }}</span>
</div>
<div class="ivu-ml">
<span>身份证:{{ archive.id_card ? archive.id_card : ' - ' }}</span>
</div>
</div>
</div>
</Card>
<!-- <ArchiveDetail :archive="archive" :col="4"></ArchiveDetail>-->
</Col>
<Col span="24" class="ivu-mt">
<Card dis-hover>
<Button type="primary" size="default" @click="create">添加</Button>
<Table
ref="table"
:columns="columns"
:data="list"
:transfer="true"
:border="true"
:loading="loading"
class="ivu-mt"
>
<template slot-scope="{ row,index }" slot="title">
<Tooltip :content="row.title" :transfer="true">
<span> {{ row.title }}</span>
</Tooltip>
</template>
<template slot-scope="{ row,index }" slot="name">
{{ row.name }}
<Tooltip :transfer="true" content="男" v-if="row.sex == 1">
<Icon type="md-male" color="primary"/>
</Tooltip>
<Tooltip :transfer="true" content="女" v-if="row.sex == 2">
<Icon type="md-female" color="red"/>
</Tooltip>
</template>
<template slot-scope="{ row }" slot="sex">
<Tag color="cyan" v-if="row.mz != ''">{{ row.mz }}</Tag>
</template>
<template slot-scope="{ row }" slot="status">
<CustomerStatus :status="row.status"></CustomerStatus>
</template>
<template slot-scope="{ row }" slot="channel">
<span v-for="(item,index) in param.channel" :key="index" v-if="row.channel_id == item.id"
:style="'color:'+item.color">{{ item.name }}</span>
</template>
<template slot-scope="{ row }" slot="yxd">
<Tag v-for="(item,index) in param.yxd" :key="index" :color="item.color"
v-if="row.yxd_id == item.id">{{
item.name
}}
</Tag>
</template>
<template slot-scope="{ row }" slot="hangye">
<Tag v-for="(item,index) in param.hanye" :key="index" :color="item.color"
v-if="row.hangye_id == item.id">{{
item.name
}}
</Tag>
</template>
<template slot-scope="{ row, index }" slot="action">
<a @click="follow(index)">跟进</a>
</template>
</Table>
<div class="ivu-mt ivu-text-center">
<Page
:total="total"
:current.sync="current"
show-total
show-sizer
:page-size="limit"
@on-page-size-change="handleChangePageSize"
/>
</div>
</Card>
</Col>
</Row>
<!--跟进-->
<Drawer
title="客户跟进"
v-model="followDrawer"
width="1200"
placement="right"
:mask-closable="true"
:closable="true"
>
<!-- <follow :customer="customer" :param="param" @setTypeResult="setTypeResult"></follow>-->
<follow
v-if="followDrawer"
:theCustomer="customer"
:param="param"
@setTypeResult="setTypeResult"
@apply="apply"
></follow>
</Drawer>
<!--追加线索-->
<Modal
title="追加线索"
v-model="createModal"
:fullscreen="false"
:transfer="false"
:draggable="true"
:scrollable="true"
:loading="createCreating"
width="1000"
@on-ok="confirmCreate"
>
<Form v-if="createModal" :model="form" :rules="formRules" :label-width="labelWidth"
:label-position="labelPosition"
ref="create">
<Row :gutter="24" justify="start">
<Col v-bind="grid">
<FormItem label="咨询人类型" prop="name_type">
<Select v-model="form.name_type" placeholder="请选择">
<Option value="1" selected>本人</Option>
<Option value="2">代咨询</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="来源渠道" prop="channel_id">
<Select v-model="form.channel_id" placeholder="请选择">
<Option v-for="(item,index) in param.channel" :key="index"
:value="(item.id).toString()">
{{ item.name }}
</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="客户等级" prop="level_id">
<Select v-model="form.level_id" placeholder="请选择">
<Option v-for="(item,index) in param.level" :key="index" :value="(item.id).toString()">
{{
item.name
}}
</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="意向度" prop="yxd_id">
<Select v-model="form.yxd_id" placeholder="请选择">
<Option v-for="(item,index) in param.yxd" :key="index" :value="(item.id).toString()">{{
item.name
}}
</Option>
</Select>
</FormItem>
</Col>
<Col span="24">
<FormItem label="项目类型" prop="sex">
<RadioGroup v-model="form.pro_type">
<!--<Radio :label="1">课程</Radio>-->
<Radio :label="2">自定义</Radio>
</RadioGroup>
</FormItem>
</Col>
<Col span="24" v-if="form.pro_type == 1">
<FormItem label="咨询课程" prop="course">
<Button type="primary" @click="courseAdd" ghost icon="md-add" class="ivu-mr">添加</Button>
<Table :transfer="true" :columns="Coursecolumns" :data="selectCourseData" class="ivu-mt"
size="small"
v-if="selectCourseData.length > 0">
<template slot-scope="{ row }" slot="method">
<span v-for="(item,index) in courseParam.methodList"
:key="index"
v-if="item.type == row.method">{{ item.name }}</span>
{{ row.method }}
</template>
<template slot-scope="{ row }" slot="price">
<strong>{{ row.price }}</strong>/{{ row.undeline_price }}
</template>
<template slot-scope="{ row }" slot="teacher">
<strong>{{ row.teacher_id }}</strong>
</template>
<template slot-scope="{ row }" slot="org_school">
<strong>【{{ row.school ? row.school.name : '' }}】</strong>
<span>{{ row.school ? row.school.org ? row.school.org.name : '' : '' }}</span>
</template>
<template slot-scope="{ row, index }" slot="action">
<Poptip
confirm
:transfer="true"
title="确定删除?"
@on-ok="removeCourse(index)"
>
<Icon type="ios-trash-outline" color="red" size="24"/>
</Poptip>
</template>
</Table>
</FormItem>
</Col>
<Col span="24" v-if="form.pro_type == 2">
<FormItem label="咨询项目" prop="title">
<Input v-model="form.title" type="textarea" :autosize="{minRows: 2,maxRows: 6}"
placeholder="请输入咨询内容"></Input>
</FormItem>
</Col>
<Col span="24">
<FormItem label="咨询内容" prop="content">
<Input v-model="form.content" type="textarea" :autosize="{minRows: 4,maxRows: 8}"
placeholder="请输入咨询内容"></Input>
</FormItem>
</Col>
</Row>
</Form>
</Modal>
<!--添加课程-->
<Modal
title="咨询课程"
v-model="courseModal"
:fullscreen="false"
:transfer="false"
width="1000"
@on-ok="confirmCourse"
>
<courseList ref="courseList"></courseList>
</Modal>
<!--客户资料-->
<Drawer
v-if="archive.id && archive.id !== 0"
v-model="archiveModal"
title="客户资料"
width="1000"
placement="left"
:mask-closable="true"
:closable="true"
>
<ArchiveDetail v-if="archiveModal" :theCustomer="archive" :param="param"></ArchiveDetail>
</Drawer>
</div>
</template>
<script>
import {customerEdit} from '@api/customer';
import ArchiveDetail from '@/components/customer/ArchiveDetail';
// import ArchiveDetail from '../common/ArchiveDetail';
import courseList from '../common/courseList';
import {customerAdd, customerArchive, customerArchiveDetail, customerParam} from '../../../api/customer';
// import follow from "../common/follow";
import follow from '@/pages/customer/follow/index'
import CustomerStatus from '../../../components/field/customer/CustomerStatus';
export default {
name: 'add',
watch: {
formData: function (val) {
this.form = val;
}
},
components: {
follow, ArchiveDetail, courseList, CustomerStatus
},
data() {
return {
archiveModal: false,
createModal: false,
createCreating: true,
Coursecolumns: [
{
title: '课程名称',
key: 'name',
minWidth: 250,
show: true,
tooltip: true,
},
{
title: '课程模式',
key: 'method',
minWidth: 100,
show: true,
slot: 'method',
},
{
title: '机构分校',
key: 'org_school',
minWidth: 140,
slot: 'org_school',
show: true
},
{
title: '售价/划线价',
key: 'price',
minWidth: 100,
align: 'center',
slot: 'price',
show: true
}
],
columns: [
{
title: '咨询项目',
key: 'title',
slot: 'title',
minWidth: 250,
show: true
},
{
title: '姓名',
key: 'name',
minWidth: 140,
slot: 'name',
show: true
},
{
title: '手机号',
key: 'phone',
minWidth: 130,
show: true
},
{
title: '微信号',
key: 'wechat',
minWidth: 130,
show: true
},
{
title: '状态',
key: 'status',
slot: 'status',
align: 'center',
minWidth: 100,
show: true,
},
{
title: '来源',
key: 'channel',
minWidth: 100,
slot: 'channel',
show: true
},
{
title: '意向度',
key: 'yxd',
minWidth: 100,
slot: 'yxd',
show: true
},
{
title: '行业',
key: 'hangye',
minWidth: 100,
slot: 'hangye',
show: true
},
{
title: '创建时间',
key: 'created_at',
minWidth: 170,
show: true
},
{
title: '操作',
slot: 'action',
align: 'center',
fixed: 'right',
minWidth: 120,
show: true
}
],
loading: false,
current: 1,
limit: 10,
total: 0,
param: {},
courseParam: {}, //课程参数
customer: {}, //当前操作线索
creating: true,
hasCourseModal: false, //已经存在课程
hasCourseList: [], //已经存在的课程列表
archive: {}, //档案信息
grid: {
xl: 12,
lg: 12,
md: 12,
sm: 24,
xs: 24
},
index: 1,
keys: {},// 提取formFiled的字段
form: {
id: 0,
name_type: '1',
level_id: '',
tj_phone: '',
channel_id: '',
yxd_id: '',
content: '',
pro_type: 2, // 项目类型
},
formRules: {
channel_id: [
{required: true, message: '必选', trigger: 'change'}
],
level_id: [
{required: true, message: '必选', trigger: 'change'}
],
yxd_id: [
{required: true, message: '必选', trigger: 'change'}
],
pro_type: [
{required: true, message: '必选', trigger: 'change'}
]
},
isOk: false, //是否允许提交表单
courseModal: false, //课程弹窗
archive_id: 0, //档案表
selectCourseData: [],
list: [], // 线索列表
followDrawer: false,
}
},
created() {
this.archive_id = this.$route.query.archive_id;
this.getArchive();
this.getCustomer();
},
methods: {
// 报名
apply(row, index) {
this.followDrawer = false;
this.index = index;
this.customer = row;
this.$router.push({
path: '/student/apply',
query: {
id: row.id,
archive_id: row.archive_id
}
})
},
create() {
this.form = {
name_type: '1',
pro_type: 2, // 项目类型
};
this.createModal = true;
},
confirmCreate() {
this.$refs.create.validate(validate => {
if (this.form.title == '' && this.form.course == '') {
return this.$Message.warning('请输入咨询内容');
}
if (validate) {
this.form.archive_id = this.archive.id;
customerAdd(this.form).then(res => {
if (res.code === 200) {
this.getCustomer();
this.createModal = false;
this.$Message.success(res.msg);
} else {
this.$Message.error(res.msg);
}
this.createCreating = false;
this.$nextTick(function () {
this.createCreating = true;
})
});
} else {
this.createCreating = false;
this.$nextTick(function () {
this.createCreating = true;
})
}
});
},
courseAdd() {
this.courseModal = true;
// 获取课程信息
this.$refs.courseList.getParam();
this.$refs.courseList.getOrgList();
this.$refs.courseList.getData();
},
// 获取参数信息
getParam() {
customerParam().then(res => {
this.param = res.data;
});
},
// 确定课程
confirmCourse() {
this.courseParam = this.$refs.courseList.param;
let courseList = this.$refs.courseList.selectedData;
this.selectCourseData = courseList;
if (courseList == null || courseList == '') {
return this.$Message.error('请选择课程');
}
// 检查课程是否已经存在
let course = []; //课程列表
let course_ids = []; // 课程id
courseList.forEach(item => {
course_ids.push(item.id);
let data = {};
data.id = item.id;
data.name = item.name;
data.school_id = item.school_id;
course.push(data);
})
this.isOk = true;
this.form.course = course;
},
removeCourse(index) {
this.form.course.splice(index, 1);
this.selectCourseData.splice(index, 1);
},
// 提交数据
submitForm() {
this.$refs.create.validate((valid) => {
if (valid) {
customerEdit(this.form).then(res => {
this.submitResult(res);
});
}
})
},
// 表单提交结果
submitResult(result) {
this.$emit('submitResult', result);
},
// 获取档案信息
getArchive() {
customerArchiveDetail({archive_id: this.archive_id}).then(res => {
this.archive = res.data;
});
},
// 获取线索
getCustomer() {
customerArchive({archive_id: this.archive_id}).then(res => {
let {data, total} = res;
this.list = data;
this.total = total;
});
},
// 跟进
follow(index) {
this.index = index;
this.customer = this.list[index];
this.followDrawer = true;
},
// 标记无效,1、转入公海无效,2、删除当前数据
setTypeResult() {
this.followDrawer = false;
this.list.splice(this.index, 1);
},
// 选中一项,将数据添加至已选项中
handleSelect(selection, row) {
this.selectedData.push(row);
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel(selection, row) {
const index = this.selectedData.findIndex(item => item.name === row.name);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll(selection) {
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.name === item.name) < 0) {
this.selectedData.push(item);
}
});
},
// 取消当前页全选时,将当前页的数据(即 dataWithPage)从已选项中删除
handleSelectAllCancel() {
this.selectedData = [];
},
// 切换每页条数
handleChangePageSize(limit) {
this.limit = limit;
this.getData();
}
},
mounted() {
this.getParam();
},
computed: {
labelWidth() {
return this.isMobile ? undefined : 100;
},
labelPosition() {
return this.isMobile ? 'top' : 'right';
},
labelKeys: function () {
let ids = [];
this.selectLabelData.forEach(item => {
ids.push(item.id);
})
return ids;
},
// 动态设置列
tableColumns() {
const columns = [...this.columns];
return columns.filter(item => item.show);
}
}
}
</script>
<style scoped>
</style>
# 组件传值
父组件
<template>
<div>
<child :list="list" ref="child"></child>
</div>
</template>
<script>
import child from '@/components/child';
export default {
data(){
return {
list: []
}
},
components: {
child
},
methods: {
fatherMethod() {
console.log('father组件');
},
// 调用子组件的方法
handChildMethods(){
this.$refs.child.childMethods()
}
}
}
</script>
子组件
<template>
<div @click="activeBtn"> </div>
</template>
<script>
export default {
// 接受父组件的值,使用:this.list
props:{
list:{
type: Array,
default: []
}
},
methods: {
activeBtn() {
// 调用父组件的方法
this.$parent.fatherMethod()
this.$emit('fatherMethod')
},
// 子组件自己的方法
childMethods(){
console.log("子组件自己的方法");
}
}
}
</script>
# 表单
<Form ref="form" :model="form" :rules="formRule" :label-width="80">
<Row>
<Col span="12">
<FormItem label="微信号" prop="name">
<Input v-model="form.name" placeholder=""></Input>
</FormItem>
</Col>
<Col span="24">
<FormItem>
<Button type="primary" @click="submitForm('form')">保 存</Button>
<Button @click="resetForm('form')" style="margin-left: 8px">重 置</Button>
</FormItem>
</Col>
</Row>
</Form>
// data
keys:{},
form: {
id: "",
name: "",
},
formRule: {
name: [
{required: true, message: '网站名称不能为空', trigger: 'blur'}
],
}
created() {
// 表单提交值
this.keys = Object.keys(this.form);
},
// methods
submitForm(name) {
this.$refs[name].validate((valid) => {
if (valid) {
websiteStore(_.pick(this.form,this.keys)).then(res=>{
this.$Message.success('Success!');
});
}
})
},
resetForm(name) {
this.$refs[name].resetFields();
}
# 表单验证规则
string
number
boolean
method
regexp
integer
float
array
object
enum
date
url
hex
email
any
:rules="formRules"
formRules: {
name: [
{required: true, message: '请输入机构名称', trigger: 'blur'}
],
phone: [
{required: true, message: '请输入电话号码', trigger: 'blur'},
{min:11, message: '手机号码必须为11位', trigger: 'blur'},
{max:11, message: '手机号码必须为11位', trigger: 'blur'},
],
email: [
{ type:"email", message: '请输入正确的邮箱格式', trigger: 'blur'}
]
},
const descriptor = {
role: { type: 'enum', enum: ['admin', 'user', 'guest'] },
};
# 下拉框验证
{ type: 'number', required: true, message: '请选择案件类型', trigger: 'change' }
必须是字符串验证
# 表单提交
ui-form-submit
formSubmit() {
this.$refs.create.validate((valid) => {
if (valid) {
$method$(_.pick(this.form, this.keys)).then(res => {
if (res.code === 200) {
this.$Message.success(res.msg);
this.showCreate = false;
this.creating = false;
this.$nextTick(() => {
this.creating = true;
});
if (this.form.id > 0) {
const index = this.list.findIndex(item => item.id === this.form.id);
this.list[index] = this.form;
} else {
this.getData();
}
} else {
this.$Message.error(res.msg);
this.showCreate = true;
this.creating = false;
this.$nextTick(() => {
this.creating = true;
});
}
});
} else {
this.creating = false;
this.$nextTick(() => {
this.creating = true;
});
}
});
},
# 单选
ui-radio
<RadioGroup v-model="">
<Radio
v-for="(item,index) in $list$"
:key="index" :label="item.id"
:true-value="true"
:false-value="false"
>{{ item.name }}</Radio>
</RadioGroup>
# 下拉
ui-select
<Select clearable v-model="form.$value$" >
<Option
v-for="(item,index) in list"
:key="index"
:value="item.id"
>{{ item.name }}</Option>
</Select>
# 开关
ui-switch
<Switch size="$size$" v-model="value" :true-value="$true_value$" :false-value="$false_value$" :loading="true" @on-change="changeStatus">
<span slot="open">开启</span>
<span slot="close">关闭</span>
</Switch>
enum("default","large","small")
enum("true","1")
enum("false","0","2")
# 表格
层级处理::transfer=“true”
<template slot-scope="{ row, index }" slot="action">
<Button type="primary" size="small" style="margin-right: 5px" @click="edit(index)">编辑</Button>
<Button type="error" size="small" @click="delete(index)">删除</Button>
</template>
<Dropdown @on-click="(name) => action(name, index)" :transfer="true">
<a type="text">更多
<Icon type="ios-arrow-down"/>
</a>
<DropdownMenu slot="list" trigger="hover" :transfer="true">
<DropdownItem name="detail">线索详情</DropdownItem>
<DropdownItem name="editArchive">编辑客户</DropdownItem>
<DropdownItem name="transfer">转移线索</DropdownItem>
<DropdownItem name="project">新增项目</DropdownItem>
<DropdownItem divided name="delete">删除</DropdownItem>
</DropdownMenu>
</Dropdown>
<template slot-scope="{ row }" slot="name">
<strong>{{ row.name }}</strong>
</template>
// 更多
action(name, index) {
this.setCustomerByIndex(index);
switch (name) {
case 'editArchive':
this.archiveEditModal = true;
break;
case 'detail':
// this.detailShow = true;
this.edit(index, true)
break;
case 'delete':
this.$Modal.confirm({
title: '删除提示',
content: `是否删除${this.list[index].title}?`,
onOk: () => {
customerDelete({id: this.list[index].id}).then(res => {
this.list.splice(index, 1);
this.$Message.success(res.msg);
});
}
});
break;
case 'transfer': // 转移线索
this.transferModal = true;
break;
case 'project':
this.$router.push({
path: '/customer/add',
query: {
archive_id: this.customer.archive_id
}
});
break;
}
},
# 表格查询参数
ui-table-form
<template>
<Form ref="form" :model="data" :rules="rules" :label-width="labelWidth" :label-position="labelPosition">
<Row :gutter="24" type="flex" justify="space-between">
<Col v-bind="grid">
<FormItem label="名字:" prop="name" label-for="name">
<Input v-model="data.name" placeholder="请输入" element-id="name"/>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="创建时间:" prop="datebt" label-for="datebt">
<DatePicker type="daterange" v-model="data.datebt" format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择时间"></DatePicker>
</FormItem>
</Col>
<template v-if="collapse">
</Col>
</template>
<Col v-bind="grid" class="ivu-text-right">
<FormItem>
<Button type="primary" @click="handleSubmit">查询</Button>
<Button class="ivu-ml-8" @click="handleReset">重置</Button>
<a v-font="14" class="ivu-ml-8" @click="collapse = !collapse">
<template v-if="!collapse">
展开
<Icon type="ios-arrow-down"/>
</template>
<template v-else>
收起
<Icon type="ios-arrow-up"/>
</template>
</a>
</FormItem>
</Col>
</Row>
</Form>
</template>
<script>
import {mapState} from 'vuex';
export default {
props: {},
data() {
return {
grid: {
xl: 6,
lg: 6,
md: 6,
sm: 24,
xs: 24
},
collapse: false,
data: {
name: '',
databt: [],
},
rules: {}
}
},
computed: {
...mapState('admin/layout', [
'isMobile'
]),
labelWidth() {
return this.isMobile ? undefined : 100;
},
labelPosition() {
return this.isMobile ? 'top' : 'right';
}
},
methods: {
handleSubmit() {
this.$emit('on-submit', this.data);
},
handleReset() {
this.$refs.form.resetFields();
this.$emit('on-reset');
}
}
}
</script>
# 表格辅助方法
// 改变表格尺寸
handleChangeTableSize(size) {
this.tableSize = size;
},
// 表格全屏
handleFullscreen() {
this.tableFullscreen = !this.tableFullscreen;
this.$emit('on-fullscreen', this.tableFullscreen);
},
// 刷新表格数据
handleRefresh() {
this.getData();
},
// 重置表格列设置
handleResetColumn() {
this.columns = this.columns.map(item => {
const newItem = item;
newItem.show = true;
return newItem;
});
},
# 表格内文字内容过长时
.text-two-line
<Ellipsis :text="row.intro" :height="100" tooltip />
<h3>属性</h3>
<h5>text</h5> //文本
<h5>height</h5> //限制高度(指定文字大小)
<h5>lines</h5> //指定行数,与height连用时会被忽略
<h5>length</h5> //指定长度
<h5>full-width-recognition</h5> //是否将全角字符的长度视为2来计算字符串长度,适用于 length
<h5>disabled</h5> //是否禁用
<h5>tooltip </h5> //是否开启 tooltip
<h5>transfer</h5> //tooltip 的 transfer 属性
<h5>theme</h5> //tooltip 的 theme 属性,可选值为 light 或 dark
<h5>max-width</h5> //tooltip 的 max-width 属性
<h5>placement</h5> //tooltip 的 placement 属性
<h3>事件</h3>
<h5>on-show</h5> //文本全部展示的时候触发
<h5>on-hide</h5> //文本省略的时候触发
# 公共方法
return {
grid: {
xl: 24,
lg: 24,
md: 24,
sm: 24,
xs: 24
},
list: [], // 数据列表
loading: false,
submitting: true, // 表单提交状态
form: {
name: '',
url: "",
},
formRule: {
name: [
{required: true, message: '名称不能为空', trigger: 'blur'}
],
url: [
{required: true, message: '地址不能为空', trigger: 'blur'},
{type: "url", message: '地址格式不正确', trigger: 'blur'}
],
},
}
mounted () {
this.getData();
},
created() {
// 表单提交值
this.keys = Object.keys(this.form);
},
// 重载表格
reloadTable() {
this.list = [];
this.getData();
},
copyData(index) {
return cloneDeep(this.list[index]);
},
// 切换页面
changePage(page){
this.page = page;
this.getData();
}
# 分页
<div class="ivu-mt ivu-text-right">
<Page :total="total" show-sizer show-elevator
:page-size="limit" show-total
:page-size-opts="[15,30,50,100]"
:simple="isMobile"
@on-change="changePage"
@on-page-size-change="changeLimit"
@on-prev="prevPage"
@on-next="nectPage"
/>
</div>
// 切换页码
changePage(page){
this.page = page;
this.getData();
},
// 切换条数
changeLimit(limit){
this.limit=limit;
},
// 上一页
prevPage(page){
this.page = page;
this.getData();
},
// 下一页
nectPage(page){
this.page = page;
this.getData();
}
table选择
@on-sort-change="handleSortChange"
@on-filter-change="handleFilterChange"
@on-select="handleSelect"
@on-select-cancel="handleSelectCancel"
@on-select-all="handleSelectAll"
@on-selection-change="selectChange"
清空
// 清空所有已选项this.selectedData = [];
handleClearSelect() {
let ids = [];
this.selectedData.forEach(item=>{
ids.push(item.id);
})
this.$Modal.confirm({
title: '删除提示',
content: `是否删除?`,
onOk: () => {
deleteCate({ids}).then(res => {
this.$Message.success(res.msg);
this.selectedData = [];
this.getData();
});
}
});
},
// 点击排序按钮时触发
handleSortChange({key, order}) {
// 将排序保存到数据
this.sortColumns = key;
this.sortType = order;
this.current = 1;
},
// 过滤条件改变时触发
handleFilterChange() {
// 从第一页开始
this.current = 1;
},
// 选中一项,将数据添加至已选项中
handleSelect(selection, row) {
this.selectedData.push(row);
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel(selection, row) {
const index = this.selectedData.findIndex(item => item.name === row.name);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll(selection) {
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.name === item.name) < 0) {
this.selectedData.push(item);
}
});
},
// 选项发生改变时
selectChange(selection){
this.selectedData = selection;
},
# 时间处理
<Col v-bind="grid">
<Col v-bind="grid">
<FormItem label="到期时间" prop="etime">
<DatePicker
v-model="form.etime"
type="date"
format="yyyy-MM-dd HH:mm:ss"
@on-change="changeTime"
placeholder="请选择时间" style="width: 200px"></DatePicker>
</FormItem>
</Col>
</Col>
etime:'2021-11-26 00:00:00',
// 选择时间
changeTime(selectedDate){
this.form.etime = selectedDate;
},
// this.form.expire_time 时间对象
this.$Date(this.form.expire_time).format('YYYY-MM-DD HH:mm:ss');
# 图片放大
// 图片放大
import "viewerjs/dist/viewer.css"
import VueViewer from 'v-viewer'
Vue.use(VueViewer);
// 查看大图
bigPic(image) {
this.$viewerApi({images:[image]})
},
// 图片放大
bigPic(url) {
let list = [];
list.push(url);
this.$viewerApi({
images: list, // 必须是已数组的形式传递 ["image.png","avatar.png",....]
})
},
# 单选
ui-radio
<RadioGroup v-model="menuData.node_type" @on-change="changeNodeType">
<Radio label="1">永久有效</Radio>
<Radio label="2">到期时间</Radio>
</RadioGroup>
# 布局
<Modal
v-model="modal"
:title="title"
:loading="creating"
:fullscreen="true"
:transfer="false"
@on-ok="confirm"
@on-cancel="cancel">
</Modal>
ui-modal
enum("false","true")
<Row type="flex" align=$alias$ justify="$justify$" gutter="$gutter$" wrap="$wrap$">
</Row>
ui-row
enum("top","middle","bottom")
enum("start","end","center","space-around","space-between" )
enum(0,8,24)
enum("true","false")
enum("",span","offset","push","pull")
<Col v-bind="grid" $tips$>
</Col>
# 常规状态
<Tag v-if="row.sex === 0">未知</Tag>
<Tag v-if="row.sex === 1" color="blue">男</Tag>
<Tag v-if="row.sex === 2" color="magenta">女</Tag>
# 表格菜单下拉
ui-tb-action-more
<template slot-scope="{ row, index }" slot="action">
<a @click="handleUpdate(index)">跟进</a>
<Divider type="vertical" />
<Dropdown @on-click="(name) => action(name, index)">
<a type="text">更多<Icon type="ios-arrow-down" /></a>
<DropdownMenu slot="list" trigger="hover" transfer="true" >
<DropdownItem name="edit">编辑</DropdownItem>
<DropdownItem name="detail">详情</DropdownItem>
<DropdownItem divided name="delete">删除</DropdownItem>
</DropdownMenu>
</Dropdown>
</template>
// 更多
action(name) {
switch (name) {
case "edit":
break;
case "detail":
break;
case "delete":
break;
}
},
# 时间轴
ui-timeline
<Timeline>
<TimelineItem color="$poprs$">
<p class="time">1976年</p>
<p class="content">Apple I 问世</p>
</TimelineItem>
<TimelineItem>
<p class="time">1984年</p>
<p class="content">发布 Macintosh</p>
</TimelineItem>
<TimelineItem>
<p class="time">2007年</p>
<p class="content">发布 iPhone</p>
</TimelineItem>
<TimelineItem>
<p class="time">2010年</p>
<p class="content">发布 iPad</p>
</TimelineItem>
<TimelineItem>
<p class="time">2011年10月5日</p>
<p class="content">史蒂夫·乔布斯去世</p>
</TimelineItem>
</Timeline>
enum("green",'red','blue')
# 图标
ui-icon
<Icon type="$type$" $props$ />
enum("md-add",'md-clipboard')
enum("size",'color','custom')
# Driawer
<Drawer
:title="detail.name"
v-model="showDrawer"
width="720"
placement="right"
:mask-closable="true"
:closable="true"
>
<div class="drawer-footer">
<Button style="margin-right: 8px" @click="value3 = false">关闭</Button>
<Button type="primary" @click="value3 = false">Submit</Button>
</div>
</Drawer>
showDrawer:true,
.drawer {
&-footer {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
background: #fff;
}
}
# 弹窗表单
<Form :model="form" :rules="formRules" :label-width="labelWidth" :label-position="labelPosition" ref="create">
<Row :gutter="24" justify="start">
<Col space="8">
<Col v-bind="grid">
<FormItem label="姓名:" prop="title" label-for="name">
<Input v-model="form.name" placeholder="" @on-blur="checkUser"/>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="咨询人类型" prop="name_type">
<Select v-model="form.name_type" placeholder="请选择">
<Option value="1" selected>本人</Option>
<Option value="2">代咨询</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="性别" prop="sex">
<RadioGroup v-model="form.sex">
<Radio label="1">男</Radio>
<Radio label="2">女</Radio>
</RadioGroup>
</FormItem>
</Col>
<Col span="24">
<FormItem label="咨询内容" prop="content">
<Input v-model="form.content" type="textarea" :autosize="{minRows: 4,maxRows: 8}"
placeholder="请输入咨询内容"></Input>
</FormItem>
</Col>
</Row>
</Form>
computed: {
labelWidth() {
return this.isMobile ? undefined : 100;
},
labelPosition() {
return this.isMobile ? 'top' : 'right';
},
}
# 性别
<Tooltip content="男">
<Icon type="md-male" color="primary"/>
</Tooltip>
<Tooltip content="女">
<Icon type="md-female" color="red"/>
</Tooltip>
# 地址
<Col span="24">
<FormItem label="地址" prop="addr">
<i-region v-model="form.addr"/>
</FormItem>
</Col>
<Col span="24">
<FormItem label="详细地址" prop="addr_detail">
<Input v-model="form.addr_detail" type="textarea" :autosize="{minRows: 3,maxRows: 6}"
placeholder="请输入详细地址"></Input>
</FormItem>
</Col>
格式化地址
<template slot-scope="{ row }" slot="addr">
{{ transformAddr(row.addr)}}
<p> {{ row.addr_detail }}</p>
</template>
transformAddr(addr=[]){
if (addr == null || addr == '' || addr.length == 0){
return "";
}
let str = "";
if (addr.length > 0){
addr.forEach(item=>{
str += " " +item.name;
})
}
return str;
},
# 时间查询
ui-date-search
<FormItem label="创建时间:" prop="date" label-for="btdate">
<DatePicker v-model="data.btdate" type="daterange" :options="dateOptions" placeholder="请选择时间" />
</FormItem>
ui-date-search-dateOptions
date: []
dateOptions: {
shortcuts: [
{
text: '今天',
value: () => {
const date = this.$Date(new Date()).format('YYYY-MM-DD');
return [date, date];
}
},
{
text: '昨天',
value: () => {
let date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
date = this.$Date(date).format('YYYY-MM-DD');
return [date, date];
}
},
{
text: '本周',
value: () => {
const date = new Date();
const start = this.$Date(date).day(1).format('YYYY-MM-DD');
const end = this.$Date(date).day(7).format('YYYY-MM-DD');
return [start, end];
}
},
{
text: '本月',
value: () => {
const date = new Date();
const start = this.$Date(date).date(1).format('YYYY-MM-DD');
const end = this.$Date(date).add(1, 'month').date(1).subtract(1, 'day').format('YYYY-MM-DD');
return [start, end];
}
}
]
}
# 支付状态
ui-badge
<Badge color="$COLOR$" text="$TEXT$" />
enum("blue","green","red")
enum("支付成功","支付失败","正常","关闭","失败")
# 提示
ui-tooltip
<Tooltip max-width="200" content="$content$">
{{ $content$ }}
</Tooltip>
# 消息提示
this.$Message.success(res.msg);
this.$Message.error(res.msg);
this.$Message.warning(res.msg);
enum('success','error','warning')
enum('res.msg','666'')
# 时间格式化方法
ui-date-format
formatDate(timestamp) {
return this.$Date.unix(timestamp).format('$type$');
},
enum('YYYY-MM-DD HH:mm:ss','YYYY-MM-DD','HH:mm:ss')
# 单删除
ui-del-one
# 批量删除
ui-del-batch
clearSelect() {
let ids = [];
this.selectedData.forEach(item => {
ids.push(item.id);
})
this.$Modal.confirm({
title: '删除提示',
content: `是否删除已选择项?`,
onOk: () => {
$method$({ids}).then(res => {
this.$Message.success(res.msg);
this.selectedData = [];
this.getData();
});
}
});
},
# 消息提示
io-notice
this.$Notice.$type$({
title: '温馨提示',
desc: res.msg,
duration: 5
});
enum("open","success","error","warning","info")
# 头像渲染
ui-avatar
<span @click="bigPic($name$)">
<Avatar icon="ios-person" :src="$name$" size="$size$" shape="$shape$"/>
</span>
enum("default","large","small","64")
enum("circle","square")
enum("pic","avatar","img","url","form.pic","form.avatar","form.img","form.url")
# 性别
ui-sex
<div class="ivu-ml">
{{ row.name }}
<Tooltip content="男" v-if="row.sex == 1">
<Icon :type="md-male" color="primary"/>
</Tooltip>
<Tooltip content="女" v-if="row.sex == 2">
<Icon type="md-female" color="red"/>
</Tooltip>
</div>
# 返回方法
this.$refs.form.validate((valid) => {
if (valid) {
agentStore(_.pick(this.form, this.keys)).then(res => {
res.code === 200 ? this.$Message.success(res.msg) : this.$Message.error(res.msg);
this.submitting = true;
this.agentModal = false;
this.getData();
this.$nextTick(() => {
this.submitting = true;
});
});
} else {
this.submitting = false;
this.$nextTick(() => {
this.submitting = true;
});
}
});
ui-msg
this.$Message.$TYPE$(res.msg);
enum("success","error","warning","info","loading");
# Poptip
ui-poptip
<Poptip
:transfer="true"
trigger="$trigger$"
placement="$placement$"
:title="标题"
>
<span>提示</span>
<template slot="content" >
<div>
</div>
</template>
</Poptip>
enum("hover","click","focus")
enum("toptop-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end")
# 表格过滤
@on-filter-change="filterChange"
// 过滤条件改变时触发
handleFilterChange () {
// 从第一页开始
this.current = 1;
},
ui-table-filter
filters: [
{
label: '关闭',
value: 0
},
{
label: '运行中',
value: 1
},
{
label: '已上线',
value: 2
},
{
label: '异常',
value: 3
}
],
filterMultiple: true, // 是否支持多选
filterRemote (value) {
// 切换过滤条件时,将条件保存到本地
this.filterType = value;
}
# 数值显示
<CountUp :end="$number$" :duration="$duration$" ref="count" v-font="$font$" />
enum("form.number","number","count","total")
enum("3","4","5","6")
enum("24","25","26","27","28","29","30")
# 对象复制
this.$key$ = Object.keys(this.$name$);
enum("keys")
enum("form")
# 方法
# iview中vuex使用方式
# 设置
import {getWebsiteInfo} from "@api/system";
import {Message} from "view-design";
import util from '@/libs/util';
export default {
namespaced: true,
state: {
website: {},
},
actions: {
getWebsite({state, commit, dispatch}) {
getWebsiteInfo().then(async res => {
Message.destroy();
let {data} = res;
dispatch('set', data);
util.storage.set("website", res.data);
});
},
/**
* @description 持久化保存网站信息
* @param {Object} state vuex state
* @param {Object} dispatch vuex dispatch
* @param {*} info info
*/
set({state, dispatch}, data) {
return new Promise(async resolve => {
// store 赋值
state.website = data;
// 持久化
await dispatch('admin/db/set', {
dbName: 'sys',
path: 'system.website',
value: data,
}, {root: false});
// end
resolve();
})
},
/**
* @description 获取网站信息
* @param {Object} state vuex state
* @param {Object} dispatch vuex dispatch
*/
load({state, dispatch}) {
return new Promise(async resolve => {
// store 赋值
state.info = await dispatch('admin/db/get', {
dbName: 'sys',
path: 'system.website',
defaultValue: {},
}, {root: true});
// end
resolve();
})
}
},
mutations: {
// 从本地缓存中加载 网站配置
setWebsite(state) {
state.website = util.storage.get("website");
}
}
}
# 获取
computed: {
...mapState("admin/system", [
"website"
])
}
解决刷新后失效?
需要在main.js文件中动态加载
created() {
// 获取网站信息
let website = util.storage.get("website");
if (website == null || website == undefined || website == '') {
this.$store.dispatch("admin/system/getWebsite");
} else {
this.$store.commit('admin/system/setWebsite');
}
}
# 删除
// 清空所有已选项
handleClearSelect() {
let ids = [];
this.selectedData.forEach(item=>{
ids.push(item.id);
})
this.$Modal.confirm({
title: "删除提醒!",
content: "是否确定删除?",
onOk: () => {
articleCateDelete({ids}).then(res=>{
this.getData();
this.$Message.success(res.msg);
});
}
});
this.selectedData = [];
},
# 遍历二维数组的children添加到Arrary里
getCateList(){
courseCateList().then(res => {
this.cateList = res.data;
this.cateList.forEach(item=>{
if (item.children.length > 0){
item.children.forEach(childItem=>{
this.cateList.push(childItem)
})
}
});
});
},
# 通过id查找列表的当前item
//根据字段找 item
getItemById(id) {
return this.list.find(item => item.id === id);
},
let list = [
{id:1,name"orangbus"},
{id:1,name"orangbus"},
{id:1,name"orangbus"},
{id:1,name"orangbus"},
{id:1,name"orangbus"},
];
ithis.list[index]
# 对象复制
import {cloneDeep} from 'lodash';
this.form = cloneDeep(item);
# 树结构编辑
通过id
# 递归找子集
ChilderTree(val) {
//声明一个数组准备接收匹配好的数据
let arr = [];
//判断传过来的数组长度
if (val.length !== 0) {
//遍历匹配,把满足条件的数据追加到arr数组中,最后返回一个结果
val.forEach((item) = >{
let obj = {};
obj.deptId = item.deptId;
obj.label = item.deptName;
obj.value = item.deptId;
obj.disabled = item.status == 0 ? true: false;;
if (item.children.length >= 1) {
obj.children = this.ChilderTree(item.children);
}
arr.push(obj);
});
}
return arr;
},
# 数组搜索
sortLists() {
let That = this;
if (!That.keywords) {
return That.lists;
} else {
return this.lists.filter(function(item) {
return item.name.includes(That.keywords);
});
}
}
# 更改当前tab标签
this.$store.dispatch('admin/page/currentUpdate', {
meta: {
title: '新的标题'
}
});
# 获取vuex信息
async function getUserAccess() {
return await store.dispatch('admin/db/get', {
dbName: 'sys',
path: 'user.info',
defaultValue: '',
user: true // 是否区分用户
});
}
getUserAccess().then(res => {
access = res.access;
let md5_data = md5(access.toString());
config.headers.common['crm'] = md5_data;
})
# 刷新用户信息
import {mapActions} from 'vuex';
methods: {
...mapActions('admin/user', [
'refreshUserInfo'
]),
}
this.refreshUserInfo();
# render 函数用法
{
title: 'name',
key: 'name',
tree: true,
render: (h, data) => {
let {row} = data;
let _this = this;
// 标签,属性对象,子元素
return h("span", {
class: "text-pointer",
// 点击事件
on: {
click: () => {
_this.$Copy({
text: row.password
});
}
}
}, data.row.name)
}
},
# 时间操作
# 获取当前时间戳
this.$Date().unix()
# unix时间转换
this.$Date(1641180193*1000).format("YYYY-MM-DD HH:mm:ss")
# 获取当前年月
// 设置当前年月
this.param.year = this.$Date().format('YYYY') * 1;
this.param.month = this.$Date().format('M') * 1;
# 日期转unix时间戳
this.$Date(2-04-22).unix()
# 树结构
$list = collect($data)->map(function ($item) {
$item->expand = true;
if (!empty($item->children)) {
for ($i = 0; $i < $item->children->count(); $i++) {
$temp = [];
$temp['value'] = $item->children[$i]['id'];
$temp['title'] = $item->children[$i]['name'];
$temp['selected'] = false;
$temp['checked'] = true;
$tempItem['expand'] = true; //是否展开直子节点
$item->school[$i] = $temp;
}
}
$tempItem = [];
$tempItem["title"] = $item['name'];
$tempItem["value"] = $item['id'];
$tempItem['selected'] = false;
$tempItem['checked'] = true; //是否勾选(如果勾选,子节点也会全部勾选)
$tempItem['disabled'] = true; // 顶级目录不可选择
$tempItem['expand'] = true; //是否展开直子节点
$tempItem['children'] = $item['children'];
return $tempItem;
});
# 封装组件
# (单 )图片/文件 上传
<FileUpload :url="form.pic" title="请选择图片" @upload="upload" @remove="removeUpload" />
// 导入组件
import FileUpload from "@/components/upload/FileUpload";
// 注册组件
components:{
FileUpload
},
// 方法接受文件上传结果
upload(res) {
this.form.pic = res.data.url
},
// 删除文件,返回 true|false
removeUpload(result){
if(result){
this.form.pic = "";
}
},
ui-upload-html // 图片上传
<FileUpload :url="form.pic" title="请选择图片" @upload="upload" @remove="removeUpload" />
ui-upload-js // 文件上传接受返回值
// 方法接受文件上传结果
upload(res) {
this.form.pic = res.data.url
},
// 删除文件,返回 true|false
removeUpload(result){
if(result){
this.form.pic = "";
}
},
ui-upload-components // 文件上传组件
components:{
FileUpload
},
# 头像上传
<AvatarUpload :url="form.pic" title="请选择图片" @upload="upload" @remove="removeUpload" />
// 导入组件
import FileUpload from "@/components/upload/AvatarUpload";
// 注册组件
components:{
AvatarUpload
},
// 方法接受文件上传结果
upload(res) {
this.form.pic = res.data.url
},
// 删除文件,返回 true|false
removeUpload(result){
if(result){
this.form.pic = "";
}
},
ui-upload-avatar // 图片上传
<FileUpload :url="form.pic" title="请选择图片" @upload="upload" @remove="removeUpload" />
ui-upload-js // 文件上传接受返回值
// 方法接受文件上传结果
upload(res) {
this.form.pic = res.data.url
},
// 删除文件,返回 true|false
removeUpload(result){
if(result){
this.form.pic = "";
}
},
ui-upload-components // 文件上传组件
components:{
FileUpload
},
# 多图上传
<FormItem label="图片" prop="images">
<ImagesUpload :imagesList="form.images" @uploadImages="uploadImages"></ImagesUpload>
</FormItem>
images:[
{name:'张三.jpg',url:'https://xxx.xom/张三.jpg'},
{name:'张三.jpg',url:'https://xxx.xom/张三.jpg'},
{name:'张三.jpg',url:'https://xxx.xom/张三.jpg'},
]
import ImagesUpload from "@/components/upload/ImagesUpload";
components:{
ImagesUpload
},
// 多图图片上传
uploadImages(imageList){
this.form.images = imageList;
},
# 部门管理
<DepartMent :selected_ids="form.major_id" @getIds="getIds"></DepartMent>
import DepartMent from "@/components/common/department";
components: {
DepartMent
},
getIds(uid){
this.form.uid = uid;
},
selected_ids: array | Number | String
# 组织人员
<RoleUserList :value="value" @getSelected="getSelected" ref="roleUserList"></RoleUserList>
import RoleUserList from "@/components/common/roleUserList"
components:{
RoleUserList
},
//获取已经选择的数据id
getSelected(item){
console.log(item)
}
value
: array | number
multiple
: true | false
使用时需要触发获取数据
getData(){
this.$refs.roleUserList.getData();
},
# 角色用户
<RoleUser @getSelected="getSelected" :value="1" :multiple="false"></RoleUser>
import RoleUser from "@/components/common/roleUserList"
components:{
RoleUser
},
getSelected(ids){
console.log(ids)
}
todo
# 组织校区
<OrgSchool :selected_ids="form.school_id" @getSchoolId="getSchoolId" :multiple="false" ref="orgSchool"></OrgSchool>
import OrgSchool from "@/components/common/OrgSchool";
components:{
OrgSchool
},
this.$refs.orgSchool.getData();
getSchoolId(id){
console.log(id)
}
# textbus富文本编辑器 -废弃
<TextBus :content="form.content" ref="edit"></TextBus>
// 导入组件组件
import TextBus from "@components/edit/TextBus";
// 注册组件
components:{
TextBus
},
// 提交表单的时候获取结果
this.form.content = this.$refs.edit.getHtml();
<template>
<div>
<div id="editor"></div>
<!-- <p>编辑器使用说明:该编辑器支持<a href="https://www.runoob.com/markdown/md-tutorial.html" target="_blank">markdown</a>语法,截图或本地图片,直接复制粘贴即可.</p>-->
</div>
</template>
<script>
import { createEditor } from '@textbus/textbus';
import '@textbus/textbus/bundles/textbus.min.css';
import { uploadImage } from '@/api/common';
let editor = null;
export default {
name: 'Textbus',
props: {
// 可选 'dark' | 'mac-os' | 'mac-os-dark',不传即为默认样式
theme: {
type: String,
default: () => 'dark'
},
content: {
type: String,
default: () => ``
}
},
data () {
return {
data: '' // 编辑器最终的内容
}
},
watch: {
content: function (newVal) {
this.data = newVal;
this.setContent();
}
},
mounted () {
let that = this;
editor = createEditor('#editor', {
theme: 'dark', // 可选 'dark' | 'mac-os' | 'mac-os-dark',不传即为默认样式
// type: string, prevValue?: string): string | Promise<string> | Observable<string>
uploader (uploadType, prevValue) {
switch (uploadType) {
case 'video':
alert('不支持视频上传');
// console.log('上传视频');
break;
case 'image':
// prevValue 图片的二进制文件
const fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
fileInput.style.cssText = 'position: absolute; left: -9999px; top: -9999px; opacity: 0';
const promise = new Promise(resolve => {
fileInput.addEventListener('change', event => {
const form = new FormData();
for (const file of event.target.files) {
form.append('file', file);
form.append('type', 'image');
}
document.body.removeChild(fileInput);
uploadImage(form).then(res => {
resolve(res.data.url);
});
})
}, false);
document.body.appendChild(fileInput);
fileInput.click();
return promise;
// eslint-disable-next-line no-unreachable
break;
case 'audio':
alert('请选择图片上传');
// console.log('不支持音频上传');
break;
default:
alert('请选择图片文件');
break;
}
},
contents: that.content
});
editor.onChange.subscribe(() => {
that.data = editor.getContents().content;
});
},
methods: {
setContent () {
editor.setContents(this.data);
}
}
}
</script>
# wangedit编辑器
<WangEdit v-if="" :content="content" ref="edit"></WangEdit>
import WangEdit from "@/components/edit/WangEdit";
components: {
WangEdit
},
// 提交表单的时候获取结果
this.form.content = this.$refs.edit.getHtml();
# 局部打印
<template>
<div>
<div ref="container">
<p>打印区域</p>
<p>打印区域</p>
<p>打印区域</p>
</div>
<Button @click="handlePrint">打印</Button>
</div>
</template>
<script>
export default {
methods: {
handlePrint () {
this.$Print(this.$refs.container);
}
}
}
</script>
API
$Print(el, options):
el:
Element
要打印区域的 DOM 节点options:Object
额外的配置项
- beforeStart:
Function
打印前的回调 - finish:
Function
打印完成的回调 - backgroundColor:
String
设置打印区域背景色 1.1.0
pageWidth:页面宽,当打印页面不足以显示时,可以指定 pageWidth,如 100%,让其适应。1.1.0
pageHeight:页面高。
- beforeStart:
如果需要忽略某个节点,只需要给这个节点设置 class 类名 i-print-hidden
。
# 二维码生成
https://www.npmjs.com/package/vue-qr
<VueQr text="http://baidu.com" logoSrc="https://doc.orangbus.cn/orangbus.png" :size="300" />
import VueQr from "vue-qr";
components:{
VueQr
},
# 表单提交字段处理
created() {
this.keys = Object.keys(this.form);
},
_.pick(this.form,Object.keys(this.formData))
# 格式化时间戳
this.$Date.unix(form.expire_time).format('YYYY-MM-DD HH:mm:ss');
formatDate(timestamp){
return this.$Date.unix(timestamp).format('YYYY-MM-DD');
},
formatDate(timestamp){
return this.$Date.unix(timestamp).format('YYYY-MM-DD HH:mm:ss');
},
# 选择人员
<DepUserList
ref="depUserList"
:userIds="[]"
@getUserList="getUserList"
></DepUserList>
import DepUserList from '@/components/common/DepUserList';
getUserList(userList) {
this.userList = userList;
console.log(userList)
},
# 机构选择
# 单选
# 多选
# 表格
<Table
ref="table"
:columns="tableColumns"
:data="list"
:loading="loading"
:size="tableSize"
class="ivu-mt"
@on-sort-change="handleSortChange"
@on-filter-change="handleFilterChange"
@on-select="handleSelect"
@on-selection-change="selectChange"
@on-select-cancel="handleSelectCancel"
@on-select-all="handleSelectAll"
@on-select-all-cancel="handleSelectAllCancel"
>
<template slot-scope="{ row }" slot="title">
<div @click="bigPic(row.pic)">
<Avatar :src="row.pic" shape="square" size="large" slot="avatar"/>
{{ row.title }}
</div>
</template>
<template slot-scope="{ row }" slot="cate">
{{ row.cate ? row.cate.name : '' }}
</template>
<template slot-scope="{ row }" slot="user">
{{ row.user ? row.user.name : '' }}
</template>
<template slot-scope="{ row }" slot="status">
<Badge v-if="row.status === 1" status="success" text="开启"/>
<Badge v-if="row.status === 2" status="error" text="关闭"/>
</template>
<template slot-scope="{ row, index }" slot="action">
<a @click="showDetail(row)">详情</a>
<Divider type="vertical"/>
<a @click="handleUpdate(index)">编辑</a>
<Divider type="vertical"/>
<a @click="del(index)">删除</a>
</template>
</Table>
<div class="ivu-mt ivu-text-center">
<Page
:total="total"
:current.sync="current"
show-total
show-sizer
:page-size="size"
@on-change="changePage"
@on-page-size-change="handleChangePageSize"
/>
</div>
// 过滤条件改变时触发
handleFilterChange() {
// 从第一页开始
this.current = 1;
},
// 选中一项,将数据添加至已选项中
handleSelect(selection, row) {
this.selectedData.push(row);
},
// 选项发生改变时
selectChange(selection){
this.selectedData = selection;
console.log( this.selectedData)
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel(selection, row) {
const index = this.selectedData.findIndex(item => item.name === row.name);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll(selection) {
console.log(selection)
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.name === item.name) < 0) {
this.selectedData.push(item);
}
});
},
// 取消当前页全选时,将当前页的数据从已选项中删除
handleSelectAllCancel() {
const selection = this.list;
selection.forEach(item => {
const index = this.selectedData.findIndex(i => i.name === item.name);
if (index >= 0) {
this.selectedData.splice(index, 1);
}
});
},
computed: {
labelWidth() {
return this.isMobile ? undefined : 100;
},
labelPosition() {
return this.isMobile ? 'top' : 'right';
},
// 动态设置列
tableColumns() {
const columns = [...this.columns];
return columns.filter(item => item.show);
}
}
样式
```html
<span class="list-goods-list-item-price">价格</span>
<span class="list-goods-list-item-title">标题</span>
<span class=“list-goods-list-item-price>价格</span>
<span class="list-goods-list-item-desc">描述</span>
<span v-color="'#EA5455'">温馨提示:本产品为虚拟产品,一经购买……</span>
# 修改 props 传递参数
# 1、子组件改变,父组件更新
父组件
<template>
<div>
<PropsChild v-bind:content.sync="parentContent"></PropsChild>
<!-- 给v-bind添加了sync,那么子组件中就有一个事件可以触发 update:xxx自定义事件并且传递要修改的值 -->
</div>
</template>
<script>
import PropsChild from './component/PropsChild.vue'
export default {
data() {
return {
parentContent:'我是父组件的数据********'
}
},
components:{
PropsChild
}
}
</script>
子组件
<template>
<div>
<button @click="btnTest">我是子组件,{{ lasterContent }}</button>
</div>
</template>
<script>
export default {
data() {
return {
lasterContent: this.content
}
},
props:{
content:{
type:String
}
},
watch: {
content(val) {
this.lasterContent = val;
}
},
methods: {
btnTest() {
this.lasterContent = '哈哈,在子组件中改变了父组件传递过来的数据';
this.$emit('update:content',this.lasterContent);
}
},
}
</script>
# 2、子组件使用传递参数并改变
父组件
子组件
computed:{
msg2(){
return this.msgVal
}
},
# 暂留方法
线索订单-代付金额
// 待支付金额
userPayMoney(order) {
let money = order.money;
if (order.pay_status === 1 || order.pay_status === 3) {
money = 0;
} else {
if (order.pre_money > 0) {
if (order.pre_money_status !== 0) {
money = order.money - order.pre_money;
} else {
money = order.pre_money
}
} else {
money = order.pre_money;
}
}
return money;
},
# textbus2.0
<template>
<div ref="editorContainer"></div>
</template>
<script>
import {createEditor} from '@textbus/editor';
import '@textbus/editor/bundles/textbus.min.css';
import {uploadImage} from "@api/common";
export default {
mounted() {
let uploadConfig = {
/** 上传类型 */
uploadType: "image",
/** 当前值 */
currentValue: "",
/** 是否支持返回多个结果 */
multiple: false,
};
let options = {
theme: 'dark', // 可选 'dark' | 'mac-os' | 'mac-os-dark',不传即为默认样式
contents: "that.content",
placeholder: '请输入内容...',
uploader(uploadConfig) {
console.log(uploadConfig)
switch (uploadConfig.uploadType) {
case 'video':
alert('不支持视频上传');
// console.log('上传视频');
break;
case 'image':
// prevValue 图片的二进制文件
const fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
fileInput.setAttribute('accept', 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon');
fileInput.style.cssText = 'position: absolute; left: -9999px; top: -9999px; opacity: 0';
const promise = new Promise(resolve => {
fileInput.addEventListener('change', event => {
const form = new FormData();
for (const file of event.target.files) {
form.append('file', file);
form.append('type', 'image');
}
document.body.removeChild(fileInput);
uploadImage(form).then(res => {
resolve(res.data.url);
});
})
}, false);
document.body.appendChild(fileInput);
fileInput.click();
return promise;
// eslint-disable-next-line no-unreachable
break;
case 'audio':
alert('请选择图片上传');
// console.log('不支持音频上传');
break;
default:
alert('请选择图片文件');
break;
}
},
}
const editor = createEditor(this.$refs.editorContainer, options);
editor.onChange.subscribe(() => {
console.log(editor.getContents());
});
}
}
</script>
# yarn安装
npm install --global yarn
# 错误处理
123
If you have
node_modules
folder andpackage-lock.json
file in your root directory then remove those:rm -r node_modules rm package-lock.json
Then run commands:
npm install --save --legacy-peer-deps npm audit fix --force
Create
.env
file in the root directory and paste below code:SKIP_PREFLIGHT_CHECK=true
Now, start your project:
npm start
npm install -g node-gyp
# before installing node-gyp on windows
npm install --global --production windows-build-tools
# install node-gyp globally
npm install -g node-gyp
npm install grpc --save
npm install node-pre-gyp --save
# Vue错误处理
总是报Expected indentation of 0 spaces but found 2如何解决
.eslintrc.js
文件后 添加一下信息,并且重启
"indent": ["off", 2]
error: Unexpected trailing comma (comma-dangle)
解决方法: 在项目根目录下创建.prettierrc文件进行配置 .prettierrc文件:
{
"semi": false,//格式化时不加分号
"singleQuote": true,//用单引号替换双引号
"trailingComma":none//对象后面默认添加逗号
}
报错:error: Unexpected trailing comma (comma-dangle) at src\components\Login.vue:99:4: 解决: 配置 “trailingComma”:none
error: Newline required at end of file but not found (eol-last)
不需要遵循时间
// 缓存key
public function getCacheValue()
{
$time = time();
$notice = Notice::find($this->notice_id);
$this->notice = $notice; // 不需要遵循时间
$cacheKey = $this->getCacheKey();
if (!Cache::has($cacheKey)) {
// Carbon::parse("2021-04-5")->getTimestamp()
Cache::put($cacheKey, $time, 86400);
}
return Cache::get($cacheKey);
}
$time = $this->getCacheValue();
Cache::put($this->getCacheKey(), $item['updated_at'], 86400);
$this->notice->time = $item['updated_at'];
Cache::forever($cacheKey, $time);
Cache::put($this->getCacheKey(), $item['updated_at'], 86400);
// ...mapActions('admin/user', [
// 'getUserInfo','setMenuList'
// ]),
# 图片选择器
<!-- 图片管理器-->
<Modal
draggable
v-model="detail"
title="选择图片"
:fullscreen="true"
:transfer="true"
@on-ok="confirm"
>
<MinioCloudManage v-if="detail"></MinioCloudManage>
</Modal>
import MinioCloudManage from "@/pages/admin/cloud/comon/MinioCloudManage.vue";
detail : true,
confirm(){
},
# 表格公共模版
# 使用技巧
2945 9568 8808
# 表格全屏
table-full
<div class="ivu-inline-block ivu-fr">
<Dropdown @on-click="handleChangeTableSize" trigger="click">
<Tooltip class="ivu-ml" content="密度" placement="top">
<i-link>
<Icon type="md-list" />
</i-link>
</Tooltip>
<DropdownMenu slot="list">
<DropdownItem name="default" :selected="tableSize === 'default'">默认</DropdownItem>
<DropdownItem name="large" :selected="tableSize === 'large'">宽松</DropdownItem>
<DropdownItem name="small" :selected="tableSize === 'small'">紧凑</DropdownItem>
</DropdownMenu>
</Dropdown>
<Tooltip class="ivu-ml" :content="tableFullscreen ? '退出全屏' : '全屏'" placement="top">
<i-link @click.native="handleFullscreen">
<Icon :custom="tableFullscreen ? 'i-icon i-icon-exit-full-screen' : 'i-icon i-icon-full-screen'" />
</i-link>
</Tooltip>
<Tooltip class="ivu-ml" content="刷新" placement="top">
<i-link @click.native="handleRefresh">
<Icon custom="i-icon i-icon-refresh" />
</i-link>
</Tooltip>
<Dropdown trigger="click">
<Tooltip class="ivu-ml" content="列设置" placement="top">
<i-link>
<Icon type="md-options" />
</i-link>
</Tooltip>
<DropdownMenu slot="list">
<div class="ivu-p-8">
<Row>
<Col span="12">列展示</Col>
<Col span="12" class="ivu-text-right">
<i-link link-color @click.native="handleResetColumn">重置</i-link>
</Col>
</Row>
</div>
<Divider size="small" class="ivu-mt-8 ivu-mb-8" />
<li class="ivu-dropdown-item" v-for="item in columns" :key="item.title" v-if="item.title" @click="item.show = !item.show">
<Checkbox v-model="item.show"></Checkbox>
<span>{{ item.title }}</span>
</li>
</DropdownMenu>
</Dropdown>
</div>
tableSize: 'default',
tableFullscreen: false,
handleChangeTableSize (size) {
this.tableSize = size;
},
// 表格全屏
handleFullscreen () {
this.tableFullscreen = !this.tableFullscreen;
if (this.tableFullscreen) {
screenfull.request(this.$refs.card.$el);
} else {
screenfull.exit();
}
},
// 刷新表格数据
handleRefresh () {
this.getData();
},
// 重置表格列设置
handleResetColumn () {
this.columns = this.columns.map(item => {
const newItem = item;
newItem.show = true;
return newItem;
});
},
# 表格公共方法
/**
* 表格 tableMixins.js
* */
export default {
data(){
return{
loading: false,
list: [],
selectedData: [],
page:1,
limit: 10,
total: 0,
fields:{}, // 允许提交的字段
form:{},
formRules:{},
}
},
methods: {
search(){
this.page = 1;
this.getData();
},
// 选中一项,将数据添加至已选项中
handleSelect (selection, row) {
this.selectedData.push(row);
},
// 取消选中一项,将取消的数据从已选项中删除
handleSelectCancel (selection, row) {
const index = this.selectedData.findIndex(item => item.id === row.id);
this.selectedData.splice(index, 1);
},
// 当前页全选时,判断已选数据是否存在,不存在则添加
handleSelectAll (selection) {
selection.forEach(item => {
if (this.selectedData.findIndex(i => i.id === item.id) < 0) {
this.selectedData.push(item);
}
});
},
// 取消当前页全选时,将当前页的数据(即 dataWithPage)从已选项中删除
handleSelectAllCancel () {
this.selectedData = [];
},
// 清空所有已选项
handleClearSelect () {
this.selectedData = [];
},
// 切换页码
changePage(page) {
this.page = page;
this.getData();
},
// 切换每页条数
changeLimit(limit) {
this.limit = this.limit;
this.getData();
},
// 上一页
prevPage (page) {
this.page = page;
this.getData();
},
// 下一页
nextPage (page) {
this.page = page;
this.getData();
}
},
computed: {
// 动态设置列
tableColumns () {
const columns = [...this.columns];
return columns.filter(item => item.show);
}
},
}
# 折现图表
<script >
import echartMixins from "@/mixins/echartMixins";
import {registerUser, uploadMovie} from "@api/dashboard";
export default {
mixins:[echartMixins],
props:{
grid:{
type:Object,
default:()=>{
return {
xl: 24,
lg: 24,
md: 24,
sm: 24,
xs: 24
}
}
},
height:{
type:Number,
default:()=>300
},
title:{
type:String,
default:()=>""
},
},
mounted() {
this.getData();
},
methods:{
getData(){
uploadMovie().then(res=>{
if (res.code === 200){
let xaxis = [];
let series = [];
res.data.forEach(item=>{
xaxis.push(item.date);
series.push(item.total)
})
let seriesList = [
{
name: '更新数量',
data: series
}
];
this.setChart(this.$refs.registerChart,xaxis,seriesList)
}
});
}
}
}
</script>
<template>
<div>
<Col v-bind="grid">
<h4>{{ title }}</h4>
<div ref="registerChart" v-height="height"></div>
</Col>
</div>
</template>
<style scoped lang="less">
</style>
/**
* 折现统计 echartMixins.js
* 使用方式
* this.setChart(this.$refs.visitChart,this.dayList,seriesList);
* dayList:[1,2,3,....]
* seriesList:[
{
name: '标题',
data:[1,2,3,....]
}
]
* */
import echarts from 'echarts';
export default {
data() {
return {
visitChart: null,
}
},
methods: {
setChart(ref, xaxis = [], series = []) {
let seriesData = series.map(item => {
return {
name: item.name,
data: item.data,
type: 'line', // bar
tooltip: true,
smooth: true,
symbol: 'none',
itemStyle: {
normal: {
barBorderRadius: [3, 3, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#69cdff'
},
{
offset: 0.5,
color: '#3eb3f7'
},
{
offset: 1,
color: '#1495eb'
}
])
}
},
areaStyle: {
normal: {
opacity: 0.2
}
}
}
})
this.visitChart = echarts.init(ref);
this.visitChart.setOption(
{
xAxis: {
type: 'category',
axisLine: {
lineStyle: {
color: '#D7DDE4'
}
},
axisTick: {
alignWithLabel: true,
lineStyle: {
color: '#D7DDE4'
}
},
axisLabel: {
textStyle: {
color: '#7F8B9C'
}
},
splitLine: {
show: false,
lineStyle: {
color: '#F5F7F9'
}
},
data: xaxis,
},
yAxis: {
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
textStyle: {
color: '#7F8B9C'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#F5F7F9'
}
},
type: 'value'
},
series: seriesData,
color: ['#1495EB', '#00CC66', '#F9D249', '#ff9900', '#9860DF'],
grid: {
left: 16,
right: 25,
bottom: 5,
top: 20,
containLabel: true
},
tooltip: {
trigger: 'axis'
}
}
);
},
handleResize() {
this.visitChart.resize();
},
},
beforeDestroy() {
if (this.visitChart) {
this.visitChart.dispose();
this.visitChart = null;
}
}
}
# 消息提示
/**
* 表格 messageMixins.js
* */
export default {
data(){
return{
}
},
methods: {
resultMsg(res,status=200){
let {code,msg} = res;
return code === status ? this.$Message.success(msg) : this.$Message.error(msg);
}
}
}
← First UI 快捷模板 M3u8播放器 →